labthings_fastapi.utilities.introspection ========================================= .. py:module:: labthings_fastapi.utilities.introspection .. autoapi-nested-parse:: A collection of utility functions to analyse types and metadata. Many parts of LabThings require us to use type annotations to generate schemas/validation/documentation. This is done using `pydantic` in keeping with the underlying FastAPI library. This module collects together some utility functions that help with a few key tasks, in particular creating pydantic models from functions by analysing their signatures. Classes ------- .. autoapisummary:: labthings_fastapi.utilities.introspection.EmptyObject labthings_fastapi.utilities.introspection.StrictEmptyObject labthings_fastapi.utilities.introspection.EmptyInput labthings_fastapi.utilities.introspection.StrictEmptyInput Functions --------- .. autoapisummary:: labthings_fastapi.utilities.introspection.input_model_from_signature labthings_fastapi.utilities.introspection.fastapi_dependency_params labthings_fastapi.utilities.introspection.return_type labthings_fastapi.utilities.introspection.get_docstring labthings_fastapi.utilities.introspection.get_summary Module Contents --------------- .. py:class:: EmptyObject(/, **data: Any) Bases: :py:obj:`pydantic.BaseModel` A model representing an object with no required keys. Create a new model by parsing and validating input data from keyword arguments. Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model. `self` is explicitly positional-only to allow `self` as a field name. .. py:attribute:: model_config Configuration for the model, should be a dictionary conforming to [`ConfigDict`][pydantic.config.ConfigDict]. .. py:class:: StrictEmptyObject(/, **data: Any) Bases: :py:obj:`EmptyObject` A model representing an object that must have no keys. Create a new model by parsing and validating input data from keyword arguments. Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model. `self` is explicitly positional-only to allow `self` as a field name. .. py:attribute:: model_config Configuration for the model, should be a dictionary conforming to [`ConfigDict`][pydantic.config.ConfigDict]. .. py:class:: EmptyInput(/, root=PydanticUndefined, **data) Bases: :py:obj:`pydantic.RootModel` Represent the input of an action that has no required parameters. This may be either a dictionary or ``None``. Create a new model by parsing and validating input data from keyword arguments. Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model. `self` is explicitly positional-only to allow `self` as a field name. .. py:attribute:: root :type: Optional[EmptyObject] :value: None .. py:class:: StrictEmptyInput(/, root=PydanticUndefined, **data) Bases: :py:obj:`EmptyInput` Represent the input of an action that never takes parameters. This may be either an empty dictionary or ``None``. Create a new model by parsing and validating input data from keyword arguments. Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model. `self` is explicitly positional-only to allow `self` as a field name. .. py:attribute:: root :type: Optional[StrictEmptyObject] :value: None .. py:function:: input_model_from_signature(func: Callable, remove_first_positional_arg: bool = False, ignore: Optional[Sequence[str]] = None) -> type[pydantic.BaseModel] Create a pydantic model for a function's signature. This is deliberately quite a lot more basic than `pydantic.decorator.ValidatedFunction` because it is designed to handle JSON input. That means that we don't want positional arguments. .. note:: LabThings-FastAPI does not currently support actions that take positional arguments, because this does not convert nicely into JSONSchema or Thing Description documents (see :ref:`gen_docs`). :param func: the function to analyse. :param remove_first_positional_arg: Remove the first argument from the model (this is appropriate for methods, as the first argument, self, is baked in when it's called, but is present in the signature). :param ignore: Ignore arguments that have the specified name. This is useful for e.g. dependencies that are injected by LabThings. :return: A pydantic model class describing the input parameters :raise TypeError: if positional arguments are used: this is not supported. :raise ValueError: if ``remove_first_positional_arg`` is true but there is no initial positional argument. .. py:function:: fastapi_dependency_params(func: Callable) -> Sequence[inspect.Parameter] Find the arguments of a function that are FastAPI dependencies. This allows us to "pass through" the full power of the FastAPI dependency injection system to thing actions. Any function parameter that has a type hint annotated with `fastapi.Depends` will be treated as a dependency, and thus be supplied automatically when it is called over HTTP. See :ref:`dependencies` for an overview. We give special treatment to dependency parameters, as they must not appear in the input model, and they must be supplied by the `.DirectThingClient` wrapper to make the signature identical to that of the `~lt.ThingClient` over HTTP. .. note:: Path and query parameters are ignored. These should not be used as action parameters, and will most likely raise an error when the `~lt.Thing` is added to FastAPI. :param func: a function to inspect. :return: a list of parameter objects that are annotated as dependencies. .. py:function:: return_type(func: Callable) -> Type Determine the return type of a function. :param func: a function to inspect :return: the return type of the function. .. py:function:: get_docstring(obj: Any, remove_summary: bool = False) -> Optional[str] Return the docstring of an object. Get the docstring of an object, optionally removing the initial "summary" line. If `remove_summary` is `True` (not default), and the docstring's second line is blank, the first two lines are removed. If the docstring follows the convention of a one-line summary, a blank line, and a description, this will get just the description. The docstring is processed by `inspect.cleandoc()` to remove whitespace from the start of each line. :param obj: Any Python object. :param remove_summary: whether to remove the summary line, if present. :return: The object's docstring. .. py:function:: get_summary(obj: Any) -> Optional[str] Return the first line of the dosctring of an object. :param obj: Any Python object :return: First line of object docstring, or ``None``.