Skip to content

Commit 16d5aaf

Browse files
authored
[PEP 695] Add daemon tests that use new type parameter syntax (#17327)
Add some basic mypy daemon test coverage, and make it possible to write daemon tests that only work on recent Python versions. Everything tested seems to work already. Work on #15238.
1 parent c762191 commit 16d5aaf

File tree

7 files changed

+210
-3
lines changed

7 files changed

+210
-3
lines changed

mypy/test/testdeps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
from __future__ import annotations
44

55
import os
6+
import sys
67
from collections import defaultdict
78

9+
import pytest
10+
811
from mypy import build
912
from mypy.errors import CompileError
1013
from mypy.modulefinder import BuildSource
@@ -28,6 +31,8 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
2831
src = "\n".join(testcase.input)
2932
dump_all = "# __dump_all__" in src
3033
options = parse_options(src, testcase, incremental_step=1)
34+
if options.python_version > sys.version_info:
35+
pytest.skip("Test case requires a newer Python version")
3136
options.use_builtins_fixtures = True
3237
options.show_traceback = True
3338
options.cache_dir = os.devnull

mypy/test/testdiff.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
from __future__ import annotations
44

55
import os
6+
import sys
7+
8+
import pytest
69

710
from mypy import build
8-
from mypy.defaults import PYTHON3_VERSION
911
from mypy.errors import CompileError
1012
from mypy.modulefinder import BuildSource
1113
from mypy.nodes import MypyFile
@@ -24,6 +26,8 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
2426
files_dict = dict(testcase.files)
2527
second_src = files_dict["tmp/next.py"]
2628
options = parse_options(first_src, testcase, 1)
29+
if options.python_version > sys.version_info:
30+
pytest.skip("Test case requires a newer Python version")
2731

2832
messages1, files1 = self.build(first_src, options)
2933
messages2, files2 = self.build(second_src, options)
@@ -53,7 +57,6 @@ def build(self, source: str, options: Options) -> tuple[list[str], dict[str, Myp
5357
options.use_builtins_fixtures = True
5458
options.show_traceback = True
5559
options.cache_dir = os.devnull
56-
options.python_version = PYTHON3_VERSION
5760
options.allow_empty_bodies = True
5861
try:
5962
result = build.build(

mypy/test/testfinegrained.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import os
1818
import re
19+
import sys
1920
import unittest
2021
from typing import Any
2122

@@ -82,6 +83,9 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
8283
f.write(main_src)
8384

8485
options = self.get_options(main_src, testcase, build_cache=False)
86+
if options.python_version > sys.version_info:
87+
pytest.skip("Test case requires a newer Python version")
88+
8589
build_options = self.get_options(main_src, testcase, build_cache=True)
8690
server = Server(options, DEFAULT_STATUS_FILE)
8791

mypy/traverser.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ def visit_match_stmt(self, o: MatchStmt) -> None:
246246

247247
def visit_type_alias_stmt(self, o: TypeAliasStmt) -> None:
248248
o.name.accept(self)
249-
# TODO: params
250249
o.value.accept(self)
251250

252251
def visit_member_expr(self, o: MemberExpr) -> None:

test-data/unit/deps.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,3 +1431,19 @@ class B(A):
14311431
<m.Z> -> m
14321432
<dataclasses.dataclass> -> m
14331433
<dataclasses> -> m
1434+
1435+
[case testPEP695TypeAliasDeps]
1436+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1437+
from a import C, E
1438+
type A = C
1439+
type A2 = A
1440+
type A3 = E
1441+
[file a.py]
1442+
class C: pass
1443+
class D: pass
1444+
type E = D
1445+
[out]
1446+
<m.A> -> m
1447+
<a.C> -> m
1448+
<a.E> -> m
1449+
<a> -> m

test-data/unit/diff.test

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,3 +1530,102 @@ class C:
15301530
[out]
15311531
__main__.C.get_by_team_and_id
15321532
__main__.Optional
1533+
1534+
[case testPEP695TypeAlias]
1535+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1536+
from typing_extensions import TypeAlias, TypeAliasType
1537+
type A = int
1538+
type B = str
1539+
type C = int
1540+
D = int
1541+
E: TypeAlias = int
1542+
F = TypeAliasType("F", int)
1543+
G = TypeAliasType("G", int)
1544+
type H = int
1545+
1546+
[file next.py]
1547+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1548+
from typing_extensions import TypeAlias, TypeAliasType
1549+
type A = str
1550+
type B = str
1551+
type C[T] = int
1552+
type D = int
1553+
type E = int
1554+
type F = int
1555+
type G = str
1556+
type H[T] = int
1557+
1558+
[builtins fixtures/tuple.pyi]
1559+
[typing fixtures/typing-full.pyi]
1560+
[out]
1561+
__main__.A
1562+
__main__.C
1563+
__main__.D
1564+
__main__.E
1565+
__main__.G
1566+
__main__.H
1567+
1568+
[case testPEP695TypeAlias2]
1569+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1570+
type A[T: int] = list[T]
1571+
type B[T: int] = list[T]
1572+
type C[T: (int, str)] = list[T]
1573+
type D[T: (int, str)] = list[T]
1574+
type E[T: int] = list[T]
1575+
type F[T: (int, str)] = list[T]
1576+
1577+
[file next.py]
1578+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1579+
type A[T] = list[T]
1580+
type B[T: str] = list[T]
1581+
type C[T: (int, None)] = list[T]
1582+
type D[T] = list[T]
1583+
type E[T: int] = list[T]
1584+
type F[T: (int, str)] = list[T]
1585+
1586+
[out]
1587+
__main__.A
1588+
__main__.B
1589+
__main__.C
1590+
__main__.D
1591+
1592+
[case testPEP695GenericFunction]
1593+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1594+
def f[T](x: T) -> T:
1595+
return x
1596+
def g[T](x: T, y: T) -> T:
1597+
return x
1598+
[file next.py]
1599+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1600+
def f[T](x: T) -> T:
1601+
return x
1602+
def g[T, S](x: T, y: S) -> S:
1603+
return y
1604+
[out]
1605+
__main__.g
1606+
1607+
[case testPEP695GenericClass]
1608+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1609+
class C[T]:
1610+
pass
1611+
class D[T]:
1612+
pass
1613+
class E[T]:
1614+
pass
1615+
class F[T]:
1616+
def f(self, x: object) -> T: ...
1617+
[file next.py]
1618+
# flags: --enable-incomplete-feature=NewGenericSyntax --python-version=3.12
1619+
class C[T]:
1620+
pass
1621+
class D[T: int]:
1622+
pass
1623+
class E:
1624+
pass
1625+
class F[T]:
1626+
def f(self, x: T) -> T: ...
1627+
[out]
1628+
__main__.D
1629+
__main__.E
1630+
__main__.F
1631+
__main__.F.f
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
[case testPEP695TypeAliasDep]
2+
# flags: --enable-incomplete-feature=NewGenericSyntax
3+
import m
4+
def g() -> m.C:
5+
return m.f()
6+
[file m.py]
7+
type C = int
8+
9+
def f() -> int:
10+
pass
11+
[file m.py.2]
12+
type C = str
13+
14+
def f() -> int:
15+
pass
16+
[out]
17+
==
18+
main:4: error: Incompatible return value type (got "int", expected "str")
19+
20+
[case testPEP695ChangeOldStyleToNewStyleTypeAlias]
21+
# flags: --enable-incomplete-feature=NewGenericSyntax
22+
from m import A
23+
A()
24+
25+
[file m.py]
26+
A = int
27+
28+
[file m.py.2]
29+
type A = int
30+
[typing fixtures/typing-full.pyi]
31+
[builtins fixtures/tuple.pyi]
32+
[out]
33+
==
34+
main:3: error: "TypeAliasType" not callable
35+
36+
[case testPEP695VarianceChangesDueToDependency]
37+
# flags: --enable-incomplete-feature=NewGenericSyntax
38+
from a import C
39+
40+
x: C[object] = C[int]()
41+
42+
[file a.py]
43+
from b import A
44+
45+
class C[T]:
46+
def f(self) -> A[T]: ...
47+
48+
[file b.py]
49+
class A[T]:
50+
def f(self) -> T: ...
51+
52+
[file b.py.2]
53+
class A[T]:
54+
def f(self) -> list[T]: ...
55+
56+
[out]
57+
==
58+
main:4: error: Incompatible types in assignment (expression has type "C[int]", variable has type "C[object]")
59+
60+
[case testPEP695TypeAliasChangesDueToDependency]
61+
# flags: --enable-incomplete-feature=NewGenericSyntax
62+
from a import A
63+
x: A
64+
x = 0
65+
x = ''
66+
67+
[file a.py]
68+
from b import B
69+
type A = B[int, str]
70+
71+
[file b.py]
72+
from typing import Union as B
73+
74+
[file b.py.2]
75+
from builtins import tuple as B
76+
77+
[builtins fixtures/tuple.pyi]
78+
[out]
79+
==
80+
main:4: error: Incompatible types in assignment (expression has type "int", variable has type "tuple[int, str]")
81+
main:5: error: Incompatible types in assignment (expression has type "str", variable has type "tuple[int, str]")

0 commit comments

Comments
 (0)