Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New extension manager #12866

Merged
merged 46 commits into from
Sep 7, 2022

Conversation

fcollonval
Copy link
Member

@fcollonval fcollonval commented Jul 27, 2022

References

Related to #11336

Code changes

  • The extension manager is fully on the backend

    • Extension manager is picked from a entry point jupyterlab.extension_manager_v1 that must implement a callback receiving optionally AppOptions, ExtensionsOption (in dictionary format) and LabApp and returning and ExtensionManager. Two default implementations are provided:
      readonly = jupyterlab.extensions:get_readonly_manager
      pypi = jupyterlab.extensions:get_pypi_manager
    • Allowed and blocked list feature is implemented in the abstract ExtensionManager but third-party may override it.
    • Listing installed extensions, enabling and disabling extensions is implemented in the abstract ExtensionManager (but could be overridden)
    • ExtensionManager inherits from traitlets.config.LoggingConfigurable to be configurable. It receives the config from LabApp by passing it as parent of the configurable.
    • Abstract methods that must be implemented are:
      - metadata: Returns extension manager metadata that will be saved in PageConfig['extension_manager'] to tune the extension manager panel
      - name: Name of the extension manager
      - can_install: whether the extension manager can (un-)install extensions
      - install_path: Extensions installation path; e.g. Python virtual environment
      - get_latest_version: Get the latest version of an extension
      - list_packages: List packages for a given query
      - install: Install a package
      - uninstall: Uninstall a package
    • Actions install, uninstall, enable and disable return a json object with a status (ok, warning, error), optional message and a list of follow-ups restart actions (server, kernels, frontend).
  • The frontend

    • presents a generic listing of extensions installed or resulting from a search query
    • Use the generic SidePanel widget with AccordionPanel for UI homogeneity
  • PyPI manager

    • Get the list of extensions from the classifier Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt
    • No check is performed to ensure the extension is compatible with the current JupyterLab version
    • No download statistics can be retrieve from PyPI directly. So the extensions are sorted in alphabetical order.
    • The name of the Python package for an extension is extracted from the install.json file. If it is missing, it normalized the npm package name. But there is no guarantee that it will be the pip package name => some packages may fail to get uninstall.
    • To know if a server or kernels restart are required, the jupyterlab.discovery metadata in package.json are used. They may not be accurate.
    • PyPI manager configurable; the base URL, the timeouts
  • Read-only manager:

    • Allows users to enable/disable installed extensions
    • Does not support un-/installing extensions.

Upgrading @lumino/widgets in staging was required for the splice-source test to succeed.

User-facing changes

By default they can installed or uninstalled pre-built extensions via pip.

The two default managers:

PyPI Read-only
Screenshot from 2022-08-25 12-09-58 Screenshot from 2022-08-25 12-08-26

Backwards-incompatible changes

Break the api as most features are now in the backend.

@jupyterlab-probot
Copy link

Thanks for making a pull request to jupyterlab!
To try out this branch on binder, follow this link: Binder

jupyterlab/extensions/manager.py Fixed Show fixed Hide fixed
jupyterlab/extensions/pypi.py Fixed Show fixed Hide fixed
jupyterlab/extensions/manager.py Fixed Show fixed Hide fixed
jupyterlab/extensions/manager.py Fixed Show fixed Hide fixed
@fcollonval
Copy link
Member Author

CI failure requires jupyterlab/lumino#321 to be reviewed, merged and published. But as this brings lots of changes reviews are welcomed.

@agoose77
Copy link
Contributor

@fcollonval this looks really cool. Thanks for all of the hard work!

Thinking about the ExtensionManager class, is there a reason not to have it inherit from traitlets.Configurable? Although third-party extension managers might not need this, for the default ones might it be useful down the road if we add configuration e.g. for BASE_URL?

@fcollonval
Copy link
Member Author

Thinking about the ExtensionManager class, is there a reason not to have it inherit from traitlets.Configurable? Although third-party extension managers might not need this, for the default ones might it be useful down the road if we add configuration e.g. for BASE_URL?

I mimic what was done in the pull-requests extension - dropping the configuration for now. But yes there is surely high value of adding configurable capability.
Do you know if a Configurable can also inherit from abstract class? I have the feeling inheriting from Configurable will require dropping inheriting from abstract class.

@agoose77
Copy link
Contributor

Do you know if a Configurable can also inherit from abstract class?

I don't believe so - both implementations leverage a metaclass (which probably could be chained, but it's messy).

If you want to keep this PR constrained, given that it doesn't add a configuration mechanism it's probably OK to hold off! :)

@jtpio
Copy link
Member

jtpio commented Aug 4, 2022

CI failure requires jupyterlab/lumino#321 to be reviewed, merged and published.

Looks like jupyterlab/lumino#321 has now been merged. Since it is on main which also includes other major changes for Lumino 2, do we want to wait for Lumino 2 to be released, or can this be backported to the 1.x branch and a new release made from the 1.x branch?

}


class PyPIExtensionManager(ExtensionManager):

Check failure

Code scanning / CodeQL

Missing call to `__init__` during object initialization

Class PyPIExtensionManager may not be initialized properly as [method HasTraits.__init__](1) is not called from its [__init__ method](2).
@fcollonval
Copy link
Member Author

bot please update documentation snapshots

@blink1073
Copy link
Member

The pagination looks good, thanks! I think we should merge and iterate once tests pass, this PR is awkward to review given the number of commits and comments.

@krassowski krassowski dismissed their stale review September 6, 2022 19:46

Requested changes addressed

@fcollonval
Copy link
Member Author

bot please update documentation snapshots

@fcollonval
Copy link
Member Author

Merging as CI is green (remain failure is not related)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-change A change that should be accompanied by a major version increase Design System CSS documentation enhancement pkg:extensionmanager pkg:services pkg:ui-components tag:CSS For general CSS related issues and pecadilloes tag:Testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants