[ENH]: Prepare Junifer for extension support #366
8 changed files with 75 additions and 2 deletions
1
docs/changes/newsfragments/366.doc
Normal file
1
docs/changes/newsfragments/366.doc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add documentation on how to make a ``junifer`` plugin by `Synchon Mandal`_
|
||||
1
docs/changes/newsfragments/366.feature
Normal file
1
docs/changes/newsfragments/366.feature
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add support for plugins by `Synchon Mandal`_
|
||||
|
|
@ -30,3 +30,4 @@ DataGrabbers, Preprocessors, Markers, etc., following the *junifer* way.
|
|||
parcellations
|
||||
coordinates
|
||||
masks
|
||||
plugins
|
||||
|
|
|
|||
50
docs/extending/plugins.rst
Normal file
50
docs/extending/plugins.rst
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
.. include:: ../links.inc
|
||||
|
||||
.. _plugins:
|
||||
|
||||
Creating a ``junifer`` plugin
|
||||
=============================
|
||||
|
||||
What is a plugin
|
||||
----------------
|
||||
|
||||
Plugins are additional components that extend the functionality of ``junifer``.
|
||||
Technically, plugins can also be called as extensions, but we clearly differentiate
|
||||
them in ``junifer`` as :ref:`extensions<extending_extension>` serve a different
|
||||
purpose. ``junifer`` plugins are command line programs which can be used
|
||||
independently but also integrates with the core ``junifer`` command line interface
|
||||
(CLI) framework.
|
||||
|
||||
When a plugin is installed, we basically inject new behaviours into the ``junifer`` CLI
|
||||
while promoting modularity and allowing for easier maintenance and updates to the core
|
||||
application. A great plugin example is `junifer-data`_ which is well-integrated
|
||||
in ``junifer`` to access assets like parcellations, coordinates and masks, but also
|
||||
remains modular enough to update its CLI without disturbing that of ``junifer``.
|
||||
|
||||
How to make a plugin
|
||||
--------------------
|
||||
|
||||
A key distinction between a ``junifer`` extension and a ``junifer`` plugin is that a
|
||||
plugin will have its own CLI and be a Python package in its own right, for example,
|
||||
`junifer-data`_.
|
||||
|
||||
The following steps should lead you to make a successful plugin:
|
||||
|
||||
#. Create CLI for your plugin. As ``junifer`` uses `click`_ for its CLI, a plugin
|
||||
should be creating its own ``click.Group`` as shown here:
|
||||
`<https://click.palletsprojects.com/en/stable/commands/#commands-and-groups>`_.
|
||||
|
||||
#. Integrate the `click`_-based plugin CLI with `setuptools`_ as shown here:
|
||||
`<https://click.palletsprojects.com/en/stable/setuptools/#setuptools-integration>`_.
|
||||
|
||||
#. Make sure the plugin CLI independently works as intended.
|
||||
|
||||
#. Follow the steps here:
|
||||
`<https://setuptools.pypa.io/en/latest/userguide/entry_point.html#entry-points-for-plugins>`_
|
||||
and make a new entry point with the *name* as the sub-command you want under ``junifer`` command
|
||||
and the *group* as ``"junifer.ext"``. The *name* should refer to the ``click.Group`` of your
|
||||
plugin CLI.
|
||||
|
||||
#. After you install your plugin in the same environment as your ``junifer`` installation, you can
|
||||
observe your plugin being added as a new sub-command under ``junifer`` and working exactly as it
|
||||
did independently.
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
.. _`AML`: https://www.fz-juelich.de/inm/inm-7/EN/Forschung/Applied%20Machine%20Learning/_node.html
|
||||
.. _`INM-7`: https://www.fz-juelich.de/inm/inm-7/EN/Home/home_node.html
|
||||
.. _`julearn`: https://juaml.github.io/julearn
|
||||
.. _`junifer-data`: https://github.com/juaml/junifer-data-client
|
||||
|
||||
.. _`pandas`: https://pandas.pydata.org
|
||||
.. _`pandas.DataFrame` : https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
.. _`nipype`: https://nipype.readthedocs.io
|
||||
.. _`datalad`: https://datalad.org
|
||||
.. _`templateflow`: https://www.templateflow.org
|
||||
.. _`click`: https://click.palletsprojects.com/en/stable/
|
||||
|
||||
.. _`venv`: https://docs.python.org/3/tutorial/venv.html
|
||||
.. _`conda env`: https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html
|
||||
|
|
@ -36,6 +38,7 @@
|
|||
.. _`Wikipedia`: https://wikipedia.org
|
||||
.. _`YAML`: https://yaml.org
|
||||
|
||||
.. _`setuptools`: https://setuptools.pypa.io/en/latest/
|
||||
.. _`setuptools_scm`: https://github.com/pypa/setuptools_scm/
|
||||
|
||||
.. _`sphinx gallery`: https://sphinx-gallery.github.io/stable/index.html
|
||||
|
|
|
|||
|
|
@ -3,7 +3,22 @@
|
|||
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
||||
# License: AGPL
|
||||
|
||||
import sys
|
||||
|
||||
import lazy_loader as lazy
|
||||
|
||||
|
||||
if sys.version_info < (3, 11): # pragma: no cover
|
||||
from importlib_metadata import entry_points
|
||||
else:
|
||||
from importlib.metadata import entry_points
|
||||
|
||||
|
||||
__getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
|
||||
|
||||
|
||||
# Register extensions
|
||||
from .cli import cli
|
||||
|
||||
for ep in entry_points(group="junifer.ext"):
|
||||
cli.add_command(ep.load(), name=ep.name)
|
||||
|
|
|
|||
|
|
@ -111,7 +111,9 @@ def _validate_verbose(
|
|||
)
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.group
|
||||
@click.version_option()
|
||||
@click.help_option()
|
||||
def cli() -> None: # pragma: no cover
|
||||
"""JUelich NeuroImaging FEature extractoR."""
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ dependencies = [
|
|||
"lazy_loader==0.4",
|
||||
"importlib_metadata; python_version<'3.9'",
|
||||
"looseversion==1.3.0; python_version>='3.12'",
|
||||
"junifer_data==1.2.0",
|
||||
"junifer_data==1.3.0",
|
||||
]
|
||||
dynamic = ["version"]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue