Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 31 additions & 1 deletion docs/source/public_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ This page summarises the parts of the LabThings API that should be most frequent
:param debug: sets the log level for `~lt.Thing` instances to DEBUG if it is set to `True`\ .
:param \**kwargs: for backwards compatibility, keyword arguments are used to create the server configuration if `config` is missing. This raises a `DeprecationWarning`\ .

.. py:method:: from_config(config: ThingServerConfig, debug: bool = False) -> ThingServer
.. py:classmethod:: from_config(config: ThingServerConfig, debug: bool = False) -> ThingServer

This method of creating a `ThingServer` is deprecated, as it is equivalent to the constructor.

Expand All @@ -276,6 +276,36 @@ This page summarises the parts of the LabThings API that should be most frequent
:param things: a mapping of Thing names to Thing configurations.
:param \**kwargs: additional keyword arguments are passed to `ThingServerConfig`\ .

.. py:property:: things
:type: collections.abc.Mapping[str, Thing]

A read-only mapping of names to `~lt.Thing` instances, for every `~lt.Thing` attached to the server.

:return: a mapping of names to `~lt.Thing` instances.

.. py:property:: application_config
:type: collections.abc.Mapping[str, Any] | None

Return the application configuration from the config file.

:return: The custom configuration as specified in the configuration
file.

.. py:property:: api_prefix
:type: str

A string that prefixes all URLs in the application. Endpoints associated with a `Thing` will appear under ``{api_prefix}/{thing_name}/``. This is validated in `ThingServerConfig` and must either be empty, or start with ``/`` and not end with ``/``\ .

.. py:property:: settings_folder
:type: str

The path to the folder used to store settings for each `Thing`\ . This will default to ``./settings/`` if not specified in the server's configuration.

.. py:property:: debug
:type: bool

Whether the server is in debug mode.


.. py:class:: ThingServerInterface(server: ThingServer, name: str)

Expand Down
17 changes: 7 additions & 10 deletions src/labthings_fastapi/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@
self._set_url_for_middleware()
self._add_exception_handlers()
self.action_manager = ActionManager()
self.app.include_router(self.action_manager.router(), prefix=self._api_prefix)
self.app.include_router(blob.router, prefix=self._api_prefix)
self.app.include_router(self._things_view_router(), prefix=self._api_prefix)
self.app.include_router(self.action_manager.router(), prefix=self.api_prefix)
self.app.include_router(blob.router, prefix=self.api_prefix)
self.app.include_router(self._things_view_router(), prefix=self.api_prefix)
self.blocking_portal: Optional[BlockingPortal] = None
self.startup_status: dict[str, str | dict] = {"things": {}}
global _thing_servers # noqa: F824
Expand Down Expand Up @@ -270,10 +270,7 @@

@property
def things(self) -> Mapping[str, Thing]:
"""Return a dictionary of all the things.

:return: a dictionary mapping thing paths to `~lt.Thing` instances.
"""
"""A read-only mapping of names to `~lt.Thing` instances."""
return MappingProxyType(self._things)

@property
Expand All @@ -286,7 +283,7 @@
return self._config.application_config

@property
def _api_prefix(self) -> str:
def api_prefix(self) -> str:
r"""A string that prefixes all URLs in the application.

This will either be empty, or start with a slash and not
Expand All @@ -305,7 +302,7 @@

:return: all instances of ``cls`` that have been added to this server.
"""
return [t for t in self.things.values() if isinstance(t, cls)]

Check warning on line 305 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

305 line is not covered with tests

def thing_by_class(self, cls: type[ThingInstance]) -> ThingInstance:
"""Return the instance of ``cls`` attached to this server.
Expand All @@ -319,10 +316,10 @@

:raise RuntimeError: if there is not exactly one matching Thing.
"""
instances = self.things_by_class(cls)
if len(instances) == 1:
return instances[0]
raise RuntimeError(

Check warning on line 322 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

319-322 lines are not covered with tests
f"There are {len(instances)} Things of class {cls}, expected 1."
)

Expand All @@ -337,7 +334,7 @@
"""
if name not in self._things:
raise KeyError(f"No thing named {name} has been added to this server.")
return f"{self._api_prefix}/{name}/"
return f"{self.api_prefix}/{name}/"

def _create_things(self) -> Mapping[str, Thing]:
r"""Create the Things, add them to the server, and connect them up if needed.
Expand Down Expand Up @@ -475,7 +472,7 @@
"""
return {
name: thing.thing_description(
path=f"{self._api_prefix}/{name}/", base=str(request.base_url)
path=f"{self.api_prefix}/{name}/", base=str(request.base_url)
)
for name, thing in thing_server.things.items()
}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def check_server(server: lt.ThingServer, debug: bool = False):
"""Make sure the server config is as expected."""
assert len(server.things) == 1
assert isinstance(server.things["my_thing"], MyThing)
assert server._api_prefix == "/api/v3"
assert server.api_prefix == "/api/v3"
assert server.debug == debug

# The type hint doesn't match a dict, but it works anyway.
Expand Down
Loading