Generate Temporary Environment like Pkg.test

The Pkg.test documentation states:
The tests are run by generating a temporary environment with only pkg and its (recursive) dependencies in it.

I love this ability, it’s a entire setup and teardown of an environment, completely isolated from the environment you are currently in. I want to know how I can do this myself from within a Julia REPL?

It’s not the same as doing Pkg.activate(), because that activated environment still exists within the current global REPL environment and all of it’s history.

I will try to read the source code of Pkg.test to find the answer, but maybe someone here knows the answer already.

I guess I would need to:

  • Choose an environment (directory with Project.toml and optionally Manifest.toml)
  • Pkg.instantiate it
  • Startup Julia from within Julia with that environment activated, without enabling a global environment like @v1.8? Maybe also without startup.jl…
  • run my desired code
  • Shutdown the environment and return back to original Julia environment

For example I would like to do this for doctesting.

You can use the environment variable JULIA_LOAD_PATH and the --startup-file command-line flag to get this behavior.

In bash, it looks like this:


JULIA_LOAD_PATH="@" julia --project=. --startup-file=no run.jl

What this does:

  • sets JULIA_LOAD_PATH so that Julia will only use the local Project.toml for finding packages, rather than also the global environment.

  • sets --startup-file=no so that the user’s startup.jl won’t affect the results.

  • sets the project to the current directory.

You can create a temporary environment with

]activate --temp

or

Pkg.activate(; temp = true)

I’m not sure what you mean here. The base Julia environment wouldn’t be active anymore since you’ve activated a different (temp) one, but maybe you mean the package usings and objects created in the REPL so far?
In that case, yeah, you’d have to create a new fresh Julia process for this environment.

You can have a file, let’s say doctestsetup.jl, with something like:

import Pkg
Pkg.activate(; temp = true)
Pkg.add("SomePackage")

and then execute

julia --startup-file=no -L doctestsetup.jl yourcodetotest.jl

(the startup-file option shouldn’t be strictly necessary, since any code in startup.jl that you don’t want to run for normal files should be inside an atreplinit block anyway, but let’s put that aside here.)

The temporary environment will be automatically cleaned up when that Julia process exits.

1 Like

Maybe I should simplify my question.

I want to have a function like:

sandboxed_doctest("MyPackage")

With behavior similar to Pkg.test("MyPackage")

Which we could probably generalize to something like:

run_in_sandbox_environment(project="MyPackage", subproject="/docs", file="doctest.jl")

Where doctest.jl calls Documenter.doctest or something.

I’m now down into Pkg.Operations.Test which sets up a sandbox which seems to use the JULIA_LOAD_PATH trick proposed by @ericphanson as you can see on line 1506 in operations.jl.

P.S. I will also look into whether Documenter.doctest already sets up a sandboxed environment…