diff --git a/debian/control b/debian/control index 1a003b4..d502bbd 100644 --- a/debian/control +++ b/debian/control @@ -18,6 +18,7 @@ Depends: ${python3:Depends}, python3-click, python3-dateutil, python3-flask, + python3-importlib-metadata, python3-jsonschema, python3-tz, python3-unicodecsv, diff --git a/docs/source/plugins.rst b/docs/source/plugins.rst index 55adaee..6cce316 100644 --- a/docs/source/plugins.rst +++ b/docs/source/plugins.rst @@ -66,6 +66,56 @@ The following methods are options to connect a plugin to pygeoapi: id_field: stn_id +Specifying custom pygeoapi CLI commands ++++++++++++++++++++++++++++++++++++++++ + +Third-party plugins may also provide custom CLI commands. This can be done by means of two additional steps: + +1. Create your CLI commands using click +2. In your plugin's ``setup.py`` or ``pyproject.toml`` file, specify an entrypoint for the ``pygeoapi`` group + pointing to your click CLI command or group. + +As a simple example, lets imagine you develop a plugin named ``myplugin``, which has a ``cli.py`` module with +the following contents: + +.. code-block:: python + + # module: myplugin.cli + import click + + @click.command(name="super-command") + def my_cli_command(): + print("Hello, this is my custom pygeoapi CLI command!") + + +Then, in your plugin's ``setup.py`` file, specify the entrypoints section: + +.. code-block:: python + + # file: setup.py + entry_points={ + 'pygeoapi': ['my-plugin = myplugin.cli:my_cli_command'] + } + +Alternatively, if using a ``pyproject.toml`` file instead: + +.. code-block:: python + + # file: pyproject.toml + # Noter that this example uses poetry, other Python projects may differ in + # how they expect entry_points to be specified + [tool.poetry.plugins."pygeoapi"] + my-plugin = 'myplugin.cli:my_cli_command' + + +After having installed this plugin, you should now be able to call the CLI command by running: + +.. code-block:: sh + + $ pygeoapi plugins super-command + Hello, this is my custom pygeoapi CLI command! + + .. note:: The United States Geological Survey has created a Cookiecutter project for creating pygeoapi plugins. See the `pygeoapi-plugin-cookiecutter`_ project to get started. **Option 2**: Update in core pygeoapi: diff --git a/pygeoapi/__init__.py b/pygeoapi/__init__.py index 2316086..91f9dfd 100644 --- a/pygeoapi/__init__.py +++ b/pygeoapi/__init__.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Tom Kralidis +# Ricardo Garcia Silva # # Copyright (c) 2021 Tom Kralidis +# Copyright (c) 2023 Ricardo Garcia Silva # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -30,16 +32,47 @@ __version__ = '0.15.dev0' import click +try: + # importlib.metadata is part of Python's standard library from 3.8 + from importlib.metadata import entry_points +except ImportError: + from importlib_metadata import entry_points from pygeoapi.config import config from pygeoapi.openapi import openapi +def _find_plugins(): + """ + A decorator to find pygeoapi CLI plugins provided by third-party packages. + + pygeoapi plugins can hook into the pygeoapi CLI by providing their CLI + functions and then using an entry_point named 'pygeoapi'. + """ + + def decorator(click_group): + for entry_point in entry_points(group="pygeoapi"): + try: + click_group.add_command(entry_point.load()) + except Exception as err: + print(err) + return click_group + + return decorator + + @click.group() @click.version_option(version=__version__) def cli(): pass +@_find_plugins() +@cli.group() +def plugins(): + """Additional commands provided by third-party pygeoapi plugins""" + pass + + @cli.command() @click.option('--flask', 'server', flag_value="flask", default=True) @click.option('--starlette', 'server', flag_value="starlette") diff --git a/requirements.txt b/requirements.txt index f6e5c7b..ae03a17 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ Babel click Flask +importlib_metadata jinja2 jsonschema pydantic