cattrs icon indicating copy to clipboard operation
cattrs copied to clipboard

cattr.gen.make_dict_structure_fn returns type incompatible with cattr.register_structure_hook causing mypy errors

Open kik-kik opened this issue 2 years ago • 7 comments

  • cattrs version: 1.9.0
  • Python version: 3.7
  • Operating System: MacOS (M1), Ubuntu

Description

It appears cattr.gen.make_dict_structure_fn returns an object type which does not provide type expected by cattr.register_structure_hook.

This results in a MyPy error as follows:

error: Argument 2 has incompatible type "Callable[[Mapping[str, Any]], T]"; expected "Callable[[Any, Type[T]], T]"

Snippets from cattrs source:

def make_dict_structure_fn(
    cl: Type[T],
    converter: "Converter",
    _cattrs_forbid_extra_keys: bool = False,
    _cattrs_use_linecache: bool = True,
    _cattrs_prefer_attrib_converters: bool = False,
    **kwargs,
) -> Callable[[Mapping[str, Any]], T]:
def register_structure_hook(
        self, cl: Any, func: Callable[[Any, Type[T]], T]
    ):

The cattrs documentation suggests that those two functions should be compatible:

>>> from pendulum import DateTime
>>> from cattr.gen import make_dict_unstructure_fn, make_dict_structure_fn, override
>>>
>>> @define
... class ExampleClass:
...     klass: Optional[int]
>>>
>>> c = cattr.Converter()
>>> unst_hook = make_dict_unstructure_fn(ExampleClass, c, klass=override(rename="class"))
>>> st_hook = make_dict_structure_fn(ExampleClass, c, klass=override(rename="class"))  # return type: Callable[[Mapping[str, Any]], T]
>>> c.register_unstructure_hook(ExampleClass, unst_hook)
>>> c.register_structure_hook(ExampleClass, st_hook)  # expected type: Callable[[Any, Type[T]], T]
>>> c.unstructure(ExampleClass(1))
{'class': 1}
>>> c.structure({'class': 1}, ExampleClass)
ExampleClass(klass=1)

Example taken from: https://cattrs.readthedocs.io/en/latest/customizing.html#rename

Started seeing this behaviour in version 1.9.0 and above.

What I Did

mypy package

kik-kik avatar Jan 19 '22 09:01 kik-kik

I'm aware, the fix will be ready for the next release. Must've had a brain fart when I wrote the type annotation for it. In the meantime, please #type: ignore it :)

Tinche avatar Jan 19 '22 10:01 Tinche

Amazing, thank you.

kik-kik avatar Jan 19 '22 10:01 kik-kik

Hm, which mypy version are you using?

Tinche avatar Jan 19 '22 10:01 Tinche

It looks like this was already fixed on main, please verify for me by trying it against the git repo and close if so ;)

Tinche avatar Jan 20 '22 00:01 Tinche

Hey @Tinche, thanks a lot for the quick response. I just tried installing the version from the main branch and it seems the error is no longer there. I guess that means the next version should include the fix?

MyPy version: mypy 0.910

kik-kik avatar Jan 20 '22 10:01 kik-kik

Yeah, the next version should be out in a couple of weeks while we finish up some big features.

Tinche avatar Jan 20 '22 11:01 Tinche

Amazing, thanks a lot for your help!

kik-kik avatar Jan 20 '22 15:01 kik-kik