Skip to content

Commit a562f0a

Browse files
stubtest: Fix wrong assumption about relative path (#12282)
Fixes #11019 `run_stubtest` creates temp directory and prepend `sys.path` with relative path (dot `.`) wrongly assuming that the dot will be resolved to absolute path on *every* import attempt. But in Python dot(`.`) in sys.path is actually resolved by PathFinder and cached in `sys.path_importer_cache` like: ``` sys.path_importer_cache['.'] FileFinder('/somepath/.') ``` later calls for `find_module` return None and import of `test_module` fails. This resulted in only the first test in stubtest's suite passed in non-pytest-xdist environments. This issue was hidden with bug or feature in pytest-xdist < 2.3.0: pytest-dev/pytest-xdist#421 It was fixed in pytest-xdist 2.3.0: pytest-dev/pytest-xdist#667 - sys.path for pytest-xdist < 2.3.0 `'.', 'project_path', ''` - sys.path for pytest-xdist >= 2.3.0 or without xdist `'.', 'project_path'` In Python for denoting cwd the empty path `''` can be used as a special case, but for readability `sys.path` is prepended with resolved absolute path of temp directory. Also it's essential to restore back `sys.path` after a test to not break subsequent tests. Signed-off-by: Stanislav Levin <[email protected]>
1 parent 73a5b3c commit a562f0a

File tree

2 files changed

+11
-9
lines changed

2 files changed

+11
-9
lines changed

mypy/test/teststubtest.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,20 @@
1616

1717

1818
@contextlib.contextmanager
19-
def use_tmp_dir() -> Iterator[None]:
19+
def use_tmp_dir(mod_name: str) -> Iterator[None]:
2020
current = os.getcwd()
21+
current_syspath = sys.path[:]
2122
with tempfile.TemporaryDirectory() as tmp:
2223
try:
2324
os.chdir(tmp)
25+
if sys.path[0] != tmp:
26+
sys.path.insert(0, tmp)
2427
yield
2528
finally:
29+
sys.path = current_syspath[:]
30+
if mod_name in sys.modules:
31+
del sys.modules[mod_name]
32+
2633
os.chdir(current)
2734

2835

@@ -92,7 +99,7 @@ def staticmethod(f: T) -> T: ...
9299
def run_stubtest(
93100
stub: str, runtime: str, options: List[str], config_file: Optional[str] = None,
94101
) -> str:
95-
with use_tmp_dir():
102+
with use_tmp_dir(TEST_MODULE_NAME):
96103
with open("builtins.pyi", "w") as f:
97104
f.write(stubtest_builtins_stub)
98105
with open("typing.pyi", "w") as f:
@@ -105,11 +112,6 @@ def run_stubtest(
105112
with open("{}_config.ini".format(TEST_MODULE_NAME), "w") as f:
106113
f.write(config_file)
107114
options = options + ["--mypy-config-file", "{}_config.ini".format(TEST_MODULE_NAME)]
108-
if sys.path[0] != ".":
109-
sys.path.insert(0, ".")
110-
if TEST_MODULE_NAME in sys.modules:
111-
del sys.modules[TEST_MODULE_NAME]
112-
113115
output = io.StringIO()
114116
with contextlib.redirect_stdout(output):
115117
test_stubs(

test-requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ flake8-pyi>=20.5
77
lxml>=4.4.0; python_version<'3.11'
88
psutil>=4.0
99
# pytest 6.2.3 does not support Python 3.10
10-
pytest>=6.2.4,<7.0.0
11-
pytest-xdist>=1.34.0,<2.0.0
10+
pytest>=6.2.4
11+
pytest-xdist>=1.34.0
1212
pytest-forked>=1.3.0,<2.0.0
1313
pytest-cov>=2.10.0,<3.0.0
1414
py>=1.5.2

0 commit comments

Comments
 (0)