From 7514bd4ab6a16247cda33ee4b0cfe7295428bc2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 17 Nov 2023 11:37:14 +0100 Subject: [PATCH 1/8] Replace `root_project_or_failed_lazytest` --- src/deps_compat.jl | 10 +++--- src/persistent_tasks.jl | 12 +++---- src/project_extras.jl | 12 ++----- src/stale_deps.jl | 5 ++- src/utils.jl | 33 +++++-------------- test/pkgs/AquaTesting.jl | 1 - .../src/PkgWithoutProject.jl | 1 - test/test_project_extras.jl | 9 ----- test/test_stale_deps.jl | 10 ------ 9 files changed, 23 insertions(+), 70 deletions(-) delete mode 100644 test/pkgs/sample/PkgWithoutProject/src/PkgWithoutProject.jl diff --git a/src/deps_compat.jl b/src/deps_compat.jl index 32c97f86..dc4beaa9 100644 --- a/src/deps_compat.jl +++ b/src/deps_compat.jl @@ -81,9 +81,8 @@ function test_julia_compat(pkg::PkgId; broken::Bool = false) end function has_julia_compat(pkg::PkgId) - result = root_project_or_failed_lazytest(pkg) - result isa LazyTestResult && error("Unable to locate Project.toml") - root_project_path = result + root_project_path, found = root_project_toml(pkg) + found || error("Unable to locate Project.toml") prj = TOML.parsefile(root_project_path) return has_julia_compat(prj) end @@ -93,9 +92,8 @@ function has_julia_compat(prj::Dict{String,Any}) end function find_missing_deps_compat(pkg::PkgId, deps_type::String = "deps"; kwargs...) - result = root_project_or_failed_lazytest(pkg) - result isa LazyTestResult && error("Unable to locate Project.toml") - root_project_path = result + root_project_path, found = root_project_toml(pkg) + found || error("Unable to locate Project.toml") missing_compat = find_missing_deps_compat(TOML.parsefile(root_project_path), deps_type; kwargs...) diff --git a/src/persistent_tasks.jl b/src/persistent_tasks.jl index 3f59b350..db6ea5ac 100644 --- a/src/persistent_tasks.jl +++ b/src/persistent_tasks.jl @@ -87,9 +87,9 @@ function test_persistent_tasks(package::Module; kwargs...) end function has_persistent_tasks(package::PkgId; tmax = 10) - result = root_project_or_failed_lazytest(package) - result isa LazyTestResult && error("Unable to locate Project.toml") - return !precompile_wrapper(result, tmax) + root_project_path, found = root_project_toml(package) + found || error("Unable to locate Project.toml") + return !precompile_wrapper(root_project_path, tmax) end """ @@ -102,9 +102,9 @@ These are likely the ones blocking precompilation of your package. Any additional kwargs (e.g., `tmax`) are passed to [`Aqua.test_persistent_tasks`](@ref). """ function find_persistent_tasks_deps(package::PkgId; kwargs...) - result = root_project_or_failed_lazytest(package) - result isa LazyTestResult && error("Unable to locate Project.toml") - prj = TOML.parsefile(result) + root_project_path, found = root_project_toml(package) + found || error("Unable to locate Project.toml") + prj = TOML.parsefile(root_project_path) deps = get(prj, "deps", Dict{String,Any}()) filter!(deps) do (name, uuid) id = PkgId(UUID(uuid), name) diff --git a/src/project_extras.jl b/src/project_extras.jl index 6869e36a..6590a1db 100644 --- a/src/project_extras.jl +++ b/src/project_extras.jl @@ -14,13 +14,6 @@ function test_project_extras(packages) end end -function project_toml_path(dir) - candidates = joinpath.(dir, ["Project.toml", "JuliaProject.toml"]) - i = findfirst(isfile, candidates) - i === nothing && return candidates[1], false - return candidates[i], true -end - analyze_project_extras(packages) = map(_analyze_project_extras, aspkgids(packages)) is_julia12_or_later(compat::AbstractString) = is_julia12_or_later(semver_spec(compat)) @@ -29,9 +22,8 @@ is_julia12_or_later(compat::VersionSpec) = isempty(compat ∩ semver_spec("1.0 - function _analyze_project_extras(pkg::PkgId) label = string(pkg) - result = root_project_or_failed_lazytest(pkg) - result isa LazyTestResult && return result - root_project_path = result + root_project_path, found = root_project_toml(pkg) + found || error("Unable to locate Project.toml") package_loc = Base.locate_package(pkg) package_loc === nothing && diff --git a/src/stale_deps.jl b/src/stale_deps.jl index 2a17dc72..cf847164 100644 --- a/src/stale_deps.jl +++ b/src/stale_deps.jl @@ -39,9 +39,8 @@ analyze_stale_deps(packages, kwargs...) = function _analyze_stale_deps_1(pkg::PkgId; ignore::AbstractVector{Symbol} = Symbol[]) label = "$pkg" - result = root_project_or_failed_lazytest(pkg) - result isa LazyTestResult && return result - root_project_path = result + root_project_path, found = root_project_toml(pkg) + found || error("Unable to locate Project.toml") @debug "Parsing `$root_project_path`" prj = TOML.parsefile(root_project_path) diff --git a/src/utils.jl b/src/utils.jl index 1a7a4413..ad886adf 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -42,36 +42,21 @@ function Base.show(io::IO, ::MIME"text/plain", result::LazyTestResult) end end -function root_project_or_failed_lazytest(pkg::PkgId) - label = "$pkg" +function project_toml_path(dir) + candidates = joinpath.(dir, ["Project.toml", "JuliaProject.toml"]) + i = findfirst(isfile, candidates) + i === nothing && return candidates[1], false + return candidates[i], true +end +function root_project_toml(pkg::PkgId) srcpath = Base.locate_package(pkg) - if srcpath === nothing - return LazyTestResult( - label, - """ - Package $pkg does not have a corresponding source file. - """, - false, - ) - end - + srcpath === nothing && return "", false pkgpath = dirname(dirname(srcpath)) root_project_path, found = project_toml_path(pkgpath) - if !found - return LazyTestResult( - label, - """ - Project.toml file at project directory does not exist: - $root_project_path - """, - false, - ) - end - return root_project_path + return root_project_path, found end - module _TempModule end eval_string(code::AbstractString) = include_string(_TempModule, code) diff --git a/test/pkgs/AquaTesting.jl b/test/pkgs/AquaTesting.jl index 4a93b41a..be1cc81b 100644 --- a/test/pkgs/AquaTesting.jl +++ b/test/pkgs/AquaTesting.jl @@ -28,7 +28,6 @@ const SAMPLE_PKGIDS = [ PkgId(UUID("6e4a843a-fdff-4fa3-bb5a-e4ae67826963"), "PkgWithCompatibleTestProject"), PkgId(UUID("7231ce0e-e308-4079-b49f-19e33cc3ac6e"), "PkgWithPostJulia12Support"), PkgId(UUID("8981f3dd-97fd-4684-8ec7-7b0c42f64e2e"), "PkgWithoutTestProject"), - PkgId(nothing, "PkgWithoutProject"), ] const SAMPLE_PKG_BY_NAME = Dict(pkg.name => pkg for pkg in SAMPLE_PKGIDS) diff --git a/test/pkgs/sample/PkgWithoutProject/src/PkgWithoutProject.jl b/test/pkgs/sample/PkgWithoutProject/src/PkgWithoutProject.jl deleted file mode 100644 index db417a66..00000000 --- a/test/pkgs/sample/PkgWithoutProject/src/PkgWithoutProject.jl +++ /dev/null @@ -1 +0,0 @@ -module PkgWithoutProject end diff --git a/test/test_project_extras.jl b/test/test_project_extras.jl index a4f0fea2..24db60ff 100644 --- a/test/test_project_extras.jl +++ b/test/test_project_extras.jl @@ -67,15 +67,6 @@ with_sample_pkgs() do msg = sprint(show, "text/plain", r) @test occursin("test/Project.toml file does not exist", msg) end - - @testset "PkgWithoutProject" begin - r = results["PkgWithoutProject"] - @test !ispass(r) - @test r ⊜ false - msg = sprint(show, "text/plain", r) - @test occursin("Project.toml file at project directory does not exist", msg) - end - end end # module diff --git a/test/test_stale_deps.jl b/test/test_stale_deps.jl index 926840cb..494b377b 100644 --- a/test/test_stale_deps.jl +++ b/test/test_stale_deps.jl @@ -90,16 +90,6 @@ with_sample_pkgs() do msg = sprint(show, "text/plain", r) @test occursin("No `deps` table in", msg) end - @testset "PkgWithoutProject" begin - pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithoutProject"] - results = Aqua.analyze_stale_deps(pkg) - @test length(results) == 1 - r, = results - @test !ispass(r) - @test r ⊜ false - msg = sprint(show, "text/plain", r) - @test occursin("Project.toml file at project directory does not exist", msg) - end end end # module From 33ef8046803437b1a58923e560f77c990f0c7a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Mon, 6 Nov 2023 18:23:52 +0100 Subject: [PATCH 2/8] Remove unused functions --- src/utils.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index ad886adf..23188680 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -2,8 +2,6 @@ if !@isdefined(isnothing) isnothing(x) = x === nothing end -splitlines(str; kwargs...) = readlines(IOBuffer(str); kwargs...) - askwargs(kwargs) = (; kwargs...) function askwargs(flag::Bool) if !flag @@ -69,8 +67,6 @@ function checked_repr(obj) return code end -ensure_exception(e::Exception) = e -ensure_exception(x) = ErrorException(string(x)) function is_kwcall(signature::DataType) @static if VERSION < v"1.9" From da62ef6cdeb5f035a48430039699edfc1eeb569e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 7 Nov 2023 10:51:12 +0100 Subject: [PATCH 3/8] Use `isnothing` from `Compat` --- src/Aqua.jl | 3 +++ src/utils.jl | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Aqua.jl b/src/Aqua.jl index a5c17b7d..fff5bdc9 100644 --- a/src/Aqua.jl +++ b/src/Aqua.jl @@ -4,6 +4,9 @@ using Base: PkgId, UUID using Pkg: Pkg, TOML, PackageSpec using Test +@static if VERSION < v"1.1.0-DEV.472" + using Compat: isnothing +end @static if VERSION < v"1.3.0-DEV.349" using Compat: findfirst end diff --git a/src/utils.jl b/src/utils.jl index 23188680..8203eb1f 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,7 +1,3 @@ -if !@isdefined(isnothing) - isnothing(x) = x === nothing -end - askwargs(kwargs) = (; kwargs...) function askwargs(flag::Bool) if !flag @@ -67,7 +63,6 @@ function checked_repr(obj) return code end - function is_kwcall(signature::DataType) @static if VERSION < v"1.9" try From 2a4623a4cf3cc93fe0c7480cc4152de47d5ab5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 7 Nov 2023 12:25:56 +0100 Subject: [PATCH 4/8] Refactor `test_stale_deps` --- src/stale_deps.jl | 63 ++++++++++----------------------- test/test_stale_deps.jl | 78 ++++++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 81 deletions(-) diff --git a/src/stale_deps.jl b/src/stale_deps.jl index cf847164..3fa7066f 100644 --- a/src/stale_deps.jl +++ b/src/stale_deps.jl @@ -26,33 +26,29 @@ directly, this can be achieved via transitivity as well. # Keyword Arguments - `ignore::Vector{Symbol}`: names of dependent packages to be ignored. """ -function test_stale_deps(packages; kwargs...) - @testset "$(result.label)" for result in analyze_stale_deps(packages, kwargs...) - @debug result.label result - @test result ⊜ true - end +function test_stale_deps(pkg::PkgId; kwargs...) + stale_deps = find_stale_deps(pkg; kwargs...) + @test isempty(stale_deps) end -analyze_stale_deps(packages, kwargs...) = - [_analyze_stale_deps_1(pkg; kwargs...) for pkg in aspkgids(packages)] +function test_stale_deps(mod::Module; kwargs...) + test_stale_deps(aspkgid(mod); kwargs...) +end -function _analyze_stale_deps_1(pkg::PkgId; ignore::AbstractVector{Symbol} = Symbol[]) - label = "$pkg" +# Remove in next breaking release +function test_stale_deps(packages::Vector{<:Union{Module,PkgId}}; kwargs...) + @testset "$pkg" for pkg in packages + test_stale_deps(pkg; kwargs...) + end +end +function find_stale_deps(pkg::PkgId; ignore::AbstractVector{Symbol} = Symbol[]) root_project_path, found = root_project_toml(pkg) found || error("Unable to locate Project.toml") - @debug "Parsing `$root_project_path`" prj = TOML.parsefile(root_project_path) - raw_deps = get(prj, "deps", nothing) - if raw_deps === nothing - return LazyTestResult(label, "No `deps` table in `$root_project_path`", true) - end - deps = [PkgId(UUID(v), k) for (k, v) in raw_deps] - - raw_weakdeps = get(prj, "weakdeps", nothing) - weakdeps = - isnothing(raw_weakdeps) ? PkgId[] : [PkgId(UUID(v), k) for (k, v) in raw_weakdeps] + deps = [PkgId(UUID(v), k) for (k, v) in get(prj, "deps", Dict{String,Any}())] + weakdeps = [PkgId(UUID(v), k) for (k, v) in get(prj, "weakdeps", Dict{String,Any}())] marker = "_START_MARKER_" code = """ @@ -65,14 +61,12 @@ function _analyze_stale_deps_1(pkg::PkgId; ignore::AbstractVector{Symbol} = Symb """ cmd = Base.julia_cmd() output = read(`$cmd --startup-file=no --color=no -e $code`, String) - @debug("Checked modules loaded in a separate process.", cmd, Text(code), Text(output)) pos = findfirst(marker, output) @assert !isnothing(pos) output = output[pos.stop+1:end] loaded_uuids = map(UUID, eachline(IOBuffer(output))) - return _analyze_stale_deps_2(; - pkg = pkg, + return find_stale_deps_2(; deps = deps, weakdeps = weakdeps, loaded_uuids = loaded_uuids, @@ -81,14 +75,12 @@ function _analyze_stale_deps_1(pkg::PkgId; ignore::AbstractVector{Symbol} = Symb end # Side-effect -free part of stale dependency analysis. -function _analyze_stale_deps_2(; - pkg::PkgId, +function find_stale_deps_2(; deps::AbstractVector{PkgId}, weakdeps::AbstractVector{PkgId}, loaded_uuids::AbstractVector{UUID}, ignore::AbstractVector{Symbol}, ) - label = "$pkg" deps_uuids = [p.uuid for p in deps] pkgid_from_uuid = Dict(p.uuid => p for p in deps) @@ -97,24 +89,5 @@ function _analyze_stale_deps_2(; stale_pkgs = setdiff(stale_pkgs, weakdeps) stale_pkgs = [p for p in stale_pkgs if !(Symbol(p.name) in ignore)] - if isempty(stale_pkgs) - return LazyTestResult( - label, - """ - All packages in `deps` are loaded via `using $(pkg.name)`. - """, - true, - ) - end - - stale_msg = join(("* $p" for p in stale_pkgs), "\n") - msglines = [ - "Some package(s) in `deps` of $pkg are not loaded during via" * - " `using $(pkg.name)`.", - stale_msg, - "", - "To ignore from stale dependency detection, pass the package name to" * - " `ignore` keyword argument of `Aqua.test_stale_deps`", - ] - return LazyTestResult(label, join(msglines, "\n"), false) + return stale_pkgs end diff --git a/test/test_stale_deps.jl b/test/test_stale_deps.jl index 494b377b..81250cd9 100644 --- a/test/test_stale_deps.jl +++ b/test/test_stale_deps.jl @@ -1,9 +1,10 @@ module TestStaleDeps include("preamble.jl") -using Aqua: PkgId, UUID, _analyze_stale_deps_2, ispass, ⊜ +using Base: PkgId, UUID +using Aqua: find_stale_deps_2, ispass, ⊜ -@testset "_analyze_stale_deps_2" begin +@testset "find_stale_deps_2" begin pkg = PkgId(UUID(42), "TargetPkg") dep1 = PkgId(UUID(1), "Dep1") @@ -11,84 +12,89 @@ using Aqua: PkgId, UUID, _analyze_stale_deps_2, ispass, ⊜ dep3 = PkgId(UUID(3), "Dep3") @testset "pass" begin - @test _analyze_stale_deps_2(; - pkg = pkg, + result = find_stale_deps_2(; deps = PkgId[], weakdeps = PkgId[], loaded_uuids = UUID[], ignore = Symbol[], - ) ⊜ true - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test isempty(result) + + result = find_stale_deps_2(; deps = PkgId[dep1], weakdeps = PkgId[], loaded_uuids = UUID[dep1.uuid, dep2.uuid, dep3.uuid], ignore = Symbol[], - ) ⊜ true - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test isempty(result) + + result = find_stale_deps_2(; deps = PkgId[dep1], weakdeps = PkgId[], loaded_uuids = UUID[dep2.uuid, dep3.uuid], ignore = Symbol[:Dep1], - ) ⊜ true - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test isempty(result) + + result = find_stale_deps_2(; deps = PkgId[dep1], weakdeps = PkgId[dep2], loaded_uuids = UUID[dep1.uuid], ignore = Symbol[], - ) ⊜ true - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test isempty(result) + + result = find_stale_deps_2(; deps = PkgId[dep1, dep2], weakdeps = PkgId[dep2], loaded_uuids = UUID[dep1.uuid], ignore = Symbol[], - ) ⊜ true - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test isempty(result) + + result = find_stale_deps_2(; deps = PkgId[dep1, dep2], weakdeps = PkgId[dep2], loaded_uuids = UUID[], ignore = Symbol[:Dep1], - ) ⊜ true + ) + @test isempty(result) end @testset "failure" begin - @test _analyze_stale_deps_2(; - pkg = pkg, + result = find_stale_deps_2(; deps = PkgId[dep1], weakdeps = PkgId[], loaded_uuids = UUID[], ignore = Symbol[], - ) ⊜ false - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test length(result) == 1 + @test dep1 in result + + result = find_stale_deps_2(; deps = PkgId[dep1], weakdeps = PkgId[], loaded_uuids = UUID[dep2.uuid, dep3.uuid], ignore = Symbol[], - ) ⊜ false - @test _analyze_stale_deps_2(; - pkg = pkg, + ) + @test length(result) == 1 + @test dep1 in result + + result = find_stale_deps_2(; deps = PkgId[dep1, dep2], weakdeps = PkgId[], loaded_uuids = UUID[dep3.uuid], ignore = Symbol[:Dep1], - ) ⊜ false + ) + @test length(result) == 1 + @test dep2 in result end end with_sample_pkgs() do @testset "Package without `deps`" begin pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithoutTestProject"] - results = Aqua.analyze_stale_deps(pkg) - @test length(results) == 1 - r, = results - @test ispass(r) - @test r ⊜ true - msg = sprint(show, "text/plain", r) - @test occursin("No `deps` table in", msg) + results = Aqua.find_stale_deps(pkg) + @test isempty(results) end end From ac60a0873b6f5ade1225462e0ae419f2094516b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 7 Nov 2023 13:19:33 +0100 Subject: [PATCH 5/8] Refactor `test_project_extras` --- src/project_extras.jl | 118 ++++++++---------- test/pkgs/AquaTesting.jl | 1 + .../PkgWithCompatibleTestProject/Project.toml | 3 + .../Project.toml | 3 + test/pkgs/sample/PkgWithoutDeps/Project.toml | 11 ++ .../PkgWithoutDeps/src/PkgWithoutDeps.jl | 1 + .../test/.gitkeep} | 0 .../sample/PkgWithoutTestProject/Project.toml | 3 + .../PkgWithoutTestProject/test/.gitkeep | 0 test/test_project_extras.jl | 70 +++++------ test/test_stale_deps.jl | 2 +- 11 files changed, 108 insertions(+), 104 deletions(-) create mode 100644 test/pkgs/sample/PkgWithoutDeps/Project.toml create mode 100644 test/pkgs/sample/PkgWithoutDeps/src/PkgWithoutDeps.jl rename test/pkgs/sample/{PkgWithoutTestProject/test/.gitignore => PkgWithoutDeps/test/.gitkeep} (100%) create mode 100644 test/pkgs/sample/PkgWithoutTestProject/test/.gitkeep diff --git a/src/project_extras.jl b/src/project_extras.jl index 6590a1db..9f01a25e 100644 --- a/src/project_extras.jl +++ b/src/project_extras.jl @@ -7,95 +7,85 @@ Check that test target of the root project and test project Julia < 1.2 while recording test-only dependency compatibility in `test/Project.toml`. """ -function test_project_extras(packages) - @testset "$(result.label)" for result in analyze_project_extras(packages) - @debug result.label result - @test result ⊜ true +function test_project_extras(pkg::PkgId; kwargs...) + msgs = analyze_project_extras(pkg; kwargs...) + @test isempty(msgs) +end + +# Remove with next breaking version +function test_project_extras(packages::Vector{<:Union{Module,PkgId}}; kwargs...) + @testset "$pkg" for pkg in packages + test_project_extras(pkg; kwargs...) end end -analyze_project_extras(packages) = map(_analyze_project_extras, aspkgids(packages)) +function test_project_extras(mod::Module; kwargs...) + test_project_extras(aspkgid(mod); kwargs...) +end is_julia12_or_later(compat::AbstractString) = is_julia12_or_later(semver_spec(compat)) is_julia12_or_later(compat::VersionSpec) = isempty(compat ∩ semver_spec("1.0 - 1.1")) -function _analyze_project_extras(pkg::PkgId) - label = string(pkg) - +function analyze_project_extras(pkg::PkgId) root_project_path, found = root_project_toml(pkg) found || error("Unable to locate Project.toml") - package_loc = Base.locate_package(pkg) - package_loc === nothing && - return LazyTestResult(label, "Base.locate_package failed.", false) - pkgpath = dirname(dirname(package_loc)) - test_project_path, found = project_toml_path(joinpath(pkgpath, "test")) - if !found - return LazyTestResult(label, "test/Project.toml file does not exist.", true) - end + test_project_path, found = + project_toml_path(joinpath(dirname(root_project_path), "test")) + found || return String[] # having no test/Project.toml is fine root_project = TOML.parsefile(root_project_path) test_project = TOML.parsefile(test_project_path) # Ignore root project's extras if only supporting julia 1.2 or later. # See: # https://julialang.github.io/Pkg.jl/v1/creating-packages/#Test-specific-dependencies-in-Julia-1.2-and-above-1 - julia_version = get(get(root_project, "compat", Dict()), "julia", "1") - if is_julia12_or_later(julia_version) - return LazyTestResult( - label, - string( - "Supporting only post-1.2 `julia` ($julia_version); ", - "ignoring root project.", - ), - true, - ) - end + julia_version = get(get(root_project, "compat", Dict{String,Any}()), "julia", nothing) + isnothing(julia_version) && return String["Could not find `julia` compat."] + is_julia12_or_later(julia_version) && return String[] - # `extras_deps`: test-only dependencies according to /Project.toml - all_extras_deps = get(root_project, "extras", Dict()) - target = Set{String}(get(get(root_project, "targets", Dict()), "test", [])) - extras_deps = setdiff( - Set{Pair{String,String}}(p for p in all_extras_deps if first(p) in target), - Set{Pair{String,String}}(get(root_project, "deps", [])), + # `extras_test_deps`: test-only dependencies according to Project.toml + deps = [PkgId(UUID(v), k) for (k, v) in get(root_project, "deps", Dict{String,Any}())] + target = + Set{String}(get(get(root_project, "targets", Dict{String,Any}()), "test", String[])) + extras_test_deps = setdiff( + [ + PkgId(UUID(v), k) for + (k, v) in get(root_project, "extras", Dict{String,Any}()) if k in target + ], + deps, ) - # `test_deps`: test-only dependencies according to /test/Project.toml: + # `test_deps`: test-only dependencies according to test/Project.toml: test_deps = setdiff( - Set{Pair{String,String}}(get(test_project, "deps", [])), - Set{Pair{String,String}}(get(root_project, "deps", [])), - [root_project["name"] => root_project["uuid"]], + [PkgId(UUID(v), k) for (k, v) in get(test_project, "deps", Dict{String,Any}())], + deps, + [PkgId(UUID(root_project["uuid"]), root_project["name"])], ) - not_in_extras = setdiff(test_deps, extras_deps) - not_in_test = setdiff(extras_deps, test_deps) + not_in_extras = setdiff(test_deps, extras_test_deps) + not_in_test = setdiff(extras_test_deps, test_deps) if isempty(not_in_extras) && isempty(not_in_test) - return LazyTestResult( - label, - """ - Root and test projects are consistent. - Root project: $root_project_path - Test project: $test_project_path - """, - true, - ) + return String[] else - msg = sprint() do io - println( - io, - "Root and test projects should be consistent for projects supporting Julia <= 1.1.", - ) - if !isempty(not_in_extras) - println(io, "Test dependencies not in root project ($root_project_path):") - for (name, uuid) in sort!(collect(not_in_extras)) - println(io, " $name = \"$uuid\"") - end + msgs = String[] + push!( + msgs, + "Root and test projects should be consistent for projects supporting Julia <= 1.1.", + ) + if !isempty(not_in_extras) + msg = "Test dependencies not in root project ($root_project_path):" + for pkgs in sort!(collect(not_in_extras); by = (pkg -> pkg.name)) + msg *= "\n\t$pkgs" end - if !isempty(not_in_test) - println(io, "Dependencies not in test project ($test_project_path):") - for (name, uuid) in sort!(collect(not_in_test)) - println(io, " $name = \"$uuid\"") - end + push!(msgs, msg) + end + if !isempty(not_in_test) + msg = "Dependencies not in test project ($test_project_path):" + for pkgs in sort!(collect(not_in_test); by = (pkg -> pkg.name)) + msg *= "\n\t$pkgs" end + push!(msgs, msg) end - return LazyTestResult(label, msg, false) + + return msgs end end diff --git a/test/pkgs/AquaTesting.jl b/test/pkgs/AquaTesting.jl index be1cc81b..b8d68bb0 100644 --- a/test/pkgs/AquaTesting.jl +++ b/test/pkgs/AquaTesting.jl @@ -28,6 +28,7 @@ const SAMPLE_PKGIDS = [ PkgId(UUID("6e4a843a-fdff-4fa3-bb5a-e4ae67826963"), "PkgWithCompatibleTestProject"), PkgId(UUID("7231ce0e-e308-4079-b49f-19e33cc3ac6e"), "PkgWithPostJulia12Support"), PkgId(UUID("8981f3dd-97fd-4684-8ec7-7b0c42f64e2e"), "PkgWithoutTestProject"), + PkgId(UUID("3922d3f4-c8f6-c8a8-00da-60b44ed8eac6"), "PkgWithoutDeps"), ] const SAMPLE_PKG_BY_NAME = Dict(pkg.name => pkg for pkg in SAMPLE_PKGIDS) diff --git a/test/pkgs/sample/PkgWithCompatibleTestProject/Project.toml b/test/pkgs/sample/PkgWithCompatibleTestProject/Project.toml index 802a5c67..15ecdbbe 100644 --- a/test/pkgs/sample/PkgWithCompatibleTestProject/Project.toml +++ b/test/pkgs/sample/PkgWithCompatibleTestProject/Project.toml @@ -1,6 +1,9 @@ name = "PkgWithCompatibleTestProject" uuid = "6e4a843a-fdff-4fa3-bb5a-e4ae67826963" +[compat] +julia = "1" + [extras] Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/pkgs/sample/PkgWithIncompatibleTestProject/Project.toml b/test/pkgs/sample/PkgWithIncompatibleTestProject/Project.toml index 3f77aa0f..1c9617a0 100644 --- a/test/pkgs/sample/PkgWithIncompatibleTestProject/Project.toml +++ b/test/pkgs/sample/PkgWithIncompatibleTestProject/Project.toml @@ -1,6 +1,9 @@ name = "PkgWithIncompatibleTestProject" uuid = "1649c42c-2196-4c52-9963-79822cd6227b" +[compat] +julia = "1" + [extras] REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/pkgs/sample/PkgWithoutDeps/Project.toml b/test/pkgs/sample/PkgWithoutDeps/Project.toml new file mode 100644 index 00000000..fbbd1c36 --- /dev/null +++ b/test/pkgs/sample/PkgWithoutDeps/Project.toml @@ -0,0 +1,11 @@ +name = "PkgWithoutDeps" +uuid = "3922d3f4-c8f6-c8a8-00da-60b44ed8eac6" + +[compat] +julia = "1" + +[extras] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test"] diff --git a/test/pkgs/sample/PkgWithoutDeps/src/PkgWithoutDeps.jl b/test/pkgs/sample/PkgWithoutDeps/src/PkgWithoutDeps.jl new file mode 100644 index 00000000..6d617f91 --- /dev/null +++ b/test/pkgs/sample/PkgWithoutDeps/src/PkgWithoutDeps.jl @@ -0,0 +1 @@ +module PkgWithoutDeps end diff --git a/test/pkgs/sample/PkgWithoutTestProject/test/.gitignore b/test/pkgs/sample/PkgWithoutDeps/test/.gitkeep similarity index 100% rename from test/pkgs/sample/PkgWithoutTestProject/test/.gitignore rename to test/pkgs/sample/PkgWithoutDeps/test/.gitkeep diff --git a/test/pkgs/sample/PkgWithoutTestProject/Project.toml b/test/pkgs/sample/PkgWithoutTestProject/Project.toml index 61e83519..2b6f8fff 100644 --- a/test/pkgs/sample/PkgWithoutTestProject/Project.toml +++ b/test/pkgs/sample/PkgWithoutTestProject/Project.toml @@ -1,6 +1,9 @@ name = "PkgWithoutTestProject" uuid = "8981f3dd-97fd-4684-8ec7-7b0c42f64e2e" +[compat] +julia = "1" + [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/pkgs/sample/PkgWithoutTestProject/test/.gitkeep b/test/pkgs/sample/PkgWithoutTestProject/test/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/test_project_extras.jl b/test/test_project_extras.jl index 24db60ff..4cd53a24 100644 --- a/test/test_project_extras.jl +++ b/test/test_project_extras.jl @@ -16,56 +16,48 @@ using Base: PkgId, UUID end with_sample_pkgs() do - - results = Dict( - zip( - [p.name for p in AquaTesting.SAMPLE_PKGIDS], - Aqua.analyze_project_extras(collect(AquaTesting.SAMPLE_PKGIDS)), - ), - ) - pkgids = Dict([p.name => p for p in AquaTesting.SAMPLE_PKGIDS]) - @testset "PkgWithIncompatibleTestProject" begin - r = results["PkgWithIncompatibleTestProject"] - @test !ispass(r) - @test r ⊜ false - msg = sprint(show, "text/plain", r) - @test occursin( - "Root and test projects should be consistent for projects supporting Julia <= 1.1.", - msg, + pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithIncompatibleTestProject"] + result = Aqua.analyze_project_extras(pkg) + @test !isempty(result) + @test any( + msg -> occursin( + "Root and test projects should be consistent for projects supporting Julia <= 1.1.", + msg, + ), + result, + ) + @test any( + msg -> + occursin("Test dependencies not in root project", msg) && + occursin("Random [", msg), + result, + ) + @test any( + msg -> + occursin("Dependencies not in test project", msg) && + occursin("REPL [", msg), + result, ) - @test occursin("Test dependencies not in root project", msg) - @test occursin("Dependencies not in test project", msg) - @test occursin("Random =", msg) - @test occursin("REPL =", msg) - @test !occursin("Test =", msg) + @test !any(msg -> occursin("Test [", msg), result) end @testset "PkgWithCompatibleTestProject" begin - r = results["PkgWithCompatibleTestProject"] - @test ispass(r) - Aqua.test_project_extras(pkgids["PkgWithCompatibleTestProject"]) - msg = sprint(show, "text/plain", r) - @test occursin("Root and test projects are consistent.", msg) - @test occursin("Root project:", msg) - @test occursin("Test project:", msg) + pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithCompatibleTestProject"] + result = Aqua.analyze_project_extras(pkg) + @test isempty(result) end @testset "PkgWithPostJulia12Support" begin - r = results["PkgWithPostJulia12Support"] - @test ispass(r) - Aqua.test_project_extras(pkgids["PkgWithPostJulia12Support"]) - msg = sprint(show, "text/plain", r) - @test occursin("Supporting only post-1.2 `julia`", msg) - @test occursin("ignoring root project", msg) + pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithPostJulia12Support"] + result = Aqua.analyze_project_extras(pkg) + @test isempty(result) end @testset "PkgWithoutTestProject" begin - r = results["PkgWithoutTestProject"] - @test ispass(r) - Aqua.test_project_extras(pkgids["PkgWithoutTestProject"]) - msg = sprint(show, "text/plain", r) - @test occursin("test/Project.toml file does not exist", msg) + pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithoutTestProject"] + result = Aqua.analyze_project_extras(pkg) + @test isempty(result) end end diff --git a/test/test_stale_deps.jl b/test/test_stale_deps.jl index 81250cd9..c748eb4d 100644 --- a/test/test_stale_deps.jl +++ b/test/test_stale_deps.jl @@ -92,7 +92,7 @@ end with_sample_pkgs() do @testset "Package without `deps`" begin - pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithoutTestProject"] + pkg = AquaTesting.SAMPLE_PKG_BY_NAME["PkgWithoutDeps"] results = Aqua.find_stale_deps(pkg) @test isempty(results) end From 698579abbf8a3efef2785744db26cc21bd11fd21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 7 Nov 2023 13:21:32 +0100 Subject: [PATCH 6/8] Remove `LazyTestResult` --- src/utils.jl | 30 ------------------------------ test/test_project_extras.jl | 2 +- test/test_stale_deps.jl | 2 +- 3 files changed, 2 insertions(+), 32 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 8203eb1f..38940529 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -6,36 +6,6 @@ function askwargs(flag::Bool) return NamedTuple() end -struct LazyTestResult - label::String - message::String - pass::Bool -end - -ispass(result::LazyTestResult) = result.pass - -# Infix operator wrapping `ispass` so that the failure case is pretty-printed -⊜(result, yes::Bool) = ispass(result)::Bool == yes - -# To be shown via `@test` when failed: -function Base.show(io::IO, result::LazyTestResult) - print(io, "⟪result: ") - show(io, MIME"text/plain"(), result) - print(io, "⟫") -end - -function Base.show(io::IO, ::MIME"text/plain", result::LazyTestResult) - if ispass(result) - printstyled(io, "✔ PASS"; color = :green, bold = true) - else - printstyled(io, "😭 FAILED"; color = :red, bold = true) - end - println(io, ": ", result.label) - for line in eachline(IOBuffer(result.message)) - println(io, " "^4, line) - end -end - function project_toml_path(dir) candidates = joinpath.(dir, ["Project.toml", "JuliaProject.toml"]) i = findfirst(isfile, candidates) diff --git a/test/test_project_extras.jl b/test/test_project_extras.jl index 4cd53a24..a0041593 100644 --- a/test/test_project_extras.jl +++ b/test/test_project_extras.jl @@ -1,7 +1,7 @@ module TestProjectExtras include("preamble.jl") -using Aqua: is_julia12_or_later, ispass, ⊜ +using Aqua: is_julia12_or_later using Base: PkgId, UUID @testset "is_julia12_or_later" begin diff --git a/test/test_stale_deps.jl b/test/test_stale_deps.jl index c748eb4d..9ec84b01 100644 --- a/test/test_stale_deps.jl +++ b/test/test_stale_deps.jl @@ -2,7 +2,7 @@ module TestStaleDeps include("preamble.jl") using Base: PkgId, UUID -using Aqua: find_stale_deps_2, ispass, ⊜ +using Aqua: find_stale_deps_2 @testset "find_stale_deps_2" begin pkg = PkgId(UUID(42), "TargetPkg") From 4fe8e46f23ff084e09429969eb791f1b61ce16a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 7 Nov 2023 13:23:49 +0100 Subject: [PATCH 7/8] Move some stuff around --- src/ambiguities.jl | 22 ---------------------- src/utils.jl | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ambiguities.jl b/src/ambiguities.jl index 7c286c26..9e8c389b 100644 --- a/src/ambiguities.jl +++ b/src/ambiguities.jl @@ -29,28 +29,6 @@ test_ambiguities(packages; kwargs...) = _test_ambiguities(aspkgids(packages); kw const ExcludeSpec = Pair{Base.PkgId,String} -aspkgids(pkg::Union{Module,PkgId}) = aspkgids([pkg]) -aspkgids(packages) = mapfoldl(aspkgid, push!, packages, init = PkgId[]) - -aspkgid(pkg::PkgId) = pkg -function aspkgid(m::Module) - if !ispackage(m) - error("Non-package (non-toplevel) module is not supported. Got: $m") - end - return PkgId(m) -end -function aspkgid(name::Symbol) - # Maybe `Base.depwarn()` - return Base.identify_package(String(name))::PkgId -end - -ispackage(m::Module) = - if m in (Base, Core) - true - else - parentmodule(m) == m - end - strnameof(x) = string(x) strnameof(x::Type) = string(nameof(x)) diff --git a/src/utils.jl b/src/utils.jl index 38940529..d869dca1 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -6,6 +6,28 @@ function askwargs(flag::Bool) return NamedTuple() end +aspkgids(pkg::Union{Module,PkgId}) = aspkgids([pkg]) +aspkgids(packages) = mapfoldl(aspkgid, push!, packages, init = PkgId[]) + +aspkgid(pkg::PkgId) = pkg +function aspkgid(m::Module) + if !ispackage(m) + error("Non-package (non-toplevel) module is not supported. Got: $m") + end + return PkgId(m) +end +function aspkgid(name::Symbol) + # Maybe `Base.depwarn()` + return Base.identify_package(String(name))::PkgId +end + +ispackage(m::Module) = + if m in (Base, Core) + true + else + parentmodule(m) == m + end + function project_toml_path(dir) candidates = joinpath.(dir, ["Project.toml", "JuliaProject.toml"]) i = findfirst(isfile, candidates) From c5d96ead56c38a2de8d428311794118870c50aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 17 Nov 2023 16:23:41 +0100 Subject: [PATCH 8/8] Fix issue reported by JET --- src/persistent_tasks.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/persistent_tasks.jl b/src/persistent_tasks.jl index db6ea5ac..85092d1b 100644 --- a/src/persistent_tasks.jl +++ b/src/persistent_tasks.jl @@ -121,7 +121,7 @@ function precompile_wrapper(project, tmax) if VERSION < v"1.10.0-" return true end - prev_project = Base.active_project() + prev_project = Base.active_project()::String isdefined(Pkg, :respect_sysimage_versions) && Pkg.respect_sysimage_versions(false) try pkgdir = dirname(project)