Skip to content

Commit 5788635

Browse files
authored
Add test cases for AST serialization (#3276)
The test cases use a serialized module in incremental mode in various ways to make sure that all important information in the AST nodes is preserved during serialization and deserialization. These are all very straightforward. The idea is to help catch regressions early and to make it easier to refactor or optimize serialization code. These found 2 issues -- separated the first to PR #3275. The second issue (#3274) is still unfixed and there is a skipped test case for it. More complex cases such as import cycles can still go to check-incremental.test.
1 parent e34f6cc commit 5788635

File tree

3 files changed

+1236
-62
lines changed

3 files changed

+1236
-62
lines changed

mypy/test/testcheck.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
'check-semanal-error.test',
5656
'check-flags.test',
5757
'check-incremental.test',
58+
'check-serialize.test',
5859
'check-bound.test',
5960
'check-optional.test',
6061
'check-fastparse.test',
@@ -90,27 +91,26 @@ def cases(cls) -> List[DataDrivenTestCase]:
9091
return c
9192

9293
def run_case(self, testcase: DataDrivenTestCase) -> None:
93-
incremental = 'incremental' in testcase.name.lower() or 'incremental' in testcase.file
94+
incremental = ('incremental' in testcase.name.lower()
95+
or 'incremental' in testcase.file
96+
or 'serialize' in testcase.file)
9497
optional = 'optional' in testcase.file
95-
if incremental:
96-
# Incremental tests are run once with a cold cache, once with a warm cache.
97-
# Expect success on first run, errors from testcase.output (if any) on second run.
98-
# We briefly sleep to make sure file timestamps are distinct.
99-
self.clear_cache()
100-
self.run_case_once(testcase, 1)
101-
self.run_case_once(testcase, 2)
102-
elif optional:
103-
try:
98+
old_strict_optional = experiments.STRICT_OPTIONAL
99+
try:
100+
if incremental:
101+
# Incremental tests are run once with a cold cache, once with a warm cache.
102+
# Expect success on first run, errors from testcase.output (if any) on second run.
103+
# We briefly sleep to make sure file timestamps are distinct.
104+
self.clear_cache()
105+
self.run_case_once(testcase, 1)
106+
self.run_case_once(testcase, 2)
107+
elif optional:
104108
experiments.STRICT_OPTIONAL = True
105109
self.run_case_once(testcase)
106-
finally:
107-
experiments.STRICT_OPTIONAL = False
108-
else:
109-
try:
110-
old_strict_optional = experiments.STRICT_OPTIONAL
110+
else:
111111
self.run_case_once(testcase)
112-
finally:
113-
experiments.STRICT_OPTIONAL = old_strict_optional
112+
finally:
113+
experiments.STRICT_OPTIONAL = old_strict_optional
114114

115115
def clear_cache(self) -> None:
116116
dn = defaults.CACHE_DIR

test-data/unit/check-incremental.test

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
-- all cases so we can avoid constantly having to annotate it. The list of
2727
-- rechecked/stale files can be in any arbitrary order, or can be left empty
2828
-- if no files should be rechecked/stale.
29+
--
30+
-- There are additional incremental mode test cases in check-serialize.test.
2931

3032
[case testIncrementalEmpty]
3133
[rechecked]
@@ -1711,28 +1713,6 @@ main:1: error: Module 'ntcrash' has no attribute 'nope'
17111713
[out2]
17121714
main:1: error: Module 'ntcrash' has no attribute 'nope'
17131715

1714-
[case testIncrementalNamedTupleInMethod4]
1715-
from ntcrash import C
1716-
reveal_type(C().a)
1717-
reveal_type(C().b)
1718-
reveal_type(C().c)
1719-
[file ntcrash.py]
1720-
from typing import NamedTuple
1721-
class C:
1722-
def __init__(self) -> None:
1723-
A = NamedTuple('A', [('x', int)])
1724-
self.a = A(0)
1725-
self.b = A(0) # type: A
1726-
self.c = A
1727-
[out1]
1728-
main:2: error: Revealed type is 'Tuple[builtins.int, fallback=ntcrash.C.A@4]'
1729-
main:3: error: Revealed type is 'Tuple[builtins.int, fallback=ntcrash.C.A@4]'
1730-
main:4: error: Revealed type is 'def (x: builtins.int) -> Tuple[builtins.int, fallback=ntcrash.C.A@4]'
1731-
[out2]
1732-
main:2: error: Revealed type is 'Tuple[builtins.int, fallback=ntcrash.C.A@4]'
1733-
main:3: error: Revealed type is 'Tuple[builtins.int, fallback=ntcrash.C.A@4]'
1734-
main:4: error: Revealed type is 'def (x: builtins.int) -> Tuple[builtins.int, fallback=ntcrash.C.A@4]'
1735-
17361716
[case testIncrementalTypedDictInMethod]
17371717
from tdcrash import nope
17381718
[file tdcrash.py]
@@ -1775,29 +1755,6 @@ main:1: error: Module 'tdcrash' has no attribute 'nope'
17751755
[out2]
17761756
main:1: error: Module 'tdcrash' has no attribute 'nope'
17771757

1778-
[case testIncrementalTypedDictInMethod4]
1779-
from ntcrash import C
1780-
reveal_type(C().a)
1781-
reveal_type(C().b)
1782-
reveal_type(C().c)
1783-
[file ntcrash.py]
1784-
from mypy_extensions import TypedDict
1785-
class C:
1786-
def __init__(self) -> None:
1787-
A = TypedDict('A', {'x': int})
1788-
self.a = A(x=0)
1789-
self.b = A(x=0) # type: A
1790-
self.c = A
1791-
[builtins fixtures/dict.pyi]
1792-
[out1]
1793-
main:2: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])'
1794-
main:3: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=ntcrash.C.A@4)'
1795-
main:4: error: Revealed type is 'def () -> ntcrash.C.A@4'
1796-
[out2]
1797-
main:2: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])'
1798-
main:3: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=ntcrash.C.A@4)'
1799-
main:4: error: Revealed type is 'def () -> ntcrash.C.A@4'
1800-
18011758
[case testIncrementalInnerClassAttrInMethod]
18021759
import crash
18031760
nonexisting

0 commit comments

Comments
 (0)