To make RPC clients and servers with Python
Project description
Introduction
It is a Python package to make Hobby-RPC clients and servers.
It depends on:
To install:
uv add hobbyrpc
Server
To create a server:
from hobbyrpc import Server
rpc = Server()
@rpc.fun
class FunctionName:
def call(self):
return 'any object serializable to JSON'
@rpc.fun
class OtherFunctionName:
def call(self):
return ['any', 'object', 'serializable', 'to', 'JSON']
In the above example, rpc is a WSGI application.
With multiple options for deployment.
To provide it via a TCP socket with Gunicorn:
uv run gunicorn --bind '127.0.0.1:8000' 'module_name:rpc'
Via Unix socket:
uv run gunicorn --bind unix:/tmp/rpc.socket 'module_name:rpc'
self.input
The raw input of a function can be accessed via self.input.
Here is an example of a function echoing its input back to the client:
@rpc.fun
class Echo:
def call(self):
return self.input
Pydantic
Validation
In most cases, it is advisable to rely on Pydantic for validating input
instead of parsing self.input by other means.
To do so, input fields shall be passed as class annotations. Like so:
@rpc.fun
class ContrivedConcatenation:
first: str
second: str
def call(self):
# self.pydantic provides an instance of Pydantic's BaseModel
# its fields are available as self attributes too:
# self.pydantic.first == self.first
# self.pydantic.second == self.second
return f'{self.first} and {self.second}'
If a client does not pass an input with all required fields or pass a value of a wrong type, the server responds with 400 Bad Request.
Output
Instances of Pydantic's BaseModel can also be used as outputs of RPC functions:
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = 'John Doe'
@rpc.fun
class SomeUser:
def call(self):
user = User(id=1)
return user
@rpc.auth
By default, any client is allowed to call the functions.
To restrict that, use @rpc.auth decorator to define find_user
function as follows:
@rpc.auth
def find_user(token):
if token == 'ValidToken':
return User(id=1)
find_user should be a function that takes one argument, token string.
token is what clients are supposed to pass in the Authorization header.
If find_user returns a falsy value or raises en error,
the server responds with 403 Forbidden.
If find_user returns something else,
the server will assume it is something that represents the current user
and will make it available as self.user:
@rpc.fun
class CurrentUser:
def call(self):
return self.user
CORS
By default, the server sets permissive CORS headers(Access-Control-Allow-Origin: *)
for requests from any origin. To restrict that, pass a list of allowed domains in
origins as follows:
from hobbyrpc import Server
CORS = {
'origins': [
'https://allowed.domain',
'https://www.allowed.domain',
]
}
rpc = Server(
CORS=CORS,
)
Client
Initialize a Client by passing it an address and, optionally, a token too.
Like so:
from hobbyrpc import Client
# via tcp
call = Client(
address='http://127.0.0.1:8080',
token="authorization token",
)
# or via unix socket
call = Client(
address='/tmp/path/to/rpc.socket',
token="authorization token",
)
Call functions remotely. Like so:
input = {
'first': 1,
'second': 2,
}
output = call('SomeUnaryFunction', **input)
output = call('SomeNullaryFunction')
# a call to Compile that compiles CoffeeScript to JavaScript
output = call(
'Compile',
code='answer = 42',
bare=True,
)
input and output are Python objects serializable to and deserializable from JSON.
Development
uv run pytest to run the tests.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hobbyrpc-0.1.2.tar.gz.
File metadata
- Download URL: hobbyrpc-0.1.2.tar.gz
- Upload date:
- Size: 5.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3a64a6493c992b0dbfd92bbf471c4a223b9342160b5458078110b00a5009617
|
|
| MD5 |
bfbd0d041c3ab139e0c84885d233ace4
|
|
| BLAKE2b-256 |
b6684a513d05a893a96fdc0dfec70f77eb5736527226badd183a777d388454d7
|
File details
Details for the file hobbyrpc-0.1.2-py3-none-any.whl.
File metadata
- Download URL: hobbyrpc-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7261d421cb749f764571a15fd24ba8f98fcacf4612602e5a565de2ca89a6297
|
|
| MD5 |
f72c2f6966131e6c7914711eeaaba9da
|
|
| BLAKE2b-256 |
f9cdc8ef771ff5e8faf8f6cc94fa8a45ae6160d9b4b7dc45632118279aafaa2a
|