Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install system dependencies
run: sudo apt-get install -y libportaudio2
Expand All @@ -28,13 +26,6 @@ jobs:
with:
cache-dependency-glob: "pyproject.toml"

- name: Generate proto stubs
run: |
uv venv .venv
source .venv/bin/activate
uv pip install --quiet "grpcio-tools>=1.70.0,<1.71.0" setuptools
PYTHONPATH=. python setup.py build_grpc

- name: Run tests via tox
run: |
TOXENV="py$(echo '${{ matrix.python-version }}' | tr -d '.')"
Expand All @@ -47,8 +38,6 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install system dependencies
run: sudo apt-get install -y libportaudio2
Expand All @@ -58,12 +47,5 @@ jobs:
with:
cache-dependency-glob: "pyproject.toml"

- name: Generate proto stubs
run: |
uv venv .venv
source .venv/bin/activate
uv pip install --quiet "grpcio-tools>=1.70.0,<1.71.0" setuptools
PYTHONPATH=. python setup.py build_grpc

- name: Run tests via tox
run: uvx --with "tox-uv>=1" tox -e py314
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

74 changes: 36 additions & 38 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,58 @@

## Project Summary

Python gRPC client for Techmo TTS (Text-to-Speech) service. Provides a CLI tool (`tts_client`) and a Python library for speech synthesis, voice listing, custom recordings, and pronunciation lexicons. Communicates via gRPC using protobuf definitions from the `submodules/tts-service-api` submodule.
Python gRPC client for Techmo TTS (Text-to-Speech) service. Provides a CLI tool (`tts_client`) and a Python library for speech synthesis, voice listing, custom recordings, and pronunciation lexicons. Communicates via gRPC using pre-built stubs from the `tts-api` package.

**Version:** `tts_client_python/VERSION.py`
**Python:** 3.8–3.14

## Repo Layout

```
tts_client_python/ # main package
tts_client_python/
tts_client.py # CLI entry point & arg parsing
general.py # gRPC client, audio player/saver, synthesis functions
recordings.py # custom recording CRUD
lexicons.py # pronunciation lexicon CRUD
wave_utils.py # WAV/A-Law/Mu-Law file writing; AudioFormat enum
VERSION.py # single version source
proto/ # generated — never in git
tests/ # pytest test suite
tests/
conftest.py # fixtures, sounddevice safety mock
test_cli.py # CLI arg validation
test_channel.py # gRPC channel creation
test_helpers.py # helper/validator functions
test_wave_utils.py # WAV encoding
test_integration.py # live service tests (excluded by default)
submodules/
tts-service-api/ # proto definitions (git submodule)
setup.py # custom build commands: build_grpc, build_py, develop, install
pyproject.toml # build backend; grpcio-tools constraint
setup.sh # one-time: submodules + pre-commit hooks
install.sh # venv creation + pip install
setup.py # standard setuptools setup; tts-api in install_requires
pyproject.toml # build backend (setuptools only, no grpcio-tools)
setup.sh # one-time: pre-commit hooks only
install.sh # venv creation + pip install (no proto generation)
```

## Environment Setup
## Proto Stubs

```bash
./setup.sh # init submodules + pre-commit (run once after clone)
./install.sh # create .venv, install package + test deps via uv
source .venv/bin/activate
sudo apt-get install libportaudio2 # required for sounddevice
gRPC stubs are provided by the `tts-api` dependency — no local generation, no submodule.

```python
from techmo.tts.api.v3 import techmo_tts_pb2, techmo_tts_pb2_grpc
```

**Never mix `setup.sh` and `install.sh` concerns.** `setup.sh` = git/hooks only. `install.sh` = Python env only.
`tts-api` is pinned to a GitHub tag in `setup.py`:
```
tts-api @ git+https://github.com/techmo-pl/tts-api-python.git@vX.Y.Z
```
Update the tag in `setup.py` when a new `tts-api-python` release is tagged.

## Generating Proto Stubs
## Environment Setup

Proto stubs are never committed. Regenerate with:
```bash
python setup.py build_grpc
./setup.sh # one-time: install pre-commit hooks
./install.sh # create .venv, install package + test deps via uv
source .venv/bin/activate
sudo apt-get install libportaudio2 # required for sounddevice
```
This is also triggered automatically by `uv pip install -e ".[test]"`.

Generated files: `tts_client_python/proto/techmo_tts_pb2.py`, `techmo_tts_pb2_grpc.py`
`setup.sh` — pre-commit hooks only. `install.sh` — Python env only. Never mix concerns.

## Running Tests

Expand All @@ -63,38 +64,35 @@ pytest -m integration # requires TTS_SERVICE_ADDRESS=host:port env var
uvx --with "tox-uv>=1" tox # full Python 3.8–3.14 matrix
```

Unit tests do not mock gRPC calls — `test_helpers.py` imports proto stubs directly, so generated stubs must exist before running tests. Only `test_channel.py` uses mocking (for the gRPC channel). sounddevice is mocked at session start only if it causes a SIGSEGV. Integration tests require a live TTS service.
Integration tests require a live TTS service at `TTS_SERVICE_ADDRESS`. sounddevice is mocked at session start only if it causes a SIGSEGV.

## Key Conventions

- **Proto files**: `*_pb2.py`, `*_pb2_grpc.py` — never commit, always generate.
- **Version**: only in `tts_client_python/VERSION.py`.
- **Dependency bounds**: Python 3.8 has tighter grpcio/protobuf constraints; do not widen without verifying.
- **Audio playback**: only PCM16 is supported by `AudioPlayer`; other encodings write files only.
- **Commit messages**: conventional format (`feat:`, `fix:`, `chore:`, `ci:`, `test:`, `refactor:`); no Claude attribution.
- **Version:** only in `tts_client_python/VERSION.py`.
- **Dependency bounds:** Python 3.8 has a tighter grpcio constraint (`<1.71.0`); do not widen without verifying.
- **Audio playback:** only PCM16 is supported by `AudioPlayer`; other encodings write files only.
- **Commit messages:** conventional format (`feat:`, `fix:`, `chore:`, `ci:`, `test:`, `refactor:`); no Claude attribution.

## Architecture Notes

- `GrpcRequestConfig` (general.py) holds the gRPC channel, stub, timeout, and metadata. All API calls receive one.
- `create_channel()` builds insecure or TLS channels depending on CLI flags.
- `synthesize()` is the high-level public function — creates the channel/stub/request, then dispatches to `internal_synthesize()` (unary gRPC call) or `internal_synthesize_streaming()` (streaming gRPC call) based on the `response` argument.
- `synthesize()` dispatches to `internal_synthesize()` (unary) or `internal_synthesize_streaming()` (server-streaming) based on the `response` argument.
- `AudioSaver` handles all file output formats; `AudioPlayer` streams PCM16 to PortAudio.
- `recordings.py` and `lexicons.py` are thin gRPC wrappers using the same `GrpcRequestConfig` pattern.
- `lxml` is listed as a dependency in `setup.py` but is not currently imported in the codebase — it may be a leftover or intended for future SSML validation.
- `lxml` is a declared dependency but not currently imported — likely a leftover or reserved for future SSML validation.

## CI/CD
## CI — GitHub Actions

GitHub Actions (`.github/workflows/test.yml`):
- Matrix: Python 3.8–3.13 (required pass), 3.14 RC (allowed failure)
- Steps per job: checkout with submodules → install libportaudio2 → install uv → generate protos → tox
- Integration tests activate automatically if `TTS_SERVICE_ADDRESS` secret is set in the repo.
`.github/workflows/test.yml`: Python 3.8–3.13 (required), 3.14 (allowed failure).
Each job: checkout → install libportaudio2 → install uv → tox (installs package including `tts-api`).
No submodule checkout. No proto generation step.

No `.gitlab-ci.yml` exists in this repo — CI runs only on GitHub Actions.
No `.gitlab-ci.yml` — CI runs only on GitHub Actions.

## Dependency Constraints

| Package | Python 3.8 | Python 3.9+ |
|---------|-----------|-------------|
| grpcio | `>=1.70.0,<1.71.0` | `>=1.70.0,<2.0` |
| protobuf | `>=5.29.0,<6.0` | `>=5.29.0` |
| grpcio-tools (build) | `>=1.70.0,<1.71.0` | same |
| tts-api | `@ git+https://github.com/techmo-pl/tts-api-python.git@vX.Y.Z` | same |
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Techmo TTS gRPC Python client Changelog

## [3.2.8+1] - 2026-03-30

### Changed
- Replace local proto generation with `tts-api` package dependency (`git+https://github.com/techmo-pl/tts-api-python.git@v3.2.1`).
No proto submodule, no `setup.py build_grpc` step required.
- All imports updated from `tts_client_python.proto` to `techmo.tts.api.v3`.
- `setup.py`: remove 5 custom build command classes; add `tts-api` to `install_requires`.
- `pyproject.toml`: remove `grpcio-tools` build dependency.
- `setup.sh`: remove submodule init (pre-commit hooks only).
- `install.sh`: remove proto sentinel check.
- `tox.ini`: switch to `skip_install=false`, `extras=test`; remove manual dep list.
- `.github/workflows/test.yml`: remove submodule checkout and `build_grpc` step.

### Added
- `AGENTS.md`: updated to reflect new architecture (no submodule, tts-api dependency).


## [3.2.8] - 2026-03-25

### Fixed
Expand Down
24 changes: 12 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ Python gRPC client for Techmo's Text-to-Speech service. Provides a CLI (`tts_cli
- **Package:** `tts_client_python`
- **Version:** tracked in `tts_client_python/VERSION.py`
- **Python support:** 3.8–3.14
- **gRPC API proto:** `submodules/tts-service-api/proto/techmo_tts.proto`
- **gRPC API stubs:** provided by the `tts-api` package (`techmo.tts.api.v3` namespace)

## Dev Environment Setup

```bash
./setup.sh # one-time: init submodules + pre-commit hooks
./setup.sh # one-time: install pre-commit hooks
./install.sh # creates .venv and installs package with test deps (uv required)
source .venv/bin/activate
```

`setup.sh` — submodules + pre-commit only. `install.sh` — venv + pip only. Never mix these concerns.
`setup.sh` — pre-commit only. `install.sh` — venv + pip only. Never mix these concerns.

System dependency: `sudo apt-get install libportaudio2` (needed by sounddevice; missing it produces a warning but tests still run — conftest handles the absence gracefully).

## Proto Stubs

Generated files (`tts_client_python/proto/*_pb2.py`, `*_pb2_grpc.py`) are **never committed**.
Generate manually: `python setup.py build_grpc`
They are regenerated automatically during `uv pip install -e ".[test]"`.
Stubs are provided by the `tts-api` dependency (package `tts-api-python` on GitHub).
Import them as: `from techmo.tts.api.v3 import techmo_tts_pb2, techmo_tts_pb2_grpc`
No manual generation required. No proto submodule.

## Key Source Files

Expand Down Expand Up @@ -54,19 +54,19 @@ Integration tests are excluded by default (`pytest.ini`). They require a running

Python 3.8 requires tighter bounds:
- `grpcio>=1.70.0,<1.71.0` (3.8) vs `grpcio>=1.70.0,<2.0` (3.9+)
- `protobuf>=5.29.0,<6.0` (3.8) vs `protobuf>=5.29.0` (3.9+)
- `grpcio-tools>=1.70.0,<1.71.0` in `pyproject.toml` (build dep)

Do not widen these bounds without verifying Python 3.8 compatibility.
`tts-api` is pinned to a GitHub tag: `git+https://github.com/techmo-pl/tts-api-python.git@vX.Y.Z`.
Update the tag in `setup.py` when a new `tts-api-python` release is tagged.

Do not widen grpcio bounds without verifying Python 3.8 compatibility.

## CI — GitHub Actions

`.github/workflows/test.yml` runs a matrix across Python 3.8–3.13 (required) and 3.14 (allowed failure). Each job:
1. Checks out with submodules
1. Checks out (no submodules)
2. Installs `libportaudio2`
3. Installs `uv`
4. Generates proto stubs: `python setup.py build_grpc`
5. Runs tox
4. Runs tox (which installs the package including `tts-api`)

## Versioning

Expand Down
7 changes: 0 additions & 7 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ if ! command -v uv &> /dev/null; then
exit 1
fi

PROTO_SENTINEL="submodules/tts-service-api/proto/techmo_tts.proto"
if [ ! -f "${PROTO_SENTINEL}" ]; then
echo "Error: submodule 'tts-service-api' is not initialised." >&2
echo "Run ./setup.sh first, then re-run ./install.sh." >&2
exit 1
fi

VENV_PATH="${1:-.venv}"

if [ ! -d "${VENV_PATH}" ]; then
Expand Down
4 changes: 1 addition & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
[build-system]
# grpcio-tools 1.71.0+ ships protobuf 6.x which generates stubs requiring Python>=3.9.
# Keep <1.71.0 so generated stubs stay compatible with Python 3.8 (protobuf 5.29.x).
requires = ["setuptools", "grpcio-tools>=1.70.0,<1.71.0"]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
Loading
Loading