Code indexing in gitaly is broken and leads to code not being visible to the user. We work on the issue with highest priority.

Skip to content

Draft: Resolve "Load plugins from installed bec_plugins automatically"

Description

DRAFT FOR DISCUSSION

This MR demonstrates a possible way to have BEC plugins following the Python plugins documentation.

It is based on !526 (merged) , because like this I could also propose --help showing the different options added by the plugin easily.

I think plugins should be independent "projects", adding the right entry point in their pyproject.toml (in fact, like pytest or other projects like flask are doing...). So, to demonstrate a project like this the "csaxs" plugin is added to bec/bec_plugins/csaxs ; of course it is just an example. In real life it can be another gitlab repository, the plugin code should have nothing to do with BEC source code.

There are 2 "mount points" for the plugin:

  • extend_command_line_args(parser): called from the application (BEC client), with the parser object -> it can be completed by the plugin user to add command line arguments
  • setup(parser): called from the application, once it is initialized -> should add things in BEC or alter prompt, whatever

Complete code of the "csaxs" plugin (file bec/bec_plugins/csaxs/bec_csaxs_plugin.py):

def extend_command_line_args(parser):
    parser.add_argument("--session", help="Session name", type=str, default="my_default_session")

def setup(parser):
    args = parser.parse_args()

    if args.session == "my_session":
        print("Loading my_session session")
    else:
        print("Loading default session")

    # SETUP PROMPTS
    bec._ip.prompts.username = args.session
    bec._ip.prompts.status = 1

And corresponding pyproject.toml:

[project]
name = "csaxs_plugin"
version = "0.1"
dependencies = [
    "bec-lib",
    "bec-client"
]

[project.entry-points.'bec.plugins']
csaxs = 'bec_csaxs_plugin'

So the plugin is called csaxs, it will be found under bec.plugins by importlib and the plugin code is bec_csaxs_plugin.py.

It is enough to do pip install . in the plugin source directory to add the plugin to BEC.

Once done, we can have BEC client loading plugins:

parser = argparse.ArgumentParser(
    prog="BEC IPython client", description="BEC command line interface"
)
parser.add_argument("--version", action="store_true", default=False)
parser.add_argument("--nogui", action="store_true", default=False)
parser.add_argument("--config", action="store", default=None)

### NEW CODE
# look for plugins, complete parser with extra args
from importlib.metadata import entry_points
discovered_plugins = entry_points(group='bec.plugins')
plugin_modules = []
for plugin in discovered_plugins:
    print(f"Loading BEC plugin: {plugin.name}")
    plugin_module = plugin.load()
    plugin_modules.append(plugin_module)
    plugin_module.extend_command_line_args(parser)
### END OF NEW CODE

args, left_args = parser.parse_known_args()

The code above extends the arguments parser:

(bec) [matias@kashyyyk bec]$ bec --help
Loading BEC plugin: csaxs
usage: BEC IPython client [-h] [--version] [--nogui] [--config CONFIG] [--session SESSION]

BEC command line interface

options:
  -h, --help         show this help message and exit
  --version
  --nogui
  --config CONFIG
  --session SESSION  Session name     <<<<<<<<<<<<<<< SEE ADDED ENTRY

And it is easy to call .setup() on the plugin(s) to have them initalized:

# go through plugins and initialize those
for plugin in plugin_modules:
    plugin.setup(parser)

try:
    app.start()
finally: 
    bec.shutdown()

Result:

(bec) [matias@kashyyyk bec]$ bec --session bla
Loading BEC plugin: csaxs  <<<<<<<<<<<<<<<<<<<< plugin is loaded
Python 3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:43:09) [GCC 12.3.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.22.2 -- An enhanced Interactive Python. Type '?' for help.
2024-04-03 16:34:55 | [INFO] | Waiting for ScanServer.
2024-04-03 16:34:55 | [SUCCESS] | ScanServer is running.
2024-04-03 16:34:55 | [INFO] | Waiting for ScanBundler.
2024-04-03 16:34:55 | [SUCCESS] | ScanBundler is running.
2024-04-03 16:34:55 | [INFO] | Waiting for DeviceServer.
2024-04-03 16:34:55 | [SUCCESS] | DeviceServer is running.
2024-04-03 16:34:55 | [INFO] | Waiting for SciHub.
2024-04-03 16:34:55 | [SUCCESS] | SciHub is running.
2024-04-03 16:34:55 | [SUCCESS] | All BEC services are running.
Loading default session

• my_default_session [1/2] ❯❯ 
^^^^^^^^^^^^^^^^^^^^^^
prompt is changed

Closes #193 (closed)

Merge request reports