Metadata-Version: 2.4
Name: fastgrpc2
Version: 0.2.1
Summary: FastAPI-like developer experience for gRPC: pydantic-first, async, built on grpc.aio
Author: Ruslan Kiradiev
License-Expression: MIT
Keywords: grpc,async,fastapi,pydantic,microservices,rpc
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Distributed Computing
Classifier: Framework :: AsyncIO
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2
Requires-Dist: grpcio>=1.60
Requires-Dist: protobuf>=4.21
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Dynamic: license-file

# fastgrpc2

FastAPI-подобная эргономика для gRPC. Pydantic на входе и выходе, вся механика
`grpc.aio` — внутри. Сестра [fastkafka2](../fastkafka2): тот же стиль `App` /
группа / декораторы / lifespan, но для gRPC.

Стек — чистый Python на `grpc.aio` (C-ядро gRPC + upb + pydantic-core). Это
тонкий эргономичный слой, не новый транспорт: потолок = `grpc.aio`, цена —
FastAPI-стиль, а не скорость компилируемых языков.

## Пример

Сервер:

```python
from pydantic import BaseModel
from fastgrpc2 import GrpcApp, GrpcService, Context, Depends, GrpcError, StatusCode

class GetOrderRequest(BaseModel):
    order_number: str

class OrderReply(BaseModel):
    order_number: str
    status: str

service = GrpcService("Orders")

@service.unary("GetOrder")
async def get_order(request: GetOrderRequest, ctx: Context) -> OrderReply:
    if not request.order_number:
        raise GrpcError(StatusCode.INVALID_ARGUMENT, "order_number required")
    return OrderReply(order_number=request.order_number, status="paid")

app = GrpcApp("orders", address="0.0.0.0:50051")
app.add_service(service)
# await app.run()
```

Клиент:

```python
from fastgrpc2 import GrpcClient, Channel

class OrderClient(GrpcClient):
    service = "Orders"
    get_order = GrpcClient.unary("GetOrder", GetOrderRequest, OrderReply)

async with Channel("127.0.0.1:50051", default_timeout=5.0) as ch:
    client = OrderClient(ch)
    reply = await client.get_order(GetOrderRequest(order_number="A-100"))
    print(reply.status)  # -> "paid"
```

## Статус (v0.2) — v1-скоуп закрыт, всё проверено прогоном

- **4 типа вызовов**: `@service.unary` / `unary_stream` / `stream_unary` / `stream_stream`.
- **codec pydantic↔protobuf**: динамические дескрипторы; `bool/int/float/str/bytes`,
  вложенные `BaseModel`, `list[...]`, `Optional[...]` (с proto3-presence). Не
  поддержанное (enum/dict/datetime/Union) — явный `TypeError`, не заглушка.
- **`export_proto()`** — .proto-контракт из моделей.
- **Context**: metadata, deadline (`time_remaining`), trailing-metadata, peer.
- **Metadata** multimap; **GrpcError + StatusCode** + rich-детали (`BadRequest`/
  `ErrorInfo`, через `grpc-status-details-bin`).
- **Клиент**: `Channel` (переиспользуемый) + типизированный `GrpcClient`,
  per-call `timeout`/`metadata`.
- **Безопасность**: `TLS` / `MTLS` / `Insecure` / `BearerToken`.
- **Интерсепторы** (pre-hook auth/логирование), **`Depends` + `dependency_overrides`**.
- **Lifespan**, **graceful `stop(grace)`**, **`run()`**.
- **`enable_health()`** (grpc.health.v1), **`TestClient`** (in-process).
- **Ручки**: `Compression`, `max_send_bytes`/`max_recv_bytes`, `RetryPolicy`,
  `Keepalive`; **deadline-propagation** по цепочке.

Проверочные прогоны (из корня пакета): `smoke_test.py` (вызовы/presence/rich-errors),
`features_test.py` (TestClient/health/bearer/overrides), `tls_test.py` (mTLS),
`config_test.py` (compression/size/interceptor/deadline), `bench.py` (клей-налог
над голым grpc.aio — единицы %).

Later (не v1): write()/done_writing() для bidi-клиента, server reflection, OTel,
Connect/gRPC-Web, отмена-propagation, полный набор 10 google.rpc деталей с
google-namespace type_url.
