Skip to content

Commit 6967fc4

Browse files
committed
[None][test] CBTS coverage_utils: pre-commit lint fixes
Squashed cleanup pass to satisfy the repo's pre-commit hooks: * coverage_audit.py: add `r` prefix to module docstring (D301), split summary/description on two helper docstrings (D205), fix spelling flagged by codespell. * stability_diff.py: split docstring summary/description (D205), replace `print(); return` semicolon-joined pair (E702). * sitecustomize.py + stability_diff.py: ruff-format auto-fixes (single-line f-strings, import grouping, trailing commas). * cbts_plugin.py: minor reformatting from ruff-format. Pure formatting / docstring cleanup -- no behavior change. Signed-off-by: Ivy Zhang <25222398+crazydemo@users.noreply.github.com>
1 parent ec26689 commit 6967fc4

4 files changed

Lines changed: 144 additions & 115 deletions

File tree

jenkins/scripts/cbts/coverage_utils/cbts_plugin.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
containing this module on ``PYTHONPATH`` (typically same dir as
4141
``sitecustomize.py``).
4242
"""
43+
4344
import hashlib
4445
import inspect
4546
import os
@@ -72,8 +73,9 @@ def install_mpi_pool_patch(*, raise_on_refactor=True):
7273
the resulting coverage gap.
7374
"""
7475
try:
75-
import tensorrt_llm.llmapi.mpi_session as _ms
7676
from mpi4py.futures import MPIPoolExecutor # noqa: F401
77+
78+
import tensorrt_llm.llmapi.mpi_session as _ms
7779
except ImportError:
7880
return False
7981

@@ -96,16 +98,15 @@ def install_mpi_pool_patch(*, raise_on_refactor=True):
9698
def _patched_start_mpi_pool(self):
9799
"""Widened env whitelist so COVERAGE_* and PYTHON* reach workers."""
98100
import sys as _sys
101+
99102
from mpi4py.futures import MPIPoolExecutor as _MPE
100103

101104
assert not self.mpi_pool, "MPI session already started"
102-
env = {
103-
k: v
104-
for k, v in os.environ.items()
105-
if k.startswith(_ENV_WHITELIST_PREFIXES)
106-
}
105+
env = {k: v for k, v in os.environ.items() if k.startswith(_ENV_WHITELIST_PREFIXES)}
107106
self.mpi_pool = _MPE(
108-
max_workers=self.n_workers, path=_sys.path, env=env,
107+
max_workers=self.n_workers,
108+
path=_sys.path,
109+
env=env,
109110
)
110111

111112
setattr(_patched_start_mpi_pool, _PATCHED_MARKER, True)
@@ -152,9 +153,7 @@ def pytest_runtest_protocol(item, nextitem): # noqa: D401 - pytest hook
152153
# vs "plugin ran but data was lost". Filename = sha1(nodeid) to dodge
153154
# any path-escape issues from "::" / "/" in nodeids.
154155
os.makedirs(SENTINEL_DIR, exist_ok=True)
155-
sentinel = os.path.join(
156-
SENTINEL_DIR, hashlib.sha1(nodeid.encode()).hexdigest()
157-
)
156+
sentinel = os.path.join(SENTINEL_DIR, hashlib.sha1(nodeid.encode()).hexdigest())
158157
Path(sentinel).touch()
159158

160159
cov = coverage.Coverage.current()

jenkins/scripts/cbts/coverage_utils/coverage_audit.py

Lines changed: 104 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
"""Post-run audit for CBTS Layer C per-test coverage data quality.
14+
r"""Post-run audit for CBTS Layer C per-test coverage data quality.
1515
1616
Non-blocking report mode (Stage 1 of the rollout): emits a per-test CSV/JSON
1717
report plus a summary, and only exits non-zero on *hard* pipeline-plumbing
@@ -85,6 +85,7 @@
8585
--out-csv ${JOB_WORKSPACE}/cbts_audit.csv \\
8686
--out-json ${JOB_WORKSPACE}/cbts_audit.json
8787
"""
88+
8889
import argparse
8990
import ast
9091
import csv
@@ -139,28 +140,31 @@ def _is_integration_test(test_id: str) -> bool:
139140
@dataclass
140141
class TestRecord:
141142
test_id: str
142-
junit_status: str # passed / failed / error / skipped / NO_JUNIT_MATCH / unknown
143-
cov_status: str # OK / MAIN_ONLY / EMPTY / MISSING
144-
n_files: int # total product files (source filter already restricts to tensorrt_llm/)
145-
n_engine_files: int # subset under _torch/pyexecutor or _torch/models -- the worker-side signal
146-
n_engine_body_lines: int # lines in engine files MINUS def/class/decorator/import lines
147-
# (shell-style hits get covered just by importing; this metric
148-
# tells us whether engine function bodies were actually executed)
149-
context_key: str # matched coverage context (may differ from test_id)
143+
junit_status: str # passed / failed / error / skipped / NO_JUNIT_MATCH / unknown
144+
cov_status: str # OK / MAIN_ONLY / EMPTY / MISSING
145+
n_files: int # total product files (source filter already restricts to tensorrt_llm/)
146+
n_engine_files: int # subset under _torch/pyexecutor or _torch/models -- the worker-side signal
147+
n_engine_body_lines: int # lines in engine files MINUS def/class/decorator/import lines
148+
# (shell-style hits get covered just by importing; this metric
149+
# tells us whether engine function bodies were actually executed)
150+
context_key: str # matched coverage context (may differ from test_id)
150151

151152

152153
# --- junit -----------------------------------------------------------------
153154

155+
154156
def _junit_class_part(classname: str, file_attr: str) -> str:
155-
"""Strip the dotted module prefix from a junit ``classname`` when the
156-
``file`` attribute is present."""
157+
"""Strip the dotted module prefix from a junit ``classname``.
158+
159+
Only does this when the ``file`` attribute is present.
160+
"""
157161
if not classname or not file_attr:
158162
return ""
159163
mod_dotted = file_attr.replace("/", ".").rsplit(".py", 1)[0]
160164
if classname == mod_dotted:
161165
return ""
162166
if classname.startswith(mod_dotted + "."):
163-
return classname[len(mod_dotted) + 1:]
167+
return classname[len(mod_dotted) + 1 :]
164168
return classname
165169

166170

@@ -189,9 +193,7 @@ def _junit_to_nodeid(classname: str, name: str, file_attr: str) -> str:
189193
if not classname:
190194
return name
191195
parts = classname.split(".")
192-
first_class_idx = next(
193-
(i for i, p in enumerate(parts) if p[:1].isupper()), None
194-
)
196+
first_class_idx = next((i for i, p in enumerate(parts) if p[:1].isupper()), None)
195197
if first_class_idx is None:
196198
file_path = "/".join(parts) + ".py"
197199
return f"{file_path}::{name}"
@@ -230,15 +232,17 @@ def load_junit(path: Path) -> dict:
230232

231233
# --- coverage db -----------------------------------------------------------
232234

235+
233236
@functools.lru_cache(maxsize=None)
234237
def _decl_import_lines(file_path: str) -> frozenset:
235-
"""Lines that are def/class/decorator/import -- 'shell' code that's
236-
counted as covered just by importing the module.
238+
"""Lines that are def/class/decorator/import -- 'shell' code.
239+
240+
These count as covered just by importing the module.
237241
238242
For any file we can't parse (missing, syntax error, encoding), return
239243
an empty frozenset, which means we'll count ALL covered lines as
240244
body -- conservative for audit purposes (we'd rather over-count body
241-
coverage than spuriously deflate it for unparseable files).
245+
coverage than spuriously deflate it for unparsable files).
242246
"""
243247
try:
244248
with open(file_path) as f:
@@ -294,6 +298,7 @@ def load_contexts(db_path: Path) -> dict:
294298

295299
# --- matching --------------------------------------------------------------
296300

301+
297302
def match_test_to_context(test_id: str, contexts: dict) -> str:
298303
"""Find the context for ``test_id``. Returns ``""`` if no match."""
299304
if test_id in contexts:
@@ -348,8 +353,7 @@ def classify(ctx_info, has_sentinel, junit_status="unknown", test_id="") -> str:
348353
return "TEST_FAILED"
349354
if ctx_info["n_engine"] == 0:
350355
return "MAIN_ONLY"
351-
if (_is_integration_test(test_id)
352-
and not ctx_info.get("hit_main_executor", False)):
356+
if _is_integration_test(test_id) and not ctx_info.get("hit_main_executor", False):
353357
return "SUBPROCESS_LOST"
354358
return "OK"
355359

@@ -372,6 +376,7 @@ def _nodeid_sentinel_name(nodeid: str) -> str:
372376

373377
# --- save error scan -------------------------------------------------------
374378

379+
375380
def count_save_errors(log_path: Path) -> int:
376381
count = 0
377382
with open(log_path, errors="replace") as f:
@@ -383,18 +388,33 @@ def count_save_errors(log_path: Path) -> int:
383388

384389
# --- outputs ---------------------------------------------------------------
385390

391+
386392
def write_csv(path: Path, records):
387393
with open(path, "w", newline="") as f:
388394
w = csv.writer(f)
389-
w.writerow([
390-
"test_id", "junit_status", "cov_status", "n_files",
391-
"n_engine_files", "n_engine_body_lines", "context_key",
392-
])
395+
w.writerow(
396+
[
397+
"test_id",
398+
"junit_status",
399+
"cov_status",
400+
"n_files",
401+
"n_engine_files",
402+
"n_engine_body_lines",
403+
"context_key",
404+
]
405+
)
393406
for r in records:
394-
w.writerow([
395-
r.test_id, r.junit_status, r.cov_status, r.n_files,
396-
r.n_engine_files, r.n_engine_body_lines, r.context_key,
397-
])
407+
w.writerow(
408+
[
409+
r.test_id,
410+
r.junit_status,
411+
r.cov_status,
412+
r.n_files,
413+
r.n_engine_files,
414+
r.n_engine_body_lines,
415+
r.context_key,
416+
]
417+
)
398418

399419

400420
def write_json(path: Path, records, save_errs, db_path):
@@ -413,10 +433,16 @@ def write_json(path: Path, records, save_errs, db_path):
413433
# every run; the rest are only shown when non-zero, to keep the summary
414434
# uncluttered when the relevant signal isn't present in this run.
415435
_REPORTED_STATUSES = (
416-
"OK", "SUBPROCESS_LOST", "MAIN_ONLY", "EMPTY",
436+
"OK",
437+
"SUBPROCESS_LOST",
438+
"MAIN_ONLY",
439+
"EMPTY",
417440
"TEST_FAILED",
418-
"NO_PRODUCT_CODE", "FAILED_EARLY",
419-
"MISSING", "MISSING_LOST", "MISSING_NO_PLUGIN",
441+
"NO_PRODUCT_CODE",
442+
"FAILED_EARLY",
443+
"MISSING",
444+
"MISSING_LOST",
445+
"MISSING_NO_PLUGIN",
420446
)
421447
_ALWAYS_SHOW = frozenset({"OK", "SUBPROCESS_LOST", "MAIN_ONLY", "EMPTY"})
422448

@@ -441,38 +467,41 @@ def print_summary(records, save_errs):
441467
if not examples:
442468
continue
443469
n_show = min(5, len(examples))
444-
print(f"\nFirst {n_show} {status} tests "
445-
f"(of {len(examples)}):")
470+
print(f"\nFirst {n_show} {status} tests (of {len(examples)}):")
446471
for r in examples[:n_show]:
447-
print(f" {r.test_id} "
448-
f"(files={r.n_files}, engine={r.n_engine_files}, "
449-
f"body_lines={r.n_engine_body_lines})")
472+
print(
473+
f" {r.test_id} "
474+
f"(files={r.n_files}, engine={r.n_engine_files}, "
475+
f"body_lines={r.n_engine_body_lines})"
476+
)
450477

451478

452479
# --- main ------------------------------------------------------------------
453480

481+
454482
def main(argv=None):
455483
p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
456-
p.add_argument("--db", type=Path, required=True,
457-
help="combined .coverage.<stage> DB")
458-
p.add_argument("--junit", type=Path,
459-
help="pytest junit.xml (enables MISSING detection)")
460-
p.add_argument("--pytest-log", type=Path,
461-
help="pytest stdout/stderr log (scanned for save errors)")
462-
p.add_argument("--sentinel-dir", type=Path,
463-
help="directory of per-test sentinel files written by "
464-
"cbts_plugin (enables MISSING_LOST vs "
465-
"MISSING_NO_PLUGIN split)")
466-
p.add_argument("--out-csv", type=Path,
467-
help="per-test CSV report (recommended for triage)")
468-
p.add_argument("--out-json", type=Path,
469-
help="per-test JSON report (recommended for trend metrics)")
484+
p.add_argument("--db", type=Path, required=True, help="combined .coverage.<stage> DB")
485+
p.add_argument("--junit", type=Path, help="pytest junit.xml (enables MISSING detection)")
486+
p.add_argument(
487+
"--pytest-log", type=Path, help="pytest stdout/stderr log (scanned for save errors)"
488+
)
489+
p.add_argument(
490+
"--sentinel-dir",
491+
type=Path,
492+
help="directory of per-test sentinel files written by "
493+
"cbts_plugin (enables MISSING_LOST vs "
494+
"MISSING_NO_PLUGIN split)",
495+
)
496+
p.add_argument("--out-csv", type=Path, help="per-test CSV report (recommended for triage)")
497+
p.add_argument(
498+
"--out-json", type=Path, help="per-test JSON report (recommended for trend metrics)"
499+
)
470500
args = p.parse_args(argv)
471501

472502
# ---- Hard signals on the DB ----
473503
if not args.db.exists() or args.db.stat().st_size == 0:
474-
print(f"FATAL: coverage DB {args.db} missing or empty",
475-
file=sys.stderr)
504+
print(f"FATAL: coverage DB {args.db} missing or empty", file=sys.stderr)
476505
return 2
477506

478507
contexts = load_contexts(args.db)
@@ -507,22 +536,20 @@ def main(argv=None):
507536
continue # NOT_RUN -- not a coverage gap
508537
ctx_name = match_test_to_context(test_id, contexts)
509538
ctx_info = contexts.get(ctx_name) if ctx_name else None
510-
has_sentinel = (
511-
_nodeid_sentinel_name(test_id) in sentinels
512-
if sentinels_in_use else None
513-
)
539+
has_sentinel = _nodeid_sentinel_name(test_id) in sentinels if sentinels_in_use else None
514540
if ctx_name:
515541
matched_contexts.add(ctx_name)
516-
records.append(TestRecord(
517-
test_id=test_id,
518-
junit_status=status,
519-
cov_status=classify(ctx_info, has_sentinel,
520-
junit_status=status, test_id=test_id),
521-
n_files=ctx_info["n_files"] if ctx_info else 0,
522-
n_engine_files=ctx_info["n_engine"] if ctx_info else 0,
523-
n_engine_body_lines=ctx_info["n_engine_body"] if ctx_info else 0,
524-
context_key=ctx_name,
525-
))
542+
records.append(
543+
TestRecord(
544+
test_id=test_id,
545+
junit_status=status,
546+
cov_status=classify(ctx_info, has_sentinel, junit_status=status, test_id=test_id),
547+
n_files=ctx_info["n_files"] if ctx_info else 0,
548+
n_engine_files=ctx_info["n_engine"] if ctx_info else 0,
549+
n_engine_body_lines=ctx_info["n_engine_body"] if ctx_info else 0,
550+
context_key=ctx_name,
551+
)
552+
)
526553

527554
# Contexts with no matching junit row: still report them. Parametrized
528555
# tests, multi-call hooks, and fixture-level captures can land here.
@@ -531,15 +558,17 @@ def main(argv=None):
531558
for ctx_name, ctx_info in contexts.items():
532559
if ctx_name in matched_contexts:
533560
continue
534-
records.append(TestRecord(
535-
test_id=ctx_name,
536-
junit_status="NO_JUNIT_MATCH" if junit_tests else "unknown",
537-
cov_status=classify(ctx_info, has_sentinel=None, test_id=ctx_name),
538-
n_files=ctx_info["n_files"],
539-
n_engine_files=ctx_info["n_engine"],
540-
n_engine_body_lines=ctx_info["n_engine_body"],
541-
context_key=ctx_name,
542-
))
561+
records.append(
562+
TestRecord(
563+
test_id=ctx_name,
564+
junit_status="NO_JUNIT_MATCH" if junit_tests else "unknown",
565+
cov_status=classify(ctx_info, has_sentinel=None, test_id=ctx_name),
566+
n_files=ctx_info["n_files"],
567+
n_engine_files=ctx_info["n_engine"],
568+
n_engine_body_lines=ctx_info["n_engine_body"],
569+
context_key=ctx_name,
570+
)
571+
)
543572

544573
# ---- Outputs ----
545574
if args.out_csv:

0 commit comments

Comments
 (0)