Metadata-Version: 2.4
Name: blackbull-protobuf
Version: 0.2.0
Summary: Protobuf integration for the BlackBull ASGI framework's gRPC support: servicer adapter, server reflection, health checking, and rich error details.
Author: TOKUJI
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/TOKUJI/blackbull-protobuf
Project-URL: Repository, https://github.com/TOKUJI/blackbull-protobuf
Project-URL: Changelog, https://github.com/TOKUJI/blackbull-protobuf/blob/master/CHANGELOG.md
Project-URL: Issues, https://github.com/TOKUJI/blackbull-protobuf/issues
Project-URL: BlackBull framework, https://github.com/TOKUJI/BlackBull
Keywords: asgi,blackbull,grpc,protobuf,reflection,health
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: blackbull>=0.51.0
Requires-Dist: protobuf>=4.25
Requires-Dist: googleapis-common-protos>=1.60
Provides-Extra: testing
Requires-Dist: pytest; extra == "testing"
Requires-Dist: pytest-asyncio; extra == "testing"
Requires-Dist: pytest-timeout; extra == "testing"
Requires-Dist: blackbull[testing]>=0.51.0; extra == "testing"
Requires-Dist: grpcio-tools; extra == "testing"
Dynamic: license-file

# blackbull-protobuf

Protobuf integration for the [BlackBull](https://github.com/TOKUJI/BlackBull)
ASGI framework's gRPC support: object-typed servicers, server reflection,
health checking, and rich error details.

BlackBull's core gRPC layer (`blackbull.grpc`) is deliberately
**protobuf-free** — handlers exchange raw message bytes. This package adds
everything whose payloads *are* protobuf on the wire, as a separate
installable so the protobuf runtime never enters the framework's dependency
metadata and can version independently.

```
pip install 'blackbull[protobuf]'      # or: pip install blackbull-protobuf
```

## Object-typed handlers (`add_servicer`)

Write servicers against your generated `*_pb2` messages. The adapter reflects
over the service descriptor, wires every implemented method onto a
`GrpcServiceRegistry` with the right streaming shape, and does
`FromString`/`SerializeToString` at the boundary:

```python
from blackbull import BlackBull
from blackbull.grpc import GrpcServiceRegistry
from blackbull_protobuf import add_servicer
import helloworld_pb2

class Greeter:                       # duck-typed; a generated
    async def SayHello(self, request, context):        # <Service>Servicer
        return helloworld_pb2.HelloReply(               # base also works
            message=f'Hello, {request.name}!')

    async def SayManyHellos(self, request, context):   # server-streaming
        for i in range(3):
            yield helloworld_pb2.HelloReply(message=f'{request.name} #{i}')

app = BlackBull()
registry = GrpcServiceRegistry()
add_servicer(registry, Greeter(), helloworld_pb2)
app.enable_grpc(registry)
app.run(port=8443, cert='cert.pem', key='key.pem')
```

All four RPC shapes are supported — unary, server-streaming (async
generator), client-streaming (`request_iter` of messages), and bidirectional.
The raw-bytes registry path is untouched; both styles coexist on one registry.

## Server reflection

`grpcurl` / `grpc_cli` / Postman work without local `.proto` files:

```python
from blackbull_protobuf import enable_reflection
enable_reflection(registry)   # serves both grpc.reflection.v1 and v1alpha
```

Both reflection package versions are registered — `v1alpha` for older
clients and `v1` for the newer ones that probe it first — so every client
generation resolves the endpoint on the first request.

```console
$ grpcurl -insecure localhost:8443 list
$ grpcurl -insecure localhost:8443 describe helloworld.Greeter
$ grpcurl -insecure -d '{"name": "world"}' localhost:8443 helloworld.Greeter/SayHello
```

## Health checking

The standard `grpc.health.v1.Health` service (`Check` + `Watch`) behind a
settable status map — the Kubernetes / load-balancer probe surface:

```python
from blackbull_protobuf import enable_health, HealthService

health = enable_health(registry)
health.set('helloworld.Greeter', HealthService.SERVING)
health.set('helloworld.Greeter', HealthService.NOT_SERVING)   # during drain
```

## Rich error details

Attach structured `google.rpc` details that ride the
`grpc-status-details-bin` trailer, decoded on a grpcio client by
`grpc_status.rpc_status.from_call`:

```python
from google.rpc import error_details_pb2
from blackbull.grpc import GrpcStatus
from blackbull_protobuf import abort_with_details

bad = error_details_pb2.BadRequest()
bad.field_violations.add(field='name', description='must not be empty')
abort_with_details(context, GrpcStatus.INVALID_ARGUMENT,
                   'name is required', [bad])
```

## Design notes

- The vendored `grpc.health.v1` / `grpc.reflection.v1alpha` /
  `grpc.reflection.v1` descriptors are embedded as serialized
  `FileDescriptorProto`s and loaded into a **private** descriptor pool — no
  generated code (so no protoc↔runtime version-lock), and no duplicate-file
  collision when the host application also imports
  `grpcio-health-checking` / `grpcio-reflection` gencode.
- Reflection describes every service registered through this package and
  *lists* raw-bytes services too (they have no descriptors to describe).
- Requires BlackBull ≥ 0.51.0 (the error-path trailing-metadata contract that
  `grpc-status-details-bin` rides on).

## Development

```
pip install -e '.[testing]'
python -m pytest tests/ -q
python scripts/gen_descriptors.py     # after touching protos/
```

License: Apache-2.0.
