Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Separate extension install from pip install #24

Merged
merged 8 commits into from
Jan 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
recursive-include urth_cms_js *.js *.css
include VERSION
recursive-include jupyter_cms/nbextension *.js *.css
25 changes: 16 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@

PYTHON?=python3

REPO:=jupyter/pyspark-notebook:a388c4a66fd4
DEV_REPO:=jupyter/pyspark-notebook-cms:a388c4a66fd4
REPO:=jupyter/pyspark-notebook:2988869079e6
DEV_REPO:=jupyter/pyspark-notebook-cms:2988869079e6
PYTHON2_SETUP:=source activate python2

define EXT_DEV_SETUP
pushd /src && \
pip install --no-deps -e . && \
jupyter cms install --user && \
jupyter cms activate && \
popd
endef

help:
@echo 'Host commands:'
@echo ' build - build dev image'
Expand All @@ -35,14 +43,13 @@ clean:

dev: dev-$(PYTHON)

dev-python2: SETUP_CMD?=$(PYTHON2_SETUP); pushd /src && pip install --no-deps -e . && popd
dev-python2: LANG_SETUP_CMD?=$(PYTHON2_SETUP) && python --version
dev-python2: _dev

dev-python3: SETUP_CMD?=pushd /src && pip install --no-deps -e . && popd
dev-python3: LANG_SETUP_CMD?=python --version
dev-python3: _dev

_dev: NB_HOME?=/root
_dev: CMD?=sh -c "python --version; jupyter notebook --no-browser --port 8888 --ip='*'"
_dev: CMD?=start-notebook.sh
_dev: AUTORELOAD?=no
_dev:
@docker run -it --rm \
Expand All @@ -51,18 +58,18 @@ _dev:
-e AUTORELOAD=$(AUTORELOAD) \
-v `pwd`:/src \
-v `pwd`/etc/notebooks:/home/jovyan/work \
$(DEV_REPO) bash -c '$(SETUP_CMD); $(CMD)'
$(DEV_REPO) bash -c '$(LANG_SETUP_CMD) && $(EXT_DEV_SETUP) && $(CMD)'

install: CMD?=exit
install:
@docker run -it --rm \
--user jovyan \
-v `pwd`:/src \
$(REPO) bash -c 'cd /src/dist && \
pip install --no-binary :all: $$(ls -1 *.tar.gz | tail -n 1) && \
jupyter cms install --user && \
jupyter cms activate && \
$(CMD)'

sdist: REPO?=jupyter/pyspark-notebook:$(TAG)
sdist:
@docker run -it --rm \
-v `pwd`:/src \
Expand Down
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,29 @@ Note that both of these deployments tend to lag the latest stable release.

## Install It

`pip install jupyter_cms` and then restart your Notebook server if it was running during the install.
```bash
# install the python package
pip install jupyter_cms
# register the notebook frontend extensions into ~/.local/jupyter
# see jupyter cms install --help for other options
jupyter cms install --user --symlink --overwrite
# enable the JS and server extensions in your ~/.jupyter
jupyter cms activate

# deactivate it later with
jupyter cms deactivate
```

You will need to restart your notebook server if it was running during the activate step.

## Uninstall It

```bash
jupyter cms deactivate
pip uninstall jupyter_cms
```

Note that there is no Jupyter method for removing the installed JavaScript extension assets. You will need to clean them up manually from your chosen install location.

## Writing Bundlers

Expand Down
6 changes: 3 additions & 3 deletions etc/notebooks/cookbooks_demo/use_cookbooks.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"source": [
"### Enable the extension\n",
"\n",
"To start, we first need to load the content management extension. This magic makes it possible to import other notebooks as Python modules. (The `urth` bit comes from a historical codename for the extension and will likely change in the future.)"
"To start, we first need to load the content management extension. This magic makes it possible to import other notebooks as Python modules."
]
},
{
Expand All @@ -47,7 +47,7 @@
},
"outputs": [],
"source": [
"%load_ext urth.cms"
"%load_ext jupyter_cms"
]
},
{
Expand Down Expand Up @@ -101,7 +101,7 @@
},
"outputs": [],
"source": [
"from urth.cms.loader import load_notebook"
"from jupyter_cms.loader import load_notebook"
]
},
{
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
226 changes: 226 additions & 0 deletions jupyter_cms/extensionapp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import errno
import os.path
import sys

from jupyter_core.paths import jupyter_config_dir
from notebook.services.config import ConfigManager
from notebook.nbextensions import (InstallNBExtensionApp, EnableNBExtensionApp,
DisableNBExtensionApp, flags, aliases)
from traitlets import Unicode
from traitlets.config.application import catch_config_error
from traitlets.config.application import Application

# Make copies to reuse flags and aliases
INSTALL_FLAGS = {}
INSTALL_FLAGS.update(flags)

INSTALL_ALIASES = {}
INSTALL_ALIASES.update(aliases)
del INSTALL_ALIASES['destination']

def makedirs(path):
'''
mkdir -p and ignore existence errors compatible with Py2/3.
'''
try:
os.makedirs(path)
except OSError as e:
if e.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise

class ExtensionInstallApp(InstallNBExtensionApp):
'''Subclass that installs this particular extension.'''
name = u'jupyter-cms-extension-install'
description = u'Install the jupyter_cms extension'

flags = INSTALL_FLAGS
aliases = INSTALL_ALIASES

examples = """
jupyter cms install
jupyter cms install --user
jupyter cms install --prefix=/path/to/prefix
jupyter cms install --nbextensions=/path/to/nbextensions
"""

destination = Unicode('')

def _classes_default(self):
return [ExtensionInstallApp, InstallNBExtensionApp]

def start(self):
here = os.path.abspath(os.path.join(os.path.dirname(__file__)))

self.log.info("Installing jupyter_cms JS notebook extensions")
self.extra_args = [os.path.join(here, 'nbextension')]
self.destination = 'jupyter_cms'
self.install_extensions()


class ExtensionActivateApp(EnableNBExtensionApp):
'''Subclass that activates this particular extension.'''
name = u'jupyter-cms-extension-activate'
description = u'Activate the jupyter_cms extension'

flags = {}
aliases = {}

examples = """
jupyter cms activate
"""

def _classes_default(self):
return [ExtensionActivateApp, EnableNBExtensionApp]

def enable_server_extension(self, extension):
'''Enables the server side extension in the user config.'''
server_cm = ConfigManager(config_dir=jupyter_config_dir())

makedirs(server_cm.config_dir)

cfg = server_cm.get('jupyter_notebook_config')
server_extensions = (
cfg.setdefault('NotebookApp', {})
.setdefault('server_extensions', [])
)
if extension not in server_extensions:
cfg['NotebookApp']['server_extensions'] += [extension]
server_cm.update('jupyter_notebook_config', cfg)

def enable_bundler(self):
'''Enables the notebook bundler extension.'''
cm = ConfigManager(parent=self, config=self.config)
cm.update('notebook', {
'jupyter_cms_bundlers': {
'notebook_associations_download': {
'label': 'IPython Notebook bundle (.zip)',
'module_name': 'jupyter_cms.nb_bundler',
'group': 'download'
}
}
})

def start(self):
self.log.info("Activating jupyter_cms notebook server extensions")
self.enable_server_extension('jupyter_cms')

self.log.info("Activating jupyter_cms JS notebook extensions")
self.section = "notebook"
self.enable_nbextension("jupyter_cms/notebook/main")
self.section = "tree"
self.enable_nbextension("jupyter_cms/dashboard/main")
self.section = "edit"
self.enable_nbextension("jupyter_cms/editor/main")
self.enable_bundler()

self.log.info("Done. You may need to restart the Jupyter notebook server for changes to take effect.")

class ExtensionDeactivateApp(DisableNBExtensionApp):
'''Subclass that deactivates this particular extension.'''
name = u'jupyter-cms-extension-deactivate'
description = u'Deactivate the jupyter_cms extension'

flags = {}
aliases = {}

examples = """
jupyter cms deactivate
"""

def _classes_default(self):
return [ExtensionDeactivateApp, DisableNBExtensionApp]

def disable_server_extension(self, extension):
'''Disables the server side extension in the user config.'''
server_cm = ConfigManager(config_dir=jupyter_config_dir())

makedirs(server_cm.config_dir)

cfg = server_cm.get('jupyter_notebook_config')
if ('NotebookApp' in cfg and
'server_extensions' in cfg['NotebookApp'] and
extension in cfg['NotebookApp']['server_extensions']):
cfg['NotebookApp']['server_extensions'].remove(extension)

server_cm.update('jupyter_notebook_config', cfg)

server_extensions = (
cfg.setdefault('NotebookApp', {})
.setdefault('server_extensions', [])
)
if extension in server_extensions:
cfg['NotebookApp']['server_extensions'].remove(extension)
server_cm.update('jupyter_notebook_config', cfg)

def disable_bundler(self):
'''Disables the notebook bundler extension.'''
cm = ConfigManager(parent=self, config=self.config)
cm.update('notebook', {
'jupyter_cms_bundlers': {
'notebook_associations_download': None
}
})

def start(self):
self.log.info("Deactivating jupyter_cms notebook server extensions")
self.disable_server_extension('jupyter_cms')

self.log.info("Deactivating jupyter_cms JS notebook extensions")
self.section = "notebook"
self.disable_nbextension("jupyter_cms/notebook/main")
self.section = "tree"
self.disable_nbextension("jupyter_cms/dashboard/main")
self.section = "edit"
self.disable_nbextension("jupyter_cms/editor/main")
self.disable_bundler()

self.log.info("Done. You may need to restart the Jupyter notebook server for changes to take effect.")

class ExtensionApp(Application):
'''CLI for extension management.'''
name = u'jupyter_cms extension'
description = u'Utilities for managing the jupyter_cms extension'
examples = ""

subcommands = dict(
install=(
ExtensionInstallApp,
"Install the extension."
),
activate=(
ExtensionActivateApp,
"Activate the extension."
),
deactivate=(
ExtensionDeactivateApp,
"Deactivate the extension."
)
)

def _classes_default(self):
classes = super(ExtensionApp, self)._classes_default()

# include all the apps that have configurable options
for appname, (app, help) in self.subcommands.items():
if len(app.class_traits(config=True)) > 0:
classes.append(app)

@catch_config_error
def initialize(self, argv=None):
super(ExtensionApp, self).initialize(argv)

def start(self):
# check: is there a subapp given?
if self.subapp is None:
self.print_help()
sys.exit(1)

# This starts subapps
super(ExtensionApp, self).start()

def main():
ExtensionApp.launch_instance()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions scripts/jupyter-cms
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import jupyter_cms.extensionapp

if __name__ == '__main__':
jupyter_cms.extensionapp.main()
Loading