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_plugins

  • Discovery 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’s OCLI_PLUGIN_API_VERSION

  • No 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_plugins

  • Metadata 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_plugins namespace package is not installed, the loader quietly exits

  • Each discovered submodule is imported; any side effects in its top-level code will execute

  • PLUGIN_API_VERSION is 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>-plugin

  • Package 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 that ocli_plugins is a namespace (no __init__.py at the root)

  • API version warnings: check your PLUGIN_API_VERSION against core’s OCLI_PLUGIN_API_VERSION (currently 1)

  • 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.