Show code cell content
import graphviz
import IPython
@IPython.core.magic.register_line_cell_magic
def dot(line, cell):
return graphviz.Source(cell)
For Starters#
The basic idea of a starter is:
pick a destination in the JupyterLab File Browser
click a button in the JupyterLab Launcher
see useful files
A slightly more accurate version is:
configure via traitlets
advertise to JupyterLab via the REST API
display in the JupyterLab Launcher
click a button in the JupyterLab Launcher
or immediately start with a Starter Tree URL
zero or more (but usually one) times:
gather more information from the user via react-jsonschema-form
perform further processing
copy files via the Contents API
see useful files in the JupyterLab File Browser
run JupyterLab Commands to do other things to JupyterLab
Which of these steps a particular starter performs depends primarily on its type.
Types of Starters#
Copy#
"type": "copy"
"src": "<an absolute or relative path>"
The simplest starter, copy
, just… copies. It can copy a single file, or a directory
of files (and subdirectories). The src
attribute tells the starter where to get the
files.
Show code cell source
%%dot
digraph g { compound=true layout=dot rankdir=TB
node[shape=none fontname="sans-serif"]
graph[fontname="sans-serif" fontcolor="grey" color="none" fillcolor="#eeeeee" style=filled]
label="a notional execution of a copy starter"
subgraph cluster_files { label="Your Files"
files
}
subgraph cluster_server { label="Notebook Server"
get[label="/starters" fontname=monospace]
post[label="/starters/{:name}/{:path}" fontname=monospace]
contents
}
subgraph cluster_lab { label="JupyterLab"
launcher
}
get -> launcher[label=①]
launcher -> post[label=②]
post -> contents[label=③]
contents -> files[label=④]
files -> contents[label=⑤]
contents -> post[label=⑥]
post -> launcher[label=⑦]
launcher -> launcher[label=⑧]
}
copy
, like all the starters, makes use of the
Contents API
directly. Existing files will not be overwritten.
Content#
"type": "content"
"content": "<a subset of Jupyter Content>"
The Content starter is similar to a cookiecutter, supporting…
named contents, interpolated with
jinja2
-compatible templates for file contents and folder and file namestemplated names that resolve as empty (and their children) will be skipped
…with the main differences being:
instead of an on-disk file tree, the enture content tree directly is defined inside the JSON definition.
when run entirely in the browser, nunjucks is used instead of
jinja2
These can be provided (and run by) the server extension, or entirely within the browser when defined in JupyterLab (or JupyterLite).
Python#
"type": "python"
"callable": "<a dotted notation python function>"
A Python Starter is a function. This type has the fewest limitations, as it has full
access to the StarterManager
(and by extension, it’s parent
, the NotebookApp
).
This powers both the Cookiecutter the Notebook starters,
with the latter directly using the notebook server’s Kernel Manager to start
short-lifespan kernels.
Show code cell source
%%dot
digraph g { compound=true layout=dot rankdir=TB
node[shape=none fontname="sans-serif"]
graph[fontname="sans-serif" fontcolor="grey" color="none" fillcolor="#eeeeee" style=filled]
label="a notional execution of a python starter"
subgraph cluster_files { label="Your Files"
files
}
subgraph cluster_server { label="Notebook Server"
get[label="/starters" fontname=monospace]
post[label="/starters/{:name}/{:path}" fontname=monospace]
contents
callable
}
subgraph cluster_lab { label="JupyterLab"
launcher
}
get -> launcher[label=①]
launcher -> post[label=②]
post -> callable[label=③]
callable -> contents[label=④]
contents -> files[label=⑤]
files -> contents[label=⑥]
contents -> callable[label=⑦]
callable -> post[label=⑧]
post -> launcher[label=⑨]
launcher -> launcher[label=⑩]
}
Notebook#
"type": "notebook"
A notebook can be a starter. Each starter run gets its own, private kernel which can persist between interactions with the user. Communication with the server manager is handled through manipulating a copy of the notebook, specfically the notebook metadata. The advantages of this approach over the Python starter is:
works with any installed kernel
state is maintained between successive re-executions
jupyterlab-starters
provides authoring support for editing and validating the starter
Show code cell source
%%dot
digraph g { compound=true layout=dot rankdir=TB title="woooo"
node[shape=none fontname="sans-serif"]
graph[fontname="sans-serif" fontcolor="grey" color="none" fillcolor="#eeeeee" style=filled]
label="a notional execution of a notebook starter"
subgraph cluster_files { label="Your Files"
files
}
subgraph cluster_server { label="Notebook Server"
get[label="/starters" fontname=monospace]
post[label="/starters/cookiecutter/{:path}" fontname=monospace]
contents
kernel
tmpdir
}
subgraph cluster_lab { label="JupyterLab"
launcher
form1[label="initial form"]
form2[label="dynamic form"]
}
get -> launcher[label=①]
launcher -> form1[label=②]
form1 -> post[label=③]
post -> tmpdir[label=④]
tmpdir -> post[label=⑤]
tmpdir -> kernel[label=⑥]
kernel -> tmpdir[label=⑦]
post -> form2[label=⑧]
form2 -> post[label=⑨]
post -> tmpdir[label=⑩]
tmpdir -> kernel[label=⑪]
kernel -> tmpdir[label=⑫]
tmpdir -> contents[label=⑬]
contents -> files[label=⑭]
files -> contents[label=⑮]
contents -> post[label=⑯]
post -> launcher[label=⑰]
launcher -> launcher[label=⑲]
}
Built-ins#
Extras#
Starter Tree URL#
By specifying a special URL when starting JupyterLab, you can immediately start a Starter, without requiring the launcher. The pattern is:
{:protocol}://{:host}:{:port}{:base-url}/lab{:whatever}?starter/{:starter-name}{:starter-path}
For example, to start the cookiecutter Starter:
http://localhost:8888/lab?starter=cookiecutter
On Binder, this path is determined by the urlpath
GET
parameter, which gets encoded again, for example:
https://mybinder.org/v2/gh/deathbeds/jupyterlab-starters/master?urlpath=lab%3Fstarter%2Fcookiecutter
Starter Body in URL#
The starter-body
parameter is a JSON-encoded dictionary that conforms to the starter
schema, and extends the above form:
&starter-body={:json-encoded-body}
For example, to pre-fill the form with the Jupyter Widget cookiecutter:
http://localhost:8888/lab?starter=cookiecutter&starter-body=%7B%22checkout%22%3A%22HEAD%22%2C%22directory%22%3A%22%22%2C%22template%22%3A%22https%3A%2F%2Fgithub.com%2Fjupyter-widgets%2Fwidget-cookiecutter%22%7D
Skip the Builder by URL#
The starter-form
parameter is a JSON-encoded dictionary that conforms to the starter
schema, and extends the above form:
&starter-form={:truthy}
Appending this to one of the above.
Note
Skipping the builder form can have undesirable effects for complex schema.