chore(v2): lint pass — black + ruff auto-fix + mypy regressions (#29 v1.1)
Some checks failed
ci.yml / chore(v2): lint pass — black + ruff auto-fix + mypy regressions (#29 v1.1) (pull_request) Failing after 0s
Some checks failed
ci.yml / chore(v2): lint pass — black + ruff auto-fix + mypy regressions (#29 v1.1) (pull_request) Failing after 0s
Pre-merge lint hygiene on the PR #30 touched files:
- `black` reformatted 9 files (cassette_transport, crud, models, tasks,
views_api, nip44, all 3 cassette test files, migrations). Cosmetic:
line lengths, trailing commas, multi-line argument layout.
- `ruff check --fix` cleared 176 of 202 errors auto-fixed. Mostly
`UP006` `typing.Optional` → `| None` modernization, `I001` import
sort order, `UP035` typing-extensions cleanup.
- Two new mypy regressions introduced by the migration commit dcb7de0
fixed:
- `crud.py:apply_bootstrap_state` — annotated `existing_first: dict
| None` on the dedup fetch.
- `tasks.py:_cassette_consumer_tick` — `# type: ignore[arg-type]` on
the `nostr_client.relay_manager.add_subscription` call; nostrclient's
upstream typing declares `list[str]` for filters but the actual
Nostr protocol takes `list[<filter-dict>]`. The runtime accepts it
(live smoke at 13:43Z dispatched `nip44_decrypt` cleanly through
this subscription); the typing mismatch is upstream's.
Remaining lint state, intentionally not addressed in this commit
(all pre-existing baseline, not regressions):
- 8 mypy errors in `calculations.py` + the unchanged-by-this-PR parts
of `crud.py` — pre-existing on v2-bitspire.
- 26 ruff style warnings: 14 are N805 false-positives on Pydantic
validators (`cls` first-arg is correct for `@validator`-decorated
methods); 4 are N818 exception-name-suffix preferences on my new
exception classes (renaming would touch many call sites; keep
`OperatorIdentityMissing` / `SignerUnavailable` / `RelayUnavailable`
/ `_NostrclientUnavailable` as-is for clarity); 5 are E501 line-too-
long on docstrings (the long lines are formatted for clarity);
1 RUF002 unicode-minus in a docstring.
Tests: 155 passed, 1 pre-existing async-plugin failure unchanged.
Live smoke (both publish + consume directions through the bunker)
unaffected — this is purely a code-style pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dcb7de0c27
commit
d448fab0d2
10 changed files with 249 additions and 352 deletions
46
tasks.py
46
tasks.py
|
|
@ -25,7 +25,6 @@
|
|||
# sat-amount invariants (range/sum).
|
||||
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
|
||||
from lnbits.core.models import Payment
|
||||
from lnbits.tasks import register_invoice_listener
|
||||
|
|
@ -126,9 +125,7 @@ async def _handle_payment(payment: Payment) -> None:
|
|||
# stamp is missing, SettlementInvariantError on any range/sum
|
||||
# breach.
|
||||
super_config = await get_super_config()
|
||||
super_fee_fraction = (
|
||||
float(super_config.super_fee_fraction) if super_config else 0.0
|
||||
)
|
||||
super_fee_fraction = float(super_config.super_fee_fraction) if super_config else 0.0
|
||||
try:
|
||||
data = parse_settlement(
|
||||
machine=machine,
|
||||
|
|
@ -195,9 +192,7 @@ async def _handle_payment(payment: Payment) -> None:
|
|||
task.add_done_callback(_inflight_distributions.discard)
|
||||
|
||||
|
||||
async def _record_rejected(
|
||||
payment: Payment, machine: Machine, exc: Exception
|
||||
) -> None:
|
||||
async def _record_rejected(payment: Payment, machine: Machine, exc: Exception) -> None:
|
||||
"""Insert a minimal `dca_settlements` row with `status='rejected'` and
|
||||
the exception message for operator forensics.
|
||||
|
||||
|
|
@ -288,7 +283,7 @@ async def wait_for_cassette_state_events() -> None:
|
|||
"satmachineadmin v2: cassette bootstrap consumer starting "
|
||||
f"(sub_id={CASSETTE_BOOTSTRAP_SUB_ID})"
|
||||
)
|
||||
current_filter_key: Optional[str] = None
|
||||
current_filter_key: str | None = None
|
||||
while True:
|
||||
try:
|
||||
current_filter_key = await _cassette_consumer_tick(current_filter_key)
|
||||
|
|
@ -304,8 +299,7 @@ async def wait_for_cassette_state_events() -> None:
|
|||
await asyncio.sleep(_CASSETTE_BACKOFF_S)
|
||||
except Exception as exc: # listener must never die
|
||||
logger.error(
|
||||
f"satmachineadmin: cassette consumer loop error (continuing): "
|
||||
f"{exc}"
|
||||
f"satmachineadmin: cassette consumer loop error (continuing): " f"{exc}"
|
||||
)
|
||||
await asyncio.sleep(_CASSETTE_POLL_INTERVAL_S)
|
||||
|
||||
|
|
@ -316,7 +310,7 @@ class _NostrclientUnavailable(Exception):
|
|||
at any time."""
|
||||
|
||||
|
||||
async def _cassette_consumer_tick(current_filter_key: Optional[str]) -> str:
|
||||
async def _cassette_consumer_tick(current_filter_key: str | None) -> str:
|
||||
"""Single iteration of the bootstrap-consumer loop. Returns the filter
|
||||
key used this tick so the caller can detect filter-set changes.
|
||||
|
||||
|
|
@ -345,34 +339,34 @@ async def _cassette_consumer_tick(current_filter_key: Optional[str]) -> str:
|
|||
if filter_key != current_filter_key:
|
||||
if d_tags:
|
||||
filters = [{"kinds": [30078], "#d": d_tags}]
|
||||
# nostrclient's add_subscription is typed as list[str] but the
|
||||
# actual relay protocol accepts list[Filter-dict] — type ignore
|
||||
# the upstream typing mismatch.
|
||||
nostr_client.relay_manager.add_subscription(
|
||||
CASSETTE_BOOTSTRAP_SUB_ID, filters
|
||||
CASSETTE_BOOTSTRAP_SUB_ID, filters # type: ignore[arg-type]
|
||||
)
|
||||
logger.info(
|
||||
"satmachineadmin: (re)registered cassette bootstrap "
|
||||
f"subscription with {len(d_tags)} d-tag(s)"
|
||||
)
|
||||
else:
|
||||
nostr_client.relay_manager.close_subscription(
|
||||
CASSETTE_BOOTSTRAP_SUB_ID
|
||||
)
|
||||
nostr_client.relay_manager.close_subscription(CASSETTE_BOOTSTRAP_SUB_ID)
|
||||
logger.info(
|
||||
"satmachineadmin: no active machines; closed cassette "
|
||||
"bootstrap subscription"
|
||||
)
|
||||
|
||||
inbound = NostrRouter.received_subscription_events.get(
|
||||
CASSETTE_BOOTSTRAP_SUB_ID
|
||||
)
|
||||
inbound = NostrRouter.received_subscription_events.get(CASSETTE_BOOTSTRAP_SUB_ID)
|
||||
if inbound:
|
||||
while inbound:
|
||||
event_message = inbound.pop(0)
|
||||
try:
|
||||
await _handle_cassette_state_event(
|
||||
event_message, get_machine_by_atm_pubkey_hex,
|
||||
event_message,
|
||||
get_machine_by_atm_pubkey_hex,
|
||||
apply_bootstrap_state,
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001 — log + skip
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
f"satmachineadmin: cassette state event handler "
|
||||
f"failed (skipping): {exc}"
|
||||
|
|
@ -450,9 +444,7 @@ async def _handle_cassette_state_event(
|
|||
return
|
||||
|
||||
try:
|
||||
account, signer = await _resolve_operator_signer(
|
||||
machine.operator_user_id
|
||||
)
|
||||
account, signer = await _resolve_operator_signer(machine.operator_user_id)
|
||||
except CassetteTransportError as exc:
|
||||
# OperatorIdentityMissing / SignerUnavailable — log + skip.
|
||||
logger.warning(
|
||||
|
|
@ -463,9 +455,7 @@ async def _handle_cassette_state_event(
|
|||
return
|
||||
|
||||
try:
|
||||
payload = await decrypt_and_parse_state_event(
|
||||
event_obj, account, signer
|
||||
)
|
||||
payload = await decrypt_and_parse_state_event(event_obj, account, signer)
|
||||
except CassetteEventTransientError as exc:
|
||||
logger.info(
|
||||
f"satmachineadmin: cassette state event for machine {machine.id} "
|
||||
|
|
@ -482,9 +472,7 @@ async def _handle_cassette_state_event(
|
|||
|
||||
event_id = event_obj.get("id", "")
|
||||
created_at_unix = event_obj.get("created_at", 0)
|
||||
event_created_at = _datetime.fromtimestamp(
|
||||
int(created_at_unix), tz=_timezone.utc
|
||||
)
|
||||
event_created_at = _datetime.fromtimestamp(int(created_at_unix), tz=_timezone.utc)
|
||||
|
||||
applied = await apply_bootstrap_state(
|
||||
machine.id, event_id, event_created_at, payload
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue