Skip to content

Mixing generic container from typing and built-in crashes on py3.7-8 #218

@bibajz

Description

@bibajz
  • cattrs version: 22.1.0dev0
  • Python version: 3.7, 3.8 (FAILS) 3.9, 3.10 (OK)
  • Operating System: irrelevant

Description

Specifying an empty generic type from a standard library - so far tested on dict and list - crashes, since these types do not have __args__ attribute until py3.9

Python 3.8.10 (default, Nov 26 2021, 20:14:08) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import typing as t
>>> 
>>> import attrs
>>> import cattrs
>>>
>>> @attrs.define
... class A1:
...     bs: t.List[dict]
... 

>>> @attrs.define
... class A2:
...     bs: t.List[list]
...

>>> @attrs.define
... class D:
...     d: dict
... 

>>> cattrs.structure({"bs": [{}, {"a": 1}]}, A1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 300, in structure
    return self._structure_func.dispatch(cl)(obj, cl)
  File "<cattrs generated structure __main__.A1>", line 3, in structure_A1
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 478, in _structure_list
    return [
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 479, in <listcomp>
    self._structure_func.dispatch(elem_type)(e, elem_type)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/dispatch.py", line 49, in _dispatch
    return self._function_dispatch.dispatch(cl)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/dispatch.py", line 126, in dispatch
    return handler(typ)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 790, in gen_structure_mapping
    h = make_mapping_structure_fn(cl, self)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/gen.py", line 465, in make_mapping_structure_fn
    if not is_bare(cl):
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/_compat.py", line 171, in is_bare
    args = type.__args__
AttributeError: type object 'dict' has no attribute '__args__'

>>> cattrs.structure({"bs": [[], [1]]}, A2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 300, in structure
    return self._structure_func.dispatch(cl)(obj, cl)
  File "<cattrs generated structure __main__.A2>", line 3, in structure_A2
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 478, in _structure_list
    return [
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 479, in <listcomp>
    self._structure_func.dispatch(elem_type)(e, elem_type)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 474, in _structure_list
    if is_bare(cl) or cl.__args__[0] is Any:
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/_compat.py", line 171, in is_bare
    args = type.__args__
AttributeError: type object 'list' has no attribute '__args__'
>>>
>>> cattrs.structure({"d": {}}, D)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 300, in structure
    return self._structure_func.dispatch(cl)(obj, cl)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/dispatch.py", line 49, in _dispatch
    return self._function_dispatch.dispatch(cl)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/dispatch.py", line 126, in dispatch
    return handler(typ)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 740, in gen_structure_attrs_fromdict
    h = make_dict_structure_fn(
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/gen.py", line 280, in make_dict_structure_fn
    handler = converter._structure_func.dispatch(t)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/dispatch.py", line 49, in _dispatch
    return self._function_dispatch.dispatch(cl)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/dispatch.py", line 126, in dispatch
    return handler(typ)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/converters.py", line 790, in gen_structure_mapping
    h = make_mapping_structure_fn(cl, self)
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/gen.py", line 465, in make_mapping_structure_fn
    if not is_bare(cl):
  File "/home/libor/.virtualenvs/cattrs/lib/python3.8/site-packages/cattr/_compat.py", line 171, in is_bare
    args = type.__args__
AttributeError: type object 'dict' has no attribute '__args__'

Swapping dict/list for their upper-cased variants produces expected behaviour

>>> @attrs.define
... class D2:
...     d: typing.Dict
... 
>>> 
>>> cattrs.structure({"d": {}}, D2)
D2(d={})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions