From f01eae4f0fc3f79618f3b7bdf24f0b4d9f388c89 Mon Sep 17 00:00:00 2001 From: YASoftwareDev Date: Mon, 30 Mar 2026 09:00:02 +0200 Subject: [PATCH 1/5] feat: replace local proto generation with tts-api package dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the tts-service-api git submodule and all custom setup.py build machinery (BuildPackageProtos, BuildPyGRPC, DevelopGRPC, CustomInstall, CustomEggInfo). gRPC stubs are now provided by the tts-api package. Changes: - setup.py: remove all proto-generation commands; add tts-api to install_requires (git ref until PyPI publish); fix doc URL to tts-api - pyproject.toml: remove grpcio-tools build dependency - setup.sh: remove submodule init (pre-commit only) - install.sh: remove proto sentinel check - tox.ini: switch skip_install=false + extras=test; remove manual grpcio/protobuf deps; remove commands_pre stub check - .github/workflows/test.yml: remove submodules checkout and build_grpc step - .gitmodules: deleted (no submodule) - tts_client_python/proto/__init__.py: deleted - 5 import sites updated: from tts_client_python.proto → from techmo.tts.api.v3 - CLAUDE.md: update proto stubs, setup, CI and dependency sections --- .github/workflows/test.yml | 18 ---- .gitmodules | 3 - CLAUDE.md | 24 ++--- install.sh | 7 -- pyproject.toml | 4 +- setup.py | 137 ++-------------------------- setup.sh | 5 +- tests/test_helpers.py | 2 +- tests/test_wave_utils.py | 2 +- tox.ini | 27 +----- tts_client_python/general.py | 4 +- tts_client_python/lexicons.py | 2 +- tts_client_python/proto/__init__.py | 0 tts_client_python/recordings.py | 2 +- 14 files changed, 28 insertions(+), 209 deletions(-) delete mode 100644 .gitmodules delete mode 100644 tts_client_python/proto/__init__.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ebbbb32..796e860 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,8 +17,6 @@ jobs: steps: - uses: actions/checkout@v4 - with: - submodules: recursive - name: Install system dependencies run: sudo apt-get install -y libportaudio2 @@ -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 '.')" @@ -47,8 +38,6 @@ jobs: steps: - uses: actions/checkout@v4 - with: - submodules: recursive - name: Install system dependencies run: sudo apt-get install -y libportaudio2 @@ -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 diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 56a2afa..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "submodules/tts-service-api"] - path = submodules/tts-service-api - url = https://github.com/techmo-pl/tts-service-api diff --git a/CLAUDE.md b/CLAUDE.md index 7bbb452..708b2c5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 @@ -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` currently installed from git (`git+https://github.com/techmo-pl/tts-api-python.git`). +Switch to `tts-api>=3.2.1` in `setup.py` once published to PyPI. + +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 diff --git a/install.sh b/install.sh index a328258..7529986 100755 --- a/install.sh +++ b/install.sh @@ -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 diff --git a/pyproject.toml b/pyproject.toml index b9fc3f3..fed528d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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" diff --git a/setup.py b/setup.py index f6ffa8f..389eeb3 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,8 @@ from __future__ import annotations from pathlib import Path -from typing import Any -from setuptools import Command, find_packages, setup -from setuptools.command.build_py import build_py -from setuptools.command.develop import develop -from setuptools.command.egg_info import egg_info -from setuptools.command.install import install +from setuptools import find_packages, setup # Read version without importing the package — avoids a circular import during # the PEP-517 build phase (setup.py is executed before the package is installed). @@ -20,115 +15,6 @@ project_root = Path(__file__).parent - -class BuildPackageProtos(Command): # type: ignore[misc] - """Command to generate project *_pb2.py modules from proto files.""" - - user_options: list[Any] = [] - - def initialize_options(self) -> None: - pass - - def finalize_options(self) -> None: - pass - - def run(self) -> None: - """Build gRPC modules.""" - import shutil - - import grpc_tools - from grpc_tools import protoc - - temp_proto_dir = project_root / "tts_service_api" - try: - proto_file = project_root / "submodules" / "tts-service-api" / "proto" / "techmo_tts.proto" - output_path = project_root / "tts_client_python" / "proto" - if not proto_file.exists(): - raise FileNotFoundError( - f"Proto source file not found: {proto_file}\n" - "The 'tts-service-api' submodule is not initialised.\n" - "Run ./setup.sh first, then re-run ./install.sh." - ) - if grpc_tools.__file__ is None: - raise RuntimeError("Cannot locate grpc_tools package directory") - well_known_protos_include = str(Path(grpc_tools.__file__).parent / "_proto") - shutil.rmtree(temp_proto_dir, ignore_errors=True) - temp_proto_dir.mkdir() - shutil.copy(proto_file, temp_proto_dir) - - command_1 = [ - "grpc_tools.protoc", - f"--proto_path={output_path.relative_to(project_root)}={temp_proto_dir.name}", - f"--proto_path={well_known_protos_include}", - f"--python_out={project_root.relative_to(project_root)}", - f"--grpc_python_out={project_root.relative_to(project_root)}", - ] + [str(temp_proto_dir.relative_to(project_root) / proto_file.name)] - - if protoc.main(command_1) != 0: - raise Exception("Problem with building gRPC modules") - except Exception as e: - print(e) - raise - finally: - shutil.rmtree(temp_proto_dir, ignore_errors=True) - - -class BuildPyGRPC(build_py): # type: ignore[misc] - """Command for Python modules build.""" - - def __init__(self, dist: Any) -> None: - """Create a sub-command to execute.""" - self.subcommand = BuildPackageProtos(dist) - super().__init__(dist) - - def run(self) -> None: - """Build Python and GRPC modules.""" - super().run() - self.subcommand.run() - - -class DevelopGRPC(develop): # type: ignore[misc] - """Command for develop installation.""" - - def __init__(self, dist: Any) -> None: - """Create a sub-command to execute.""" - self.subcommand = BuildPackageProtos(dist) - super().__init__(dist) - - def run(self) -> None: - """Build GRPC modules before the default installation.""" - self.subcommand.run() - super().run() - - -class CustomInstall(install): # type: ignore[misc] - """Command for pip installation.""" - - def __init__(self, dist: Any) -> None: - """Create a sub-command to execute.""" - self.subcommand = BuildPackageProtos(dist) - super().__init__(dist) - - def run(self) -> None: - """Build GRPC modules before the default installation.""" - self.subcommand.run() - super().run() - - -class CustomEggInfo(egg_info): # type: ignore[misc] - """Command for pip installation.""" - - def __init__(self, dist: Any) -> None: - """Create a sub-command to execute.""" - self.subcommand = BuildPackageProtos(dist) - super().__init__(dist) - - def run(self) -> None: - """Build GRPC modules before the default installation.""" - self.subcommand.run() - super().run() - - setup( name="tts_client_python", version=package_version, @@ -140,15 +26,13 @@ def run(self) -> None: packages=find_packages(), include_package_data=True, install_requires=[ - # Generated stubs embed GRPC_GENERATED_VERSION='1.70.0' and raise - # RuntimeError for grpcio<1.70.0. grpcio 1.71.0 dropped Python 3.8. - # Python 3.9+ uses a recent known-good version (1.70.0) as lower bound. + # gRPC stubs come from tts-api; grpcio is also needed directly for channel creation. + # grpcio 1.71.0 dropped Python 3.8; keep <1.71.0 for 3.8 compatibility. "grpcio>=1.70.0,<2.0.0; python_version>='3.9'", "grpcio>=1.70.0,<1.71.0; python_version=='3.8'", - # Stubs are generated with protobuf 5.29.x; runtime must be >=5.29.0. - # protobuf 6.x requires Python>=3.9, so cap at <6.0 for Python 3.8. - "protobuf>=5.29.0,<6.0.0; python_version=='3.8'", - "protobuf>=5.29.0; python_version>='3.9'", + # Pre-built gRPC stubs for the Techmo TTS API. + # Switch to "tts-api>=3.2.1" once published to PyPI. + "tts-api @ git+https://github.com/techmo-pl/tts-api-python.git", "lxml>=4.6.4", "numpy>=1.19.5", "sounddevice>=0.4.0", @@ -163,14 +47,7 @@ def run(self) -> None: python_requires=">=3.8", project_urls={ "Source": "https://github.com/techmo-pl/tts-client-python", - "Documentation": "https://github.com/techmo-pl/tts-service-api/blob/master/doc/Documentation.md", + "Documentation": "https://github.com/techmo-pl/tts-api/blob/master/doc/Documentation.md", }, entry_points={"console_scripts": ["tts_client = tts_client_python.tts_client:main"]}, - cmdclass={ - "build_py": BuildPyGRPC, - "build_grpc": BuildPackageProtos, - "develop": DevelopGRPC, - "egg_info": CustomEggInfo, - "install": CustomInstall, - }, ) diff --git a/setup.sh b/setup.sh index 3454459..d58fee1 100755 --- a/setup.sh +++ b/setup.sh @@ -2,13 +2,10 @@ # # usage: ./setup.sh # -# Run once after cloning: initialises submodules and installs pre-commit hooks. +# Run once after cloning: installs pre-commit hooks. set -euo pipefail -git submodule sync --recursive -git submodule update --init --recursive - if [ ! -d pre-commit ]; then git clone --depth 1 --branch v3.0.0 https://github.com/techmo-pl/pre-commit.git fi diff --git a/tests/test_helpers.py b/tests/test_helpers.py index b0a8534..277ab70 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -5,7 +5,7 @@ import pytest from tts_client_python.general import create_out_path, create_voice, get_audio_encoding, prepare_synthesis_config -from tts_client_python.proto import techmo_tts_pb2 +from techmo.tts.api.v3 import techmo_tts_pb2 class TestGetAudioEncoding: diff --git a/tests/test_wave_utils.py b/tests/test_wave_utils.py index a4088e9..9079689 100644 --- a/tests/test_wave_utils.py +++ b/tests/test_wave_utils.py @@ -7,7 +7,7 @@ import pytest from tts_client_python.general import AudioSaver -from tts_client_python.proto import techmo_tts_pb2 +from techmo.tts.api.v3 import techmo_tts_pb2 from tts_client_python.wave_utils import AudioFormat, write_wave_file diff --git a/tox.ini b/tox.ini index 88f3198..ce29646 100644 --- a/tox.ini +++ b/tox.ini @@ -6,35 +6,10 @@ requires = tox-uv>=1 [testenv] -# skip_install=true keeps each env lightweight: the package is found via PYTHONPATH -# rather than doing a full editable install in each env. -# Proto stubs (tts_client_python/proto/*_pb2.py) are NOT committed — they are -# gitignored and must be generated before tests run. In CI the "Generate proto -# stubs" step does this; locally, run `./install.sh` first (triggers proto -# generation via the setup.py cmdclass hooks; requires the tts-service-api -# submodule — see README § Running tests). -skip_install = true -set_env = PYTHONPATH = {toxinidir} +extras = test # Pass service-address variables so integration tests can connect to a live service # when run via tox (e.g. tox -e py312 -- -m integration). passenv = TTS_* -deps = - # grpcio 1.71.0 dropped Python 3.8; stubs require grpcio>=1.70.0. - grpcio>=1.70.0,<2.0.0; python_version>="3.9" - grpcio>=1.70.0,<1.71.0; python_version=="3.8" - protobuf>=5.29.0,<6.0.0; python_version=="3.8" - protobuf>=5.29.0; python_version>="3.9" - lxml>=4.6.4 - numpy>=1.19.5 - sounddevice>=0.4.0 - pytest>=7.0 - pytest-cov>=4.0 - jiwer>=3.0 -commands_pre = - # Abort early with a clear message if proto stubs are missing rather than - # letting pytest fail with a cryptic ModuleNotFoundError deep in imports. - # PYTHONPATH already contains {toxinidir} so we use it to locate the stub. - python -c "import os, sys; stub = os.path.join(os.environ['PYTHONPATH'], 'tts_client_python', 'proto', 'techmo_tts_pb2.py'); sys.exit(0) if os.path.exists(stub) else sys.exit('Proto stubs missing. Run: ./install.sh (or: python setup.py build_grpc)')" commands = pytest --basetemp={envtmpdir} --cov=tts_client_python --cov-report=term-missing --cov-report=xml:{envtmpdir}/coverage.xml {posargs} diff --git a/tts_client_python/general.py b/tts_client_python/general.py index 0d4bcf9..aa8ff69 100644 --- a/tts_client_python/general.py +++ b/tts_client_python/general.py @@ -8,8 +8,8 @@ import numpy as np import sounddevice as sd -from tts_client_python.proto import techmo_tts_pb2 as techmo_tts_pb2 -from tts_client_python.proto import techmo_tts_pb2_grpc as techmo_tts_pb2_grpc +from techmo.tts.api.v3 import techmo_tts_pb2 +from techmo.tts.api.v3 import techmo_tts_pb2_grpc from tts_client_python.wave_utils import AudioFormat, write_wave_file diff --git a/tts_client_python/lexicons.py b/tts_client_python/lexicons.py index c3f5640..be509ec 100644 --- a/tts_client_python/lexicons.py +++ b/tts_client_python/lexicons.py @@ -6,7 +6,7 @@ from grpc import StatusCode from tts_client_python.general import GrpcRequestConfig -from tts_client_python.proto import techmo_tts_pb2 as techmo_tts_pb2 +from techmo.tts.api.v3 import techmo_tts_pb2 def delete_lexicon( diff --git a/tts_client_python/proto/__init__.py b/tts_client_python/proto/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tts_client_python/recordings.py b/tts_client_python/recordings.py index 3c5c798..8b0ddf7 100644 --- a/tts_client_python/recordings.py +++ b/tts_client_python/recordings.py @@ -5,7 +5,7 @@ import grpc from tts_client_python.general import GrpcRequestConfig -from tts_client_python.proto import techmo_tts_pb2 as techmo_tts_pb2 +from techmo.tts.api.v3 import techmo_tts_pb2 from tts_client_python.wave_utils import AudioFormat, write_wave_file From 5f0659e85d0f2512b7f2e6b14357e8a20d1f69b5 Mon Sep 17 00:00:00 2001 From: YASoftwareDev Date: Mon, 30 Mar 2026 09:37:42 +0200 Subject: [PATCH 2/5] fix: pin tts-api to tagged GitHub release v3.2.1 --- CLAUDE.md | 4 ++-- setup.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 708b2c5..b402465 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -55,8 +55,8 @@ 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+) -`tts-api` currently installed from git (`git+https://github.com/techmo-pl/tts-api-python.git`). -Switch to `tts-api>=3.2.1` in `setup.py` once published to PyPI. +`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. diff --git a/setup.py b/setup.py index 389eeb3..60184e4 100644 --- a/setup.py +++ b/setup.py @@ -31,8 +31,7 @@ "grpcio>=1.70.0,<2.0.0; python_version>='3.9'", "grpcio>=1.70.0,<1.71.0; python_version=='3.8'", # Pre-built gRPC stubs for the Techmo TTS API. - # Switch to "tts-api>=3.2.1" once published to PyPI. - "tts-api @ git+https://github.com/techmo-pl/tts-api-python.git", + "tts-api @ git+https://github.com/techmo-pl/tts-api-python.git@v3.2.1", "lxml>=4.6.4", "numpy>=1.19.5", "sounddevice>=0.4.0", From 8ec86336d04db3bd32a4f95f78fea209dcbb71c7 Mon Sep 17 00:00:00 2001 From: YASoftwareDev Date: Mon, 30 Mar 2026 10:09:53 +0200 Subject: [PATCH 3/5] docs: update AGENTS.md for tts-api package migration --- AGENTS.md | 74 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 97fdb7c..35019ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## 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 @@ -10,49 +10,50 @@ Python gRPC client for Techmo TTS (Text-to-Speech) service. Provides a CLI tool ## 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 @@ -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 | From a30fd565d186c0d489cf1b64ecdf2510ff63ba2c Mon Sep 17 00:00:00 2001 From: YASoftwareDev Date: Mon, 30 Mar 2026 10:14:05 +0200 Subject: [PATCH 4/5] =?UTF-8?q?chore:=20bump=20version=203.2.8=20=E2=86=92?= =?UTF-8?q?=203.2.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 17 +++++++++++++++++ tts_client_python/VERSION.py | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe0f5e..4bf07b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Techmo TTS gRPC Python client Changelog +## [3.2.9] - 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 diff --git a/tts_client_python/VERSION.py b/tts_client_python/VERSION.py index cfee65c..7107643 100644 --- a/tts_client_python/VERSION.py +++ b/tts_client_python/VERSION.py @@ -1 +1 @@ -TTS_CLIENT_PYTHON_VERSION = "3.2.8" +TTS_CLIENT_PYTHON_VERSION = "3.2.9" From 47af1aec6aae4c2f90c5f6a07ba69038947469af Mon Sep 17 00:00:00 2001 From: YASoftwareDev Date: Mon, 30 Mar 2026 10:17:12 +0200 Subject: [PATCH 5/5] chore: fix version to 3.2.8+1 (postfix, not patch bump) --- CHANGELOG.md | 2 +- tts_client_python/VERSION.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bf07b0..b1e1626 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Techmo TTS gRPC Python client Changelog -## [3.2.9] - 2026-03-30 +## [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`). diff --git a/tts_client_python/VERSION.py b/tts_client_python/VERSION.py index 7107643..572df37 100644 --- a/tts_client_python/VERSION.py +++ b/tts_client_python/VERSION.py @@ -1 +1 @@ -TTS_CLIENT_PYTHON_VERSION = "3.2.9" +TTS_CLIENT_PYTHON_VERSION = "3.2.8+1"