diff --git a/docs/source/stonesoup.plugins.rst b/docs/source/stonesoup.plugins.rst new file mode 100644 index 000000000..f01cfd832 --- /dev/null +++ b/docs/source/stonesoup.plugins.rst @@ -0,0 +1,5 @@ +Plugins +======= + +.. automodule:: stonesoup.plugins + diff --git a/docs/source/stonesoup.rst b/docs/source/stonesoup.rst index 29aa3634e..d61d5da63 100644 --- a/docs/source/stonesoup.rst +++ b/docs/source/stonesoup.rst @@ -11,6 +11,7 @@ Stone Soup Framework stonesoup.functions stonesoup.measures stonesoup.plotter + stonesoup.plugins stonesoup.serialise Components diff --git a/stonesoup/plugins.py b/stonesoup/plugins.py new file mode 100644 index 000000000..60dac965f --- /dev/null +++ b/stonesoup/plugins.py @@ -0,0 +1,41 @@ +""" +Plugin system for Stone Soup. + +Stone Soup is able to import plugins using package metadata. Packages can +register themselves for discovery by providing the :attr:`entry_points` argument +to setup() in :attr:`setup.py`. + +For example if you have a package named :attr:`my_package` and its :attr:`setup.py` file includes: + +.. code-block:: python + + setup( + ... + entry_points={'stonesoup.plugins': 'my_plugin = my_package'} + ... + ) + +Then Stone Soup will discover your plugin and load all of the registered entry points. It is +possible to name your plugin the same name as your package name in :attr:`setup()`. Your plugin +can be loaded using: + +.. code-block:: python + + from stonesoup.plugins.my_plugin import MyClass + +.. note:: + When developing plugins for Stone Soup, :attr:`entry_points` must be associated with + the :attr:`stonesoup.plugins` key in the :attr:`entry_points` dictionary. +""" +import sys +import pkg_resources +import warnings + +for entry_point in pkg_resources.iter_entry_points('stonesoup.plugins'): + try: + name = entry_point.name + plugin_module = f'{__name__}.{name}' + sys.modules[plugin_module] = entry_point.load() + + except (ImportError, ModuleNotFoundError) as e: + warnings.warn(f'Failed to load module. {e}')