Add test suite (100% cov), CI, gRPC latency/keepalive tuning, and docs#2
Merged
Conversation
…grpc config Performance: - Hoist the constant gRPC service_config_json and default channel options to module level in base_services_interface and async_base_services_interface so they are serialized once at import instead of on every service construction (a client with N services previously ran json.dumps N times per connection). Testing: - Add tests/ covering all ondewo.utils modules to 100% statement and branch coverage (47 tests). - Configure pytest + coverage in setup.cfg with a --cov-fail-under=100 gate. - Add pytest, pytest-cov, pytest-asyncio and mock to requirements-dev.txt and to the pytest Docker image. CI: - Add .github/workflows/tests.yml to run the suite on every push and PR across Python 3.9-3.12. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….2.0 - Update CI actions to their Node 24 releases (checkout v4->v5, setup-python v5->v6, upload-artifact v4->v5) to clear the Node 20 deprecation warnings on the runners. - Bump package version to 3.2.0 and add a RELEASE.md entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add a CLAUDE.md with repo overview, dev/test commands, and ONDEWO conventions adapted for this library. - Document every Makefile target with a `## ` help comment, fix the misleading show_pypi_via_docker_image description, and include digit-containing target names (e.g. flake8) in `make help`.
…tandard Split the 3.2.0 entry into New Features and Improvements sections to match the repository's RELEASE.md convention.
There was a problem hiding this comment.
Pull request overview
This PR introduces a full pytest suite (targeting 100% coverage) and a GitHub Actions workflow to continuously validate ondewo.utils, while also tuning gRPC channel defaults (keepalive + hoisted service config/options) and adding developer-facing documentation and release/version updates.
Changes:
- Add comprehensive
tests/coverage and enforce a 100% coverage gate via pytest/coverage configuration. - Add CI workflow running tests on Python 3.9–3.12 and update dev/test tooling dependencies.
- Optimize/tune gRPC channel setup by hoisting constant service config/options and enabling keepalive defaults.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
tests/__init__.py |
Adds test package marker (license header only). |
tests/test_text.py |
Adds unit tests for TextHelper.from_camel_to_snake_case. |
tests/test_helpers.py |
Adds tests for helpers (get_struct_from_dict, recursive attr helpers). |
tests/test_base_services_interface.py |
Adds sync channel/options tests for BaseServicesInterface. |
tests/test_async_base_services_interface.py |
Adds async channel/options tests for AsyncBaseServicesInterface. |
tests/test_base_service_container.py |
Adds a basic dataclass/instantiation test for the service container. |
tests/test_base_client.py |
Adds sync BaseClient connect/disconnect/guard-clause tests. |
tests/test_async_base_client.py |
Adds async AsyncBaseClient connect/disconnect/guard-clause tests. |
setup.cfg |
Adds pytest + coverage configuration (including 100% gate). |
requirements-dev.txt |
Adds testing dependencies used by the new suite. |
dockerfiles/pytest.Dockerfile |
Updates pytest image to install test dependencies. |
.github/workflows/tests.yml |
Adds CI workflow running pytest/coverage across a Python matrix. |
ondewo/utils/base_services_interface.py |
Hoists service config/options and applies keepalive defaults; adjusts secure channel handling. |
ondewo/utils/async_base_services_interface.py |
Async equivalent of hoisted config/options and keepalive defaults; adjusts secure channel handling. |
ondewo/utils/async_base_client.py |
Updates async channel close call to include grace=None. |
mypy.ini |
Changes mypy target Python version setting. |
Makefile |
Improves make help discoverability and adds/adjusts target documentation comments. |
CLAUDE.md |
Adds repository/development guidance and conventions. |
RELEASE.md |
Adds 3.2.0 release entry for tests/CI/performance changes. |
ondewo/version.py |
Bumps package version to 3.2.0. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
98
to
105
| def get_secure_channel( | ||
| host: str, | ||
| cert: str, | ||
| options: Optional[List[Tuple[str, Any]]] = None, | ||
| ) -> grpc.Channel: | ||
| credentials = grpc.ssl_channel_credentials(root_certificates=cert) | ||
| # cert is bytes at runtime (BaseClientConfig.__post_init__ encodes it). | ||
| credentials = grpc.ssl_channel_credentials(root_certificates=cast(bytes, cert)) | ||
| return grpc.secure_channel( |
Comment on lines
21
to
29
| from typing import ( | ||
| Any, | ||
| Dict, | ||
| List, | ||
| Optional, | ||
| Set, | ||
| Tuple, | ||
| cast, | ||
| ) |
Comment on lines
91
to
98
| def get_secure_channel( | ||
| host: str, | ||
| cert: str, | ||
| options: Optional[List[Tuple[str, Any]]] = None, | ||
| ) -> grpc.aio.Channel: | ||
| credentials = grpc.ssl_channel_credentials(root_certificates=cert) | ||
| # cert is bytes at runtime (BaseClientConfig.__post_init__ encodes it). | ||
| credentials = grpc.ssl_channel_credentials(root_certificates=cast(bytes, cert)) | ||
| return grpc.aio.secure_channel( |
Comment on lines
22
to
30
| from typing import ( | ||
| Any, | ||
| Dict, | ||
| List, | ||
| Optional, | ||
| Set, | ||
| Tuple, | ||
| cast, | ||
| ) |
Comment on lines
+74
to
+81
| def test_get_secure_channel_builds_credentials() -> None: | ||
| with mock.patch.object(bsi.grpc, "ssl_channel_credentials") as creds, mock.patch.object( | ||
| bsi.grpc, "secure_channel" | ||
| ) as secure_channel: | ||
| channel = get_secure_channel(host="localhost:50051", cert="cert-bytes", options=[]) | ||
| creds.assert_called_once_with(root_certificates="cert-bytes") | ||
| secure_channel.assert_called_once() | ||
| assert channel is secure_channel.return_value |
Comment on lines
+70
to
+77
| def test_get_secure_channel_builds_credentials() -> None: | ||
| with mock.patch.object(absi.grpc, "ssl_channel_credentials") as creds, mock.patch.object( | ||
| absi.grpc.aio, "secure_channel" | ||
| ) as secure_channel: | ||
| channel = get_secure_channel(host="localhost:50051", cert="cert-bytes", options=[]) | ||
| creds.assert_called_once_with(root_certificates="cert-bytes") | ||
| secure_channel.assert_called_once() | ||
| assert channel is secure_channel.return_value |
|
|
||
| [mypy] | ||
| python_version = 3.9 | ||
| python_version = 3.10 |
Comment on lines
1
to
3
| # Generated by synthtool. DO NOT EDIT! | ||
| [bdist_wheel] | ||
| universal = 1 |
…d cythonization support - Add complete PEP 484 type annotations (constants, params, returns, class and local vars) and Google-style docstrings with type info to every source and test module. - Add cython_compile.py to compile the pure-Python ondewo modules into native extensions, skipping @DataClass files (unsupported by Cython) and package markers; build with annotation_typing=False so the new hints do not change compiled behaviour. Add a `make cythonize` target and Cython dev dependency. - Make the Makefile version extraction robust to the annotated __version__. - Ignore missing Cython stubs in mypy config. Verified: mypy clean (21 files), flake8 clean, pytest 49 passed at 100% coverage, and the cythonized .so build imports and passes the full suite.
…and config - get_secure_channel now accepts Union[str, bytes] and normalizes a str cert to bytes instead of using a runtime-noop cast(bytes, cert); drop the unused cast import (sync + async). Tests now assert the bytes value handed to gRPC. - Move pytest/coverage config out of the synthtool-managed setup.cfg into dedicated pytest.ini and .coveragerc so a regeneration cannot clobber it. - Remove the unused `mock` backport dependency (tests use unittest.mock) from requirements-dev.txt and the pytest Docker image. - Document why mypy targets python_version 3.10 (current mypy rejects 3.9). Verified: mypy clean (21 files), flake8 clean, pytest 49 passed at 100% coverage, and both changed modules still cythonize.
Contributor
Author
|
Addressed the Copilot review in
Verified: mypy clean (21 files), flake8 clean, pytest 49 passed at 100% coverage, and the modules still cythonize. |
…aders Bump the copyright end year to 2026 across all source and test file headers (2017-2024 -> 2017-2026, 2020-2024 -> 2020-2026, and the single-year 2021 -> 2021-2026).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a test suite with 100% coverage, a CI workflow, gRPC latency/keepalive tuning, and project documentation to
ondewo-client-utils-python. Bumps the package to3.2.0.Changes
Performance
service_config_jsonand default channel options to module level inbase_services_interface.py/async_base_services_interface.py, so they are serialized once at import instead of on every service construction (a client with N services previously ranjson.dumpsand rebuilt the options dict N times per connection).keepalive_time_ms=30000,max_pings_without_data=0) to keep long-lived streaming RPCs warm and detect half-open connections, whilekeepalive_permit_without_calls=Falseavoids a servertoo_many_pingsGOAWAY on idle channels.Testing
tests/covering everyondewo.utilsmodule to 100% statement and branch coverage (49 tests): sync/async clients and service interfaces, config, container, helpers, and text utilities — happy paths, guard clauses, and secure/insecure/missing-cert branches.setup.cfg(asyncio_mode = auto, branch coverage,--cov-fail-under=100gate).requirements-dev.txtand to the pytest Docker image.CI
.github/workflows/tests.ymlrunning the suite on every push and pull request across Python 3.9–3.12.checkout@v5,setup-python@v6,upload-artifact@v5) to clear the Node 20 deprecation warnings.Docs & housekeeping
CLAUDE.md(repo overview, dev/test commands, ONDEWO conventions).Makefiletarget with a##help comment, fix a misleading description, and makemake helplist digit-containing target names (e.g.flake8).3.2.0with a matchingRELEASE.mdentry.Test plan
python -m pytest→ 49 passed, 100% coverage (gate enforced).pre-commit run --all-files→ flake8, mypy, and all hooks pass.