1616from .parser import MypyTestItem , parse_file
1717
1818
19+ PYTEST_VERSION = pytest .__version__
20+ PYTEST_VERISON_INFO = tuple (int (part ) for part in PYTEST_VERSION .split ("." ))
21+
22+
1923class MypyResult (NamedTuple ):
2024 mypy_args : List [str ]
2125 returncode : int
@@ -36,15 +40,27 @@ def __init__(
3640 self ,
3741 name : str ,
3842 parent : "PytestMypyFile" ,
39- config : Config ,
43+ * ,
4044 mypy_item : MypyTestItem ,
45+ config : Optional [Config ] = None ,
4146 ) -> None :
42- super ().__init__ (name , parent , config )
47+ if config is None :
48+ config = parent .config
49+ super ().__init__ (name , parent = parent , config = config )
4350 self .add_marker ("mypy" )
4451 self .mypy_item = mypy_item
4552 for mark in self .mypy_item .marks :
4653 self .add_marker (mark )
4754
55+ @classmethod
56+ def from_parent (cls , parent , name , mypy_item ):
57+ if PYTEST_VERISON_INFO < (5 , 4 ):
58+ return cls (
59+ parent = parent , name = name , config = parent .config , mypy_item = mypy_item
60+ )
61+ else :
62+ return super ().from_parent (parent = parent , name = name , mypy_item = mypy_item )
63+
4864 def runtest (self ) -> None :
4965 returncode , actual_messages = self .parent .run_mypy (self .mypy_item )
5066
@@ -59,44 +75,55 @@ def reportinfo(self) -> Tuple[str, Optional[int], str]:
5975 return self .parent .fspath , self .mypy_item .lineno , self .name
6076
6177 def repr_failure (self , excinfo , style = None ):
62- if excinfo .errisinstance (MypyAssertionError ):
63- exception_repr = excinfo .getrepr (style = "short" )
64- exception_repr .reprcrash .message = ""
65- exception_repr .reprtraceback .reprentries = [
66- ReprEntry (
67- filelocrepr = ReprFileLocation (
78+ if not excinfo .errisinstance (MypyAssertionError ):
79+ return super ().repr_failure (excinfo , style = style ) # pragma: no cover
80+ reprfileloc_key = (
81+ "filelocrepr" if PYTEST_VERISON_INFO < (5 , 4 ) else "reprfileloc"
82+ )
83+ exception_repr = excinfo .getrepr (style = "short" )
84+ exception_repr .reprcrash .message = ""
85+ exception_repr .reprtraceback .reprentries = [
86+ ReprEntry (
87+ lines = mismatch .lines ,
88+ style = "short" ,
89+ reprlocals = None ,
90+ reprfuncargs = None ,
91+ ** {
92+ reprfileloc_key : ReprFileLocation (
6893 path = self .parent .fspath ,
6994 lineno = mismatch .lineno ,
7095 message = mismatch .error_message ,
71- ),
72- lines = mismatch .lines ,
73- style = "short" ,
74- reprlocals = None ,
75- reprfuncargs = None ,
76- )
77- for mismatch in excinfo .value .errors
78- ]
79- return exception_repr
80- else :
81- return super ().repr_failure (excinfo , style = style ) # pragma: no cover
96+ )
97+ },
98+ )
99+ for mismatch in excinfo .value .errors
100+ ]
101+ return exception_repr
82102
83103
84104class PytestMypyFile (pytest .File ):
85105 def __init__ (
86106 self , fspath : LocalPath , parent = None , config = None , session = None , nodeid = None ,
87107 ) -> None :
108+ if config is None :
109+ config = getattr (parent , "config" , None )
88110 super ().__init__ (fspath , parent , config , session , nodeid )
89111 self .add_marker ("mypy" )
90112 self .mypy_file = parse_file (self .fspath )
91113 self ._mypy_result : Optional [MypyResult ] = None
92114
115+ @classmethod
116+ def from_parent (cls , parent , fspath ):
117+ if PYTEST_VERISON_INFO < (5 , 4 ):
118+ config = getattr (parent , "config" , None )
119+ return cls (parent = parent , config = config , fspath = fspath )
120+ else :
121+ return super ().from_parent (parent = parent , fspath = fspath )
122+
93123 def collect (self ) -> Iterator [PytestMypyTestItem ]:
94124 for item in self .mypy_file .items :
95- yield PytestMypyTestItem (
96- name = "[mypy]" + item .name ,
97- parent = self ,
98- config = self .config ,
99- mypy_item = item ,
125+ yield PytestMypyTestItem .from_parent (
126+ parent = self , name = "[mypy]" + item .name , mypy_item = item ,
100127 )
101128
102129 def run_mypy (self , item : MypyTestItem ) -> Tuple [int , List [Message ]]:
@@ -163,14 +190,17 @@ def pytest_collect_file(path: LocalPath, parent):
163190 if not hasattr (builtins , "reveal_type" ):
164191 setattr (builtins , "reveal_type" , lambda x : x )
165192
166- config = getattr (parent , "config" , None )
193+ if path .ext not in (".mypy-testing" , ".py" ):
194+ return None # pragma: no cover
195+ if not path .basename .startswith ("test_" ):
196+ return None # pragma: no cover
167197
168- if path . ext in ( ".mypy-testing" , ".py" ) and path . basename . startswith ( "test_" ):
169- file = PytestMypyFile ( path , parent = parent , config = config )
170- if file .mypy_file .items :
171- return file
198+ file = PytestMypyFile . from_parent ( parent = parent , fspath = path )
199+
200+ if file .mypy_file .items :
201+ return file
172202 else :
173- return None # pragma: no cover
203+ return None
174204
175205
176206def pytest_configure (config ):
0 commit comments