labthings_fastapi.descriptors.action ==================================== .. py:module:: labthings_fastapi.descriptors.action .. autoapi-nested-parse:: Define an object to represent an Action, as a descriptor. Attributes ---------- .. autoapisummary:: labthings_fastapi.descriptors.action.ACTION_POST_NOTICE labthings_fastapi.descriptors.action.ACTION_GET_DESCRIPTION Classes ------- .. autoapisummary:: labthings_fastapi.descriptors.action.ActionDescriptor Module Contents --------------- .. py:data:: ACTION_POST_NOTICE :value: Multiline-String .. raw:: html
Show Value .. code-block:: python """ ## Important note This `POST` request starts an Action, i.e. the server will do something that may continue after the HTTP request has been responded to. The response will always be an ActionInvocation object, that details the current status of the action and provides an interface to poll for completion. If the action completes within a specified timeout, we will return an HTTP status code of `200` and the return value will include any output from the action. If it does not complete, we will return a `201` response code, and the action's endpoint may be polled to follow its progress. """ .. raw:: html
.. py:data:: ACTION_GET_DESCRIPTION :value: Multiline-String .. raw:: html
Show Value .. code-block:: python """ This will include times and input values, as well as output values for actions that have completed. These actions will also show up under the `action_invocations` endpoint, and can also be retrieved individually using the link included in each action. """ .. raw:: html
.. py:class:: ActionDescriptor(func: Callable, response_timeout: float = 1, retention_time: float = 300) Wrap actions to enable them to be run over HTTP. This class is responsible for generating the action description for the :ref:`wot_td` and creating the function that responds to ``POST`` requests to invoke the action. .. note:: Descriptors are instantiated once per class. This means that we cannot assume there is only one action corresponding to this descriptor: there may be multiple `.Thing` instances with the same descriptor. That is why the host `.Thing` must be passed to many functions as an argument, and why observers, for example, must be keyed by the `.Thing` rather than kept as a property of ``self``. Create a new action descriptor. The action descriptor wraps a method of a `.Thing`. It may still be called from Python in the same way, but it will also be added to the HTTP API and automatic documentation. :param func: is the method that will be run when the action is called. :param response_timeout: is how long we should wait before returning a response to the client. This is not currently used, as we always return immediately with a `201` code. In the future, it may set a default time to wait before responding. If the action finishes before we respond, we will be able to return the completed action and its output. If the action is still running, we return a 201 code and data enabling the client to poll to find out the status of the action. :param retention_time: how long, in seconds, the action should be kept for after it has completed. .. py:attribute:: func .. py:attribute:: response_timeout :value: 1 .. py:attribute:: retention_time :value: 300 .. py:attribute:: dependency_params :value: [] .. py:attribute:: input_model .. py:attribute:: output_model .. py:attribute:: invocation_model :value: None .. py:method:: __get__(obj: Literal[None], type=None) -> ActionDescriptor __get__(obj: labthings_fastapi.thing.Thing, type=None) -> Callable Return the function, bound to an object as for a normal method. This currently doesn't validate the arguments, though it may do so in future. In its present form, this is equivalent to a regular Python method, i.e. all we do is supply the first argument, `self`. If `obj` is None, the descriptor is returned, so we can get the descriptor conveniently as an attribute of the class. :param obj: the `.Thing` to which we are attached. This will be the first argument supplied to the function wrapped by this descriptor. :param type: the class of the `.Thing` to which we are attached. If the descriptor is accessed via the class it is returned directly. :return: the action function, bound to ``obj`` (when accessed via an instance), or the descriptor (accessed via the class). .. py:property:: name The name of the wrapped function. .. py:property:: title A human-readable title. .. py:property:: description A description of the action. .. py:method:: _observers_set(obj: labthings_fastapi.thing.Thing) -> weakref.WeakSet Return a set used to notify changes. Note that we need to supply the `.Thing` we are looking at, as in general there may be more than one object of the same type, and descriptor instances are shared between all instances of their class. :param obj: The `.Thing` on which the action is being observed. :return: a weak set of callables to notify on changes to the action. This is used by websocket endpoints. .. py:method:: emit_changed_event(obj: labthings_fastapi.thing.Thing, status: str) Notify subscribers that the action status has changed. This function is run from within the `.Invocation` thread that is created when an action is called. It must be run from a thread as it is communicating with the event loop via an `asyncio` blocking portal. Async code must not use the blocking portal as it can deadlock the event loop. :param obj: The `.Thing` on which the action is being observed. :param status: The status of the action, to be sent to observers. :raise NotConnectedToServerError: if the Thing calling the action is not connected to a server with a running event loop. .. py:method:: emit_changed_event_async(obj: labthings_fastapi.thing.Thing, value: Any) -> None :async: Notify subscribers that the action status has changed. This is an async function that must be run in the `anyio` event loop. It will send messages to each observer to notify them that something has changed. :param obj: The `.Thing` on which the action is defined. `.ActionDescriptor` objects are unique to the class, but there may be more than one `.Thing` attached to a server with the same class. We use ``obj`` to look up the observers of the current `.Thing`. :param value: The action status to communicate to the observers. .. py:method:: add_to_fastapi(app: fastapi.FastAPI, thing: labthings_fastapi.thing.Thing) -> None Add this action to a FastAPI app, bound to a particular Thing. This function creates two functions to handle ``GET`` and ``POST`` requests to the action's endpoint, and adds them to the `fastapi.FastAPI` application. :param app: The `fastapi.FastAPI` app to add the endpoint to. :param thing: The `.Thing` to which the action is attached. Bear in mind that the descriptor may be used by more than one `.Thing`, so this can't be a property of the descriptor. .. py:method:: action_affordance(thing: labthings_fastapi.thing.Thing, path: Optional[str] = None) -> labthings_fastapi.thing_description._model.ActionAffordance Represent the property in a Thing Description. This function describes the Action in :ref:`wot_td` format. :param thing: The `.Thing` to which the action is attached. :param path: The prefix applied to all endpoints associated with the `.Thing`. This is the URL for the Thing Description. If it is omitted, we use the ``path`` property of the ``thing``. :return: An `.ActionAffordance` describing this action.