From 37513c43edc55f93a7d68551787a1de8680c5122 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 07:22:18 -0400 Subject: [PATCH 1/5] QA: run_qa v1.6 form + ExplicitImports Bring QA onto the SciMLTesting 1.6 run_qa folder model with ExplicitImports enabled, replacing the hand-rolled inline ExplicitImports test. - Add a `test/qa` group (qa.jl + Project.toml) wired through the run_tests `qa` entry; declare `[QA]` in test_groups.toml (lts, 1; out of All). - `run_qa(GeometricIntegratorsDiffEq; explicit_imports = true, ...)` runs Aqua (all sub-checks) + the 6 ExplicitImports checks. JET/AllocCheck stay in the existing NoPre group (those are @test_opt type-stability / allocation checks, not run_qa's report/test_package JET). - Fix the EI all_qualified_accesses_via_owners finding properly: access the 9 SciMLBase-owned names (AbstractODEAlgorithm, AbstractODEProblem, __solve, build_solution, has_jac, has_tgrad, unwrapped_f, StandardODEProblem, AbstractParameterizedFunction, AbstractDynamicalODEProblem) from their owner SciMLBase instead of via the DiffEqBase re-export. These are identical objects (DiffEqBase.X === SciMLBase.X), present since SciMLBase 2.x (verified down to the 2.5.0 downgrade floor), so the change is behavior-preserving. - ei_kwargs ignore-list for all_qualified_accesses_are_public: the remaining names are non-public in their owner (SciMLBase API-extension points / problem types, ReturnCode.Success enum member flagged only on Julia 1.10) or the non-public DiffEqBase.RecursiveArrayTools module path to ArrayPartition. Source package noted per name; they go public as the base libraries release. - Fix the Aqua deps_compat extras finding by adding root [compat] for ODEProblemLibrary and Test (test-only extras that lacked compat entries). - Drop ExplicitImports from root [extras]/[targets]/[compat] (now transitive via SciMLTesting in the QA sub-env); bump root SciMLTesting compat to "1.6". Verified locally against released SciMLTesting 1.6.0 (Pkg resolves it; no dev-from-branch): GROUP=QA green on Julia 1.10 (17/17) and 1.11 (17/17), 0 Fail/Error/Broken; Core tests 32/32 on 1.11 with the source change. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- Project.toml | 8 ++++---- src/algorithms.jl | 2 +- src/solve.jl | 16 ++++++++-------- test/explicit_imports_test.jl | 8 -------- test/qa/Project.toml | 16 ++++++++++++++++ test/qa/qa.jl | 29 +++++++++++++++++++++++++++++ test/runtests.jl | 9 +++++---- test/test_groups.toml | 4 ++++ 8 files changed, 67 insertions(+), 25 deletions(-) delete mode 100644 test/explicit_imports_test.jl create mode 100644 test/qa/Project.toml create mode 100644 test/qa/qa.jl diff --git a/Project.toml b/Project.toml index 4cc2ba6..01729de 100644 --- a/Project.toml +++ b/Project.toml @@ -12,21 +12,21 @@ SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" [compat] DiffEqBase = "6.62, 7" -ExplicitImports = "1.14.0" GeometricIntegrators = "0.15.5, 0.16" +ODEProblemLibrary = "0.1, 1" Reexport = "0.2, 1" SafeTestsets = "0.0.1, 0.1" SciMLBase = "2, 3" SciMLLogging = "1.10.1, 2" -SciMLTesting = "1" +SciMLTesting = "1.6" +Test = "1.10" julia = "1.10" [extras] -ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7" ODEProblemLibrary = "fdc4e326-1af4-4b90-96e7-779fcce2daa5" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["ExplicitImports", "ODEProblemLibrary", "SafeTestsets", "SciMLTesting", "Test"] +test = ["ODEProblemLibrary", "SafeTestsets", "SciMLTesting", "Test"] diff --git a/src/algorithms.jl b/src/algorithms.jl index 8ca60c1..29f5d83 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -1,4 +1,4 @@ -abstract type GeometricIntegratorAlgorithm <: DiffEqBase.AbstractODEAlgorithm end +abstract type GeometricIntegratorAlgorithm <: SciMLBase.AbstractODEAlgorithm end struct GIEuler <: GeometricIntegratorAlgorithm end struct GIMidpoint <: GeometricIntegratorAlgorithm end struct GIHeun2 <: GeometricIntegratorAlgorithm end diff --git a/src/solve.jl b/src/solve.jl index d8e3bad..6bb4cf3 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -1,5 +1,5 @@ -function DiffEqBase.__solve( - prob::DiffEqBase.AbstractODEProblem{uType, tType, isinplace}, +function SciMLBase.__solve( + prob::SciMLBase.AbstractODEProblem{uType, tType, isinplace}, alg::AlgType, timeseries = nothing, ts = nothing, ks = nothing; verbose = true, @@ -41,15 +41,15 @@ function DiffEqBase.__solve( warned = true end end - if !(prob.f isa DiffEqBase.AbstractParameterizedFunction) && isstiff - if DiffEqBase.has_tgrad(prob.f) + if !(prob.f isa SciMLBase.AbstractParameterizedFunction) && isstiff + if SciMLBase.has_tgrad(prob.f) @SciMLMessage( "Explicit t-gradient given to this stiff solver is ignored.", verbose, :mismatched_input_output_type ) warned = true end - if DiffEqBase.has_jac(prob.f) + if SciMLBase.has_jac(prob.f) @SciMLMessage( "Explicit Jacobian given to this stiff solver is ignored.", verbose, :mismatched_input_output_type @@ -91,7 +91,7 @@ function DiffEqBase.__solve( _alg = get_method_from_alg(alg) needs_solver = requires_newton_solver(alg) - if prob.problem_type isa DiffEqBase.StandardODEProblem + if prob.problem_type isa SciMLBase.StandardODEProblem # Create function wrapper for GeometricIntegrators API # GeometricIntegrators expects: v(v, t, q, params) # DiffEqBase provides: f(du, u, p, t) for inplace or f(u, p, t) for out-of-place @@ -134,7 +134,7 @@ function DiffEqBase.__solve( _timeseries = [q[1] for q in sol.q] end - elseif prob.problem_type isa DiffEqBase.AbstractDynamicalODEProblem + elseif prob.problem_type isa SciMLBase.AbstractDynamicalODEProblem # For second order / partitioned problems # PODE expects: v(v, t, q, p, params), f(f, t, q, p, params) # DiffEqBase SecondOrderODEProblem has f.f1 and f.f2: @@ -183,7 +183,7 @@ function DiffEqBase.__solve( ] end - return DiffEqBase.build_solution( + return SciMLBase.build_solution( prob, alg, ts, _timeseries[start_idx:end], timeseries_errors = timeseries_errors, retcode = ReturnCode.Success diff --git a/test/explicit_imports_test.jl b/test/explicit_imports_test.jl deleted file mode 100644 index a97314a..0000000 --- a/test/explicit_imports_test.jl +++ /dev/null @@ -1,8 +0,0 @@ -using ExplicitImports -using GeometricIntegratorsDiffEq -using Test - -@testset "Explicit Imports" begin - @test check_no_implicit_imports(GeometricIntegratorsDiffEq) === nothing - @test check_no_stale_explicit_imports(GeometricIntegratorsDiffEq) === nothing -end diff --git a/test/qa/Project.toml b/test/qa/Project.toml new file mode 100644 index 0000000..7906779 --- /dev/null +++ b/test/qa/Project.toml @@ -0,0 +1,16 @@ +[deps] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +GeometricIntegratorsDiffEq = "5a33fad7-5ce4-5983-9f5d-5f26ceab5c96" +SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" +SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[sources] +GeometricIntegratorsDiffEq = {path = "../.."} + +[compat] +Aqua = "0.8" +SafeTestsets = "0.0.1, 0.1, 1" +SciMLTesting = "1.6" +Test = "1.10" +julia = "1.10" diff --git a/test/qa/qa.jl b/test/qa/qa.jl new file mode 100644 index 0000000..fa445df --- /dev/null +++ b/test/qa/qa.jl @@ -0,0 +1,29 @@ +using SciMLTesting, GeometricIntegratorsDiffEq, Test + +run_qa( + GeometricIntegratorsDiffEq; + explicit_imports = true, + ei_kwargs = (; + # All qualified accesses are sourced from each name's owner, but a handful of + # SciMLBase API-extension points / problem types are non-public (not exported + # or `public`-declared) and `ArrayPartition` is reached through the non-public + # `DiffEqBase.RecursiveArrayTools` module. These go public as the base libraries + # release; ignore them until then. Source package noted per name. + all_qualified_accesses_are_public = (; + ignore = ( + :AbstractDynamicalODEProblem, # SciMLBase + :AbstractODEAlgorithm, # SciMLBase + :AbstractODEProblem, # SciMLBase + :AbstractParameterizedFunction, # SciMLBase + :StandardODEProblem, # SciMLBase + :__solve, # SciMLBase + :build_solution, # SciMLBase + :has_jac, # SciMLBase + :has_tgrad, # SciMLBase + :unwrapped_f, # SciMLBase + :Success, # SciMLBase.ReturnCode (enum member; flagged only on Julia 1.10) + :RecursiveArrayTools, # DiffEqBase (module path to ArrayPartition) + ), + ), + ), +) diff --git a/test/runtests.jl b/test/runtests.jl index 81b4385..b27615c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,13 +4,14 @@ using SciMLTesting run_tests(; core = function () - @safetestset "GeometricIntegratorsDiffEq" begin + return @safetestset "GeometricIntegratorsDiffEq" begin include("core_tests.jl") end - return @safetestset "Explicit Imports" begin - include("explicit_imports_test.jl") - end end, + qa = (; + env = joinpath(@__DIR__, "qa"), + body = joinpath(@__DIR__, "qa", "qa.jl"), + ), groups = Dict( # NoPre runs the JET and AllocCheck tests in their own environment. The # original dispatcher ran these only for GROUP=="NoPre" (never as part of diff --git a/test/test_groups.toml b/test/test_groups.toml index e69be8a..f762020 100644 --- a/test/test_groups.toml +++ b/test/test_groups.toml @@ -3,3 +3,7 @@ versions = ["lts", "1", "pre"] [NoPre] versions = ["lts", "1"] + +[QA] +versions = ["lts", "1"] +in_all = false From 337cf23774a5db1bbb9d0ec89141427fbdd31c6d Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 26 Jun 2026 15:39:09 -0400 Subject: [PATCH 2/5] QA: trim public-API EI ignores now public in released base libs SciMLTesting 1.7 runs check_all_qualified_accesses_are_public only on Julia >= 1.11, and SciMLBase 3.24.0 made AbstractODEProblem, AbstractODEAlgorithm, AbstractDynamicalODEProblem, build_solution and has_jac public. Drop those plus :Success (ReturnCode.Success is public on 1.11+; the lts-only flag no longer fires since 1.7 skips the check there). Verified against registered releases (SciMLBase 3.24.0, DiffEqBase 7.5.7, SciMLTesting 1.7.0): QA group is 17/17 green on Julia 1.12 with the remaining six still-non-public ignores, and 15/15 green on Julia 1.10. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/qa/qa.jl | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index fa445df..ccf9ae5 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -4,24 +4,18 @@ run_qa( GeometricIntegratorsDiffEq; explicit_imports = true, ei_kwargs = (; - # All qualified accesses are sourced from each name's owner, but a handful of - # SciMLBase API-extension points / problem types are non-public (not exported - # or `public`-declared) and `ArrayPartition` is reached through the non-public - # `DiffEqBase.RecursiveArrayTools` module. These go public as the base libraries - # release; ignore them until then. Source package noted per name. + # The handful of names below are still non-public in their owners' latest + # registered releases (SciMLBase 3.24.0, DiffEqBase 7.5.7): a few SciMLBase + # API-extension points / problem types that have not yet been `public`-declared, + # and `ArrayPartition` reached through the non-public `DiffEqBase.RecursiveArrayTools` + # module. Ignore them until they go public upstream. all_qualified_accesses_are_public = (; ignore = ( - :AbstractDynamicalODEProblem, # SciMLBase - :AbstractODEAlgorithm, # SciMLBase - :AbstractODEProblem, # SciMLBase :AbstractParameterizedFunction, # SciMLBase :StandardODEProblem, # SciMLBase :__solve, # SciMLBase - :build_solution, # SciMLBase - :has_jac, # SciMLBase :has_tgrad, # SciMLBase :unwrapped_f, # SciMLBase - :Success, # SciMLBase.ReturnCode (enum member; flagged only on Julia 1.10) :RecursiveArrayTools, # DiffEqBase (module path to ArrayPartition) ), ), From 1e96bd1f4311c877fab0a5e26fa8c9d1df5cb9d1 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 27 Jun 2026 00:23:41 -0400 Subject: [PATCH 3/5] QA: bump SciMLTesting compat to 1.7; verify EI ignores vs released base libs SciMLTesting 1.7 gates the two public-API ExplicitImports checks (all_qualified_accesses_are_public, all_explicit_imports_are_public) to Julia >= 1.11, so they now RUN on 1.12 and SKIP on the 1.10 LTS. Verified the full GROUP=QA CI path (Pkg.test) against the registered releases SciMLBase 3.27.0 / DiffEqBase 7.6.0 / SciMLTesting 1.7.0 / ExplicitImports 1.15.0 / Aqua 0.8.16: * Julia 1.12: QA 17/17 (public-API checks run), 0 Fail/Error/Broken. * Julia 1.10: QA 15/15 (public-API checks skipped), 0 Fail/Error/Broken. The six all_qualified_accesses_are_public ignores are kept because each name is still genuinely non-public in its owner's released version (Base.ispublic == false on 3.27.0/7.6.0): AbstractParameterizedFunction, StandardODEProblem, __solve, has_tgrad, unwrapped_f (SciMLBase), and the DiffEqBase.RecursiveArrayTools module path to ArrayPartition. The source's owner-qualified accesses (now-public SciMLBase names) already pass all_qualified_accesses_via_owners on both versions; no migration was outstanding. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- Project.toml | 2 +- test/qa/Project.toml | 2 +- test/qa/qa.jl | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index 01729de..c047079 100644 --- a/Project.toml +++ b/Project.toml @@ -18,7 +18,7 @@ Reexport = "0.2, 1" SafeTestsets = "0.0.1, 0.1" SciMLBase = "2, 3" SciMLLogging = "1.10.1, 2" -SciMLTesting = "1.6" +SciMLTesting = "1.7" Test = "1.10" julia = "1.10" diff --git a/test/qa/Project.toml b/test/qa/Project.toml index 7906779..3145bfe 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -11,6 +11,6 @@ GeometricIntegratorsDiffEq = {path = "../.."} [compat] Aqua = "0.8" SafeTestsets = "0.0.1, 0.1, 1" -SciMLTesting = "1.6" +SciMLTesting = "1.7" Test = "1.10" julia = "1.10" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index ccf9ae5..2eaa09d 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -4,11 +4,12 @@ run_qa( GeometricIntegratorsDiffEq; explicit_imports = true, ei_kwargs = (; - # The handful of names below are still non-public in their owners' latest - # registered releases (SciMLBase 3.24.0, DiffEqBase 7.5.7): a few SciMLBase - # API-extension points / problem types that have not yet been `public`-declared, - # and `ArrayPartition` reached through the non-public `DiffEqBase.RecursiveArrayTools` - # module. Ignore them until they go public upstream. + # The names below are still non-public in their owners' latest registered + # releases (verified on Julia 1.12 against SciMLBase 3.27.0, DiffEqBase 7.6.0: + # `Base.ispublic` returns `false` for each): a few SciMLBase API-extension + # points / problem types not yet `public`-declared, and `ArrayPartition` + # reached through the non-public `DiffEqBase.RecursiveArrayTools` module. + # Ignore them until they go public upstream. all_qualified_accesses_are_public = (; ignore = ( :AbstractParameterizedFunction, # SciMLBase From 6ab80051c9e890a936dea732d762571f6ead4307 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 28 Jun 2026 06:03:56 -0400 Subject: [PATCH 4/5] QA: trim now-public ExplicitImports ignores Co-Authored-By: Chris Rackauckas --- test/qa/qa.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 2eaa09d..e017028 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -12,10 +12,8 @@ run_qa( # Ignore them until they go public upstream. all_qualified_accesses_are_public = (; ignore = ( - :AbstractParameterizedFunction, # SciMLBase :StandardODEProblem, # SciMLBase :__solve, # SciMLBase - :has_tgrad, # SciMLBase :unwrapped_f, # SciMLBase :RecursiveArrayTools, # DiffEqBase (module path to ArrayPartition) ), From 37926953d025751921e8567c422b71781271ef11 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 28 Jun 2026 10:29:26 -0400 Subject: [PATCH 5/5] QA: thorough EI ignore re-clean (drop stale incl via_owners, migrate non-public re-exports) Co-Authored-By: Chris Rackauckas --- Project.toml | 2 ++ src/GeometricIntegratorsDiffEq.jl | 1 + src/solve.jl | 4 ++-- test/qa/qa.jl | 12 +++++------- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Project.toml b/Project.toml index c047079..43d24e5 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ authors = ["Chris Rackauckas "] [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" GeometricIntegrators = "dcce2d33-59f6-5b8d-9047-0defad88ae06" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" @@ -14,6 +15,7 @@ SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" DiffEqBase = "6.62, 7" GeometricIntegrators = "0.15.5, 0.16" ODEProblemLibrary = "0.1, 1" +RecursiveArrayTools = "2, 3, 4" Reexport = "0.2, 1" SafeTestsets = "0.0.1, 0.1" SciMLBase = "2, 3" diff --git a/src/GeometricIntegratorsDiffEq.jl b/src/GeometricIntegratorsDiffEq.jl index 1f1b178..7b851fb 100644 --- a/src/GeometricIntegratorsDiffEq.jl +++ b/src/GeometricIntegratorsDiffEq.jl @@ -4,6 +4,7 @@ using Reexport: Reexport, @reexport @reexport using DiffEqBase: DiffEqBase using SciMLBase: SciMLBase, ReturnCode using SciMLLogging: @SciMLMessage +using RecursiveArrayTools: RecursiveArrayTools using GeometricIntegrators: GeometricIntegrators, CrankNicolson, Crouzeix, ExplicitEuler, ExplicitMidpoint, Gauss, Heun2, Heun3, ImplicitEuler, diff --git a/src/solve.jl b/src/solve.jl index 6bb4cf3..aec0611 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -126,7 +126,7 @@ function SciMLBase.__solve( ts = (prob.tspan[1] + dt):dt:prob.tspan[end] end - if u0 isa DiffEqBase.RecursiveArrayTools.ArrayPartition + if u0 isa RecursiveArrayTools.ArrayPartition _timeseries = [copy(vec(q)) for q in sol.q] elseif u0 isa AbstractArray _timeseries = [reshape(copy(vec(q)), sizeu) for q in sol.q] @@ -178,7 +178,7 @@ function SciMLBase.__solve( end _timeseries = [ - DiffEqBase.RecursiveArrayTools.ArrayPartition(copy(vec(q)), copy(vec(p))) + RecursiveArrayTools.ArrayPartition(copy(vec(q)), copy(vec(p))) for (q, p) in zip(sol.q, sol.p) ] end diff --git a/test/qa/qa.jl b/test/qa/qa.jl index e017028..e9ea72f 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -4,18 +4,16 @@ run_qa( GeometricIntegratorsDiffEq; explicit_imports = true, ei_kwargs = (; - # The names below are still non-public in their owners' latest registered - # releases (verified on Julia 1.12 against SciMLBase 3.27.0, DiffEqBase 7.6.0: - # `Base.ispublic` returns `false` for each): a few SciMLBase API-extension - # points / problem types not yet `public`-declared, and `ArrayPartition` - # reached through the non-public `DiffEqBase.RecursiveArrayTools` module. - # Ignore them until they go public upstream. + # The names below are still non-public in their owner's latest registered + # release (verified on Julia 1.12 against SciMLBase 3.28.1 that + # `Base.ispublic` returns `false` for each): SciMLBase API-extension + # points / problem types not yet `public`-declared. Ignore them until they + # go public upstream. all_qualified_accesses_are_public = (; ignore = ( :StandardODEProblem, # SciMLBase :__solve, # SciMLBase :unwrapped_f, # SciMLBase - :RecursiveArrayTools, # DiffEqBase (module path to ArrayPartition) ), ), ),