39
39
import json
40
40
import os
41
41
import random
42
+ import re
42
43
import shutil
43
44
import subprocess
44
45
import sys
@@ -125,7 +126,7 @@ def run_mypy(target_file_path: Optional[str],
125
126
* ,
126
127
incremental : bool = False ,
127
128
daemon : bool = False ,
128
- verbose : bool = False ) -> Tuple [float , str ]:
129
+ verbose : bool = False ) -> Tuple [float , str , Dict [ str , Any ] ]:
129
130
"""Runs mypy against `target_file_path` and returns what mypy prints to stdout as a string.
130
131
131
132
If `incremental` is set to True, this function will use store and retrieve all caching data
@@ -134,8 +135,9 @@ def run_mypy(target_file_path: Optional[str],
134
135
135
136
If `daemon` is True, we use daemon mode; the daemon must be started and stopped by the caller.
136
137
"""
138
+ stats = {} # type: Dict[str, Any]
137
139
if daemon :
138
- command = DAEMON_CMD + ["check" , "-q " ]
140
+ command = DAEMON_CMD + ["check" , "-v " ]
139
141
else :
140
142
if mypy_script is None :
141
143
command = ["python3" , "-m" , "mypy" ]
@@ -152,8 +154,27 @@ def run_mypy(target_file_path: Optional[str],
152
154
output , stderr , _ = execute (command , False )
153
155
if stderr != "" :
154
156
output = stderr
157
+ else :
158
+ if daemon :
159
+ output , stats = filter_daemon_stats (output )
155
160
runtime = time .time () - start
156
- return runtime , output
161
+ return runtime , output , stats
162
+
163
+
164
+ def filter_daemon_stats (output : str ) -> Tuple [str , Dict [str , Any ]]:
165
+ stats = {} # type: Dict[str, Any]
166
+ lines = output .splitlines ()
167
+ output_lines = []
168
+ for line in lines :
169
+ m = re .match ('(\w+)\s+:\s+(.*)' , line )
170
+ if m :
171
+ key , value = m .groups ()
172
+ stats [key ] = value
173
+ else :
174
+ output_lines .append (line )
175
+ if output_lines :
176
+ output_lines .append ('\n ' )
177
+ return '\n ' .join (output_lines ), stats
157
178
158
179
159
180
def start_daemon (mypy_cache_path : str ) -> None :
@@ -197,8 +218,8 @@ def set_expected(commits: List[Tuple[str, str]],
197
218
else :
198
219
print ('Caching expected output for commit {0}: "{1}"' .format (commit_id , message ))
199
220
execute (["git" , "-C" , temp_repo_path , "checkout" , commit_id ])
200
- runtime , output = run_mypy (target_file_path , mypy_cache_path , mypy_script ,
201
- incremental = False )
221
+ runtime , output , stats = run_mypy (target_file_path , mypy_cache_path , mypy_script ,
222
+ incremental = False )
202
223
cache [commit_id ] = {'runtime' : runtime , 'output' : output }
203
224
if output == "" :
204
225
print (" Clean output ({:.3f} sec)" .format (runtime ))
@@ -224,11 +245,13 @@ def test_incremental(commits: List[Tuple[str, str]],
224
245
"""
225
246
print ("Note: first commit is evaluated twice to warm up cache" )
226
247
commits = [commits [0 ]] + commits
248
+ overall_stats = {} # type: Dict[str, float]
227
249
for commit_id , message in commits :
228
250
print ('Now testing commit {0}: "{1}"' .format (commit_id , message ))
229
251
execute (["git" , "-C" , temp_repo_path , "checkout" , commit_id ])
230
- runtime , output = run_mypy (target_file_path , mypy_cache_path , mypy_script ,
231
- incremental = True , daemon = daemon )
252
+ runtime , output , stats = run_mypy (target_file_path , mypy_cache_path , mypy_script ,
253
+ incremental = True , daemon = daemon )
254
+ relevant_stats = combine_stats (overall_stats , stats )
232
255
expected_runtime = cache [commit_id ]['runtime' ] # type: float
233
256
expected_output = cache [commit_id ]['output' ] # type: str
234
257
if output != expected_output :
@@ -243,6 +266,23 @@ def test_incremental(commits: List[Tuple[str, str]],
243
266
print (" Output matches expected result!" )
244
267
print (" Incremental: {:.3f} sec" .format (runtime ))
245
268
print (" Original: {:.3f} sec" .format (expected_runtime ))
269
+ if relevant_stats :
270
+ print (" Stats: {}" .format (relevant_stats ))
271
+ if overall_stats :
272
+ print ("Overall stats:" , overall_stats )
273
+
274
+
275
+ def combine_stats (overall_stats : Dict [str , float ],
276
+ new_stats : Dict [str , Any ]) -> Dict [str , float ]:
277
+ INTERESTING_KEYS = ['build_time' , 'gc_time' ]
278
+ # For now, we only support float keys
279
+ relevant_stats = {} # type: Dict[str, float]
280
+ for key in INTERESTING_KEYS :
281
+ if key in new_stats :
282
+ value = float (new_stats [key ])
283
+ relevant_stats [key ] = value
284
+ overall_stats [key ] = overall_stats .get (key , 0.0 ) + value
285
+ return relevant_stats
246
286
247
287
248
288
def cleanup (temp_repo_path : str , mypy_cache_path : str ) -> None :
0 commit comments