6
6
import pexpect
7
7
import pytest
8
8
9
+ import pytest_mypy
10
+
9
11
10
12
MYPY_VERSION = Version (mypy .version .__version__ )
11
13
PYTEST_VERSION = Version (pytest .__version__ )
@@ -98,7 +100,7 @@ def pyfunc(x: int) -> str:
98
100
assert result .ret != 0
99
101
100
102
101
- def test_mypy_annotation_unchecked (testdir , xdist_args ):
103
+ def test_mypy_annotation_unchecked (testdir , xdist_args , tmp_path , monkeypatch ):
102
104
"""Verify that annotation-unchecked warnings do not manifest as an error."""
103
105
testdir .makepyfile (
104
106
"""
@@ -107,16 +109,37 @@ def pyfunc(x):
107
109
return x * y
108
110
""" ,
109
111
)
112
+ min_mypy_version = Version ("0.990" )
113
+ if MYPY_VERSION < min_mypy_version :
114
+ # mypy doesn't emit annotation-unchecked warnings until 0.990:
115
+ fake_mypy_path = tmp_path / "mypy"
116
+ fake_mypy_path .mkdir ()
117
+ (fake_mypy_path / "__init__.py" ).touch ()
118
+ (fake_mypy_path / "api.py" ).write_text (
119
+ textwrap .dedent (
120
+ """
121
+ def run(*args, **kwargs):
122
+ return (
123
+ "test_mypy_annotation_unchecked.py:2:"
124
+ " note: By default the bodies of untyped functions"
125
+ " are not checked, consider using --check-untyped-defs"
126
+ " [annotation-unchecked]\\ nSuccess: no issues found in"
127
+ " 1 source file\\ n",
128
+ "",
129
+ 0,
130
+ )
131
+ """
132
+ )
133
+ )
134
+ monkeypatch .setenv ("PYTHONPATH" , str (tmp_path ))
110
135
result = testdir .runpytest_subprocess (* xdist_args )
111
136
result .assert_outcomes ()
112
137
result = testdir .runpytest_subprocess ("--mypy" , * xdist_args )
113
138
mypy_file_checks = 1
114
139
mypy_status_check = 1
115
140
mypy_checks = mypy_file_checks + mypy_status_check
116
141
outcomes = {"passed" : mypy_checks }
117
- # mypy doesn't emit annotation-unchecked warnings until 0.990:
118
- min_mypy_version = Version ("0.990" )
119
- if MYPY_VERSION >= min_mypy_version and PYTEST_VERSION >= Version ("7.0" ):
142
+ if PYTEST_VERSION >= Version ("7.0" ):
120
143
# assert_outcomes does not support `warnings` until 7.x.
121
144
outcomes ["warnings" ] = 1
122
145
result .assert_outcomes (** outcomes )
@@ -554,3 +577,59 @@ def test_mypy_item_collect(request):
554
577
mypy_status_check = 1
555
578
result .assert_outcomes (passed = test_count + mypy_file_checks + mypy_status_check )
556
579
assert result .ret == 0
580
+
581
+
582
+ @pytest .mark .xfail (
583
+ MYPY_VERSION < Version ("0.750" ),
584
+ raises = AssertionError ,
585
+ reason = "https://github.com/python/mypy/issues/7800" ,
586
+ )
587
+ def test_mypy_results_from_mypy_with_opts ():
588
+ """MypyResults.from_mypy respects passed options."""
589
+ mypy_results = pytest_mypy .MypyResults .from_mypy ([], opts = ["--version" ])
590
+ assert mypy_results .status == 0
591
+ assert mypy_results .abspath_errors == {}
592
+ assert str (MYPY_VERSION ) in mypy_results .stdout
593
+
594
+
595
+ def test_mypy_no_output (testdir , xdist_args ):
596
+ """No terminal summary is shown if there is no output from mypy."""
597
+ type_ignore = (
598
+ "# type: ignore"
599
+ if (
600
+ PYTEST_VERSION
601
+ < Version ("6.0" ) # Pytest didn't add type annotations until 6.0.
602
+ or MYPY_VERSION < Version ("0.710" )
603
+ )
604
+ else ""
605
+ )
606
+ testdir .makepyfile (
607
+ conftest = f"""
608
+ import tempfile
609
+
610
+ import pytest { type_ignore }
611
+
612
+ @pytest.hookimpl(hookwrapper=True)
613
+ def pytest_terminal_summary(config):
614
+ pytest_mypy = config.pluginmanager.getplugin("mypy")
615
+ with open(config._mypy_results_path, mode="r") as results_f:
616
+ results = pytest_mypy.MypyResults.load(results_f)
617
+ with open(config._mypy_results_path, mode="w") as results_f:
618
+ pytest_mypy.MypyResults(
619
+ opts=results.opts,
620
+ stdout=results.stdout,
621
+ stderr="",
622
+ status=results.status,
623
+ abspath_errors=results.abspath_errors,
624
+ unmatched_stdout="",
625
+ ).dump(results_f)
626
+ yield
627
+ """ ,
628
+ )
629
+ result = testdir .runpytest_subprocess ("--mypy" , * xdist_args )
630
+ mypy_file_checks = 1
631
+ mypy_status_check = 1
632
+ mypy_checks = mypy_file_checks + mypy_status_check
633
+ result .assert_outcomes (passed = mypy_checks )
634
+ assert result .ret == 0
635
+ assert "= mypy =" not in str (result .stdout )
0 commit comments