Skip to content

Commit 07edc92

Browse files
Put filelock around PEP 561 tests (fixes #12615) (#12857)
Fixes #12615. As discussed in the linked issue, this PR would put a filesystem-based lock around the pip install steps of the suite of PEP561 testcases, to address race conditions. It introduces a test-dependency on tox-dev/py-filelock. I used 3.0.0 as a lower bound, simply because that's what the tox version mentioned in tox.ini specifies as its lower bound. However from the release history it seems that Python 3.6 support was dropped in 3.4.2, hence the second line in the requirements. I ended up just adding the location of the lock file to .gitignore -- I guess it would be possible to try and remove it after the suite has run, e.g. with atexit.register, but I didn't want to make this complicated.
1 parent d3ef642 commit 07edc92

File tree

5 files changed

+28
-7
lines changed

5 files changed

+28
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ venv/
1414
.mypy_cache/
1515
.incremental_checker_cache.json
1616
.cache
17+
test-data/packages/.pip_lock
1718
dmypy.json
1819
.dmypy.json
1920

mypy/test/config.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,12 @@
1515
# This is *within* the tempfile.TemporaryDirectory that is chroot'ed per testcase.
1616
# It is also hard-coded in numerous places, so don't change it.
1717
test_temp_dir = 'tmp'
18+
19+
# The PEP 561 tests do a bunch of pip installs which, even though they operate
20+
# on distinct temporary virtual environments, run into race conditions on shared
21+
# file-system state. To make this work reliably in parallel mode, we'll use a
22+
# FileLock courtesy of the tox-dev/py-filelock package.
23+
# Ref. https://github.com/python/mypy/issues/12615
24+
# Ref. mypy/test/testpep561.py
25+
pip_lock = os.path.join(package_path, '.pip_lock')
26+
pip_timeout = 60

mypy/test/testpep561.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from contextlib import contextmanager
2+
import filelock
23
import os
34
import pytest
45
import re
@@ -9,7 +10,7 @@
910
from typing import Tuple, List, Generator
1011

1112
import mypy.api
12-
from mypy.test.config import package_path
13+
from mypy.test.config import package_path, pip_lock, pip_timeout
1314
from mypy.util import try_find_python2_interpreter
1415
from mypy.test.data import DataDrivenTestCase, DataSuite
1516
from mypy.test.config import test_temp_dir
@@ -77,11 +78,15 @@ def install_package(pkg: str,
7778
env = {'PIP_BUILD': dir}
7879
# Inherit environment for Windows
7980
env.update(os.environ)
80-
proc = subprocess.run(install_cmd,
81-
cwd=working_dir,
82-
stdout=PIPE,
83-
stderr=PIPE,
84-
env=env)
81+
try:
82+
with filelock.FileLock(pip_lock, timeout=pip_timeout):
83+
proc = subprocess.run(install_cmd,
84+
cwd=working_dir,
85+
stdout=PIPE,
86+
stderr=PIPE,
87+
env=env)
88+
except filelock.Timeout as err:
89+
raise Exception("Failed to acquire {}".format(pip_lock)) from err
8590
if proc.returncode != 0:
8691
raise Exception(proc.stdout.decode('utf-8') + proc.stderr.decode('utf-8'))
8792

runtests.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,15 @@
5858
'pytest-slow': ['pytest', '-q', '-k', ' or '.join(
5959
[SAMPLES,
6060
TYPESHED,
61-
PEP561,
6261
DAEMON,
6362
MYPYC_EXTERNAL,
6463
MYPYC_COMMAND_LINE,
6564
ERROR_STREAM])],
65+
66+
# Test cases that might take minutes to run
67+
'pytest-slower': ['pytest', '-q', '-k', ' or '.join(
68+
[PEP561])],
69+
6670
# Test cases to run in typeshed CI
6771
'typeshed-ci': ['pytest', '-q', '-k', ' or '.join([CMDLINE,
6872
EVALUATION,

test-requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
-r mypy-requirements.txt
22
-r build-requirements.txt
33
attrs>=18.0
4+
filelock>=3.0.0,<3.4.2; python_version<'3.7'
5+
filelock>=3.0.0; python_version>='3.7'
46
flake8==3.9.2
57
flake8-bugbear==22.3.20
68
flake8-pyi>=20.5

0 commit comments

Comments
 (0)