Closed StefanBrand closed 3 years 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:
Thanks for filing an issue!
As far as JupyterLab is concerned, the kernel is separate from the frontend. This is by design; kernels don't need to be installed into virtual environments (or even conda environments), they just need to have a kernelspec installed into the right location (which you are doing manually).
Because of this separation, it is (in my opinion) unlikely that this will ever be changed to fulfil your use case.
Elaborating on this: the frontend and its extensions serve many kernels. If the kernels have different extensions, or conflicting extensions, it's not clear what should be loaded and how to handle conflicts. I agree in general this is unlikely to change in the architecture. Right now, the frontend environment is the one that determines what extensions are loaded.
In your specific case, it sounds like you are talking about ipywidgets extensions. ipywidgets itself has a mechanism for dealing with multiple versions of the same extension, so it may be possible to have something work in this specific case. However, I think it will require a decent amount of work to explore this to even come up with a proposal to discuss, for example:
If someone wants to explore putting together a precise proposal to discuss, let us know and we can help you get started. Probably a lot of this code would be implemented in ipywidgets as well.
Small note, the configuration parameter extra_labextensions_path
could be used to address this (not tested):
In your case, you could try:
jupyter lab --LabApp.extra_labextensions_path="/opt/conda/envs/jlab-test/share/jupyter/labextensions" --LabApp.extra_labextensions_path="/opt/conda/share/jupyter/labextensions/jupyter-leaflet/"
Note the need for setting two paths is due to that bug: https://github.com/ipython/traitlets/issues/668
@fcollonval Thank you for the command. It actually works for our use case :+1:
I'm now trying to employ the jupyter_lab_config.py
to set the extra_labextensions_path
. I see multiple configuration options that seem relevant:
## Extra paths to look for federated JupyterLab extensions
# Default: []
# c.LabServerApp.extra_labextensions_path = []
--
## The standard paths to look in for federated JupyterLab extensions
# Default: []
# c.LabServerApp.labextensions_path = []
--
## Extra paths to look for federated JupyterLab extensions
# Default: []
# c.LabApp.extra_labextensions_path = []
--
## The standard paths to look in for federated JupyterLab extensions
# Default: []
# c.LabApp.labextensions_path = []
I have some questions:
jupyter_lab_config.py
so that it is applied automatically? The home directory is not an option as it is being mounted into the container in our JupyterHub setup.LabApp
and LabServerApp
options, if any?labextensions_path
is []
by default?If you run jupyter --paths
in a terminal, you will be presented with a breakdown of the various locations that Jupyter uses for configuration and data.
You can place a configuration file in any of the config
locations and it will be picked up by the configuration system. If you have multiple configuration files, all will be considered, but higher priority configs will override lower priority ones.
LabApp
vs LabServerApp
The inheritance of the configuration objects is roughly
LabApp -> LabServerApp -> ExtensionApp -> JupyterApp
As to what jupyterlab_server
does, I'm actually not entirely sure. I think it provides a way to develop with a subset of JupyterLab, but one of the more knowledgeable developers might correct me here.
In general, a lot of the Jupyter stack is built upon traitlets
, which provides (amongst other things) the configuration system that we're discussing here. In the traitlets
library, class inheritance is used as a way to support configuration inheritance, which is why there are often relatively deep class hierarchies.
Given that LabApp
inherits from LabServerApp
, I would suggest setting the trait on LabServerApp
, so that child classes are also given the same configuration. I doubt that there are any other applications that inherit from LabServerApp
right now (at least, in your environment), but that's not important.
The comment in the configuration file concerning the default labextensions path is a little misleading. traitlets
has two mechanisms for providing default values
The latter mechanism allows a HasTraits
class (i.e. nearly all Python classes in the Jupyter codebase) to define a method that is called when the trait needs a default value.
This default doesn't show up in the configuration file comments, but it is used in the absence of a value. The labextensions_path
trait is defined in LabConfig
, which is inherited from by LabServerApp
(which inherits from multiple classes).
The default for this trait is set in this method.
Thank very much you for the comprehensive write-up! :heart:
We ended up copying jupyter_lab_config.py
to /etc/jupyter/
within the Dockerfile(s).
The jupyter_lab_config.py
would look like this (in the context of this issue and its OP):
# Configuration file for lab.
## Extra paths to look for federated JupyterLab extensions
c.LabServerApp.extra_labextensions_path = ["/opt/conda/envs/jlab-test/share/jupyter/labextensions"]
This is the actual commit that contains the change for our use case: https://github.com/eurodatacube/base-images/pull/4/commits/bbf9bf25e4ee1088eb17940338ca87404418bcdb
Thanks @StefanBrand for sharing your findings.
Description
I install a JupyterLab extension via mamba in an environment other than the one where JupyterLab is installed. Then I install this environment as a new kernel. The extensions installed in this environment cannot be used in the notebook's kernel.
Reproduce
docker run -p 8888:8888 jupyter/base-notebook jupyter lab
docker exec -it <container-id> bash
mamba install -c conda-forge jupyterlab_widgets
(base environment)conda create -n jlab-test --override-channels --strict-channel-priority -c conda-forge -c nodefaults ipyleaflet
conda activate jlab-test
(new environment)python -m ipykernel install --user --name "jlab-test-kernel" --display-name "JLab Test Kernel (Python)"
cp -r /opt/conda/envs/jlab-test/share/jupyter/labextensions/jupyter-leaflet/ /opt/conda/share/jupyter/labextensions/jupyter-leaflet/
Expected behavior
JupyterLab should detect lab extensions that are installed in the environment used by the notebook's kernel.
Context
Docker image:
docker pull jupyter/base-notebook:d75d70f3e661
Troubleshoot Output
Browser Output