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

NamedTuple subclass class objects do not pass check_argument_types for "Type[BaseClass]" #249

Closed
zbentley opened this issue Apr 11, 2022 · 4 comments

Comments

@zbentley
Copy link

Describe the bug
Given a parent class "Foo" and a subclass "Bar" which also subclasses NamedTuple, typeguard fails to validate "Bar" for the annotation Type[Foo].

To Reproduce

from typing import NamedTuple, Type
from typeguard import check_argument_types

class Foo(NamedTuple):
	field: int

class Bar:
	...

class Baz(Bar, NamedTuple):
	field: int


def test1(arg: Type[Foo]):
	check_argument_types()

def test2(arg: Type[Bar]):
	check_argument_types()

test1(Foo)
test2(Bar)
test2(Baz)

Expected behavior
All three test calls should pass.

Additional context

Subclassing NamedTuple is dicey and not recommended, but it works OK if your superclass doesn't add any fields (just behavior), so this is a semi-reasonable use case.

@agronholm
Copy link
Owner

How am I supposed to get the type information to pass these? The superclasses don't show up in either mro() or __bases__. They just show as inheriting directly from tuple.

@agronholm agronholm added the needs more info Development cannot proceed before requested information has been provided label Jan 10, 2023
@zbentley
Copy link
Author

That's a good question. I'm not sure; you can introspect that it's a namedtuple by checking cls.__new__'s docstring and repr.

Checking the parent hierarchy is where it gets weird:

In 3.7, I don't think you can do this. This line seems to effectively strip out the real class hierarchy such that a brand new NamedTuple gets constructed.

In py3.9+ (via this PR), I think this information is preserved in __bases__, see this line.

If indeed this works on 3.9+, what would you think about adding this to typeguard with something (docstring? warning?) indicating that it only works on py3.9+?

@agronholm
Copy link
Owner

The example script does not run at all on Python 3.10 (TypeError: Multiple inheritance with NamedTuple is not supported). If I remove NamedTuple from the declaration of Baz, the tests pass as-is on latest master. So, I don't think there's anything to do, is there?

@agronholm agronholm removed the needs more info Development cannot proceed before requested information has been provided label Jan 10, 2023
@zbentley
Copy link
Author

If they fixed the ability to even do this at all in 3.10, then yep, this should be considered resolved! Sorry for the issue-report noise, I only had a Py3.7 environment to test against so wasn't aware of the new fixes for this pattern as a whole.

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

No branches or pull requests

2 participants