# 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: ```python # 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--plugin` - Package name: `ocli_plugins.` Example structure: ``` pyproject.toml # or setup.py ocli_plugins/ myplugin/ __init__.py hooks.py ``` Minimal example code: ```python # 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): ```python 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: ```toml [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.` 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.