Open fcollonval opened 1 year ago
Thank you for opening your first issue in this project! Engagement like this is essential for open source projects! :hugs:
If you haven't done so already, check out Jupyter's Code of Conduct. Also, please try to follow the issue template as it helps other other community members to contribute more effectively.
You can meet the other Jovyans by joining our Discourse forum. There is also an intro thread there where you can stop by and say Hi! :wave:
Welcome to the Jupyter community! :tada:
Discussion notes: https://hackmd.io/DBlDBDszSVSjYK9ieg1mZA
More thoughts about this for the GSoC project that will be implemented in JupyterLab repo directly - on a specific branch.
[!NOTE] This is a proposal to help kicking off an implementation
A type of application feature is defined by an object provided by a plugin through a Token
or an attribute of the Application
. Other plugins may request that token to add a variant for that feature. For example, a application feature is the command that can be added through the CommandRegistry
. Another example is a document viewer that can be added through the DocRegistry
in JupyterLab. In the following I will name registry an object allowing to add a type of application feature.
Therefore the generic logic to use entrypoints is the following:
Application
Application
Application
. So that the application can disposed them before activating the associated plugin.Let take the example of a new document viewer for CSV (interface IWidgetFactory) that is added to the DocRegistry using addWidgetFactory.
If the JSON schema of IWidgetFactory
looks like:
{
defaultFor?: readonly string[];
defaultRendered?: readonly string[];
fileTypes: readonly string[];
label?: string;
modelName?: string;
name: string;
}
The placeholder interface will be something like:
interface IPlaceholder extends IObservableDisposable {}
The idea of using
IObservableDisposable
is to automatically trigger loading and activating the plugin by theApplication
when it is notified that a placeholder is disposed. But a dedicated method inIPlaceholder
that returns a Promise resolving when the plugin is activated may be more appropriate to know when the actual call to the feature can be made.
The example could be
{
"name": "CSVTable",
"label": "CSV Viewer",
"fileTypes": ["csv"],
"defaultFor": ["csv"]
}
class WidgetFactoryPlaceholder implements IWidgetFactory, IPlaceholder {
constructor(entrypoint: IWidgetFactoryPlaceholder) {
// ...
}
createNew() {
// This is actually this method that when triggered should load the plugin
}
}
The DocRegistry
would add the placeholder:
app.docRegistry.addWidgetFactory(new WidgetFactoryPlaceholder(entrypoint));
[!NOTE] One of the technical difficulty is to be able to redo the action triggered on the placeholder with the real code once the plugin is loaded. For the aforementioned example, this materializes in how to trigger the widget factory
createNew
method from the real code.
To reduce the start-up time of JupyterLab, we could be smarter about plugin loading logic. For now, a Lumino plugin can be started automatically or not using the autoStart flag. But there is no way to specify conditions for which a plugin should start.
Before laying down a plan for Lumino plugin, here is an analysis of VS Code extension API that allows to conditionally load plugins. There are two key points:
In VS Code, those elements are defined in the extension package.json. The entry points are for example (see contributions documentation):
The trigger events are for example (see activation events documentation):
onCommand
: When a command of the extension is triggeredonView
: When a specific view is restoredonStartupFinished
: After the application has started The side effect of defining the contributed element in a no-code format raises the need to have an evaluable string to determine if an element is activable or not. This is calledwhen
clause in VS Code.Back to JupyterLab and Lumino, the equivalent of
onStartupFinished
could be implemented quickly. But it may result in unwanted side effects; e.g. if the plugin is providing a widget and that widget is used in a notebook output that is loaded at startup, the widget may or may not be rendered. To ensure robustness, other events should be available; for example the widget plugin should load before opening a notebook.Plugins adding new panels in the main area or in the side panel, like jupyterlab-git, are probably the best candidates for optimization. This requires defining side panels and main area widgets in a no-code way. In JupyterLab, we introduced the definition of keyboard shortcuts and menus in setting schema files. So it seems a more natural place than the extension
package.json
.To be able to add a panel, widget titles need to be defined in a no-code way. This requires in particular the definition of icons in a no-code way.
Some first actions could be:
autoStart
to be a boolean or ‘"defer"’ (done in #588)