Skip to content

Commit

Permalink
Isolate compiler_path to compiled() methods (#4)
Browse files Browse the repository at this point in the history
Remove tox.ini, setup.cfg, requirements/ci.txt
Enhance pyproject.toml
Add ruff-powered linting
Add some docstrings
Add examples to README.md
Breaking change1: compiler_path as parameter of compile() instead of ProtoCollection constructor
Breaking change2: rename ProtoCollection.compile() to compiled()
Bump version 0.2.0 -> 1.0.0
  • Loading branch information
decitre authored Feb 5, 2024
1 parent 53d03a5 commit 26da7db
Show file tree
Hide file tree
Showing 16 changed files with 469 additions and 420 deletions.
36 changes: 24 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ on:
- cron: "0 8 * * *"

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e '.[dev]'
- name: Format with Black
run: black .
- name: Lint with Ruff
run: ruff .


py_39_proto_203:
strategy:
fail-fast: false
Expand All @@ -30,17 +48,15 @@ jobs:
- name: install dependencies
run: |
pip install --upgrade pip
pip install --progress-bar=off -r requirements/ci.txt
pip install --progress-bar=off "virtualenv>=16.6.0" "pip>=19.1.1" "setuptools>=18.0.1" "six>=1.14.0" "tox" "tox-gh>=1.2"
pip --version
tox --version
protoc --version
pip freeze
- name: Setup test suite
run: tox -vv --notest
- name: Run test suite
run: |
tox -e check --skip-pkg-install
tox --skip-pkg-install
run: tox --skip-pkg-install

py_31x_proto_252:
strategy:
Expand Down Expand Up @@ -71,17 +87,15 @@ jobs:
- name: install dependencies
run: |
pip install --upgrade pip
pip install --progress-bar=off -r requirements/ci.txt
pip install --progress-bar=off "virtualenv>=16.6.0" "pip>=19.1.1" "setuptools>=18.0.1" "six>=1.14.0" "tox" "tox-gh>=1.2"
pip --version
tox --version
protoc --version
pip freeze
- name: Setup test suite
run: tox -vv --notest
- name: Run test suite
run: |
tox -e check --skip-pkg-install
tox --skip-pkg-install
run: tox --skip-pkg-install

py_3x_proto_25x:
strategy:
Expand All @@ -107,14 +121,12 @@ jobs:
- name: install dependencies
run: |
pip install --upgrade pip
pip install --progress-bar=off -r requirements/ci.txt
pip install --progress-bar=off "virtualenv>=16.6.0" "pip>=19.1.1" "setuptools>=18.0.1" "six>=1.14.0" "tox" "tox-gh>=1.2"
pip --version
tox --version
protoc --version
pip freeze
- name: Setup test suite
run: tox -vv --notest
- name: Run test suite
run: |
tox -e check --skip-pkg-install
tox --skip-pkg-install
run: tox --skip-pkg-install
35 changes: 20 additions & 15 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@
# pre-commit install
# To update the pre-commit hooks run:
# pre-commit install-hooks
exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)'
exclude: '^(\.tox|\.bumpversion\.cfg)(/|$)'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: master
- repo: https://github.com/psf/black
rev: 24.1.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: debug-statements
- repo: https://github.com/timothycrosley/isort
rev: master
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.2.0"
hooks:
- id: isort
- repo: https://gitlab.com/pycqa/flake8
rev: master
- id: ruff
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.0
hooks:
- id: flake8
- repo: https://github.com/psf/black
rev: main
- id: pyupgrade
args: [ --py38-plus ]
- repo: https://github.com/mgedmin/check-python-versions
rev: 0.22.0
hooks:
- id: black
- id: check-python-versions
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: debug-statements
15 changes: 15 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Testing

pip install -e '.[dev]'
pre-commit autoupdate
pre-commit install
pre-commit run --all-files
tox

On a macos machine:

tests/tox_mac.sh

## Releasing

TBD
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of

The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4 changes: 2 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ graft tests

include .bumpversion.cfg
include .coveragerc
include tox.ini
include pyproject.toml
include .github/workflows/test.yml
include .pre-commit-config.yaml
include LICENSE
include README.md
recursive-include requirements *.txt
include CONTRIBUTING.md


global-exclude *.py[cod] __pycache__/* *.so *.dylib
84 changes: 71 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,26 @@
[![python version][python_versions_badge]][pypi]
[![python implementation][python_implementation_badge]][pypi]

A tool that
- takes a `str` containing protobuf messages definitions
A tool that
- takes a `str` containing protobuf messages definitions
- returns a `types.ModuleType` instance

It is useful for Python programs needing to parse protobuf messages without having to host `.proto` files in their code base.

It is useful for Python programs needing to en/decode protobuf messages for which the definition is provided as a string at runtime.

## Installation

pip install proto-topy

## Example: address book
## single proto example: address book

Adaptation of the `protocolbuffers` [example](https://github.com/protocolbuffers/protobuf/tree/main/examples):

```python
import requests
import sys
from shutil import which
from proto_topy.entities import ProtoModule
from pathlib import Path
from proto_topy import ProtoModule

# Retrieve protobuf messages definitions
# Retrieve protobuf messages definitions as a string
example_source = requests.get(
"https://raw.githubusercontent.com/protocolbuffers/protobuf/main/"
"examples/addressbook.proto").text
Expand All @@ -35,9 +32,7 @@ example_path = Path(
"protocolbuffers/protobuf/blob/main/examples/addressbook.proto")

# Compile and import
module = (ProtoModule(file_path=example_path, source=example_source)
.compiled(Path(which("protoc"))))
sys.modules["addressbook"] = module.py
module = ProtoModule(file_path=example_path, source=example_source).compiled()

# Produce a serialized address book
address_book = module.py.AddressBook()
Expand All @@ -59,6 +54,69 @@ with open("address_book.data", "rb") as i:
print(person.id, person.name, person.email, phone_number.number)
```

## multiple protos example

When several `.proto` need to be considered, use a `ProtoCollection`:

```python
import sys
from pathlib import Path
from proto_topy import ProtoModule, ProtoCollection

module1 = ProtoModule(
file_path=Path("p1/p2/other2.proto"),
source="""
syntax = "proto3";
import "google/protobuf/timestamp.proto";
message OtherThing2 {
google.protobuf.Timestamp created = 1;
};"""
)

module2 = ProtoModule(
file_path=Path("p3/p4/test6.proto"),
source="""
syntax = "proto3";
import "p1/p2/other2.proto";
message Test6 {
OtherThing2 foo = 1;
};"""
)

collection = ProtoCollection(module1, module2).compiled()
sys.modules.update({proto.name: proto.py
for proto in collection.modules.values()})
print(sys.modules['test6'].Test6,
sys.modules['other2'].OtherThing2)
```
## Stream of delimited messages

To decode a stream of contiguous protobuf messages of the same type, use `DelimitedMessageFactory`. Example:

```python
from io import BytesIO
from pathlib import Path
from proto_topy import ProtoModule, DelimitedMessageFactory

# Generate Python module
module = ProtoModule(
file_path=Path("int32_streams.proto"),
source="""
syntax = "proto3";
message TestInt { int32 val = 1; };"""
).compiled()

# Feed a DelimitedMessageFactory with a sequence of TestInt instances for a range of 10 ints
integers = (module.py.TestInt(val=val) for val in range(10))
factory = DelimitedMessageFactory(BytesIO(), *integers)

# Rewind and read the stream of 10 protobuf messages
factory.rewind()
for offset_val in factory.message_read(module.py.TestInt):
print(f"TestInt message of val set to {offset_val[1]}")
```



[pypi]: https://pypi.org/project/proto-topy
[test_badge]: https://github.com/decitre/python-proto-topy/actions/workflows/test.yml/badge.svg
Expand All @@ -67,4 +125,4 @@ with open("address_book.data", "rb") as i:
[wheel_badge]: https://img.shields.io/pypi/wheel/proto-topy.svg
[python_versions_badge]: https://img.shields.io/pypi/pyversions/proto-topy.svg
[python_implementation_badge]: https://img.shields.io/pypi/implementation/proto-topy.svg
[tests]: tests/test_proto_topy.py
[tests]: tests/test_proto_topy.py
Loading

0 comments on commit 26da7db

Please sign in to comment.