style(s51): ruff format hitl module + tests
Gate: ruff format --check . clean.
This commit is contained in:
parent
eaca95a325
commit
5807ac428c
3 changed files with 48 additions and 11 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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}"
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue