Skip to content

refactor: validate voiceover cache with pydantic#135

Merged
osolmaz merged 4 commits into
mainfrom
refactor/pydantic-cache-models
Jun 14, 2026
Merged

refactor: validate voiceover cache with pydantic#135
osolmaz merged 4 commits into
mainfrom
refactor/pydantic-cache-models

Conversation

@osolmaz

@osolmaz osolmaz commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Opened on behalf of Onur Solmaz (osolmaz).

Summary

Voiceover cache entries were plain dictionaries with no validation at the cache boundary.
This change adds Pydantic models for the existing cache JSON shape without changing the saved schema.
It also raises the package Python floor to 3.11, matching current Manim support, and adds tests that lock the current cache list format.

Acknowledgements

Gemini TTS support in this branch overlaps with and should have credited the earlier Gemini TTS contribution in #119 by @Abhishek6792. That PR introduced the original Gemini service direction for Manim Voiceover, including use of the Google Gen AI SDK, WAV output, bookmark removal, cache input data, and the Kore voice default.

What Changed

Cache reads and writes now pass through a typed model layer, but the serialized cache stays as the same top-level JSON list.
Provider-specific input_data fields are preserved, and invalid cache entries now fail with a clear validation error.

  • Added manim_voiceover.services.cache with Pydantic models and cache load/parse/serialize/append helpers.
  • Updated SpeechService cache lookup and generation wrapping to validate cache entries through the model layer.
  • Kept cache writes on the existing JSON list helper so the file format and pretty-printing behavior stay unchanged.
  • Raised requires-python and tool targets to Python 3.11, added direct pydantic>=2.10,<3, and simplified dependency markers that only existed for older Python versions.
  • Added cache model tests for minimal entries, provider extras, invalid cache data, append behavior, and non-list cache rejection.

Testing

I ran the local gates, including the example-rendering test and mutation testing.
All required checks passed locally.

  • uv run ruff format --check .
  • uv run ruff check .
  • uv run ty check src/manim_voiceover
  • uv run mypy
  • uv run pytest --cov=manim_voiceover --cov-fail-under=85
  • uvx slophammer-py@0.3.0 dry .
  • uv run mutmut run --max-children 2
  • uv run python scripts/check_mutmut_results.py
  • uv run pip-audit
  • uvx slophammer-py@0.3.0 check .
  • PATH="/Users/onur/repos/manim-voiceover/.venv/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/usr/local/go/bin:/Users/onur/.local/bin:/Users/onur/.nvm/versions/node/v22.17.0/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/onur/.codex/tmp/arg0/codex-arg0dhHXKv:/opt/homebrew/opt/llvm/bin:/Users/onur/.nvm/versions/node/v22.17.0/bin:/opt/homebrew/lib/ruby/gems/3.2.0/bin:/Users/onur/.modular/pkg/packages.modular.com_mojo/bin:/opt/homebrew/opt/postgresql@15/bin:/opt/homebrew/opt/ruby/bin:/Users/onur/.docker/bin:/Users/onur/google-cloud-sdk/bin:/Users/onur/Library/pnpm/bin:/Users/onur/.cargo/bin:/Applications/iTerm.app/Contents/Resources/utilities:/usr/local/texlive/2022/bin/universal-darwin/:/Users/onur/.lmstudio/bin" uvx slophammer-py@0.3.0 check . --execute

Risks

The main compatibility risk is stricter validation of malformed cache files.
Valid existing cache files should keep the same serialized shape, including provider-specific input_data extras.

  • This intentionally does not add a schema version or wrapper object.
  • It does not migrate old cache files; it validates the current schema in place.
  • The lockfile changed substantially because the Python floor moved from 3.8 to 3.11.

@osolmaz osolmaz merged commit 06b7829 into main Jun 14, 2026
1 check passed
@osolmaz osolmaz mentioned this pull request Jun 14, 2026
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.

1 participant