From 2c113d7f3540ee9b99795170aaf56f258e62a8de Mon Sep 17 00:00:00 2001 From: Hong Ge Date: Wed, 24 Jun 2026 10:21:50 +0100 Subject: [PATCH 1/2] Install Colab notebook deps via downloaded Project.toml + instantiate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recreate the example environment instead of a flat Pkg.add: the setup cell downloads the example's Project.toml, activates it, adds the in-repo packages (GeneralisedFilters/SSMProblems) from the repo's main branch — their registered versions are too old/unregistered (e.g. lack ReferenceTrajectory) — then instantiates the registered dependencies. Verified the flow instantiates from a clean environment. Co-Authored-By: Claude Opus 4.8 (1M context) --- GeneralisedFilters/docs/literate.jl | 48 +++++++++++++++++------------ SSMProblems/docs/literate.jl | 48 +++++++++++++++++------------ 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/GeneralisedFilters/docs/literate.jl b/GeneralisedFilters/docs/literate.jl index abee89f3..61c3ff55 100644 --- a/GeneralisedFilters/docs/literate.jl +++ b/GeneralisedFilters/docs/literate.jl @@ -55,16 +55,17 @@ end const SCRIPTJL = joinpath(EXAMPLEPATH, "script.jl") -# The example's declared dependencies (Literate is build-only), so the notebook can install -# everything it needs on Colab — including packages used only by included helper files. -function example_packages() +# In-repo packages the example depends on; the notebook installs these from the repo's main +# branch because their registered versions may be too old (or unregistered) for the example. +function repo_packages() deps = get(Pkg.TOML.parsefile(joinpath(EXAMPLEPATH, "Project.toml")), "deps", Dict()) - return sort(filter(!=("Literate"), collect(keys(deps)))) + return sort(filter(in(("SSMProblems", "GeneralisedFilters")), collect(keys(deps)))) end -# Notebook postprocess: use a generic Julia kernel (so Colab picks its default Julia -# runtime, with no pinned version) and prepend a single Pkg.add for the example's -# dependencies so the notebook runs on a fresh Colab runtime. +# Notebook postprocess: use a generic Julia kernel (so Colab picks its default Julia runtime, +# with no pinned version) and prepend a cell that recreates the example environment on a +# fresh Colab runtime — download its Project.toml, add the in-repo packages from main, then +# instantiate the (registered) dependencies. function prepare_notebook(nb) nb["metadata"]["kernelspec"] = Dict( "display_name" => "Julia", "language" => "julia", "name" => "julia" @@ -75,19 +76,26 @@ function prepare_notebook(nb) cell["cell_type"] == "code" || continue cell["source"] = filter(line -> !endswith(rstrip(line), "#hide"), cell["source"]) end - packages = example_packages() - if !isempty(packages) - setup = Dict( - "cell_type" => "code", - "execution_count" => nothing, - "metadata" => Dict(), - "outputs" => [], - "source" => - ["import Pkg\n", string("Pkg.add([", join(repr.(packages), ", "), "])")], - ) - idx = findfirst(cell -> cell["cell_type"] == "code", nb["cells"]) - insert!(nb["cells"], something(idx, lastindex(nb["cells"]) + 1), setup) - end + proj = "https://raw.githubusercontent.com/$(REPO)/main/$(PKG)/examples/$(EXAMPLE)/Project.toml" + specs = [ + "Pkg.PackageSpec(; url=\"https://github.com/$(REPO)\", subdir=\"$(p)\", rev=\"main\")" + for p in repo_packages() + ] + setup = Dict( + "cell_type" => "code", + "execution_count" => nothing, + "metadata" => Dict(), + "outputs" => [], + "source" => [ + "import Pkg, Downloads\n", + "Downloads.download(\"$(proj)\", \"Project.toml\")\n", + "Pkg.activate(\".\")\n", + "Pkg.add([$(join(specs, ", "))])\n", + "Pkg.instantiate()", + ], + ) + idx = findfirst(cell -> cell["cell_type"] == "code", nb["cells"]) + insert!(nb["cells"], something(idx, lastindex(nb["cells"]) + 1), setup) return nb end diff --git a/SSMProblems/docs/literate.jl b/SSMProblems/docs/literate.jl index cc1196b3..2459ecb3 100644 --- a/SSMProblems/docs/literate.jl +++ b/SSMProblems/docs/literate.jl @@ -54,16 +54,17 @@ end const SCRIPTJL = joinpath(EXAMPLEPATH, "script.jl") -# The example's declared dependencies (Literate is build-only), so the notebook can install -# everything it needs on Colab — including packages used only by included helper files. -function example_packages() +# In-repo packages the example depends on; the notebook installs these from the repo's main +# branch because their registered versions may be too old (or unregistered) for the example. +function repo_packages() deps = get(Pkg.TOML.parsefile(joinpath(EXAMPLEPATH, "Project.toml")), "deps", Dict()) - return sort(filter(!=("Literate"), collect(keys(deps)))) + return sort(filter(in(("SSMProblems", "GeneralisedFilters")), collect(keys(deps)))) end -# Notebook postprocess: use a generic Julia kernel (so Colab picks its default Julia -# runtime, with no pinned version) and prepend a single Pkg.add for the example's -# dependencies so the notebook runs on a fresh Colab runtime. +# Notebook postprocess: use a generic Julia kernel (so Colab picks its default Julia runtime, +# with no pinned version) and prepend a cell that recreates the example environment on a +# fresh Colab runtime — download its Project.toml, add the in-repo packages from main, then +# instantiate the (registered) dependencies. function prepare_notebook(nb) nb["metadata"]["kernelspec"] = Dict( "display_name" => "Julia", "language" => "julia", "name" => "julia" @@ -74,19 +75,26 @@ function prepare_notebook(nb) cell["cell_type"] == "code" || continue cell["source"] = filter(line -> !endswith(rstrip(line), "#hide"), cell["source"]) end - packages = example_packages() - if !isempty(packages) - setup = Dict( - "cell_type" => "code", - "execution_count" => nothing, - "metadata" => Dict(), - "outputs" => [], - "source" => - ["import Pkg\n", string("Pkg.add([", join(repr.(packages), ", "), "])")], - ) - idx = findfirst(cell -> cell["cell_type"] == "code", nb["cells"]) - insert!(nb["cells"], something(idx, lastindex(nb["cells"]) + 1), setup) - end + proj = "https://raw.githubusercontent.com/$(REPO)/main/$(PKG)/examples/$(EXAMPLE)/Project.toml" + specs = [ + "Pkg.PackageSpec(; url=\"https://github.com/$(REPO)\", subdir=\"$(p)\", rev=\"main\")" + for p in repo_packages() + ] + setup = Dict( + "cell_type" => "code", + "execution_count" => nothing, + "metadata" => Dict(), + "outputs" => [], + "source" => [ + "import Pkg, Downloads\n", + "Downloads.download(\"$(proj)\", \"Project.toml\")\n", + "Pkg.activate(\".\")\n", + "Pkg.add([$(join(specs, ", "))])\n", + "Pkg.instantiate()", + ], + ) + idx = findfirst(cell -> cell["cell_type"] == "code", nb["cells"]) + insert!(nb["cells"], something(idx, lastindex(nb["cells"]) + 1), setup) return nb end From 12aff9b65371563671c8e2bc783da4932018758e Mon Sep 17 00:00:00 2001 From: Hong Ge Date: Wed, 24 Jun 2026 10:41:25 +0100 Subject: [PATCH 2/2] Move Colab dependency setup into #nb script lines Express the Colab environment setup as Literate `#nb` lines in each example script (download Project.toml, add in-repo packages from main, instantiate) instead of injecting it via the notebook postprocess. The postprocess now only does what `#nb` can't: set a generic Julia kernelspec (metadata) and strip the Documenter-only `#hide` lines Literate leaves in the notebook. Co-Authored-By: Claude Opus 4.8 (1M context) --- GeneralisedFilters/docs/literate.jl | 37 ++----------------- .../examples/trend-inflation/script.jl | 15 ++++++++ SSMProblems/docs/literate.jl | 37 ++----------------- SSMProblems/examples/kalman-filter/script.jl | 13 ++++++- 4 files changed, 35 insertions(+), 67 deletions(-) diff --git a/GeneralisedFilters/docs/literate.jl b/GeneralisedFilters/docs/literate.jl index 61c3ff55..fb1e9ff3 100644 --- a/GeneralisedFilters/docs/literate.jl +++ b/GeneralisedFilters/docs/literate.jl @@ -55,47 +55,18 @@ end const SCRIPTJL = joinpath(EXAMPLEPATH, "script.jl") -# In-repo packages the example depends on; the notebook installs these from the repo's main -# branch because their registered versions may be too old (or unregistered) for the example. -function repo_packages() - deps = get(Pkg.TOML.parsefile(joinpath(EXAMPLEPATH, "Project.toml")), "deps", Dict()) - return sort(filter(in(("SSMProblems", "GeneralisedFilters")), collect(keys(deps)))) -end - -# Notebook postprocess: use a generic Julia kernel (so Colab picks its default Julia runtime, -# with no pinned version) and prepend a cell that recreates the example environment on a -# fresh Colab runtime — download its Project.toml, add the in-repo packages from main, then -# instantiate the (registered) dependencies. +# Notebook postprocess: only what can't be expressed as `#nb` source lines — a generic Julia +# kernel (so Colab picks its default Julia runtime, with no pinned version) and dropping the +# Documenter-only `#hide` lines Literate otherwise leaves in the notebook. The Colab +# dependency setup lives in the example script as `#nb` lines. function prepare_notebook(nb) nb["metadata"]["kernelspec"] = Dict( "display_name" => "Julia", "language" => "julia", "name" => "julia" ) - # `#hide` is a Documenter-only directive that Literate leaves in the notebook; drop - # those lines (e.g. the repo-relative paths that only work during the docs build). for cell in nb["cells"] cell["cell_type"] == "code" || continue cell["source"] = filter(line -> !endswith(rstrip(line), "#hide"), cell["source"]) end - proj = "https://raw.githubusercontent.com/$(REPO)/main/$(PKG)/examples/$(EXAMPLE)/Project.toml" - specs = [ - "Pkg.PackageSpec(; url=\"https://github.com/$(REPO)\", subdir=\"$(p)\", rev=\"main\")" - for p in repo_packages() - ] - setup = Dict( - "cell_type" => "code", - "execution_count" => nothing, - "metadata" => Dict(), - "outputs" => [], - "source" => [ - "import Pkg, Downloads\n", - "Downloads.download(\"$(proj)\", \"Project.toml\")\n", - "Pkg.activate(\".\")\n", - "Pkg.add([$(join(specs, ", "))])\n", - "Pkg.instantiate()", - ], - ) - idx = findfirst(cell -> cell["cell_type"] == "code", nb["cells"]) - insert!(nb["cells"], something(idx, lastindex(nb["cells"]) + 1), setup) return nb end diff --git a/GeneralisedFilters/examples/trend-inflation/script.jl b/GeneralisedFilters/examples/trend-inflation/script.jl index 966c8e44..34b97961 100644 --- a/GeneralisedFilters/examples/trend-inflation/script.jl +++ b/GeneralisedFilters/examples/trend-inflation/script.jl @@ -4,6 +4,21 @@ # Watson, 2016) using GeneralisedFilters to define a heirarchical model for use in Rao- # Blackwellised particle filtering. +#nb # Install dependencies so the notebook runs on a fresh Colab runtime. GeneralisedFilters +#nb # and SSMProblems are added from the repo's main branch (registered versions may be too +#nb # old, e.g. lack ReferenceTrajectory): +#nb import Pkg, Downloads +#nb Downloads.download( +#nb "https://raw.githubusercontent.com/TuringLang/SSMProblems.jl/main/GeneralisedFilters/examples/trend-inflation/Project.toml", +#nb "Project.toml", +#nb ) +#nb Pkg.activate(".") +#nb Pkg.add([ +#nb Pkg.PackageSpec(; url="https://github.com/TuringLang/SSMProblems.jl", subdir="GeneralisedFilters", rev="main"), +#nb Pkg.PackageSpec(; url="https://github.com/TuringLang/SSMProblems.jl", subdir="SSMProblems", rev="main"), +#nb ]) +#nb Pkg.instantiate() + using GeneralisedFilters using SSMProblems using Distributions diff --git a/SSMProblems/docs/literate.jl b/SSMProblems/docs/literate.jl index 2459ecb3..61e70dcb 100644 --- a/SSMProblems/docs/literate.jl +++ b/SSMProblems/docs/literate.jl @@ -54,47 +54,18 @@ end const SCRIPTJL = joinpath(EXAMPLEPATH, "script.jl") -# In-repo packages the example depends on; the notebook installs these from the repo's main -# branch because their registered versions may be too old (or unregistered) for the example. -function repo_packages() - deps = get(Pkg.TOML.parsefile(joinpath(EXAMPLEPATH, "Project.toml")), "deps", Dict()) - return sort(filter(in(("SSMProblems", "GeneralisedFilters")), collect(keys(deps)))) -end - -# Notebook postprocess: use a generic Julia kernel (so Colab picks its default Julia runtime, -# with no pinned version) and prepend a cell that recreates the example environment on a -# fresh Colab runtime — download its Project.toml, add the in-repo packages from main, then -# instantiate the (registered) dependencies. +# Notebook postprocess: only what can't be expressed as `#nb` source lines — a generic Julia +# kernel (so Colab picks its default Julia runtime, with no pinned version) and dropping the +# Documenter-only `#hide` lines Literate otherwise leaves in the notebook. The Colab +# dependency setup lives in the example script as `#nb` lines. function prepare_notebook(nb) nb["metadata"]["kernelspec"] = Dict( "display_name" => "Julia", "language" => "julia", "name" => "julia" ) - # `#hide` is a Documenter-only directive that Literate leaves in the notebook; drop - # those lines (e.g. the repo-relative paths that only work during the docs build). for cell in nb["cells"] cell["cell_type"] == "code" || continue cell["source"] = filter(line -> !endswith(rstrip(line), "#hide"), cell["source"]) end - proj = "https://raw.githubusercontent.com/$(REPO)/main/$(PKG)/examples/$(EXAMPLE)/Project.toml" - specs = [ - "Pkg.PackageSpec(; url=\"https://github.com/$(REPO)\", subdir=\"$(p)\", rev=\"main\")" - for p in repo_packages() - ] - setup = Dict( - "cell_type" => "code", - "execution_count" => nothing, - "metadata" => Dict(), - "outputs" => [], - "source" => [ - "import Pkg, Downloads\n", - "Downloads.download(\"$(proj)\", \"Project.toml\")\n", - "Pkg.activate(\".\")\n", - "Pkg.add([$(join(specs, ", "))])\n", - "Pkg.instantiate()", - ], - ) - idx = findfirst(cell -> cell["cell_type"] == "code", nb["cells"]) - insert!(nb["cells"], something(idx, lastindex(nb["cells"]) + 1), setup) return nb end diff --git a/SSMProblems/examples/kalman-filter/script.jl b/SSMProblems/examples/kalman-filter/script.jl index d924f69a..7d7536b4 100644 --- a/SSMProblems/examples/kalman-filter/script.jl +++ b/SSMProblems/examples/kalman-filter/script.jl @@ -1,7 +1,18 @@ # # Kalman Filter # # This example implements a Kalman filter for a linear Gaussian state space model using the -# SSMProblems interface. +# SSMProblems interface. + +#nb # Install dependencies so the notebook runs on a fresh Colab runtime. SSMProblems is +#nb # added from the repo's main branch (the registered version may be too old): +#nb import Pkg, Downloads +#nb Downloads.download( +#nb "https://raw.githubusercontent.com/TuringLang/SSMProblems.jl/main/SSMProblems/examples/kalman-filter/Project.toml", +#nb "Project.toml", +#nb ) +#nb Pkg.activate(".") +#nb Pkg.add(Pkg.PackageSpec(; url="https://github.com/TuringLang/SSMProblems.jl", subdir="SSMProblems", rev="main")) +#nb Pkg.instantiate() using AbstractMCMC using Distributions