Skip to content

Commit 5fd33b9

Browse files
committed
Update logic; create lru log
1 parent 72c57d0 commit 5fd33b9

File tree

5 files changed

+41
-161
lines changed

5 files changed

+41
-161
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ docs/build/
1212
.mypy_cache/
1313
.incremental_checker_cache.json
1414
.cache
15+
.runtest_log.json
1516

1617
# Packages
1718
*.egg

.runtest_timing.json

Lines changed: 0 additions & 138 deletions
This file was deleted.

mypy/waiter.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This is used for running mypy tests.
44
"""
55

6-
from typing import Dict, List, Optional, Set, Tuple
6+
from typing import Dict, List, Optional, Set, Tuple, Any
77

88
import os
99
from multiprocessing import cpu_count
@@ -110,8 +110,8 @@ class Waiter:
110110
if not waiter.run():
111111
print('error')
112112
"""
113-
114-
TIMING_FILENAME = '.runtest_timing.json'
113+
LOGSIZE = 50
114+
FULL_LOG_FILENAME = '.runtest_log.json'
115115

116116
def __init__(self, limit: int = 0, *, verbosity: int = 0, xfail: List[str] = []) -> None:
117117
self.verbosity = verbosity
@@ -135,18 +135,19 @@ def __init__(self, limit: int = 0, *, verbosity: int = 0, xfail: List[str] = [])
135135
self._note = None # type: Noter
136136
self.times1 = {} # type: Dict[str, float]
137137
self.times2 = {} # type: Dict[str, float]
138+
self.new_log = defaultdict(dict) # type: Dict[str, Dict[str, Any]]
138139

139-
# we likely add only a few tasks, so it's ok to put them in front even if they fast
140-
# much worse if we put them in the back, and one of them turns out to be slow
141-
self.times = defaultdict(lambda: float('inf')) # type: Dict[str, float]
140+
def load_log_file(self) -> Optional[List[Dict[str, Dict[str, Any]]]]:
142141
try:
143-
with open(self.TIMING_FILENAME) as fp:
144-
times = json.load(fp)
145-
self.times.update(times)
146-
self.found_timing_file = True
147-
except Exception:
148-
print('cannot find runtest timing file')
149-
self.found_timing_file = False
142+
# get the last log
143+
with open(self.FULL_LOG_FILENAME) as fp:
144+
test_log = json.load(fp)
145+
except FileNotFoundError:
146+
test_log = []
147+
except json.JSONDecodeError:
148+
print('corrupt test log file {}'.format(self.FULL_LOG_FILENAME))
149+
test_log = []
150+
return test_log
150151

151152
def add(self, cmd: LazySubprocess) -> int:
152153
rv = len(self.queue)
@@ -186,7 +187,8 @@ def _poll_current(self) -> Tuple[int, int]:
186187
code = cmd.process.poll()
187188
if code is not None:
188189
cmd.end_time = time.perf_counter()
189-
self.times[cmd.name] = cmd.end_time - cmd.start_time
190+
self.new_log[cmd.name]['exit_code'] = code
191+
self.new_log[cmd.name]['runtime'] = cmd.end_time - cmd.start_time
190192
return pid, code
191193

192194
def _wait_next(self) -> Tuple[List[str], int, int]:
@@ -260,8 +262,16 @@ def run(self) -> int:
260262
self._note = Noter(len(self.queue))
261263
print('SUMMARY %d tasks selected' % len(self.queue))
262264

263-
self.queue = sorted(self.queue, key=lambda c: self.times[c.name], reverse=True)
264-
print([t.name for t in self.queue][:5])
265+
if self.limit > 1:
266+
logs = self.load_log_file()
267+
if logs:
268+
# we don't know how long a new task takes
269+
# better err by putting it in front in case it is slow:
270+
# a fast task in front hurts performance less than a slow task in the back
271+
default = float('inf')
272+
times = {cmd.name: sum(log[cmd.name].get('runtime', default) for log in logs)
273+
/ len(logs) for cmd in self.queue}
274+
self.queue = sorted(self.queue, key=lambda cmd: times[cmd.name], reverse=True)
265275

266276
sys.stdout.flush()
267277
# Failed tasks.
@@ -296,12 +306,14 @@ def run(self) -> int:
296306
print('*** OK ***')
297307
sys.stdout.flush()
298308

299-
if not self.found_timing_file:
309+
if self.limit > 1:
310+
# log only LOGSIZE most recent tests
311+
test_log = (self.load_log_file() + [self.new_log])[:self.LOGSIZE]
300312
try:
301-
with open(self.TIMING_FILENAME, 'w') as fp:
302-
json.dump(self.times, fp, sort_keys=True, indent=4)
303-
except Exception:
304-
print('cannot save runtest timing file')
313+
with open(self.FULL_LOG_FILENAME, 'w') as fp:
314+
json.dump(test_log, fp, sort_keys=True, indent=4)
315+
except Exception as e:
316+
print('cannot save test log file:', e)
305317

306318
return 0
307319

runtests.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def get_versions(): # type: () -> typing.List[str]
3434
import itertools
3535
import os
3636
import re
37+
import json
3738

3839

3940
# Ideally, all tests would be `discover`able so that they can be driven
@@ -58,6 +59,10 @@ def __init__(self, whitelist: List[str], blacklist: List[str],
5859
self.env = dict(os.environ)
5960
self.coverage = coverage
6061

62+
def run(self) -> int:
63+
exit_code = self.sequential.run() & self.waiter.run()
64+
return exit_code
65+
6166
def prepend_path(self, name: str, paths: List[str]) -> None:
6267
old_val = self.env.get(name)
6368
paths = [p for p in paths if isdir(p)]
@@ -424,7 +429,7 @@ def main() -> None:
424429
driver.list_tasks()
425430
return
426431

427-
exit_code = driver.sequential.run() & driver.waiter.run()
432+
exit_code = driver.run()
428433
t1 = time.perf_counter()
429434
print('total runtime:', t1 - t0, 'sec')
430435

typeshed

Submodule typeshed updated 163 files

0 commit comments

Comments
 (0)