Skip to content

Commit

Permalink
Merge pull request #2 from zerlok/dev
Browse files Browse the repository at this point in the history
prepare for first release
  • Loading branch information
zerlok authored Aug 22, 2024
2 parents f53afcb + 8d3ca84 commit fbbe628
Show file tree
Hide file tree
Showing 33 changed files with 776 additions and 503 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Publish Python Package

on:
release:
types: [published]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: abatilo/actions-poetry@v2
- name: Poetry build
run: poetry build -n
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
53 changes: 53 additions & 0 deletions .github/workflows/pull-request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Check On Pull Request

on:
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
protoc-version: [ "26.1" ]
buf-version: [ "1.31.0" ]
steps:
- uses: actions/checkout@v4
- name: Install Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
# see details (matrix, python-version, python-version-file, etc.)
# https://github.com/actions/setup-python
- name: Install poetry
uses: abatilo/actions-poetry@v2
- name: Setup a local virtual environment (if no poetry.toml file)
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
- uses: actions/cache@v3
name: Define a cache for the virtual environment based on the dependencies lock file
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}
- name: Install the project dependencies
run: poetry install --all-extras
- name: Download protoc ${{ matrix.protoc-version }}
run: wget -q -O protoc.zip "https://github.com/protocolbuffers/protobuf/releases/download/v${{ matrix.protoc-version }}/protoc-${{ matrix.protoc-version }}-linux-x86_64.zip"
- name: Unzip protoc ${{ matrix.protoc-version }}
run: unzip -q -n protoc.zip 'bin/*' 'include/google/protobuf/*' -d .venv
- name: Download buf ${{ matrix.buf-version }}
run: wget -q -O .venv/bin/buf "https://github.com/bufbuild/buf/releases/download/v${{ matrix.buf-version }}/buf-Linux-x86_64"
- name: Allow run buf ${{ matrix.buf-version }}
run: chmod +x .venv/bin/buf
- name: Run mypy
run: poetry run mypy
- name: Run pytest
run: poetry run pytest
- name: Run ruff format
run: poetry run ruff format --check
- name: Run ruff format
run: poetry run ruff format --check
91 changes: 69 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,24 @@ install
poetry add pyprotostuben
```

available executables:
### protoc-gen-pyprotostuben

* `protoc-gen-pyprotostuben` -- a protoc plugin that generates MyPy stubs
a protoc plugin that generates MyPy stubs

#### features

* choose message structure immutability / mutability
* choose async / sync grpc module stubs
* grpc servicer abstract methods have full signature (with appropriate type args in generics), thus it is easier to
implement methods in IDE

#### flags

* `message-mutable` -- add setters for fields, use mutable containers
* `message-all-init-args-optional` -- each field is optional in message constructor (event if required)
* `grpc-sync` -- use sync grpc stubs instead of grpc.aio module and async defs
* `grpc-skip-servicer` -- don't generate code for servicers
* `grpc-skip-stub` -- don't generate code for stubs

## examples

Expand All @@ -25,16 +40,22 @@ available executables:

* /
* src/
* foo.proto
* greeting.proto
```protobuf
syntax = "proto3";

package bar;

message Spam {
string eggs = 1;
repeated int64 pizza = 2;
optional string apple = 3;

package greeting;

message GreetRequest {
string name = 1;
}

message GreetResponse {
string text = 1;
}

service Greeter {
rpc Greet(GreetRequest) returns (GreetResponse) {}
}
```
* buf.yaml
Expand Down Expand Up @@ -63,30 +84,56 @@ buf generate

#### output

##### src/foo_pb2.pyi
##### src/greeting_pb2.pyi

```python
import builtins
import google.protobuf.message
import typing

import google.protobuf.message
class GreetRequest(google.protobuf.message.Message):

def __init__(self, *, name: builtins.str) -> None:...

@builtins.property
def name(self) -> builtins.str:...

class Spam(google.protobuf.message.Message):
def HasField(self, field_name: typing.NoReturn) -> typing.NoReturn:...

def __init__(self, *, eggs: builtins.str, pizza: typing.Sequence[builtins.int],
apple: typing.Optional[builtins.str] = None) -> None: ...
def WhichOneof(self, oneof_group: typing.NoReturn) -> typing.NoReturn:...

@builtins.property
def eggs(self) -> builtins.str: ...
class GreetResponse(google.protobuf.message.Message):

@builtins.property
def pizza(self) -> typing.Sequence[builtins.int]: ...
def __init__(self, *, text: builtins.str) -> None:...

@builtins.property
def apple(self) -> builtins.str: ...
def text(self) -> builtins.str:...

def HasField(self, field_name: typing.NoReturn) -> typing.NoReturn:...

def WhichOneof(self, oneof_group: typing.NoReturn) -> typing.NoReturn:...
```

##### src/greeting_pb2_grpc.pyi

```python
import abc
import builtins
import greeting_pb2
import grpc
import grpc.aio
import typing

class GreeterServicer(metaclass=abc.ABCMeta):

@abc.abstractmethod
async def Greet(self, request: greeting_pb2.GreetRequest, context: grpc.aio.ServicerContext[greeting_pb2.GreetRequest, greeting_pb2.GreetResponse]) -> greeting_pb2.GreetResponse:...

def add_GreeterServicer_to_server(servicer: GreeterServicer, server: grpc.aio.Server) -> None:...

class GreeterStub:

def HasField(self, field_name: typing.Literal['apple']) -> bool: ...
def __init__(self, channel: grpc.aio.Channel) -> None:...

def WhichOneof(self, oneof_group: typing.NoReturn) -> typing.NoReturn: ...
async def Greet(self, request: greeting_pb2.GreetRequest, *, timeout: typing.Optional[builtins.float]=None, metadata: typing.Optional[grpc.aio.MetadataType]=None, credentials: typing.Optional[grpc.CallCredentials]=None, wait_for_ready: typing.Optional[builtins.bool]=None, compression: typing.Optional[grpc.Compression]=None) -> grpc.aio.UnaryUnaryCall[greeting_pb2.GreetRequest, greeting_pb2.GreetResponse]:...
```
Loading

0 comments on commit fbbe628

Please sign in to comment.