diff --git a/docs/backend_architecture/plugins.rst b/docs/backend_architecture/plugins.rst index 175fcd5e005..b17e3c33049 100644 --- a/docs/backend_architecture/plugins.rst +++ b/docs/backend_architecture/plugins.rst @@ -44,6 +44,19 @@ Similarly, to disable the plugin the following command can be used: kolibri plugin disable kolibri.plugins.example_plugin +.. note:: + **Using externally-built plugins with PEX** + + When using externally-built plugins (plugins installed separately from Kolibri's core installation) with a PEX distribution of Kolibri, you must set the environment variable ``PEX_INHERIT_PATH=fallback`` to enable the PEX file to access plugins installed in the system Python path. + + For example: + + .. code-block:: bash + + PEX_INHERIT_PATH=1 python kolibri.pex start + + This allows Kolibri to discover and use plugins that were installed via ``pip install`` outside of the PEX environment. + To exactly set the currently enabled plugins (disabling all other plugins, and enabling the ones specified) you can do this: .. code-block:: bash diff --git a/kolibri/utils/cli.py b/kolibri/utils/cli.py index 813e251eb49..c3ad3340411 100644 --- a/kolibri/utils/cli.py +++ b/kolibri/utils/cli.py @@ -1,4 +1,5 @@ import logging +import os import signal import sys import traceback @@ -22,6 +23,7 @@ from kolibri.utils import server from kolibri.utils.compat import module_exists from kolibri.utils.conf import OPTIONS +from kolibri.utils.constants import installation_types from kolibri.utils.debian_check import check_debian_user from kolibri.utils.main import initialize from kolibri.utils.main import set_django_settings_and_python_path @@ -390,6 +392,33 @@ def plugin(): pass +def generate_pex_error(): + """ + Format plugin error message with additional context for PEX installations. + """ + if "PEX_INHERIT_PATH" in os.environ and ( + os.environ["PEX_INHERIT_PATH"] == "fallback" + or os.environ["PEX_INHERIT_PATH"] == "prefer" + ): + return "" + + # Add PEX-specific help if running from PEX + current_installation = server.installation_type() + if ( + current_installation + and installation_types.PEX.lower() in current_installation.lower() + ): + return ( + "\n\nYou are running Kolibri from a PEX file. " + "To use externally-installed plugins with PEX, you must set the " + "PEX_INHERIT_PATH environment variable:\n\n" + " PEX_INHERIT_PATH=fallback python kolibri.pex start\n\n" + "This allows the PEX file to access plugins installed in the system Python path." + ) + + return "" + + @plugin.command(cls=KolibriCommand, help="Enable Kolibri plugins") @click.argument("plugin_names", nargs=-1) @click.option("-d", "--default-plugins", default=False, is_flag=True) @@ -399,7 +428,9 @@ def enable(plugin_names, default_plugins): else: error = enable_plugins(plugin_names) if error: - exception = click.ClickException("One or more plugins could not be enabled") + exception = click.ClickException( + "One or more plugins could not be enabled" + generate_pex_error() + ) exception.exit_code = 2 raise exception @@ -428,7 +459,7 @@ def apply(plugin_names): error = enable_plugins(plugin_names) or error if error: exception = click.ClickException( - "An error occurred applying the plugin configuration" + "An error occurred applying the plugin configuration" + generate_pex_error() ) exception.exit_code = 2 raise exception