build(backend): close the lint gaps the E32 audit measured
ruff gains RUF100, PLW1510 and flake8-bugbear, every hit fixed rather than ignored. B008 stays on with FastAPI's Depends/Query declared immutable. basedpyright moves to standard mode, pytest to --strict-markers, and a hand run of pytest now requires the database unless SIFTLODE_TEST_REQUIRE_DB=0. PLW1510 found a real bug: the three ffprobe probes in plex/stream.py never looked at the exit status, so a probe that failed was read as the file's truth (an HDR source sent down the HW-safe path, a multi-audio file collapsed to one track, a subtitle offset taken from garbage) and the warning each except branch promises never fired. They now run with check=True.
This commit is contained in:
@@ -245,6 +245,9 @@ def _probe_video_kind(src: Path) -> str:
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
# A non-zero exit is a failed probe (CalledProcessError, a SubprocessError → the branch
|
||||
# below), not an answer: whatever it printed before refusing is not the file's truth.
|
||||
check=True,
|
||||
)
|
||||
except (subprocess.SubprocessError, OSError) as exc:
|
||||
# The safe kind is a real answer, but it is the answer for an 8-bit SDR source — a blind
|
||||
@@ -502,6 +505,9 @@ def _probe_audio_langs(src: Path) -> list[str]:
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
# A non-zero exit is a failed probe (CalledProcessError, a SubprocessError → the branch
|
||||
# below), not an answer: whatever it printed before refusing is not the file's truth.
|
||||
check=True,
|
||||
)
|
||||
return [ln.strip() for ln in out.stdout.splitlines()]
|
||||
except (subprocess.SubprocessError, OSError) as exc:
|
||||
@@ -615,6 +621,9 @@ def _probe_first_pts(seg: Path) -> float | None:
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
# A non-zero exit is a failed probe (CalledProcessError, a SubprocessError → the branch
|
||||
# below), not an answer: whatever it printed before refusing is not the file's truth.
|
||||
check=True,
|
||||
)
|
||||
for line in out.stdout.splitlines():
|
||||
tok = line.strip().strip(",")
|
||||
|
||||
@@ -162,7 +162,8 @@ def ffmpeg_to_vtt(src: str, sub_ord: int | None) -> str:
|
||||
"webvtt",
|
||||
"pipe:1",
|
||||
]
|
||||
r = subprocess.run(cmd, capture_output=True, timeout=EXTRACT_TIMEOUT_S)
|
||||
# check=False: the exit status is read on the next line, with ffmpeg's own stderr as the reason.
|
||||
r = subprocess.run(cmd, capture_output=True, timeout=EXTRACT_TIMEOUT_S, check=False)
|
||||
if r.returncode != 0 or not r.stdout:
|
||||
raise PlexError(
|
||||
(r.stderr or b"").decode("utf-8", "replace")[:200] or "ffmpeg subtitle convert failed"
|
||||
|
||||
@@ -273,7 +273,7 @@ def sync(db: Session) -> dict:
|
||||
# becomes filterable over successive runs (the cheap listing above only stored the top ~3).
|
||||
try:
|
||||
stats["people_enriched"] = _enrich_people_batch(db, plex)
|
||||
except Exception: # noqa: BLE001 — best-effort; never fail the sync over a backfill
|
||||
except Exception: # best-effort; never fail the sync over a backfill
|
||||
# With the traceback: a blind catch over a batch that fetches AND writes can be
|
||||
# a Plex shape change, a DB error or our own bug, and `%s` told them apart badly.
|
||||
log.exception("the Plex people-enrich batch failed")
|
||||
@@ -282,7 +282,7 @@ def sync(db: Session) -> dict:
|
||||
# successive runs. Only HW-decodable-codec transcodes are probed — the rest are SW by codec.
|
||||
try:
|
||||
stats["media_probed"] = _probe_media_batch(db, plex)
|
||||
except Exception: # noqa: BLE001 — best-effort; never fail the sync over a backfill
|
||||
except Exception: # best-effort; never fail the sync over a backfill
|
||||
log.exception("the Plex media-probe batch failed")
|
||||
# silent-ok: the return value IS the report. `{"skipped": …}` goes to the scheduler, which
|
||||
# logs the job result, and to the admin route, which answers it to the caller.
|
||||
@@ -296,7 +296,7 @@ def sync(db: Session) -> dict:
|
||||
# appear in ANY item's cast/directors — drop those rows, mirroring how Plex drops orphaned metadata.
|
||||
try:
|
||||
stats["people_pruned"] = people.prune_orphan_people(db)
|
||||
except Exception: # noqa: BLE001 — best-effort housekeeping; never fail the sync over it
|
||||
except Exception: # best-effort housekeeping; never fail the sync over it
|
||||
log.exception("the Plex people prune failed")
|
||||
log.info("Plex sync done: %s", stats)
|
||||
return stats
|
||||
|
||||
Reference in New Issue
Block a user