diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 98adab83804b..aec7f2585064 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -1027,6 +1027,11 @@ value of type ``Awaitable[T]``: my_coroutine = countdown_1("Millennium Falcon", 5) reveal_type(my_coroutine) # has type 'Awaitable[str]' +.. note:: + + :ref:`reveal_type() ` displays the inferred static type of + an expression. + If you want to use coroutines in older versions of Python that do not support the ``async def`` syntax, you can instead use the ``@asyncio.coroutine`` decorator to convert a generator into a coroutine. @@ -1284,6 +1289,14 @@ just need to be careful with it, as it could result in a ``KeyError``. Requiring ``get()`` everywhere would be too cumbersome. (Note that you are free to use ``get()`` with total TypedDicts as well.) +Keys that aren't required are shown with a ``?`` in error messages: + +.. code-block:: python + + # Revealed type is 'TypedDict('GuiOptions', {'language'?: builtins.str, + # 'color'?: builtins.str})' + reveal_type(options) + Totality also affects structural compatibility. You can't use a partial TypedDict when a total one is expected. Also, a total typed dict is not valid when a partial one is expected. diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index a1da1328b090..636a56b11a70 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -188,8 +188,10 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: return self.accept(e.analyzed, self.type_context[-1]) if isinstance(e.callee, NameExpr) and isinstance(e.callee.node, TypeInfo) and \ e.callee.node.typeddict_type is not None: - return self.check_typeddict_call(e.callee.node.typeddict_type, - e.arg_kinds, e.arg_names, e.args, e) + # Use named fallback for better error messages. + typeddict_type = e.callee.node.typeddict_type.copy_modified( + fallback=Instance(e.callee.node, [])) + return self.check_typeddict_call(typeddict_type, e.arg_kinds, e.arg_names, e.args, e) if isinstance(e.callee, NameExpr) and e.callee.name in ('isinstance', 'issubclass'): for typ in mypy.checker.flatten(e.args[1]): if isinstance(typ, NameExpr): @@ -303,7 +305,6 @@ def check_typeddict_call_with_kwargs(self, callee: TypedDictType, context=context) return AnyType() - items = OrderedDict() # type: OrderedDict[str, Type] for (item_name, item_expected_type) in callee.items.items(): if item_name in kwargs: item_value = kwargs[item_name] @@ -312,12 +313,8 @@ def check_typeddict_call_with_kwargs(self, callee: TypedDictType, msg=messages.INCOMPATIBLE_TYPES, lvalue_name='TypedDict item "{}"'.format(item_name), rvalue_name='expression') - items[item_name] = item_expected_type - mapping_value_type = join.join_type_list(list(items.values())) - fallback = self.chk.named_generic_type('typing.Mapping', - [self.chk.str_type(), mapping_value_type]) - return TypedDictType(items, set(callee.required_keys), fallback) + return callee # Types and methods that can be used to infer partial types. item_args = {'builtins.list': ['append'], diff --git a/mypy/types.py b/mypy/types.py index da6ddba5207d..60cf37aca48b 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1513,19 +1513,22 @@ def visit_tuple_type(self, t: TupleType) -> str: return 'Tuple[{}]'.format(s) def visit_typeddict_type(self, t: TypedDictType) -> str: - s = self.keywords_str(t.items.items()) - if t.required_keys == set(t.items): - keys_str = '' - elif t.required_keys == set(): - keys_str = ', _total=False' - else: - keys_str = ', _required_keys=[{}]'.format(', '.join(sorted(t.required_keys))) + def item_str(name: str, typ: str) -> str: + if name in t.required_keys: + return '{!r}: {}'.format(name, typ) + else: + return '{!r}?: {}'.format(name, typ) + + s = '{' + ', '.join(item_str(name, typ.accept(self)) + for name, typ in t.items.items()) + '}' + prefix = '' + suffix = '' if t.fallback and t.fallback.type: - if s == '': - return 'TypedDict(_fallback={}{})'.format(t.fallback.accept(self), keys_str) + if t.fallback.type.fullname() != 'typing.Mapping': + prefix = repr(t.fallback.type.fullname()) + ', ' else: - return 'TypedDict({}, _fallback={}{})'.format(s, t.fallback.accept(self), keys_str) - return 'TypedDict({})'.format(s) + suffix = ', fallback={}'.format(t.fallback.accept(self)) + return 'TypedDict({}{}{})'.format(prefix, s, suffix) def visit_star_type(self, t: StarType) -> str: s = t.type.accept(self) @@ -1560,15 +1563,6 @@ def list_str(self, a: List[Type]) -> str: res.append(str(t)) return ', '.join(res) - def keywords_str(self, a: Iterable[Tuple[str, Type]]) -> str: - """Convert keywords to strings (pretty-print types) - and join the results with commas. - """ - return ', '.join([ - '{}={}'.format(name, t.accept(self)) - for (name, t) in a - ]) - class TypeQuery(SyntheticTypeVisitor[T]): """Visitor for performing queries of types. diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index f8f27d3a2178..19b6a7f2db56 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -3350,8 +3350,8 @@ x: TD x1 = TD({'x': []}) y: NM y1 = NM(x=[]) -reveal_type(x) # E: Revealed type is 'TypedDict(x=builtins.list[Any], _fallback=__main__.TD)' -reveal_type(x1) # E: Revealed type is 'TypedDict(x=builtins.list[Any], _fallback=typing.Mapping[builtins.str, builtins.list[Any]])' +reveal_type(x) # E: Revealed type is 'TypedDict('__main__.TD', {'x': builtins.list[Any]})' +reveal_type(x1) # E: Revealed type is 'TypedDict('__main__.TD', {'x': builtins.list[Any]})' reveal_type(y) # E: Revealed type is 'Tuple[builtins.list[Any], fallback=__main__.NM]' reveal_type(y1) # E: Revealed type is 'Tuple[builtins.list[Any], fallback=__main__.NM]' [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index d28cb1acf512..7fd17acd3041 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -1901,11 +1901,11 @@ A = TypedDict('A', {'x': int, 'y': str}) x: A [builtins fixtures/dict.pyi] [out1] -main:2: error: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=b.A)' -main:4: error: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=b.A)' +main:2: error: Revealed type is 'TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})' +main:4: error: Revealed type is 'TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})' [out2] -main:2: error: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=b.A)' -main:4: error: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=b.A)' +main:2: error: Revealed type is 'TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})' +main:4: error: Revealed type is 'TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})' [case testSerializeMetaclass] import b diff --git a/test-data/unit/check-serialize.test b/test-data/unit/check-serialize.test index bf0faebe5880..65692ee94b76 100644 --- a/test-data/unit/check-serialize.test +++ b/test-data/unit/check-serialize.test @@ -1018,12 +1018,12 @@ class C: self.c = A [builtins fixtures/dict.pyi] [out1] -main:2: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -main:3: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=ntcrash.C.A@4)' +main:2: error: Revealed type is 'TypedDict('ntcrash.C.A@4', {'x': builtins.int})' +main:3: error: Revealed type is 'TypedDict('ntcrash.C.A@4', {'x': builtins.int})' main:4: error: Revealed type is 'def () -> ntcrash.C.A@4' [out2] -main:2: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -main:3: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=ntcrash.C.A@4)' +main:2: error: Revealed type is 'TypedDict('ntcrash.C.A@4', {'x': builtins.int})' +main:3: error: Revealed type is 'TypedDict('ntcrash.C.A@4', {'x': builtins.int})' main:4: error: Revealed type is 'def () -> ntcrash.C.A@4' [case testSerializeNonTotalTypedDict] @@ -1035,9 +1035,9 @@ D = TypedDict('D', {'x': int, 'y': str}, total=False) d: D [builtins fixtures/dict.pyi] [out1] -main:2: error: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=m.D, _total=False)' +main:2: error: Revealed type is 'TypedDict('m.D', {'x'?: builtins.int, 'y'?: builtins.str})' [out2] -main:2: error: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=m.D, _total=False)' +main:2: error: Revealed type is 'TypedDict('m.D', {'x'?: builtins.int, 'y'?: builtins.str})' -- -- Modules diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index a5679da83ae2..a923a403b63d 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -4,29 +4,41 @@ from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int}) p = Point(x=42, y=1337) -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})' +# Use values() to check fallback value type. +reveal_type(p.values()) # E: Revealed type is 'typing.Iterable[builtins.int*]' [builtins fixtures/dict.pyi] +[typing fixtures/typing-full.pyi] [case testCanCreateTypedDictInstanceWithDictCall] from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int}) p = Point(dict(x=42, y=1337)) -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})' +# Use values() to check fallback value type. +reveal_type(p.values()) # E: Revealed type is 'typing.Iterable[builtins.int*]' [builtins fixtures/dict.pyi] +[typing fixtures/typing-full.pyi] [case testCanCreateTypedDictInstanceWithDictLiteral] from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int}) p = Point({'x': 42, 'y': 1337}) -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})' +# Use values() to check fallback value type. +reveal_type(p.values()) # E: Revealed type is 'typing.Iterable[builtins.int*]' [builtins fixtures/dict.pyi] +[typing fixtures/typing-full.pyi] [case testCanCreateTypedDictInstanceWithNoArguments] +from typing import TypeVar, Union from mypy_extensions import TypedDict EmptyDict = TypedDict('EmptyDict', {}) p = EmptyDict() -reveal_type(p) # E: Revealed type is 'TypedDict(_fallback=typing.Mapping[builtins.str, ])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.EmptyDict', {})' +reveal_type(p.values()) # E: Revealed type is 'typing.Iterable[]' [builtins fixtures/dict.pyi] +[typing fixtures/typing-full.pyi] -- Create Instance (Errors) @@ -47,13 +59,13 @@ p = Point({x: 42, 'y': 1337}) # E: Expected TypedDict key to be string literal [case testCannotCreateTypedDictInstanceWithExtraItems] from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int}) -p = Point(x=42, y=1337, z=666) # E: Expected TypedDict keys ('x', 'y') but found keys ('x', 'y', 'z') +p = Point(x=42, y=1337, z=666) # E: Extra key 'z' for TypedDict "Point" [builtins fixtures/dict.pyi] [case testCannotCreateTypedDictInstanceWithMissingItems] from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int}) -p = Point(x=42) # E: Expected TypedDict keys ('x', 'y') but found only key 'x' +p = Point(x=42) # E: Key 'y' missing for TypedDict "Point" [builtins fixtures/dict.pyi] [case testCannotCreateTypedDictInstanceWithIncompatibleItemType] @@ -74,7 +86,7 @@ class Point(TypedDict): y: int p = Point(x=42, y=1337) -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})' [builtins fixtures/dict.pyi] [case testCanCreateTypedDictWithSubclass] @@ -87,8 +99,8 @@ class Point2D(Point1D): y: int r: Point1D p: Point2D -reveal_type(r) # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=__main__.Point1D)' -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=__main__.Point2D)' +reveal_type(r) # E: Revealed type is 'TypedDict('__main__.Point1D', {'x': builtins.int})' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point2D', {'x': builtins.int, 'y': builtins.int})' [builtins fixtures/dict.pyi] [case testCanCreateTypedDictWithSubclass2] @@ -101,7 +113,7 @@ class Point2D(TypedDict, Point1D): # We also allow to include TypedDict in bases y: int p: Point2D -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=__main__.Point2D)' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point2D', {'x': builtins.int, 'y': builtins.int})' [builtins fixtures/dict.pyi] [case testCanCreateTypedDictClassEmpty] @@ -112,7 +124,7 @@ class EmptyDict(TypedDict): pass p = EmptyDict() -reveal_type(p) # E: Revealed type is 'TypedDict(_fallback=typing.Mapping[builtins.str, ])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.EmptyDict', {})' [builtins fixtures/dict.pyi] @@ -138,7 +150,7 @@ class Point2D(Point1D, A): # E: All bases of a new TypedDict must be TypedDict t y: int p: Point2D -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=__main__.Point2D)' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point2D', {'x': builtins.int, 'y': builtins.int})' [builtins fixtures/dict.pyi] [case testCannotCreateTypedDictWithClassWithOtherStuff] @@ -152,7 +164,7 @@ class Point(TypedDict): z = int # E: Invalid statement in TypedDict definition; expected "field_name: field_type" p = Point(x=42, y=1337, z='whatever') -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, z=Any, _fallback=typing.Mapping[builtins.str, Any])' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int, 'z': Any})' [builtins fixtures/dict.pyi] [case testCanCreateTypedDictTypeWithUnderscoreItemName] @@ -169,7 +181,7 @@ class Point(TypedDict): _y: int p: Point -reveal_type(p) # E: Revealed type is 'TypedDict(x=builtins.int, _y=builtins.int, _fallback=__main__.Point)' +reveal_type(p) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, '_y': builtins.int})' [builtins fixtures/dict.pyi] [case testCannotCreateTypedDictWithClassOverwriting] @@ -181,7 +193,7 @@ class Bad(TypedDict): x: str # E: Duplicate TypedDict field "x" b: Bad -reveal_type(b) # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=__main__.Bad)' +reveal_type(b) # E: Revealed type is 'TypedDict('__main__.Bad', {'x': builtins.int})' [builtins fixtures/dict.pyi] [case testCannotCreateTypedDictWithClassOverwriting2] @@ -196,7 +208,7 @@ class Bad(Point1, Point2): # E: Cannot overwrite TypedDict field "x" while mergi pass b: Bad -reveal_type(b) # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=__main__.Bad)' +reveal_type(b) # E: Revealed type is 'TypedDict('__main__.Bad', {'x': builtins.int})' [builtins fixtures/dict.pyi] [case testCannotCreateTypedDictWithClassOverwriting2] @@ -209,7 +221,7 @@ class Point2(Point1): x: float # E: Cannot overwrite TypedDict field "x" while extending p2: Point2 -reveal_type(p2) # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=__main__.Point2)' +reveal_type(p2) # E: Revealed type is 'TypedDict('__main__.Point2', {'x': builtins.int})' [builtins fixtures/dict.pyi] @@ -292,7 +304,7 @@ from typing import Any, Mapping Point = TypedDict('Point', {'x': float, 'y': float}) def create_point() -> Point: return Point(x=1, y=2) -reveal_type(Point(x=1, y=2)) # E: Revealed type is 'TypedDict(x=builtins.float, y=builtins.float, _fallback=typing.Mapping[builtins.str, builtins.float])' +reveal_type(Point(x=1, y=2)) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.float, 'y': builtins.float})' [builtins fixtures/dict.pyi] [case testTypedDictDoesNotAcceptsFloatForInt] @@ -321,7 +333,7 @@ def create_point(something: Any) -> Point: from mypy_extensions import TypedDict from typing import List D = TypedDict('D', {'x': List[int]}) -reveal_type(D(x=[])) # E: Revealed type is 'TypedDict(x=builtins.list[builtins.int], _fallback=typing.Mapping[builtins.str, builtins.list[builtins.int]])' +reveal_type(D(x=[])) # E: Revealed type is 'TypedDict('__main__.D', {'x': builtins.list[builtins.int]})' [builtins fixtures/dict.pyi] -- TODO: Fix mypy stubs so that the following passes in the test suite @@ -384,11 +396,12 @@ TaggedPoint = TypedDict('TaggedPoint', {'type': str, 'x': int, 'y': int}) Point3D = TypedDict('Point3D', {'x': int, 'y': int, 'z': int}) p1 = TaggedPoint(type='2d', x=0, y=0) p2 = Point3D(x=1, y=1, z=1) -joined_points = [p1, p2] -reveal_type(p1) # E: Revealed type is 'TypedDict(type=builtins.str, x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.object])' -reveal_type(p2) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, z=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -reveal_type(joined_points) # E: Revealed type is 'builtins.list[TypedDict(x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' +joined_points = [p1, p2][0] +reveal_type(p1.values()) # E: Revealed type is 'typing.Iterable[builtins.object*]' +reveal_type(p2.values()) # E: Revealed type is 'typing.Iterable[builtins.int*]' +reveal_type(joined_points) # E: Revealed type is 'TypedDict({'x': builtins.int, 'y': builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' [builtins fixtures/dict.pyi] +[typing fixtures/typing-full.pyi] [case testJoinOfTypedDictRemovesNonequivalentKeys] from mypy_extensions import TypedDict @@ -397,9 +410,9 @@ CellWithObject = TypedDict('CellWithObject', {'value': object, 'meta': object}) c1 = CellWithInt(value=1, meta=42) c2 = CellWithObject(value=2, meta='turtle doves') joined_cells = [c1, c2] -reveal_type(c1) # E: Revealed type is 'TypedDict(value=builtins.object, meta=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.object])' -reveal_type(c2) # E: Revealed type is 'TypedDict(value=builtins.object, meta=builtins.object, _fallback=typing.Mapping[builtins.str, builtins.object])' -reveal_type(joined_cells) # E: Revealed type is 'builtins.list[TypedDict(value=builtins.object, _fallback=typing.Mapping[builtins.str, builtins.object])]' +reveal_type(c1) # E: Revealed type is 'TypedDict('__main__.CellWithInt', {'value': builtins.object, 'meta': builtins.int})' +reveal_type(c2) # E: Revealed type is 'TypedDict('__main__.CellWithObject', {'value': builtins.object, 'meta': builtins.object})' +reveal_type(joined_cells) # E: Revealed type is 'builtins.list[TypedDict({'value': builtins.object}, fallback=typing.Mapping[builtins.str, builtins.object])]' [builtins fixtures/dict.pyi] [case testJoinOfDisjointTypedDictsIsEmptyTypedDict] @@ -409,9 +422,9 @@ Cell = TypedDict('Cell', {'value': object}) d1 = Point(x=0, y=0) d2 = Cell(value='pear tree') joined_dicts = [d1, d2] -reveal_type(d1) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -reveal_type(d2) # E: Revealed type is 'TypedDict(value=builtins.object, _fallback=typing.Mapping[builtins.str, builtins.object])' -reveal_type(joined_dicts) # E: Revealed type is 'builtins.list[TypedDict(_fallback=typing.Mapping[builtins.str, ])]' +reveal_type(d1) # E: Revealed type is 'TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})' +reveal_type(d2) # E: Revealed type is 'TypedDict('__main__.Cell', {'value': builtins.object})' +reveal_type(joined_dicts) # E: Revealed type is 'builtins.list[TypedDict({}, fallback=typing.Mapping[builtins.str, ])]' [builtins fixtures/dict.pyi] [case testJoinOfTypedDictWithCompatibleMappingIsMapping] @@ -474,7 +487,7 @@ YZ = TypedDict('YZ', {'y': int, 'z': int}) T = TypeVar('T') def f(x: Callable[[T, T], None]) -> T: pass def g(x: XY, y: YZ) -> None: pass -reveal_type(f(g)) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, z=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' +reveal_type(f(g)) # E: Revealed type is 'TypedDict({'x': builtins.int, 'y': builtins.int, 'z': builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' [builtins fixtures/dict.pyi] [case testMeetOfTypedDictsWithIncompatibleCommonKeysIsUninhabited] @@ -497,7 +510,7 @@ Z = TypedDict('Z', {'z': int}) T = TypeVar('T') def f(x: Callable[[T, T], None]) -> T: pass def g(x: X, y: Z) -> None: pass -reveal_type(f(g)) # E: Revealed type is 'TypedDict(x=builtins.int, z=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' +reveal_type(f(g)) # E: Revealed type is 'TypedDict({'x': builtins.int, 'z': builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' [builtins fixtures/dict.pyi] # TODO: It would be more accurate for the meet to be TypedDict instead. @@ -546,7 +559,7 @@ YZ = TypedDict('YZ', {'y': int, 'z': int}, total=False) T = TypeVar('T') def f(x: Callable[[T, T], None]) -> T: pass def g(x: XY, y: YZ) -> None: pass -reveal_type(f(g)) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, z=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int], _total=False)' +reveal_type(f(g)) # E: Revealed type is 'TypedDict({'x'?: builtins.int, 'y'?: builtins.int, 'z'?: builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' [builtins fixtures/dict.pyi] [case testMeetOfTypedDictsWithNonTotalAndTotal] @@ -557,7 +570,7 @@ YZ = TypedDict('YZ', {'y': int, 'z': int}) T = TypeVar('T') def f(x: Callable[[T, T], None]) -> T: pass def g(x: XY, y: YZ) -> None: pass -reveal_type(f(g)) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, z=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int], _required_keys=[y, z])' +reveal_type(f(g)) # E: Revealed type is 'TypedDict({'x'?: builtins.int, 'y': builtins.int, 'z': builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' [builtins fixtures/dict.pyi] [case testMeetOfTypedDictsWithIncompatibleNonTotalAndTotal] @@ -681,7 +694,7 @@ p['x'] = 'y' # E: Argument 2 has incompatible type "str"; expected "int" from mypy_extensions import TypedDict TaggedPoint = TypedDict('TaggedPoint', {'type': str, 'x': int, 'y': int}) p = TaggedPoint(type='2d', x=42, y=1337) -p['z'] = 1 # E: 'z' is not a valid TypedDict key; expected one of ('type', 'x', 'y') +p['z'] = 1 # E: TypedDict "TaggedPoint" has no key 'z' [builtins fixtures/dict.pyi] [case testCannotSetItemOfTypedDictWithNonLiteralKey] @@ -749,15 +762,15 @@ e = E(a='') f = F(x=1) g = G(a=cast(Any, 1)) # Work around #2610 -reveal_type(u(d, d)) # E: Revealed type is 'TypedDict(a=builtins.int, b=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -reveal_type(u(c, d)) # E: Revealed type is 'TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -reveal_type(u(d, c)) # E: Revealed type is 'TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])' -reveal_type(u(c, e)) # E: Revealed type is 'Union[TypedDict(a=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.str]), TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' -reveal_type(u(e, c)) # E: Revealed type is 'Union[TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int]), TypedDict(a=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.str])]' -reveal_type(u(c, f)) # E: Revealed type is 'Union[TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int]), TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' -reveal_type(u(f, c)) # E: Revealed type is 'Union[TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int]), TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' -reveal_type(u(c, g)) # E: Revealed type is 'Union[TypedDict(a=Any, _fallback=typing.Mapping[builtins.str, Any]), TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' -reveal_type(u(g, c)) # E: Revealed type is 'Union[TypedDict(a=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int]), TypedDict(a=Any, _fallback=typing.Mapping[builtins.str, Any])]' +reveal_type(u(d, d)) # E: Revealed type is 'TypedDict('__main__.D', {'a': builtins.int, 'b': builtins.int})' +reveal_type(u(c, d)) # E: Revealed type is 'TypedDict('__main__.C', {'a': builtins.int})' +reveal_type(u(d, c)) # E: Revealed type is 'TypedDict('__main__.C', {'a': builtins.int})' +reveal_type(u(c, e)) # E: Revealed type is 'Union[TypedDict('__main__.E', {'a': builtins.str}), TypedDict('__main__.C', {'a': builtins.int})]' +reveal_type(u(e, c)) # E: Revealed type is 'Union[TypedDict('__main__.C', {'a': builtins.int}), TypedDict('__main__.E', {'a': builtins.str})]' +reveal_type(u(c, f)) # E: Revealed type is 'Union[TypedDict('__main__.F', {'x': builtins.int}), TypedDict('__main__.C', {'a': builtins.int})]' +reveal_type(u(f, c)) # E: Revealed type is 'Union[TypedDict('__main__.C', {'a': builtins.int}), TypedDict('__main__.F', {'x': builtins.int})]' +reveal_type(u(c, g)) # E: Revealed type is 'Union[TypedDict('__main__.G', {'a': Any}), TypedDict('__main__.C', {'a': builtins.int})]' +reveal_type(u(g, c)) # E: Revealed type is 'Union[TypedDict('__main__.C', {'a': builtins.int}), TypedDict('__main__.G', {'a': Any})]' [builtins fixtures/dict.pyi] [case testTypedDictUnionSimplification2] @@ -778,9 +791,9 @@ m_s_a: Mapping[str, Any] reveal_type(u(c, m_s_i)) # E: Revealed type is 'typing.Mapping*[builtins.str, builtins.int]' reveal_type(u(m_s_i, c)) # E: Revealed type is 'typing.Mapping*[builtins.str, builtins.int]' -reveal_type(u(c, m_s_s)) # E: Revealed type is 'Union[typing.Mapping*[builtins.str, builtins.str], TypedDict(a=builtins.int, b=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' -reveal_type(u(c, m_i_i)) # E: Revealed type is 'Union[typing.Mapping*[builtins.int, builtins.int], TypedDict(a=builtins.int, b=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' -reveal_type(u(c, m_s_a)) # E: Revealed type is 'Union[typing.Mapping*[builtins.str, Any], TypedDict(a=builtins.int, b=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]' +reveal_type(u(c, m_s_s)) # E: Revealed type is 'Union[typing.Mapping*[builtins.str, builtins.str], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]' +reveal_type(u(c, m_i_i)) # E: Revealed type is 'Union[typing.Mapping*[builtins.int, builtins.int], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]' +reveal_type(u(c, m_s_a)) # E: Revealed type is 'Union[typing.Mapping*[builtins.str, Any], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]' [builtins fixtures/dict.pyi] @@ -817,7 +830,7 @@ p2: Point p2 = dict(x='bye') # E: Key 'y' missing for TypedDict "Point" p3 = Point(x=1, y=2) -p3 = {'x': 'hi'} # E: Expected TypedDict keys ('x', 'y') but found only key 'x' +p3 = {'x': 'hi'} # E: Key 'y' missing for TypedDict "Point" p4: Point = {'x': 1, 'y': 2} @@ -902,7 +915,7 @@ from mypy_extensions import TypedDict D = TypedDict('D', {'x': int, 'y': str}) E = TypedDict('E', {'d': D}) p = E(d=D(x=0, y='')) -reveal_type(p.get('d', {'x': 1, 'y': ''})) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=__main__.D)' +reveal_type(p.get('d', {'x': 1, 'y': ''})) # E: Revealed type is 'TypedDict('__main__.D', {'x': builtins.int, 'y': builtins.str})' [builtins fixtures/dict.pyi] [typing fixtures/typing-full.pyi] @@ -921,9 +934,9 @@ C = TypedDict('C', {'a': int}) D = TypedDict('D', {'x': C, 'y': str}) d: D reveal_type(d.get('x', {})) \ - # E: Revealed type is 'TypedDict(a=builtins.int, _fallback=__main__.C, _total=False)' + # E: Revealed type is 'TypedDict('__main__.C', {'a'?: builtins.int})' reveal_type(d.get('x', None)) \ - # E: Revealed type is 'Union[TypedDict(a=builtins.int, _fallback=__main__.C), builtins.None]' + # E: Revealed type is 'Union[TypedDict('__main__.C', {'a': builtins.int}), builtins.None]' reveal_type(d.get('x', {}).get('a')) # E: Revealed type is 'Union[builtins.int, builtins.None]' reveal_type(d.get('x', {})['a']) # E: Revealed type is 'builtins.int' [builtins fixtures/dict.pyi] @@ -937,7 +950,7 @@ from mypy_extensions import TypedDict D = TypedDict('D', {'x': int, 'y': str}, total=True) d: D reveal_type(d) \ - # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=__main__.D)' + # E: Revealed type is 'TypedDict('__main__.D', {'x': builtins.int, 'y': builtins.str})' [builtins fixtures/dict.pyi] [case testTypedDictWithInvalidTotalArgument] @@ -952,7 +965,7 @@ D = TypedDict('D', {'x': int}, False) # E: Unexpected arguments to TypedDict() from mypy_extensions import TypedDict D = TypedDict('D', {'x': int, 'y': str}, total=False) def f(d: D) -> None: - reveal_type(d) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=__main__.D, _total=False)' + reveal_type(d) # E: Revealed type is 'TypedDict('__main__.D', {'x'?: builtins.int, 'y'?: builtins.str})' f({}) f({'x': 1}) f({'y': ''}) @@ -965,11 +978,11 @@ f({'x': ''}) # E: Incompatible types (expression has type "str", TypedDict item from mypy_extensions import TypedDict D = TypedDict('D', {'x': int, 'y': str}, total=False) def f(d: D) -> None: pass -reveal_type(D()) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.object], _total=False)' -reveal_type(D(x=1)) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.object], _total=False)' +reveal_type(D()) # E: Revealed type is 'TypedDict('__main__.D', {'x'?: builtins.int, 'y'?: builtins.str})' +reveal_type(D(x=1)) # E: Revealed type is 'TypedDict('__main__.D', {'x'?: builtins.int, 'y'?: builtins.str})' f(D(y='')) f(D(x=1, y='')) -f(D(x=1, z='')) # E: Expected TypedDict key 'x' but found keys ('x', 'z') +f(D(x=1, z='')) # E: Extra key 'z' for TypedDict "D" f(D(x='')) # E: Incompatible types (expression has type "str", TypedDict item "x" has type "int") [builtins fixtures/dict.pyi] @@ -1015,15 +1028,15 @@ a: A b: B c: C reveal_type(j(a, b)) \ - # E: Revealed type is 'TypedDict(_fallback=typing.Mapping[builtins.str, ])' + # E: Revealed type is 'TypedDict({}, fallback=typing.Mapping[builtins.str, ])' reveal_type(j(b, b)) \ - # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int], _total=False)' + # E: Revealed type is 'TypedDict({'x'?: builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' reveal_type(j(c, c)) \ - # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.object], _total=False)' + # E: Revealed type is 'TypedDict({'x'?: builtins.int, 'y'?: builtins.str}, fallback=typing.Mapping[builtins.str, builtins.object])' reveal_type(j(b, c)) \ - # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int], _total=False)' + # E: Revealed type is 'TypedDict({'x'?: builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' reveal_type(j(c, b)) \ - # E: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int], _total=False)' + # E: Revealed type is 'TypedDict({'x'?: builtins.int}, fallback=typing.Mapping[builtins.str, builtins.int])' [builtins fixtures/dict.pyi] [case testTypedDictClassWithTotalArgument] @@ -1032,7 +1045,7 @@ class D(TypedDict, total=False): x: int y: str d: D -reveal_type(d) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.str, _fallback=__main__.D, _total=False)' +reveal_type(d) # E: Revealed type is 'TypedDict('__main__.D', {'x'?: builtins.int, 'y'?: builtins.str})' [builtins fixtures/dict.pyi] [case testTypedDictClassWithInvalidTotalArgument] @@ -1055,7 +1068,7 @@ class B(TypedDict, A, total=False): class C(TypedDict, B, total=True): z: str c: C -reveal_type(c) # E: Revealed type is 'TypedDict(x=builtins.int, y=builtins.int, z=builtins.str, _fallback=__main__.C, _required_keys=[x, z])' +reveal_type(c) # E: Revealed type is 'TypedDict('__main__.C', {'x': builtins.int, 'y'?: builtins.int, 'z': builtins.str})' [builtins fixtures/dict.pyi] [case testNonTotalTypedDictInErrorMessages] @@ -1172,7 +1185,7 @@ def f(x: int) -> None: ... def f(x): pass a: A -f(a) # E: No overload variant of "f" matches argument types [TypedDict(x=builtins.int, _fallback=__main__.A)] +f(a) # E: No overload variant of "f" matches argument types [TypedDict('__main__.A', {'x': builtins.int})] [builtins fixtures/dict.pyi] [typing fixtures/typing-full.pyi] @@ -1250,7 +1263,7 @@ X = TypedDict('X', {'b': 'B', 'c': 'C'}) class B: pass class C(B): pass x: X -reveal_type(x) # E: Revealed type is 'TypedDict(b=__main__.B, c=__main__.C, _fallback=__main__.X)' +reveal_type(x) # E: Revealed type is 'TypedDict('__main__.X', {'b': __main__.B, 'c': __main__.C})' m1: Mapping[str, B] = x m2: Mapping[str, C] = x # E: Incompatible types in assignment (expression has type "X", variable has type Mapping[str, C]) [builtins fixtures/dict.pyi] @@ -1264,7 +1277,7 @@ class X(TypedDict): class B: pass class C(B): pass x: X -reveal_type(x) # E: Revealed type is 'TypedDict(b=__main__.B, c=__main__.C, _fallback=__main__.X)' +reveal_type(x) # E: Revealed type is 'TypedDict('__main__.X', {'b': __main__.B, 'c': __main__.C})' m1: Mapping[str, B] = x m2: Mapping[str, C] = x # E: Incompatible types in assignment (expression has type "X", variable has type Mapping[str, C]) [builtins fixtures/dict.pyi] @@ -1276,6 +1289,6 @@ from mypy_extensions import TypedDict X = TypedDict('X', {'a': 'A'}) # E: Invalid type "__main__.A" A = TypedDict('A', {'b': int}) x: X -reveal_type(x) # E: Revealed type is 'TypedDict(a=TypedDict(b=builtins.int, _fallback=__main__.A), _fallback=__main__.X)' +reveal_type(x) # E: Revealed type is 'TypedDict('__main__.X', {'a': TypedDict('__main__.A', {'b': builtins.int})})' reveal_type(x['a']['b']) # E: Revealed type is 'builtins.int' [builtins fixtures/dict.pyi] diff --git a/test-data/unit/fixtures/dict.pyi b/test-data/unit/fixtures/dict.pyi index 62234c69d0b2..4182afb0eecd 100644 --- a/test-data/unit/fixtures/dict.pyi +++ b/test-data/unit/fixtures/dict.pyi @@ -31,6 +31,7 @@ class str: pass # for keyword argument key type class unicode: pass # needed for py2 docstrings class list(Iterable[T], Generic[T]): # needed by some test cases + def __getitem__(self, x: int) -> T: pass def __iter__(self) -> Iterator[T]: pass def __mul__(self, x: int) -> list[T]: pass diff --git a/test-data/unit/fixtures/typing-full.pyi b/test-data/unit/fixtures/typing-full.pyi index 5a3a866b8a41..4e78cf8b16f5 100644 --- a/test-data/unit/fixtures/typing-full.pyi +++ b/test-data/unit/fixtures/typing-full.pyi @@ -108,6 +108,7 @@ class Mapping(Iterable[T], Generic[T, U]): def get(self, k: T) -> Optional[U]: ... @overload def get(self, k: T, default: Union[U, V]) -> Union[U, V]: ... + def values(self) -> Iterable[U]: pass # Approximate return type class MutableMapping(Mapping[T, U]): pass