diff --git a/Project.toml b/Project.toml index 02c649a..36abf67 100644 --- a/Project.toml +++ b/Project.toml @@ -23,6 +23,8 @@ SIASparseArraysUnitful = ["SparseArrays", "Unitful"] SIAUnitful = "Unitful" [compat] +Aqua = "0.8" +ExplicitImports = "1.15" HiGHS = "1" Ipopt = "1" JuMP = "1" @@ -32,10 +34,14 @@ PrecompileTools = "1" Random = "1" SparseArrays = "1.10.0" StableRNGs = "1" +Statistics = "1" +Test = "1" Unitful = "1" julia = "1.10.10" [extras] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7" HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b" Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9" JuMP = "4076af6c-e467-56ae-b986-b466b2749572" @@ -47,4 +53,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" [targets] -test = ["HiGHS", "Ipopt", "JuMP", "OffsetArrays", "SparseArrays", "StableRNGs", "Statistics", "Test", "Unitful"] +test = ["Aqua", "ExplicitImports", "HiGHS", "Ipopt", "JuMP", "OffsetArrays", "SparseArrays", "StableRNGs", "Statistics", "Test", "Unitful"] diff --git a/README.md b/README.md index a5ccb1a..aee5a00 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://HolyLab.github.io/ScaleInvariantAnalysis.jl/dev/) [![Build Status](https://github.com/HolyLab/ScaleInvariantAnalysis.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/HolyLab/ScaleInvariantAnalysis.jl/actions/workflows/CI.yml?query=branch%3Amain) [![Coverage](https://codecov.io/gh/HolyLab/ScaleInvariantAnalysis.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/HolyLab/ScaleInvariantAnalysis.jl) +[![Aqua QA](https://juliatesting.github.io/Aqua.jl/dev/assets/badge.svg)](https://github.com/JuliaTesting/Aqua.jl) This package computes **covers** of matrices: non-negative vectors `a` (and `b`) such that `a[i] * b[j] >= abs(A[i, j])` for all `i`, `j`. Covers are the diff --git a/ext/SIASparseArrays.jl b/ext/SIASparseArrays.jl index fbf453a..0a3500b 100644 --- a/ext/SIASparseArrays.jl +++ b/ext/SIASparseArrays.jl @@ -1,9 +1,9 @@ module SIASparseArrays -using LinearAlgebra -using SparseArrays +using LinearAlgebra: LinearAlgebra, Hermitian, Symmetric +using SparseArrays: SparseArrays, SparseMatrixCSC, nonzeros, nzrange, rowvals using ScaleInvariantAnalysis -using ScaleInvariantAnalysis: AbsLog, AbsLinear, _abslinear2_iter!, _abslinear1_iter!, _symcover_min_abslog2, _cover_min_abslog2 +using ScaleInvariantAnalysis: AbsLog, _symcover_min_abslog2, _cover_min_abslog2 # ============================================================ # Support traversal diff --git a/ext/SIASparseArraysUnitful.jl b/ext/SIASparseArraysUnitful.jl index bb33aee..9706d0d 100644 --- a/ext/SIASparseArraysUnitful.jl +++ b/ext/SIASparseArraysUnitful.jl @@ -5,10 +5,10 @@ module SIASparseArraysUnitful # are ambiguous there. These methods resolve that pair. They are the only overlap -- # every other sparse method leaves its matrix slot untyped. -using LinearAlgebra +using LinearAlgebra: LinearAlgebra, Hermitian, Symmetric using ScaleInvariantAnalysis using ScaleInvariantAnalysis: AbsLog -using SparseArrays +using SparseArrays: SparseArrays, SparseMatrixCSC using Unitful: Quantity const SIA = ScaleInvariantAnalysis diff --git a/ext/SIAUnitful.jl b/ext/SIAUnitful.jl index b2171f9..e5c20e3 100644 --- a/ext/SIAUnitful.jl +++ b/ext/SIAUnitful.jl @@ -1,10 +1,9 @@ module SIAUnitful -using LinearAlgebra +using LinearAlgebra: LinearAlgebra using ScaleInvariantAnalysis using ScaleInvariantAnalysis: AbsLog, AbsLinear -using Unitful -using Unitful: FreeUnits, Quantity, Unit +using Unitful: Unitful, FreeUnits, Quantity, Unit, unit, ustrip const SIA = ScaleInvariantAnalysis diff --git a/src/ScaleInvariantAnalysis.jl b/src/ScaleInvariantAnalysis.jl index 8f51630..9be1ca7 100644 --- a/src/ScaleInvariantAnalysis.jl +++ b/src/ScaleInvariantAnalysis.jl @@ -1,8 +1,9 @@ module ScaleInvariantAnalysis -using LinearAlgebra -using PrecompileTools -using Random +using LinearAlgebra: LinearAlgebra, Adjoint, Bidiagonal, Diagonal, SymTridiagonal, + Symmetric, Transpose, Tridiagonal, dot, norm +using PrecompileTools: PrecompileTools, @compile_workload +using Random: Random, AbstractRNG, MersenneTwister export AbsLog, AbsLinear export cover_objective diff --git a/test/runtests.jl b/test/runtests.jl index 2ae7ccd..e0b8eb0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,6 +8,8 @@ using OffsetArrays using Statistics: median using Random: MersenneTwister using StableRNGs: StableRNG +using Aqua +using ExplicitImports using Test include("helpers.jl") # iscover, covaries, PENALTIES @@ -25,6 +27,36 @@ include("helpers.jl") # iscover, covaries, PENALTIES include("unitful.jl") # dimensional covers via the Unitful extension include("invariants.jl") # shared conventions checked across every notion + Aqua.test_all(ScaleInvariantAnalysis) + + @testset "ExplicitImports" begin + # The public-ness checks consult `Base.ispublic` only on 1.11+; before that they + # fall back to `isexported` and flag every `public`-but-unexported binding, so + # they are meaningful only on 1.11+. The other five checks run on every version. + # + # These are this package's own internals, which its extensions legitimately + # extend and call: extension and package ship from one repo at one version, so + # there is no cross-package promise to break. + internals = (:_cover_min_abslog2, :_symcover_min_abslog2, + :_prepare_cover_start!, :_prepare_symcover_start!, + :_prepare_soft_cover_start!, :_prepare_soft_symcover_start!, + :foreach_support, :foreach_support_sym, + :cover_min_jump, :symcover_min_jump) + # Non-public names owned by other packages, each with no public equivalent: + # `FreeUnits`/`Unit` are Unitful's unit representation, `Optimizer` is the + # solver handle JuMP's own documented `Model(HiGHS.Optimizer)` entry point + # names, and `register_error_hint` is Base-internal. + foreign = (:FreeUnits, :Unit, :Optimizer, :Experimental, :register_error_hint) + test_explicit_imports( + ScaleInvariantAnalysis; + all_explicit_imports_are_public = VERSION >= v"1.11" ? + (; ignore = (internals..., foreign...)) : false, + all_qualified_accesses_are_public = VERSION >= v"1.11" ? + (; ignore = (internals..., foreign...)) : false, + ) + end + + # Aqua checks the package alone; the extensions need their own sweep. @testset "method ambiguities" begin @test isempty(detect_ambiguities(ScaleInvariantAnalysis; recursive=true)) for extname in (:SIASparseArrays, :SIAJuMP, :SIAIpopt, :SIAUnitful, :SIASparseArraysUnitful)