Skip to content

TypeError when registering ForwardRefs in python 3.10.2 #206

Open
@JWCook

Description

@JWCook
  • cattrs version: 1.10.0
  • Python version: 3.10.2
  • Operating System: Ubuntu 20.04.3

Description

This is related to #201, but probably worth making a separate issue for, since it affects one of the (previously working) workarounds mentioned in that issue. Feel free to close this if you feel this is redundant with #201 or #94.

I have a converter that registers a ForwardRef. In python 3.6.x through 3.10.1, this has worked as intended. As of python 3.10.2, this is now throwing a TypeError:

TypeError: Invalid first argument to `register()`. ForwardRef('MyClass') is not a class.

Strangely, I don't see anything in the python 3.10.2 changelog that would indicate changed behavior with ForwardRef or register().

What I Did

Minimal example:

from attr import define, field
from cattr import Converter  # Note: same behavior with GenConverter
from typing import ForwardRef, List

@define()
class MyClass:
    history: List['MyClass'] = field(factory=list)

converter = Converter()
converter.register_structure_hook(
    ForwardRef('MyClass'), lambda obj, _: converter.structure(obj, MyClass)
)

Traceback:

TypeError                                 Traceback (most recent call last)
Input In [17], in <module>
----> 1 converter.register_structure_hook(
      2     ForwardRef("MyClass"), (lambda obj, _: converter.structure(obj, MyClass))
      3 )

File ~/.virtualenvs/rc-310/lib/python3.10/site-packages/cattr/converters.py:269, in Converter.register_structure_hook(self, cl, func)
    267     self._structure_func.clear_cache()
    268 else:
--> 269     self._structure_func.register_cls_list([(cl, func)])

File ~/.virtualenvs/rc-310/lib/python3.10/site-packages/cattr/dispatch.py:57, in MultiStrategyDispatch.register_cls_list(self, cls_and_handler, direct)
     55         self._direct_dispatch[cls] = handler
     56     else:
---> 57         self._single_dispatch.register(cls, handler)
     58         self.clear_direct()
     59 self.dispatch.cache_clear()

File ~/.pyenv/versions/3.10.2/lib/python3.10/functools.py:856, in singledispatch.<locals>.register(cls, func)
    854 else:
    855     if func is not None:
--> 856         raise TypeError(
    857             f"Invalid first argument to `register()`. "
    858             f"{cls!r} is not a class."
    859         )
    860     ann = getattr(cls, '__annotations__', {})
    861     if not ann:

TypeError: Invalid first argument to `register()`. ForwardRef('MyClass') is not a class.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions