style(s51): ruff format hitl module + tests

Gate: ruff format --check . clean.
This commit is contained in:
Kjell Tore Guttormsen 2026-07-15 19:43:41 +02:00
commit 5807ac428c
3 changed files with 48 additions and 11 deletions

View file

@ -261,7 +261,9 @@ def main(argv: list[str] | None = None) -> int:
sub = parser.add_subparsers(dest="command", required=True) sub = parser.add_subparsers(dest="command", required=True)
p_pending = sub.add_parser("pending", help="list proposals still awaiting an expert verdict") p_pending = sub.add_parser("pending", help="list proposals still awaiting an expert verdict")
p_pending.add_argument("--outbox-dir", required=True, help="run outbox (proposal/outcome files)") p_pending.add_argument(
"--outbox-dir", required=True, help="run outbox (proposal/outcome files)"
)
p_pending.add_argument("--verdict-dir", required=True, help="expert verdict inbox") p_pending.add_argument("--verdict-dir", required=True, help="expert verdict inbox")
p_route = sub.add_parser("route", help="route pending proposals to experts by cost-code prefix") p_route = sub.add_parser("route", help="route pending proposals to experts by cost-code prefix")
@ -287,7 +289,9 @@ def main(argv: list[str] | None = None) -> int:
print(f"{p.run_id} {p.verdict_id} → UNROUTABLE") print(f"{p.run_id} {p.verdict_id} → UNROUTABLE")
else: else:
suffix = " AMBIGUOUS" if routed.ambiguous else "" suffix = " AMBIGUOUS" if routed.ambiguous else ""
print(f"{p.run_id} {p.verdict_id}{routed.expert} [dim:{routed.dimension_id}]{suffix}") print(
f"{p.run_id} {p.verdict_id}{routed.expert} [dim:{routed.dimension_id}]{suffix}"
)
return 0 return 0

View file

@ -50,11 +50,18 @@ def _make_validated(measure: str, codes: list[str], claimed: float = 200.0) -> V
proposal = SavingsProposal( proposal = SavingsProposal(
project_id="P1", measure=measure, affected_items=items, claimed_saving_nok=claimed project_id="P1", measure=measure, affected_items=items, claimed_saving_nok=claimed
) )
return ValidatedProposal(proposal=proposal, p10=100.0, p50=150.0, p90=200.0, nominal_feasible=180.0) return ValidatedProposal(
proposal=proposal, p10=100.0, p50=150.0, p90=200.0, nominal_feasible=180.0
)
def _write_proposal( def _write_proposal(
outbox: Path, run_id: str, *, verdict_id: str, measure: str = "LED-retrofit", codes: list[str] | None = None outbox: Path,
run_id: str,
*,
verdict_id: str,
measure: str = "LED-retrofit",
codes: list[str] | None = None,
) -> None: ) -> None:
"""Persist one run's outbox pair via the real writer, keyed on ``verdict_id``.""" """Persist one run's outbox pair via the real writer, keyed on ``verdict_id``."""
write_outbox( write_outbox(
@ -276,8 +283,12 @@ def test_route_ambiguous_uses_sorted_first_tie_break(tmp_path: Path) -> None:
_write_proposal(outbox, "run-1", verdict_id="v1", codes=["05.2"]) _write_proposal(outbox, "run-1", verdict_id="v1", codes=["05.2"])
config = hitl.RoutingConfig( config = hitl.RoutingConfig(
entries=[ entries=[
hitl.RoutingEntry(id="b-energi", allowed_code_prefixes=frozenset({"05"}), expert="Beta"), hitl.RoutingEntry(
hitl.RoutingEntry(id="a-energi", allowed_code_prefixes=frozenset({"05"}), expert="Alpha"), id="b-energi", allowed_code_prefixes=frozenset({"05"}), expert="Beta"
),
hitl.RoutingEntry(
id="a-energi", allowed_code_prefixes=frozenset({"05"}), expert="Alpha"
),
] ]
) )
r = hitl.route(str(outbox), str(inbox), config)[0] r = hitl.route(str(outbox), str(inbox), config)[0]
@ -338,7 +349,15 @@ def test_cli_route_lists_expert_and_unroutable(
tmp_path, {"entries": [{"id": "energi", "allowed_code_prefixes": ["05"], "expert": "Ola"}]} tmp_path, {"entries": [{"id": "energi", "allowed_code_prefixes": ["05"], "expert": "Ola"}]}
) )
rc = hitl.main( rc = hitl.main(
["route", "--outbox-dir", str(outbox), "--verdict-dir", str(inbox), "--routing-config", str(cfg)] [
"route",
"--outbox-dir",
str(outbox),
"--verdict-dir",
str(inbox),
"--routing-config",
str(cfg),
]
) )
assert rc == 0 assert rc == 0
out = capsys.readouterr().out out = capsys.readouterr().out
@ -355,7 +374,15 @@ def test_cli_route_malformed_config_returns_rc1(
_write_proposal(outbox, "run-1", verdict_id="v1") _write_proposal(outbox, "run-1", verdict_id="v1")
bad_cfg = _write_config(tmp_path, {"entries": [{"id": "energi"}]}) # missing required expert bad_cfg = _write_config(tmp_path, {"entries": [{"id": "energi"}]}) # missing required expert
rc = hitl.main( rc = hitl.main(
["route", "--outbox-dir", str(outbox), "--verdict-dir", str(inbox), "--routing-config", str(bad_cfg)] [
"route",
"--outbox-dir",
str(outbox),
"--verdict-dir",
str(inbox),
"--routing-config",
str(bad_cfg),
]
) )
assert rc == 1 assert rc == 1
captured = capsys.readouterr() captured = capsys.readouterr()

View file

@ -34,7 +34,9 @@ _PROVENANCE = ProvenanceStamp(
) )
def _write_proposal(outbox: Path, run_id: str, *, verdict_id: str, codes: list[str] | None = None) -> None: def _write_proposal(
outbox: Path, run_id: str, *, verdict_id: str, codes: list[str] | None = None
) -> None:
items = [AffectedItem(code=c, quantity=1000.0, unit_cost=1.0) for c in (codes or ["05.2"])] items = [AffectedItem(code=c, quantity=1000.0, unit_cost=1.0) for c in (codes or ["05.2"])]
proposal = SavingsProposal( proposal = SavingsProposal(
project_id="P1", measure="LED-retrofit", affected_items=items, claimed_saving_nok=200.0 project_id="P1", measure="LED-retrofit", affected_items=items, claimed_saving_nok=200.0
@ -155,7 +157,9 @@ def test_route_classification_is_load_bearing(tmp_path: Path) -> None:
config = hitl.RoutingConfig( config = hitl.RoutingConfig(
entries=[ entries=[
hitl.RoutingEntry(id="z-vei", allowed_code_prefixes=frozenset({"07"}), expert="Zeta"), hitl.RoutingEntry(id="z-vei", allowed_code_prefixes=frozenset({"07"}), expert="Zeta"),
hitl.RoutingEntry(id="a-energi", allowed_code_prefixes=frozenset({"05"}), expert="Alpha"), hitl.RoutingEntry(
id="a-energi", allowed_code_prefixes=frozenset({"05"}), expert="Alpha"
),
] ]
) )
_write_proposal(outbox, "run-A", verdict_id="vA", codes=["99.9"]) # matches nothing _write_proposal(outbox, "run-A", verdict_id="vA", codes=["99.9"]) # matches nothing
@ -270,4 +274,6 @@ def test_hitl_source_has_no_network_import() -> None:
imported |= {a.name.split(".")[0] for a in node.names} imported |= {a.name.split(".")[0] for a in node.names}
elif isinstance(node, ast.ImportFrom): elif isinstance(node, ast.ImportFrom):
imported.add((node.module or "").split(".")[0]) imported.add((node.module or "").split(".")[0])
assert imported & forbidden == set(), f"hitl must not import network libs: {imported & forbidden}" assert imported & forbidden == set(), (
f"hitl must not import network libs: {imported & forbidden}"
)