diff --git a/pytype/pyi/parser.py b/pytype/pyi/parser.py index 3aa59d539..1411756c3 100644 --- a/pytype/pyi/parser.py +++ b/pytype/pyi/parser.py @@ -18,6 +18,10 @@ # Typing members that represent sets of types. _TYPING_SETS = ("typing.Intersection", "typing.Optional", "typing.Union") +_TYPED_DICT_ALIASES = ( + "typing.TypedDict", + parser_constants.EXTERNAL_NAME_PREFIX + "typing_extensions.TypedDict") + _Params = collections.namedtuple("_", ["required", "starargs", "starstarargs", @@ -1113,7 +1117,7 @@ def new_class(self, decorators, class_name, parent_args, defs): raise ParseError("Unexpected classdef kwarg %r" % keyword) elif keyword == "total" and not any( isinstance(parent, pytd.NamedType) and - parent.name == "typing.TypedDict" for parent in parents): + parent.name in _TYPED_DICT_ALIASES for parent in parents): raise ParseError( "'total' allowed as classdef kwarg only for TypedDict subclasses") if keyword == "metaclass": diff --git a/pytype/pyi/parser_test.py b/pytype/pyi/parser_test.py index f1bfa276b..b457645d7 100644 --- a/pytype/pyi/parser_test.py +++ b/pytype/pyi/parser_test.py @@ -1275,6 +1275,19 @@ class Foo(TypedDict): ... class Foo(object, total=False): ... """, 1, "'total' allowed as classdef kwarg only for TypedDict subclasses") + def test_typing_extensions_typed_dict(self): + self.check(""" + from typing_extensions import TypedDict + + class Foo(TypedDict, total=False): ... + """, """ + import typing_extensions + + from typing_extensions import TypedDict + + class Foo(typing_extensions.TypedDict): ... + """) + def test_multiple_classdef_kwargs(self): self.check(""" from typing import TypedDict