From acaecb229fd7cbe8ea7ff370aef304671e44ec5e Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Mar 2025 14:55:33 +0100 Subject: [PATCH 1/5] update: add help and version option to junifer cli group --- junifer/cli/cli.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/junifer/cli/cli.py b/junifer/cli/cli.py index b7081daa2..5d7b1cc7c 100644 --- a/junifer/cli/cli.py +++ b/junifer/cli/cli.py @@ -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.""" -- 2.52.0 From 35a73eace91c7cd974389e82cdbf985868f56ed9 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Mar 2025 14:56:10 +0100 Subject: [PATCH 2/5] feat: add support for registering junifer extensions in cli --- junifer/cli/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/junifer/cli/__init__.py b/junifer/cli/__init__.py index 675084ab5..e7e724fb1 100644 --- a/junifer/cli/__init__.py +++ b/junifer/cli/__init__.py @@ -3,7 +3,22 @@ # Authors: Synchon Mandal # 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) -- 2.52.0 From d3ba2bd3e167a6a32bb0cdc6e10c66346d994894 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Mar 2025 17:54:06 +0100 Subject: [PATCH 3/5] docs: add page on how to make a plugin --- docs/extending/index.rst | 1 + docs/extending/plugins.rst | 50 ++++++++++++++++++++++++++++++++++++++ docs/links.inc | 3 +++ 3 files changed, 54 insertions(+) create mode 100644 docs/extending/plugins.rst diff --git a/docs/extending/index.rst b/docs/extending/index.rst index ac441aa34..5a95060fb 100644 --- a/docs/extending/index.rst +++ b/docs/extending/index.rst @@ -30,3 +30,4 @@ DataGrabbers, Preprocessors, Markers, etc., following the *junifer* way. parcellations coordinates masks + plugins diff --git a/docs/extending/plugins.rst b/docs/extending/plugins.rst new file mode 100644 index 000000000..166c59a13 --- /dev/null +++ b/docs/extending/plugins.rst @@ -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` 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: + ``_. + +#. Integrate the `click`_-based plugin CLI with `setuptools`_ as shown here: + ``_. + +#. Make sure the plugin CLI independently works as intended. + +#. Follow the steps here: + ``_ + 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. diff --git a/docs/links.inc b/docs/links.inc index aa697d703..dfc113e5b 100644 --- a/docs/links.inc +++ b/docs/links.inc @@ -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 -- 2.52.0 From bc124977abd1e18239e9d6cb6918f55db3e30f68 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Mar 2025 17:56:19 +0100 Subject: [PATCH 4/5] chore: add changelogs 366.{doc,feature} --- docs/changes/newsfragments/366.doc | 1 + docs/changes/newsfragments/366.feature | 1 + 2 files changed, 2 insertions(+) create mode 100644 docs/changes/newsfragments/366.doc create mode 100644 docs/changes/newsfragments/366.feature diff --git a/docs/changes/newsfragments/366.doc b/docs/changes/newsfragments/366.doc new file mode 100644 index 000000000..95f7e61ff --- /dev/null +++ b/docs/changes/newsfragments/366.doc @@ -0,0 +1 @@ +Add documentation on how to make a ``junifer`` plugin by `Synchon Mandal`_ diff --git a/docs/changes/newsfragments/366.feature b/docs/changes/newsfragments/366.feature new file mode 100644 index 000000000..e21bdbfb3 --- /dev/null +++ b/docs/changes/newsfragments/366.feature @@ -0,0 +1 @@ +Add support for plugins by `Synchon Mandal`_ -- 2.52.0 From 58a325da05ce420df332f16b527d5dd70cef5702 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 21 Mar 2025 14:34:14 +0100 Subject: [PATCH 5/5] chore: bump junifer_data to 1.3.0 to access junifer.ext --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 806ad6015..feb8713d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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"] -- 2.52.0