Skip to content

Commit

Permalink
Merge pull request #187 from JuliaAI/in
Browse files Browse the repository at this point in the history
Add Aqua.jl to tests
  • Loading branch information
ablaom authored Jan 11, 2024
2 parents 4393ab5 + 4ac5584 commit 6da0fa5
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 80 deletions.
5 changes: 4 additions & 1 deletion .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ coverage:
status:
project:
default:
threshold: 0.5%
threshold: 0.5%
patch:
default:
target: 80%
16 changes: 14 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,23 @@ ScientificTypesBase = "30f210dd-8aff-4c5f-94ba-8e64358c1161"
StatisticalTraits = "64bff920-2084-43da-a3e6-9bb72801c0c9"

[compat]
ScientificTypesBase = "3.0"
Aqua = "0.8"
CategoricalArrays = "0.10"
DataFrames = "1"
Distances = "0.10"
InteractiveUtils = "<0.0.1, 1"
Markdown = "<0.0.1, 1"
OrderedCollections = "1"
Random = "<0.0.1, 1"
ScientificTypes = "3"
ScientificTypesBase = "3"
StatisticalTraits = "3.2"
Tables = "1"
Test = "<0.0.1, 1"
julia = "1.6"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Expand All @@ -25,4 +37,4 @@ Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["CategoricalArrays", "DataFrames", "Distances", "InteractiveUtils", "Markdown", "OrderedCollections", "ScientificTypes", "Tables", "Test"]
test = ["Aqua", "CategoricalArrays", "DataFrames", "Distances", "InteractiveUtils", "Markdown", "OrderedCollections", "ScientificTypes", "Tables", "Test"]
6 changes: 3 additions & 3 deletions src/data_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ end
# int

"""
int(x; type=nothing)
int(x)
The positional integer of the `CategoricalString` or `CategoricalValue` `x`, in
the ordering defined by the pool of `x`. The type of `int(x)` is the reference
Expand Down Expand Up @@ -96,9 +96,9 @@ julia> int(v)
```
See also: [`decoder`](@ref).
"""
function int(x; type::Union{Nothing, Type{T}}=nothing) where T <: Real
function int(x; type=nothing)
type === nothing && return int(get_interface_mode(), x)
return convert.(T, int(get_interface_mode(), x))
return convert.(type, int(get_interface_mode(), x))
end

int(::LightInterface, x) = errlight("int")
Expand Down
5 changes: 3 additions & 2 deletions src/equality.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ function is_same_except(m1::M1,
is_same_except(
getproperty(m1, name),
getproperty(m2, name)
) ||
) ||
getproperty(m1, name) isa AbstractRNG ||
getproperty(m2, name) isa AbstractRNG
) || return false
Expand Down Expand Up @@ -155,7 +155,8 @@ function special_in(x, itr)::Union{Bool,Missing}
end

Base.in(x::MLJType, itr::Set) = special_in(x, itr)
Base.in(x::MLJType, itr::AbstractVector) = special_in(x, itr)
Base.in(x::MLJType, itr::AbstractVector{<:MLJType}) = special_in(x, itr)
Base.in(x::MLJType, itr::AbstractRange{<:MLJType}) = special_in(x, itr)
Base.in(x::MLJType, itr::Tuple) = special_in(x, itr)

# A version of `in` that actually uses `==`:
Expand Down
59 changes: 24 additions & 35 deletions src/model_traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,50 +97,39 @@ end
# in `prediction_type` for models which, historically, have not
# implemented the trait.

# Actually, this has proven more trouble than it's worth and should be removed in 2.0.
# See https://discourse.julialang.org/t/deconstructing-unionall-types/108328 to appreciate
# some of the complications.

function StatTraits.predict_scitype(
M::Type{<:Union{Probabilistic, ProbabilisticDetector}}
)
return _density(target_scitype(M))
end

_density(::Any) = Unknown

for T in [:Continuous, :Count, :Textual]
eval(
quote
function _density(::Type{AbstractArray{$T, D}}) where D
return AbstractArray{Density{$T}, D}
end
end
)
end
const SCALAR_SCITYPES_EXS =
[:Finite, :Multiclass, :OrderedFactor, :Infinite, :Continuous, :Count, :Textual]

for T in [:Finite, :Multiclass, :OrderedFactor, :Infinite, :Continuous, :Count, :Textual]
eval(
quote
function _density(::Type{AbstractArray{<:$T, D}}) where D
return AbstractArray{Density{<:$T}, D}
end
const SCALAR_SCITYPES =
eval.([:Finite, :Multiclass, :OrderedFactor, :Infinite, :Continuous, :Count, :Textual])

_density(::Type{Table($T)}) = Table(Density{$T})
end
)
function _density(t)
for T in SCALAR_SCITYPES
t == AbstractVector{<:T} && return AbstractVector{Density{<:T}}
t == AbstractMatrix{<:T} && return AbstractMatrix{Density{<:T}}
t == Table(T) && return Table{<:AbstractVector{<:Density{<:T}}}
end
for T in [Finite, Multiclass, OrderedFactor]
t == Table(T{2}) && return Table(Density{<:T{2}})
end
return Unknown
end


for T in [:Finite, :Multiclass, :OrderedFactor]
eval(
for T in SCALAR_SCITYPES_EXS
quote
function _density(::Type{AbstractArray{<:$T{N}, D}}) where {N, D}
return AbstractArray{Density{<:$T{N}}, D}
end

function _density(::Type{AbstractArray{$T{N}, D}}) where {N, D}
return AbstractArray{Density{$T{N}}, D}
end

_density(::Type{Table($T{N})}) where N = Table(Density{$T{N}})
end
)
_density(::Type{<:AbstractArray{W, D}}) where {W<:$T, D} =
AbstractArray{Density{W}, D}
_density(::Type{<:Table{<:AbstractVector{W}}}) where W<:$T =
Table(Density{W})
end |> eval
end

4 changes: 4 additions & 0 deletions test/aqua.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Aqua
import MLJModelInterface

Aqua.test_all(MLJModelInterface, ambiguities=true)
27 changes: 14 additions & 13 deletions test/data_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ end
# needing the `FullInterface`.
X = (1, 2, 3)
@test_throws M.InterfaceError matrix(X)

X = (a=[1, 2, 3], b=[1, 2, 3])
@test_throws M.InterfaceError matrix(X)
end

@testset "matrix-full" begin
setfull()
M.matrix(::FI, ::Val{:table}, X; kw...) = Tables.matrix(X; kw...)
# next line commented out as already defined in test/mode.jl:
# M.matrix(::FI, ::Val{:table}, X; kw...) = Tables.matrix(X; kw...)
X = (a=[1, 2, 3], b=[1, 2, 3])
@test matrix(X) == hcat([1, 2, 3], [1, 2, 3])
end
Expand Down Expand Up @@ -120,14 +121,14 @@ end
# ------------------------------------------------------------------------
@testset "istable" begin
# Nothing stops someone from implementing a Tables.jl
# interface that subtypes `AbstractArray`, so therefore
# interface that subtypes `AbstractArray`, so therefore
# `istable` should throw an error for `LightInterface`
setlight()
X = rand(5)
@test_throws M.InterfaceError M.istable(X)
X = randn(5, 5)
@test_throws M.InterfaceError M.istable(X)

# The method runs in `FullInterface`
setfull()
X = rand(5)
Expand Down Expand Up @@ -184,10 +185,10 @@ end
X = ones(5)
@test nrows(X) == 5
X = ones(5, 3)
@test nrows(X) == 5
# It doesn't make sense to get the numbers of rows for
# `AbstractArray`'s of dimension 3 or more. Except if these are
# defined as Tables. Hence `FullInterface` would be required to check this
@test nrows(X) == 5
# It doesn't make sense to get the numbers of rows for
# `AbstractArray`'s of dimension 3 or more. Except if these are
# defined as Tables. Hence `FullInterface` would be required to check this
X = ones(5, 3, 2)
@test_throws ArgumentError nrows(X)
M.nrows(::FI, ::Val{:table}, X) = Tables.rowcount(X)
Expand Down Expand Up @@ -220,13 +221,13 @@ end

@testset "select-full" begin
setfull()

# test fallback
X = nothing
@test selectrows(X, 1) === nothing
@test selectcols(X, 1) === nothing
@test select(X, 1, 2) === nothing

# vector
X = ones(5)
@test selectrows(X, 1) == [1.0]
Expand Down Expand Up @@ -273,11 +274,11 @@ end

project(t::NamedTuple, label::Colon) = t
project(t::NamedTuple, label::Symbol) = project(t, [label,])

function project(t::NamedTuple, indices::AbstractArray{<:Integer})
return NamedTuple{tuple(keys(t)[indices]...)}(tuple([t[i] for i in indices]...))
end

project(t::NamedTuple, i::Integer) = project(t, [i,])

X = (x=[1, 2, 3], y=[4, 5, 6], z=[0, 0, 0])
Expand All @@ -292,7 +293,7 @@ end
@test select(X, :, 1) == [1, 2, 3]
@test selectcols(X, :x) == [1, 2, 3]
@test select(X, 1:2, :z) == [0, 0]

# extra tests by Anthony
X = (x=[1, 2, 3], y=[10, 20, 30], z= [:a, :b, :c])
@test select(X, 2, :y) == 20
Expand Down
6 changes: 0 additions & 6 deletions test/metadata_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,6 @@ metadata_pkg(FooRegressor2,
is_wrapper=false
)

# this is added in MLJBase but not in MLJModelInterface, to avoid
# InteractiveUtils as dependency:
setfull()
M.implemented_methods(::FI, M::Type{<:MLJType}) =
getfield.(methodswith(M), :name)

const HEADER2 = MLJModelInterface.doc_header(FooRegressor2, augment=true)

@doc """
Expand Down
12 changes: 2 additions & 10 deletions test/model_traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,6 @@ M.human_name(::Type{<:U1}) = "funky model"

setfull()

function M.implemented_methods(::FI, M::Type{<:MLJType})
return getfield.(methodswith(M), :name)
end

@test Set(implemented_methods(mp)) == Set([:clean!,:bar,:foo])
end

Expand All @@ -140,19 +136,15 @@ end
M._density(AbstractVector{<:T}),
AbstractVector{Density{<:T}}
)
@test M._density(Table(T)) == Table(Density{T})
@test M._density(Table(T)) == Table(Density{<:T})
end

for T in [Finite, Multiclass, OrderedFactor]
@test ==(
M._density(AbstractArray{<:T{2},3}),
AbstractArray{Density{<:T{2}},3}
)
@test ==(
M._density(AbstractArray{T{2},3}),
AbstractArray{Density{T{2}},3}
)
@test M._density(Table(T{2})) == Table(Density{T{2}})
@test M._density(Table(T{2})) == Table(Density{<:T{2}})
end
end

Expand Down
43 changes: 35 additions & 8 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,45 @@ using Tables, Distances, CategoricalArrays, InteractiveUtils
import DataFrames: DataFrame
import Markdown
import OrderedCollections
import Aqua

const M = MLJModelInterface
const FI = M.FullInterface

setlight() = M.set_interface_mode(M.LightInterface())
setfull() = M.set_interface_mode(M.FullInterface())

include("mode.jl")
include("parameter_inspection.jl")
include("data_utils.jl")
include("metadata_utils.jl")
include("model_def.jl")
include("model_api.jl")
include("model_traits.jl")
include("equality.jl")
@testset "mode.jl" begin
include("mode.jl")
end

@testset "parameter_inspection.jl" begin
include("parameter_inspection.jl")
end

@testset "data_utils.jl" begin
include("data_utils.jl")
end

@testset "metadata_utils.jl" begin
include("metadata_utils.jl")
end
@testset "model_def.jl" begin
include("model_def.jl")
end

@testset "model_api.jl" begin
include("model_api.jl")
end

@testset "model_traits.jl" begin
include("model_traits.jl")
end

@testset "equality.jl" begin
include("equality.jl")
end

@testset "aqua.jl" begin
include("aqua.jl")
end

0 comments on commit 6da0fa5

Please sign in to comment.