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.
Files changed (101) hide show
  1. jupyterlab_workshop-0.1.0/.gitignore +58 -0
  2. jupyterlab_workshop-0.1.0/.prettierignore +15 -0
  3. jupyterlab_workshop-0.1.0/.python-version +1 -0
  4. jupyterlab_workshop-0.1.0/.readthedocs.yaml +15 -0
  5. jupyterlab_workshop-0.1.0/.yarnrc.yml +2 -0
  6. jupyterlab_workshop-0.1.0/AGENTS.md +204 -0
  7. jupyterlab_workshop-0.1.0/CLAUDE.md +1 -0
  8. jupyterlab_workshop-0.1.0/CONTRIBUTING.md +83 -0
  9. jupyterlab_workshop-0.1.0/Justfile +121 -0
  10. jupyterlab_workshop-0.1.0/LICENSE +202 -0
  11. jupyterlab_workshop-0.1.0/PKG-INFO +105 -0
  12. jupyterlab_workshop-0.1.0/README.md +70 -0
  13. jupyterlab_workshop-0.1.0/TESTING.md +95 -0
  14. jupyterlab_workshop-0.1.0/binder/postBuild +19 -0
  15. jupyterlab_workshop-0.1.0/binder/requirements.txt +5 -0
  16. jupyterlab_workshop-0.1.0/docs/actions.md +117 -0
  17. jupyterlab_workshop-0.1.0/docs/analytics.md +81 -0
  18. jupyterlab_workshop-0.1.0/docs/authoring.md +125 -0
  19. jupyterlab_workshop-0.1.0/docs/checks.md +199 -0
  20. jupyterlab_workshop-0.1.0/docs/cli.md +180 -0
  21. jupyterlab_workshop-0.1.0/docs/conf.py +40 -0
  22. jupyterlab_workshop-0.1.0/docs/demo.md +76 -0
  23. jupyterlab_workshop-0.1.0/docs/environment.md +73 -0
  24. jupyterlab_workshop-0.1.0/docs/index.md +133 -0
  25. jupyterlab_workshop-0.1.0/docs/lite.md +109 -0
  26. jupyterlab_workshop-0.1.0/docs/platforms.md +117 -0
  27. jupyterlab_workshop-0.1.0/docs/registry.md +161 -0
  28. jupyterlab_workshop-0.1.0/docs/trust.md +165 -0
  29. jupyterlab_workshop-0.1.0/eslint.config.mjs +70 -0
  30. jupyterlab_workshop-0.1.0/examples/git-basics/README.md +8 -0
  31. jupyterlab_workshop-0.1.0/examples/git-basics/pages/01-create-a-repository.md +73 -0
  32. jupyterlab_workshop-0.1.0/examples/git-basics/pages/02-first-commit.md +103 -0
  33. jupyterlab_workshop-0.1.0/examples/git-basics/pages/03-edit-and-diff.md +65 -0
  34. jupyterlab_workshop-0.1.0/examples/git-basics/pages/04-branch-and-merge.md +75 -0
  35. jupyterlab_workshop-0.1.0/examples/git-basics/pages/05-resolve-a-conflict.md +139 -0
  36. jupyterlab_workshop-0.1.0/examples/git-basics/verify/merged.py +22 -0
  37. jupyterlab_workshop-0.1.0/examples/git-basics/workshop.yaml +39 -0
  38. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/README.md +8 -0
  39. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/files/notes.md +3 -0
  40. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/01-welcome.md +57 -0
  41. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/02-notebooks.md +71 -0
  42. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/03-kernels.md +49 -0
  43. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/04-files.md +53 -0
  44. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/05-variables.md +57 -0
  45. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/06-conda.md +16 -0
  46. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/06-pip.md +17 -0
  47. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/07-automation.md +46 -0
  48. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/pages/08-finish.md +18 -0
  49. jupyterlab_workshop-0.1.0/examples/hello-jupyterlab/workshop.yaml +41 -0
  50. jupyterlab_workshop-0.1.0/examples/workshop-authoring/.gitignore +5 -0
  51. jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/01-what-a-workshop-is.md +52 -0
  52. jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/02-scaffold.md +62 -0
  53. jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/03-write-a-page.md +81 -0
  54. jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/04-lint.md +115 -0
  55. jupyterlab_workshop-0.1.0/examples/workshop-authoring/pages/05-test-and-publish.md +64 -0
  56. jupyterlab_workshop-0.1.0/examples/workshop-authoring/workshop.yaml +34 -0
  57. jupyterlab_workshop-0.1.0/github-pages/index.html +136 -0
  58. jupyterlab_workshop-0.1.0/install.json +5 -0
  59. jupyterlab_workshop-0.1.0/jupyter-config/server-config/jupyterlab_workshop.json +7 -0
  60. jupyterlab_workshop-0.1.0/jupyterlab_workshop/__init__.py +37 -0
  61. jupyterlab_workshop-0.1.0/jupyterlab_workshop/_version.py +4 -0
  62. jupyterlab_workshop-0.1.0/jupyterlab_workshop/analytics.py +130 -0
  63. jupyterlab_workshop-0.1.0/jupyterlab_workshop/bridge.py +159 -0
  64. jupyterlab_workshop-0.1.0/jupyterlab_workshop/checks.py +374 -0
  65. jupyterlab_workshop-0.1.0/jupyterlab_workshop/cli.py +598 -0
  66. jupyterlab_workshop-0.1.0/jupyterlab_workshop/environment.py +323 -0
  67. jupyterlab_workshop-0.1.0/jupyterlab_workshop/fetch.py +576 -0
  68. jupyterlab_workshop-0.1.0/jupyterlab_workshop/handlers.py +555 -0
  69. jupyterlab_workshop-0.1.0/jupyterlab_workshop/harness.py +617 -0
  70. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/package.json +107 -0
  71. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/schemas/@jupyterlab-workshop/labextension/package.json.orig +102 -0
  72. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/schemas/@jupyterlab-workshop/labextension/panel.json +107 -0
  73. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/232.481d5c3b8e52db67.js +1195 -0
  74. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/270.87efb2259a5141d9.js +38 -0
  75. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/338.df6d26e0a8dc72bc.js +3 -0
  76. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/549.f1be8a4092f8420e.js +18 -0
  77. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/57.bb504983081811aa.js +1 -0
  78. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/remoteEntry.cad779096a460e70.js +1 -0
  79. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/style.js +4 -0
  80. jupyterlab_workshop-0.1.0/jupyterlab_workshop/labextension/static/third-party-licenses.json +34 -0
  81. jupyterlab_workshop-0.1.0/jupyterlab_workshop/lite.py +332 -0
  82. jupyterlab_workshop-0.1.0/jupyterlab_workshop/mcp.py +467 -0
  83. jupyterlab_workshop-0.1.0/jupyterlab_workshop/nodejs/workshop-cli.cjs +15888 -0
  84. jupyterlab_workshop-0.1.0/jupyterlab_workshop/platform.py +132 -0
  85. jupyterlab_workshop-0.1.0/jupyterlab_workshop/publish.py +155 -0
  86. jupyterlab_workshop-0.1.0/jupyterlab_workshop/py.typed +0 -0
  87. jupyterlab_workshop-0.1.0/jupyterlab_workshop/registry.py +263 -0
  88. jupyterlab_workshop-0.1.0/jupyterlab_workshop/scaffold.py +482 -0
  89. jupyterlab_workshop-0.1.0/jupyterlab_workshop/schema/registry.schema.json +78 -0
  90. jupyterlab_workshop-0.1.0/jupyterlab_workshop/schema/workshop.schema.json +223 -0
  91. jupyterlab_workshop-0.1.0/package.json +110 -0
  92. jupyterlab_workshop-0.1.0/pyproject.toml +146 -0
  93. jupyterlab_workshop-0.1.0/registry/index.json +71 -0
  94. jupyterlab_workshop-0.1.0/scripts/generate_manifest_reference.py +152 -0
  95. jupyterlab_workshop-0.1.0/skills/workshop-author/SKILL.md +304 -0
  96. jupyterlab_workshop-0.1.0/skills/workshop-author/references/actions.md +117 -0
  97. jupyterlab_workshop-0.1.0/skills/workshop-author/references/page-template.md +82 -0
  98. jupyterlab_workshop-0.1.0/skills/workshop-author/references/style-guide.md +93 -0
  99. jupyterlab_workshop-0.1.0/tsconfig.base.json +23 -0
  100. jupyterlab_workshop-0.1.0/uv.lock +2939 -0
  101. 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,2 @@
1
+ nodeLinker: node-modules
2
+ enableScripts: false
@@ -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 {} +