Skip to content

Type checking fails when registering a generic structure hook #106

@tdsmith

Description

@tdsmith
  • cattrs version: 1.1.1
  • Python version: 3.8.6, mypy 0.790
  • Operating System: macOS 10.15.7

Description

I might be misspecifying it, but I'm not sure how to register a generic structure hook function that can return more than one type.

mypy didn't complain about cattrs 1.0 and it continues to execute fine.

What I Did

from typing import Any, Protocol, Type, TypeVar

import attr
import cattr


class Nameable(Protocol):
    def __init__(self, name: str) -> None: ...


@attr.s(auto_attribs=True)
class A:
    name: str

@attr.s(auto_attribs=True)
class B:
    name: str


@attr.s(auto_attribs=True)
class Widget:
    spam: A
    eggs: B


T = TypeVar("T", bound=Nameable)


def instantiate_from_name(value: Any, klass: Type[T]) -> T:
    return klass(name=value)


cattr.register_structure_hook(A, instantiate_from_name)
cattr.register_structure_hook(B, instantiate_from_name)

print(cattr.structure({"spam": "Hormel", "eggs": "Farm Fresh"}, Widget))
$ python demo3.py
Widget(spam=A(name='Hormel'), eggs=B(name='Farm Fresh'))

$ mypy demo3.py
demo3.py:33: error: Argument 2 has incompatible type "Callable[[Any, Type[T]], T]"; expected "Callable[[Any, Type[T]], A]"
demo3.py:34: error: Argument 2 has incompatible type "Callable[[Any, Type[T]], T]"; expected "Callable[[Any, Type[T]], B]"
Found 2 errors in 1 file (checked 1 source file)

Changing the signature on register_structure_hook from self, cl: Type[T], func: Callable[[Any, Type[V]], T] to self, cl: Type[T], func: Callable[[Any, Type[T]], T] resolves this and I'm not sure why the latter is wrong but I'm probably missing some subtlety.

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