Skip to content

Commit

Permalink
Add config for autostart.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Fleming committed Oct 30, 2024
1 parent d6493b8 commit 7cc0d86
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 35 deletions.
1 change: 0 additions & 1 deletion .copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ project_short_description: Control JupyterLab from Python notebooks
python_name: ipylab
repository: https://github.com/jtpio/ipylab
test: false

53 changes: 40 additions & 13 deletions examples/plugins.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"source": [
"## Autostart\n",
"\n",
"Ipylab automatically starts a Python kernel with the path 'ipylab' when the ipylab plugin is activated. The `autostart` hookspec is called as soon as comms has been established. Autostart is performed prior to restoring Jupyterlab such as when refreshing the page or starting from scratch.\n",
"The `autostart` hookspec is called as when the App is ready.\n",
"\n",
"Possible uses include:\n",
"* Create and register custom commands;\n",
Expand Down Expand Up @@ -193,17 +193,12 @@
" )\n",
" await cmd.add_launcher(\"Ipylab\", extra=\"Ipylab extra arguments\")\n",
"\n",
" @ipylab.hookimpl\n",
" def vpath_getter(self, app: ipylab.App, kwgs: dict): # noqa: ARG002\n",
" return app.vpath\n",
"\n",
"pluginmodule = MyPlugins()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Instead of defining entry points and installing a module. Let's roughly simulate what the entry point does.\n",
"\n",
"Note that entry points will run 'autostart' for every kernel. The property `app.is_ipylab_kernel` can be used to determine if the code is running in the ipylab kernel."
"pluginmodule = MyPlugins()"
]
},
{
Expand Down Expand Up @@ -238,7 +233,7 @@
"source": [
"## Entry points\n",
"\n",
"Entry points provide for automatic registration for when ipylab is loaded.\n",
"Entry points provide for automatic registration for when ipylab is imported.\n",
"\n",
"Add the following in your `pyproject.toml`\n",
"\n",
Expand All @@ -260,8 +255,40 @@
"\n",
"plugin1 = MyPlugins()\n",
"plugin2 = MyOtherPlugins()\n",
"```"
"```\n",
"\n",
"\n",
"### Ipylab kernel (autostart)\n",
"\n",
"**Starting kernels with widgets enabled requires a widget manager capable of running independent of a notebook or console.**\n",
"\n",
"Currently this isn't supported by IpyWidgets. There is an outstanding PR [here](https://github.com/jupyter-widgets/ipywidgets/pull/3922) which enables this. \n",
"\n",
"#### Command\n",
"\n",
"The ipylab kernel can be started/re-started with the command 'Start ipylab kernel' (`Ctrl c` -> 'Start ipylab kernel').\n",
"\n",
"#### Configure\n",
"\n",
"An *autostart* ipylab kernel can be enabled in the configuration settings which will automatically start when Jupyterlab is started (intended to run locally). This provides a means for entry points to be loaded when Jupyterlab is launched.\n",
"\n",
"To change the configuration use the Jupyterlab settings editor: \n",
"\n",
"`Ctrl + ,` \n",
"\n",
"`Ipylab` \n",
"\n",
"`ipylab kernel enabled = True`.\n",
"\n",
"The next time Jupyterlab is started, a kerenel on the path 'ipylab' will be started."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand All @@ -280,7 +307,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.7"
"version": "3.10.15"
}
},
"nbformat": 4,
Expand Down
15 changes: 3 additions & 12 deletions ipylab/hookspecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,13 @@ def ready(obj: ipylab.Ipylab) -> None | Awaitable[None]:
@hookspec(historic=True)
async def autostart(app: ipylab.App) -> None | Awaitable[None]:
"""
Called inside each Python kernel when the frontend is 'ready'.
Use this with modules that define entry points.
To run in the Ipylab kernel exclusively use.
``` python
if not app.is_ipylab_kernel:
return
```
Called inside each Python kernel when the App is 'ready'.
Historic
--------
This plugin is historic so will activate when a plugin is registered after
the app is ready.
This plugin is historic so will activate when a plugin is registered if the
App is already ready.
"""


Expand Down
4 changes: 1 addition & 3 deletions ipylab/jupyterfrontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import ipywidgets
from IPython.core.getipython import get_ipython
from ipywidgets import TypedTuple, Widget, register
from traitlets import Bool, Container, Dict, Instance, Tuple, Unicode, UseEnum, observe
from traitlets import Container, Dict, Instance, Tuple, Unicode, UseEnum, observe

import ipylab
import ipylab.hookspecs
Expand Down Expand Up @@ -70,7 +70,6 @@ class App(Ipylab):
notification = Instance(NotificationManager, (), read_only=True)
console = Instance(ShellConnection, (), allow_none=True, read_only=True)

is_ipylab_kernel = Bool()
active_namespace = Unicode("", read_only=True, help="name of the current namespace")

namespace_names: Container[tuple[str, ...]] = Tuple(read_only=True).tag(sync=True)
Expand All @@ -89,7 +88,6 @@ def __init__(self, **kwgs):
return
if vpath := kwgs.pop("vpath", None):
self.set_trait("vpath", vpath)
self.set_trait("is_ipylab_kernel", vpath == "ipylab")
super().__init__(**kwgs)

def close(self):
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"dist/*.js",
"style/*.css",
"style/*.js",
"style/index.js"
"style/index.js",
"schema/*.json"
],
"homepage": "https://github.com/jtpio/ipylab",
"bugs": {
Expand Down Expand Up @@ -95,6 +96,7 @@
"@jupyterlab/mainmenu": "^4.2.5",
"@jupyterlab/observables": "^5.2.5",
"@jupyterlab/rendermime": "^4.2.5",
"@jupyterlab/settingregistry": "^4.2.5",
"@lumino/commands": "^2.3.1",
"@lumino/disposable": "^2.1.3",
"@lumino/widgets": "^2.5.0",
Expand Down Expand Up @@ -134,6 +136,7 @@
"jupyterlab": {
"extension": "lib/plugin",
"outputDir": "ipylab/labextension",
"schemaDir": "schema",
"sharedPackages": {
"@jupyter-widgets/base": {
"bundled": false,
Expand Down
14 changes: 14 additions & 0 deletions schema/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"title": "Ipylab",
"description": "Settings for ipylab.",
"properties": {
"autostart": {
"type": "boolean",
"title": "Ipylab kernel enabled",
"description": "Automatically start the ipylab kernel when Jupyterlab is started. This enables plugins to use the autostart feature. Note: This feature requires a special version of Jupyterlab widgets https://github.com/jupyter-widgets/ipywidgets/pull/3922",
"default": false
}
},
"additionalProperties": false,
"type": "object"
}
19 changes: 14 additions & 5 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import { ILauncher } from '@jupyterlab/launcher';
import { ILoggerRegistry } from '@jupyterlab/logconsole';
import { IMainMenu } from '@jupyterlab/mainmenu';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { ITranslator } from '@jupyterlab/translation';
import { MODULE_NAME, MODULE_VERSION } from './version';
import { IpylabModel, JupyterFrontEndModel, ShellModel } from './widget';
import { IpylabAutostart } from './widgets/autostart';
const EXTENSION_ID = 'ipylab:plugin';

const PLUGIN_ID = 'ipylab:settings';

/**
* The command IDs used by the plugin.
Expand All @@ -34,9 +36,9 @@ namespace CommandIDs {
* The default plugin.
*/
const extension: JupyterFrontEndPlugin<void> = {
id: EXTENSION_ID,
id: PLUGIN_ID,
autoStart: true,
requires: [IJupyterWidgetRegistry, IRenderMimeRegistry],
requires: [IJupyterWidgetRegistry, IRenderMimeRegistry, ISettingRegistry],
optional: [
ILayoutRestorer,
ICommandPalette,
Expand Down Expand Up @@ -65,6 +67,7 @@ async function activate(
app: JupyterFrontEnd,
registry: IJupyterWidgetRegistry,
rendermime: IRenderMimeRegistry,
settings: ISettingRegistry,
restorer: ILayoutRestorer,
palette: ICommandPalette,
labShell: ILabShell | null,
Expand Down Expand Up @@ -95,8 +98,8 @@ async function activate(
registry.registerWidget(widgetExports.IpylabModel.exports);
}
app.commands.addCommand(CommandIDs.checkStartKernel, {
label: 'Ipylab restart default kernel',
caption: 'Start or restart the default Ipylab Kernel.',
label: 'Start ipylab kernel',
caption: 'Start or restart the python kernel with path="ipylab".',
execute: () => IpylabAutostart.checkStart(true)
});
app.commands.addCommand(CommandIDs.restore, {
Expand Down Expand Up @@ -125,6 +128,12 @@ async function activate(
category: 'ipylab',
rank: 50
});
await settings.load(PLUGIN_ID);
const autostart = (await settings.get(PLUGIN_ID, 'autostart'))
.composite as boolean;
if (autostart) {
app.commands.execute(CommandIDs.checkStartKernel);
}

// Handle state restoration.
if (restorer) {
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4185,6 +4185,7 @@ __metadata:
"@jupyterlab/mainmenu": ^4.2.5
"@jupyterlab/observables": ^5.2.5
"@jupyterlab/rendermime": ^4.2.5
"@jupyterlab/settingregistry": ^4.2.5
"@lumino/commands": ^2.3.1
"@lumino/disposable": ^2.1.3
"@lumino/widgets": ^2.5.0
Expand Down

0 comments on commit 7cc0d86

Please sign in to comment.