Skip to content

asdict fails for attributes of type Mapping with keys of type Tuple #646

Closed

Description

@radugrosu
@attr.s
class A:
    a = attr.ib()
        
instance = A({(1, ): 1})
attr.asdict(instance)

produces:
TypeError: unhashable type: 'list'

when the retain_collection_types flag is set to false (the default). This can take a while to figure out, since the error is not the most descriptive (and the classes are not toy examples like this one).
I just thought it would be worth mentioning. In any case, thanks for this awesome library.

Activity

  1. tovrstra commented on Aug 27, 2020

    @tovrstra

    I stumbled upon the same issue and it is indeed not easy to figure out what is going wrong. I'm trying to think how this could be fixed. @hynek Could you comment on the following? Thanks!

    • Would it be acceptable to change the default value for retain_collection_types to True? This would reduce the likelihood of this issue to appear unexpectedly. It is not a full fix though.

    • Would it be ok to use tuple as default collection type, when retain_collection_types=False? I would expect this to completely resolve the issue.

  2. hynek commented on Sep 1, 2020

    @hynek
    Member

    We cannot change the defaults for attr.asdict due to backward compatibility but we can do that for the upcoming attrs.asdict.

  3. tovrstra commented on Sep 1, 2020

    @tovrstra

    @hynek I understand. I've been thinking about related corner cases for asdict, which may also be addressed when making a newer version.

    Frozen sets are not changed into a default collection type, while sets are:

    >>> import attr
    >>> @attr.s
    ... class A:
    ...     a = attr.ib()
    ... 
    >>> instance = A(frozenset([1, 2]))
    >>> attr.asdict(instance)
    {'a': frozenset({1, 2})}
    >>>
    >>> instance = A(set([1, 2]))
    >>> attr.asdict(instance)
    {'a': [1, 2]}
    >>>

    This type of behavior can be made consistent in general by checking whether objects are instances of the classes defined in collections.abc.

    (Before making a new version, it would also be useful to understand the motivation for the current behavior.)

  4. hynek commented on Oct 19, 2020

    @hynek
    Member

    I have just merged #704 that fixes the frozenset issue – sorry for the late reply!

  5. hynek commented on Oct 19, 2020

    @hynek
    Member

    I have created a new issue for the new defaults, so closing this one.

  6. tovrstra commented on Oct 19, 2020

    @tovrstra

    No problem. Thank you for fixing!

  7. ikalnytskyi commented on Jun 16, 2021

    @ikalnytskyi

    I think I still experience this issue on latest stable attrs == 21.2.0. Is this expected?

    import attr
    
    @attr.s
    class Test:
        x = attr.ib()
    
    t = Test(x={(1, 2): 3})
    attr.asdict(t)
    Traceback (most recent call last):
      File "/tmp/t.py", line 11, in <module>
        attr.asdict(t)
      File "/tmp/.venv/lib/python3.9/site-packages/attr/_funcs.py", line 86, in asdict
        rv[a.name] = df(
    TypeError: unhashable type: 'list'
    
  8. hynek commented on Jun 28, 2021

    @hynek
    Member

    You have to pass retain_collection_types=True because we can't change the default value – that would be a very breaking change.

    We intend to change it when you can import it from attrs. I hope I'll get to it later this year.

  9. added 2 commits that reference this issue on Dec 28, 2021
  10. added a commit that references this issue on Dec 29, 2021
  11. added a commit that references this issue on Jan 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions