Added docs for subclassing and lifecycle hooks
This commit is contained in:
parent
093e5a0a7a
commit
4626fa0565
4 changed files with 107 additions and 2 deletions
|
|
@ -0,0 +1,41 @@
|
||||||
|
from labthings.server.extensions import BaseExtension
|
||||||
|
from labthings.server.find import find_component
|
||||||
|
|
||||||
|
|
||||||
|
# Create the extension class
|
||||||
|
class MyExtension(BaseExtension):
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
# Create some instance variable
|
||||||
|
self.state_variable = "An example of a persistant instance variable"
|
||||||
|
|
||||||
|
# Superclass init function
|
||||||
|
super().__init__("com.myname.myextension", version="0.0.0")
|
||||||
|
|
||||||
|
def identify(self):
|
||||||
|
"""
|
||||||
|
Demonstrate access to Microscope.camera, and Microscope.stage
|
||||||
|
"""
|
||||||
|
microscope = find_component("org.openflexure.microscope")
|
||||||
|
|
||||||
|
response = (
|
||||||
|
f"My name is {microscope.name}. "
|
||||||
|
f"My parent camera is {microscope.camera}, "
|
||||||
|
f"and my parent stage is {microscope.stage}."
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def rename(self, new_name):
|
||||||
|
"""
|
||||||
|
Rename the microscope
|
||||||
|
"""
|
||||||
|
|
||||||
|
microscope = find_component("org.openflexure.microscope")
|
||||||
|
|
||||||
|
microscope.name = new_name
|
||||||
|
microscope.save_settings()
|
||||||
|
|
||||||
|
|
||||||
|
# Create your extension object
|
||||||
|
my_extension = MyExtension()
|
||||||
53
docs/source/extensions/lifecycle_hooks.rst
Normal file
53
docs/source/extensions/lifecycle_hooks.rst
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
Lifecycle Hooks
|
||||||
|
===============
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
In some cases it is useful to have functions triggered by events in an extensions lifecycle. Currently two such lifecycle events can be used, ``on_register``, and ``on_component``.
|
||||||
|
|
||||||
|
``on_register``
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The ``on_register`` method can be used to have a function call as soon as the extension has been successfully registered to the microscope. For example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class MyExtension(BaseExtension):
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
# Track if the extension has been registered
|
||||||
|
self.registered = False
|
||||||
|
|
||||||
|
# Add lifecycle hooks
|
||||||
|
self.on_register(self.on_register_handler, args=(), kwargs={})
|
||||||
|
|
||||||
|
# Superclass init function
|
||||||
|
super().__init__("com.myname.myextension", version="0.0.0")
|
||||||
|
|
||||||
|
def on_register_handler(self, *args, **kwargs):
|
||||||
|
self.registered = True
|
||||||
|
print("Extension has been registered!")
|
||||||
|
|
||||||
|
|
||||||
|
``on_component``
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The ``on_component`` method can be used to have a function call as soon as a particular LabThings component has been added. This can be used, for example, to get information about the microscope instance as soon as it is available. For example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class MyExtension(BaseExtension):
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
# Hold a reference to the microscope object as soon as it is available
|
||||||
|
self.microscope = None
|
||||||
|
|
||||||
|
# Add lifecycle hooks
|
||||||
|
self.on_component("com.myname.myextension", self.on_microscope_handler)
|
||||||
|
|
||||||
|
# Superclass init function
|
||||||
|
super().__init__("org.openflexure.microscope", version="0.0.0")
|
||||||
|
|
||||||
|
def on_microscope_handler(self, microscope_object):
|
||||||
|
print("Microscope object has been found!")
|
||||||
|
self.microscope = microscope_object
|
||||||
|
|
@ -24,3 +24,13 @@ Once this extension is loaded, any other extensions will have access to your met
|
||||||
# Call a function from your extension
|
# Call a function from your extension
|
||||||
if my_found_extension:
|
if my_found_extension:
|
||||||
my_found_extension.identify()
|
my_found_extension.identify()
|
||||||
|
|
||||||
|
|
||||||
|
Subclassing ``BaseExtension``
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The syntax used above allows novice programmers to easily start building extensions, without having to deal with subclassing. However, for more complex extensions which require persistent state, subclassing :py:class:`labthings.server.extensions.BaseExtension` is recommended.
|
||||||
|
|
||||||
|
The same simple extension as seen above can be written using subclassing:
|
||||||
|
|
||||||
|
.. literalinclude:: ./example_extension/01b_basic_structure_subclass.py
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,4 @@ Developing API Extensions
|
||||||
./extensions/actions.rst
|
./extensions/actions.rst
|
||||||
./extensions/tasks_locks.rst
|
./extensions/tasks_locks.rst
|
||||||
./extensions/ev_gui.rst
|
./extensions/ev_gui.rst
|
||||||
|
./extensions/lifecycle_hooks.rst
|
||||||
Loading…
Add table
Add a link
Reference in a new issue