Skip to content

feat(notebooks): optional Docker launcher for Python notebook series#79

Merged
nicolotognoni merged 5 commits into
mainfrom
feat/notebook-docker-launcher
May 1, 2026
Merged

feat(notebooks): optional Docker launcher for Python notebook series#79
nicolotognoni merged 5 commits into
mainfrom
feat/notebook-docker-launcher

Conversation

@FrancescoRosciano
Copy link
Copy Markdown
Collaborator

Summary

  • New examples/notebooks/python/Dockerfile + docker-compose.yml build a Python 3.13-slim image with getpatter (pinned via PATTER_VERSION, default 0.5.4), JupyterLab, and the helper deps from pyproject.toml. Compose mounts the parent examples/notebooks/ tree at /notebooks so _setup.py still finds .env and fixtures/; ports 8888 (Lab) and 8765 (EmbeddedServer for T2/T4 cells) are published. env_file is marked required: false so §1 zero-key cells just work.
  • _setup.py gains in_docker() (checks PATTER_NOTEBOOKS_IN_DOCKER=1 and /.dockerenv) and start_docker(*, build, detach, open_url) which shells out to docker compose up -d --build from the notebooks dir; no-ops when already inside the container or when the docker CLI is missing.
  • All 12 Python notebooks get an optional markdown + commented code cell at the top — Run All on a fresh checkout still behaves identically because the launcher is commented by default.

Test plan

  • cd examples/notebooks/python && docker compose config parses without warnings
  • docker compose up --build opens JupyterLab at http://localhost:8888/lab/tree/01_quickstart.ipynb
  • Run All on 01_quickstart.ipynb inside the container — §1 cells pass with zero keys
  • On the host, uncomment _setup.start_docker() in cell 1 of any notebook → container starts, URL printed
  • _setup.in_docker() returns True inside the container, False on host
  • nbstripout still strips outputs cleanly across all 12 notebooks

Adds a scoped Dockerfile + docker-compose.yml under
examples/notebooks/python/ that build JupyterLab on Python 3.13 with
getpatter (pinned via PATTER_VERSION) and the helper deps. _setup.py
gains in_docker() and start_docker() so any notebook can spin the stack
up from a single cell; the launcher is commented by default in all 12
Python notebooks, keeping host-Python Run All behaviour unchanged.
@mintlify
Copy link
Copy Markdown

mintlify Bot commented Apr 28, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
patter-06b046ce 🟢 Ready View Preview Apr 28, 2026, 10:30 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

- docker-compose: bind ports loopback-only (127.0.0.1) so Lab never reaches
  the LAN; pass JUPYTER_TOKEN through to the container.
- Dockerfile: drop --allow-root, run as patter (UID 1000 by default, override
  via PUID/PGID), install pinned deps from requirements.txt.
- _setup.start_docker: returns bool, captures and prints stderr on compose
  failure, refuses detach=False, generates a stable per-host JUPYTER_TOKEN
  (PATTER_NOTEBOOKS_NO_TOKEN=1 to opt out), accepts truthy variants for
  PATTER_NOTEBOOKS_IN_DOCKER.
- New requirements.txt with pinned top-level deps.
- New tests/test_docker_bootstrap.py — 19 unit tests covering env parsing,
  every start_docker early-return, argv assembly, token persistence.
- _setup module docstring acknowledges the TS-side parity gap on the Docker
  helpers (tracking issue to follow).
@FrancescoRosciano
Copy link
Copy Markdown
Collaborator Author

Review fixes pushed (f9a9efb)

Multi-agent review completed (Python style, security, project conventions, SDK parity, silent-failure hunt). Per request, all MEDIUM findings escalated and fixed alongside the HIGH ones.

HIGH — fixed

  • Loopback-only port maps127.0.0.1:8888:8888 and 127.0.0.1:8765:8765 in docker-compose.yml. JupyterLab is no longer LAN-reachable.
  • Auth token by default_setup._generate_jupyter_token() writes a 32-byte URL-safe secret to ~/.config/patter-notebooks/jupyter_token (mode 0o600) on first call and reuses it. Injected via JUPYTER_TOKEN env var; the Dockerfile CMD reads it from env. PATTER_NOTEBOOKS_NO_TOKEN=1 is the explicit opt-out.
  • start_docker() -> bool — every early-return now returns False so callers can branch. subprocess.run(check=False, capture_output=True) surfaces stdout/stderr on compose failure instead of swallowing them.
  • TS parity_setup.py module docstring acknowledges the gap; tracking issue notebooks: port Docker launcher to TypeScript notebook series #80 filed.

MEDIUM (escalated → fixed)

  • Non-root container — Dockerfile creates patter (UID 1000 default, override via PUID/PGID build args), drops --allow-root.
  • Pinned deps — new requirements.txt with exact versions; Dockerfile installs from it.
  • Version driftPATTER_VERSION is now a build arg consumed from a single line in requirements.txt; release process should update both. Documented in DEVLOG.
  • detach=False guard — refuses to launch (would hang the kernel) and returns False with a banner.

LOW — fixed

  • in_docker() accepts 1/true/yes/on (case-insensitive).
  • webbrowser and secrets hoisted to top-of-file imports.
  • New tests/test_docker_bootstrap.py — 19 unit tests covering env parsing, every start_docker() early-return, command argv assembly, and token persistence. All green.

Open follow-up

@FrancescoRosciano
Copy link
Copy Markdown
Collaborator Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Resolves the PEP 8 E402 warning IDEs surface on this file. Late imports
(contextlib, time, traceback, typing.Iterable/Iterator, re) pre-dated PR
\#79 — they came in with the original notebook skeleton — but the partial
hoist of `webbrowser` made the inconsistency more visible. Moving them
all to the top in one go keeps the file cleanly PEP 8-compliant. No
behaviour change.
Three CI gates were red on PR #79:
- Pre-commit / fix-end-of-files: trailing blank lines in
  docs/superpowers/plans/2026-04-24-patter-feature-test-notebook-implementation.md
- Pre-commit / nbstripout: cell IDs, outputs, and \\u-escaped unicode
  not normalized across all 24 .ipynb files in examples/notebooks/.
- notebooks/parity: Python notebooks gained `## Optional: run in Docker`
  in 5cad9f6 but TypeScript siblings did not, breaking the section-by-
  section parity contract enforced by scripts/check_notebook_parity.py.

Fixes:
- nbstripout 0.7.1 canonicalisation across all 24 notebooks (sequential
  string IDs, unicode normalisation, no outputs/execution_count).
- EOF trim on the plans markdown.
- Added matching `## Optional: run in Docker` markdown + commented-out
  TS launcher cell to all 12 TypeScript notebooks. The `_setup.ts`
  helpers (`inDocker`, `startDocker`) are still pending per issue #80;
  the cells are commented so behaviour is unchanged.

New tool — scripts/pr-validate.sh — runs every PR-blocking CI check
locally before opening a PR, mirroring .github/workflows/{test,notebooks}.yml.
Modes: --quick (~30 s), default (~3-5 min), --full (~10 min). Selective
skips: --skip-py, --skip-ts, --skip-notebooks. Documented escape hatches
for memory-constrained / hardened-macOS local environments
(PR_VALIDATE_SKIP_GITLEAKS, PR_VALIDATE_SKIP_NBSTRIPOUT) — CI runs the
full pre-commit unaltered.

Verified locally: pre-commit + parity + outputs-stripped all green.
@nicolotognoni nicolotognoni merged commit 6c84374 into main May 1, 2026
16 checks passed
nicolotognoni added a commit that referenced this pull request May 1, 2026
PR #79 added an optional Docker launcher under examples/notebooks/python/ and re-touched all 24 .ipynb files (kernel ID renumbering, source-array reshape).

Resolution:
- examples/notebooks/python/**.ipynb + examples/notebooks/typescript/**.ipynb: take the main version. Our only prior contribution to these files was the nbstripout pass, which is now re-applied via pre-commit (no behaviour or content of ours is lost).
- docs/DEVLOG.md + docs/superpowers/plans/2026-04-24-...md: keep deletion. Both were removed from this branch as out-of-scope for the public docs site; no merge-back.
@github-actions github-actions Bot deleted the feat/notebook-docker-launcher branch May 1, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants