From e5b1a568f3608a801219165e0c3d913a147a86eb Mon Sep 17 00:00:00 2001 From: STerliakov Date: Wed, 22 Feb 2023 02:04:50 +0300 Subject: [PATCH] Handle type[TypeVar] --- mypy/checkmember.py | 7 +++++++ mypy/messages.py | 6 ++++++ test-data/unit/check-classes.test | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index a2c580e134460..136c08247ef97 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -412,6 +412,13 @@ def analyze_type_type_member_access( upper_bound = get_proper_type(typ.item.upper_bound) if isinstance(upper_bound, Instance): item = upper_bound + elif isinstance(upper_bound, UnionType): + return _analyze_member_access( + name, + TypeType.make_normalized(upper_bound, line=typ.line, column=typ.column), + mx, + override_info, + ) elif isinstance(upper_bound, TupleType): item = tuple_fallback(upper_bound) elif isinstance(upper_bound, AnyType): diff --git a/mypy/messages.py b/mypy/messages.py index ba25080337904..2ba34ea4fe12c 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -516,6 +516,12 @@ def has_no_attr( context, code=codes.UNION_ATTR, ) + else: + self.fail( + '{} has no attribute "{}"{}'.format(format_type(original_type), member, extra), + context, + code=codes.ATTR_DEFINED, + ) return AnyType(TypeOfAny.from_error) def unsupported_operand_types( diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index d5fb830487e85..a7d13a586f561 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -3464,9 +3464,9 @@ class ProUser(User): pass class BasicUser(User): pass U = TypeVar('U', bound=Union[ProUser, BasicUser]) def process(cls: Type[U]): - cls.foo() # E: "Type[U]" has no attribute "foo" + cls.foo() obj = cls() - cls.bar(obj) # E: "Type[U]" has no attribute "bar" + cls.bar(obj) cls.mro() # Defined in class type cls.error # E: "Type[U]" has no attribute "error" [builtins fixtures/classmethod.pyi]