77from pathlib import Path
88from tempfile import NamedTemporaryFile
99import typing
10- import warnings
1110
1211from filelock import FileLock
1312import mypy .api
@@ -227,6 +226,14 @@ def repr_failure(
227226 return super ().repr_failure (excinfo )
228227
229228
229+ def _error_severity (error : str ) -> str :
230+ components = [component .strip () for component in error .split (":" )]
231+ # The second component is either the line or the severity:
232+ # demo/note.py:2: note: By default the bodies of untyped functions are not checked
233+ # demo/sub/conftest.py: error: Duplicate module named "conftest"
234+ return components [2 ] if components [1 ].isdigit () else components [1 ]
235+
236+
230237class MypyFileItem (MypyItem ):
231238 """A check for Mypy errors in a File."""
232239
@@ -238,20 +245,15 @@ def runtest(self) -> None:
238245 error .partition (":" )[2 ].strip ()
239246 for error in results .abspath_errors .get (abspath , [])
240247 ]
241- if errors :
242- if not all (
243- error .partition (":" )[2 ].partition (":" )[0 ].strip () == "note"
244- for error in errors
245- ):
246- if self .session .config .option .mypy_xfail :
247- self .add_marker (
248- pytest .mark .xfail (
249- raises = MypyError ,
250- reason = "mypy errors are expected by --mypy-xfail." ,
251- )
248+ if errors and not all (_error_severity (error ) == "note" for error in errors ):
249+ if self .session .config .option .mypy_xfail :
250+ self .add_marker (
251+ pytest .mark .xfail (
252+ raises = MypyError ,
253+ reason = "mypy errors are expected by --mypy-xfail." ,
252254 )
253- raise MypyError ( file_error_formatter ( self , results , errors ) )
254- warnings . warn ( " \n " + " \n " . join ( errors ), MypyWarning )
255+ )
256+ raise MypyError ( file_error_formatter ( self , results , errors ))
255257
256258 def reportinfo (self ) -> Tuple [str , None , str ]:
257259 """Produce a heading for the test report."""
@@ -371,10 +373,6 @@ class MypyError(Exception):
371373 """
372374
373375
374- class MypyWarning (pytest .PytestWarning ):
375- """A non-failure message regarding the mypy run."""
376-
377-
378376class MypyControllerPlugin :
379377 """A plugin that is not registered on xdist worker processes."""
380378
@@ -397,9 +395,17 @@ def pytest_terminal_summary(
397395 if results .stdout :
398396 if config .option .mypy_xfail :
399397 terminalreporter .write (results .stdout )
400- elif results .unmatched_stdout :
401- color = {"red" : True } if results .status else {"green" : True }
402- terminalreporter .write_line (results .unmatched_stdout , ** color )
398+ else :
399+ for note in (
400+ unreported_note
401+ for errors in results .abspath_errors .values ()
402+ if all (_error_severity (error ) == "note" for error in errors )
403+ for unreported_note in errors
404+ ):
405+ terminalreporter .write_line (note )
406+ if results .unmatched_stdout :
407+ color = {"red" : True } if results .status else {"green" : True }
408+ terminalreporter .write_line (results .unmatched_stdout , ** color )
403409 if results .stderr :
404410 terminalreporter .write_line (results .stderr , yellow = True )
405411
0 commit comments