python-attrs / python-attrs/cattrs

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

Open
#208 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.1k
Forks
159
Avg merge
12h 21m
Merged PRs (30d)
6

Description

  • 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

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

Start by inspecting cattr.gen.make_dict_structure_fn and Converter.register_structure_hook, then run mypy package to reproduce the incompatible callable error. Done means the documented rename example type-checks without errors while structure and unstructure behavior remains compatible.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
developer-experience
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.