widget-cookiecutter
A cookiecutter template for creating a custom Jupyter widget project
A cookiecutter template for a custom Jupyter widget project.
What is widget-cookiecutter?
With widget-cookiecutter you can create a custom Jupyter interactive widget project with sensible defaults. widget-cookiecutter helps custom widget authors get started with best practices for the packaging and distribution of a custom Jupyter interactive widget library.
Who uses widget-cookiecutter
Popular widget libraries such as bqplot, pythreejs and ipyleaflet can serve as advanced examples of usage of the Jupyter widget infrastructure.
Usage
Install cookiecutter:
$ pip install cookiecutter
After installing cookiecutter, use the widget-cookiecutter:
$ cookiecutter https://github.com/jupyter/widget-cookiecutter.git
As widget-cookiecutter runs, you will be asked for basic information about your custom Jupyter widget project. You will be prompted for the following information:
author_name
: your name or the name of your organization,author_email
: your project's contact email,github_project_name
: name of your custom Jupyter widget's GitHub repository,github_organization_name
: name of your custom Jupyter widget's GitHub user or organization,python_package_name
: name of the Python "backend" package used in your custom widget.npm_package_name
: name for the npm "frontend" package holding the JavaScript implementation used in your custom widget.project_short_description
: a short description for your project that will be used for both the "backend" and "frontend" packages.
After this, you will have a directory containing files used for creating a custom Jupyter widget. You will now be able to easily package and distribute your custom Jupyter widget.
Files Generated by cookiecutter
Jupyter widgets are composed of two separate programs:
- A Python package for the code executed in notebook kernel as the backend of the widget
- A Javascript package for the frontend of the widget running in browser
This cookiecutter generates example source files for both the backend and frontend programs, as well as the tooling to develop and publish the widget in the classic notebook, JupyterLab and in stand-alone HTML pages.
Running the cookiecutter generates the following file tree:
βββ <python_package_name>
βΒ Β βββ __init__.py
βΒ Β βββ _version.py
βΒ Β βββ example.py
βββ js
βΒ Β βββ lib
βΒ Β βΒ Β βββ embed.js
βΒ Β βΒ Β βββ example.js
βΒ Β βΒ Β βββ extension.js
βΒ Β βΒ Β βββ index.js
βΒ Β βΒ Β βββ labplugin.js
βΒ Β βββ package.json
βΒ Β βββ README.md
βΒ Β βββ webpack.config.js
βββ .gitignore
βββ <npm_package_name>.json
βββ MANIFEST.in
βββ README.md
βββ RELEASE.md
βββ setup.cfg
βββ setup.py
-
<python_package_name> directory
This directory contains the python package that runs in the kernel-
__init__.py
Marks the<python_package_name>
directory as a python module, allowing<python_package_name>
to be imported -
_version.py
Contains version definitions for both the backend and the frontend code, to be used from Python. You should not need to modify this file, apart from when you release a new version of the package. -
example.py
Example source file containing a widget. Modify this to define your own widgets.
-
-
js directory
Source files for widget frontend. There are actually three different frontend programs:- one that is suitable for loading the widget frontend in the classic notebook
- one that is suitable for loading the widget frontend in standalone HTML webpages with no backend
- one that is suitable for loading the widget frontend in JupyterLab
Fortunately, you don't have to write three different versions of your widgets. There are three entrypoints that all load the widget source files. Each of the frontend program gets bundled using webpack:
- The classic notebook frontend bundle gets created using
index.js
as the entrypoint. - The standalone frontend bundle gets created using
embed.js
as the entrypoint. - For JupyterLab, the frontend code gets folded into the JupyterLab frontend itself using JupyterLab's webpack. JupyterLab will include
labplugin.js
as the entrypoint to the widgets.
-
lib directory
Directory containing source files-
embed.js
Webpack entry-point for generating the code bundle that is loaded when widgets are used in a stand-alone HTML page. Learn more about embedding widgets into a stand-alone HTML page here. When you add new source files to your project that declare widgets, you will need to export them here. -
example.js
Widget frontend source code. Contains widget model and view class definitions. Widget model is derived from DOMWidgetModel which provides functionality to communicate with the model instance on kernel. Widget view is derived from DOMWidgetView which has amodel
attribute referencing to widget model it is presenting. -
extension.js
Entry-point that is loaded by the classic notebook to load your widget. You should not need to modify this. Note that this does not get included in the webpack bundle. -
index.js
This is the entrypoint to your library. When you add new widgets, or change widget names, add these here. When bundling for the classic notebook, webpack will create a single bundle based on this file. This bundle is then loaded byextension.js
. For JupyterLab,labplugin.js
loads this file. -
labplugin.js
JupyterLab extension definition for JupyterLab integration. When JupyterLab loads, it activates the plugin defined in this file. Widget registry service provided by@jupyter-widgets/jupyterlab-manager
is used during activation to register the widget with JupyterLab. You should not need to modify this file.
-
-
package.json
npm package definiton file for widget frontend. You should not need to modify this file, apart from to add new JavaScript dependencies. -
README.md
Auto-generated documentation file for frontend npm package, with installation instructions. -
webpack.config.js
Webpack bundler configuration that defines bundler entry points and ouputs along with other configuration
-
.gitignore
Ignore rules for widget project git repository. -
<npm_package_name>.json
This file gets copied into the configuration directory for the classic notebook as part of the installation process. This enables the extension for the notebook. You should not need to modify this file. -
MANIFEST.in
setuptools configuration file containing commands to execute (include / exclude files) during installation (pip install). You should not need to modify this file, unless you change the directory structure for your project. -
README.md
Auto-generated documentation file for widget project. -
RELEASE.md
Auto-generated documentation file with instructions for publishing python package to PyPI and npm package to npm registry. -
setup.cfg
Configuration file to mark the python package as a Universal Wheel. -
setup.py
Build script for the widget package. Note that thesetup.py
is heavily customised compared to pure Python packages. In particular, it builds the JavaScript code when creating a source distribution, and copies the notebook frontend into the right directory when a user installs the package.
Local Dev Installation for Classic Notebook
To develop this package against the classic notebook, run:
pip install -e .
(installs python package for development, runsnpm install
andnpm run build
)jupyter nbextension install --py --symlink --sys-prefix <python_package_name>
(symlinksnbextension/
directory into<jupyter path>/nbextensions/<extension_name>/
). Now the notebook has access to the frontend code.jupyter nbextension enable --py --sys-prefix <python_package_name>
(copies<npm_package_name>.json
into<environment path>/etc/jupyter/nbconfig/notebook.d/
directory). Now the notebook will load your frontend code on page load.
Now make some changes to your source code. Then:
- After making Python code changes, restarting the notebook kernel will be enough to reflect changes
- After making JavaScript code changes:
cd js
yarn run build
- Refresh browser to reflect changes
Local Dev Installation for JupyterLab
To develop this package against JupyterLab, run:
pip install -e .
(installs python package for development, runsyarn install
andyarn run build
and installs the labextension)jupyter labextension develop <python_package_name> --overwrite
Now make some changes to your source code. Then:
- After making Python code changes, restarting the notebook kernel will be enough to reflect changes
- After making JavaScript code changes:
cd js
yarn run build
- Refresh browser to reflect changes
Publishing Widget
Follow the steps in (RELEASE.md) to publish widget python package and npm packages.
Widget Installation Process for Notebook
When installing published package in non-development mode
pip install
installs python package for access from kernel and copies frontend code files fromnbextension/
directory into<jupyter path>/nbextensions/<extension_name>/
and enables by copying<npm_package_name>.json
file into<environment path>/etc/jupyter/nbconfig/notebook.d/
directory.
Widget Load Process for Notebook
- Python code is loaded into kernel from python package directory
- Frontend javascript code loaded from
<jupyter path>/nbextensions/<extension_name>/extension.js
More information
- Documentation of Jupyter widgets
- Ask questions about using widget-cookiecutter on the Gitter channel
- If you find an issue with widget-cookiecutter or would like to contribute an enhancement, file an issue at the widget-cookiecutter GitHub repo.