Skip to content

Commit bf700d9

Browse files
authored
Merge pull request #172 from dmtucker/tests-stash
Use config.stash to store the results path
2 parents 02795e2 + 90e1f32 commit bf700d9

File tree

3 files changed

+32
-75
lines changed

3 files changed

+32
-75
lines changed

src/pytest_mypy.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
mypy_argv = []
1616
nodeid_name = "mypy"
17+
stash_keys = {
18+
"mypy_results_path": pytest.StashKey[Path](),
19+
}
1720
terminal_summary_title = "mypy"
1821

1922

@@ -80,18 +83,18 @@ def pytest_configure(config):
8083
# Subsequent MypyItems will see the file exists,
8184
# and they will read the parsed results.
8285
with NamedTemporaryFile(delete=True) as tmp_f:
83-
config._mypy_results_path = tmp_f.name
86+
config.stash[stash_keys["mypy_results_path"]] = Path(tmp_f.name)
8487

8588
# If xdist is enabled, then the results path should be exposed to
8689
# the workers so that they know where to read parsed results from.
8790
if config.pluginmanager.getplugin("xdist"):
8891

8992
class _MypyXdistPlugin:
9093
def pytest_configure_node(self, node): # xdist hook
91-
"""Pass config._mypy_results_path to workers."""
92-
_get_xdist_workerinput(node)[
93-
"_mypy_results_path"
94-
] = node.config._mypy_results_path
94+
"""Pass the mypy results path to workers."""
95+
_get_xdist_workerinput(node)["_mypy_results_path"] = str(
96+
node.config.stash[stash_keys["mypy_results_path"]]
97+
)
9598

9699
config.pluginmanager.register(_MypyXdistPlugin())
97100

@@ -259,14 +262,14 @@ def from_mypy(
259262
@classmethod
260263
def from_session(cls, session) -> "MypyResults":
261264
"""Load (or generate) cached mypy results for a pytest session."""
262-
results_path = (
263-
session.config._mypy_results_path
265+
mypy_results_path = Path(
266+
session.config.stash[stash_keys["mypy_results_path"]]
264267
if _is_xdist_controller(session.config)
265268
else _get_xdist_workerinput(session.config)["_mypy_results_path"]
266269
)
267-
with FileLock(results_path + ".lock"):
270+
with FileLock(str(mypy_results_path) + ".lock"):
268271
try:
269-
with open(results_path, mode="r") as results_f:
272+
with open(mypy_results_path, mode="r") as results_f:
270273
results = cls.load(results_f)
271274
except FileNotFoundError:
272275
results = cls.from_mypy(
@@ -276,7 +279,7 @@ def from_session(cls, session) -> "MypyResults":
276279
if isinstance(item, MypyFileItem)
277280
],
278281
)
279-
with open(results_path, mode="w") as results_f:
282+
with open(mypy_results_path, mode="w") as results_f:
280283
results.dump(results_f)
281284
return results
282285

@@ -295,10 +298,10 @@ class MypyWarning(pytest.PytestWarning):
295298
def pytest_terminal_summary(terminalreporter, config):
296299
"""Report stderr and unrecognized lines from stdout."""
297300
if not _is_xdist_controller(config):
298-
# This isn't hit in pytest 5.0 for some reason.
299-
return # pragma: no cover
301+
return
302+
mypy_results_path = config.stash[stash_keys["mypy_results_path"]]
300303
try:
301-
with open(config._mypy_results_path, mode="r") as results_f:
304+
with open(mypy_results_path, mode="r") as results_f:
302305
results = MypyResults.load(results_f)
303306
except FileNotFoundError:
304307
# No MypyItems executed.
@@ -310,4 +313,4 @@ def pytest_terminal_summary(terminalreporter, config):
310313
terminalreporter.write_line(results.unmatched_stdout, **color)
311314
if results.stderr:
312315
terminalreporter.write_line(results.stderr, yellow=True)
313-
Path(config._mypy_results_path).unlink()
316+
mypy_results_path.unlink()

tests/test_pytest_mypy.py

Lines changed: 15 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44

55
import mypy.version
66
from packaging.version import Version
7-
import pexpect
87
import pytest
98

109
import pytest_mypy
1110

1211

1312
MYPY_VERSION = Version(mypy.version.__version__)
14-
PYTEST_VERSION = Version(pytest.__version__)
1513
PYTHON_VERSION = Version(
1614
".".join(
1715
str(token)
@@ -325,14 +323,7 @@ def pytest_configure(config):
325323
@pytest.mark.parametrize(
326324
"module_name",
327325
[
328-
pytest.param(
329-
"__init__",
330-
marks=pytest.mark.xfail(
331-
Version("3.10") <= PYTEST_VERSION < Version("6.2"),
332-
raises=AssertionError,
333-
reason="https://github.com/pytest-dev/pytest/issues/8016",
334-
),
335-
),
326+
"__init__",
336327
"good",
337328
],
338329
)
@@ -464,14 +455,6 @@ def pyfunc(x: int) -> str:
464455
expect_timeout=60.0,
465456
)
466457

467-
num_tests = 2
468-
if module_name == "__init__" and Version("3.10") <= PYTEST_VERSION < Version("6.2"):
469-
# https://github.com/pytest-dev/pytest/issues/8016
470-
# Pytest had a bug where it assumed only a Package would have a basename of
471-
# __init__.py. In this test, Pytest mistakes MypyFile for a Package and
472-
# returns after collecting only one object (the MypyFileItem).
473-
num_tests = 1
474-
475458
def _expect_session():
476459
child.expect("==== test session starts ====")
477460

@@ -480,11 +463,9 @@ def _expect_failure():
480463
child.expect("==== FAILURES ====")
481464
child.expect(pyfile.basename + " ____")
482465
child.expect("2: error: Incompatible return value")
483-
# if num_tests == 2:
484-
# # These only show with mypy>=0.730:
485-
# child.expect("==== mypy ====")
486-
# child.expect("Found 1 error in 1 file (checked 1 source file)")
487-
child.expect(str(num_tests) + " failed")
466+
child.expect("==== mypy ====")
467+
child.expect("Found 1 error in 1 file (checked 1 source file)")
468+
child.expect("2 failed")
488469
child.expect("#### LOOPONFAILING ####")
489470
_expect_waiting()
490471

@@ -503,29 +484,9 @@ def _expect_changed():
503484
def _expect_success():
504485
for _ in range(2):
505486
_expect_session()
506-
# if num_tests == 2:
507-
# # These only show with mypy>=0.730:
508-
# child.expect("==== mypy ====")
509-
# child.expect("Success: no issues found in 1 source file")
510-
try:
511-
child.expect(str(num_tests) + " passed")
512-
except pexpect.exceptions.TIMEOUT:
513-
if module_name == "__init__" and (
514-
Version("6.0") <= PYTEST_VERSION < Version("6.2")
515-
):
516-
# MypyItems hit the __init__.py bug too when --looponfail
517-
# re-collects them after the failing file is modified.
518-
# Unlike MypyFile, MypyItem is not a Collector, so this used
519-
# to cause an AttributeError until a workaround was added
520-
# (MypyItem.collect was defined to yield itself).
521-
# Mypy probably noticed the __init__.py problem during the
522-
# development of Pytest 6.0, but the error was addressed
523-
# with an isinstance assertion, which broke the workaround.
524-
# Here, we hit that assertion:
525-
child.expect("AssertionError")
526-
child.expect("1 error")
527-
pytest.xfail("https://github.com/pytest-dev/pytest/issues/8016")
528-
raise
487+
child.expect("==== mypy ====")
488+
child.expect("Success: no issues found in 1 source file")
489+
child.expect("2 passed")
529490
_expect_waiting()
530491

531492
def _break():
@@ -550,35 +511,29 @@ def test_mypy_results_from_mypy_with_opts():
550511

551512
def test_mypy_no_output(testdir, xdist_args):
552513
"""No terminal summary is shown if there is no output from mypy."""
553-
type_ignore = (
554-
"# type: ignore"
555-
if (
556-
PYTEST_VERSION
557-
< Version("6.0") # Pytest didn't add type annotations until 6.0.
558-
)
559-
else ""
560-
)
561514
testdir.makepyfile(
562515
# Mypy prints a success message to stderr by default:
563516
# "Success: no issues found in 1 source file"
564517
# Clear stderr and unmatched_stdout to simulate mypy having no output:
565-
conftest=f"""
566-
import pytest {type_ignore}
518+
conftest="""
519+
import pytest
567520
568521
@pytest.hookimpl(hookwrapper=True)
569522
def pytest_terminal_summary(config):
570-
mypy_results_path = getattr(config, "_mypy_results_path", None)
571-
if not mypy_results_path:
523+
pytest_mypy = config.pluginmanager.getplugin("mypy")
524+
stash_key = pytest_mypy.stash_keys["mypy_results_path"]
525+
try:
526+
mypy_results_path = config.stash[stash_key]
527+
except KeyError:
572528
# xdist worker
573529
return
574-
pytest_mypy = config.pluginmanager.getplugin("mypy")
575530
with open(mypy_results_path, mode="w") as results_f:
576531
pytest_mypy.MypyResults(
577532
opts=[],
578533
stdout="",
579534
stderr="",
580535
status=0,
581-
abspath_errors={{}},
536+
abspath_errors={},
582537
unmatched_stdout="",
583538
).dump(results_f)
584539
yield

tox.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ deps =
3232
mypy1.x: mypy ~= 1.0
3333

3434
packaging ~= 21.3
35-
pexpect ~= 4.8.0
3635
pytest-cov ~= 4.1.0
3736
pytest-randomly ~= 3.4
3837
pytest-xdist ~= 1.34

0 commit comments

Comments
 (0)