Skip to content
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

New nbextensions installation API #879

Merged
merged 90 commits into from
Mar 26, 2016
Merged

Conversation

ellisonbg
Copy link
Contributor

This is working draft exploring the feasibility of the first part of the work described in #878

So far this does:

  • Adds an nbextensions config traitlet to the main NotebookApp.
  • Adds logic to the templates and handlers to json serialize that list, put it into the template and get it into a location that main.js could access it.

@@ -187,6 +187,7 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
},
version_hash=version_hash,
ignore_minified_js=ipython_app.ignore_minified_js,
nbextensions=ipython_app.nbextensions,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be smarter if we want this to be updated while the server runs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I want to keep it simple. I think that allowing updating this while the server runs is out of scope. But, there is nothing to prevent someone else from just calling utils.load_extensions() in the frontend at any time to load an extension. We could even provide an IPython magic that does that, or another extension could be written to handle runtime loading.

@Carreau Carreau added this to the 4.2 milestone Dec 17, 2015
@@ -645,6 +647,12 @@ def nbextensions_path(self):
path.append(os.path.join(get_ipython_dir(), 'nbextensions'))
return path

nbextensions_tree = Dict(config=True,
help="A list of nbextensions to enable for the tree/dashboard page.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/list/dict(key:bool)/

@ellisonbg
Copy link
Contributor Author

OK, the current state of this code allows you to install the following nbextensions:

https://github.com/jdfreder/jupyter-tree-filter
https://github.com/jdfreder/jupyter-lightsaber
https://github.com/jdfreder/jupyter-lightsaber-yoda

Using the following sequence of commands (notebook doesn't have to be restarted):

pip install jupyter-tree-filter
jupyter nbextension install --python jupyter-tree-filter
jupyter nbextension enable --python jupyter-tree-filter

I am going to work on cleaning it all up, but review can start.

@parente
Copy link
Member

parente commented Dec 19, 2015

My diff comment got clobbered in an update, so reposting as a comment to make sure it's not lost: there's a third view, the edit view, that has a config file and supports extensions, just like notebook and tree. I think that view should be supported in the new approach as well. (We're using it in jupyter-incubator/contentmanagement for example).

It means adding one more if/else case in a few spots.

"""Config Manager used for storing notebook frontend config"""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref for #893 discussion

@captainsafia
Copy link
Member

Hopefully, I'm not late to any reviews but I just pulled this PR locally and tested out what I could. I noticed that that prior to rewrite --python is used to reference an extension to be installed from a Python package. I actually this is much more usable and friendly than the --py currently in place. Some code related comments are in-line as notes.

Edit: Also not sure if now would be the right time to start writing some documentation on this, if so, let me know I can get started and we can build documentation/code in parallel.

Edit 2: I have some questions/comments about logging but will wait until you are done with that part of the PR.

@@ -292,7 +292,7 @@ def check_origin(self, origin_to_satisfy_tornado=""):
#---------------------------------------------------------------
# template rendering
#---------------------------------------------------------------

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OCD kicking in, but might want to remove this whitespace.


def _read_config_data(user=False, sys_prefix=False):
config_dir = _get_config_dir(user=user, sys_prefix=sys_prefix)
config_file = os.path.join(config_dir, 'jupyter_notebook_config.json')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice if jupyter_notebook_config.json was exposed as a constant someplace: but hopefully nobody should ever have to deal with this again!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConfigManager can be used to do this reading/writing, without any open/json/ensure_dir calls:

config_man = BaseJSONConfigManager(config_dir)
config = config_man.get('jupyter_notebook_config')
# < update config >
config_man.update('jupyter_notebook_config', new_config)

prefix=self.prefix,
destination=self.destination,
nbextensions_dir=self.nbextensions_dir,
if self.python:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these duplicate blocks can be removed by making the function a variable:

install = install_nbextension_python if self.python else install_nbextension

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@parente
Copy link
Member

parente commented Feb 9, 2016

@ellisonbg I worked on installing this branch and trying to migrate the https://github.com/jupyter-incubator/contentmanagement extension to using this to install/enable instead of its own custom CLI (https://github.com/jupyter-incubator/contentmanagement/blob/master/jupyter_cms/extensionapp.py).

Here's what I found:

  1. jupyter nbextension install --py jupyter_cms works as expected as written and with various additional params (--symlink, --user)
  2. jupyter nbextension enable --py jupyter_cms missed the editor section I specified in _jupyter_nbextension_path
  3. As expected, there was no command provided in the new jupyter nbextension * --py implementation for enabling server-side extensions which jupyter_cms has
  4. When I try to use the existing CLI that works in 4.1, the jupyter cms activate command raises the exception below. So overriding the CLI for install/activate is not backward compatible at the moment.
[ExtensionActivateApp] Activating jupyter_cms notebook server extensions
Traceback (most recent call last):
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/bin/jupyter-cms", line 11, in <module>
    sys.exit(main())
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/jupyter_cms/extensionapp.py", line 226, in main
    ExtensionApp.launch_instance()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/traitlets/config/application.py", line 589, in launch_instance
    app.start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/jupyter_cms/extensionapp.py", line 223, in start
    super(ExtensionApp, self).start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/traitlets/config/application.py", line 276, in start
    return self.subapp.start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/jupyter_cms/extensionapp.py", line 109, in start
    self.enable_server_extension('jupyter_cms')
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/jupyter_cms/extensionapp.py", line 92, in enable_server_extension
    server_cm.update('jupyter_notebook_config', cfg)
  File "/Users/parente/projects/jupyter/ellisonbg/notebook/services/config/manager.py", line 33, in update
    self._write_config_manager.update(section_name, new_data)
AttributeError: 'ConfigManager' object has no attribute '_write_config_manager'

To double-check, I tried nbgrader's CLI. It, too, raises an error because the base class nbextension implementation has changed.

[ExtensionActivateApp] Activating create_assignment nbextension
Traceback (most recent call last):
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/bin/nbgrader", line 11, in <module>
    sys.exit(main())
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/nbgrader/apps/nbgraderapp.py", line 232, in main
    NbGraderApp.launch_instance()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/jupyter_core/application.py", line 267, in launch_instance
    return super(JupyterApp, cls).launch_instance(argv=argv, **kwargs)
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/traitlets/config/application.py", line 589, in launch_instance
    app.start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/nbgrader/apps/nbgraderapp.py", line 225, in start
    super(NbGraderApp, self).start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/jupyter_core/application.py", line 256, in start
    self.subapp.start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/nbgrader/apps/extensionapp.py", line 207, in start
    super(ExtensionApp, self).start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/traitlets/config/application.py", line 276, in start
    return self.subapp.start()
  File "/Users/parente/miniconda3/envs/notebook-4.2-nbexts/lib/python3.5/site-packages/nbgrader/apps/extensionapp.py", line 99, in start
    self.enable_nbextension("create_assignment/main")
AttributeError: 'ExtensionActivateApp' object has no attribute 'enable_nbextension'

Current takeaways:

  • If server-side extensions are not going to also be supported, then I still have to provide a custom CLI for activating them.
  • If there's no way for this change to go in without breaking the current nbextension CLI overrides used in nbgrader, jupyter-incubator/declarativewidgets, jupyter-incubator/dashboards, etc.,
    then I'll have to do some version detection to support install/activate on both <4.2 and >4.1.

Small update: Here's the metadata I put into jupyter_cms to test this.

def _jupyter_nbextension_paths():
    return [{
        'section': 'notebook',
        'src': 'nbextension',
        'dest': 'jupyter_cms',
        'require': 'jupyter_cms/notebook/main'
    },
    {
        'section': 'tree',
        'src': 'nbextension',
        'dest': 'jupyter_cms',
        'require': 'jupyter_cms/dashboard/main'
    },
   # below does not get picked up
    {
        'section': 'edit',
        'src': 'nbextension',
        'dest': 'jupyter_cms',
        'require': 'jupyter_cms/editor/main'
    }]

@damianavila
Copy link
Member

If server-side extensions are not going to also be supported, then I still have to provide a custom CLI for activating them.

This is really important... otherwise people working with nbextension/serverextension complex extensions should implement an additional CLI as @parente mentioned or alternative a custom configmanager to write config outside the user space (since the current config manager implementation on this PR only writes to the user space)

What about adding the server extension info at the python metadata level? I mean adding a field to load that info if it is provided... In that way we should only modify enable_nbextension_python to be able to write the server-related config in NotebookApp.server_extensions

I mean:

def _jupyter_nbextension_paths():
    return [{
        'section': 'notebook',
        'src': 'amd',
        'dest': 'jupyter-lightsaber',
        'require': 'jupyter-lightsaber/index',
        'server': ['my_server_ext1', 'my_server_ext2']
    }]

and then make enable_nbextension_python able to understand this server key and write to the NotebookApp.server_extensions space in the diff being created.

If there's no way for this change to go in without breaking the current nbextension CLI overrides used in nbgrader, jupyter-incubator/declarativewidgets, jupyter-incubator/dashboards, etc., then I'll have to do some version detection to support install/activate on both <4.2 and >4.1.

Not sure if it will be a nice way to not break this since the config manager implementation has changed a lot on this PR... version detection seems like a good alternative.

@damianavila
Copy link
Member

Additionally, the CLI should offer some keyword to enable/disable the server part... I guess... or maybe an independent CLI for the server part...

@minrk
Copy link
Member

minrk commented Feb 10, 2016

I would probably treat server and client extensions separately

@@ -299,118 +355,300 @@ def _config_file_name_default(self):
def install_extensions(self):
if len(self.extra_args)>1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is triggering an error when I tried to install using --py in a sys-prefix... I mean:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing this condition work as expected... if we want to warn more than one nbextension we should detect that in another way...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forget about this... it is working...

@bollwyvl
Copy link
Contributor

Ok, with that PR in... are we looking for anything else? More doc? Glad to help!

minrk added 3 commits March 24, 2016 15:03
logging is inappropriate here

also only show config dir if there's config in it.
add more docs coverage, help output

So that the three cases are covered:

- system-wide (default for install)
- user (default for enable)
- sys-prefix
@minrk
Copy link
Member

minrk commented Mar 24, 2016

@bollwyvl I think we're almost there. We can merge soon and make the beta. I opened ellisonbg#24 with a few things I found that were still missing.

@willingc
Copy link
Member

@bollwyvl If you think that there are more docs needed, please dive in or ping me. Thanks :D

@minrk minrk changed the title Adding prototype nbextensions argument to NotebookApp New nbextensions installation API Mar 25, 2016
@minrk
Copy link
Member

minrk commented Mar 25, 2016

I'm happy to merge this as-is, now.

@minrk
Copy link
Member

minrk commented Mar 25, 2016

I'm about to board my flight to California, but I'll merge by the end of Friday (CA time) unless someone wants to do anything else here.

@willingc
Copy link
Member

Safe travels @minrk.

@jdfreder
Copy link
Contributor

@minrk safe travels

@minrk minrk merged commit 41d6da2 into jupyter:master Mar 26, 2016
@jdfreder
Copy link
Contributor

🎉 🍰 Welcome back to cali @minrk (and @takluyver) !

https://www.youtube.com/watch?v=E_B0rOLvAOo

:)

@takluyver
Copy link
Member

takluyver commented Mar 26, 2016 via email

@willingc
Copy link
Member

Welcome back @takluyver. See you on Monday.

Congrats to all on getting this merged.

@SylvainCorlay
Copy link
Member

🍰 👍

@bollwyvl
Copy link
Contributor

🍦 🍰 🍕 from DFW... See y'all soon!

On 09:07, Sun, Mar 27, 2016 Sylvain Corlay [email protected] wrote:

[image: 🍰] [image: 👍]


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#879 (comment)

@damianavila
Copy link
Member

\o/
nice...
See you all in a little bit!! 😉

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.