@@ -101,7 +101,7 @@ def mypy_to_pandas(input_lines: Iterator[str]) -> pandas.DataFrame:
101
101
"file" : [],
102
102
"line" : [],
103
103
"type" : [],
104
- "section " : [],
104
+ "errorcode " : [],
105
105
"message" : [],
106
106
}
107
107
for line in input_lines :
@@ -120,7 +120,7 @@ def mypy_to_pandas(input_lines: Iterator[str]) -> pandas.DataFrame:
120
120
data ["file" ].append (file )
121
121
data ["line" ].append (lineno )
122
122
data ["type" ].append (message_type )
123
- data ["section " ].append (current_section )
123
+ data ["errorcode " ].append (current_section )
124
124
data ["message" ].append (message )
125
125
except Exception as ex :
126
126
print (elems )
@@ -154,43 +154,67 @@ def check_no_unexpected_results(mypy_lines: Iterator[str]):
154
154
if not unexpected_failing :
155
155
print (f"{ len (passing )} /{ len (all_files )} files pass as expected." )
156
156
else :
157
- print (f"{ len (unexpected_failing )} files unexpectedly failed:" )
157
+ print ("!!!!!!!!!" )
158
+ print (f"{ len (unexpected_failing )} files unexpectedly failed." )
158
159
print ("\n " .join (sorted (map (str , unexpected_failing ))))
160
+ print (
161
+ "These files did not fail before, so please check the above output"
162
+ f" for errors in { unexpected_failing } and fix them."
163
+ )
164
+ print ("!!!!!!!!!" )
159
165
sys .exit (1 )
160
166
161
167
if unexpected_passing == {"pymc/sampling_jax.py" }:
162
168
print ("Letting you know that 'pymc/sampling_jax.py' unexpectedly passed." )
163
169
print ("But this file is known to sometimes pass and sometimes not." )
164
- print ("Unless tried to resolve problems in sampling_jax.py just ignore this message." )
170
+ print ("Unless you tried to resolve problems in sampling_jax.py just ignore this message." )
165
171
elif unexpected_passing :
172
+ print ("!!!!!!!!!" )
166
173
print (f"{ len (unexpected_passing )} files unexpectedly passed the type checks:" )
167
174
print ("\n " .join (sorted (map (str , unexpected_passing ))))
168
175
print ("This is good news! Go to scripts/run_mypy.py and add them to the list." )
169
176
if all_files .issubset (passing ):
170
177
print ("WOW! All files are passing the mypy type checks!" )
171
178
print ("scripts\\ run_mypy.py may no longer be needed." )
179
+ print ("!!!!!!!!!" )
172
180
sys .exit (1 )
173
181
return
174
182
175
183
176
184
if __name__ == "__main__" :
177
185
# Enforce PEP 561 for some important dependencies that
178
186
# have relevant type hints but don't tell that to mypy.
179
- enforce_pep561 ("aesara" )
180
187
enforce_pep561 ("aeppl" )
181
188
182
- parser = argparse .ArgumentParser (description = "Process some integers ." )
189
+ parser = argparse .ArgumentParser (description = "Run mypy type checks on PyMC codebase ." )
183
190
parser .add_argument (
184
191
"--verbose" , action = "count" , default = 0 , help = "Pass this to print mypy output."
185
192
)
193
+ parser .add_argument (
194
+ "--groupby" ,
195
+ default = "file" ,
196
+ help = "How to group verbose output. One of {file|errorcode|message}." ,
197
+ )
186
198
args , _ = parser .parse_known_args ()
187
199
188
200
cp = subprocess .run (
189
- ["mypy" , "--exclude" , "pymc/tests" , "pymc" ],
201
+ ["mypy" , "--show-error-codes" , "-- exclude" , "pymc/tests" , "pymc" ],
190
202
capture_output = True ,
191
203
)
192
204
output = cp .stdout .decode ()
193
205
if args .verbose :
194
- print (output )
206
+ df = mypy_to_pandas (output .split ("\n " ))
207
+ for section , sdf in df .reset_index ().groupby (args .groupby ):
208
+ print (f"\n \n [{ section } ]" )
209
+ for row in sdf .itertuples ():
210
+ print (f"{ row .file } :{ row .line } : { row .type } : { row .message } " )
211
+ print ()
212
+ else :
213
+ print (
214
+ "Mypy output hidden."
215
+ " Run `python run_mypy.py --verbose` to see the full output,"
216
+ " or `python run_mypy.py --help` for other options."
217
+ )
218
+
195
219
check_no_unexpected_results (output .split ("\n " ))
196
220
sys .exit (0 )
0 commit comments