16
16
from .parser import MypyTestItem , parse_file
17
17
18
18
19
+ PYTEST_VERSION = pytest .__version__
20
+ PYTEST_VERISON_INFO = tuple (int (part ) for part in PYTEST_VERSION .split ("." ))
21
+
22
+
19
23
class MypyResult (NamedTuple ):
20
24
mypy_args : List [str ]
21
25
returncode : int
@@ -36,15 +40,27 @@ def __init__(
36
40
self ,
37
41
name : str ,
38
42
parent : "PytestMypyFile" ,
39
- config : Config ,
43
+ * ,
40
44
mypy_item : MypyTestItem ,
45
+ config : Optional [Config ] = None ,
41
46
) -> None :
42
- super ().__init__ (name , parent , config )
47
+ if config is None :
48
+ config = parent .config
49
+ super ().__init__ (name , parent = parent , config = config )
43
50
self .add_marker ("mypy" )
44
51
self .mypy_item = mypy_item
45
52
for mark in self .mypy_item .marks :
46
53
self .add_marker (mark )
47
54
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
+
48
64
def runtest (self ) -> None :
49
65
returncode , actual_messages = self .parent .run_mypy (self .mypy_item )
50
66
@@ -59,44 +75,55 @@ def reportinfo(self) -> Tuple[str, Optional[int], str]:
59
75
return self .parent .fspath , self .mypy_item .lineno , self .name
60
76
61
77
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 (
68
93
path = self .parent .fspath ,
69
94
lineno = mismatch .lineno ,
70
95
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
82
102
83
103
84
104
class PytestMypyFile (pytest .File ):
85
105
def __init__ (
86
106
self , fspath : LocalPath , parent = None , config = None , session = None , nodeid = None ,
87
107
) -> None :
108
+ if config is None :
109
+ config = getattr (parent , "config" , None )
88
110
super ().__init__ (fspath , parent , config , session , nodeid )
89
111
self .add_marker ("mypy" )
90
112
self .mypy_file = parse_file (self .fspath )
91
113
self ._mypy_result : Optional [MypyResult ] = None
92
114
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
+
93
123
def collect (self ) -> Iterator [PytestMypyTestItem ]:
94
124
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 ,
100
127
)
101
128
102
129
def run_mypy (self , item : MypyTestItem ) -> Tuple [int , List [Message ]]:
@@ -163,14 +190,17 @@ def pytest_collect_file(path: LocalPath, parent):
163
190
if not hasattr (builtins , "reveal_type" ):
164
191
setattr (builtins , "reveal_type" , lambda x : x )
165
192
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
167
197
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
172
202
else :
173
- return None # pragma: no cover
203
+ return None
174
204
175
205
176
206
def pytest_configure (config ):
0 commit comments