Packaging Starters#

Starters are configured through the traitlets system. As of notebook 5.3, these configurations can be packaged as simple files. Here’s a quick example, assuming the following file structure:

my-project:
  - setup.py
  - MANIFEST.in
  # other good stuff like LICENSE, README.md, CHANGELOG.md, CODE_OF_CONDUCT.md
  - src:
      - my_project:
          - __init__.py
          - foo.py
          - my-starter-folder:
              - my-starter-file.json
          - etc:
              - my-project-starter.json

MANIFEST.in#

# the usual suspects
include LICENSE README.md CHANGELOG.md CODE_OF_CONDUCT.md
# ensure the starter is included in the source distribution
recursive-include src *.json

setup.py#

import setuptools

setuptools.setup(
    ...
    include_package_data=True,
    data_files=[
        (
            "etc/jupyter/jupyter_server_config.d",
            ["src/my_project/etc/my-project-starter.json"],
        )
    ]
    zip_safe=False
)

my-project-starter.json#

{
  "StarterManager": {
    "extra_starters": {
      "my-project-starter": {
        "description": "copies a JSON file to your working directory",
        "label": "My Starter",
        "py_src": "my_project",
        "src": "my-starter-folder/my-starter-file.json",
        "type": "copy"
      }
    }
  }
}

Note that all paths should be /-delimited, even on Windows.

src can be absolute or relative to the cwd of the running notebook server…

This is not very useful when packaging, as these values cannot be known in advance!

Starter copy and notebook types, in addition to src, can use a py_src of any importable module as a portable “anchor” without

  • having to know the details of the installed location

  • or executing/importing any arbitrary code until the user requests it

However, because of how dynamic the python import system is (see importnb), giving a dotted module, e.g. my_module.foo does cause the top-level module to be imported.