Skip to content

Commit 3eed98a

Browse files
committed
Do not generate __match_args__ for dataclasses and named tuples when running with --python-version < 3.10
1 parent b44d2bc commit 3eed98a

File tree

7 files changed

+163
-6
lines changed

7 files changed

+163
-6
lines changed

mypy/plugins/dataclasses.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ def transform(self) -> None:
223223
if (decorator_arguments['match_args'] and
224224
('__match_args__' not in info.names or
225225
info.names['__match_args__'].plugin_generated) and
226-
attributes):
226+
attributes and
227+
py_version >= (3, 10)):
227228
str_type = ctx.api.named_type("builtins.str")
228229
literals: List[Type] = [LiteralType(attr.name, str_type)
229230
for attr in attributes if attr.is_in_init]

mypy/semanal_namedtuple.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,8 @@ def add_field(var: Var, is_initialized_in_class: bool = False,
439439
add_field(Var('_source', strtype), is_initialized_in_class=True)
440440
add_field(Var('__annotations__', ordereddictype), is_initialized_in_class=True)
441441
add_field(Var('__doc__', strtype), is_initialized_in_class=True)
442-
add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True)
442+
if self.options.python_version >= (3, 10):
443+
add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True)
443444

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

mypy/test/testmerge.py

Lines 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,
@@ -108,7 +107,6 @@ def build(self, source: str, testcase: DataDrivenTestCase) -> Optional[BuildResu
108107
options.use_builtins_fixtures = True
109108
options.export_types = True
110109
options.show_traceback = True
111-
options.python_version = PYTHON3_VERSION
112110
main_path = os.path.join(test_temp_dir, 'main')
113111
with open(main_path, 'w', encoding='utf8') as f:
114112
f.write(source)

test-data/unit/check-dataclasses.test

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,3 +1568,48 @@ class B:
15681568
class Derived(A, B):
15691569
pass
15701570
[builtins fixtures/dataclasses.pyi]
1571+
1572+
[case testDataclassWithMatchArgs]
1573+
# flags: --python-version 3.10
1574+
from dataclasses import dataclass
1575+
@dataclass
1576+
class One:
1577+
bar: int
1578+
baz: str
1579+
o: One
1580+
reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]"
1581+
@dataclass(match_args=True)
1582+
class Two:
1583+
bar: int
1584+
t: Two
1585+
reveal_type(t.__match_args__) # N: Revealed type is "Tuple[Literal['bar']]"
1586+
[builtins fixtures/dataclasses.pyi]
1587+
1588+
[case testDataclassWithoutMatchArgs]
1589+
# flags: --python-version 3.10
1590+
from dataclasses import dataclass
1591+
@dataclass(match_args=False)
1592+
class One:
1593+
bar: int
1594+
baz: str
1595+
o: One
1596+
reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \
1597+
# N: Revealed type is "Any"
1598+
[builtins fixtures/dataclasses.pyi]
1599+
1600+
[case testDataclassWithMatchArgsOldVersion]
1601+
# flags: --python-version 3.9
1602+
from dataclasses import dataclass
1603+
@dataclass(match_args=True)
1604+
class One:
1605+
bar: int
1606+
o: One
1607+
reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \
1608+
# N: Revealed type is "Any"
1609+
@dataclass
1610+
class Two:
1611+
bar: int
1612+
t: Two
1613+
reveal_type(t.__match_args__) # E: "Two" has no attribute "__match_args__" \
1614+
# N: Revealed type is "Any"
1615+
[builtins fixtures/dataclasses.pyi]

test-data/unit/check-namedtuple.test

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,3 +1120,26 @@ def bar1(c: C1) -> None:
11201120
reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C1]"
11211121
[builtins fixtures/tuple.pyi]
11221122
[typing fixtures/typing-namedtuple.pyi]
1123+
1124+
[case testNamedTupleHasMatchArgs]
1125+
# flags: --python-version 3.10
1126+
from typing import NamedTuple
1127+
class One(NamedTuple):
1128+
bar: int
1129+
baz: str
1130+
o: One
1131+
reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]"
1132+
[builtins fixtures/tuple.pyi]
1133+
[typing fixtures/typing-namedtuple.pyi]
1134+
1135+
[case testNamedTupleHasNoMatchArgsOldVersion]
1136+
# flags: --python-version 3.9
1137+
from typing import NamedTuple
1138+
class One(NamedTuple):
1139+
bar: int
1140+
baz: str
1141+
o: One
1142+
reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \
1143+
# N: Revealed type is "Any"
1144+
[builtins fixtures/tuple.pyi]
1145+
[typing fixtures/typing-namedtuple.pyi]

test-data/unit/deps.test

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ class D(C):
14171417
<m.C> -> m, m.C, m.D
14181418
<m.D> -> m.D
14191419

1420-
[case testDataclassDeps]
1420+
[case testDataclassDepsOldVersion]
14211421
# flags: --python-version 3.7
14221422
from dataclasses import dataclass
14231423

@@ -1432,6 +1432,36 @@ class B(A):
14321432
y: int
14331433
[builtins fixtures/dataclasses.pyi]
14341434

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

test-data/unit/merge.test

Lines 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)