python-attrs / python-attrs/attrs
asdict filter exclude list matches on name instead of attribute
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.8k
- Forks
- 480
- Avg merge
- 2h 15m
- Merged PRs (30d)
- 2
Description
Hi, first of all, love the project and use it nearly every day for my job.
I have come across some behaviour that is unexpected.
Please consider this minimal worked example:
import attr
from typing import List
@attr.s(auto_attribs=True)
class Cop:
my_field: str
repeated_field_name: str
@attr.s(auto_attribs=True)
class Robber:
my_other_field: str
repeated_field_name: str
@attr.s(auto_attribs=True)
class Payload:
cops: List[Cop]
robbers: List[Robber]
if __name__ == "__main__":
cop = Cop("abc", "shared1")
robber = Robber("def", "shared2")
payload = Payload([cop], [robber])
print(attr.asdict(payload, recurse=True))
"""
{
'cops': [{'my_field': 'abc', 'repeated_field_name': 'shared1'}],
'robbers': [{'my_other_field': 'def', 'repeated_field_name': 'shared2'}]
}
"""
print(
attr.asdict(
payload,
recurse=True,
filter=attr.filters.exclude(attr.fields(Cop).repeated_field_name)
)
)
"""
{
'cops': [{'my_field': 'abc'}],
'robbers': [{'my_other_field': 'def'}]
}
"""
When the asdict filter argument is passed a variadic collection of attributes (available from attr.fields), and you have a range of attrs models that are recursively asdict-ified that may share a field name (in this example repeated_field_name) then the returned dictionary excludes this attribute for ALL classes, not just the one passed to fields.
This is understandable to a degree given assert attr.fields(Cop).repeated_field_name == attr.fields(Robber).repeated_field_name holds, but still a little unexpected given the method explicitly does not accept field names as strings.
As it happens, this behaviour is what I wanted 😄 though again I found it unexpected and wanted to confirm it is not a bug before I move forward with the implementation.
If this is a bug, a suggestion would be to permit string field names
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the nested example using attr.asdict, attr.filters.exclude, and attr.fields(Cop).repeated_field_name. Read the asdict filtering path and existing tests to establish whether matching by attribute identity or name is intended; done means the behavior is confirmed and covered by a focused regression test or clarified in the documentation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100