-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Improving 4.x nbextensions #878
Comments
Another pain point, which I don't know if it could be addressed for the 4.x series is the fact that certain nbextensions depend on (a certain version) kernel-side code such as custom interactive widgets libraries. At the moment, it is impossible to have two kernels with two different versions of ipywidgets, or bqplot, installed because they will look for the JavaScript at the same location. Therefore, I think that the extension mechanism should acknowledge that there are two categories of extensions:
A proposal to solve this would be to have the kernelspec contain one more information: a uuid which would typically be generated when the kernelspec is installed. When running a notebook with this kernel, cc @jdfreder |
Here is a super rough draft of a PR that addresses the first pain point: #879 Some questions that this bring up:
There are some design decisions to make, but the good news is that it is simple code and logic to add this. Let's discuss more tomorrow. |
I don't agree with "quickly". I would prefer "thoroughly tested" with "with good documentation and example".
I would still like if you make extensions in python packages to be able to activate them per submodule:
Does that implicate you need to restart the server on loading extensions ? |
Extra note, if the packages are Python and have versions, we should be able to |
Re: @SylvainCorlay's point, also during that discussion, we proposed a kernel-specific nbextension path, which we never got around to implementing. I feel bad about that. I think we ended up proposing an nbextensions dir inside the kernelspec that kernel-specific extensions could go in. It seems a bit worrisome that we would officially bless Python packages as the temporary solution for 4.x nbextensions, and then turn 180º and say that it's all npm, and not Python packages as fast as we can. But if we want to make it more convenient, adding a flag for 'install js from a Python package':
seems like a better middle ground than breaking
I don't think so. What would these common nbextensions be?
I would do it the same way we do with the rest of config, where the more specific config has priority: user > env > system. I think that's the only thing that's missing from nbconfig for this to work.
During the nbextension discussion a year ago, it was concluded that we must not activate extensions as part of installing them - that install & activate must be two separate actions. Are we changing our minds on that? If someone wants to enable nbextensions via conda packages, the biggest hurdle is that all enabling currently resides in a single file, and conda packages should only write, not modify files. To support this, the only idea I have is a |
You can load extension from kernelspec directory using kernel.js, you just need to do relative requires.
What about "just" adding
For general frontend config, it's hard to merge JSON, though for list of extension, that might be easier. |
I don't think so, I think the setup.py list is to discover extensions. |
Just that I understand it correctly: This:
just means that developers of packages need to use npm, not that users of the package need to install npm in addition to python+python package manager? If not: I don't think it's good for the adoption of extensions if e.g. a julia user has to install a python environment to get a python package manager to install a jupyter notebook and then start installing node and npm to get extensions. Learning python (the language, the tools, the libs...) instead of using a preinstalled SPSS/STATA/... is already hard for students and researchers, so don't add on learning another packaging ecosystem to get notebook extensions. |
Maybe this belongs in a separate issue, but it seems like the right time to fix it along with these other problems. Installing server-side extensions suffers from a similar pain point about We found out the hard way that the JSON config takes precedence over the Python config in jupyter/dashboards#153. So if some server-side extensions ask users to add themselves to the .py config like I have no problem switching over to one or the other, but, which is the correct one? Or does something need to change so that both are supported and the lists of extensions are merged across the config types? |
It's probably correct for .py config files to have higher priority, since they are generally human-edited and more powerful, while .json config files should always and only be programmatically edited. .py files can be considered 'manual overrides'. In Python, it makes sense to do |
We already had a long discussion on which one between py an json should take precedence and decided on Json, as we want at some point to edit configuration only through UI. Having Json could perfectly have append also, as long as we decide that an append or prepend keys become a LazyAppend/LazyPrepend. We maybe should just warn more loudly if one file erase the settings of another, or put some time in looking at tools like redbaron to modify a Python config file in obvious case when a config option is not dynamic. |
The warning is definitely there and pretty loud on server start:
But I'll admit @jtyberg and I missed it for some time when debugging the issue I linked above. Even when we did see it, we only knew what to do because we're expert-amateurs in how the Jupyter config system works. I'd bet a typical notebook user wouldn't have an easy time rectifying the problem.
If you wanted to scope it down to prepending/appending sequence values instead of having to merge arbitrary config objects, that would still solve the extension problem specifically without growing into a general purpose "merge all the configs!" solution. |
What is the non-Continuum-camp feeling about the importance of being able to support "sandboxing" of extensions? For us (at Continuum) that means having a clean mechanism to be able to use conda environments to sandbox different sets of extensions and perhaps different versions of the same extension. From our work which has mixed both JS and Python code in the extensions conda packaging and conda environments have worked really well. I'm not clear on how this works in either a pure-Python-package or pure-NPM-package world. If there is a good and clean solution that doesn't include conda, great. But is there scope to discuss how conda can fill the need here to manage cross-language packaging, or has that ship already sailed? |
If redbaron would allow us to write and update Python config files programmatically, I would be pretty happy to drop json config files altogether, since they would no longer solve a problem. But that's a long-term idea. |
We can never rely on conda for this, so it's always going to be the case for us to use standard language packaging in multiple languages with some manual steps for stitching the two together, and then it can be 'simpler' for conda users, where packages can properly express cross-language dependencies. But whatever we come up with, it has to work outside conda. |
I would be ok to give it a try if you guys are ok with the proposal described earlier. |
How is everyone's availability for a video chat later today? I am free after 10 am PST. |
I'm free any time. |
11am PT, 2pm ET would be good for me or An our later is "possible" but sub-optimal. Friday AM-midday ET also WFM. Afternoon not so great. |
I probably can make it too. |
If I have to choose I would do it tomorrow, so we give another 24 hs to the things raised here (in other discussion and the PR itself), but if we are doing it today, I would prefer around/after 12pm PT. |
Is there a hackpad for this meeting? |
Friday would be better here too if possible. /cc @lbustelo |
I like Damian's idea of having the meeting tomorrow. That will give me I propose 10am PST on appear.in or bluejeans to allow our "further east" On Thu, Dec 17, 2015 at 9:27 AM, Peter Parente [email protected]
Brian E. Granger |
I will be unavailable for tomorrow, but would like to suggest the model used by git for chaining configuration files together: "If not set explicitly with --file, there are four files where git config will search for configuration options:
If no further options are given, all reading options will read all of these files that are available. The files are read in the order given above, with last value found taking precedence over values All writing options will per default write to the repository specific configuration file. Note that this You can override these rules either by command-line options or by environment variables. https://www.kernel.org/pub/software/scm/git/docs/git-config.html |
We can also push that a few days down the road, I'm not sure there is an urgent need to do that now, as 4.1 is not yet out. |
I'll try to make it, but have a company event. So we're going to use Let's also try to make developers happy, and ease them into the npm world (lotta bower out there right now). And let's try to make sysadmins happy. A surrogate for this is: how simply can I use binder to make a demo of my software? If you are doing a py/js job and I am 👍 allowing enabling extensions from all the places, as suggested... and would like to see this wrapped as a switch to As to the chaining: I almost would rather see the behavior like lodash's The version stuff is scary, and treading on what a real package manager should do, but if it's an identified need, we should go ahead and address it. So, with the those assumptions and:
...changing the command to make the positional argument optional, and accept $> jupyter nbextension install --prefix="${CONDA_ENV_PATH}" \
--py=nbgrader.nbextensions.assignment_list.static \
--enable
Installing and enabling nbextension to `{prefix}` from python package `nbgrader`...
... found package.json
... found name `nbgrader.assignment_list`
... found version `0.2.0`
... creating `[email protected]`
... `0.2.0` is newer than previous version in `nbgrader.assignment_list` (`0.1.0`)
... removing `nbgrader.assignment_list`
... copying `[email protected]` to `nbgrader.assignment_list`
... found main `main.js`
... `nbgrader.assignment_list/main` already enabled Speaking of "standard package management"... being able to communicate all of that at install time with setuptools #setup.py
setup(
#...
entry_points={
'jupyter.nbextension': [
'nbgrader.assignment_list = nbgrader.nbextensions.assignment_list.static',
],
'jupyter.server_extension': [
'nbgrader = nbgrader.nbextensions.assignment_list:load_jupyter_server_extension',
],
#...
) ...but there are probably complexities i am missing: environments (should be detectable), hub deployments, etc. I would really rather see the config files as a way to opt out of or customize what happens at the package manager level, rather than a necessary step for every single installed package. |
For reference, notes of the Dec. 18 meeting are in this hackpad. |
For the record, the proposal that this mornings meeting came to was:
|
Mmh, I thought we'd agreed to go to the |
I don't think we can do that in our current approach without breaking BW compat:
The only thing we could do is to add another separate layer that does the |
Well, if we can offer for 4.2 the I think for example apt has post-install scripts, but the policy is that they shouldn't modify the files that they installed, only do other things. So I'd like to see if we can go in the |
I agree that in the long run we want to have the conf.d type of approach as On Fri, Dec 18, 2015 at 5:17 PM, Fernando Perez [email protected]
Brian E. Granger |
I'm jumping into this discussion awfully late, coming over from @blink1073's great work in matplotlib/matplotlib#5754 to make interactive matplotlib plots a proper Jupyter widget. My concern there is that the matplotlib widget fits very squarely into @SylvainCorlay's second category of "kernel dependent extensions". The coupling between the Javascript and Python side there is very tight, and as that stuff has developed it's almost never been the case that a new feature could be added or a bug fixed without changing both sides of the coin. It will be very important to the matplotlib widgets that there are no opportunities for a version mismatch between the Python and Javascript sides of the communication. It looks on first blush that #879 will address that -- matplotlib can create a NotebookApp subclass and specify where its Javascript lives (which could continue to be installed along with matplotlib in Python with Python-packaging tools etc. as it is now). Is my impression correct? And will that remain in the longer term plans? |
Mike, we are still working out the details, but we expect the situation to With 4.x nbextensions, most projects like matplotlib will ship their JS in Starting with 5.x we will start to rely on npm for a lot of this, but will Cheers, Brian On Wed, Dec 30, 2015 at 9:40 AM, Michael Droettboom <
Brian E. Granger |
The versioning here is critical obviously, and should prevent version mismatch problems, but it won't prevent problems with stale packages etc. On a purely logical level, it seems to me that code that is tightly coupled, and that couldn't exist without both client and server sides, should be installed in an atomic way. The piece I'm probably missing is what an npm package/installation provides over libraries in the kernel providing/pointing to their own resources (for the case of "kernel-specific extensions" -- it makes sense for primarily client-side extensions). |
@mdboom Among other things, it prevents the duplicate loading of dependencies. Some client-side libs will not function correctly if they are loaded multiple times. It also makes it much simpler to specify those client-side dependencies. |
But how does any of that apply to @SylvainCorlay's second category above (kernel-dependent extensions)? |
Kernel dependent extensions can provide their own list of JS dependencies, which get unioned with the front-end dependencies of the rest of the app. |
If I'm understanding correctly, there appears to be no way to install the Javascript library atomically along with the kernel-side library under the proposed scheme. That is my fundamental objection with the design here. The strong versioning goes a long way, but not all the way, toward ameliorating some of the problems with that. The necessities/advantages of installing javascript content through npm seems to only apply to primarily client side extensions, and cut against the needs of kernel-dependent extensions, where atomic installation is important. All that said, I'll apologize again for coming late to this discussion. Certainly from matplotlib's perspective, this seems like a regression for both users (which have an additional manual installation step and the possibility for confusion and more toes to shoot oneself in) and developers (that must release packages on two different package frameworks, where before there was one), with little benefit in our particular use case. But obviously, we are but one case and will go with the flow if the benefits for other kinds of extensions outweigh the disadvantages for our kind. |
With nbextensions 4.x, there isn't a really reliable way of doing what you With the new npm based 5.x approach, code in the kernel or server will be On Wed, Jan 6, 2016 at 7:54 AM, Michael Droettboom <[email protected]
Brian E. Granger |
Jupyter kernels have some of the same issues, see jupyter/jupyter_core#61 You want to consider one solution fixing both nbextensions and kernels specs at the same time. |
@damianavila , @parente and maybe more: Just want to know is there any decisions made about the extensions (including both front-end and server-side) installation and management mechanism. As you may have known, there is a popular project ( Besides, I also think, for Jupyter Notebook end user (not developers), just using command line |
@haobibo there were several discussions about this and we have now a clear picture about the things needed and how to implemented. In fact, @ellisonbg started a PR for this and I am working in some other branches to complete that PR and add additional missing pieces (for instance, a way to enable/disable server based extensions ala nbextension). I should be easy to adapt the ipython-notebook-extensions into the new mechanism once that is finally merged. I would encourage you to try port some of the extension with the current proposed implementation (#879) to see if there is something we are missing. |
Damian, please coordinate with @jdfreder - he is also working on finishing On Thu, Feb 18, 2016 at 6:18 AM, Damián Avila [email protected]
Brian E. Granger |
@ellisonbg Nice, I will ping him. Thanks for letting me know 👍 |
Since #879 was merged, I think this should be closed. There are other interesting discussions here but the thread is long and they get easily missed. I would have further discussions in new threads. Thoughts? |
@fperez @damianavila @bollwyvl @sccolbert teoliphant @minrk @takluyver @ijstokes
I have been having a lot of on- and off-line discussion this week about the current state of nbextensions in 4.x. For a long time, we (at least this was my own logic) have hesitated to make any significant changes to how 4.x nbextensions are installed/loaded/packaged, because we know that much bigger changes are on the way in 5.0. After these recent conversations, I am convinced that we need to improve the existing 4.x nbextension architecture in the meantime. The current situation in 4.x is causing way to many problems for users and devs.
This goal of this issue is to 1) raise our community awareness that we need to do something about this and 2) come up with a concrete proposal for moving forward.
Current pain points of 4.x nbextensions
nbextensions can be installed in the following locations:
Config can be loaded from the following locations:
By default, installed extensions are not loaded, until activated. The only place extensions can be activated is in the users config directory (
~/.jupyter/nbconfig/notebook|notebook.json
):Pain Point #1: even though nbextensions and config can be installed in system, sys.prefix or user paths, the list of extensions to activate is only loaded from the user config. Thus, there is no way of activating nbextensions at the system or
sys.prefix
level.Point Point #2: There is no standard package format for nbextensions (other than a directory of stuff) and no standard way of copying an nbextension into place. Because of this, there are multiple, separate hacky ways of packaging and installing nbextensions.
nbgrader extension install
andnbgrader extensions activate
.install.py
script that installs and activate its extension.ls -n
to "install" his nbextensions here: https://github.com/minrk/ipython_extensionsProposal for addressing these pain points.
Here is the overall approach:
Here are the technical details of the proposal:
Pain Point 1
@takluyver has made an excellent point that the "nbconfig" frontend configuration system deliberately only loads from the users config (
~/.jupyter
) because these are really mean to only be "user preferences". I completely agree with this and others I have spoken to also concur. So we can't make that part of our app start to load system orsys.prefix
based config.I propose to start to load nbextension activation config from all config paths (system,
sys.prefix
and user) always, but do that instead by throwing that data into thepage.html
template itself, rather than loading later using the nbconfig web service. This would allow us to keep system data out of the user level app-preferences but still load config for nbextensions from all locations. This is not difficult to implement and is fully backwards compatible.Pain Point 2
This one is more difficult and my proposal will be more controversial. Today, in many cases, people are shipping JS code in Python packages. For 5.0 we are going to stop doing that and embrace npm as our package format and manager, but that would require breaking changes in 4.x, so is not on the table.
I propose, that for 4.2+ we embrace putting nbextensions into Python packages:
setup.py
that gives the package relative paths of those assets and 2) provide that same metadata in__init__.py
to enable runtime inspection. Something like this:jupyter nbextension
command line tool to work with python packages:jupyter nbextension install nbgrader
andjupyter nbextension enable nbgrader
. We could also include flags the target installation/config to the system, sys.prefix and user directories. This would again be fully backwards compatible.The text was updated successfully, but these errors were encountered: