Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 49b4b3d

Browse filesBrowse files
authored
Don't add __match_args__ for dataclasses and named tuples with --python-version < 3.10 (#12503)
Fixes #12489
1 parent 1fedf2c commit 49b4b3d
Copy full SHA for 49b4b3d

File tree

Expand file treeCollapse file tree

7 files changed

+163
-6
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+163
-6
lines changed

‎mypy/plugins/dataclasses.py

Copy file name to clipboardExpand all lines: mypy/plugins/dataclasses.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ def transform(self) -> bool:
230230
if (decorator_arguments['match_args'] and
231231
('__match_args__' not in info.names or
232232
info.names['__match_args__'].plugin_generated) and
233-
attributes):
233+
attributes and
234+
py_version >= (3, 10)):
234235
str_type = ctx.api.named_type("builtins.str")
235236
literals: List[Type] = [LiteralType(attr.name, str_type)
236237
for attr in attributes if attr.is_in_init]

‎mypy/semanal_namedtuple.py

Copy file name to clipboardExpand all lines: mypy/semanal_namedtuple.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,8 @@ def add_field(var: Var, is_initialized_in_class: bool = False,
447447
add_field(Var('_source', strtype), is_initialized_in_class=True)
448448
add_field(Var('__annotations__', ordereddictype), is_initialized_in_class=True)
449449
add_field(Var('__doc__', strtype), is_initialized_in_class=True)
450-
add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True)
450+
if self.options.python_version >= (3, 10):
451+
add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True)
451452

452453
tvd = TypeVarType(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME,
453454
-1, [], info.tuple_type)

‎mypy/test/testmerge.py

Copy file name to clipboardExpand all lines: mypy/test/testmerge.py
-2Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from mypy import build
88
from mypy.build import BuildResult
99
from mypy.modulefinder import BuildSource
10-
from mypy.defaults import PYTHON3_VERSION
1110
from mypy.errors import CompileError
1211
from mypy.nodes import (
1312
Node, MypyFile, SymbolTable, SymbolTableNode, TypeInfo, Expression, Var, TypeVarExpr,
@@ -107,7 +106,6 @@ def build(self, source: str, testcase: DataDrivenTestCase) -> Optional[BuildResu
107106
options.use_builtins_fixtures = True
108107
options.export_types = True
109108
options.show_traceback = True
110-
options.python_version = PYTHON3_VERSION
111109
main_path = os.path.join(test_temp_dir, 'main')
112110
with open(main_path, 'w', encoding='utf8') as f:
113111
f.write(source)

‎test-data/unit/check-dataclasses.test

Copy file name to clipboardExpand all lines: test-data/unit/check-dataclasses.test
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,3 +1790,48 @@ class MyDataclass:
17901790
class MyGeneric(Generic[T]): ...
17911791
class MyClass(MyGeneric[MyDataclass]): ...
17921792
[builtins fixtures/dataclasses.pyi]
1793+
1794+
[case testDataclassWithMatchArgs]
1795+
# flags: --python-version 3.10
1796+
from dataclasses import dataclass
1797+
@dataclass
1798+
class One:
1799+
bar: int
1800+
baz: str
1801+
o: One
1802+
reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]"
1803+
@dataclass(match_args=True)
1804+
class Two:
1805+
bar: int
1806+
t: Two
1807+
reveal_type(t.__match_args__) # N: Revealed type is "Tuple[Literal['bar']]"
1808+
[builtins fixtures/dataclasses.pyi]
1809+
1810+
[case testDataclassWithoutMatchArgs]
1811+
# flags: --python-version 3.10
1812+
from dataclasses import dataclass
1813+
@dataclass(match_args=False)
1814+
class One:
1815+
bar: int
1816+
baz: str
1817+
o: One
1818+
reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \
1819+
# N: Revealed type is "Any"
1820+
[builtins fixtures/dataclasses.pyi]
1821+
1822+
[case testDataclassWithMatchArgsOldVersion]
1823+
# flags: --python-version 3.9
1824+
from dataclasses import dataclass
1825+
@dataclass(match_args=True)
1826+
class One:
1827+
bar: int
1828+
o: One
1829+
reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \
1830+
# N: Revealed type is "Any"
1831+
@dataclass
1832+
class Two:
1833+
bar: int
1834+
t: Two
1835+
reveal_type(t.__match_args__) # E: "Two" has no attribute "__match_args__" \
1836+
# N: Revealed type is "Any"
1837+
[builtins fixtures/dataclasses.pyi]

‎test-data/unit/check-namedtuple.test

Copy file name to clipboardExpand all lines: test-data/unit/check-namedtuple.test
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,3 +1134,26 @@ def f(fields) -> None:
11341134
NT2 = namedtuple("bad", "x") # E: First argument to namedtuple() should be "NT2", not "bad"
11351135
nt2: NT2 = NT2(x=1)
11361136
[builtins fixtures/tuple.pyi]
1137+
1138+
[case testNamedTupleHasMatchArgs]
1139+
# flags: --python-version 3.10
1140+
from typing import NamedTuple
1141+
class One(NamedTuple):
1142+
bar: int
1143+
baz: str
1144+
o: One
1145+
reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]"
1146+
[builtins fixtures/tuple.pyi]
1147+
[typing fixtures/typing-namedtuple.pyi]
1148+
1149+
[case testNamedTupleHasNoMatchArgsOldVersion]
1150+
# flags: --python-version 3.9
1151+
from typing import NamedTuple
1152+
class One(NamedTuple):
1153+
bar: int
1154+
baz: str
1155+
o: One
1156+
reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \
1157+
# N: Revealed type is "Any"
1158+
[builtins fixtures/tuple.pyi]
1159+
[typing fixtures/typing-namedtuple.pyi]

‎test-data/unit/deps.test

Copy file name to clipboardExpand all lines: test-data/unit/deps.test
+31-1Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,7 @@ class D(C):
14201420
<m.C> -> m, m.C, m.D
14211421
<m.D> -> m.D
14221422

1423-
[case testDataclassDeps]
1423+
[case testDataclassDepsOldVersion]
14241424
# flags: --python-version 3.7
14251425
from dataclasses import dataclass
14261426

@@ -1435,6 +1435,36 @@ class B(A):
14351435
y: int
14361436
[builtins fixtures/dataclasses.pyi]
14371437

1438+
[out]
1439+
<m.A.(abstract)> -> <m.B.__init__>, m
1440+
<m.A.__dataclass_fields__> -> <m.B.__dataclass_fields__>
1441+
<m.A.__init__> -> <m.B.__init__>, m.B.__init__
1442+
<m.A.__new__> -> <m.B.__new__>
1443+
<m.A.x> -> <m.B.x>
1444+
<m.A.y> -> <m.B.y>
1445+
<m.A> -> m, m.A, m.B
1446+
<m.A[wildcard]> -> m
1447+
<m.B.y> -> m
1448+
<m.B> -> m.B
1449+
<m.Z> -> m
1450+
<dataclasses.dataclass> -> m
1451+
<dataclasses> -> m
1452+
1453+
[case testDataclassDeps]
1454+
# flags: --python-version 3.10
1455+
from dataclasses import dataclass
1456+
1457+
Z = int
1458+
1459+
@dataclass
1460+
class A:
1461+
x: Z
1462+
1463+
@dataclass
1464+
class B(A):
1465+
y: int
1466+
[builtins fixtures/dataclasses.pyi]
1467+
14381468
[out]
14391469
<m.A.(abstract)> -> <m.B.__init__>, m
14401470
<m.A.__dataclass_fields__> -> <m.B.__dataclass_fields__>

‎test-data/unit/merge.test

Copy file name to clipboardExpand all lines: test-data/unit/merge.test
+60-1Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ TypeInfo<2>(
646646
f<3>))
647647

648648
[case testNamedTuple_typeinfo]
649-
649+
# flags: --python-version 3.10
650650
import target
651651
[file target.py]
652652
from typing import NamedTuple
@@ -707,6 +707,65 @@ TypeInfo<2>(
707707
x<19> (target.A<0>)
708708
y<20> (target.A<0>)))
709709

710+
[case testNamedTupleOldVersion_typeinfo]
711+
import target
712+
[file target.py]
713+
from typing import NamedTuple
714+
class A: pass
715+
N = NamedTuple('N', [('x', A)])
716+
[file target.py.next]
717+
from typing import NamedTuple
718+
class A: pass
719+
N = NamedTuple('N', [('x', A), ('y', A)])
720+
[builtins fixtures/tuple.pyi]
721+
[out]
722+
TypeInfo<0>(
723+
Name(target.A)
724+
Bases(builtins.object<1>)
725+
Mro(target.A<0>, builtins.object<1>)
726+
Names())
727+
TypeInfo<2>(
728+
Name(target.N)
729+
Bases(builtins.tuple[target.A<0>, ...]<3>)
730+
Mro(target.N<2>, builtins.tuple<3>, typing.Sequence<4>, typing.Iterable<5>, builtins.object<1>)
731+
Names(
732+
_NT<6>
733+
__annotations__<7> (builtins.object<1>)
734+
__doc__<8> (builtins.str<9>)
735+
__new__<10>
736+
_asdict<11>
737+
_field_defaults<12> (builtins.object<1>)
738+
_field_types<13> (builtins.object<1>)
739+
_fields<14> (Tuple[builtins.str<9>])
740+
_make<15>
741+
_replace<16>
742+
_source<17> (builtins.str<9>)
743+
x<18> (target.A<0>)))
744+
==>
745+
TypeInfo<0>(
746+
Name(target.A)
747+
Bases(builtins.object<1>)
748+
Mro(target.A<0>, builtins.object<1>)
749+
Names())
750+
TypeInfo<2>(
751+
Name(target.N)
752+
Bases(builtins.tuple[target.A<0>, ...]<3>)
753+
Mro(target.N<2>, builtins.tuple<3>, typing.Sequence<4>, typing.Iterable<5>, builtins.object<1>)
754+
Names(
755+
_NT<6>
756+
__annotations__<7> (builtins.object<1>)
757+
__doc__<8> (builtins.str<9>)
758+
__new__<10>
759+
_asdict<11>
760+
_field_defaults<12> (builtins.object<1>)
761+
_field_types<13> (builtins.object<1>)
762+
_fields<14> (Tuple[builtins.str<9>, builtins.str<9>])
763+
_make<15>
764+
_replace<16>
765+
_source<17> (builtins.str<9>)
766+
x<18> (target.A<0>)
767+
y<19> (target.A<0>)))
768+
710769
[case testUnionType_types]
711770
import target
712771
[file target.py]

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.