Skip to content

feat(plugins): local plugin catalogs in shared folders - #399

Merged
PierreRaybaut merged 1 commit into
developfrom
feature/local-plugin-catalog
Oct 19, 2026
Merged

PierreRaybaut merged 1 commit into
developfrom
feature/local-plugin-catalog

Conversation

@PierreRaybaut

Copy link
Copy Markdown
Contributor

Lets organizations distribute their own plugins, or the versions of public plugins they have approved, from local plugin catalogs. A local catalog is a folder, typically a network share, read in addition to the online DataLab plugin catalog.

Why

The Available plugins tab read a single catalog, set by the plugins_catalog_url option (configuration file only). A file: URL was accepted, but:

  • it replaced the online catalog instead of complementing it;
  • it failed with standard Windows UNC paths: Path(r"\\server\share\catalog.json").as_uri() gives file://server/share/..., which urllib refuses. Only file:////server/... works, which users are unlikely to guess.

What changes

Local catalogs (datalab/plugins/catalog.py, Qt-free)

  • A folder provides its catalog.json file if any, with release URLs relative to the folder and kept inside it. Otherwise DataLab lists the plugin wheels the folder holds (pure Python, datalab.plugins entry point, versions grouped). Other files are ignored and reported.
  • Folders are read as files, so UNC paths work. The existing online catalog behavior is unchanged.
  • load_catalogs() reads every source independently. A source that cannot be read (disconnected share, no Internet access) is reported without hiding the plugins of the other sources.
  • Priority: DATALAB_PLUGINS_CATALOG folders, then configured folders, then the online catalog. A plugin listed by a local catalog hides the same plugin (same distribution or ID) in the following catalogs. When a hidden online entry is revoked, a warning is shown.

Configuration

  • New plugins_catalog_path_list option.
  • New DATALAB_PLUGINS_CATALOG environment variable (os.pathsep-separated). It is read when catalogs are loaded, and missing folders are kept: a share unavailable at startup is reported, not silently dropped.

User interface

  • Plugin settings tab: new Local plugin catalogs section with Add / Edit / Remove. Environment folders appear as read-only entries. Changes are saved on OK/Apply and do not require reloading plugins.
  • Available plugins tab: plugins from a local catalog are labeled Local catalog, with the folder in their tooltip. Per-source problems are shown in a dedicated label below the plugin count. The consent dialog shows Local plugin catalog (folder) as the origin.

Command line (datalab/plugins/catalogtool.py, Qt-free)

  • datalab-plugin catalog build <folder> writes catalog.json from the folder wheels. Each wheel is checked as DataLab does before installing it, for one of the Python versions DataLab supports. Edited fields (ID, name, tier, status and reason, repository, keywords, yanked…) are kept, and revoked plugins stay listed. The file is replaced atomically, and nothing is written if a wheel is refused.
  • datalab-plugin catalog check <folder> reports missing, changed, refused or unlisted wheels. Exit code 1 on problems.

Other

  • store.get_available_distributions() is extracted as a module function and reused by the CLI.
  • SearchPathItemWidget now takes the name of the environment variable providing a path (env_var) instead of a from_env flag.

Documentation and translations

  • doc/features/advanced/plugins.rst: new Local plugin catalogs subsection. The paragraph recommending file: URLs for network folders is replaced.
  • doc/release_notes/release_1.04.md: three user-facing bullets in Plugin installation.
  • French translations of the UI and the doc. Translation-template extraction excluded the stale build/lib sources, and only the entries related to this feature were updated.

Tests

  • plugin_local_catalog_unit_test.py: folder scan, local catalog.json (relative paths, escaping the folder refused), copy with digest check, precedence and per-source errors, environment variable.
  • plugin_catalogtool_unit_test.py: build and check, curated fields kept, refused wheels, exit codes.
  • plugin_available_dialog_test.py: local catalog takes precedence and installs with the expected origin, failing online source, settings section persisted without reload prompt.
  • catalogtool added to the Qt-free import contract test.

The plugin and configuration test suites pass locally (230 tests).

Notes for reviewers

  • Without catalog.json, the SHA-256 of every wheel is computed at each refresh. This is fine for a few dozen wheels on a share.
  • Once a folder holds a catalog.json, newly copied wheels appear only after datalab-plugin catalog build (documented, and reported by check).
  • DESKTOP_PYTHONS (3.9–3.14) must be updated when DataLab supports a new Python version.

Organizations can offer plugins from folders, typically network shares,
in addition to the online DataLab plugin catalog:

- A folder provides its catalog.json file if any, otherwise the plugin
  wheels it holds. It is read as files, so UNC paths work.
- Local catalogs are listed before the online catalog and hide the same
  plugins in it.
- Folders are set in the Plugin settings tab (plugins_catalog_path_list
  option) or with the DATALAB_PLUGINS_CATALOG environment variable.
- A catalog that cannot be read is reported without hiding the plugins
  of the other catalogs.
- "datalab-plugin catalog build" writes catalog.json from the wheels of
  a folder, keeping the edited fields. "datalab-plugin catalog check"
  reports wheels that are missing, changed, refused or not listed.

Includes tests, documentation, release notes and French translations.
@PierreRaybaut
PierreRaybaut merged commit 72885fc into develop Oct 19, 2026
4 checks passed
@PierreRaybaut
PierreRaybaut deleted the feature/local-plugin-catalog branch October 23, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant