/widget-cookiecutter

A cookiecutter template for creating a custom Jupyter widget project.

Primary LanguageJavaScriptBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

widget-cookiecutter (deprecated)

This cookitcutter template is now deprecated

We recommend anywidget as an alternative for those who want to learn or quickly prototype widgets. For production uses, we recommend the TypeScript cookiecutter

A cookiecutter template for creating a custom Jupyter widget project

Documentation Status Join the chat at https://gitter.im/jupyter-widgets/Lobby

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:

    1. one that is suitable for loading the widget frontend in the classic notebook
    2. one that is suitable for loading the widget frontend in standalone HTML webpages with no backend
    3. 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:

    1. The classic notebook frontend bundle gets created using `index.js` as the entrypoint.
    2. The standalone frontend bundle gets created using `embed.js` as the entrypoint.
    3. 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 a model 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 by extension.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 the setup.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, runs npm install and npm run build)
  • jupyter nbextension install --py --symlink --sys-prefix <python_package_name>
    (symlinks nbextension/ 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, runs yarn install and yarn 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 from nbextension/ 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.