diff --git a/docs/source/extensions/example_extension/01b_basic_structure_subclass.py b/docs/source/extensions/example_extension/01b_basic_structure_subclass.py new file mode 100644 index 00000000..6177a2a9 --- /dev/null +++ b/docs/source/extensions/example_extension/01b_basic_structure_subclass.py @@ -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() diff --git a/docs/source/extensions/lifecycle_hooks.rst b/docs/source/extensions/lifecycle_hooks.rst new file mode 100644 index 00000000..451618a4 --- /dev/null +++ b/docs/source/extensions/lifecycle_hooks.rst @@ -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 \ No newline at end of file diff --git a/docs/source/extensions/structure.rst b/docs/source/extensions/structure.rst index ee2bc478..9d35e934 100644 --- a/docs/source/extensions/structure.rst +++ b/docs/source/extensions/structure.rst @@ -23,4 +23,14 @@ Once this extension is loaded, any other extensions will have access to your met # Call a function from your extension if my_found_extension: - my_found_extension.identify() \ No newline at end of file + 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 diff --git a/docs/source/plugins.rst b/docs/source/plugins.rst index ad28657e..bb865f26 100644 --- a/docs/source/plugins.rst +++ b/docs/source/plugins.rst @@ -11,4 +11,5 @@ Developing API Extensions ./extensions/properties.rst ./extensions/actions.rst ./extensions/tasks_locks.rst - ./extensions/ev_gui.rst \ No newline at end of file + ./extensions/ev_gui.rst + ./extensions/lifecycle_hooks.rst \ No newline at end of file