Skip to content

klen/muffin-grpc

Muffin-GRPC

Tests Status PyPI Version

Muffin-GRPC is a plugin for the Muffin framework that brings gRPC support to your application.

  • 📦 Automatically compiles .proto files to Python
  • ⚙️ Simplified gRPC server and client integration
  • 🔁 CLI commands to manage proto compilation and server lifecycle
  • 🧩 Automatically handles proto dependencies and import fixes
  • 🧪 Designed with asyncio and modern Python standards
  • Python >= 3.10
  • grpcio
  • grpcio-tools
  • protobuf
  • muffin

Note

This plugin supports only the asyncio event loop (Trio is not supported).

Install via pip:

pip install muffin-grpc

Set up the plugin and attach it to your Muffin application:

from muffin import Application
from muffin_grpc import Plugin as GRPC

app = Application("example")
grpc = GRPC(default_channel="localhost:50051")
grpc.setup(app)

Create a helloworld.proto:

syntax = "proto3";

package helloworld;

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

Register the file:

grpc.add_proto("project_name/proto/helloworld.proto")

Compile proto files:

muffin project_name grpc_build

This generates:

  • helloworld_pb2.py — messages
  • helloworld_pb2_grpc.py — gRPC services
  • helloworld.py — bundled import helper
  • __init__.py — so the folder is importable

Note

Muffin-GRPC automatically fixes Python imports.

Now implement the Greeter service:

from .proto.helloworld import GreeterServicer, HelloReply, HelloRequest
import grpc.aio as grpc_aio

@grpc.add_to_server
class Greeter(GreeterServicer):

    async def SayHello(
        self, request: HelloRequest, context: grpc_aio.ServicerContext
    ) -> HelloReply:
        return HelloReply(message=f"Hello, {request.name}!")

Run the gRPC server:

muffin project_name grpc_server

Client example:

from .proto.helloworld import GreeterStub, HelloRequest
from aiohttp.web import Application, Response

@app.route("/")
async def index(request):
    name = request.url.query.get("name", "anonymous")
    try:
        async with grpc.get_channel() as channel:
            stub = GreeterStub(channel)
            response = await stub.SayHello(HelloRequest(name=name), timeout=10)
            return Response(text=response.message)

    except grpc_aio.AioRpcError as exc:
        return Response(text=exc.details())

You can configure the plugin either via setup() or using GRPC_ prefixed settings in the Muffin app config.

Available options:

Name Default value Description
build_dir None Directory to store compiled files
server_listen "[::]:50051" gRPC server address
ssl_server False Enable SSL for server
ssl_server_params None Tuple of credentials for SSL server
ssl_client False Enable SSL for client
ssl_client_params None Tuple of credentials for SSL client
default_channel "localhost:50051" Default gRPC client target
default_channel_options {} Additional gRPC options

Via setup():

grpc.setup(app, server_listen="localhost:40000")

Or from config:

GRPC_SERVER_LISTEN = "localhost:40000"

Build registered proto files:

muffin project_name grpc_build

Start the gRPC server:

muffin project_name grpc_server

Found a bug or have a suggestion? Submit an issue here: https://github.com/klen/muffin-grpc/issues

Want to contribute? Pull requests are welcome! Development happens at: https://github.com/klen/muffin-grpc

Licensed under the MIT license.

About

GRPC Support for Muffin Framework

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •