From 49055a8bf1abce179c9b667c1970bc8ee31066ee Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 7 May 2026 07:50:34 +0300 Subject: [PATCH] =?UTF-8?q?fix(ci):=20restore=20develop=20CI=20green=20?= =?UTF-8?q?=E2=80=94=20ruff=20T20=20exemption=20+=20ADAR1000=20setter=20re?= =?UTF-8?q?gex=20extension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two independent root causes landed together in the recent develop merge burst, leaving CI red on every commit since. Both fixes are narrow parser/ config updates; no code logic changes. 1. Ruff T201 violation in 8_Utils/Python/LUT.py:24 The recent restoration of `print(f"8'd{val},")` (replacing `pass`) made the LUT generator functional again, but the file is not in pyproject's per-file-ignores so ruff's T20 rule flags it. Add a narrow per-file- ignore for T20 specifically scoped to LUT.py. 2. Five tests in TestTier1Adar1000ChannelRegisterRoundTrip The recent SPI/ADC error-propagation refactor on ADAR1000_Manager.cpp changed the four setters adarSet{Rx,Tx}{Phase,VgaGain} from `void` to `bool` returns AND introduced the `ok = setter(args) && ok` error-chain idiom at internal call sites. The test class's parser regexes were authored for the pre-refactor convention. Two regex extensions: * Body parser: `void\s+...` -> `(?:void|bool)\s+...` so bodies are found under either return-type convention. * Caller finder: `\)\s*;` -> `\)(?:\s*&&\s*\w+)*\s*;` so the error-chain idiom is matched alongside standalone calls. Body extraction logic, REG_CHn_XXX + regex, symbolic AST evaluation, round-trip strict-equality, and stride detection are all unchanged. The two regex extensions only acknowledge the new C++ conventions introduced by the SPI/ADC refactor. Verified locally: - `uv run ruff check .` returns 0 errors. - `uv run pytest 9_Firmware/tests/cross_layer/test_cross_layer_contract.py` passes 51 tests + 5 skipped (Tier2VerilogCosim local-only, requires iverilog which is installed in CI). - `uv run pytest 9_Firmware/9_3_GUI/test_v7.py` passes 83 tests + 3 skipped (no regression). --- .../cross_layer/test_cross_layer_contract.py | 23 +++++++++++++++---- pyproject.toml | 3 +++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/9_Firmware/tests/cross_layer/test_cross_layer_contract.py b/9_Firmware/tests/cross_layer/test_cross_layer_contract.py index aed68a3..f8bce65 100644 --- a/9_Firmware/tests/cross_layer/test_cross_layer_contract.py +++ b/9_Firmware/tests/cross_layer/test_cross_layer_contract.py @@ -768,14 +768,21 @@ def _safe_eval_int_expr(expr, **variables): def _extract_adar_helper_sites(manager_cpp, setter_names): """ - For each setter, locate the body of ``void ADAR1000Manager::`` - and return a list of (setter, base_register, offset_expr_c, stride) - for every ``REG_CHn_XXX + `` memory-address assignment. + For each setter, locate the body of ``void`` or ``bool`` + ``ADAR1000Manager::`` and return a list of (setter, + base_register, offset_expr_c, stride) for every ``REG_CHn_XXX + + `` memory-address assignment. + + The setters originally returned ``void``. After the SPI/ADC error- + propagation refactor they return ``bool`` so callers can observe + write/read failures. The body form (``REG_CHn_XXX + ``, + ``(channel - 1) & 0x03`` mask, ``* 2`` stride for phase I/Q) is + unchanged. """ sites = [] for setter in setter_names: m = re.search( - rf"void\s+ADAR1000Manager::{setter}\s*\([^)]*\)\s*\{{(.+?)^\}}", + rf"(?:void|bool)\s+ADAR1000Manager::{setter}\s*\([^)]*\)\s*\{{(.+?)^\}}", manager_cpp, re.MULTILINE | re.DOTALL, ) @@ -818,9 +825,15 @@ def _extract_adar_caller_sites(sources, setter): call sites fit on one line; a future multi-line refactor would drop callers from the scan, which the round-trip test surfaces loudly via `assert callers` (rather than silently missing a site). + + Two terminating forms are accepted: + * ``setter(args);`` — standalone call. + * ``ok = setter(args) && ok;`` (one or more chains) — error-propagation + idiom introduced by the SPI/ADC refactor where setters return + ``bool`` and callers AND the result into a running success flag. """ out = [] - call_re = re.compile(rf"\b{setter}\s*\(([^;]*?)\)\s*;") + call_re = re.compile(rf"\b{setter}\s*\(([^;]*?)\)(?:\s*&&\s*\w+)*\s*;") for filename, text in sources: for line_no, line in enumerate(text.splitlines(), start=1): # Skip method definition / declaration lines. diff --git a/pyproject.toml b/pyproject.toml index 4f6ea09..274ca8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,3 +49,6 @@ select = [ "test_*.py" = ["ARG", "T20", "ERA"] # Re-export modules: unused imports are intentional "v7/hardware.py" = ["F401"] +# 8_Utils/Python/LUT.py is a single-purpose Verilog LUT generator whose only +# output is `print(f"8'd{val},")` per the file's docstring intent. +"8_Utils/Python/LUT.py" = ["T20"]