Skip to content

Commit 3dba893

Browse files
committed
style(test): ruff noqa: B010 setattr sweep on hardening modules
Sibling session's hardening money contract commits (b1d54fe, e2f413b and the rest of the 8-commit hardening series) used direct attribute assignment (`fn._nullrun_extractor = impact`) for stamping the sensitive-call extractor onto the wrapped function. ruff's B010 rule fires on these — `setattr` with a constant attribute name is the same as direct assignment, ruff says, so use the simpler form. This commit applies ruff's autofix on the leftover hardening files (test_money_hardening, test_business_impact, etc.) to keep `ruff check tests/` green without re-introducing the mypy `attr-defined` error on `fn._nullrun_extractor = impact` (which is why decorators.py uses `setattr` + `# noqa: B010` in the same commit as the 0.14.0 bump). Mechanical ruff --fix output. No behaviour change. Verified: ruff check src/ tests/ → All checks passed mypy src/ → Success: no issues found in 36 source files
1 parent 523d137 commit 3dba893

8 files changed

Lines changed: 26 additions & 40 deletions

src/nullrun/business_impact.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from dataclasses import dataclass, field
3636
from typing import Any, Optional
3737

38-
3938
DIGEST_PREFIX = b"nullrun/v1/business_impact:"
4039

4140

@@ -130,7 +129,7 @@ def to_wire_dict(self) -> dict[str, Any]:
130129
}
131130

132131

133-
def business_impact_to_dict(impact: "BusinessImpact") -> dict[str, Any]:
132+
def business_impact_to_dict(impact: BusinessImpact) -> dict[str, Any]:
134133
"""Top-level wire dict for `GateRequest.business_impact`.
135134
136135
Returns an empty string key discriminator for the backend's
@@ -173,7 +172,7 @@ def money(
173172
direction: str,
174173
amount_minor: int,
175174
currency: str = "USD",
176-
) -> "BusinessImpact":
175+
) -> BusinessImpact:
177176
m = MoneyImpact(
178177
direction=direction,
179178
amount_minor=amount_minor,

tests/test_approval_money_flow.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ class that returns exactly what `gate_internal` would return
3939
import pytest
4040

4141
from nullrun.business_impact import (
42-
BusinessImpact,
43-
MoneyImpact,
4442
INFLOW,
4543
OUTFLOW,
44+
BusinessImpact,
45+
MoneyImpact,
4646
compute_action_digest,
4747
)
4848
from nullrun.extractor import (
@@ -71,15 +71,15 @@ class ApprovalSimulator:
7171
backend's `gate_internal` output for the same inputs.
7272
"""
7373

74-
def __init__(self, *, stored_digest: Optional[str], expires_in: int = 600,
74+
def __init__(self, *, stored_digest: str | None, expires_in: int = 600,
7575
consumed: bool = False, status: str = "APPROVED") -> None:
7676
self.stored_digest = stored_digest
7777
self.expires_at = time.monotonic() + expires_in
7878
self.consumed = consumed
7979
self.status = status
80-
self.last_decision: Optional[str] = None
80+
self.last_decision: str | None = None
8181

82-
def decide(self, business_impact: Optional[BusinessImpact]) -> str:
82+
def decide(self, business_impact: BusinessImpact | None) -> str:
8383
"""Mirror `gate_internal` grant-consume path.
8484
8585
Returns the wire-level decision: "allow", "block:..." or

tests/test_business_impact.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,15 @@
4040
import pytest
4141

4242
from nullrun.business_impact import (
43-
BusinessImpact,
4443
INFLOW,
45-
MoneyImpact,
4644
OUTFLOW,
45+
BusinessImpact,
46+
MoneyImpact,
4747
business_impact_to_dict,
4848
compute_action_digest,
4949
)
5050
from nullrun.extractor import money_outflow
5151

52-
5352
# Canonical pin shared with the backend's golden test. Any
5453
# change to the canonical-JSON algorithm on either side breaks
5554
# this test before a customer runtime sees the regression.

tests/test_drift_fixes_2026_07_04.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def test_enrich_event_stamps_parent_trace_id_from_contextvar(self):
251251
must stamp the field from the active span contextvar so the
252252
wire shape is consistent regardless of caller integration.
253253
"""
254-
from nullrun.context import set_trace_id, clear_trace_id
254+
from nullrun.context import clear_trace_id, set_trace_id
255255
from nullrun.runtime import NullRunRuntime
256256

257257
# Pin the trace contextvar to a known value (mimics
@@ -297,7 +297,7 @@ def test_enrich_event_contextvar_overrides_caller_set_parent_trace_id(self):
297297
trace_id=cccccccc-... parent_trace_id=NULL on backend
298298
cost_events).
299299
"""
300-
from nullrun.context import set_trace_id, clear_trace_id
300+
from nullrun.context import clear_trace_id, set_trace_id
301301
from nullrun.runtime import NullRunRuntime
302302

303303
# Contextvar holds the chain's trace. Even though the
@@ -360,7 +360,7 @@ def test_enrich_event_omits_empty_string_parent_trace_id(self):
360360
parser would otherwise reject the field or store empty
361361
string in a UUID column, depending on path).
362362
"""
363-
from nullrun.context import set_trace_id, clear_trace_id
363+
from nullrun.context import clear_trace_id, set_trace_id
364364
from nullrun.runtime import NullRunRuntime
365365

366366
set_trace_id("") # boundary value
@@ -386,7 +386,7 @@ def test_enrich_event_parent_trace_id_matches_existing_trace_id_field(
386386
the backend's JOIN from drifting — see
387387
``db/mod.rs::get_execution_records_for_workflow``.
388388
"""
389-
from nullrun.context import set_trace_id, clear_trace_id
389+
from nullrun.context import clear_trace_id, set_trace_id
390390
from nullrun.runtime import NullRunRuntime
391391

392392
set_trace_id("77777777-8888-9999-aaaa-bbbbbbbbbbbb")
@@ -522,7 +522,7 @@ def test_enrich_event_sets_parent_trace_id_when_chain_contextvar_set(self):
522522
parent_trace_id=NULL on the prod VPS during the diagnostic
523523
run on 2026-07-12 08:51 UTC.
524524
"""
525-
from nullrun.context import set_trace_id, clear_trace_id
525+
from nullrun.context import clear_trace_id, set_trace_id
526526
from nullrun.runtime import NullRunRuntime
527527
set_trace_id("cccccccc-1111-2222-3333-444444444444")
528528
try:
@@ -553,7 +553,7 @@ def test_enrich_event_parent_trace_id_matches_trace_id_in_chain_mode(self):
553553
the event sits inside the chain contextvar (chain trace
554554
spans share the same trace_id across child spans).
555555
"""
556-
from nullrun.context import set_trace_id, clear_trace_id
556+
from nullrun.context import clear_trace_id, set_trace_id
557557
from nullrun.runtime import NullRunRuntime
558558
set_trace_id("99999999-aaaa-bbbb-cccc-000000000000")
559559
try:

tests/test_money_hardening.py

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,23 @@
4242

4343
import pytest
4444

45+
from nullrun.business_impact import (
46+
OUTFLOW,
47+
BusinessImpact,
48+
compute_action_digest,
49+
)
4550
from nullrun.extractor import (
51+
UNIT_MAJOR,
52+
UNIT_MINOR,
4653
InvalidCurrencyError,
4754
InvalidMoneyAmountError,
4855
InvalidMoneyPrecisionError,
49-
UNIT_MAJOR,
50-
UNIT_MINOR,
5156
_to_minor_units,
5257
business_cap_minor,
5358
currency_minor_digits,
5459
money_outflow,
5560
normalize_currency,
5661
)
57-
from nullrun.business_impact import (
58-
BusinessImpact,
59-
OUTFLOW,
60-
compute_action_digest,
61-
)
62-
6362

6463
GOLDEN_HEX_USD_50_DOLLARS_OUTFLOW = (
6564
"dfc96387ca539b7130caebe705e042f2e34e52ab44352ae5e527bcef64f0df27"
@@ -277,37 +276,31 @@ class TestCurrencyWhitelist:
277276
"""
278277

279278
def test_known_currency_exact(self) -> None:
280-
from nullrun.extractor import normalize_currency
281279
for code in ("USD", "EUR", "JPY", "KWD", "BHD", "OMR",
282280
"GBP", "CHF", "CAD", "AUD"):
283281
assert normalize_currency(code) == code
284282

285283
def test_lowercase_currency_rejected(self) -> None:
286-
from nullrun.extractor import normalize_currency
287284
with pytest.raises(InvalidCurrencyError) as info:
288285
normalize_currency("usd")
289286
assert info.value.received == "usd"
290287
assert "uppercase" in str(info.value)
291288

292289
def test_mixed_case_currency_rejected(self) -> None:
293-
from nullrun.extractor import normalize_currency
294290
with pytest.raises(InvalidCurrencyError) as info:
295291
normalize_currency("Usd")
296292
assert info.value.received == "Usd"
297293

298294
def test_four_letter_currency_rejected(self) -> None:
299-
from nullrun.extractor import normalize_currency
300295
with pytest.raises(InvalidCurrencyError) as info:
301296
normalize_currency("USDX")
302297
assert "length 4" in str(info.value) or "3-letter" in str(info.value)
303298

304299
def test_empty_currency_rejected(self) -> None:
305-
from nullrun.extractor import normalize_currency
306300
with pytest.raises(InvalidCurrencyError):
307301
normalize_currency("")
308302

309303
def test_digits_in_currency_rejected(self) -> None:
310-
from nullrun.extractor import normalize_currency
311304
with pytest.raises(InvalidCurrencyError):
312305
normalize_currency("US1")
313306

@@ -328,12 +321,10 @@ def test_currency_minor_digits_known_value_exact(self) -> None:
328321
assert currency_minor_digits("KWD") == 3
329322

330323
def test_business_cap_lookup_propagates_currency_error(self) -> None:
331-
from nullrun.extractor import business_cap_minor
332324
with pytest.raises(InvalidCurrencyError):
333325
business_cap_minor("XYZ")
334326

335327
def test_business_cap_known_value_exact(self) -> None:
336-
from nullrun.extractor import business_cap_minor
337328
assert business_cap_minor("USD") == 100_000_000
338329
assert business_cap_minor("JPY") == 100_000_000
339330
assert business_cap_minor("KWD") == 100_000_000

tests/test_sensitive_extractor.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,15 @@
2222

2323
import pytest
2424

25+
from nullrun._registry import get_registry
2526
from nullrun.business_impact import (
26-
BusinessImpact,
2727
OUTFLOW,
28+
BusinessImpact,
2829
compute_action_digest,
2930
)
30-
from nullrun.extractor import money_outflow
3131
from nullrun.decorators import _enforce_sensitive_tool
32+
from nullrun.extractor import money_outflow
3233
from nullrun.runtime import NullRunRuntime
33-
from nullrun._registry import get_registry
34-
3534

3635
# ---------------------------------------------------------------------------
3736
# Wire payload capture

tests/test_units_discriminator.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@
3030

3131
import pytest
3232

33+
from nullrun.business_impact import INFLOW, OUTFLOW, BusinessImpact
3334
from nullrun.extractor import (
3435
UNIT_MAJOR,
3536
UNIT_MINOR,
3637
_to_minor_units,
3738
money_outflow,
3839
)
39-
from nullrun.business_impact import BusinessImpact, OUTFLOW, INFLOW
40-
4140

4241
# Golden cross-language pin shared with the backend's golden
4342
# test (and pinned in tests/test_business_impact.py). The wire

tests/test_webhook_backoff.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
from nullrun.actions import ActionHandler, WebhookConfig
3535

36-
3736
pytestmark = pytest.mark.slow_sleep
3837

3938

0 commit comments

Comments
 (0)