[project] name = "japanese-learning-avatar" version = "0.1.0" description = "A lip-synced VRM avatar that speaks and hears Japanese, on a Hugging Face Space" requires-python = ">=3.12,<3.13" dependencies = [ "gradio==6.22.0", "spaces==0.51.1", "huggingface_hub==1.28.0", # Phase 2 language core (plan 02-01): tokenizer, dictionary, CPU translation runtime. # No transformers, no torch - the MT model is pre-converted to CTranslate2 int8 in # data/mt/ by scripts/convert_mt.py, which runs in a throwaway venv (plan 02-04). "SudachiPy==0.6.11", "SudachiDict-core==20260723", "jaconv==0.5.0", "ctranslate2==4.8.2", "sentencepiece==0.2.2", ] [project.optional-dependencies] dev = [ "pytest>=8.0", "pytest-playwright>=0.5", "playwright>=1.48", "ruff>=0.6", "numpy>=1.26", "requests>=2.32", ] # voicevox_core is NOT on PyPI; it ships only as abi3 wheels attached to its GitHub # release. It is an extra rather than a hard dependency so `import japanese_avatar` # and the quick test loop still work for contributors without it. The Space installs # the Linux wheel from requirements.txt, which is its own dependency contract. voice = ["voicevox_core==0.17.0 ; sys_platform == 'win32' or sys_platform == 'linux'"] [tool.uv.sources] # Marker-differentiated so one lockfile serves local Windows dev and the Linux Space # builder. Never vendor the wheel into the repo: the VOICEVOX ソフトウェア利用規約 # 禁止事項 forbids unauthorised redistribution of the software. voicevox_core = [ { url = "https://github.com/VOICEVOX/voicevox_core/releases/download/0.17.0/voicevox_core-0.17.0-cp310-abi3-win_amd64.whl", marker = "sys_platform == 'win32'" }, { url = "https://github.com/VOICEVOX/voicevox_core/releases/download/0.17.0/voicevox_core-0.17.0-cp310-abi3-manylinux_2_34_x86_64.whl", marker = "sys_platform == 'linux'" }, ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/japanese_avatar"] [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["src", "."] addopts = "-q --strict-markers" markers = [ "deployed: requires a live Space; skipped unless --space-url is given", "slow: takes more than ~10s", "mt: loads the CTranslate2 translator (~0.3 s, +100 MB); excluded from the quick loop", ] [tool.ruff] line-length = 100 target-version = "py312" # ruff 0.16+ lints and formats Python code blocks embedded in Markdown. Planning docs, # research notes and design snippets are prose, not source: excluding *.md keeps the lint # gate about shipped Python and stops doc snippets from failing `ruff format --check`. # *.pyi: Gradio auto-generates a type stub beside any module that subclasses a # component, with no opt-out. It is generated output we cannot edit, so it is not # subject to our lint gate. extend-exclude = ["avatar/vendor", "*.md", "*.pyi"] [tool.ruff.lint] select = ["E", "F", "I", "UP", "B", "SIM"] [tool.ruff.format] quote-style = "double"