Skip to content

Commit 08b8e6d

Browse files
machshevhcallahan-lowrisc
authored andcommitted
style: linting, docstrings and typing
Signed-off-by: James McCorrie <[email protected]>
1 parent 53bbfd4 commit 08b8e6d

File tree

5 files changed

+94
-33
lines changed

5 files changed

+94
-33
lines changed

src/dvsim/flow/base.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,16 +445,19 @@ def _gen_results(self, results: Mapping[str, CompletedJobStatus]) -> str:
445445
prints the full list of failures for debug / triage to the final
446446
report, which is in markdown format.
447447
448-
Results:
449-
dictionary mapping deployed item names to job status.
448+
Args:
449+
results: dictionary mapping deployed item names to completed job status.
450+
451+
Returns:
452+
Results as a formatted string
450453
451454
"""
452455

453456
def gen_results(self, results: Mapping[str, CompletedJobStatus]) -> None:
454-
"""Public facing API for _gen_results().
457+
"""Generate flow results.
455458
456459
Args:
457-
results: dictionary mapping deployed item names to job status.
460+
results: dictionary mapping deployed item names to completed job status.
458461
459462
"""
460463
for item in self.cfgs:

src/dvsim/job/deploy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def pre_launch(self, launcher: Launcher) -> None:
293293
This is invoked by launcher::_pre_launch().
294294
"""
295295

296-
def post_finish(self, status) -> None:
296+
def post_finish(self, status: str) -> None:
297297
"""Perform additional post-finish activities (callback).
298298
299299
This is invoked by launcher::_post_finish().

src/dvsim/launcher/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Launcher(ABC):
6767
poll_freq = 1
6868

6969
# Points to the python virtual env area.
70-
pyvenv = None
70+
pyvenv: Path | None = None
7171

7272
# If a history of previous invocations is to be maintained, then keep no
7373
# more than this many directories.
@@ -250,6 +250,10 @@ def poll(self) -> str | None:
250250
"""Poll the launched job for completion.
251251
252252
Invokes _check_status() and _post_finish() when the job completes.
253+
254+
Returns:
255+
status of the job or None
256+
253257
"""
254258

255259
@abstractmethod

src/dvsim/scheduler.py

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,14 @@ def __init__(
9191
*,
9292
interactive: bool,
9393
) -> None:
94-
"""Initialise a job scheduler."""
94+
"""Initialise a job scheduler.
95+
96+
Args:
97+
items: sequence of jobs to deploy.
98+
launcher_cls: Launcher class to use to deploy the jobs.
99+
interactive: launch the tools in interactive mode.
100+
101+
"""
95102
self.items: Sequence[Deploy] = items
96103

97104
# 'scheduled[target][cfg]' is a list of Deploy objects for the chosen
@@ -148,7 +155,7 @@ def __init__(
148155
msg = self.msg_fmt.format(0, 0, 0, 0, 0, self._total[target])
149156
self.status_printer.init_target(target=target, msg=msg)
150157

151-
# A map from the Deploy object names tracked by this class to their
158+
# A map from the Deployment names tracked by this class to their
152159
# current status. This status is 'Q', 'D', 'P', 'F' or 'K',
153160
# corresponding to membership in the dicts above. This is not
154161
# per-target.
@@ -271,8 +278,13 @@ def _enqueue_successors(self, item: Deploy | None = None) -> None:
271278
them to _queued.
272279
"""
273280
for next_item in self._get_successors(item):
274-
assert next_item.full_name not in self.item_status
275-
assert next_item not in self._queued[next_item.target]
281+
if (
282+
next_item.full_name in self.item_status
283+
or next_item in self._queued[next_item.target]
284+
):
285+
msg = f"Job {next_item.full_name} already scheduled"
286+
raise RuntimeError(msg)
287+
276288
self.item_status[next_item.full_name] = "Q"
277289
self._queued[next_item.target].append(next_item)
278290
self._unschedule_item(next_item)
@@ -281,6 +293,10 @@ def _cancel_successors(self, item: Deploy) -> None:
281293
"""Cancel an item's successors.
282294
283295
Recursively move them from _scheduled or _queued to _killed.
296+
297+
Args:
298+
item: job whose successors are to be canceled.
299+
284300
"""
285301
items = list(self._get_successors(item))
286302
while items:
@@ -291,14 +307,17 @@ def _cancel_successors(self, item: Deploy) -> None:
291307
def _get_successors(self, item: Deploy | None = None) -> Sequence[Deploy]:
292308
"""Find immediate successors of an item.
293309
294-
'item' is a job that has completed. We choose the target that follows
295-
the 'item''s current target and find the list of successors whose
296-
dependency list contains 'item'. If 'item' is None, we pick successors
297-
from all cfgs, else we pick successors only from the cfg to which the
298-
item belongs.
310+
We choose the target that follows the 'item''s current target and find
311+
the list of successors whose dependency list contains 'item'. If 'item'
312+
is None, we pick successors from all cfgs, else we pick successors only
313+
from the cfg to which the item belongs.
314+
315+
Args:
316+
item: is a job that has completed.
317+
318+
Returns:
319+
list of item's successors, or an empty list if there are none.
299320
300-
Returns the list of item's successors, or an empty list if there are
301-
none.
302321
"""
303322
if item is None:
304323
target = next(iter(self._scheduled))
@@ -320,8 +339,10 @@ def _get_successors(self, item: Deploy | None = None) -> Sequence[Deploy]:
320339
while not found:
321340
if target == item.target:
322341
found = True
342+
323343
try:
324344
target = next(target_iterator)
345+
325346
except StopIteration:
326347
return []
327348

@@ -349,7 +370,15 @@ def _get_successors(self, item: Deploy | None = None) -> Sequence[Deploy]:
349370
return successors
350371

351372
def _ok_to_enqueue(self, item: Deploy) -> bool:
352-
"""Return true if ALL dependencies of item are complete."""
373+
"""Check if all dependencies jobs are completed.
374+
375+
Args:
376+
item: is a deployment job.
377+
378+
Returns:
379+
true if ALL dependencies of item are complete.
380+
381+
"""
353382
for dep in item.dependencies:
354383
# Ignore dependencies that were not scheduled to run.
355384
if dep not in self.items:
@@ -366,11 +395,18 @@ def _ok_to_enqueue(self, item: Deploy) -> bool:
366395
return True
367396

368397
def _ok_to_run(self, item: Deploy) -> bool:
369-
"""Return true if the required dependencies have passed.
398+
"""Check if a job is ready to start.
370399
371400
The item's needs_all_dependencies_passing setting is used to figure
372401
out whether we can run this item or not, based on its dependent jobs'
373402
statuses.
403+
404+
Args:
405+
item: is a deployment job.
406+
407+
Returns:
408+
true if the required dependencies have passed.
409+
374410
"""
375411
# 'item' can run only if its dependencies have passed (their results
376412
# should already show up in the item to status map).
@@ -395,7 +431,9 @@ def _ok_to_run(self, item: Deploy) -> bool:
395431
def _poll(self, hms: str) -> bool:
396432
"""Check for running items that have finished.
397433
398-
Returns True if something changed.
434+
Returns:
435+
True if something changed.
436+
399437
"""
400438
max_poll = min(
401439
self.launcher_cls.max_poll,
@@ -615,6 +653,11 @@ def _cancel_item(self, item: Deploy, *, cancel_successors: bool = True) -> None:
615653
616654
Supplied item may be in _scheduled list or the _queued list. From
617655
either, we move it straight to _killed.
656+
657+
Args:
658+
item: is a deployment job.
659+
cancel_successors: if set then cancel successors as well (True).
660+
618661
"""
619662
self.item_status[item.full_name] = "K"
620663
self._killed[item.target].add(item)
@@ -627,7 +670,12 @@ def _cancel_item(self, item: Deploy, *, cancel_successors: bool = True) -> None:
627670
self._cancel_successors(item)
628671

629672
def _kill_item(self, item: Deploy) -> None:
630-
"""Kill a running item and cancel all of its successors."""
673+
"""Kill a running item and cancel all of its successors.
674+
675+
Args:
676+
item: is a deployment job.
677+
678+
"""
631679
self._launchers[item.full_name].kill()
632680
self.item_status[item.full_name] = "K"
633681
self._killed[item.target].add(item)

src/dvsim/sim_utils.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@
66

77
import re
88
from collections import OrderedDict
9+
from collections.abc import Sequence
10+
from io import TextIOWrapper
911
from pathlib import Path
1012

1113

12-
def get_cov_summary_table(cov_report_txt: Path, tool: str):
14+
def get_cov_summary_table(
15+
txt_cov_report: Path,
16+
tool: str,
17+
) -> tuple[Sequence[Sequence[str]], str]:
1318
"""Capture the summary results as a list of lists.
1419
1520
The text coverage report is passed as input to the function, in addition to
16-
the tool used. The tool returns a 2D list if the coverage report file was read
17-
and the coverage was extracted successfully.
21+
the tool used.
1822
1923
Returns:
2024
tuple of, List of metrics and values, and final coverage total
@@ -23,7 +27,7 @@ def get_cov_summary_table(cov_report_txt: Path, tool: str):
2327
the appropriate exception if the coverage summary extraction fails.
2428
2529
"""
26-
with Path(cov_report_txt).open() as f:
30+
with Path(txt_cov_report).open() as f:
2731
if tool == "xcelium":
2832
return xcelium_cov_summary_table(f)
2933

@@ -35,7 +39,8 @@ def get_cov_summary_table(cov_report_txt: Path, tool: str):
3539

3640

3741
# Same desc as above, but specific to Xcelium and takes an opened input stream.
38-
def xcelium_cov_summary_table(buf):
42+
def xcelium_cov_summary_table(buf: TextIOWrapper) -> tuple[Sequence[Sequence[str]], str]:
43+
"""Capture the summary results as a list of lists from Xcelium."""
3944
for line in buf:
4045
if "name" in line:
4146
# Strip the line and remove the unwanted "* Covered" string.
@@ -87,7 +92,8 @@ def xcelium_cov_summary_table(buf):
8792

8893

8994
# Same desc as above, but specific to VCS and takes an opened input stream.
90-
def vcs_cov_summary_table(buf):
95+
def vcs_cov_summary_table(buf: TextIOWrapper) -> tuple[Sequence[Sequence[str]], str]:
96+
"""Capture the summary results as a list of lists from VCS."""
9197
for line in buf:
9298
match = re.match("total coverage summary", line, re.IGNORECASE)
9399
if match:
@@ -124,7 +130,7 @@ def get_job_runtime(log_text: list, tool: str) -> tuple[float, str]:
124130
tool: is the EDA tool used to run the job.
125131
126132
Returns:
127-
the runtime, units as a tuple.
133+
a tuple of (runtime, units).
128134
129135
Raises:
130136
NotImplementedError: exception if the EDA tool is not supported.
@@ -184,8 +190,7 @@ def xcelium_job_runtime(log_text: list) -> tuple[float, str]:
184190
"""
185191
pattern = r"^TOOL:\s*xrun.*: Exiting on .*\(total:\s*(\d+):(\d+):(\d+)\)\s*$"
186192
for line in reversed(log_text):
187-
m = re.search(pattern, line)
188-
if m:
193+
if m := re.search(pattern, line):
189194
t = int(m.group(1)) * 3600 + int(m.group(2)) * 60 + int(m.group(3))
190195
return t, "s"
191196
msg = "Job runtime not found in the log."
@@ -265,9 +270,10 @@ def vcs_simulated_time(log_text: list) -> tuple[float, str]:
265270
next_line = ""
266271

267272
for line in reversed(log_text):
268-
if "V C S S i m u l a t i o n R e p o r t" in line and (
269-
m := re.search(pattern, next_line)
270-
):
273+
if "V C S S i m u l a t i o n R e p o r t" not in line:
274+
continue
275+
276+
if m := re.search(pattern, next_line):
271277
return float(m.group(1)), m.group(2).lower()
272278

273279
next_line = line

0 commit comments

Comments
 (0)