DeepL Translator CLI using Playwright browser automation (no API key required). See README.md for usage and pyproject.toml for dependencies.
uv run pytest # run tests
uv run pytest --cov=deepl tests/ # run tests with coverage
uvx ty check --respect-ignore-files # type check (ty, not mypy)
uv run ruff check . # lint
uv run ruff format . # format
uv run pymarkdown fix --list-files . # lint markdownOr via mise task runner:
mise run pytest
mise run ty
mise run ruff
mise run pymarkdown| File | Purpose |
|---|---|
deepl/deepl.py |
Core DeepLCLI class — Playwright scraping logic |
deepl/main.py |
CLI entry point (argparse), registered as deepl script |
deepl/languages.py |
FR_LANGS / TO_LANGS sets of valid language codes |
deepl/__init__.py |
Public exports: DeepLCLI, DeepLCLIError, DeepLCLIPageLoadError |
tests/test_deepl.py |
pytest + pytest-asyncio tests |
- Python 3.10+ required; use modern union syntax (
X | Y) overOptional/Union - Line length: 120 characters (ruff config)
- Docstrings: Google convention (
Args:,Returns:,Raises:) - Formatter:
ruff format(double quotes, 4-space indent) - Linter:
ruffwithALLrules; see per-file ignores inpyproject.toml - Package manager:
uv— useuv add/uv run, never barepip - Versioning: dynamic via
uv-dynamic-versioning(git tags) — do not setversionmanually
- Max input: 1500 characters (
DeepLCLI.max_length) autosource language detection does not work via URL path param (tests for it are@pytest.mark.skip)- Language updates: scrape the DeepL language dropdown and run the JS snippet in
deepl.pydocstring to regeneratelanguages.py
- Tests make real network requests to deepl.com via Playwright — no mocking
- Async tests use
@pytest.mark.asyncio(pytest-asyncio) - Timeout should be set high in tests (e.g.
100000ms) to avoid flakiness