From 57186de4831c7d47477a78247e162d9dccab3792 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:29:06 +0000 Subject: [PATCH 01/14] Bump Jupyter Book dependency to v2 Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 37dfeb44..640a9813 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,6 +39,6 @@ nbconvert[webpdf]>=7.16.6 nbdime pytest -jupyter-book==1.* +jupyter-book==2.* # https://github.com/sphinx-doc/sphinx/issues/10440#issuecomment-1556180835 sphinx>=6.2.0 From 9fd5d46feb8af4f67f548a7a1ef1887926d4d5c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:35:07 +0000 Subject: [PATCH 02/14] Migrate build config to Jupyter Book 2 Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- .readthedocs.yaml | 20 +++---- Makefile | 2 +- meta/instructor_guide.md | 2 +- myst.yml | 110 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 myst.yml diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 208d7528..226afa5e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -6,16 +6,12 @@ python: - requirements: requirements.txt build: - os: ubuntu-lts-latest + os: ubuntu-22.04 tools: - python: "3" - jobs: - # https://jupyterbook.org/en/stable/publish/readthedocs.html - pre_build: - - jupyter-book config sphinx . - post_build: - - make fix_double_escaping build_dir="$READTHEDOCS_OUTPUT" - -sphinx: - # https://about.readthedocs.com/blog/2024/12/deprecate-config-files-without-sphinx-or-mkdocs-config/ - configuration: conf.py + python: "3.12" + nodejs: "22" + commands: + - jupyter-book build --html + - mkdir -p $READTHEDOCS_OUTPUT/html/ + - cp -r _build/html/. "$READTHEDOCS_OUTPUT/html" + - make fix_double_escaping build_dir="$READTHEDOCS_OUTPUT" diff --git a/Makefile b/Makefile index 310bfb6d..ff6c3c96 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ format: # https://jupyterbook.org/en/stable/content/references.html#check-for-missing-references site: - jupyter-book build --all -W -n --keep-going . + jupyter-book build --html --all --ci setup: python -m venv .venv diff --git a/meta/instructor_guide.md b/meta/instructor_guide.md index e9af36f6..49095693 100644 --- a/meta/instructor_guide.md +++ b/meta/instructor_guide.md @@ -23,7 +23,7 @@ make slides lec=N ## Site -The site is generated using [JupyterBook](https://jupyterbook.org/) and deployed to [ReadTheDocs](https://readthedocs.org/). Markdown (`.md`) files and the files and folders that start with an underscore (`_`) are related to JupyterBook. +The site is generated using [JupyterBook](https://jupyterbook.org/) and deployed to [ReadTheDocs](https://readthedocs.org/). Markdown (`.md`) files, [`myst.yml`](../myst.yml), and files and folders that start with an underscore (`_`) are related to JupyterBook. ### Publishing diff --git a/myst.yml b/myst.yml new file mode 100644 index 00000000..94424e9f --- /dev/null +++ b/myst.yml @@ -0,0 +1,110 @@ +version: 1 +project: + id: f6e67d86-5ff0-4f42-ab5a-a421c82f8f9e + title: "{{course_name}} @ {{school_name}}" + authors: + - name: Aidan Feldman + exclude: + - .github/* + - .pytest_cache/* + - tmp/* + github: afeld/python-public-policy + toc: + - file: home.md + - file: index + title: Homepage + - file: syllabus + children: + - file: registration + - file: joining_late + - file: exam + {% if id == "columbia" -%} + - file: curve + {%- endif %} + - file: resources + children: + - file: brackets + title: Brackets + - url: "{{lms_url}}" + title: "{{lms_name}}" + - url: "{{discussions_url}}" + title: Ed Discussion + - url: https://colab.research.google.com + title: Google Colab + - url: "{{submission_tool_url}}" + title: Gradescope + - file: lectures + children: + - file: lecture_0 + - file: lecture_1 + children: + - file: lecture_1_exercise + title: In-class exercise + - file: lecture_1_exercise_solution + title: In-class exercise solution + - file: lecture_1_demo_solution + title: Demo solution + - file: lecture_2 + children: + - file: lecture_2_exercise + title: In-class exercise + {% if id == "columbia" -%} + - file: lecture_2_exercise_2_solution + title: Exercise 2 solution + {%- endif %} + - file: lecture_3 + children: + - file: lecture_3_exercise_solution + title: In-class exercise solution + - file: lecture_3_demo_solution + title: Demo solution + - file: lecture_4 + children: + - file: lecture_4_demo_solution + title: Demo solution + - file: lecture_5 + children: + - file: lecture_5_exercise_solution + title: In-class exercise solution + - file: lecture_6 + - file: assignments + title: Assignments + children: + - file: assignments/open_ended + - file: hw_0 + - file: hw_1 + - file: hw_2 + - file: hw_3 + - file: hw_4 + - file: final_project + children: + - file: final_project/proposal + title: Proposal + - file: final_project/resources + title: Resources + - file: final_project/peer_grading + title: Peer grading + - file: final_project/examples + title: Examples + children: + - file: final_project/creepy_crawly.ipynb + - file: final_project/lead.ipynb + - file: final_project/universities.ipynb + - file: meta + children: + - file: meta/assistant_guide + children: + - file: meta/ed_helper + - file: meta/instructor_guide + {% if id == "nyu" -%} + - file: meta/adrs + children: + - file: meta/adrs/plotting + title: Plotting + - file: meta/adrs/submission + title: Submission + {%- endif %} +site: + template: book-theme + options: + folders: true From 231261216361cf464ff8f4458f81834c90bf9333 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:36:56 +0000 Subject: [PATCH 03/14] Fix MyST TOC entries for Jupyter Book 2 Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- myst.yml | 88 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/myst.yml b/myst.yml index 94424e9f..f2cd820a 100644 --- a/myst.yml +++ b/myst.yml @@ -11,19 +11,19 @@ project: github: afeld/python-public-policy toc: - file: home.md - - file: index + - file: index.md title: Homepage - - file: syllabus + - file: syllabus.md children: - - file: registration - - file: joining_late - - file: exam + - file: registration.md + - file: joining_late.md + - file: exam.md {% if id == "columbia" -%} - - file: curve + - file: curve.ipynb {%- endif %} - - file: resources + - file: resources.md children: - - file: brackets + - file: brackets.ipynb title: Brackets - url: "{{lms_url}}" title: "{{lms_name}}" @@ -33,75 +33,75 @@ project: title: Google Colab - url: "{{submission_tool_url}}" title: Gradescope - - file: lectures + - file: lectures.md children: - - file: lecture_0 - - file: lecture_1 + - file: lecture_0.ipynb + - file: lecture_1.ipynb children: - - file: lecture_1_exercise + - file: lecture_1_exercise.ipynb title: In-class exercise - - file: lecture_1_exercise_solution + - file: lecture_1_exercise_solution.ipynb title: In-class exercise solution - - file: lecture_1_demo_solution + - file: lecture_1_demo_solution.ipynb title: Demo solution - - file: lecture_2 + - file: lecture_2.ipynb children: - - file: lecture_2_exercise + - file: lecture_2_exercise.ipynb title: In-class exercise {% if id == "columbia" -%} - - file: lecture_2_exercise_2_solution + - file: lecture_2_exercise_2_solution.ipynb title: Exercise 2 solution {%- endif %} - - file: lecture_3 + - file: lecture_3.ipynb children: - - file: lecture_3_exercise_solution + - file: lecture_3_exercise_solution.ipynb title: In-class exercise solution - - file: lecture_3_demo_solution + - file: lecture_3_demo_solution.ipynb title: Demo solution - - file: lecture_4 + - file: lecture_4.ipynb children: - - file: lecture_4_demo_solution + - file: lecture_4_demo_solution.ipynb title: Demo solution - - file: lecture_5 + - file: lecture_5.ipynb children: - - file: lecture_5_exercise_solution + - file: lecture_5_exercise_solution.ipynb title: In-class exercise solution - - file: lecture_6 - - file: assignments + - file: lecture_6.ipynb + - file: assignments.md title: Assignments children: - - file: assignments/open_ended - - file: hw_0 - - file: hw_1 - - file: hw_2 - - file: hw_3 - - file: hw_4 - - file: final_project + - file: assignments/open_ended.md + - file: hw_0.ipynb + - file: hw_1.md + - file: hw_2.ipynb + - file: hw_3.ipynb + - file: hw_4.md + - file: final_project.md children: - - file: final_project/proposal + - file: final_project/proposal.md title: Proposal - - file: final_project/resources + - file: final_project/resources.md title: Resources - - file: final_project/peer_grading + - file: final_project/peer_grading.md title: Peer grading - - file: final_project/examples + - file: final_project/examples.md title: Examples children: - file: final_project/creepy_crawly.ipynb - file: final_project/lead.ipynb - file: final_project/universities.ipynb - - file: meta + - file: meta.md children: - - file: meta/assistant_guide + - file: meta/assistant_guide.md children: - - file: meta/ed_helper - - file: meta/instructor_guide + - file: meta/ed_helper.ipynb + - file: meta/instructor_guide.md {% if id == "nyu" -%} - - file: meta/adrs + - file: meta/adrs.md children: - - file: meta/adrs/plotting + - file: meta/adrs/plotting.md title: Plotting - - file: meta/adrs/submission + - file: meta/adrs/submission.md title: Submission {%- endif %} site: From 0a84ed19f8a6a631df385702a19d9987ad08edc4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 8 Sep 2026 15:35:24 +0000 Subject: [PATCH 04/14] Merge main and fix Jupyter Book 2 build failures Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- _toc.yml | 97 ------------------------------------- extras/scripts/school_ci.sh | 2 +- myst.yml | 2 +- requirements.txt | 1 + 4 files changed, 3 insertions(+), 99 deletions(-) delete mode 100644 _toc.yml diff --git a/_toc.yml b/_toc.yml deleted file mode 100644 index 8b4f4f89..00000000 --- a/_toc.yml +++ /dev/null @@ -1,97 +0,0 @@ -format: jb-book -root: home -# conditionals should match school_ci.sh -chapters: - - file: index - title: Homepage - - file: syllabus - sections: - - file: registration - - file: joining_late - - file: exam - {% if id == "columbia" -%} - - file: curve - {%- endif %} - - file: resources - sections: - - file: brackets - title: Brackets - - url: "{{lms_url}}" - title: "{{lms_name}}" - - url: "{{discussions_url}}" - title: Ed Discussion - - url: https://colab.research.google.com - title: Google Colab - - url: {{submission_tool_url}} - title: Gradescope - - file: lectures - sections: - - file: lecture_0 - - file: lecture_1 - sections: - - file: lecture_1_exercise - title: In-class exercise - - file: lecture_1_exercise_solution - title: In-class exercise solution - - file: lecture_1_demo_solution - title: Demo solution - - file: lecture_2 - sections: - - file: lecture_2_exercise - title: In-class exercise - {% if id == "columbia" -%} - - file: lecture_2_exercise_2_solution - title: Exercise 2 solution - {%- endif %} - - file: lecture_3 - sections: - - file: lecture_3_exercise_solution - title: In-class exercise solution - - file: lecture_3_demo_solution - title: Demo solution - - file: lecture_4 - sections: - - file: lecture_4_demo_solution - title: Demo solution - - file: lecture_5 - sections: - - file: lecture_5_exercise_solution - title: In-class exercise solution - - file: lecture_6 - - file: assignments - title: Assignments - sections: - - file: assignments/open_ended - - file: hw_0 - - file: hw_1 - - file: hw_2 - - file: hw_3 - - file: hw_4 - - file: final_project - sections: - - file: final_project/proposal - title: Proposal - - file: final_project/resources - title: Resources - - file: final_project/peer_grading - title: Peer grading - - file: final_project/examples - title: Examples - sections: - - file: final_project/creepy_crawly.ipynb - - file: final_project/lead.ipynb - - file: final_project/universities.ipynb - - file: meta - sections: - - file: meta/assistant_guide - sections: - - file: meta/ed_helper - - file: meta/instructor_guide - {% if id == "nyu" -%} - - file: meta/adrs - sections: - - file: meta/adrs/plotting - title: Plotting - - file: meta/adrs/submission - title: Submission - {%- endif %} diff --git a/extras/scripts/school_ci.sh b/extras/scripts/school_ci.sh index 43d927a2..13797b16 100755 --- a/extras/scripts/school_ci.sh +++ b/extras/scripts/school_ci.sh @@ -14,7 +14,7 @@ git rm -r \ extras/terraform/ \ extras/**/test_*.py -# match the conditionals in _toc.yml +# match the conditionals in myst.yml if [ "$SCHOOL" = "columbia" ]; then git rm -r meta/adrs* else diff --git a/myst.yml b/myst.yml index f2cd820a..95739316 100644 --- a/myst.yml +++ b/myst.yml @@ -107,4 +107,4 @@ project: site: template: book-theme options: - folders: true + folders: false diff --git a/requirements.txt b/requirements.txt index 640a9813..e5d7d90f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -38,6 +38,7 @@ jinja2 nbconvert[webpdf]>=7.16.6 nbdime pytest +markdown-it-py jupyter-book==2.* # https://github.com/sphinx-doc/sphinx/issues/10440#issuecomment-1556180835 From 5e53235f38bc011dc8ce29751bfc165441a79fe7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:13:25 +0000 Subject: [PATCH 05/14] Adjust link checker for JB2 folder URLs Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- extras/scripts/broken_links.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extras/scripts/broken_links.rb b/extras/scripts/broken_links.rb index 178b78fc..3e0b7109 100644 --- a/extras/scripts/broken_links.rb +++ b/extras/scripts/broken_links.rb @@ -20,7 +20,9 @@ # https://github.com/gjtorikian/html-proofer/issues/663#issuecomment-989274727 /(?<=\.pdf)#.*$/ => "", # make absolute links relative - %r{^https://python-public-policy\.afeld\.me/en/\w+} => "" + %r{^https://python-public-policy\.afeld\.me/en/\w+} => "", + # Jupyter Book 2 builds pages as //index.html by default + %r{^/(.+)\.html(#.*)?$} => '/\1/\2' } } HTMLProofer.check_directory("_build/html", options).run From 060f01007dfccfdb68fcc85e60750a7dbb3087fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 8 Sep 2026 18:19:33 +0000 Subject: [PATCH 06/14] Update uv lockfile after dependency merge Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- uv.lock | 411 +++----------------------------------------------------- 1 file changed, 20 insertions(+), 391 deletions(-) diff --git a/uv.lock b/uv.lock index 4de358ff..1f23121f 100644 --- a/uv.lock +++ b/uv.lock @@ -6,18 +6,6 @@ resolution-markers = [ "python_full_version < '3.14'", ] -[[package]] -name = "accessible-pygments" -version = "0.0.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bc/c1/bbac6a50d02774f91572938964c582fff4270eee73ab822a4aeea4d8b11b/accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872", size = 1377899, upload-time = "2024-05-10T11:23:10.216Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7", size = 1395903, upload-time = "2024-05-10T11:23:08.421Z" }, -] - [[package]] name = "alabaster" version = "0.7.16" @@ -436,15 +424,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ba/6c/ff8bf52315064dbeb55cb5067e191120a5b2e58bb648d0d34cf7969dc2c2/choreographer-1.3.0-py3-none-any.whl", hash = "sha256:cea4cb739e4f61625e4b53888a8d3fa1d3bf73948b56753e460ab44da7d8d44f", size = 52622, upload-time = "2026-04-28T22:57:44.015Z" }, ] -[[package]] -name = "click" -version = "8.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/0e/7fa0ef50764b67090eca4114772a2abf8b6148198475e54c660b97caeee6/click-8.5.0.tar.gz", hash = "sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34", size = 382235, upload-time = "2026-08-26T13:33:14.56Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/58/50/6c0d534c5f134586a8e1ba4e330569e32f057e33372ae556463212fb4cd3/click-8.5.0-py3-none-any.whl", hash = "sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360", size = 125251, upload-time = "2026-08-26T13:33:12.928Z" }, -] - [[package]] name = "colorama" version = "0.4.6" @@ -688,18 +667,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/01/f9/575c8d760eae1fc99651b7cc5efd96ad5379ca4d6b53750b0fb4fe983f34/imagesize-2.0.1-py3-none-any.whl", hash = "sha256:ea0c9a0384df69ed86a943a15cde37d0360b82491b3910dc2215e202e62b5b02", size = 14794, upload-time = "2026-08-24T12:35:12.548Z" }, ] -[[package]] -name = "importlib-metadata" -version = "9.0.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6f/7e/1e7e8dc30634b93ebb3d58a3dea569ad146e656218d3960ab04f62047b29/importlib_metadata-9.0.1.tar.gz", hash = "sha256:ab830580bc0ef3db61ce8fae716389e5462b67e033018bab6d8f80ef17172f99", size = 59124, upload-time = "2026-08-28T15:30:34.646Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/55/ecca97ae19075f1fac62def77731e7f535e6c1fb8f92ff08160c5e6dade8/importlib_metadata-9.0.1-py3-none-any.whl", hash = "sha256:bba5600596a7e21f3eef53281cf28d6a5195634d2f2b78ff9501a3272c6eaab0", size = 27920, upload-time = "2026-08-28T15:30:33.433Z" }, -] - [[package]] name = "iniconfig" version = "2.3.0" @@ -878,31 +845,18 @@ wheels = [ [[package]] name = "jupyter-book" -version = "1.0.4.post1" +version = "2.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, - { name = "jinja2" }, - { name = "jsonschema" }, - { name = "linkify-it-py" }, - { name = "myst-nb" }, - { name = "myst-parser" }, - { name = "pyyaml" }, - { name = "sphinx" }, - { name = "sphinx-book-theme" }, - { name = "sphinx-comments" }, - { name = "sphinx-copybutton" }, - { name = "sphinx-design" }, - { name = "sphinx-external-toc" }, - { name = "sphinx-jupyterbook-latex" }, - { name = "sphinx-multitoc-numbering" }, - { name = "sphinx-thebe" }, - { name = "sphinx-togglebutton" }, - { name = "sphinxcontrib-bibtex" }, + { name = "ipykernel" }, + { name = "jupyter-core" }, + { name = "jupyter-server" }, + { name = "nodeenv" }, + { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/ee/5d10ce5b161764ad44219853f386e98b535cb3879bcb0d7376961a1e3897/jupyter_book-1.0.4.post1.tar.gz", hash = "sha256:2fe92c49ff74840edc0a86bb034eafdd0f645fca6e48266be367ce4d808b9601", size = 67412, upload-time = "2025-02-28T14:55:48.637Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/39/df74148121170368574b18b325cff961d871fb1bba536f774829d354a7e3/jupyter_book-2.1.6.tar.gz", hash = "sha256:fb52cf7f7056a8475aebefa78376801e45cc3daa010a48ac3ea089a5f10dd17c", size = 3222318, upload-time = "2026-07-05T16:14:58.105Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/86/d45756beaeb4b9b06125599b429451f8640b5db6f019d606f33c85743fd4/jupyter_book-1.0.4.post1-py3-none-any.whl", hash = "sha256:3a27a6b2581f1894ffe8f347d1a3432f06fc616997547919c42cd41c54db625d", size = 45005, upload-time = "2025-02-28T14:55:46.561Z" }, + { url = "https://files.pythonhosted.org/packages/76/5c/07bd7d4e5cb58451fea187d187722976f8b152e09569ec8cb215167fdd58/jupyter_book-2.1.6-py3-none-any.whl", hash = "sha256:677a11211a142757405a0c6cc6f4b36a371ef4887220a4833ed00101b0d52691", size = 2623674, upload-time = "2026-07-05T16:14:56.154Z" }, ] [[package]] @@ -918,25 +872,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/aa/be79e87c50698673f196d0633fc1664607da2289f9688d1de7a1c9db9e71/jupyter_builder-1.2.3-py3-none-any.whl", hash = "sha256:c5ea5a7190c2a7b082494abade98eece1b2b5bd5dbd7d610606cbcd10a1d08b3", size = 947541, upload-time = "2026-09-04T18:54:07.644Z" }, ] -[[package]] -name = "jupyter-cache" -version = "1.0.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "click" }, - { name = "importlib-metadata" }, - { name = "nbclient" }, - { name = "nbformat" }, - { name = "pyyaml" }, - { name = "sqlalchemy" }, - { name = "tabulate" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bb/f7/3627358075f183956e8c4974603232b03afd4ddc7baf72c2bc9fff522291/jupyter_cache-1.0.1.tar.gz", hash = "sha256:16e808eb19e3fb67a223db906e131ea6e01f03aa27f49a7214ce6a5fec186fb9", size = 32048, upload-time = "2024-11-15T16:03:55.322Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/64/6b/67b87da9d36bff9df7d0efbd1a325fa372a43be7158effaf43ed7b22341d/jupyter_cache-1.0.1-py3-none-any.whl", hash = "sha256:9c3cafd825ba7da8b5830485343091143dff903e4d8c69db9349b728b140abf6", size = 33907, upload-time = "2024-11-15T16:03:54.021Z" }, -] - [[package]] name = "jupyter-client" version = "8.10.0" @@ -1139,24 +1074,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, ] -[[package]] -name = "latexcodec" -version = "3.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/27/dd/4270b2c5e2ee49316c3859e62293bd2ea8e382339d63ab7bbe9f39c0ec3b/latexcodec-3.0.1.tar.gz", hash = "sha256:e78a6911cd72f9dec35031c6ec23584de6842bfbc4610a9678868d14cdfb0357", size = 31222, upload-time = "2025-06-17T18:47:34.051Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/40/23569737873cc9637fd488606347e9dd92b9fa37ba4fcda1f98ee5219a97/latexcodec-3.0.1-py3-none-any.whl", hash = "sha256:a9eb8200bff693f0437a69581f7579eb6bca25c4193515c09900ce76451e452e", size = 18532, upload-time = "2025-06-17T18:47:30.726Z" }, -] - -[[package]] -name = "linkify-it-py" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/45/98/7a1a5f31fd5c7ba93e963b168e244b8e3dd705b3d2a718e3c3307583bf57/linkify_it_py-2.2.0.tar.gz", hash = "sha256:907acd2d17ac1fbb9ddb62c8957ccbd6158cac602231a15c3b0cd1e215f03cee", size = 32939, upload-time = "2026-08-29T07:07:08.305Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/d4/1152d1c7ab42d8b908be64fd200ddc870dc9d4925e951198702084aa1a7d/linkify_it_py-2.2.0-py3-none-any.whl", hash = "sha256:3adc40eb5af300b2605fcfdb968c24e1d780a90f1f2221af7c15e5111e94d443", size = 21971, upload-time = "2026-08-29T07:07:07.164Z" }, -] - [[package]] name = "logistro" version = "2.0.1" @@ -1363,18 +1280,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" }, ] -[[package]] -name = "mdit-py-plugins" -version = "0.6.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/59/fc/f8d0863f8862f25602c0404d75568e89fb6b4109804645e5cdfb1be5cf56/mdit_py_plugins-0.6.1.tar.gz", hash = "sha256:a2bca0f039f39dbd35fb74ae1b5f998608c437463371f0ff7f49a19a17a114d0", size = 56114, upload-time = "2026-05-13T09:03:38.91Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/69/6da5581c6a7fede7dc261bf4e67d6adca4196f176b43288b55b3db395b6e/mdit_py_plugins-0.6.1-py3-none-any.whl", hash = "sha256:214c82fb2ac524472ab6a5bcab1de80f73b50443e187f401bfd77efbc7c6481d", size = 66663, upload-time = "2026-05-13T09:03:37.76Z" }, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -1393,44 +1298,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/e4/288365afae98953bc01de09f686f40d8ee84578135aa7767d5d4e60b5278/mistune-3.3.4-py3-none-any.whl", hash = "sha256:ee015381e955e370962968befe1d729ab60fafb6a715ac6751763fbce38c8d4a", size = 66862, upload-time = "2026-07-22T05:22:29.419Z" }, ] -[[package]] -name = "myst-nb" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "importlib-metadata" }, - { name = "ipykernel" }, - { name = "ipython" }, - { name = "jupyter-cache" }, - { name = "myst-parser" }, - { name = "nbclient" }, - { name = "nbformat" }, - { name = "pyyaml" }, - { name = "sphinx" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bd/b4/ff1abeea67e8cfe0a8c033389f6d1d8b0bfecfd611befb5cbdeab884fce6/myst_nb-1.4.0.tar.gz", hash = "sha256:c145598de62446a6fd009773dd071a40d3b76106ace780de1abdfc6961f614c2", size = 82285, upload-time = "2026-03-02T21:14:56.95Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/94/93/0a378b48488879a1d925b42a804edfc6e0cd0ef854220f2dce738a46e7e9/myst_nb-1.4.0-py3-none-any.whl", hash = "sha256:0e2c86e7d3b82c3aa51383f82d6268f7714f3b772c23a796ab09538a8e68b4e4", size = 82555, upload-time = "2026-03-02T21:14:55.652Z" }, -] - -[[package]] -name = "myst-parser" -version = "3.0.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "jinja2" }, - { name = "markdown-it-py" }, - { name = "mdit-py-plugins" }, - { name = "pyyaml" }, - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/49/64/e2f13dac02f599980798c01156393b781aec983b52a6e4057ee58f07c43a/myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87", size = 92392, upload-time = "2024-04-28T20:22:42.116Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/de/21aa8394f16add8f7427f0a1326ccd2b3a2a8a3245c9252bc5ac034c6155/myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1", size = 83163, upload-time = "2024-04-28T20:22:39.985Z" }, -] - [[package]] name = "narwhals" version = "2.26.0" @@ -1528,6 +1395,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c5/3c/3179b85b0e1c3659f0369940200cd6d0fa900e6cefcc7ea0bc6dd0e29ffb/nest_asyncio2-1.7.2-py3-none-any.whl", hash = "sha256:f5dfa702f3f81f6a03857e9a19e2ba578c0946a4ad417b4c50a24d7ba641fe01", size = 7843, upload-time = "2026-02-13T00:34:02.691Z" }, ] +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + [[package]] name = "notebook" version = "7.6.2" @@ -1909,32 +1785,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, ] -[[package]] -name = "pybtex" -version = "0.26.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "latexcodec" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4d/f5/f30da9c93f0fa6d619332b2f69597219b625f35780473a05164a9981fd9a/pybtex-0.26.1.tar.gz", hash = "sha256:2e5543bea424e60e9e42eef70bff597be48649d8f68ba061a7a092b2477d5464", size = 692991, upload-time = "2026-04-03T13:05:39.014Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/44/f6/775eb92e865b28cdb4ad1f2bed7a5446197516f76b58a950faa3be3fd08d/pybtex-0.26.1-py3-none-any.whl", hash = "sha256:e26c0412cc54f5f21b2a6d9d175762a2d2af9ccf3a8f651cdb89ec035db77aa1", size = 126134, upload-time = "2026-04-03T13:05:40.623Z" }, -] - -[[package]] -name = "pybtex-docutils" -version = "1.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "pybtex" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7e/84/796ea94d26188a853660f81bded39f8de4cfe595130aef0dea1088705a11/pybtex-docutils-1.0.3.tar.gz", hash = "sha256:3a7ebdf92b593e00e8c1c538aa9a20bca5d92d84231124715acc964d51d93c6b", size = 18348, upload-time = "2023-08-22T18:47:54.833Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/b1/ce1f4596211efb5410e178a803f08e59b20bedb66837dcf41e21c54f9ec1/pybtex_docutils-1.0.3-py3-none-any.whl", hash = "sha256:8fd290d2ae48e32fcb54d86b0efb8d573198653c7e2447d5bec5847095f430b9", size = 6385, upload-time = "2023-08-22T06:43:20.513Z" }, -] - [[package]] name = "pycparser" version = "3.0" @@ -1944,24 +1794,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, ] -[[package]] -name = "pydata-sphinx-theme" -version = "0.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "accessible-pygments" }, - { name = "babel" }, - { name = "beautifulsoup4" }, - { name = "docutils" }, - { name = "pygments" }, - { name = "sphinx" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ce/f7/c74c7100a7f4c0f77b5dcacb7dfdb8fee774fb70e487dd97acba2b930774/pydata_sphinx_theme-0.17.1.tar.gz", hash = "sha256:2cfc1d926c753c77039b7ee53f0ccebcbee5e81f0db61432b01cbb10ad7fd0af", size = 4991415, upload-time = "2026-04-21T13:00:34.263Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/bc/2cb8c78300ce1ace4eeac3b3522218cea2c2053bfa6b4e32cc972a477f9a/pydata_sphinx_theme-0.17.1-py3-none-any.whl", hash = "sha256:320b022d7808bdf5920d9a28e573f27aace9b23e1af6ca103eecc752411df492", size = 6823346, upload-time = "2026-04-21T13:00:31.978Z" }, -] - [[package]] name = "pyee" version = "13.0.1" @@ -2035,6 +1867,7 @@ dependencies = [ { name = "jupyterlab" }, { name = "kaleido" }, { name = "lxml" }, + { name = "markdown-it-py" }, { name = "nbconvert", extra = ["webpdf"] }, { name = "nbdime" }, { name = "nbformat" }, @@ -2056,11 +1889,12 @@ requires-dist = [ { name = "ipykernel" }, { name = "isoduration" }, { name = "jinja2" }, - { name = "jupyter-book", specifier = "==1.*" }, + { name = "jupyter-book", specifier = "==2.*" }, { name = "jupyter-resource-usage" }, { name = "jupyterlab" }, { name = "kaleido" }, { name = "lxml" }, + { name = "markdown-it-py" }, { name = "nbconvert", extras = ["webpdf"], specifier = ">=7.16.6" }, { name = "nbdime" }, { name = "nbformat", specifier = ">=4.2.0" }, @@ -2459,15 +2293,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, ] -[[package]] -name = "setuptools" -version = "84.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/44/f5da03a8ef95d369145c5bb53050e7877c9f3d312e128605fd9504829143/setuptools-84.0.0.tar.gz", hash = "sha256:f4695c21257f0d9b537ec2692c941d02ee143b7cc1276941349a546573b2ef73", size = 1168449, upload-time = "2026-08-08T18:27:58.365Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl", hash = "sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670", size = 818216, upload-time = "2026-08-08T18:27:56.719Z" }, -] - [[package]] name = "simplejson" version = "4.1.2" @@ -2584,122 +2409,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624, upload-time = "2024-07-20T14:46:52.142Z" }, ] -[[package]] -name = "sphinx-book-theme" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydata-sphinx-theme" }, - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b7/0c/e5d71c66f14a975286b9e975cbeb610b5bb6c5ad3c5162b33ea4e1ca557e/sphinx_book_theme-1.3.0.tar.gz", hash = "sha256:0bdcd3c3670154eed4bd8452a62a7884cb1317dcfc6ee80e0ae8f9fbf43a9eaa", size = 446446, upload-time = "2026-07-19T21:05:26.395Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/a6/346db89b279a13662389aaac0cac9d543f1184020d6969e01aaeda4902c5/sphinx_book_theme-1.3.0-py3-none-any.whl", hash = "sha256:143020f5c1d2ce733646eb765594f16684e3e1d116d1679f1f03823f85c63626", size = 461187, upload-time = "2026-07-19T21:05:24.622Z" }, -] - -[[package]] -name = "sphinx-comments" -version = "0.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c0/75/5bbf29e83eaf79843180cf424d0d550bda14a1792ca51dcf79daa065ba93/sphinx-comments-0.0.3.tar.gz", hash = "sha256:00170afff27019fad08e421da1ae49c681831fb2759786f07c826e89ac94cf21", size = 7960, upload-time = "2020-08-12T00:07:31.183Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/26/97/a5c39f619375d4f81d5422377fb027075898efa6b6202c1ccf1e5bb38a32/sphinx_comments-0.0.3-py3-none-any.whl", hash = "sha256:1e879b4e9bfa641467f83e3441ac4629225fc57c29995177d043252530c21d00", size = 4591, upload-time = "2020-08-12T00:07:30.297Z" }, -] - -[[package]] -name = "sphinx-copybutton" -version = "0.5.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd", size = 23039, upload-time = "2023-04-14T08:10:22.998Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/48/1ea60e74949eecb12cdd6ac43987f9fd331156388dcc2319b45e2ebb81bf/sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e", size = 13343, upload-time = "2023-04-14T08:10:20.844Z" }, -] - -[[package]] -name = "sphinx-design" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/13/7b/804f311da4663a4aecc6cf7abd83443f3d4ded970826d0c958edc77d4527/sphinx_design-0.7.0.tar.gz", hash = "sha256:d2a3f5b19c24b916adb52f97c5f00efab4009ca337812001109084a740ec9b7a", size = 2203582, upload-time = "2026-01-19T13:12:53.297Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/30/cf/45dd359f6ca0c3762ce0490f681da242f0530c49c81050c035c016bfdd3a/sphinx_design-0.7.0-py3-none-any.whl", hash = "sha256:f82bf179951d58f55dca78ab3706aeafa496b741a91b1911d371441127d64282", size = 2220350, upload-time = "2026-01-19T13:12:51.077Z" }, -] - -[[package]] -name = "sphinx-external-toc" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "pyyaml" }, - { name = "sphinx" }, - { name = "sphinx-multitoc-numbering" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c5/f8/85bcd2f1c142e580a1394c18920506d9399b8e8e97e4899bbee9c74a896e/sphinx_external_toc-1.1.0.tar.gz", hash = "sha256:f81833865006f6b4a9b2550a2474a6e3d7e7f2cb23ba23309260577ea65552f6", size = 37194, upload-time = "2026-01-16T13:15:59.03Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/80/1704c9179012e289dee2178354e385277ea51f4fa827c4bf7e36c77b0f4b/sphinx_external_toc-1.1.0-py3-none-any.whl", hash = "sha256:26c390b8d85aa641366fed2d3674910ec6820f48b91027affef485a2655ad7d0", size = 30609, upload-time = "2026-01-16T13:15:57.926Z" }, -] - -[[package]] -name = "sphinx-jupyterbook-latex" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/80/29/18a1fc30e9315e72f068637079169525069a7c0b2fbe51cf689af0576214/sphinx_jupyterbook_latex-1.0.0.tar.gz", hash = "sha256:f54c6674c13f1616f9a93443e98b9b5353f9fdda8e39b6ec552ccf0b3e5ffb62", size = 11945, upload-time = "2023-12-11T15:37:25.034Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/1f/1d4ecaf58b17fe61497644655f40b04d84a88348e41a6f0c6392394d95e4/sphinx_jupyterbook_latex-1.0.0-py3-none-any.whl", hash = "sha256:e0cd3e9e1c5af69136434e21a533343fdf013475c410a414d5b7b4922b4f3891", size = 13319, upload-time = "2023-12-11T15:37:23.25Z" }, -] - -[[package]] -name = "sphinx-multitoc-numbering" -version = "0.1.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/37/1e/577bae038372885ebc34bd8c0f290295785a0250cac6528eb6d50e4b92d5/sphinx-multitoc-numbering-0.1.3.tar.gz", hash = "sha256:c9607671ac511236fa5d61a7491c1031e700e8d498c9d2418e6c61d1251209ae", size = 4542, upload-time = "2021-03-15T12:01:43.758Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/9f/902f2030674cd9473fdbe5a2c2dec2618c27ec853484c35f82cf8df40ece/sphinx_multitoc_numbering-0.1.3-py3-none-any.whl", hash = "sha256:33d2e707a9b2b8ad636b3d4302e658a008025106fe0474046c651144c26d8514", size = 4616, upload-time = "2021-03-15T12:01:42.419Z" }, -] - -[[package]] -name = "sphinx-thebe" -version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/da/fd/926ba4af1eb2708b1ac0fa4376e4bfb11d9a32b2a00e3614137a569c1ddf/sphinx_thebe-0.3.1.tar.gz", hash = "sha256:576047f45560e82f64aa5f15200b1eb094dcfe1c5b8f531a8a65bd208e25a493", size = 20789, upload-time = "2024-02-07T13:31:57.002Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/7c/a53bdb465fd364bc3d255d96d5d70e6ba5183cfb4e45b8aa91c59b099124/sphinx_thebe-0.3.1-py3-none-any.whl", hash = "sha256:e7e7edee9f0d601c76bc70156c471e114939484b111dd8e74fe47ac88baffc52", size = 9030, upload-time = "2024-02-07T13:31:55.286Z" }, -] - -[[package]] -name = "sphinx-togglebutton" -version = "0.4.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "setuptools" }, - { name = "sphinx" }, - { name = "wheel" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/cc/be/169a0b0a8ad9588e8697c85e1d489aaaca7416073c2fc0267c360af5aae9/sphinx_togglebutton-0.4.5.tar.gz", hash = "sha256:c870dfbd3bc6e119b50ff9a37a64f8991902269e856728931c7d89877e8d4b3d", size = 18101, upload-time = "2026-03-27T13:50:41.984Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/2e/3dd55564928c5d61f92827d4b91307dde7911a40fbe0000645d73202eea9/sphinx_togglebutton-0.4.5-py3-none-any.whl", hash = "sha256:74eac6d2426110c3e1e6f989a98e07d7823141a335df1ad8a9d637bdf6a7af62", size = 44907, upload-time = "2026-03-27T13:50:40.94Z" }, -] - [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" @@ -2709,21 +2418,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, ] -[[package]] -name = "sphinxcontrib-bibtex" -version = "2.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "pybtex" }, - { name = "pybtex-docutils" }, - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/15/6a/8e0b2c2420286389e7fed78ff361ec30e2f1d58c8560af8d64df5e7b61e0/sphinxcontrib_bibtex-2.7.0.tar.gz", hash = "sha256:fee700f7aae29bb8f654c62913f00d34ac44fc0b8ca0fa67ac922ff4453addee", size = 120669, upload-time = "2026-05-06T09:29:24.935Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/52/c0/d28e62407f4733bbe0169287bc012f0ac3b4a2021066b285570654119c8b/sphinxcontrib_bibtex-2.7.0-py3-none-any.whl", hash = "sha256:28cf0ec7a957d1c7548d5749317ed472ce877e1b629f430f88e3789aa51f87b1", size = 40287, upload-time = "2026-05-06T09:29:23.253Z" }, -] - [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" @@ -2769,41 +2463,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] -[[package]] -name = "sqlalchemy" -version = "2.0.52" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3b/21/77b4c147963073040dc3c3a5cb7a8c3001a1893c0209432cb77f9df836aa/sqlalchemy-2.0.52.tar.gz", hash = "sha256:5e2d46356ac2ccb7d268ab6c2319ac6a2b42f1b8d5fd8bd3d46855cd82abee97", size = 9945637, upload-time = "2026-08-11T19:07:09.829Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/d5/1b77a026d161f98a08f11af1a5f6c47b98ee7c7e2648af525a1004826c78/sqlalchemy-2.0.52-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be8c49131665dfe2cc74c498aa1240ffb548d0fd901325dd11c2c7a18956f727", size = 2170940, upload-time = "2026-08-11T20:58:11.25Z" }, - { url = "https://files.pythonhosted.org/packages/54/bd/f444444adb37b5d53753fb1730ee7a421628e2e3b756c4da461af7e6394a/sqlalchemy-2.0.52-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b2d9e507a458832adcfbd8af6e2036ddf069b7710b799448542ebccae2dceee", size = 3383415, upload-time = "2026-08-11T21:02:38.534Z" }, - { url = "https://files.pythonhosted.org/packages/be/57/2eadf93a552568c57e8680b7e58bb5e9770d80942a1bdbaf4f2f63f0d7c8/sqlalchemy-2.0.52-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8738008376d22f30f411ea3efecf39b51110b6996d80bb73786f30bcfdd5fd3b", size = 3398577, upload-time = "2026-08-11T21:16:59.092Z" }, - { url = "https://files.pythonhosted.org/packages/15/c3/2887cf9dd111d1fbf05d22165b404c221ef43e029f7a2695e7302f27a7cc/sqlalchemy-2.0.52-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37a4d548327b6cab9c7d8cdb4e0e82feabee0110c4d150059068e2d1cfbd99ee", size = 3328225, upload-time = "2026-08-11T21:02:40.183Z" }, - { url = "https://files.pythonhosted.org/packages/02/0f/466bdf9e1feeeef5587f868c187d8687e21ff8c85b1775e9041130181132/sqlalchemy-2.0.52-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e49f51a5d59857a7a0dcaf9469febf7197d9394bd88f00d69c2c4e848112cdbf", size = 3357374, upload-time = "2026-08-11T21:17:01.076Z" }, - { url = "https://files.pythonhosted.org/packages/22/20/5c2b4583904af4173076dda1c9e53c9e2ffc7a702d2efde0216bbacbf7cb/sqlalchemy-2.0.52-cp312-cp312-win32.whl", hash = "sha256:afda3ec521d0517d0de783fc70030775841900896d832de5bbd066549290470e", size = 2129366, upload-time = "2026-08-11T21:14:50.991Z" }, - { url = "https://files.pythonhosted.org/packages/ed/06/543dab8ef62d4e9fb96fb31a30c2b8b14a8763bccf48d428294d6b3041c0/sqlalchemy-2.0.52-cp312-cp312-win_amd64.whl", hash = "sha256:2d5e53e36e37129fe0be8b9d08b6e4052c10a963ee6cda56c8c10dcc194b99ca", size = 2157344, upload-time = "2026-08-11T21:14:52.453Z" }, - { url = "https://files.pythonhosted.org/packages/7f/18/e30c6fe1eca1bf34a39fbdd6066121cc9974c850faf6f349eac563697a26/sqlalchemy-2.0.52-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2eb3c6a64b1bfe6704777cfd504e7b8ad093a5f3e03ce67663a5e6742f294e43", size = 2167724, upload-time = "2026-08-11T20:58:12.679Z" }, - { url = "https://files.pythonhosted.org/packages/d0/56/2e17d161a4f7ecc1c2ffb93e607b4e1898bb551b451b283235acb8f6ce47/sqlalchemy-2.0.52-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:923bb183c1dc64fdf7b717965e3d59938ec4f8b8710b419a21ce403e5da9a9e1", size = 3321189, upload-time = "2026-08-11T21:02:41.932Z" }, - { url = "https://files.pythonhosted.org/packages/cf/b8/8490916e893f3f8d74dc9cc54c078619364999dee37047a188e73abbc852/sqlalchemy-2.0.52-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:651d6d8782e80679e6151707c7b490834d46ada526328895abf567f25e63d29c", size = 3338185, upload-time = "2026-08-11T21:17:02.597Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f7/752cc8ee453da222829b3f5c4613614bf750d97429363b70414fa10478e4/sqlalchemy-2.0.52-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b08cddb8989775e3c88799d86704bdfc3ee6e9846118201aa5997f16f27e3a15", size = 3271698, upload-time = "2026-08-11T21:02:43.963Z" }, - { url = "https://files.pythonhosted.org/packages/51/e6/074ade0c07b9e4c8e8bca46820320ed94df9702afdb6f2af06623068d2e6/sqlalchemy-2.0.52-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ab66fa9618269390d4dfa222f2f2f88f7bc4bf5da13905131b818217db7e8057", size = 3308936, upload-time = "2026-08-11T21:17:04.172Z" }, - { url = "https://files.pythonhosted.org/packages/66/07/557c0d04716705599227945ac14e0a17ad0338e899f37d8c2ddff4dcc663/sqlalchemy-2.0.52-cp313-cp313-win32.whl", hash = "sha256:c63bda077685c85ca513286547a531ba57e7a68cf0a7ed3bafcc2bbd18896f4d", size = 2127308, upload-time = "2026-08-11T21:14:53.879Z" }, - { url = "https://files.pythonhosted.org/packages/96/4e/226eda27654318ce525d043025221f689abef883da2c7126f9065121618c/sqlalchemy-2.0.52-cp313-cp313-win_amd64.whl", hash = "sha256:9876b09b9f1ce7398b0ffece585c0a911244c53191187341f6bcae640e133751", size = 2153876, upload-time = "2026-08-11T21:14:55.527Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f5/71cb30af58c9b80a4e1fac0b73bb48f86d497a774a6a2eb6d2f1e657bb73/sqlalchemy-2.0.52-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:410d52be41d17f1a236d19520fbe776257dc16516ed06bd16d433311842aefd9", size = 2169537, upload-time = "2026-08-11T20:58:13.855Z" }, - { url = "https://files.pythonhosted.org/packages/4c/93/d07ebd645d1b07b6b5ed63450a70f063a346a7e0f2c8810daf2e532400cb/sqlalchemy-2.0.52-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfe9ce533dbe4d0a2ae1486546619bd30b76bcd670539a44d910361376175f5e", size = 3319606, upload-time = "2026-08-11T21:02:45.829Z" }, - { url = "https://files.pythonhosted.org/packages/ae/5c/290c84c7c2566ecd3b65baaae0fddec9bc33b033b398a06123bb86fbfc6e/sqlalchemy-2.0.52-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:812bae5138bfc0aa46fb0686da0fc7f581f68e2bbb05bc24c3713bebaedd1437", size = 3323642, upload-time = "2026-08-11T21:17:05.675Z" }, - { url = "https://files.pythonhosted.org/packages/13/f5/2cc160590ca49173359557880b92a0572293ccb899e8f6cedf150c5a3ddf/sqlalchemy-2.0.52-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:50bff43b632a56fbf5ed9afdd76307e1512b62051bcd5afb341ae67205bbb6c8", size = 3268125, upload-time = "2026-08-11T21:02:47.649Z" }, - { url = "https://files.pythonhosted.org/packages/35/f3/ea8933fc9f7d1353e9c2ff9965eae687c4cef181120574591ed2fa0633e1/sqlalchemy-2.0.52-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:49565daf5af554f538e23aef1fc81a95a4e49658f152285e45c02f5fc44f04cd", size = 3289516, upload-time = "2026-08-11T21:17:07.267Z" }, - { url = "https://files.pythonhosted.org/packages/45/67/05cf86541c1e1716fca1e4a996954a439cd74501707cda607fb7cb02ef50/sqlalchemy-2.0.52-cp314-cp314-win32.whl", hash = "sha256:ab9da41e61b9979b910499d633b241df20c51ee5037e5405b11c2faac3cbe1a2", size = 2130249, upload-time = "2026-08-11T21:14:57.273Z" }, - { url = "https://files.pythonhosted.org/packages/96/d7/8ac6ffa1e36169e762ef65bd835046abb2251b1bc17f8f6708e14ed8d31f/sqlalchemy-2.0.52-cp314-cp314-win_amd64.whl", hash = "sha256:a593db51b3bae75db17a5738ad5f992244b3a03863f83c28117ee482c6a3f76d", size = 2156718, upload-time = "2026-08-11T21:14:58.667Z" }, - { url = "https://files.pythonhosted.org/packages/dc/4b/e01a737eef378e734cc6394a82248a6ce13b167dfa36c731075ce9fc9c64/sqlalchemy-2.0.52-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1e61d08bdf4ee2f41024569e3400de7d6734ba498144766b11260936ccfa582", size = 2190344, upload-time = "2026-08-11T19:53:21.393Z" }, - { url = "https://files.pythonhosted.org/packages/b3/3f/3582293d1e185e71d19d7c731c3e2ee20ba21981c4a1115c0806c1f62120/sqlalchemy-2.0.52-py3-none-any.whl", hash = "sha256:3b81b8363a919ce53453591cdb93702e6bd54ade6c4fa2f468fc053baee5ed89", size = 1950700, upload-time = "2026-08-11T20:47:21.603Z" }, -] - [[package]] name = "stack-data" version = "0.6.3" @@ -2851,15 +2510,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/33/f1652d0c59fa51de18492ee2345b65372550501ad061daa38f950be390b6/statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721", size = 9588010, upload-time = "2025-12-05T23:14:07.28Z" }, ] -[[package]] -name = "tabulate" -version = "0.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/46/58/8c37dea7bbf769b20d58e7ace7e5edfe65b849442b00ffcdd56be88697c6/tabulate-0.10.0.tar.gz", hash = "sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d", size = 91754, upload-time = "2026-03-04T18:55:34.402Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl", hash = "sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3", size = 39814, upload-time = "2026-03-04T18:55:31.284Z" }, -] - [[package]] name = "terminado" version = "0.18.1" @@ -2984,18 +2634,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d5/d2/cc4dc1271e464942db7ee278baae2daa99ee77cb2af744025c04da585a3e/websocket_client-1.9.2-py3-none-any.whl", hash = "sha256:e1a673830a9c7bfa47b1cd3d5e4178f4c9651d80a4eab02c9c23a1c3ec6250ce", size = 95786, upload-time = "2026-08-31T14:08:39.899Z" }, ] -[[package]] -name = "wheel" -version = "0.48.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d0/20/50ed6bdf27dec98b568a8ae25dc599f35baa3d9709f9e83fd1edb56b9a90/wheel-0.48.0.tar.gz", hash = "sha256:94800765601e9171bf5d58d066e640662842bcedcbab982b2c90787a2c987322", size = 66471, upload-time = "2026-08-11T22:02:27.327Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/29/69cfbb602cd91690c55d38ba9fe53e6a7e76a6fa647bf38f19c138d25449/wheel-0.48.0-py3-none-any.whl", hash = "sha256:3217dcc807155e45db462d7ef2431f5ddda0d7273b700d05a67b271ceb1287ab", size = 33320, upload-time = "2026-08-11T22:02:26.1Z" }, -] - [[package]] name = "widgetsnbextension" version = "4.0.16" @@ -3004,12 +2642,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/bf/60/bc7a980fc78837d6e wheels = [ { url = "https://files.pythonhosted.org/packages/34/95/40e17e20046b7bc820d29d09ae84ec157ec8dd6e6f6cd722626292c31b2e/widgetsnbextension-4.0.16-py3-none-any.whl", hash = "sha256:a31a8774885b96fe825462f5d6496166f0c7cae111195b6465c801d230eb5a4e", size = 2225148, upload-time = "2026-08-18T08:52:53.736Z" }, ] - -[[package]] -name = "zipp" -version = "4.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, -] From 9b359f522ab95e6551903b8b45e58aaa23d1e84b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Sep 2026 04:14:50 +0000 Subject: [PATCH 07/14] Fix link checker URL rewriting for JB2 build Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- extras/scripts/broken_links.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extras/scripts/broken_links.rb b/extras/scripts/broken_links.rb index 3e0b7109..178b78fc 100644 --- a/extras/scripts/broken_links.rb +++ b/extras/scripts/broken_links.rb @@ -20,9 +20,7 @@ # https://github.com/gjtorikian/html-proofer/issues/663#issuecomment-989274727 /(?<=\.pdf)#.*$/ => "", # make absolute links relative - %r{^https://python-public-policy\.afeld\.me/en/\w+} => "", - # Jupyter Book 2 builds pages as //index.html by default - %r{^/(.+)\.html(#.*)?$} => '/\1/\2' + %r{^https://python-public-policy\.afeld\.me/en/\w+} => "" } } HTMLProofer.check_directory("_build/html", options).run From 2f2e24d15f860a5e077b1351c163fce487f23eff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Sep 2026 04:17:38 +0000 Subject: [PATCH 08/14] Add JB1 redirect generation to school builds Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- extras/scripts/school_ci.sh | 7 +++++++ meta/instructor_guide.md | 1 + 2 files changed, 8 insertions(+) diff --git a/extras/scripts/school_ci.sh b/extras/scripts/school_ci.sh index 13797b16..44666309 100755 --- a/extras/scripts/school_ci.sh +++ b/extras/scripts/school_ci.sh @@ -26,4 +26,11 @@ fi make site +# Generate redirects from old Jupyter Book 1 URLs to Jupyter Book 2 URLs. +uv run --with click --with pyyaml \ + https://raw.githubusercontent.com/jupyter-book/jb1-redirect-generator/main/generate_redirects.py \ + --base-url "https://python-public-policy.afeld.me/en/$SCHOOL/" \ + --output-dir _build/html \ + --myst-config myst.yml + git diff diff --git a/meta/instructor_guide.md b/meta/instructor_guide.md index 51eddf93..19015967 100644 --- a/meta/instructor_guide.md +++ b/meta/instructor_guide.md @@ -41,6 +41,7 @@ For each school, [the workflow](../.github/actions/setup/action.yml): - It uses {% raw %}`{% if id == "columbia" %}` and `{% if id == "nyu" %}`{% endraw %} conditionals for school-only content; the generated files must contain neither Jinja tags nor identifiers for the other school. - For notebooks, `school.sh` first removes cells tagged for the other school (`columbia-only` or `nyu-only`) and cells tagged `remove`. It then renders each remaining cell source with the same Jinja variables, while resetting notebook kernel metadata to the default Python kernel for Colab. 1. Runs `make site`, which builds the Jupyter Book HTML into `_build/html`. +1. Generates redirects from old Jupyter Book 1 `.html` paths to Jupyter Book 2 URLs using [jb1-redirect-generator](https://github.com/jupyter-book/jb1-redirect-generator). 1. When the push is to `main`, the workflow pushes the amended commit to the relevant school branch. Pushes to other branches still render both versions and upload their HTML, but do not update either published branch. 1. ReadTheDocs is notified of updates to the school-specific branches, which are then built as separate [versions](https://docs.readthedocs.com/platform/stable/versions.html). From 36dcdf0621b020f8a8286bd3b4769518e9c3ac45 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Sep 2026 05:00:46 +0000 Subject: [PATCH 09/14] Fix publish linkcheck for JB1 redirect flow Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- extras/scripts/broken_links.rb | 3 +++ myst.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/extras/scripts/broken_links.rb b/extras/scripts/broken_links.rb index 178b78fc..b82a4c9f 100644 --- a/extras/scripts/broken_links.rb +++ b/extras/scripts/broken_links.rb @@ -19,6 +19,9 @@ # ignore PDF page hash # https://github.com/gjtorikian/html-proofer/issues/663#issuecomment-989274727 /(?<=\.pdf)#.*$/ => "", + # Redirect files generated from old JB1 .html URLs don't contain anchors. + # Strip hashes so linkcheck validates file existence without false anchor failures. + /(?<=\.html)#.*$/ => "", # make absolute links relative %r{^https://python-public-policy\.afeld\.me/en/\w+} => "" } diff --git a/myst.yml b/myst.yml index 95739316..f2cd820a 100644 --- a/myst.yml +++ b/myst.yml @@ -107,4 +107,4 @@ project: site: template: book-theme options: - folders: false + folders: true From bddc1eaab0209e1be624f1835b696699eb2980ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:39:39 +0000 Subject: [PATCH 10/14] Fix Columbia linkcheck failures Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- extras/scripts/broken_links.rb | 4 ++++ lecture_0.ipynb | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/extras/scripts/broken_links.rb b/extras/scripts/broken_links.rb index b82a4c9f..a620a76c 100644 --- a/extras/scripts/broken_links.rb +++ b/extras/scripts/broken_links.rb @@ -22,6 +22,10 @@ # Redirect files generated from old JB1 .html URLs don't contain anchors. # Strip hashes so linkcheck validates file existence without false anchor failures. /(?<=\.html)#.*$/ => "", + # Folder-style pages coexist with redirect files, and html-proofer doesn't + # resolve their anchors correctly. Strip hashes so it validates page + # existence without false anchor failures. + %r{\A((?:/[^/.#?]+)+)#.*$} => "\\1", # make absolute links relative %r{^https://python-public-policy\.afeld\.me/en/\w+} => "" } diff --git a/lecture_0.ipynb b/lecture_0.ipynb index 0845dd85..42c08e95 100644 --- a/lecture_0.ipynb +++ b/lecture_0.ipynb @@ -161,7 +161,7 @@ "source": [ "## Excited about this class? Drop it!\n", "\n", - "[Comparison with Computing in Context](https://python-public-policy.afeld.me/en/columbia/#comparison-to-computing-in-context)\n" + "[Comparison with Computing in Context](https://python-public-policy.afeld.me/en/{{school_slug}}/index-1/#comparison-to-computing-in-context)\n" ] }, { @@ -261,7 +261,7 @@ } }, "source": [ - "### [Why this class?](https://python-public-policy.afeld.me/en/{{school_slug}}/#why-this-class)\n" + "### [Why this class?](https://python-public-policy.afeld.me/en/{{school_slug}}/index-1/#why-this-class)\n" ] }, { @@ -421,7 +421,7 @@ "\n", "Why are you taking _this_ class instead of R or whatever else?\n", "\n", - "![Python logo](https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Python-logo-notext.svg/110px-Python-logo-notext.svg.png)\n" + "\"Python\n" ] }, { @@ -439,7 +439,7 @@ "- Relatively easy to learn\n", "- Open source\n", "\n", - "![Python logo](https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Python-logo-notext.svg/110px-Python-logo-notext.svg.png)\n" + "\"Python\n" ] }, { @@ -921,7 +921,7 @@ "source": [ "## Class materials walkthrough\n", "\n", - "[Important links](https://python-public-policy.afeld.me/en/{{school_slug}}/#important-links)\n" + "[Important links](https://python-public-policy.afeld.me/en/{{school_slug}}/index-1/#important-links)\n" ] }, { From 166c0e4e29d9823d113af475887c4b0e6819b283 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:40:50 +0000 Subject: [PATCH 11/14] Fix Read the Docs build path Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 94405584..2d279558 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,7 @@ build: python: "3.12" nodejs: "22" commands: - - jupyter-book build --html + - jupyter-book build . --html - mkdir -p $READTHEDOCS_OUTPUT/html/ - cp -r _build/html/. "$READTHEDOCS_OUTPUT/html" - make fix_double_escaping build_dir="$READTHEDOCS_OUTPUT" From ba037b0f489c4126e2c05f82dcd19a62c59927a6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:41:22 +0000 Subject: [PATCH 12/14] Align site build entrypoints Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- Makefile | 2 +- extras/scripts/school_ci.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2ce64524..1da8c123 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ format: # https://jupyterbook.org/en/stable/content/references.html#check-for-missing-references site: - jupyter-book build --html --all --ci + jupyter-book build . --html --all --ci setup: uv sync diff --git a/extras/scripts/school_ci.sh b/extras/scripts/school_ci.sh index 44666309..a924d884 100755 --- a/extras/scripts/school_ci.sh +++ b/extras/scripts/school_ci.sh @@ -28,7 +28,7 @@ make site # Generate redirects from old Jupyter Book 1 URLs to Jupyter Book 2 URLs. uv run --with click --with pyyaml \ - https://raw.githubusercontent.com/jupyter-book/jb1-redirect-generator/main/generate_redirects.py \ + https://raw.githubusercontent.com/jupyter-book/jb1-redirect-generator/d70ce6d7df9f2dfc83bb1d409336c0cc3e20697f/generate_redirects.py \ --base-url "https://python-public-policy.afeld.me/en/$SCHOOL/" \ --output-dir _build/html \ --myst-config myst.yml From 011386d5fdc81c0c2e9b285c160c739d901f53bd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:42:05 +0000 Subject: [PATCH 13/14] Restore strict site build checks Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- .readthedocs.yaml | 8 +++++++- Makefile | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 2d279558..91bb6a82 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,13 @@ build: python: "3.12" nodejs: "22" commands: - - jupyter-book build . --html + - make site + - >- + uv run --with click --with pyyaml + https://raw.githubusercontent.com/jupyter-book/jb1-redirect-generator/d70ce6d7df9f2dfc83bb1d409336c0cc3e20697f/generate_redirects.py + --base-url "${READTHEDOCS_CANONICAL_URL%/}/" + --output-dir _build/html + --myst-config myst.yml - mkdir -p $READTHEDOCS_OUTPUT/html/ - cp -r _build/html/. "$READTHEDOCS_OUTPUT/html" - make fix_double_escaping build_dir="$READTHEDOCS_OUTPUT" diff --git a/Makefile b/Makefile index 1da8c123..5a9191dd 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ format: # https://jupyterbook.org/en/stable/content/references.html#check-for-missing-references site: - jupyter-book build . --html --all --ci + jupyter-book build . --html --all --ci -W -n --keep-going setup: uv sync From 2205f0f0c192f4f195695fb8198af4b675efe905 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Sep 2026 20:44:03 +0000 Subject: [PATCH 14/14] Stabilize homepage links Co-authored-by: afeld <86842+afeld@users.noreply.github.com> --- extras/scripts/broken_links.rb | 2 +- index.md | 4 ++++ lecture_0.ipynb | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/extras/scripts/broken_links.rb b/extras/scripts/broken_links.rb index a620a76c..5cf44358 100644 --- a/extras/scripts/broken_links.rb +++ b/extras/scripts/broken_links.rb @@ -25,7 +25,7 @@ # Folder-style pages coexist with redirect files, and html-proofer doesn't # resolve their anchors correctly. Strip hashes so it validates page # existence without false anchor failures. - %r{\A((?:/[^/.#?]+)+)#.*$} => "\\1", + %r{\A((?:/[^/.#?]+)+(?:/)?)#.*$} => "\\1", # make absolute links relative %r{^https://python-public-policy\.afeld\.me/en/\w+} => "" } diff --git a/index.md b/index.md index 5b388cbd..87c83e24 100644 --- a/index.md +++ b/index.md @@ -1,3 +1,7 @@ +--- +slug: homepage +--- + # {{course_name}} **Alternate course title:** _How to Use a Bit of Code to Do Things That Would Be Really Hard in Spreadsheets_ diff --git a/lecture_0.ipynb b/lecture_0.ipynb index 42c08e95..ea75d29d 100644 --- a/lecture_0.ipynb +++ b/lecture_0.ipynb @@ -161,7 +161,7 @@ "source": [ "## Excited about this class? Drop it!\n", "\n", - "[Comparison with Computing in Context](https://python-public-policy.afeld.me/en/{{school_slug}}/index-1/#comparison-to-computing-in-context)\n" + "[Comparison with Computing in Context](https://python-public-policy.afeld.me/en/{{school_slug}}/homepage/#comparison-to-computing-in-context)\n" ] }, { @@ -261,7 +261,7 @@ } }, "source": [ - "### [Why this class?](https://python-public-policy.afeld.me/en/{{school_slug}}/index-1/#why-this-class)\n" + "### [Why this class?](https://python-public-policy.afeld.me/en/{{school_slug}}/homepage/#why-this-class)\n" ] }, { @@ -921,7 +921,7 @@ "source": [ "## Class materials walkthrough\n", "\n", - "[Important links](https://python-public-policy.afeld.me/en/{{school_slug}}/index-1/#important-links)\n" + "[Important links](https://python-public-policy.afeld.me/en/{{school_slug}}/homepage/#important-links)\n" ] }, {