8000 Set TypedDicts to always be their declared type as opposed to the type inferred when instantiated by rowillia · Pull Request #2621 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Set TypedDicts to always be their declared type as opposed to the type inferred when instantiated #2621

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Take suggestion from Jukka to have calls to typed dicts always result…
… in exact declared type

See #2621 (comment)
  • Loading branch information
Roy Williams committed Jan 6, 2017
commit 0ca0ae608b293c67c20db1a06180d6336fe29ee7
4 changes: 2 additions & 2 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,12 @@ def check_typeddict_call_with_kwargs(self, callee: TypedDictType,
for (item_name, item_expected_type) in callee.items.items():
item_value = kwargs[item_name]

item_actual_type = self.chk.check_simple_assignment(
self.chk.check_simple_assignment(
lvalue_type=item_expected_type, rvalue=item_value, context=item_value,
msg=messages.INCOMPATIBLE_TYPES,
lvalue_name='TypedDict item "{}"'.format(item_name),
rvalue_name='expression')
items[item_name] = item_actual_type
items[item_name] = item_expected_type

mapping_value_type = join.join_type_list(list(items.values()))
fallback = self.chk.named_generic_type('typing.Mapping',
Expand Down
2 changes: 1 addition & 1 deletion mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def visit_typeddict_type(self, left: TypedDictType) -> bool:
if not left.names_are_wider_than(right):
return False
for (_, l, r) in left.zip(right):
if not is_subtype(l, r, self.check_type_parameter):
if not is_equivalent(l, r, self.check_type_parameter):
return False
# (NOTE: Fallbacks don't matter.)
return True
Expand Down
17 changes: 12 additions & 5 deletions test-data/unit/check-typeddict.test
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ def convert(op: ObjectPoint) -> Point:
return op # E: Incompatible return value type (got "ObjectPoint", expected "Point")
[builtins fixtures/dict.pyi]

[case testCannotConvertTypedDictToSimilarTypedDictWithWiderItemTypes]
from mypy_extensions import TypedDict
Point = TypedDict('Point', {'x': int, 'y': int})
ObjectPoint = TypedDict('ObjectPoint', {'x': object, 'y': object})
def convert(p: Point) -> ObjectPoint:
return p # E: Incompatible return value type (got "Point", expected "ObjectPoint")
[builtins fixtures/dict.pyi]

[case testCannotConvertTypedDictToSimilarTypedDictWithIncompatibleItemTypes]
from mypy_extensions import TypedDict
Point = TypedDict('Point', {'x': int, 'y': int})
Expand Down Expand Up @@ -143,7 +151,6 @@ Point = TypedDict('Point', {'x': int, 'y': int})
def create_point() -> Point:
return Point(x=1.2, y=2.5)
[out]
main:5: error: Incompatible return value type (got "TypedDict(x=float, y=float)", expected "Point")
main:5: error: Incompatible types (expression has type "float", TypedDict item "x" has type "int")
main:5: error: Incompatible types (expression has type "float", TypedDict item "y" has type "int")
[builtins fixtures/dict.pyi]
Expand Down Expand Up @@ -214,9 +221,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.int, meta=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])'
reveal_type(c2) # E: Revealed type is 'TypedDict(value=builtins.int, meta=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.object])'
reveal_type(joined_cells) # E: Revealed type is 'builtins.list[TypedDict(value=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]'
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])]'
[builtins fixtures/dict.pyi]

[case testJoinOfDisjointTypedDictsIsEmptyTypedDict]
Expand All @@ -227,7 +234,7 @@ 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.str, _fallback=typing.Mapping[builtins.str, builtins.str])'
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, builtins.None])]'
[builtins fixtures/dict.pyi]

Expand Down
0