Giter Club home page Giter Club logo

ipylab's Introduction

ipylab

Github Actions Status JupyterLite Binder Conda Version pypi npm

Control JupyterLab from Python notebooks.

The goal is to provide access to most of the JupyterLab environment from Python notebooks. For example:

  • Adding widgets to the main area DockPanel, left, right or top area
  • Build more advanced interfaces leveraging SplitPanel, Toolbar and other Lumino widgets
  • Launch arbitrary commands (new terminal, change theme, open file and so on)
  • Open a workspace with a specific layout
  • Listen to JupyterLab signals (notebook opened, console closed) and trigger Python callbacks

Try it online

Try it in your browser with Binder:

Binder

Or with JupyterLite:

JupyterLite

Examples

Add Jupyter Widgets to the JupyterLab interface

widgets-panels

Execute Commands

command-registry

Custom Python Commands and Command Palette

custom-commands

Build small applications

ipytree-example

Compatibility with RetroLab

A subset of the features can be used in RetroLab:

retrolab-example

Installation

You can install using pip:

pip install ipylab

Or with mamba / conda:

mamba install -c conda-forge ipylab

Running the examples locally

To try out the examples locally, the recommended way is to create a new environment with the dependencies:

# create a new conda environment
conda create -n ipylab-examples -c conda-forge jupyterlab ipylab ipytree bqplot ipywidgets numpy
conda activate ipylab-examples

# start JupyterLab
jupyter lab

Under the hood

ipylab can be seen as a proxy from Python to JupyterLab over Jupyter Widgets:

ipylab-diagram

Development

# create a new conda environment
mamba create -n ipylab -c conda-forge jupyter-packaging nodejs python -y

# activate the environment
conda activate ipylab

# install the Python package
python -m pip install -e ".[dev]"

# link the extension files
jupyter labextension develop . --overwrite

# compile the extension
jlpm && jlpm run build

Related projects

There are a couple of projects that also enable interacting with the JupyterLab environment from Python notebooks:

ipylab's People

Contributors

bollwyvl avatar dependabot[bot] avatar github-actions[bot] avatar jtpio avatar readthedocs-assistant avatar tk-21st avatar vidartf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ipylab's Issues

Ipylab returns empty list of commands. Console shows error Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module

I use JupyterLab 3.2.3 and installed ipylab 0.5.2 using pip.

Following notebook code


from ipylab import JupyterFrontEnd

app = JupyterFrontEnd()
commands = app.commands.list_commands()
commands

returns an empty array.

The Chrome dev tools console contains the error

Module ipylab, semver range ^0.5.2 is not registered as a widget module

Full output:

react_devtools_backend.js:4045 Could not instantiate widget
overrideMethod @ react_devtools_backend.js:4045
(anonymous) @ manager-base.js:274
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
rejected @ manager-base.js:18
Promise.then (async)
step @ manager-base.js:19
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Error: Could not create a model.
    at promiseRejection (utils.js:119)
    at async _handleCommOpen (523.fa256ee012d38a89b65a.js:1)
    at async KernelConnection._handleCommOpen (default.js:1038)
    at async KernelConnection._handleMessage (default.js:1206)
overrideMethod @ react_devtools_backend.js:4045
promiseRejection @ utils.js:119
Promise.catch (async)
ManagerBase.handle_comm_open @ manager-base.js:150
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Exception opening new comm
overrideMethod @ react_devtools_backend.js:4045
_handleCommOpen @ default.js:1044
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Could not instantiate widget
overrideMethod @ react_devtools_backend.js:4045
(anonymous) @ manager-base.js:274
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
rejected @ manager-base.js:18
Promise.then (async)
step @ manager-base.js:19
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Error: Could not create a model.
    at promiseRejection (utils.js:119)
    at async _handleCommOpen (523.fa256ee012d38a89b65a.js:1)
    at async KernelConnection._handleCommOpen (default.js:1038)
    at async KernelConnection._handleMessage (default.js:1206)
overrideMethod @ react_devtools_backend.js:4045
promiseRejection @ utils.js:119
Promise.catch (async)
ManagerBase.handle_comm_open @ manager-base.js:150
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Exception opening new comm
overrideMethod @ react_devtools_backend.js:4045
_handleCommOpen @ default.js:1044
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Could not instantiate widget
overrideMethod @ react_devtools_backend.js:4045
(anonymous) @ manager-base.js:274
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
rejected @ manager-base.js:18
Promise.then (async)
step @ manager-base.js:19
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Error: Could not create a model.
    at promiseRejection (utils.js:119)
    at async _handleCommOpen (523.fa256ee012d38a89b65a.js:1)
    at async KernelConnection._handleCommOpen (default.js:1038)
    at async KernelConnection._handleMessage (default.js:1206)
overrideMethod @ react_devtools_backend.js:4045
promiseRejection @ utils.js:119
Promise.catch (async)
ManagerBase.handle_comm_open @ manager-base.js:150
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Exception opening new comm
overrideMethod @ react_devtools_backend.js:4045
_handleCommOpen @ default.js:1044
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Could not instantiate widget
overrideMethod @ react_devtools_backend.js:4045
(anonymous) @ manager-base.js:274
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
rejected @ manager-base.js:18
Promise.then (async)
step @ manager-base.js:19
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Error: Could not create a model.
    at promiseRejection (utils.js:119)
    at async _handleCommOpen (523.fa256ee012d38a89b65a.js:1)
    at async KernelConnection._handleCommOpen (default.js:1038)
    at async KernelConnection._handleMessage (default.js:1206)
overrideMethod @ react_devtools_backend.js:4045
promiseRejection @ utils.js:119
Promise.catch (async)
ManagerBase.handle_comm_open @ manager-base.js:150
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
react_devtools_backend.js:4045 Exception opening new comm
overrideMethod @ react_devtools_backend.js:4045
_handleCommOpen @ default.js:1044
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
ManagerBase.register_model @ manager-base.js:209
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
ManagerBase.register_model @ manager-base.js:209
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
ManagerBase.register_model @ manager-base.js:209
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)
loadClass @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:264
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
Promise.then (async)
ManagerBase.register_model @ manager-base.js:209
register_model @ 523.fa256ee012d38a89b65a.js:1
(anonymous) @ manager-base.js:249
step @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
__awaiter @ manager-base.js:16
ManagerBase.new_model @ manager-base.js:233
ManagerBase.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1038
async function (async)
_handleCommOpen @ default.js:1037
_handleMessage @ default.js:1206
async function (async)
_handleMessage @ default.js:1168
(anonymous) @ default.js:110
Promise.then (async)
KernelConnection._onWSMessage @ default.js:107
523.fa256ee012d38a89b65a.js:1 Uncaught (in promise) Error: Module ipylab, semver range ^0.5.2 is not registered as a widget module
    at x.loadClass (523.fa256ee012d38a89b65a.js:1)
    at x.<anonymous> (manager-base.js:264)
    at step (manager-base.js:45)
    at Object.next (manager-base.js:26)
    at manager-base.js:20
    at new Promise (<anonymous>)
    at __awaiter (manager-base.js:16)
    at x.ManagerBase._make_model (manager-base.js:258)
    at x.<anonymous> (manager-base.js:247)
    at step (manager-base.js:45)

Any support for "compound panels"?

I think it's not existing yet, but it would be very nice to have some workspace-like support for panels. This would allow to create panel sets with some predefined layout as in the attached example from the start. At the moment I can create these only as a sequence filling up (and cluttering) the space, and I have to drag and drop them heavily to achieve some desired layout. I have used HBox/VBox hierachies before, but this is just so much more dynamic. ;)

codeview

Execute notebook programatically has different behavior from running it on a Jupyter Notebook UI

Context

I am creating a Jupyter magic that will create multiple cells. When I run it manually (i.e. Ctrl + Enter), I can create new cells successfully. When I run it programatically, the code get run without error but the cells are not created.

A gif to show how this magic should behave.
image

See: kedro-org/kedro#3510

I am trying to create automated test for this feature, thus it is important to execute this in an automated fashion. I wonder how this is tested

import nbformat
from nbconvert.preprocessors import ExecutePreprocessor

ep = ExecutePreprocessor(timeout=600, kernel_name="python3")
print(f"Executing Notebook {notebook_filename}")
try:
    # Execute the notebook from the same directory
    ep.preprocess(nb,
                  {'metadata': {'path': Path(notebook_filename).parent.resolve()}})

I wonder if you have any idea why it doesn't work, or you can give me some pointers to some relevant tests in this repository. Thank you in advance!

Allow `ipylab` to consume arbitrary Token without rebuilding

Related to #44 and #43.

General Description

ipylab interfaces with JLab by exposing requires Tokens as follows:

const extension: JupyterFrontEndPlugin<void> = {
  id: EXTENSION_ID,
  autoStart: true,
  requires: [IJupyterWidgetRegistry, ILabShell],  // <= Token Consumed
  optional: [ICommandPalette],  // <= Optional Token Consumed
  activate: (
    app: JupyterFrontEnd,
    registry: IJupyterWidgetRegistry,
    shell: ILabShell,
    palette: ICommandPalette
  ): void => {
    widgetExports.JupyterFrontEndModel.app = app;
    widgetExports.ShellModel.shell = shell;
    widgetExports.CommandRegistryModel.commands = app.commands; 
    widgetExports.CommandPaletteModel.palette = palette;
...

Every time an update is introduced that exposes additional tokens to ipylab, the plugin will be rebuilt.

Specific use case for FocusTracker discussed in #44

Following up on the original discussion around providing a mechanism for ipylab to be aware of the sessionContext associated with the current widget from which ipylab is invoked. The current approach is to expose the entire global FocusTracker to user, but the more disciplined approach will be to use INotebookTracker and IConsoleTracker instead. However, if there is a custom extension that needs to track the current sessionContext that is not tracked in either tokens (since this custom extension would not be notebook or console), the user could provide custom tracker token but that will require rebuilding ipylab.

Right, but it could indeed be useful! Maybe we could track that in a separate issue?

But I was also considering the super edge-case where the user wants to use, say, CodeCell in a custom extension not tracked by INotebookTracker or IConsoleTracker, and hope to inject some code there with ipylab, then this won't work.

The custom extension could provide its own track (ICustomTracker), and then ipylab could require this token as optional in the activate function. Although that would mean making a change to ipylab everytime we need to support a new extension. So yes a more general focus tracker could probably scale better.

Originally posted by @jtpio in #44

Possible Solutions

  1. Use global FocusTracker as it is and work from there. Or maybe expose app to every widget and do some black magic within each widget. ๐Ÿ”จ
  2. Ask user to define custom tracker and rebuild every time.
  3. Somehow allow user to specify arbitrary token as a string? wolfv had a solution to go through the token maps in application in browser (https://github.com/wolfv/jupyterlab-dynext/blob/df14dd245b0b487eb9ba2bec185964d266ad7b85/src/index.ts#L20-L32).

List of JupyterLab commands

The command registry has a listCommands() method: app.commands.listCommands().

This should be exposed from Python so it's easier to know what commands are available.

docmanager:open called from ipylab takes absolute paths

The docmanager:open command, at least when called from ipylab, seems to interpret paths as absolute
from the lab root.

Option 1: this is a feature (possibly consistent with other pieces of JupyterLab); documentation mentionning the fact and suggesting how to open files referred to by a relative path from the current notebook would be helpful.

Option 2: it's a bug :-)

Thanks in advance!

Handle restore

At the moment the panels are not restored on page refresh.

not-restored

We could transparently use the LayoutRestorer to transparently restore these panels that are added to the shell.

Removing panel

I looked extensively through the api, but it's not clear to me how to remove a panel after adding and losing the object variable in python.

This seems to work:

app = JupyterFrontEnd()
app.shell.add(panel, 'left', {'rank': 10000})
..
  panel.close()
  del panel

But what happens if you lose the panel object (eg: accidentally create a new and clobber it). Is there a way to enumerate through the app and get the panel and then clean it up?

example not working

@jtpio pretty nice project!

from ipylab import JupyterFrontEnd, Panel, SplitPanel
from ipywidgets import IntSlider, Layout

app = JupyterFrontEnd()
panel = Panel()
slider = IntSlider()
panel.children = [slider]
app.shell.add(panel, 'main', { 'mode': 'split-right' })

gives in the js console:

Uncaught (in promise) TypeError: Cannot set properties of undefined (setting 'id')
    at ShellModel._add (shell.js:44:1)
    at async ShellModel._onMessage (shell.js:89:1)

Automate releases

It would be interesting to experiment with automated releases to npm and pypi when a new release tag is pushed, using GitHub Actions.

Automate versioning

#20 added a workflow to automate the release to PyPI and npm. But the versions still had to manually be bumped before.

It would be great if instead there was a script that would bump the versions using the tag of the release, commit the changes and push to master, before publishing the packages.

get a list of active windows/panels

ipylab is very cool, have been experimenting with it a bit.

I'm trying to get a list of active windows (PhosphorJS panels? Not sure of the right jargon) from the jupyterlab framework, but I don't see how it's done. Looks like the app.shell.widgets dictionary contains a number of widgets that are related to the active panels, but I don't understand the structure.

Ideally I would like to be able to write in Python using ipywidgets a widget that I could place in the left panel (as you demonstrate in the widgets.ipynb example), and which could e.g. open and close windows in the main panel (and keep track of them, interact with them). Sort of how the standard javascript based file explorer in jupyterlab behaves. Is something like that at all possible with the current ipylab framework or should I look elsewhere?

Exposing current `sessionContext` to ipylab

General Description

Add API to ipylab where the user can gather information about the current or all sessionContext currently in the JLab workspace (potentially exposing sessionManager).

Usage

ipylab currently supports command execution such as

from ipylab import JupyterFrontEnd
app = JupyterFrontEnd()
opts = {}
# create new console with no options
app.commands.execute('console:create', opts)

For JupyterLab extensions that interacts with kernel sessions via sessionContext, we should be able to have access to the current session in the notebook/console via ipylab. For example

from ipylab import JupyterFrontEnd
from ipylab import SessionContext
app = JupyterFrontEnd()
opts = SessionContext.currentSession()
# this will create a console with the current session.
# mimicking behavior of `notebook:create-console` command
app.commands.execute('console:create', opts)

Initialise widgets without going through a notebook

Also a question rather than an issue.

Let's say I want to have the widgets that I defined to be created without having to run a notebook first, is there a simple way to achieve this?

Right now I am just quickly executing and closing a notebook when the jupyter session starts.

I believe there should be a way to rather go through a python script but I am noit sure how the notebook communicates with the jupyterlab APIs

Does this make sense?

Previous cell execution

Is it possible to run the previous notebook cell with ipylab?

I have a notebook with a cell with a button widget that runs unittests on the code in the cell above.

So it would be great to programmatically run the latest version of the code I want to test (which is in the previous cell) before.

Regards

Exposing Jupyter(Lab) Contents

Elevator Pitch

Offer access to Jupyter Contents, as viewed by a JupyterFrontend, as a set of widget subclasses.

Some points worth considering for wrapping

  • ContentsManager
  • IDrive
  • ContentsModel
  • FileBrowser
  • DocumentManager

Motivation

The long-standing issue of "what is a file" according to Jupyter Kernels, a Server, and Clients creates a number of difficult-to-resolve situations. While a widget-based solution may not be the optimal, general-purpose, long-term solution, it's easier to imagine and demonstrate on this repo than probably anyplace else.

Design Ideas

A low-level sketch:

app = JupyterFrontEnd()
contents: ContentsManager = app.service_manager.contents
root: ContentsModel = contents.get("/")

for child in root.contents:
    print(child.contents)

untitled = ContentsModel(type="text", content="# hello world", path="untitled.md")

contents.save(untitled)

Making all of the above feel widget-like (almost all of the above are several layers deep of async) and still be efficient would of course be a challenge. But there are probably worse things than introducing some async methods which then get cached as trait members.

Sadly, a lot of the methods are rather private, such as enumerating _additionalDrives and even finding _defaultDrive.

The IDrive interface, used in things like GitHub and IRODS, could make this very interesting indeed, as well as a wrapping such a drive in a FileBrowser which could be attached to a Panel.

This would give someone the tools to rapidly prototype browsing just about anything by answering, at the very simplest, only the get method.

Going straight to the sharedModel and all its... ahem.. features... might be a bridge too far.

ipylab and voila preview clash?

I can't seem to get voila jupyterlab preview and ipylab working in the same ipynb. Reduced to the essentials, the problem is shown by the following code:

import ipylab
import ipywidgets as w
panel = ipylab.Panel() # uncomment this line, or else the button will not render in jupyterlab voila preview
button = w.Button(description="OK")
display(button)

If you render the above in a voila preview, the OK button is not shown. If you comment out the line with the ipylab Panel, the button renders correctly in the voila preview.

Enabled extensions on my setup:

  • @jupyter-voila/jupyterlab-preview v0.1.3 enabled OK
  • @jupyter-widgets/jupyterlab-manager v1.1.0 enabled OK
  • ipylab v0.1.3 enabled OK
  • jupyterlab_iframe v0.2.1 enabled OK
  • voila v0.1.0 enabled OK

Running JupyterLab 1.2.7 (I have not yet gotten voila to work with JupyterLab 2.0, keep getting incorrect dependencies when I try to install the voila preview extension).

I don't know if the problem is with ipylab or voila, but I'm posting it here since I've noticed you've worked on both projects.

change kernel

I was looking for the functionality to change the running kernel from code and came across this.
https://discourse.jupyter.org/t/is-there-magic-to-restart-kernel-change-kernel/10763/2

It was suggested that a github issue could be made (and as far as i can see it never happened) for some additional features "adding an argument that allows to skip the confirmation for kernelmenu:restart and pre-specify kernel for notebook:change-kernel"

Im most interested in being able to pre-specify the kernel for notebook:change-kernel.

I had a poke around the source to see if i could work out what to do but didn't make any progress unfortunately.

Support for awaitables

Ideally we would be able to write code that looks like this:

res = await app.commands.execute('docmanager:new-untitled')
await app.commands.execute('docmanager:open', { 'path': res.path })

So it stays very similar to how we would do things on the TypeScript side.

Convert notebook with ipylab

Hi,

Usually I am using nbconvert to convert a notebook to html. Today I was searching for a way to do it via code from inside the notebook. When searching for it I found ipylab and the command "notebook:export-to-format" but I don't understand how to use it.

From the notebook I did

from ipylab import JupyterFrontEnd
app = JupyterFrontEnd()
app.commands.execute("docmanager:save")
app.commands.execute("notebook:export-to-format")

I get no error messages but also no file.

What I eventually would like to do is something corresponding to
nbconvert --to html --template classic --no-input notebook

Do you have any idea on how to do it?

Disable "save widget state automatically" via notebook command?

I'm looking for a snippet similar to

from ipylab import JupyterFrontEnd
app = JupyterFrontEnd()
app.commands.execute('notebook:insert-cell-below')

but instead of insert-cell-below, I would like to disable "save widget state automatically".
That way, I could enable "save widget state automatically" by default for all my notebooks, and exclude some notebooks where I don't want to save widget states.
Here's a list of notebook commands that I found, but I don't know which one is right for disabling saving the widget state
https://github.com/jupyterlab/jupyterlab/blob/49f6ec28b738243a53a947d544bebafafcbd4a73/packages/notebook-extension/src/index.ts#L136-L325

Looking forward to suggestions and ideas!

Expose the settings

So some settings could be persisted:

image

For example whether widgets and panels should be restored automatically.

Better support for left and right area

At the moment adding to the left and right area is quite minimal.

css

There should be nice defaults (closable, title, CSS), or this should be easily configurable from Python.

Complete rest of Title API

Elevator Pitch

Add the rest of the (reasonable) Title (getter/)setters.

Motivation

When using a custom icon, it's also nice to have the tooltip/aria text info.

The other accessors are of perhaps less interest, but while changing the API, might as well be exhaustive.

Design Considerations

dataset would be a little weird, but still useful for some reason... perhaps for hiding stuff not created by a custom app, though presumably this could be done with class_name as well... need to see how they work together.

Add more examples

There could be more examples, such as more advanced widgets, for example with bqplot:

bqplot-example

app.commands.execute("notebook:run-all-below") does not work if cell collapsed

If I use this code and have the cell collapsed, it doesn't work. Only if the cell code is visible.

import asyncio
app = JupyterFrontEnd()
out = Output()

async def init():
    await app.ready()
    app.commands.execute("notebook:move-cursor-down")
    app.commands.execute("notebook:run-all-below")
    out.append_stdout(cmds)


def on_button_clicked(b):
    global channel_name
    channel_name = cn.value
    cn.close()
    button.close()    
    asyncio.create_task(init())
    out
    
# start check
button.on_click(on_button_clicked)

Add commands and expose the palette

At the moment it's possible to execute commands.

It would be interesting to see if it makes sense to also be able to add commands to the command registry, and also to the palette.

Executing a user defined command would trigger an event back to the kernel where the command would be executed.

Purpose and Use Cases for ipylab

It's unclear to me what the purpose of this library is. I'm not sure what would be the right use cases. Is it supposed to be an alternative to writing a Jupyter Frontend plugin? How is it better or worse than writing a plugin? Is it just a proof of concept? The motivation for my question(s) is about making the best use of it.

I believe an answer to this question could be part of the description of the library.

Furthermore, what is the expected or planned future for the library? It seems that is is missing some pieces for it to be appropriate for a production environment, like a Jupyter Server extension that loads a Python kernel, or a way to remove widgets when a kernel is stopped, just to mention a few that come to mind.

Thanks!

Support more JupyterLab distributions

It would be interesting to see if ipylab can be used in a custom JupyterLab build (or just a frontend that reuses lab components), to create standalone a UI without all the other extra lab extensions (menu, left and right area...).

This would probably require making the ILabShell dependency optional:

requires: [IJupyterWidgetRegistry, ILabShell],

Args for commands?

Thank you for providing this module. I'd been looking for a way to open the Jupyter console from python.

Looking through your example notebook I can see you are using args for the commands such as:

app.commands.execute('console:create', {
    'insertMode': 'split-right',
    'kernelPreference': {
        'shutdownOnClose': True,
    }
})

. Would it be possible to provide some details on what args can be passed to each of the commands?

The best ref I found sofar was here: https://jupyterlab.readthedocs.io/en/latest/user/commands.html#commands-list
however it only lists the commands without arguments.

Panel and SplitPanel do not always render initially

The example is running from recent WinPython distribution (Jupyterlab 4.0.4), but the same issue happens for me using a conda dev environment running on WSL. The JupyterLite example works correctly, but everywhere else I've tried this has similar behaviour to that shown below.

Running through widgets.ipynb from the examples folder code. The panels appear, but the contents do not show up.

image

Dragging the panels about can make the contents appear.

image

Lab ready event

There are a few things that first require a roundtrip to the frontend so they can become usable in the kernel.

For example retrieving the list of commands: #7

There could be an app_ready or lab_ready event, and users can set their own callbacks using a CallbackDispatcher.

Or using the await keyword, something like this:

app = JupyterFrontEnd()
await app.ready()
app.commands.list_commands()

Open new kernel communication from ipylab

Trying to use ipylab without a notebook.

We have an extension for JupyterLab that creates a new kernel connection and executes the following code in the kernel:

from ipylab import JupyterFrontEnd, Panel, SplitPanel
from ipywidgets import IntSlider, Layout
app = JupyterFrontEnd()
panel = Panel()
slider = IntSlider()
panel.children = [slider]
app.shell.add(panel, 'main', { 'mode': 'split-right' })

The issue is that with the response we get the exception "Exception opening new comm" that comes from _handelCommOpen() when calls to loadObject.

Screenshot 2020-07-29 at 22 39 53

Screenshot 2020-07-29 at 22 42 42

@jtpio
@wolfv

app.commands.list_commands() returns empty array

app.commands.list_commands() returns empty array. However, app.commands.execute('docmanager:save') does save the document.

Jupyter Lab Version 3.2.2 on Python 3.9.9.

from ipylab import JupyterFrontEnd

app = JupyterFrontEnd()
# app.commands.execute('docmanager:save')
app.commands.list_commands()

[]

Integration with JupyterLite?

I think it would be nice to run ipylab in JupyterLite, so I gave it a try, although I see no claim that ipylab should support JupyterLite. So while ipylab does install fine, it does not appear to have any effect on the (JupyterLab) interface, like in this code:

import micropip
await micropip.install('ipylab')
from ipylab import JupyterFrontEnd

app = JupyterFrontEnd()
app.commands.execute('apputils:change-theme', {'theme': 'JupyterLab Dark'})

When using widgets in a panel like this (from a standard example snippet) I get a "Loding widget..." message:

import micropip
await micropip.install("ipylab")
await micropip.install("ipywidgets")
from ipylab import Panel
from ipywidgets import IntSlider

panel = Panel()
slider = IntSlider()
panel.children = [slider]
panel

I'd appreciate any statement if this should work and I'm doing something wrong, or if JupyterLite support is considered enough of a nice to have feature in the future?

Using in Production Code

This is not an issue. I just want to know that how stable is this API to use as a dependency in other python packages? I want to use it in ipyslides for creating useful layouts based on the device resolution.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.