jupyterlab-workshop 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jupyterlab_workshop-0.1.0/.gitignore +58 -0
- jupyterlab_workshop-0.1.0/.prettierignore +15 -0
- jupyterlab_workshop-0.1.0/.python-version +1 -0
- jupyterlab_workshop-0.1.0/.readthedocs.yaml +15 -0
- jupyterlab_workshop-0.1.0/.yarnrc.yml +2 -0
- jupyterlab_workshop-0.1.0/AGENTS.md +204 -0
- jupyterlab_workshop-0.1.0/CLAUDE.md +1 -0
- jupyterlab_workshop-0.1.0/CONTRIBUTING.md +83 -0
- jupyterlab_workshop-0.1.0/Justfile +121 -0
- jupyterlab_workshop-0.1.0/LICENSE +202 -0
- jupyterlab_workshop-0.1.0/PKG-INFO +105 -0
- jupyterlab_workshop-0.1.0/README.md +70 -0
- jupyterlab_workshop-0.1.0/TESTING.md +95 -0
- jupyterlab_workshop-0.1.0/binder/postBuild +19 -0
- jupyterlab_workshop-0.1.0/binder/requirements.txt +5 -0
- jupyterlab_workshop-0.1.0/docs/actions.md +117 -0
- jupyterlab_workshop-0.1.0/docs/analytics.md +81 -0
- jupyterlab_workshop-0.1.0/docs/authoring.md +125 -0
- jupyterlab_workshop-0.1.0/docs/checks.md +199 -0
- jupyterlab_workshop-0.1.0/docs/cli.md +180 -0
- jupyterlab_workshop-0.1.0/docs/conf.py +40 -0
- jupyterlab_workshop-0.1.0/docs/demo.md +76 -0
- jupyterlab_workshop-0.1.0/docs/environment.md +73 -0
- jupyterlab_workshop-0.1.0/docs/index.md +133 -0
- jupyterlab_workshop-0.1.0/docs/lite.md +109 -0
- jupyterlab_workshop-0.1.0/docs/platforms.md +117 -0
- jupyterlab_workshop-0.1.0/docs/registry.md +161 -0
- jupyterlab_workshop-0.1.0/docs/trust.md +165 -0
- jupyterlab_workshop-0.1.0/eslint.config.mjs +70 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/README.md +8 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/pages/01-create-a-repository.md +73 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/pages/02-first-commit.md +103 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/pages/03-edit-and-diff.md +65 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/pages/04-branch-and-merge.md +75 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/pages/05-resolve-a-conflict.md +139 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/verify/merged.py +22 -0
- jupyterlab_workshop-0.1.0/examples/git-basics/workshop.yaml +39 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/README.md +8 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/files/notes.md +3 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/01-welcome.md +57 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/02-notebooks.md +71 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/03-kernels.md +49 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/04-files.md +53 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/05-variables.md +57 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/06-conda.md +16 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/06-pip.md +17 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/07-automation.md +46 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/08-finish.md +18 -0
- jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/workshop.yaml +41 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/.gitignore +5 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/01-what-a-workshop-is.md +52 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/02-scaffold.md +62 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/03-write-a-page.md +81 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/04-lint.md +115 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/05-test-and-publish.md +64 -0
- jupyterlab_workshop-0.1.0/examples/workshop-authoring/workshop.yaml +34 -0
- jupyterlab_workshop-0.1.0/github-pages/index.html +136 -0
- jupyterlab_workshop-0.1.0/install.json +5 -0
- jupyterlab_workshop-0.1.0/jupyter-config/server-config/jupyterlab_workshop.json +7 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/__init__.py +37 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/_version.py +4 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/analytics.py +130 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/bridge.py +159 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/checks.py +374 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/cli.py +598 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/environment.py +323 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/fetch.py +576 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/handlers.py +555 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/harness.py +617 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/package.json +107 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/schemas/@jupyterlab-workshop/labextension/package.json.orig +102 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/schemas/@jupyterlab-workshop/labextension/panel.json +107 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/232.481d5c3b8e52db67.js +1195 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/270.87efb2259a5141d9.js +38 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/338.df6d26e0a8dc72bc.js +3 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/549.f1be8a4092f8420e.js +18 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/57.bb504983081811aa.js +1 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/remoteEntry.cad779096a460e70.js +1 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/style.js +4 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/third-party-licenses.json +34 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/lite.py +332 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/mcp.py +467 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/nodejs/workshop-cli.cjs +15888 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/platform.py +132 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/publish.py +155 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/py.typed +0 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/registry.py +263 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/scaffold.py +482 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/schema/registry.schema.json +78 -0
- jupyterlab_workshop-0.1.0/jupyterlab_workshop/schema/workshop.schema.json +223 -0
- jupyterlab_workshop-0.1.0/package.json +110 -0
- jupyterlab_workshop-0.1.0/pyproject.toml +146 -0
- jupyterlab_workshop-0.1.0/registry/index.json +71 -0
- jupyterlab_workshop-0.1.0/scripts/generate_manifest_reference.py +152 -0
- jupyterlab_workshop-0.1.0/skills/workshop-author/SKILL.md +304 -0
- jupyterlab_workshop-0.1.0/skills/workshop-author/references/actions.md +117 -0
- jupyterlab_workshop-0.1.0/skills/workshop-author/references/page-template.md +82 -0
- jupyterlab_workshop-0.1.0/skills/workshop-author/references/style-guide.md +93 -0
- jupyterlab_workshop-0.1.0/tsconfig.base.json +23 -0
- jupyterlab_workshop-0.1.0/uv.lock +2939 -0
- jupyterlab_workshop-0.1.0/yarn.lock +8939 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
scratch/
|
|
2
|
+
|
|
3
|
+
# JavaScript
|
|
4
|
+
node_modules/
|
|
5
|
+
.yarn/
|
|
6
|
+
*.bundle.*
|
|
7
|
+
*.log
|
|
8
|
+
*.tsbuildinfo
|
|
9
|
+
.eslintcache
|
|
10
|
+
.stylelintcache
|
|
11
|
+
packages/*/lib/
|
|
12
|
+
packages/core/coverage/
|
|
13
|
+
|
|
14
|
+
# Built labextension, Node CLI bundle, schema copy and generated version file
|
|
15
|
+
jupyterlab_workshop/labextension/
|
|
16
|
+
jupyterlab_workshop/nodejs/
|
|
17
|
+
jupyterlab_workshop/schema/
|
|
18
|
+
jupyterlab_workshop/_version.py
|
|
19
|
+
|
|
20
|
+
# Documentation build outputs and the assembled GitHub Pages site
|
|
21
|
+
docs/_build/
|
|
22
|
+
docs/reference/
|
|
23
|
+
site/
|
|
24
|
+
|
|
25
|
+
# Integration tests
|
|
26
|
+
tests/ui-tests/test-results/
|
|
27
|
+
tests/ui-tests/playwright-report/
|
|
28
|
+
|
|
29
|
+
# Python
|
|
30
|
+
.venv/
|
|
31
|
+
__pycache__/
|
|
32
|
+
*.py[cod]
|
|
33
|
+
*.egg-info/
|
|
34
|
+
build/
|
|
35
|
+
dist/
|
|
36
|
+
.pytest_cache/
|
|
37
|
+
.mypy_cache/
|
|
38
|
+
.ruff_cache/
|
|
39
|
+
.coverage
|
|
40
|
+
htmlcov/
|
|
41
|
+
.ipynb_checkpoints/
|
|
42
|
+
|
|
43
|
+
# Editors and OS
|
|
44
|
+
.DS_Store
|
|
45
|
+
|
|
46
|
+
# Files created by running the example workshops
|
|
47
|
+
examples/*/demo/
|
|
48
|
+
examples/*/_workshop/
|
|
49
|
+
examples/*/scratch/
|
|
50
|
+
|
|
51
|
+
# Workshops downloaded through the extension
|
|
52
|
+
workshops/
|
|
53
|
+
|
|
54
|
+
# JupyterLite site built by `just lite`
|
|
55
|
+
lite-site/
|
|
56
|
+
|
|
57
|
+
# JupyterLite build state written next to a build
|
|
58
|
+
.jupyterlite.doit.db
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
**/node_modules
|
|
3
|
+
**/lib
|
|
4
|
+
**/package.json
|
|
5
|
+
!/package.json
|
|
6
|
+
jupyterlab_workshop
|
|
7
|
+
eslint.config.mjs
|
|
8
|
+
.venv
|
|
9
|
+
scratch
|
|
10
|
+
tests/ui-tests/test-results
|
|
11
|
+
tests/ui-tests/playwright-report
|
|
12
|
+
site
|
|
13
|
+
lite-site
|
|
14
|
+
docs/_build
|
|
15
|
+
docs/reference
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Read the Docs build. The project itself is not installed (that would need
|
|
2
|
+
# Node.js to build the extension); only the docs dependency group is synced
|
|
3
|
+
# with uv, matching `just docs`.
|
|
4
|
+
version: 2
|
|
5
|
+
|
|
6
|
+
build:
|
|
7
|
+
os: ubuntu-24.04
|
|
8
|
+
tools:
|
|
9
|
+
python: "3.12"
|
|
10
|
+
commands:
|
|
11
|
+
- asdf plugin add uv
|
|
12
|
+
- asdf install uv latest
|
|
13
|
+
- asdf global uv latest
|
|
14
|
+
- uv sync --only-group docs --no-install-project
|
|
15
|
+
- uv run --no-sync sphinx-build -W --keep-going -b html docs $READTHEDOCS_OUTPUT/html
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Agent guidance for jupyterlab-workshop
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
jupyterlab-workshop is a JupyterLab extension for running guided,
|
|
6
|
+
interactive workshops inside JupyterLab. Workshop instructions are shown in
|
|
7
|
+
a side panel and contain clickable actions that drive the live JupyterLab
|
|
8
|
+
session: terminals, the file browser, the editor, notebooks, kernels and
|
|
9
|
+
layout. Workshops can verify learner progress, gate pages on that progress,
|
|
10
|
+
and include forms and quizzes. The concept comes from the Educates Training
|
|
11
|
+
Platform (educates.dev), re-imagined so that a single workshop runs wherever
|
|
12
|
+
JupyterLab runs, without Kubernetes or containers. See README.md for the
|
|
13
|
+
project goals.
|
|
14
|
+
|
|
15
|
+
A workshop is a directory containing a `workshop.yaml` manifest and
|
|
16
|
+
MyST-flavoured Markdown pages. The format is text based and git friendly.
|
|
17
|
+
|
|
18
|
+
The repository is a monorepo with three main parts:
|
|
19
|
+
|
|
20
|
+
- `packages/core/` is `@jupyterlab-workshop/core`, pure TypeScript with no
|
|
21
|
+
JupyterLab dependencies: workshop format parsing, action definitions,
|
|
22
|
+
variable substitution, lint rules and JSON schemas. Keep it free of
|
|
23
|
+
JupyterLab imports so the CLI and other tooling can reuse it under Node.
|
|
24
|
+
|
|
25
|
+
- `packages/labextension/` is `@jupyterlab-workshop/labextension`, the
|
|
26
|
+
JupyterLab frontend extension: instructions panel, renderer, action
|
|
27
|
+
implementations, verify engine, trust manager, loader and state.
|
|
28
|
+
|
|
29
|
+
- `jupyterlab_workshop/` is the Python package: the
|
|
30
|
+
`jupyter_server` extension (platform detection, fetching, script
|
|
31
|
+
verifies, checkpoints) and the `jupyter workshop` CLI.
|
|
32
|
+
|
|
33
|
+
README.md is the long description shown on PyPI, so it stays short and
|
|
34
|
+
user facing and links to the documentation site; development setup and
|
|
35
|
+
workflow belong in CONTRIBUTING.md, and the full documentation is under
|
|
36
|
+
`docs/` and published on Read the Docs.
|
|
37
|
+
|
|
38
|
+
Example workshops live in `examples/` and double as test fixtures. Tests
|
|
39
|
+
live in `tests/` (Python and Galata UI tests) and alongside the source in
|
|
40
|
+
`packages/core/`. See TESTING.md for where tests are, how to run them, and
|
|
41
|
+
conventions for adding new ones.
|
|
42
|
+
|
|
43
|
+
The scratch/ directory is not part of the git repo. It holds temporary
|
|
44
|
+
working files, such as reference material given to an agent or plans an
|
|
45
|
+
agent is asked to generate. Its contents come and go, so never reference
|
|
46
|
+
scratch/ files by name from code or documentation that will be committed.
|
|
47
|
+
|
|
48
|
+
## Tooling: always use uv and jlpm
|
|
49
|
+
|
|
50
|
+
All Python environment and package management in this project is done with
|
|
51
|
+
[uv](https://docs.astral.sh/uv/). Never use the Python venv module, bare
|
|
52
|
+
pip, or python -m build directly.
|
|
53
|
+
|
|
54
|
+
- Run commands in the project environment: `uv run <command>`
|
|
55
|
+
(e.g. `uv run pytest`, `uv run jupyter lab`)
|
|
56
|
+
|
|
57
|
+
- Run a Python interpreter: `uv run python`
|
|
58
|
+
|
|
59
|
+
- Build sdist and wheel: `uv build`
|
|
60
|
+
|
|
61
|
+
- Add or remove dependencies (updates pyproject.toml): `uv add <package>`,
|
|
62
|
+
`uv remove <package>`
|
|
63
|
+
|
|
64
|
+
- Sync the environment from pyproject.toml: `uv sync`
|
|
65
|
+
|
|
66
|
+
All JavaScript and TypeScript package management is done with `jlpm`, the
|
|
67
|
+
pinned Yarn that ships with JupyterLab. Never use npm or a system yarn
|
|
68
|
+
directly, and never commit a lockfile produced by them. jlpm is installed
|
|
69
|
+
into the project environment with JupyterLab, so run it as `uv run jlpm`.
|
|
70
|
+
|
|
71
|
+
- Install workspace dependencies: `uv run jlpm install`
|
|
72
|
+
|
|
73
|
+
- Add a dependency to one workspace package: run `uv run jlpm add <package>`
|
|
74
|
+
from inside that package's directory (for example `packages/core`)
|
|
75
|
+
|
|
76
|
+
- Build all packages: `uv run jlpm build`
|
|
77
|
+
|
|
78
|
+
## Common tasks: use the Justfile
|
|
79
|
+
|
|
80
|
+
The Justfile defines targets for the common development tasks, wrapping
|
|
81
|
+
the correct uv and jlpm invocations (including details like linking the
|
|
82
|
+
labextension into JupyterLab in development mode and running the Galata
|
|
83
|
+
tests against a live server). Prefer these targets over synthesizing the
|
|
84
|
+
underlying commands yourself; run `just --list` to see everything.
|
|
85
|
+
|
|
86
|
+
- `just install` sets up the development environment: syncs the Python
|
|
87
|
+
environment, installs JavaScript dependencies and links the extension
|
|
88
|
+
into JupyterLab in development mode.
|
|
89
|
+
|
|
90
|
+
- `just build` builds the TypeScript packages and the labextension bundle.
|
|
91
|
+
`just watch` rebuilds on change; run it alongside `just lab`.
|
|
92
|
+
|
|
93
|
+
- `just lab` starts JupyterLab from the repository root with the extension
|
|
94
|
+
loaded, so the example workshops are reachable through the contents API.
|
|
95
|
+
|
|
96
|
+
- `just test` runs the fast test suites: the Jest tests for `packages/core`
|
|
97
|
+
and the pytest suite for the Python package. Extra arguments pass
|
|
98
|
+
through to pytest, so a specific file or test is
|
|
99
|
+
`just test tests/python/test_fetch.py` or `just test -k pattern`.
|
|
100
|
+
|
|
101
|
+
- `just test-core` runs only the Jest tests; `just test-python` runs only
|
|
102
|
+
pytest; `just test-ui` runs the Galata browser tests against a real
|
|
103
|
+
JupyterLab (slow; run before finishing frontend work, not on every edit).
|
|
104
|
+
|
|
105
|
+
- `just lint` checks TypeScript with eslint and prettier and Python with
|
|
106
|
+
the ruff linter and formatter; `just format` reformats and applies
|
|
107
|
+
auto-fixes in both.
|
|
108
|
+
|
|
109
|
+
- `just typecheck` runs tsc for the TypeScript packages and mypy for
|
|
110
|
+
Python.
|
|
111
|
+
|
|
112
|
+
- `just docs` builds the documentation with Sphinx into `docs/_build/html`
|
|
113
|
+
(the pages are MyST Markdown under `docs/`, and the manifest reference is
|
|
114
|
+
generated from the JSON schema on every build); `just docs-serve` rebuilds
|
|
115
|
+
on change; `just docs-clean` clears a stale build after structural changes
|
|
116
|
+
such as renamed or removed pages.
|
|
117
|
+
|
|
118
|
+
- `just pages` assembles the GitHub Pages site into `site/`: the landing
|
|
119
|
+
page from `github-pages/`, the JSON schemas under `schemas/v1alpha1/`,
|
|
120
|
+
and the example workshop as a JupyterLite site under `demo/`.
|
|
121
|
+
|
|
122
|
+
- `just clean` removes build outputs only. `just distclean` also removes
|
|
123
|
+
`node_modules`, `.venv`, caches, built docs and sites, and files left
|
|
124
|
+
by running the examples, returning the tree to a fresh checkout; run
|
|
125
|
+
`just install` afterwards.
|
|
126
|
+
|
|
127
|
+
## Style
|
|
128
|
+
|
|
129
|
+
- Do not use emdashes in any files in this project. Rephrase with commas,
|
|
130
|
+
parentheses, colons, or separate sentences instead.
|
|
131
|
+
|
|
132
|
+
- In bulleted lists where items run to multiple lines, put a blank
|
|
133
|
+
line between the bullets: in docstrings, markdown files, and any
|
|
134
|
+
other prose. This is about the raw file being readable, not the
|
|
135
|
+
rendered form, which can look fine either way. Be consistent within
|
|
136
|
+
a list: if one item needs the spacing, space every item in that
|
|
137
|
+
list, never a mix.
|
|
138
|
+
|
|
139
|
+
- Python code must always use type hints. Add them to all function
|
|
140
|
+
and method signatures (parameters and return types), and to attributes
|
|
141
|
+
and variables where the type is not obvious from the assignment. When
|
|
142
|
+
adding or modifying code that lacks type hints, add them.
|
|
143
|
+
|
|
144
|
+
- TypeScript code must be explicitly typed at its boundaries: every
|
|
145
|
+
exported function, method, class member and module-level constant has
|
|
146
|
+
an explicit type or return type. Never use `any`; use `unknown` and
|
|
147
|
+
narrow it. Do not disable strict compiler options.
|
|
148
|
+
|
|
149
|
+
- Use vertical white space liberally inside function and method bodies,
|
|
150
|
+
in both Python and TypeScript. Write code in paragraphs: group the
|
|
151
|
+
statements that together perform one step, and separate each group
|
|
152
|
+
from the next with a blank line. Natural paragraph boundaries include
|
|
153
|
+
setup versus the main work versus the result, before and after a
|
|
154
|
+
conditional or loop, and around a with or try block. Do not cram a body
|
|
155
|
+
into one contiguous blob, and equally do not put a blank line between
|
|
156
|
+
every single statement; the blank lines should mark where one thought
|
|
157
|
+
ends and the next begins.
|
|
158
|
+
|
|
159
|
+
- Where it helps the reader, start a paragraph of code with a short
|
|
160
|
+
comment saying what that step does or why it is needed. Prefer one
|
|
161
|
+
comment per logical block over line-by-line commentary, and skip the
|
|
162
|
+
comment entirely when the code already says it plainly.
|
|
163
|
+
|
|
164
|
+
- Put a blank line between such a block comment and the code below it:
|
|
165
|
+
the comment introduces the paragraph rather than sitting flush against
|
|
166
|
+
its first line.
|
|
167
|
+
|
|
168
|
+
- Put a blank line between a function or method docstring and the first
|
|
169
|
+
line of code in the body.
|
|
170
|
+
|
|
171
|
+
- Every function, method or property that is part of the public API must
|
|
172
|
+
have a docstring (Python) or a TSDoc comment (TypeScript) saying what it
|
|
173
|
+
does. The exceptions are cases that are truly trivial and obvious, such
|
|
174
|
+
as an accessor property named for the attribute it returns, and dunder
|
|
175
|
+
methods implementing standard protocols.
|
|
176
|
+
|
|
177
|
+
- Every directive, action type or option added to the workshop format must
|
|
178
|
+
be reflected in the JSON schema, the lint rules and the format
|
|
179
|
+
documentation in the same change.
|
|
180
|
+
|
|
181
|
+
- Verify JupyterLab API names against the installed version's TypeScript
|
|
182
|
+
definitions (under `node_modules/@jupyterlab/*/lib/`) before using them.
|
|
183
|
+
Use only public tokens and APIs.
|
|
184
|
+
|
|
185
|
+
## Git
|
|
186
|
+
|
|
187
|
+
- Git commit messages must never include a co-authored-by agent message or
|
|
188
|
+
any similar agent attribution trailer.
|
|
189
|
+
|
|
190
|
+
- An AI agent must never commit changes on its own initiative. Finish the
|
|
191
|
+
piece of work, summarize it, and wait to be told to commit. Permission to
|
|
192
|
+
commit applies only to the work it was given for; it does not carry
|
|
193
|
+
forward to later steps of a multi-step plan, each of which needs its own
|
|
194
|
+
review and its own instruction to commit. Uncommitted changes are how the
|
|
195
|
+
review happens: once work is committed it can no longer be reviewed as
|
|
196
|
+
the pending diff, so committing early makes review harder, not easier.
|
|
197
|
+
|
|
198
|
+
- When merging a feature branch back to main and pushing to the remote,
|
|
199
|
+
do not treat the work as landed until the CI workflow on GitHub has run
|
|
200
|
+
against the pushed merge and passed. Check the run (for example with
|
|
201
|
+
`gh run list --branch main` and `gh run watch`), and only once it is
|
|
202
|
+
green report that the changes are on the remote and clean up the feature
|
|
203
|
+
branch. If CI fails, leave the feature branch in place, report the
|
|
204
|
+
failure, and wait for instructions rather than deleting anything.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Development setup and workflow for jupyterlab-workshop. The user-facing
|
|
4
|
+
documentation is under `docs/` and published at
|
|
5
|
+
<https://jupyterlab-workshop.readthedocs.io/>; this file is about working
|
|
6
|
+
on the project itself.
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
Requires [uv](https://docs.astral.sh/uv/), [just](https://just.systems/),
|
|
11
|
+
Node.js and git.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
just install
|
|
15
|
+
just lab
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`just install` creates the Python environment, installs the JavaScript
|
|
19
|
+
workspace, builds the extension and links it into JupyterLab in
|
|
20
|
+
development mode. `just lab` starts JupyterLab with the repository root
|
|
21
|
+
as its root directory, which is where the example workshops live. Open
|
|
22
|
+
the Workshop panel in the right sidebar (the `panelSide` setting, or
|
|
23
|
+
dragging the tab, moves it to the left).
|
|
24
|
+
|
|
25
|
+
To rebuild while editing the TypeScript, run `just watch` in a second
|
|
26
|
+
terminal and refresh the browser after each rebuild. `just --list` shows
|
|
27
|
+
every task.
|
|
28
|
+
|
|
29
|
+
## Layout
|
|
30
|
+
|
|
31
|
+
- `packages/core/` is `@jupyterlab-workshop/core`, pure TypeScript with no
|
|
32
|
+
JupyterLab dependencies: the workshop format, actions, variables, lint
|
|
33
|
+
rules and JSON schemas.
|
|
34
|
+
|
|
35
|
+
- `packages/labextension/` is `@jupyterlab-workshop/labextension`, the
|
|
36
|
+
JupyterLab frontend extension.
|
|
37
|
+
|
|
38
|
+
- `jupyterlab_workshop/` is the Python package: the `jupyter_server`
|
|
39
|
+
extension and the `jupyter workshop` command line.
|
|
40
|
+
|
|
41
|
+
- `examples/` holds the example workshops, which double as test fixtures.
|
|
42
|
+
|
|
43
|
+
- `docs/` is the Sphinx documentation and `github-pages/` the landing page
|
|
44
|
+
of the project site.
|
|
45
|
+
|
|
46
|
+
## Checks and tests
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
just lint
|
|
50
|
+
just typecheck
|
|
51
|
+
just test
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`just test` runs the Jest tests for `packages/core` and the pytest suite.
|
|
55
|
+
`just test-ui` runs the Galata browser tests against a real JupyterLab,
|
|
56
|
+
`just selftest` runs every action of the example workshops in JupyterLab,
|
|
57
|
+
and `just selftest-lite` does the same in a JupyterLite build. See
|
|
58
|
+
TESTING.md for where the tests live and how to add more.
|
|
59
|
+
|
|
60
|
+
Python is managed with uv and JavaScript with `jlpm`, the Yarn that ships
|
|
61
|
+
with JupyterLab, run as `uv run jlpm`. Do not use pip, npm or a system
|
|
62
|
+
yarn directly. AGENTS.md records the coding conventions the project
|
|
63
|
+
follows.
|
|
64
|
+
|
|
65
|
+
## Documentation and the project site
|
|
66
|
+
|
|
67
|
+
`just docs` builds the documentation into `docs/_build/html`, and
|
|
68
|
+
`just docs-serve` rebuilds it on change. The manifest reference page is
|
|
69
|
+
generated from the JSON schema on every build.
|
|
70
|
+
|
|
71
|
+
`just pages` assembles the GitHub Pages site into `site/`: the landing
|
|
72
|
+
page, the JSON schemas and the example workshop built as a JupyterLite
|
|
73
|
+
site under `demo/`. Building the JupyterLite terminal needs `node`, `npm`
|
|
74
|
+
and `micromamba` on the path; pass `--no-terminal` to leave it out.
|
|
75
|
+
|
|
76
|
+
## Releases
|
|
77
|
+
|
|
78
|
+
The version is read from the root `package.json` by the Python build, so
|
|
79
|
+
bump it there and in the two workspace `package.json` files together.
|
|
80
|
+
Releases are made by pushing a tag that is the bare version string, such
|
|
81
|
+
as `0.1.0`, with no `v` prefix. The release workflow refuses to build if
|
|
82
|
+
the tag does not match the version in `package.json`, then builds the
|
|
83
|
+
wheel and sdist, attaches them to a GitHub release and publishes to PyPI.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Development tasks for jupyterlab-workshop.
|
|
2
|
+
#
|
|
3
|
+
# Python is managed with uv, JavaScript with jlpm (the Yarn that ships with
|
|
4
|
+
# JupyterLab, installed into the project environment). Run `just --list`
|
|
5
|
+
# to see the available targets.
|
|
6
|
+
|
|
7
|
+
set positional-arguments
|
|
8
|
+
|
|
9
|
+
# List the available targets.
|
|
10
|
+
default:
|
|
11
|
+
@just --list
|
|
12
|
+
|
|
13
|
+
# Set up the development environment and link the extension into JupyterLab.
|
|
14
|
+
install:
|
|
15
|
+
uv sync --no-install-project
|
|
16
|
+
uv run --no-sync jlpm install
|
|
17
|
+
uv run --no-sync jlpm build
|
|
18
|
+
uv sync
|
|
19
|
+
uv run jupyter labextension develop . --overwrite
|
|
20
|
+
uv run jupyter server extension enable jupyterlab_workshop
|
|
21
|
+
|
|
22
|
+
# Build the TypeScript packages and the labextension bundle.
|
|
23
|
+
build:
|
|
24
|
+
uv run jlpm build
|
|
25
|
+
|
|
26
|
+
# Rebuild the TypeScript packages and labextension on change (run alongside `just lab`).
|
|
27
|
+
watch:
|
|
28
|
+
uv run jlpm watch
|
|
29
|
+
|
|
30
|
+
# Start JupyterLab from the repository root with the extension loaded.
|
|
31
|
+
lab *args:
|
|
32
|
+
uv run jupyter lab --notebook-dir=. "$@"
|
|
33
|
+
|
|
34
|
+
# Run the fast test suites: Jest for packages/core and pytest for the Python package.
|
|
35
|
+
test *args:
|
|
36
|
+
uv run jlpm test
|
|
37
|
+
uv run pytest "$@"
|
|
38
|
+
|
|
39
|
+
# Run only the Jest tests for packages/core.
|
|
40
|
+
test-core *args:
|
|
41
|
+
uv run jlpm test "$@"
|
|
42
|
+
|
|
43
|
+
# Run only the pytest suite for the Python package.
|
|
44
|
+
test-python *args:
|
|
45
|
+
uv run pytest "$@"
|
|
46
|
+
|
|
47
|
+
# Run the Galata browser tests against a real JupyterLab on port 8890 (slow).
|
|
48
|
+
test-ui *args:
|
|
49
|
+
cd tests/ui-tests && uv run jlpm install && JUPYTER_PORT=8890 uv run jlpm playwright test "$@"
|
|
50
|
+
|
|
51
|
+
# Check TypeScript with eslint and prettier, and Python with ruff.
|
|
52
|
+
lint:
|
|
53
|
+
uv run jlpm lint:check
|
|
54
|
+
uv run ruff check .
|
|
55
|
+
uv run ruff format --check .
|
|
56
|
+
|
|
57
|
+
# Reformat and apply auto-fixes for TypeScript and Python.
|
|
58
|
+
format:
|
|
59
|
+
uv run jlpm lint
|
|
60
|
+
uv run ruff check --fix .
|
|
61
|
+
uv run ruff format .
|
|
62
|
+
|
|
63
|
+
# Type check the TypeScript packages with tsc and the Python package with mypy.
|
|
64
|
+
typecheck:
|
|
65
|
+
uv run jlpm typecheck
|
|
66
|
+
uv run mypy
|
|
67
|
+
|
|
68
|
+
# Build the documentation with Sphinx into docs/_build/html (generates the manifest reference first).
|
|
69
|
+
docs:
|
|
70
|
+
uv run sphinx-build -W --keep-going -b html docs docs/_build/html
|
|
71
|
+
|
|
72
|
+
# Serve the documentation with live reload.
|
|
73
|
+
docs-serve:
|
|
74
|
+
uv run sphinx-autobuild docs docs/_build/html
|
|
75
|
+
|
|
76
|
+
# Clear generated documentation outputs.
|
|
77
|
+
docs-clean:
|
|
78
|
+
rm -rf docs/_build docs/reference
|
|
79
|
+
|
|
80
|
+
# Assemble the GitHub Pages site into site/: landing page, JSON schemas and the JupyterLite demo.
|
|
81
|
+
pages *args:
|
|
82
|
+
rm -rf site
|
|
83
|
+
mkdir -p site/schemas/v1alpha1
|
|
84
|
+
cp github-pages/index.html site/index.html
|
|
85
|
+
touch site/.nojekyll
|
|
86
|
+
cp packages/core/src/schema/workshop.schema.json packages/core/src/schema/registry.schema.json site/schemas/v1alpha1/
|
|
87
|
+
uv run jupyter workshop lite examples/hello-jupyterlab --out site/demo "$@"
|
|
88
|
+
|
|
89
|
+
# Self-test a workshop directory in a real JupyterLab (default: every example).
|
|
90
|
+
selftest *args:
|
|
91
|
+
#!/usr/bin/env bash
|
|
92
|
+
set -euo pipefail
|
|
93
|
+
if [ "$#" -eq 0 ]; then set -- examples/git-basics examples/hello-jupyterlab examples/workshop-authoring; fi
|
|
94
|
+
for dir in "$@"; do uv run jupyter workshop test "$dir"; done
|
|
95
|
+
|
|
96
|
+
# Self-test a workshop in a static JupyterLite build (default: hello-jupyterlab).
|
|
97
|
+
selftest-lite *args:
|
|
98
|
+
#!/usr/bin/env bash
|
|
99
|
+
set -euo pipefail
|
|
100
|
+
if [ "$#" -eq 0 ]; then set -- examples/hello-jupyterlab; fi
|
|
101
|
+
for dir in "$@"; do uv run jupyter workshop test "$dir" --lite; done
|
|
102
|
+
|
|
103
|
+
# Build a JupyterLite site with the example workshop into lite-site/ and serve it.
|
|
104
|
+
lite *args:
|
|
105
|
+
uv run jupyter workshop lite examples/hello-jupyterlab --out lite-site --serve "$@"
|
|
106
|
+
|
|
107
|
+
# Remove build outputs (compiled TypeScript, the labextension bundle, lint caches).
|
|
108
|
+
clean:
|
|
109
|
+
uv run jlpm clean
|
|
110
|
+
uv run jlpm clean:lintcache
|
|
111
|
+
|
|
112
|
+
# Return to a fresh checkout: also removes node_modules, .venv, caches, built docs and sites.
|
|
113
|
+
distclean:
|
|
114
|
+
rm -rf packages/core/lib packages/labextension/lib packages/*/tsconfig.tsbuildinfo
|
|
115
|
+
rm -rf jupyterlab_workshop/labextension jupyterlab_workshop/nodejs jupyterlab_workshop/schema
|
|
116
|
+
rm -rf .eslintcache .stylelintcache packages/core/coverage
|
|
117
|
+
rm -rf node_modules packages/*/node_modules tests/ui-tests/node_modules .venv
|
|
118
|
+
rm -rf site docs/_build docs/reference build dist lite-site .jupyterlite.doit.db .coverage htmlcov
|
|
119
|
+
rm -rf tests/ui-tests/test-results tests/ui-tests/playwright-report
|
|
120
|
+
rm -rf examples/*/_workshop examples/*/scratch examples/*/demo workshops
|
|
121
|
+
find . -type d \( -name __pycache__ -o -name .ipynb_checkpoints -o -name '*.egg-info' -o -name .yarn -o -name .mypy_cache -o -name .ruff_cache -o -name .pytest_cache \) -prune -exec rm -rf {} +
|