OCLI plugin system overview (as used by ocli-core)
This repository is part of the OCLI ecosystem. OCLI core provides a lightweight plugin system based on Python namespace packages (PEP 420). This document explains how the plugin system works in ocli-core and how to create plugins that OCLI can discover.
Key points:
Namespace for plugins:
ocli_pluginsDiscovery is best-effort: import errors in one plugin do not prevent loading others
Optional version guard: plugins may declare
PLUGIN_API_VERSION, compared to core’sOCLI_PLUGIN_API_VERSIONNo mandatory entry points; discovery relies on importing modules under the shared namespace
Why PEP 420 namespace plugins?
Simple install/uninstall via standard Python packaging (pip/venv/conda)
No central registry or entry points required
Multiple distributions can contribute to the same namespace
Trade-offs:
Avoid subpackage name conflicts under
ocli_pluginsMetadata is minimal; provide your own module-level constants or documentation
How discovery works in ocli-core
At startup, the CLI attempts to load plugins very early:
# ocli/ocli/cli/cli.py (excerpt)
from ocli.core.plugins import load_plugins
load_plugins("ocli_plugins")
Behavior notes:
If the
ocli_pluginsnamespace package is not installed, the loader quietly exitsEach discovered submodule is imported; any side effects in its top-level code will execute
PLUGIN_API_VERSIONis optional; mismatch emits a warning but does not prevent loading
Writing a plugin
Create a separate Python distribution that provides a subpackage under the shared namespace. Do not add __init__.py at the namespace root ocli_plugins/ (PEP 420 requirement), but your subpackage should have one if needed.
Recommended distribution name and layout:
Distribution name:
ocli-<your-plugin>-pluginPackage name:
ocli_plugins.<your_plugin>
Example structure:
pyproject.toml # or setup.py
ocli_plugins/
myplugin/
__init__.py
hooks.py
Minimal example code:
# ocli_plugins/myplugin/__init__.py
# Optional: declare the plugin API version expected by ocli-core
PLUGIN_API_VERSION = "1"
# Import your modules so their registrations/side effects occur at plugin import time
from . import hooks # noqa: F401
# hooks.py
# Put your registrations here. For example, define classes, register templates,
# or import modules that expose CLI commands which ocli will later reference.
Because the core loader only imports plugin modules, integration should happen via import-time registrations or by exposing objects that the core or other OCLI components import later by fully-qualified name (e.g., ocli_plugins.aikp.sentinel_1).
Packaging templates
Setuptools (setup.py):
from setuptools import setup, find_namespace_packages
setup(
name="ocli-myplugin-plugin",
version="0.1.0",
description="My OCLI plugin",
packages=find_namespace_packages(include=["ocli_plugins.*"]),
python_requires=">=3.9",
)
PEP 621 (pyproject.toml) with setuptools backend:
[build-system]
requires = ["setuptools>=61", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "ocli-myplugin-plugin"
version = "0.1.0"
description = "My OCLI plugin"
requires-python = ">=3.9"
[tool.setuptools]
packages = { find = { include = ["ocli_plugins.*"] } }
Troubleshooting
Plugin not discovered: ensure your distribution installs a package under
ocli_plugins.<your_plugin>and thatocli_pluginsis a namespace (no__init__.pyat the root)API version warnings: check your
PLUGIN_API_VERSIONagainst core’sOCLI_PLUGIN_API_VERSION(currently1)Import errors: the loader logs exceptions but continues with other plugins; check missing dependencies or syntax errors
Notes for contributors in this repo
This repository focuses on SarPy. The plugin system is provided by ocli-core; the early plugin discovery is triggered from the OCLI CLI. Use readme.md for legacy development environment instructions.