Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 81 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,31 @@ anyio==4.9.0
# httpx
# starlette
# watchfiles
apeye==1.4.1
# via sphinx-toolbox
apeye-core==1.1.5
# via apeye
astroid==3.3.11
# via sphinx-autoapi
attrs==25.3.0
# via
# jsonschema
# referencing
autodocsumm==0.2.14
# via sphinx-toolbox
babel==2.17.0
# via sphinx
beautifulsoup4==4.14.2
# via sphinx-toolbox
cachecontrol==0.14.3
# via sphinx-toolbox
certifi==2025.7.14
# via
# httpcore
# httpx
# requests
# sentry-sdk
# sphinx-prompt
charset-normalizer==3.4.2
# via requests
click==8.2.1
Expand All @@ -42,6 +53,10 @@ colorama==0.4.6
# uvicorn
coverage==7.9.2
# via pytest-cov
cssutils==2.11.1
# via dict2css
dict2css==0.3.0.post1
# via sphinx-toolbox
dnspython==2.7.0
# via email-validator
docstring-parser-fork==0.0.12
Expand All @@ -50,7 +65,16 @@ docutils==0.21.2
# via
# restructuredtext-lint
# sphinx
# sphinx-prompt
# sphinx-rtd-theme
# sphinx-tabs
# sphinx-toolbox
domdf-python-tools==3.10.0
# via
# apeye
# apeye-core
# dict2css
# sphinx-toolbox
email-validator==2.2.0
# via
# fastapi
Expand All @@ -65,6 +89,10 @@ fastapi-cli==0.0.8
# via fastapi
fastapi-cloud-cli==0.1.4
# via fastapi-cli
filelock==3.20.0
# via
# cachecontrol
# sphinx-toolbox
flake8==7.3.0
# via
# labthings-fastapi (pyproject.toml)
Expand All @@ -82,6 +110,8 @@ h11==0.16.0
# via
# httpcore
# uvicorn
html5lib==1.1
# via sphinx-toolbox
httpcore==1.0.9
# via httpx
httptools==0.6.4
Expand All @@ -94,9 +124,11 @@ httpx==0.28.1
idna==3.10
# via
# anyio
# apeye-core
# email-validator
# httpx
# requests
# sphinx-prompt
ifaddr==0.2.0
# via zeroconf
imagesize==1.4.1
Expand All @@ -110,22 +142,31 @@ jinja2==3.1.6
# fastapi
# sphinx
# sphinx-autoapi
# sphinx-jinja2-compat
jsonschema==4.24.1
# via labthings-fastapi (pyproject.toml)
jsonschema-specifications==2025.4.1
# via jsonschema
markdown-it-py==3.0.0
# via rich
markupsafe==3.0.2
# via jinja2
# via
# jinja2
# sphinx-jinja2-compat
mccabe==0.7.0
# via flake8
mdurl==0.1.2
# via markdown-it-py
more-itertools==10.8.0
# via cssutils
msgpack==1.1.2
# via cachecontrol
mypy==1.17.0
# via labthings-fastapi (pyproject.toml)
mypy-extensions==1.1.0
# via mypy
natsort==8.4.0
# via domdf-python-tools
numpy==2.2.6
# via labthings-fastapi (pyproject.toml)
orjson==3.11.0
Expand All @@ -138,6 +179,8 @@ pathspec==0.12.1
# via mypy
pillow==11.3.0
# via labthings-fastapi (pyproject.toml)
platformdirs==4.5.0
# via apeye
pluggy==1.6.0
# via
# pytest
Expand Down Expand Up @@ -167,6 +210,8 @@ pygments==2.19.2
# pytest
# rich
# sphinx
# sphinx-prompt
# sphinx-tabs
pytest==8.4.1
# via
# labthings-fastapi (pyproject.toml)
Expand All @@ -193,7 +238,10 @@ referencing==0.36.2
# jsonschema-specifications
# types-jsonschema
requests==2.32.4
# via sphinx
# via
# apeye
# cachecontrol
# sphinx
restructuredtext-lint==1.4.0
# via flake8-rst-docstrings
rich==14.0.0
Expand All @@ -210,26 +258,49 @@ rpds-py==0.26.0
# via
# jsonschema
# referencing
ruamel-yaml==0.18.16
# via sphinx-toolbox
ruamel-yaml-clib==0.2.14
# via ruamel-yaml
ruff==0.12.3
# via labthings-fastapi (pyproject.toml)
sentry-sdk==2.33.0
# via fastapi-cloud-cli
shellingham==1.5.4
# via typer
six==1.17.0
# via html5lib
sniffio==1.3.1
# via anyio
snowballstemmer==3.0.1
# via sphinx
soupsieve==2.8
# via beautifulsoup4
sphinx==8.1.3
# via
# labthings-fastapi (pyproject.toml)
# autodocsumm
# sphinx-autoapi
# sphinx-autodoc-typehints
# sphinx-prompt
# sphinx-rtd-theme
# sphinx-tabs
# sphinx-toolbox
# sphinxcontrib-jquery
sphinx-autoapi==3.6.0
# via labthings-fastapi (pyproject.toml)
sphinx-autodoc-typehints==3.0.1
# via sphinx-toolbox
sphinx-jinja2-compat==0.4.1
# via sphinx-toolbox
sphinx-prompt==1.9.0
# via sphinx-toolbox
sphinx-rtd-theme==3.0.2
# via labthings-fastapi (pyproject.toml)
sphinx-tabs==3.4.5
# via sphinx-toolbox
sphinx-toolbox==4.0.0
# via labthings-fastapi (pyproject.toml)
sphinxcontrib-applehelp==2.0.0
# via sphinx
sphinxcontrib-devhelp==2.0.0
Expand All @@ -246,6 +317,8 @@ sphinxcontrib-serializinghtml==2.0.0
# via sphinx
starlette==0.47.1
# via fastapi
tabulate==0.9.0
# via sphinx-toolbox
tomli==2.2.1
# via
# coverage
Expand All @@ -265,6 +338,8 @@ typing-extensions==4.14.1
# labthings-fastapi (pyproject.toml)
# anyio
# astroid
# beautifulsoup4
# domdf-python-tools
# exceptiongroup
# fastapi
# mypy
Expand All @@ -274,6 +349,7 @@ typing-extensions==4.14.1
# referencing
# rich
# rich-toolkit
# sphinx-toolbox
# starlette
# typer
# typing-inspection
Expand All @@ -286,13 +362,16 @@ urllib3==2.5.0
# via
# requests
# sentry-sdk
# sphinx-prompt
uvicorn==0.35.0
# via
# fastapi
# fastapi-cli
# fastapi-cloud-cli
watchfiles==1.1.0
# via uvicorn
webencodings==0.5.1
# via html5lib
websockets==15.0.1
# via uvicorn
zeroconf==0.147.0
Expand Down
11 changes: 7 additions & 4 deletions docs/source/actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ terms, any method of a `.Thing` that we want to be able to call over HTTP
should be decorated as an Action, using `.thing_action`.

This page gives an overview of how actions are implemented in LabThings-FastAPI.
:ref:`wot_cc` includes a section on :ref:`wot_actions` that introduces the general concept.
Our implementation should align with :ref:`wot_actions` as defined by the Web of Things standard.

Running actions via HTTP
------------------------
Expand Down Expand Up @@ -58,7 +58,8 @@ The first is ``self`` (the first positional argument), which is always the
supply resources needed by the action. Most often, this is a way of accessing
other `.Things` on the same server.

.. action_logging:
.. _action_logging:

Logging from actions
--------------------
Action code should use `.Thing.logger` to log messages. This will be configured
Expand All @@ -70,7 +71,8 @@ a long time to run, or it may simply be a helpful debugging aid.

See :mod:`.logs` for details of how this is implemented.

.. action_cancellation:
.. _action_cancellation:

Cancelling actions
------------------
If an action could run for a long time, it is useful to be able to cancel it
Expand All @@ -82,7 +84,8 @@ is equivalent, but will raise an exception if the action is cancelled.

For more advanced options, see `.invocation_contexts` for detail.

.. invocation_context:
.. _invocation_context:

Invocation contexts
-------------------
Cancelling actions and capturing their logs requires action code to use a
Expand Down
4 changes: 3 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import labthings_fastapi
import importlib.metadata

# Configuration file for the Sphinx documentation builder.
#
Expand All @@ -12,7 +13,7 @@
project = "labthings-fastapi"
copyright = "2024, Richard Bowman"
author = "Richard Bowman"
release = "0.0.10"
release = importlib.metadata.version("labthings-fastapi")

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand All @@ -23,6 +24,7 @@
# "autodoc2",
"autoapi.extension",
"sphinx_rtd_theme",
"sphinx_toolbox.decorators",
]

templates_path = ["_templates"]
Expand Down
9 changes: 4 additions & 5 deletions docs/source/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
Generated documentation
=======================

LabThings describes its HTTP API in two ways: with a :ref:`wot_td` and with an OpenAPI_ document.
LabThings describes its HTTP API in two ways: with a :ref:`gen_td` and with an OpenAPI_ document.

.. _openapi:

OpenAPI
-------

OpenAPI_ is a standard way to describe an HTTP interface. It lists all of the possible HTTP requests that may be made, along with a description of each one, and a description of the possible responses.
`OpenAPI <https://www.openapis.org/>` is a standard way to describe an HTTP interface. It lists all of the possible HTTP requests that may be made, along with a description of each one, and a description of the possible responses.

.. _gen_td:

Thing Description
-----------------

Each :ref:`wot_thing` is documented by a Thing Description, which is a JSON document describing all of the ways to interact with that Thing (:ref:`wot_affordances`\ ). The WoT_ standard defines the `Thing Description`_ and includes a JSON Schema against which it may be validated.
Each :ref:`Thing <things>` is documented by a :ref:`gen_td`, which is a JSON document describing all of the ways to interact with that Thing (:ref:`wot_affordances`\ ). The WoT_ standard defines the `Thing Description`_ and includes a JSON Schema against which it may be validated.

Thing Description documents are higher-level than OpenAPI_ and focus on the capabilities of the Thing. For example, they include a list of properties, where each action is described only once. LabThings treats the Thing Description as your public API, and as a general rule anything not described in the Thing Description is not available over HTTP or to a `.DirectThingClient`\ .
Thing Description documents are higher-level than OpenAPI_ and focus on the capabilities of the Thing. For example, they include a list of properties, where each action is described only once. LabThings treats the Thing Description as your public API, and as a general rule anything not described in the Thing Description is not available over HTTP.

Comparison of Thing Description and OpenAPI
-------------------------------------------
Expand All @@ -30,4 +30,3 @@ OpenAPI describes each HTTP endpoint individually. There are usually more HTTP e

.. _WoT: https://www.w3.org/WoT/
.. _Thing Description: https://www.w3.org/TR/wot-thing-description/
.. _OpenAPI: https://www.openapis.org/
9 changes: 5 additions & 4 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ Documentation for LabThings-FastAPI
:caption: Contents:

quickstart/quickstart.rst
wot_core_concepts.rst
structure.rst
tutorial/index.rst
structure.rst
examples.rst
documentation.rst
actions.rst
thing_slots.rst
dependencies/dependencies.rst
blobs.rst
concurrency.rst
using_things.rst
see_also.rst
wot_core_concepts.rst

autoapi/index

Expand All @@ -28,13 +29,13 @@ Documentation for LabThings-FastAPI
* Actions are decorated methods of a `.Thing` class. There is no need for separate schemas or endpoint definitions.
* Properties are defined either as typed attributes (similar to `pydantic` or `dataclasses`) or with a `property`\ -like decorator.
* Lifecycle and concurrency are appropriate for hardware: `Thing` code is always run in a thread, and each `Thing` is instantiated, started up, and shut down only once.
* Vocabulary and concepts are aligned with the `W3C Web of Things <https://www.w3.org/WoT/>`_ standard (see :doc:`wot_core_concepts`)
* Vocabulary and concepts are aligned with the `W3C Web of Things <https://www.w3.org/WoT/>`_ standard (see :ref:`wot_cc`)

Previous version
----------------

This is a ground-up rewrite of python-labthings_, replacing Flask 1 and Marshmallow with FastAPI and Pydantic.
Compared to `python-labthings`_, this framework updates dependencies, shrinks the codebase, and simplifies the API (see :doc:`lt_structure`).
Compared to `python-labthings`_, this framework updates dependencies, shrinks the codebase, and simplifies the API (see :doc:`structure`).
* FastAPI more or less completely eliminates OpenAPI generation code from our codebase
* Marshmallow schemas and endpoint classes are replaced with Python type hints, eliminating double- or triple-definition of actions and their inputs/outputs.
* Thing Description generation is very much simplified by the new structure (multiple Things instead of one massive Thing with many extensions)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/see_also.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Descriptors

Descriptors are a way to intercept attribute access on an object. By default, attributes of an object are just variables - so an object called ``foo`` might have an attribute called ``bar``, and you may read its value with ``foo.bar``, write its value with ``foo.bar = "baz"``, and delete the attribute with ``del foo.bar``. If ``foo`` is a descriptor, Python will call the ``__get__`` method of that descriptor when it's read and the ``__set__`` method when it's written to. You have quite probably used a descriptor already, because the built-in `~builtins.property` creates a descriptor object: that's what runs your getter method when the property is accessed. The descriptor protocol is described with plenty of examples in the `Descriptor Guide`_ in the Python documentation.

In LabThings-FastAPI, descriptors are used to implement :ref:`wot_actions` and :ref:`wot_properties` on `.Thing` subclasses. The intention is that these will function like standard Python methods and properties, but will also be available over HTTP, along with automatic documentation in the :ref:`wot_td` and OpenAPI documents.
In LabThings-FastAPI, descriptors are used to implement :ref:`actions` and :ref:`properties` on `.Thing` subclasses. The intention is that these will function like standard Python methods and properties, but will also be available over HTTP, along with :ref:`gen_docs`.

There are a few useful notes that relate to many of the descriptors in LabThings-FastAPI:

Expand Down
Loading