diff --git a/CHANGELOG b/CHANGELOG index 5b46d01bc..d0af7297f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2020.07.20 +* pyi parser: support importing TypedDict from typing_extensions. + Version 2020.07.14 * Populate the `cls` arg in classmethods with the class type. * Log [not-supported-yet] as soon as a recursive type alias is defined. diff --git a/pytype/__version__.py b/pytype/__version__.py index bff9c103f..4c8803d96 100644 --- a/pytype/__version__.py +++ b/pytype/__version__.py @@ -1,2 +1,2 @@ # pylint: skip-file -__version__ = '2020.07.14' +__version__ = '2020.07.20' 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 diff --git a/pytype/pytd/builtins/2/__builtin__.pytd b/pytype/pytd/builtins/2/__builtin__.pytd index a11e193d0..ee581d183 100644 --- a/pytype/pytd/builtins/2/__builtin__.pytd +++ b/pytype/pytd/builtins/2/__builtin__.pytd @@ -477,7 +477,6 @@ class dict(Dict[_K, _V]): self = dict[_K or str, _V or _V2] def update(self, E, ...) -> None: self = dict[?, ?] - def update(self) -> NoneType def viewitems(self) -> dict_items[_K,_V] def viewkeys(self) -> dict_keys[_K] def viewvalues(self) -> dict_values[_V] diff --git a/pytype/pytd/builtins/3/__builtin__.pytd b/pytype/pytd/builtins/3/__builtin__.pytd index 68988efbc..0e0ea210b 100644 --- a/pytype/pytd/builtins/3/__builtin__.pytd +++ b/pytype/pytd/builtins/3/__builtin__.pytd @@ -1175,4 +1175,4 @@ def open( errors: Optional[str] = ..., newline: Optional[str] = ..., closefd: bool = ..., -) -> IO: ... \ No newline at end of file +) -> IO: ... diff --git a/pytype/pytd/builtins/3/builtins.pytd b/pytype/pytd/builtins/3/builtins.pytd index 68988efbc..0e0ea210b 100644 --- a/pytype/pytd/builtins/3/builtins.pytd +++ b/pytype/pytd/builtins/3/builtins.pytd @@ -1175,4 +1175,4 @@ def open( errors: Optional[str] = ..., newline: Optional[str] = ..., closefd: bool = ..., -) -> IO: ... \ No newline at end of file +) -> IO: ... diff --git a/pytype/tools/traces/README.md b/pytype/tools/traces/README.md new file mode 100644 index 000000000..7933a5780 --- /dev/null +++ b/pytype/tools/traces/README.md @@ -0,0 +1 @@ +A flexible, lightweight library to access the type information in pytype’s opcode traces.