labthings_fastapi.thing_server_interface
Interface between Thing subclasses and the ThingServer.
Attributes
Exceptions
The error raised when a ThingServer is no longer available. |
Classes
An interface for Things to interact with their server. |
Module Contents
- labthings_fastapi.thing_server_interface.Params
- labthings_fastapi.thing_server_interface.ReturnType
- exception labthings_fastapi.thing_server_interface.ThingServerMissingError
Bases:
RuntimeErrorThe error raised when a ThingServer is no longer available.
This error indicates that a ThingServerInterface is still in use even though its underlying ThingServer has been deleted. This is unlikely to happen and usually indicates that the server has been created in an odd way.
Initialize self. See help(type(self)) for accurate signature.
- class labthings_fastapi.thing_server_interface.ThingServerInterface(server: labthings_fastapi.server.ThingServer, name: str, class_name: str)
An interface for Things to interact with their server.
This is added to every
Thingduring__init__and is available asself._thing_server_interface.Initialise a ThingServerInterface.
The ThingServerInterface sits between a Thing and its ThingServer, with the intention of providing a useful set of functions, without exposing too much of the server to the Thing.
One reason for using this intermediary class is to make it easier to mock the server during testing: only functions provided here need be mocked, not the whole functionality of the server.
- Parameters:
server – the
ThingServerinstance we’re connected to. This will be retained as a weak reference.name – the name of the
Thinginstance this interface is provided for.class_name – The name of the class of the Thing, used as part of the settings filename.
- _get_server() labthings_fastapi.server.ThingServer
Return a live reference to the ThingServer.
This will evaluate the weak reference to the ThingServer, and will raise an exception if the server has been garbage collected.
The server is, in practice, not going to be finalized before the Things, so this should not be a problem.
- Returns:
the ThingServer.
- Raises:
ThingServerMissingError – if the
ThingServeris no longer available.
- start_async_task_soon(async_function: Callable[Params, Awaitable[ReturnType]], *args: Any) concurrent.futures.Future[ReturnType]
Run an asynchronous task in the server’s event loop.
This function wraps
anyio.from_thread.BlockingPortal.start_task_soonto provide a way of calling asynchronous code from threaded code. It will call the provided async function in the server’s event loop, without any guarantee of exactly when it will happen. This means we will return immediately, and the return value of this function will be aconcurrent.futures.Futureobject that may resolve to the async function’s return value.- Parameters:
async_function – the asynchronous function to call.
*args – positional arguments to be provided to the function.
- Returns:
an
asyncio.Futureobject wrapping the return value.- Raises:
ServerNotRunningError – if the server is not running (i.e. there is no event loop).
- call_async_task(async_function: Callable[Params, Awaitable[ReturnType]], *args: Any) ReturnType
Run an asynchronous task in the server’s event loop in a blocking manner.
This function wraps
anyio.from_thread.BlockingPortal.callto provide a way of calling asynchronous code from threaded code. It will block the current thread while it calls the provided async function in the server’s event loop.Do not call this from the event loop or it may lead to a deadlock.
- Parameters:
async_function – the asynchronous function to call.
*args – positional arguments to be provided to the function.
- Returns:
The return value from the asynchronous function.
- Raises:
ServerNotRunningError – if the server is not running (i.e. there is no event loop).
- publish(message: labthings_fastapi.message_broker.Message) None
Publish an event.
Use the async event loop to notify subscribers that something has happened. The message should contain the name of the
Thingand affordance.Note that this function will do nothing if the event loop is not yet running.
- Parameters:
message – the message being published.
- property path: str
The path, relative to the server’s base URL, of the Thing.
A ThingServerInterface is specific to one Thing, so this path points to the base URL of the Thing, i.e. the Thing Description’s endpoint.
- property application_config: Mapping[str, Any] | None
The custom application configuration options from configuration.
- get_thing_states() Mapping[str, Any]
Retrieve metadata from all Things on the server.
This function will retrieve the
thing_stateproperty from eachThingon the server, and return it as a dictionary. It is intended to make it easy to add metadata to the results of actions, for example to embed in an image.- Returns:
a dictionary of metadata, with the
Thingnames as keys.
- property _action_manager: labthings_fastapi.actions.ActionManager
The ActionManager for the Thing attached to this interface.
This property may be removed in future, and is for internal use only.
- property global_lock: labthings_fastapi.global_lock.GlobalLock | None
A lock that ensures property writes and actions are one-at-a-time.
If global locking is not enabled, this property will return None.
- _optionally_hold_global_lock(enabled: bool | None = True) collections.abc.Iterator[None]
Hold the global lock, if required, as a context manager.
This function will hold the global lock if necessary while a block of code runs. Its behaviour is controlled by the
enabledparameter: ifenabledisFalsethis function does nothing. If it isNone(the default when called from a property or action that’s not otherwise configured), the global lock is held if it exists, but no error is raised if global locking is disabled.If
enabledisTrue(the default if no arguments are passed), an error will be raised if there is no global lock.- Parameters:
enabled – whether to use the global lock.
TrueandFalsehave the obvious meanings described above,Nonewill use the lock if it is enabled globally but won’t raise an error if it is unavailable.- Raises:
FeatureNotEnabledError – if
enabledisTruebut the global lock is not enabled.
- hold_global_lock(*, error_if_unavailable: bool = True) collections.abc.Iterator[None]
Hold the global lock for the duration of a with block.
This context manager will hold the global lock while a
with:block runs. By default, an exception will be raised if the global lock is not enabled.- Parameters:
error_if_unavailable – may be set to
Falseto suppress errors if the global lock is not enabled. This means the context manager silently does nothing, if the global lock is not available.