Skip to content

chore(mypy): make the type check clean and a hard gate#28

Merged
Guillain-RDCDE merged 2 commits into
mainfrom
chore/mypy-clean-and-gate
Jun 2, 2026
Merged

chore(mypy): make the type check clean and a hard gate#28
Guillain-RDCDE merged 2 commits into
mainfrom
chore/mypy-clean-and-gate

Conversation

@Guillain-RDCDE
Copy link
Copy Markdown
Owner

@

What & why

Follows up the flake8 gate (#27): mypy was running but advisory because
src/ carried 43 pre-existing type errors. This PR fixes all of them and
promotes mypy to a required check (added to Code Quality Checks, the
gating job; removed the advisory copy from test).

No runtime behaviour changes — these are annotations, Optional fixes, casts,
and narrowing asserts.

Key changes

  • models.pyScoringContext.audio_data / cache typed via
    TYPE_CHECKING forward refs (np.ndarray / AudioCache) instead of
    object, so the real types flow without importing numpy at runtime.
  • implicit Optionalspectrum/calculator/silence params and the
    console globals in main.py & logging_config.py.
  • accumulatorsreasons: list[str], details / stats: Dict[str, Any].
  • Any-returning calls — cast soundfile/scipy results in file_cache,
    silence_utils, cassette to their declared return types.
  • audio_cache — corrected _spectrum / _segments element types (the
    third tuple element is the sample-rate int, not an ndarray), sr-None
    guards, and assert ... is not None after the double-checked-lock build.
  • audio_loaderload_audio_with_retry returns np.ndarray (not
    NDArray[float64]) so the float32 partial-load path type-checks.
  • quality.py# type: ignore[override] on the detector registry's
    intentionally-specialised detect() signatures.
  • deleted src/flac_detective/reporter.py — dead compatibility shim that
    imported a removed symbol (ExcelReporter); referenced nowhere, would have
    raised ImportError if anyone tried to use it.

Verification (local)

  • mypy srcSuccess: no issues found in 49 source files
  • flake8 src tests0 · black --check ✅ · isort --check-only
  • pytest (CI selection) → 139 passed, 8 skipped

🤖 Generated with Claude Code
@

chore(mypy): make the type check clean and a hard gate

Fixed all 43 pre-existing mypy errors and promoted mypy to a required
status check (added to the Code Quality Checks job; removed the advisory
copy from the test job). src/ now type-checks clean against py3.10.

Highlights (no runtime behaviour change):
- models.py: type ScoringContext.audio_data/cache via TYPE_CHECKING
  forward refs (np.ndarray / AudioCache) instead of `object`, keeping
  numpy out of the runtime import graph.
- implicit Optional fixes: spectrum/calculator/silence params, console
  globals in main.py & logging_config.py.
- annotate accumulator lists (`reasons: list[str]`) and dicts
  (`details`/`stats: Dict[str, Any]`).
- cast Any-returning soundfile/scipy calls (file_cache, silence_utils,
  cassette) to their declared types.
- audio_cache: correct _spectrum/_segments element types (sample rate is
  int, not ndarray), guard sr-None, assert non-None after the
  double-checked-lock build.
- audio_loader: load_audio_with_retry returns np.ndarray (not
  NDArray[float64]) so the float32 partial-load path type-checks.
- quality.py: `# type: ignore[override]` on the detector registry's
  intentionally-specialised detect() signatures.
- delete src/flac_detective/reporter.py: dead compat shim importing a
  removed symbol (ExcelReporter no longer exists); referenced nowhere.

flake8 = 0, black & isort clean, mypy clean, pytest 139 passed / 8 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
Comment thread src/flac_detective/analysis/quality.py Fixed
Comment thread src/flac_detective/analysis/quality.py Fixed
Comment thread src/flac_detective/analysis/quality.py Fixed
Comment thread src/flac_detective/analysis/quality.py Fixed
Comment thread src/flac_detective/analysis/quality.py Fixed
Comment thread src/flac_detective/analysis/quality.py Fixed
refactor(quality): uniform detect(**kwargs) signature (Liskov-clean)

The QualityDetector subclasses overrode detect() with extra required
positional params (filepath / reported_depth / cutoff_freq+samplerate),
which both mypy AND CodeQL flagged as a signature-mismatch / Liskov
violation. The previous commit silenced mypy with `# type: ignore[override]`,
but that was a suppression — CodeQL still (correctly) reported it.

Real fix: every detector now matches the base `detect(self, **kwargs)`
exactly and pulls its inputs from kwargs at the top of the method. All
call sites already pass these by keyword (registry dispatch), so behaviour
is unchanged. Removed all 6 `# type: ignore[override]`.

mypy clean, flake8 = 0, black & isort clean, pytest 139 passed / 8 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
@Guillain-RDCDE Guillain-RDCDE merged commit 347ecc2 into main Jun 2, 2026
16 checks passed
@Guillain-RDCDE Guillain-RDCDE deleted the chore/mypy-clean-and-gate branch June 2, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants