Skip to content

Commit f6032b1

Browse files
authored
Merge pull request #306 from labthings/docs-improvements
Docs improvements
2 parents a6e5f78 + bd4a760 commit f6032b1

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

docs/source/actions.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,32 @@ a long time to run, or it may simply be a helpful debugging aid.
6767

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

70+
.. _get_thing_states:
71+
72+
Collecting metadata
73+
--------------------
74+
It's relatively common to want to collect metadata that summarises all of the `.Thing`
75+
instances in the current server. It's good practice to embed this kind of metadata in
76+
data files or images, and so LabThings provides a convenience function to collect it.
77+
`.ThingServerInterface.get_thing_states` will return a mapping of `.Thing` names to
78+
metadata dictionaries, suitable for embedding in a data file. The metadata dictionaries
79+
are generated by the ``thing_state`` property of each `.Thing`\ .
80+
81+
The metadata can be accessed through the Thing-Server Interface, which is a property
82+
of the `.Thing`\ :
83+
84+
.. code-block:: python
85+
86+
import json
87+
import labthings_fastapi as lt
88+
89+
class MyThing(lt.Thing):
90+
@lt.action
91+
def gather_metadata(self) -> str:
92+
"""Return metadata about all Things, as a string."""
93+
metadata_dict = self._thing_server_interface.get_thing_states()
94+
return json.dumps(metadata_dict)
95+
7096
.. _action_cancellation:
7197

7298
Cancelling actions

docs/source/blobs.rst

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ A `.Blob` consists of some data and a MIME type, which sets how the data should
1414
Creating and using `.Blob` objects
1515
------------------------------------------------
1616

17-
Blobs can be created from binary data that is in memory (a `bytes` object) with `.Blob.from_bytes`, on disk (with `.Blob.from_temporary_directory` or `.Blob.from_file`). A `.Blob` may also point to remote data (see `.Blob.from_url`). Code that uses a `.Blob` should not need to know how the data is stored, as the interface is the same in each case.
17+
Blobs can be created from binary data that is in memory (a `bytes` object) with `.Blob.from_bytes` or on disk (with `.Blob.from_temporary_directory` or `.Blob.from_file`). A `.Blob` may also point to remote data (see `.Blob.from_url`). Code that uses a `.Blob` should not need to know how the data is stored, as the interface is the same in each case.
1818

1919
Blobs offer three ways to access their data:
2020

2121
* A `bytes` object, obtained via the `.Blob.data` property. For blobs created with a `bytes` object, this simply returns the original data object with no copying. If the data is stored in a file, the file is opened and read when the `.Blob.data` property is accessed. If the `.Blob` references a URL, it is retrieved and returned when `.Blob.data` is accessed.
22-
* An `.Blob.open` method providing a file-like object. This returns a `~io.BytesIO` wrapper if the `.Blob` was created from a `bytes` object or the file if the data is stored on disk. URLs are retrieved, stored as `bytes` and returned wrapped in a :class:`~io.BytesIO` object.
22+
* An `~.Blob.open` method providing a file-like object. This returns a `~io.BytesIO` wrapper if the `.Blob` was created from a `bytes` object or the file if the data is stored on disk. URLs are retrieved, stored as `bytes` and returned wrapped in a :class:`~io.BytesIO` object.
2323
* A `.Blob.save` method will either save the data to a file, or copy the existing file on disk. This should be more efficient than loading `.Blob.data` and writing to a file, if the `.Blob` is pointing to a file rather than data in memory.
2424

2525
The intention here is that `.Blob` objects may be used identically with data in memory or on disk or even at a remote URL, and the code that uses them should not need to know which is the case.
@@ -59,6 +59,26 @@ The corresponding client code might look like this:
5959
img = Image.open(f)
6060
img.show() # This will display the image in a window
6161
62+
Another `.Thing` on the same server can also make use of this action, in which case the image data will not be copied:
63+
64+
.. code-block:: python
65+
66+
from datetime import datetime
67+
import os.path
68+
69+
class Gallery(lt.Thing):
70+
_camera: Camera = lt.thing_slot()
71+
72+
@lt.action
73+
def capture_to_gallery(self) -> str:
74+
"""Capture an image and save it in the gallery."""
75+
jpeg = self._camera.capture_image()
76+
fname = f"{datetime.now().strftime('%Y%m%d-%H%M%S')}.jpg"
77+
jpeg.save(os.path.join(".", "gallery", fname))
78+
return fname
79+
80+
When the ``JPEGBlob`` is returned by the camera, nothing is copied - and when it is saved, the `bytes` object is written to disk. Note that, if the data had been backed by a file, ``save`` would have copied the file on disk, with no requirement for Python to load it back into memory.
81+
6282
Using `.Blob` objects as inputs
6383
--------------------------------------
6484

@@ -119,6 +139,10 @@ On the client, we can use the `capture_image` action directly (as before), or we
119139
120140
raw_blob.save("raw_image.raw") # Download and save the raw image to a file
121141
142+
.. warning::
143+
144+
Currently, `.Blob` objects are only retained on the server as part of the output of the action that created them. This means they will expire after a timeout (by default, a few minutes). This mechanism is likely to change in future releases: the use of `.Blob` objects as inputs should be considered experimental.
145+
122146
HTTP interface and serialization
123147
--------------------------------
124148

0 commit comments

Comments
 (0)