3939import json
4040import os
4141import random
42+ import re
4243import shutil
4344import subprocess
4445import sys
@@ -125,7 +126,7 @@ def run_mypy(target_file_path: Optional[str],
125126 * ,
126127 incremental : bool = False ,
127128 daemon : bool = False ,
128- verbose : bool = False ) -> Tuple [float , str ]:
129+ verbose : bool = False ) -> Tuple [float , str , Dict [ str , Any ] ]:
129130 """Runs mypy against `target_file_path` and returns what mypy prints to stdout as a string.
130131
131132 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],
134135
135136 If `daemon` is True, we use daemon mode; the daemon must be started and stopped by the caller.
136137 """
138+ stats = {} # type: Dict[str, Any]
137139 if daemon :
138- command = DAEMON_CMD + ["check" , "-q " ]
140+ command = DAEMON_CMD + ["check" , "-v " ]
139141 else :
140142 if mypy_script is None :
141143 command = ["python3" , "-m" , "mypy" ]
@@ -152,8 +154,27 @@ def run_mypy(target_file_path: Optional[str],
152154 output , stderr , _ = execute (command , False )
153155 if stderr != "" :
154156 output = stderr
157+ else :
158+ if daemon :
159+ output , stats = filter_daemon_stats (output )
155160 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
157178
158179
159180def start_daemon (mypy_cache_path : str ) -> None :
@@ -197,8 +218,8 @@ def set_expected(commits: List[Tuple[str, str]],
197218 else :
198219 print ('Caching expected output for commit {0}: "{1}"' .format (commit_id , message ))
199220 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 )
202223 cache [commit_id ] = {'runtime' : runtime , 'output' : output }
203224 if output == "" :
204225 print (" Clean output ({:.3f} sec)" .format (runtime ))
@@ -224,11 +245,13 @@ def test_incremental(commits: List[Tuple[str, str]],
224245 """
225246 print ("Note: first commit is evaluated twice to warm up cache" )
226247 commits = [commits [0 ]] + commits
248+ overall_stats = {} # type: Dict[str, float]
227249 for commit_id , message in commits :
228250 print ('Now testing commit {0}: "{1}"' .format (commit_id , message ))
229251 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 )
232255 expected_runtime = cache [commit_id ]['runtime' ] # type: float
233256 expected_output = cache [commit_id ]['output' ] # type: str
234257 if output != expected_output :
@@ -243,6 +266,23 @@ def test_incremental(commits: List[Tuple[str, str]],
243266 print (" Output matches expected result!" )
244267 print (" Incremental: {:.3f} sec" .format (runtime ))
245268 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
246286
247287
248288def cleanup (temp_repo_path : str , mypy_cache_path : str ) -> None :
0 commit comments