Operations
What are operations?
With client-server communication, Hoist has two fundamental items, the first being operations, and the second one being messages, which we will talk about more later.
Think of an operation like a function call. We send a name and some data to the server, and then it sends back the response.
An operation could look like this:
sequenceDiagram
Client->>Server: Execute operation x with data {...}
alt Error Occured
Server->>Client: Error occured while executing: {...}
else
Server->>Client: Response of operation is ...
end
Whitelisting and Blacklisting
Hoist comes with some operations out of the box. By default, all of these are enabled.
To blacklist one, pass its name to the unsupported_operations
keyword argument:
import hoist
server = hoist.start(unsupported_operations=("print",))
# all operations work except print
If you would like a whilelist instead, pass the whitelisted names to the supported_operations
argument:
import hoist
server = hoist.start(supported_operations=("print",))
# no operations work except print
You may also disable all operations by passing a sequence (such as tuple
) containing "*"
:
Custom Operations
We can define operations ourself by using the operation
decorator.
Here's a quick example:
import hoist
server = hoist.start(...)
@server.operation("my custom operation")
async def operation():
return "hello world"
This isn't very useful though, since we aren't getting any arguments from the user.
Getting Parameters
Hoist will try to figure out what parameters you want based off the signature of the function.
The recommended way to is to use type hints, but you can do it without them.
Server and Payload
Server Only
import hoist
server = hoist.start(...)
@server.operation("...")
async def operation(server: hoist.Server):
...
Payload Only
Dynamic Parameters
Payload Validation
You can hint a dataclass (such as NamedTuple
) as your payload to get Hoist to validate the sent payload.
Note
Hoist uses the __annotations__
attribute to create schemas for validation. Any custom payload object should contain that with corresponding attributes.
Here's an example:
import hoist
from typing import NamedTuple
server = hoist.start(...)
class MyPayload(NamedTuple):
a: str
b: int
@server.operation("...")
async def operation(payload: MyPayload):
...
The above would make Hoist ensure that the payload sent by the client looks like this: