Metadata-Version: 2.1
Name: hyper-rpc
Version: 0.0.1a4
Summary: Simple RPC with Protobuf Services
Home-page: https://github.com/hyperpy/hyper-rpc
Author: decentral1se
Author-email: hi@decentral1.se
Maintainer: decentral1se
Maintainer-email: hi@decentral1.se
Requires-Python: >=3.6,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Requires-Dist: grpcio_tools (>=1.31.0,<2.0.0)
Requires-Dist: purerpc (>=0.6.1,<0.7.0)
Project-URL: Repository, https://github.com/hyperpy/hyper-rpc
Description-Content-Type: text/markdown

# hyper-rpc

[![Build Status](https://drone.autonomic.zone/api/badges/hyperpy/hyper-rpc/status.svg)](https://drone.autonomic.zone/hyperpy/hyper-rpc)

## Simple RPC with Protobuf Services

Uses [grpcio_tools](https://pypi.org/project/grpc-tools) and [purerpc](https://github.com/standy66/purerpc) under the hood.

## Install

```sh
$ pip install hyper-rpc
```

## Example

> **TLDR; See the [example](./example) directory**

Define an RPC service in a `greeter.proto`.

```protobuf
syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayHelloGoodbye (HelloRequest) returns (stream HelloReply) {}
  rpc SayHelloToMany (stream HelloRequest) returns (stream HelloReply) {}
  rpc SayHelloToManyAtOnce (stream HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
```

Then generate the services and stubs with `hyper-rpc`.

```sh
$ pip install hyper-rpc
$ hrpc greeter.proto
```

This creates `greeter_gprc.py` (services) and `greeter_pb2.py` (stubs) files.

You can then write an async-ready server.

```python
"""Greeter server."""

from greeter_grpc import GreeterServicer
from greeter_pb2 import HelloReply, HelloRequest
from purerpc import Server


class Greeter(GreeterServicer):
    async def SayHello(self, message):
        return HelloReply(message=f"Hello {message.name}")

    async def SayHelloToMany(self, input_messages):
        async for message in input_messages:
            yield HelloReply(message=f"Hello, {message.name}")


if __name__ == "__main__":
    server = Server(50055)
    server.add_service(Greeter().service)
    server.serve(backend="trio")

```

And a client.

```python
"""Greeter client."""

import anyio
import purerpc
from greeter_grpc import GreeterStub
from greeter_pb2 import HelloReply, HelloRequest


async def gen():
    for i in range(5):
        yield HelloRequest(name=str(i))


async def main():
    async with purerpc.insecure_channel("localhost", 50055) as channel:
        stub = GreeterStub(channel)
        reply = await stub.SayHello(HelloRequest(name="World"))
        print(reply.message)

        async for reply in stub.SayHelloToMany(gen()):
            print(reply.message)


if __name__ == "__main__":
    anyio.run(main, backend="trio")
```

And run them in separate terminals to see the output.

```
$ python server.py # terminal 1
$ python client.py # terminal 2
```

Output:

```
Hello, World
Hello, 0
Hello, 1
Hello, 2
Hello, 3
Hello, 4
```

Go forth and [Remote Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call).

![The person who invented the term RPC](https://upload.wikimedia.org/wikipedia/en/9/90/BruceJayNelson.JPG)

