The module provides functionality to expose Python functions to be called remotely over ethernet.
Project description
Remotecall
The module provides functionality to expose Python functions to be called remotely over ethernet.
The implementation uses Python's http.server.HTTPServer to implement a server side functionality and Request for client implementation.
Getting started
Exposing a function to be called remotely.
Server
Create a server and expose a function.
from remotecall import Server
def hello() -> str:
return "Hello World"
with Server(("localhost", 8000)) as server:
server.expose(hello)
server.serve_forever()
Client
Subclass a client from BaseClient to call exposed functions.
from remotecall import Server
class Client(BaseClient):
def hello(self) -> str:
return self.call("hello")
client = Client(("localhost", 8000))
client.hello()
Code generation
Use the module to generate client code instead of writing the client code.
python -m remotecall generate_client http://localhost:8000
Usage
Basic example
Server side implementation to expose hello() function:
from remotecall import Server
def hello() -> str:
return "Hello World"
with Server(server_address=("localhost", 8000)) as server:
server.register(hello)
server.serve_forever()
Client side implementation is based on BaseClient class which is a thin wrapper around Requests module.
from remotecall import BaseClient
client = BaseClient(server_address=("localhost", 8000))
client.call("hello")
Subclassing BaseClient makes accessing the available functions more convenient - for example, by enabling IDE autocompletion and providing the type information.
from remotecall import BaseClient
class Client(BaseClient):
def hello(self) -> str:
return self.call("hello")
client = Client(server_address=("localhost", 8000))
client.hello()
Usage of python -m remotecall generate_client
automates the client code generation.
For more example, see examples directory.
Passing arguments
Module uses Python type annotations to determine type of parameter and return values.
The type information is used to generate API definition. The API definition is provided in JSON format and can be used to generate client code.
The type information is also used to encode and decode data - like parameter and return values - send between client and server.
The implementation support basic Python data types including bytes
, int
, float
, bool
, str
,
list
, tuple
and dict
. It is possible to add support for addition types. See examples
directory for an implementation for PIL Images and NumPy arrays.
Server
Exposing a function with parameters and return value.
def echo(message: str) -> str:
return message
Client
Calling the function from the client side.
class Client(BaseClient):
def echo(self, message: str) -> str:
return self.call("echo", message=message)
HTTPS and SSL
By default, the server uses HTTP for the communication. HTTPS communication can be enabled by providing SSL certificate. The certificate is used to create a SSLContext to wrap the underlying socket instance.
See examples folder for an example and instructions to generate a self-signed certificate.
Server
server = Server(...)
server.use_ssl(cert_file="server.crt", key_file="server.key")
Client
client = BaseClient(...)
client.use_ssl(cert_file="server.pem")
Authentication
By default, the server does not require authentication.
Server provides an implementation for HTTP basic authenticator that can be set in use as
demonstrated below. However, it's also possible to subclass
remotecall.authentication.Authenticator
and implement other type of authenticators.
Client implementation wraps Requests library and makes it possible to use the authentication methods available for that library. More documentation can be found from the library documentation https://requests.readthedocs.io/en/latest/user/authentication/.
Server
server = Server(...)
server.set_authenticator(BasicAuthenticator("user", "pass"))
Client
from requests.auth import HTTPBasicAuth
client = BaseClient(...)
client.set_authentication(HTTPBasicAuth("user", "pass"))
Implementing authenticator
Implementing a custom authenticator begins with subclassing remotecall.authentication. Authenticator
.
Authenticator is expected to implement authenticate
method to carry out the authentication. It
is called right after the HTTP server's do_*
method gets called.
authenticate
method receives an instance of
BaseHTTPRequestHandler
that represents the HTTP request received by the HTTP server and to handle it.
Authenticator
is expected to handle the actions required to carry out the authentication.
It may raise AuthenticationError
if the server should not continue processing the request.
Server expects the authenticator to resolves the request by sending the corresponding headers and
related data.
class Authenticator(ABC):
@abstractmethod
def authenticate(self, request: BaseHTTPRequestHandler):
"""Do the authentication."""
Code generation
The module provides an easy way to generate a Python client for a service provided by a server.
The API definition can be fetched from the server with the following command line command. The command returns an API definition in JSON format.
$ python -m remotecall fetch_api http://localhost:8000
For example, in case of echo example the output would be:
{
"endpoints": [
{
"name": "echo",
"documentation": "",
"parameters": [
{
"name": "message",
"type": "str"
}
],
"return_type": "str"
}
],
"ssl_enabled": false,
"address": {
"hostname": "localhost",
"port": 8000
}
}
The API definition can be written in a file with output
option.
$ python -m remotecall fetch_api http://localhost:8000 --output api.json
Client code can be generated based on the definition:
$ python -m remotecall generate_client api.json --output client.py
Where, output
defines the output file.
By default, the client class is named as Client
. This can be changed by using name
option. For example, --name EchoClient
.
The above steps can be combined if the intermediate results are not needed.
$ python -m remotecall generate_client http://localhost:8000 --output client.py
Extending supported data type
See examples/image and examples/numpy for image and numpy codec examples.
Development
Set up virtual environment
Create virtual environment:
python3 -m venv venv
Activate virtual environment:
source venv/bin/activate
Running from source
pip install -e .
Installing from source
pip install .
python -m remotecall
Running tests
pip install .[test]
pytest
py.test -s
Building
Creating a wheel
$ pip install wheel
$ python setup.py bdist_wheel
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
Hashes for remotecall-0.3.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 42a6d05f4e3fb43b9e4df18d500aa4aa53026cffda188ba3b33d49b3e1b99af1 |
|
MD5 | c816e6b6fecb251ceab3b8b34df9b2ec |
|
BLAKE2b-256 | a968f8b71f7700bb10a9d51f897aff94386e628672d57da7b34396a047ff7f1c |