Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type checking fails when registering a generic structure hook #106

Closed
tdsmith opened this issue Oct 31, 2020 · 2 comments · Fixed by #107
Closed

Type checking fails when registering a generic structure hook #106

tdsmith opened this issue Oct 31, 2020 · 2 comments · Fixed by #107

Comments

@tdsmith
Copy link
Contributor

tdsmith commented Oct 31, 2020

  • 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.

@Tinche
Copy link
Member

Tinche commented Nov 1, 2020

Hm, I think we would be ok with changing the type signature to self, cl: Type[T], func: Callable[[Any, Type[T]], T]. I don't remember the reason for using a different type var here.

Feel free to submit a PR :)

@tdsmith
Copy link
Contributor Author

tdsmith commented Nov 2, 2020

Will do! Thanks for the quick feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants