chore(v2): lint pass — black + ruff auto-fix + mypy regressions (#29 v1.1)

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:
Padreug 2026-05-31 15:50:14 +02:00
commit d448fab0d2
10 changed files with 249 additions and 352 deletions

View file

@ -42,7 +42,6 @@ from __future__ import annotations
import json
import time
from typing import Optional
from lnbits.core.crud.users import get_account
from lnbits.core.services.nip46_bunker_client import (
@ -172,8 +171,7 @@ async def _resolve_operator_signer(operator_user_id: str):
signer = resolve_signer(account)
except SignerError as exc:
raise SignerUnavailable(
f"signer resolve failed for operator {operator_user_id[:8]}...: "
f"{exc}"
f"signer resolve failed for operator {operator_user_id[:8]}...: " f"{exc}"
) from exc
if not signer.can_sign():
raise SignerUnavailable(
@ -185,9 +183,7 @@ async def _resolve_operator_signer(operator_user_id: str):
return account, signer
async def _sign_as_operator(
operator_user_id: str, event: dict
) -> Optional[dict]:
async def _sign_as_operator(operator_user_id: str, event: dict) -> dict | None:
"""Sign `event` using the operator's signer (LocalSigner or
RemoteBunkerSigner). Mutates `event` to add `created_at` (now),
`pubkey`, `id`, and `sig`.
@ -203,8 +199,7 @@ async def _sign_as_operator(
return await signer.sign_event(event)
except SignerUnavailableError as exc:
raise SignerUnavailable(
f"signer unavailable for operator {operator_user_id[:8]}...: "
f"{exc}"
f"signer unavailable for operator {operator_user_id[:8]}...: " f"{exc}"
) from exc
@ -231,13 +226,8 @@ async def _nip44_encrypt_via_signer(
try:
return await signer.nip44_encrypt(plaintext, peer_pubkey_hex)
except SignerUnavailableError:
if (
account.signer_type == "LocalSigner"
and account.prvkey
):
return _nip44_local_encrypt(
plaintext, account.prvkey, peer_pubkey_hex
)
if account.signer_type == "LocalSigner" and account.prvkey:
return _nip44_local_encrypt(plaintext, account.prvkey, peer_pubkey_hex)
# ClientSideOnly, or RemoteBunkerSigner with bunker comms failure
# at config time — re-raise without wrapping; caller maps it.
raise
@ -251,13 +241,8 @@ async def _nip44_decrypt_via_signer(
try:
return await signer.nip44_decrypt(ciphertext, peer_pubkey_hex)
except SignerUnavailableError:
if (
account.signer_type == "LocalSigner"
and account.prvkey
):
return _nip44_local_decrypt(
ciphertext, account.prvkey, peer_pubkey_hex
)
if account.signer_type == "LocalSigner" and account.prvkey:
return _nip44_local_decrypt(ciphertext, account.prvkey, peer_pubkey_hex)
raise
@ -411,9 +396,7 @@ async def decrypt_and_parse_state_event(
f"bunker rejected nip44_decrypt (policy / MAC / config): {exc}"
) from exc
except SignerUnavailableError as exc:
raise CassetteEventDecodeError(
f"signer cannot nip44-decrypt: {exc}"
) from exc
raise CassetteEventDecodeError(f"signer cannot nip44-decrypt: {exc}") from exc
except Nip44Error as exc:
# Hand-rolled LocalSigner fallback path (transitional) — MAC fail
# / version mismatch / length issue.
@ -424,9 +407,7 @@ async def decrypt_and_parse_state_event(
# coincurve raises ValueError on a malformed pubkey hex (only
# reachable via the LocalSigner fallback path; the bunker handles
# pubkey validation server-side).
raise CassetteEventDecodeError(
f"sender pubkey is malformed: {exc}"
) from exc
raise CassetteEventDecodeError(f"sender pubkey is malformed: {exc}") from exc
try:
raw = json.loads(plaintext)
@ -437,7 +418,7 @@ async def decrypt_and_parse_state_event(
try:
return PublishCassettesPayload(**raw)
except Exception as exc: # noqa: BLE001 — Pydantic raises various subclasses
except Exception as exc:
raise CassetteEventDecodeError(
f"payload didn't validate as PublishCassettesPayload: {exc}"
) from exc