Skip to content

Commit 3743b1e

Browse files
authored
Merge pull request #22 from JuliaTesting/ox/14cleanup
Clean-up release 1.4 branch
2 parents 53390df + 236d37a commit 3743b1e

14 files changed

+250
-405
lines changed

Project.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
77

88
[compat]
99
ChainRulesCore = "=1.0.2"
10+
MCMCDiagnosticTools = "=0.1.0"
11+
YAXArrays = "0.1.3"
1012
julia = "~1.4, ~1.5, ~1.6"
1113

1214
[extras]
1315
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
16+
MCMCDiagnosticTools = "be115224-59cd-429b-ad48-344e309966f0"
1417
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
18+
YAXArrays = "c21b50f5-aa40-41ea-b809-c0f5e47bfa5c"
1519

1620
[targets]
17-
test = ["ChainRulesCore", "Test"]
21+
test = ["ChainRulesCore", "MCMCDiagnosticTools", "Test", "YAXArrays"]

src/TestEnv.jl

+7-37
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,15 @@
11
module TestEnv
22
using Pkg
33
using Pkg: PackageSpec
4-
using Pkg.Types: Context, ensure_resolved, is_project_uuid, write_env
4+
using Pkg.Types: Context, ensure_resolved, is_project_uuid, write_env, is_stdlib
5+
using Pkg.Types: Types, projectfile_path, manifestfile_path
56
using Pkg.Operations: manifest_info, manifest_resolve!, project_deps_resolve!
67
using Pkg.Operations: project_rel_path, project_resolve!
8+
using Pkg.Operations: sandbox, source_path, sandbox_preserve, abspath!
9+
using Pkg.Operations: gen_target_project, update_package_test!
710

8-
using Pkg.Types: Types, projectfile_path, manifestfile_path
9-
10-
# Version specific imports
11-
@static if VERSION >= v"1.4.0"
12-
using Pkg.Operations: gen_target_project
13-
else
14-
using Pkg.Operations: with_dependencies_loadable_at_toplevel
15-
end
16-
@static if isdefined(Pkg.Operations, :update_package_test!)
17-
using Pkg.Operations: update_package_test!
18-
else
19-
function update_package_test!(pkg, entry)
20-
is_stdlib(pkg.uuid) && return
21-
pkg.version = entry.version
22-
pkg.tree_hash = entry.tree_hash
23-
pkg.repo = entry.repo
24-
pkg.path = entry.path
25-
pkg.pinned = entry.pinned
26-
end
27-
end
28-
29-
@static if VERSION >= v"1.2.0"
30-
using Pkg.Types: is_stdlib
31-
using Pkg.Operations: sandbox, source_path, sandbox_preserve, abspath!
32-
else
33-
using Pkg.Operations: find_installed
34-
using Pkg.Types: SHA1
35-
end
36-
37-
38-
include("exceptions.jl")
39-
40-
include("activate.jl")
41-
include("make_test_env.jl")
42-
include("sandbox.jl")
43-
include("test_dir.jl")
11+
include("common.jl")
12+
include("activate_do.jl")
13+
include("activate_set.jl")
4414

4515
end

src/activate.jl

-69
This file was deleted.

src/activate_do.jl

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
TestEnv.activate(f, [pkg])
3+
4+
Activate the test enviroment of `pkg` (defaults to current enviroment), and run `f()`,
5+
then deactivate the enviroment.
6+
This is not useful for many people: Julia is not really designed to have the enviroment
7+
being changed while you are executing code.
8+
However, this *is* useful for anyone doing something like making a alternative to
9+
`Pkg.test()`.
10+
Indeed this is basically extracted from what `Pkg.test()` does.
11+
"""
12+
function activate(f, pkg::AbstractString=current_pkg_name())
13+
ctx, pkgspec = ctx_and_pkgspec(pkg)
14+
test_project_override = maybe_gen_project_override!(ctx, pkgspec)
15+
return sandbox(ctx, pkgspec, pkgspec.path, joinpath(pkgspec.path, "test"), test_project_override) do
16+
flush(stdout)
17+
f()
18+
end
19+
end

src/activate_set.jl

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""
2+
TestEnv.activate([pkg])
3+
4+
Activate the test enviroment of `pkg` (defaults to current enviroment).
5+
"""
6+
function activate(pkg::AbstractString=current_pkg_name())
7+
ctx, pkgspec = ctx_and_pkgspec(pkg)
8+
# This needs to be first as `gen_target_project` fixes `pkgspec.path` if it is nothing
9+
sandbox_project_override = maybe_gen_project_override!(ctx, pkgspec)
10+
11+
sandbox_path = joinpath(pkgspec.path, "test")
12+
sandbox_project = projectfile_path(sandbox_path)
13+
14+
tmp = mktempdir()
15+
tmp_project = projectfile_path(tmp)
16+
tmp_manifest = manifestfile_path(tmp)
17+
18+
# Copy env info over to temp env
19+
if sandbox_project_override !== nothing
20+
Types.write_project(sandbox_project_override, tmp_project)
21+
elseif isfile(sandbox_project)
22+
cp(sandbox_project, tmp_project)
23+
chmod(tmp_project, 0o600)
24+
end
25+
# create merged manifest
26+
# - copy over active subgraph
27+
# - abspath! to maintain location of all deved nodes
28+
working_manifest = abspath!(ctx, sandbox_preserve(ctx, pkgspec, tmp_project))
29+
30+
# - copy over fixed subgraphs from test subgraph
31+
# really only need to copy over "special" nodes
32+
sandbox_env = Types.EnvCache(projectfile_path(sandbox_path))
33+
sandbox_manifest = abspath!(sandbox_path, sandbox_env.manifest)
34+
35+
for (name, uuid) in sandbox_env.project.deps
36+
entry = get(sandbox_manifest, uuid, nothing)
37+
if entry !== nothing && isfixed(entry)
38+
subgraph = prune_manifest(sandbox_manifest, [uuid])
39+
for (uuid, entry) in subgraph
40+
if haskey(working_manifest, uuid)
41+
pkgerror("can not merge projects")
42+
end
43+
working_manifest[uuid] = entry
44+
end
45+
end
46+
end
47+
48+
Types.write_manifest(working_manifest, tmp_manifest)
49+
50+
# sandbox
51+
push!(empty!(LOAD_PATH), "@", tmp)
52+
Base.ACTIVE_PROJECT[] = nothing
53+
54+
temp_ctx = Context()
55+
temp_ctx.env.project.deps[pkgspec.name] = pkgspec.uuid
56+
57+
try
58+
Pkg.resolve(temp_ctx; io=devnull)
59+
@debug "Using _parent_ dep graph"
60+
catch err# TODO
61+
@debug err
62+
@warn "Could not use exact versions of packages in manifest, re-resolving"
63+
temp_ctx.env.manifest.deps = Dict(
64+
uuid => entry for
65+
(uuid, entry) in temp_ctx.env.manifest.deps if isfixed(entry)
66+
)
67+
Pkg.resolve(temp_ctx; io=devnull)
68+
@debug "Using _clean_ dep graph"
69+
end
70+
71+
# Absolutify stdlibs paths
72+
for (uuid, entry) in temp_ctx.env.manifest
73+
if is_stdlib(uuid)
74+
entry.path = Types.stdlib_path(entry.name)
75+
end
76+
end
77+
write_env(temp_ctx.env; update_undo=false)
78+
79+
# update enviroment variables
80+
path_sep = Sys.iswindows() ? ';' : ':'
81+
ENV["JULIA_LOAD_PATH"] = "@$(path_sep)$(tmp)"
82+
delete!(ENV, "JULIA_PROJECT")
83+
84+
return Base.active_project()
85+
end

src/common.jl

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
struct TestEnvError <: Exception
2+
msg::AbstractString
3+
end
4+
5+
function Base.showerror(io::IO, ex::TestEnvError, bt; backtrace=true)
6+
printstyled(io, ex.msg, color=Base.error_color())
7+
end
8+
9+
10+
current_pkg_name() = Context().env.pkg.name
11+
12+
"""
13+
ctx, pkgspec = ctx_and_pkgspec(pkg::AbstractString)
14+
15+
For a given package name `pkg`, instantiate a `Context` for it, and return that `Context`,
16+
and it's `PackageSpec`.
17+
"""
18+
function ctx_and_pkgspec(pkg::AbstractString)
19+
pkgspec = deepcopy(PackageSpec(pkg))
20+
ctx = Context()
21+
isinstalled!(ctx, pkgspec) || throw(TestEnvError("$pkg not installed 👻"))
22+
Pkg.instantiate(ctx)
23+
return ctx, pkgspec
24+
end
25+
26+
27+
"""
28+
isinstalled!(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
29+
30+
Checks if the package is installed by using `ensure_resolved` from `Pkg/src/Types.jl`.
31+
This function fails if the package is not installed, but here we wrap it in a
32+
try-catch as we may want to test another package after the one that isn't installed.
33+
34+
For Julia versions V1.4 and later, the first arguments of the Pkg functions used
35+
is of type `Pkg.Types.Context`. For earlier versions, they are of type
36+
`Pkg.Types.EnvCache`.
37+
"""
38+
function isinstalled!(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
39+
project_resolve!(ctx, [pkgspec])
40+
project_deps_resolve!(ctx, [pkgspec])
41+
manifest_resolve!(ctx, [pkgspec])
42+
43+
try
44+
ensure_resolved(ctx, [pkgspec])
45+
catch err
46+
err isa MethodError && rethrow()
47+
return false
48+
end
49+
return true
50+
end
51+
52+
function test_dir_has_project_file(ctx, pkgspec)
53+
return isfile(joinpath(get_test_dir(ctx, pkgspec), "Project.toml"))
54+
end
55+
56+
"""
57+
get_test_dir(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
58+
59+
Gets the testfile path of the package. Code for each Julia version mirrors that found
60+
in `Pkg/src/Operations.jl`.
61+
"""
62+
function get_test_dir(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
63+
if is_project_uuid(ctx, pkgspec.uuid)
64+
pkgspec.path = dirname(ctx.env.project_file)
65+
pkgspec.version = ctx.env.pkg.version
66+
else
67+
update_package_test!(pkgspec, manifest_info(ctx, pkgspec.uuid))
68+
pkgspec.path = project_rel_path(ctx, source_path(ctx, pkgspec))
69+
end
70+
pkgfilepath = source_path(ctx, pkgspec)
71+
return joinpath(pkgfilepath, "test")
72+
end
73+
74+
75+
function maybe_gen_project_override!(ctx, pkgspec)
76+
if !test_dir_has_project_file(ctx, pkgspec)
77+
sandbox_project_override = gen_target_project(ctx, pkgspec, pkgspec.path, "test")
78+
else
79+
nothing
80+
end
81+
end

src/exceptions.jl

-7
This file was deleted.

0 commit comments

Comments
 (0)