initial crack at documentation for new-wave extension stuff

This commit is contained in:
Nicholas Bollweg 2016-03-10 13:44:50 -05:00
parent a17b7021ab
commit d54ed564af

View File

@ -0,0 +1,251 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Distributing Jupyter Extensions as Python Packages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## How can the notebook be extended?\n",
"The Jupyter Notebook server and client application are both deeply customizable. Their behavior can be extended by, respectively:\n",
"\n",
"- nbextension:\n",
" - a single JS file, or directory of JavaScript, Cascading StyleSheets, etc. that contain at least\n",
" - a JavaScript module packaged as an [AMD modules](https://en.wikipedia.org/wiki/Asynchronous_module_definition)\n",
" - that exports a function `load_ipython_extension`\n",
"- server extension: an importable Python module\n",
" - that implements `load_jupyter_server_extension`\n",
"\n",
"Since it is somewhat rare to have a server extension that does not have any frontend components, for convenience ad consistency, all these assets can be versioned together, with a few simple commands to make installing them easy and less error-prone for the user. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install a Python Package with Jupyter Extensions\n",
"There are many ways someone may get the enclosing python package:\n",
"```shell\n",
"pip install some_package\n",
"# or\n",
"conda install some_package\n",
"# or\n",
"apt-get install some_package\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Enable a Server Extension\n",
"\n",
"For the simplest case, a server extension with no frontend components, a `pip` user that wants their configuration stored in their home directory would type:\n",
"```shell\n",
"jupyter serverextension enable --py some_package --user\n",
"```\n",
"\n",
"A `virtualenv` or `conda` user can pass `--sys-prefix` insted of `--user` to keep their environment reproducible.\n",
"```shell\n",
"[source] activate my-environment\n",
"jupyter serverextension enable --py some_package --sys-prefix\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install the nbextension assets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In any event, if a package also has frontend assets that must be available (but not neccessarily enabled by default):\n",
"```shell\n",
"jupyter nbextension install --py some_package --user # or --sys-prefix\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Enable nbextension assets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, if a package has extensions that need to be required in the browser without user interactions,\n",
"```shell\n",
"jupyter nbextension enable --py some_package --user # or --sys-prefix\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Did it work?\n",
"After running some extension install steps, one can list what is presently known about, whether it's enabled, etc.\n",
"\n",
"```shell\n",
"jupyter nbextension list\n",
"jupyter serverextension list\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Of course, in addition to the files listed, there are number of other files one needs to build a proper package. Here are some good resources:\n",
"- [The Hitchhiker's Guide to Packaging](http://the-hitchhikers-guide-to-packaging.readthedocs.org/en/latest/quickstart.html)\n",
"- [Repository Structure and Python](http://www.kennethreitz.org/essays/repository-structure-and-python) by Kenneth Reitz\n",
"\n",
"> How you distribute them, too, is important:\n",
"- [Packaging and Distributing Projects](http://python-packaging-user-guide.readthedocs.org/en/latest/distributing/)\n",
"- [conda: Building packages](http://conda.pydata.org/docs/building/build.html)\n",
"\n",
"> Here are some tools to get you started:\n",
"- [generator-nbextension](https://github.com/Anaconda-Server/generator-nbextension)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Implementing Python-wrapped extensions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is an example of a python module which contains a server extension directly on itself. It has this directory structure\n",
"```\n",
"- setup.py\n",
"- MANIFEST.in\n",
"- my_module/\n",
" - __init__.py\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `my_module/__init__.py`\n",
"\n",
"```python\n",
"def _jupyter_server_extension_paths():\n",
" return [{\n",
" \"module\": \"my_module\"\n",
" }]\n",
"\n",
"\n",
"def load_jupyter_server_extension(nbapp):\n",
" nbapp.log.info(\"my module enabled!\")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Which a user can install with:\n",
"```\n",
"jupyter serverextension enable --py my_module [--sys-prefix|--user]\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is another server extension, with a front-end module. It assumes this directory structure:\n",
"\n",
"```\n",
"- setup.py\n",
"- MANIFEST.in\n",
"- my_fancy_module/\n",
" - __init__.py\n",
" - static/\n",
" index.js\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"### `my_fancy_module/__init__.py`\n",
"\n",
"```python\n",
"def _jupyter_server_extension_paths():\n",
" return [{\n",
" \"module\": \"my_fancy_module\"\n",
" }]\n",
"\n",
"# Jupyter Extension points\n",
"def _jupyter_nbextension_paths():\n",
" return [dict(\n",
" section=\"notebook\",\n",
" # the path is relative to the `my_fancy_module` directory\n",
" src=\"static\",\n",
" # directory in the `nbextension/` namespace\n",
" dest=\"my_fancy_module\",\n",
" # _also_ in the `nbextension/` namespace\n",
" require=\"my_fancy_module/index\")]\n",
"\n",
"def load_jupyter_server_extension(nbapp):\n",
" nbapp.log.info(\"my module enabled!\")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Which a user can install with:\n",
"```\n",
"jupyter serverextension install --py my_fancy_module [--sys-prefix|--user]\n",
"jupyter nbextension install --py my_fancy_module [--sys-prefix|--user]\n",
"jupyter nbextension enable --py my_fancy_module [--sys-prefix|--user]\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}