Typing
Specifying type hints allows Lightbus to validate data types in both incoming and outgoing messages.
Type hints are used to create your bus' schema, which is shared across your entire bus.
Typing syntax for RPCs¶
You can provide typing information for Remote Procedure Calls using regular Python type hinting:
class AuthApi(lightbus.Api):
    class Meta:
        name = 'auth'
    def check_password(self, username: str, password: str) -> bool:
        return username == 'admin' and password == 'secret'
This will:
- Ensure the received usernameparameter is a string
- Ensure the received passwordparameter is a string
- Ensure the returned value is a boolean
This behaviour can be configured via the validate configuration option.
Typing syntax for events¶
Typing information for events is different to that for RPCs. Firstly, events do not provide return values. Secondly, event parameters are specified differently:
# auth_service/bus.py
from lightbus import Api, Event, Parameter
class AuthApi(Api):
    # WITHOUT types
    user_created = Event(parameters=('username', 'email', 'is_admin'))
    # WITH types
    user_created = Event(parameters=(
        Parameter('username', str),
        Parameter('new_email', str),
        Parameter('is_admin', bool, default=False),
    ))
This will:
- Ensure the received usernameparameter is a string
- Ensure the received new_emailparameter is a string
- Ensure the received is_adminparameter is a boolean. If omitted,Falsewill be used.
This behaviour can be configured via the validate configuration option.
Data structures¶
In additional to built in types, Lightbus can derive typing information from the following data structures:
- Named Tuples
- Dataclasses
- Any class defining the __to_bus__and__from_bus__methods
For each of these data structures Lightbus will:
- Encode values as JSON objects (i.e. dictionaries)
- Use the structure's type hints in generating the JSON schema...
- ... and therefore validate incoming/outgoing objects against this schema
NamedTuple example¶
# bus.py
from lightbus import Api
from typing import NamedTuple
class User(NamedTuple):
    username: str
    name: str
    email: str
    is_admin: bool = False
class AuthApi(Api):
    class Meta:
        name = 'auth'
    def get_user(self, username: str) -> User:
        return ...
Dataclass example¶
Lightbus supports dataclasses in the same way as it supports named tuples. For example:
# bus.py
from lightbus import Api
from dataclasses import dataclass
@dataclass()
class User():
    username: str
    name: str
    email: str
    is_admin: bool = False
class AuthApi(Api):
    class Meta:
        name = 'auth'
    def get_user(self, username: str) -> User:
        return ...
Custom class example¶
Lightbus can also work with classes of any type provided that:
- The class defines a __from_bus__(self, value)class method, which returns an instance of the class. Ifvalueis a dict, it will be best-effort cased to the class' type annotations before__from_bus__is invoked.
- The class defines a __to_bus__(self)method which both annotates its return type, and returns a value suitable for serialising on the bus.
from lightbus import Api
class User:
    username: str
    name: str
    email: str
    is_admin: bool = False
    def do_something(self):
        pass
    @classmethod
    def __from_bus__(cls, value):
        user = cls()
        user.username = value["username"]
        user.name = value["name"]
        user.email = value["email"]
        user.is_admin = value.get("is_admin", False)
        return user
    def __to_bus__(self) -> dict:
        return dict(
            username=self.username,
            name=self.name,
            email=self.email,
            is_admin=self.is_admin,
        )
class AuthApi(Api):
    class Meta:
        name = 'auth'
    def get_user(self, username: str) -> User:
        return ...