labthings_fastapi.server
Code supporting the LabThings server.
LabThings wraps the fastapi.FastAPI application in a ThingServer, which
provides the tools to serve and manage Thing instances.
See the LabThings-FastAPI tutorial for examples of how to set up a ThingServer.
Submodules
Classes
Use FastAPI to serve |
Package Contents
- class labthings_fastapi.server.ThingServer(config: config_model.ThingServerConfig, *, debug: bool = False)
- class labthings_fastapi.server.ThingServer(*, debug: bool = False, **kwargs: Any)
Use FastAPI to serve
Thinginstances.The
ThingServersets up afastapi.FastAPIapplication and uses it to expose the capabilities ofThinginstances over HTTP.There are several functions of a
ThingServer:Manage where settings are stored, to allow
Thinginstances to load and save their settings from disk.Configure the server to allow cross-origin requests (required if we use a web app that is not served from the
ThingServer).Manage the threads used to run Actions.
Manage Blob input/output to allow binary data to be returned.
Allow threaded code to call functions in the event loop, by providing an
anyio.from_thread.BlockingPortal.
Initialise a LabThings server.
The
ThingServeris responsible for running the code inThinginstances, and making them available over the network. It should be configured by passing aThingServerConfigobject (or a dictionary that can be validated as aThingServerConfigobject).For convenience and backwards compatibility, if
configisNonethe keyword arguments will be passed toThingServerConfiginstead. Keyword arguments may not be used if theconfigargument is used, and may be removed in the future.Setting up the
ThingServerinvolves creating the underlyingfastapi.FastAPIapp, setting its lifespan function (used to set up and shut down theThinginstances), and configuring it to allow cross-origin requests.- Parameters:
config – a
ThingServerConfigobject that configures the server, or something that may be converted to one.debug – ff
True, set the log level forThinginstances to DEBUG.**kwargs – ff keyword arguments are supplied, they will be passed to the constructor of
ThingServerConfig. This is not allowed ifconfigis aThingServerConfigobject.
- Raises:
TypeError – if the value of
configcannot be parsed as aThingServerConfig.ValueError – if keyword arguments are supplied together with
config.
- _debug = False
- app
- action_manager
- message_broker
- blocking_portal: anyio.from_thread.BlockingPortal | None = None
- global_lock
- _things
- classmethod from_things(things: config_model.ThingsConfig, debug: bool = False, **kwargs: Any) Self
Create a ThingServer using a dictionary of
Thingsubclasses.In test and example code, it’s convenient to be able to pass server and
Thingconfigurations as keyword arguments rather than a config model.This convenience method will turn its keyword arguments into a server configuration and create a server based on it.
- Parameters:
things – A mapping of names to
Thingconfigurations. These may be specified as aThingConfigobject, aThingsubclass, or an import string referencing aThingsubclass.debug – Whether to start the server in debug mode.
**kwargs – Additional keyword arguments are passed to
ThingServerConfig.
- Returns:
a
ThingServerinstance.
- classmethod from_config(config: config_model.ThingServerConfig, debug: bool = False) Self
Create a ThingServer from a configuration model.
This is equivalent to
ThingServer(config, debug=debug).- Parameters:
config – The configuration parameters for the server.
debug – If
True, set the log level forThinginstances to DEBUG.
- Returns:
A
ThingServerconfigured as per the model.
- _set_cors_middleware() None
Configure the server to allow requests from other origins.
This is required to allow web applications access to the HTTP API, if they are not served from the same origin (i.e. if they are not served as part of the
ThingServer.).This is usually needed during development, and may be needed at other times depending on how you are using LabThings.
- _set_url_for_middleware() None
Add middleware to support
url_forin Pydantic models.This middleware adds a request state variable that allows
labthings_fastapi.server.URLForinstances to be serialised using FastAPI’surl_forfunction.
- property settings_folder: str
The folder in which we will store
Thingsettings.- Raises:
RuntimeError – if there is no settings folder set. This should never happen, as it’s set in
__init__.
- property things: collections.abc.Mapping[str, labthings_fastapi.thing.Thing]
A read-only mapping of names to
Thinginstances.
- property application_config: collections.abc.Mapping[str, Any] | None
Return the application configuration from the config file.
- Returns:
The custom configuration as specified in the configuration file.
- property api_prefix: str
A string that prefixes all URLs in the application.
This will either be empty, or start with a slash and not end with a slash. Validation is performed in
ThingServerConfig.
- ThingInstance
- things_by_class(cls: type[ThingInstance]) collections.abc.Sequence[ThingInstance]
Return all Things attached to this server matching a class.
Return all instances of
clsattached to this server.- Parameters:
cls – A
Thingsubclass.- Returns:
all instances of
clsthat have been added to this server.
- thing_by_class(cls: type[ThingInstance]) ThingInstance
Return the instance of
clsattached to this server.This function calls
ThingServer.things_by_class, but asserts that there is exactly one match.- Parameters:
cls – a
Thingsubclass.- Returns:
the instance of
clsattached to this server.- Raises:
RuntimeError – if there is not exactly one matching Thing.
- path_for_thing(name: str) str
Return the path for a thing with the given name.
- Parameters:
name – The name of the thing.
- Returns:
The path at which the thing is served.
- Raises:
KeyError – if no thing with the given name has been added.
- _create_things() collections.abc.Mapping[str, labthings_fastapi.thing.Thing]
Create the Things, add them to the server, and connect them up if needed.
This method is responsible for creating instances of
Thingsubclasses and adding them to the server. It also ensures theThings are connected together if required.The Things are defined in
self._config.thing_configswhich in turn is generated from thethingsargument to__init__.
- _connect_things() None
Connect the
thing_slotattributes of Things.A
Thingmay have attributes defined aslt.thing_slot(), which will be populated after allThinginstances are loaded on the server.This function is responsible for supplying the
Thinginstances required for each connection. This will be done by using the name specified either in the connection’s default, or in the configuration of the server.ThingSlotErrorwill be raised by code called by this method if the connection cannot be provided. SeeThingSlot.connectfor more details.
- _attach_things_to_server() None
Add the Things to the FastAPI App.
This calls
attach_to_serveron eachThingthat is a part of thisThingServerin order to add the HTTP endpoints and load settings.
- async lifespan(app: fastapi.FastAPI) AsyncGenerator[None, None]
Manage set up and tear down of the server and Things.
This method is used as a lifespan function for the FastAPI app. See the lifespan page in FastAPI’s documentation.
This does two important things:
It sets up the blocking portal so background threads can run async code (this is required for events, streams, etc.).
It runs setup/teardown code for Things by calling them as context managers.
- Parameters:
app – The FastAPI application wrapped by the server.
- Yield:
no value. The FastAPI application will serve requests while this function yields.
- Raises:
BaseException – Reraises any errors that are caught when calling
__enter__on each Thing. The error is also saved toself.startup_failurefor post mortem, as otherwise uvicorn will swallow it and replace it with SystemExit(3) and no traceback.
- _things_view_router() fastapi.APIRouter
Create a router for the endpoint that shows the list of attached things.
- Returns:
an APIRouter with the
thing_descriptionsendpoint.
- serve(host: str = 'localhost', port: int = 5000) None
Run the server in
uvicorn.This method will run the server from Python, using
uvicorn.run. This is the most convenient way to run a LabThings server from Python, and is identical to what happens when it is run from the command line.- Parameters:
host – The IP address or hostname on which to serve. By default, this is
localhostwhich is only accessible from your computer. To serve over a network on all available IPv4 addresses, use"0.0.0.0".port – The port on which to serve. This defaults to 5000.
- test_client() collections.abc.Iterator[fastapi.testclient.TestClient]
A context manager to test out a server without binding to a port.
This context manager will start up the server and run an event loop, but instead of responding to requests on a network port, it uses
fastapi.testclient.TestClientto simulate HTTP requests.This is provided to simplify test code, and should not be used in production.
- Yields:
a
fastapi.testclient.TestClientto simulate HTTP requests.
Warning
Usually, a server is only started up and shut down once. Calling this method multiple times may have unexpected results.
As a rule, only ever use this method in your test suite.