python-attrs / python-attrs/attrs

asdict filter exclude list matches on name instead of attribute

Open
#864 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.