From 652b79354e12a935a3587452e24c2d18e2a412a6 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 21 Jul 2023 11:56:56 -0500 Subject: [PATCH] Eliminate old version cruft Now that we require Julia 1.6, a lot of cruft can be removed. This includes the nominal dependency on AbstractFFTs. This also improves a few method definitions and now passes Aqua's `unbound_args` test. --- Project.toml | 2 -- src/ImageCore.jl | 22 ++++----------- src/colorchannels.jl | 51 +++++++++++----------------------- src/convert_reinterpret.jl | 57 ++------------------------------------ src/deprecations.jl | 24 +++++++--------- src/functions.jl | 20 ------------- src/stackedviews.jl | 2 +- test/colorchannels.jl | 2 +- test/runtests.jl | 6 ++-- test/show.jl | 16 ++++------- 10 files changed, 44 insertions(+), 158 deletions(-) delete mode 100644 src/functions.jl diff --git a/Project.toml b/Project.toml index a10cc4f..5aa9fba 100644 --- a/Project.toml +++ b/Project.toml @@ -3,7 +3,6 @@ uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" version = "0.10.1" [deps] -AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4" Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" @@ -15,7 +14,6 @@ PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" [compat] -AbstractFFTs = "0.4, 0.5, 1.0" ColorVectorSpace = "0.10" Colors = "0.12" FixedPointNumbers = "0.8" diff --git a/src/ImageCore.jl b/src/ImageCore.jl index cc4eff5..76bb1b6 100644 --- a/src/ImageCore.jl +++ b/src/ImageCore.jl @@ -30,11 +30,7 @@ const ColorA{N,C,T} = ColorAlpha{C,T,N} const NonparametricColors = Union{RGB24,ARGB32,Gray24,AGray32} const Color1Array{C<:Color1,N} = AbstractArray{C,N} # Type that arises from reshape(reinterpret(To, A), sz): -if VERSION >= v"1.6.0-DEV.1083" - const RRArray{To,From,M,P} = Base.ReinterpretArray{To,M,From,P,true} -else - const RRArray{To,From,N,M,P} = Base.ReshapedArray{To,N,Base.ReinterpretArray{To,M,From,P}} -end +const RRArray{To,From,M,P} = Base.ReinterpretArray{To,M,From,P,true} const RGArray = Union{Base.ReinterpretArray{<:AbstractGray,M,<:Number,P}, Base.ReinterpretArray{<:Number,M,<:AbstractGray,P}} where {M,P} # delibrately not export these constants to enable extensibility for downstream packages @@ -173,20 +169,14 @@ function throw_ffterror(io, @nospecialize(f), x, dims=1:ndims(x)) print(io, '\n', f, " not defined for eltype $(eltype(x)). Use channelview, and likely $newdims for the dims in the fft.") end -if Base.VERSION >= v"1.5" - function __init__() - Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs - if nameof(exc.f) ∈ (:fft, :rfft, :plan_fft, :plan_rfft, :realfloat) && argtypes[1] <: AbstractArray{<:Colorant} - throw_ffterror(io, exc.f, exc.args...) - end +function __init__() + Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs + if nameof(exc.f) ∈ (:fft, :rfft, :plan_fft, :plan_rfft, :realfloat) && argtypes[1] <: AbstractArray{<:Colorant} + throw_ffterror(io, exc.f, exc.args...) end end -else - include("functions.jl") end -if VERSION >= v"1.4.2" # work around https://github.com/JuliaLang/julia/issues/34121 - include("precompile.jl") -end +include("precompile.jl") end ## module diff --git a/src/colorchannels.jl b/src/colorchannels.jl index 811c835..ffca438 100644 --- a/src/colorchannels.jl +++ b/src/colorchannels.jl @@ -27,22 +27,19 @@ dimorder(::Type{<:AlphaColor{<:Color3,T,N}}) where {T,N} = ColorChanPerm((4, 1, const ColorChanPermSubArray{T,N,P,I<:Tuple,L} = SubArray{T,N,P,I,L} -if VERSION >= v"1.6.0-DEV.1083" - const RRPermArray{To,From,M,P<:ColorChanPermSubArray} = - RRArray{To,From,M,P} -else - const RRPermArray{To,From,N,M,P<:ColorChanPermSubArray} = - RRArray{To,From,N,M,P} -end +const RRPermArray{To,From,M,P<:ColorChanPermSubArray} = + RRArray{To,From,M,P} # This type exists solely to set multiple values in the color channel axis struct NVector{T,N} <: AbstractVector{T} v::NTuple{N,T} + + NVector{T,N}(x::NTuple{N}) where {T,N} = new{T,N}(x) end Base.IndexStyle(::Type{<:NVector}) = IndexLinear() Base.size(v::NVector{T,N}) where {T,N} = (N,) Base.getindex(v::NVector, i::Int) = v.v[i] -NVector(x::Vararg{T,N}) where {T,N} = NVector{T,N}(x) +NVector(x1::T, x::Vararg{T,N}) where {T,N} = NVector{T,N+1}((x1, x...)) @inline Base.setindex!(A::RRPermArray{<:RGBX,<:Number,N}, val::AbstractRGB, i::Vararg{Int,N}) where N = setindex!(parent(parent(parent(A))), NVector(red(val), green(val), blue(val)), :, i...) @@ -66,13 +63,8 @@ A = channelview(img) # a 3×10×10 array See also: [`colorview`](@ref) """ channelview(A::AbstractArray{T}) where {T<:Number} = A -if VERSION >= v"1.6.0-DEV.1083" - channelview(A::RRArray{<:Colorant,<:Number}) = parent(A) - channelview(A::RRPermArray{<:Colorant,<:Number}) = parent(parent(A)) -else - channelview(A::RRArray{<:Colorant,<:Number}) = parent(parent(A)) - channelview(A::RRPermArray{<:Colorant,<:Number}) = parent(parent(parent(A))) -end +channelview(A::RRArray{<:Colorant,<:Number}) = parent(A) +channelview(A::RRPermArray{<:Colorant,<:Number}) = parent(parent(A)) channelview(A::Base.ReinterpretArray{<:AbstractGray,M,<:Number}) where M = parent(A) channelview(A::AbstractArray{RGB{T}}) where {T} = reinterpretc(T, A) function channelview(A::AbstractArray{C}) where {C<:AbstractRGB} @@ -117,25 +109,14 @@ _ccolorview(::Type{C}, A::RRPermArray{T,C}) where {C<:Colorant,T<:Number} = parent(parent(parent(A))) _ccolorview(::Type{C}, A::RRArray{T,C}) where {C<:Colorant,T<:Number} = parent(parent(A)) -if VERSION >= v"1.6.0-DEV.1083" - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:RGB,T<:Number,M,AA} = - reshape(parent(A), Base.tail(axes(parent(A)))) - # _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:RGB,T<:Number,M,AA} = - # parent(A) - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:Color,T<:Number,M,AA} = - reshape(parent(A), Base.tail(axes(parent(A)))) - # _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:Color,T<:Number,M,AA} = - # parent(A) -else - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractGray,T<:Number,M} = - parent(A) - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:RGB,T<:Number,M} = - reshape(parent(A), Base.tail(axes(parent(A)))) - _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:Color,T<:Number,M} = - reshape(parent(A), Base.tail(axes(parent(A)))) - end -# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractRGB,T<:Number,M} = -# _colorview_reorder(C, A) +_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:RGB,T<:Number,M,AA} = + reshape(parent(A), Base.tail(axes(parent(A)))) +# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:RGB,T<:Number,M,AA} = +# parent(A) +_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:Color,T<:Number,M,AA} = + reshape(parent(A), Base.tail(axes(parent(A)))) +# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:Color,T<:Number,M,AA} = +# parent(A) _ccolorview(::Type{C}, A::AbstractArray{T}) where {C<:Colorant,T<:Number} = __ccolorview(C, A) # necessary to avoid ambiguities from dispatch on eltype __ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:RGB{T}} = reinterpretc(C, A) @@ -198,7 +179,7 @@ Create a function that is equivalent to `(As...) -> colorview(C, Ax...)`. ```jldoctest; setup = :(using ImageCore) julia> ones(Float32, 2, 2) |> colorview(Gray) -2×2 reinterpret($(VERSION >= v"1.6.0-DEV.1083" ? "reshape, " : "")Gray{Float32}, ::$(Array{Float32,2}))$(VERSION >= v"1.6.0-DEV.1083" ? " with eltype Gray{Float32}" : ""): +2×2 reinterpret(reshape, Gray{Float32}, ::$(Array{Float32,2})) with eltype Gray{Float32}: Gray{Float32}(1.0) Gray{Float32}(1.0) Gray{Float32}(1.0) Gray{Float32}(1.0) ``` diff --git a/src/convert_reinterpret.jl b/src/convert_reinterpret.jl index 6ce1cde..c87b8d1 100644 --- a/src/convert_reinterpret.jl +++ b/src/convert_reinterpret.jl @@ -2,61 +2,8 @@ @pure samesize(::Type{T}, ::Type{S}) where {T,S} = sizeof(T) == sizeof(S) -if VERSION >= v"1.6.0-DEV.1083" - reinterpretc(::Type{T}, a::AbstractArray) where T = reinterpret(reshape, ccolor_number(T, eltype(a)), a) - reinterpretc(::Type{T}, a::Base.ReinterpretArray{S,N,T,AA,true}) where {T,S,N,AA<:AbstractArray{T}} = parent(a) -else - # Color->Color - function reinterpretc(::Type{CV1}, a::Array{CV2,1}) where {CV1<:Colorant,CV2<:Colorant} - CV = ccolor(CV1, CV2) - l = (length(a)*sizeof(CV2))÷sizeof(CV1) - l*sizeof(CV1) == length(a)*sizeof(CV2) || throw(ArgumentError("sizes are incommensurate")) - reshape(reinterpret(CV, a), (l,)) - end - function reinterpretc(::Type{CV1}, a::AbstractArray{CV2}) where {CV1<:Colorant,CV2<:Colorant} - CV = ccolor(CV1, CV2) - if samesize(CV, CV2) - return reshape(reinterpret(CV, a), size(a)) - end - throw(ArgumentError("result shape not specified")) - end - - # Color->T - function reinterpretc(::Type{T}, a::AbstractArray{CV}) where {T<:Number,CV<:Colorant} - if samesize(T, CV) - return reinterpret(T, a) - end - axs = axes(a) - if sizeof(CV) == sizeof(T)*_len(CV) - return reinterpret(T, reshape(a, Base.OneTo(1), axs...)) - end - throw(ArgumentError("result shape not specified")) - end - reinterpretc(::Type{T}, a::AbstractArray{CV,0}) where {T<:Number,CV<:Colorant} = - reinterpret(T, reshape(a, 1)) - - _len(::Type{C}) where {C} = _len(C, eltype(C)) - _len(::Type{C}, ::Type{Any}) where {C} = error("indeterminate type") - _len(::Type{C}, ::Type{T}) where {C,T} = sizeof(C) ÷ sizeof(T) - - ## T->Color - # We have to distinguish two forms of call: - # form 1: reinterpretc(RGB{N0f8}, img) - # form 2: reinterpretc(RGB, img) - function reinterpretc(CV::Type{<:Colorant}, a::AbstractArray{T}) where T<:Number # {CV<:Colorant,T<:Number} - @noinline throwdm(C::Type, ind1) = - throw(DimensionMismatch("indices $ind1 are not consistent with color type $C")) - CVT = ccolor_number(CV, T) - if samesize(CVT, T) - return reinterpret(CVT, a) - end - axs = axes(a) - if axs[1] == Base.OneTo(sizeof(CVT) ÷ sizeof(eltype(CVT))) - return reshape(reinterpret(CVT, a), tail(axs)) - end - throwdm(CV, axs[1]) - end -end +reinterpretc(::Type{T}, a::AbstractArray) where T = reinterpret(reshape, ccolor_number(T, eltype(a)), a) +reinterpretc(::Type{T}, a::Base.ReinterpretArray{S,N,T,AA,true}) where {T,S,N,AA<:AbstractArray{T}} = parent(a) # ccolor_number converts form 2 calls to form 1 calls ccolor_number(::Type{T}, ::Any) where T<:Number = T diff --git a/src/deprecations.jl b/src/deprecations.jl index e59a676..a03a3b4 100644 --- a/src/deprecations.jl +++ b/src/deprecations.jl @@ -1,19 +1,15 @@ const warned_once = Ref(false) -if VERSION >= v"1.5" - function forced_depwarn(msg, sym) - opts = Base.JLOptions() - if !warned_once[] && !(opts.depwarn == 1) - @warn msg - @info """It is recommended that you fix this now to avoid breakage when a new version is released and this warning is removed. - Tip: to see all deprecation warnings together with code locations, launch Julia with `--depwarn=yes` and rerun your code.""" - warned_once[] = true - else - Base.depwarn(msg, sym) - end - return nothing +function forced_depwarn(msg, sym) + opts = Base.JLOptions() + if !warned_once[] && !(opts.depwarn == 1) + @warn msg + @info """It is recommended that you fix this now to avoid breakage when a new version is released and this warning is removed. + Tip: to see all deprecation warnings together with code locations, launch Julia with `--depwarn=yes` and rerun your code.""" + warned_once[] = true + else + Base.depwarn(msg, sym) end -else - forced_depwarn(msg, sym) = Base.depwarn(msg, sym) + return nothing end # a perhaps "permanent" deprecation diff --git a/src/functions.jl b/src/functions.jl deleted file mode 100644 index 8e6f553..0000000 --- a/src/functions.jl +++ /dev/null @@ -1,20 +0,0 @@ -import AbstractFFTs: fft, rfft, plan_fft, plan_rfft - -# It's better not to define fft on Colorant arrays, because keeping -# track of the color dimension and the fft-dims is prone to omissions -# or problems due to later operations. So we put the bookkeeping on -# the user, but we try to give helpful suggestions. - -function throw_ffterror(f, x, dims=1:ndims(x)) - newdims = plus(dims, channelview_dims_offset(x)) - error("$f not defined for eltype $(eltype(x)). Use channelview, and likely $newdims for the dims in the fft.") -end - -for f in (:fft, :rfft) - pf = Symbol("plan_", f) - @eval begin - $f(x::AbstractArray{C}) where {C<:Colorant} = throw_ffterror($f, x) - $f(x::AbstractArray{C}, dims) where {C<:Colorant} = throw_ffterror($f, x, dims) - $pf(x::AbstractArray{C}; kws...) where {C<:Colorant} = throw_ffterror($pf, x) - end -end diff --git a/src/stackedviews.jl b/src/stackedviews.jl index 93baeb3..c35d3bf 100644 --- a/src/stackedviews.jl +++ b/src/stackedviews.jl @@ -102,7 +102,7 @@ struct ZeroArray{T,N,R<:AbstractUnitRange} <: AbstractArray{T,N} inds::NTuple{N,R} end -ZeroArrayPromise{T}(inds::NTuple{N,R}) where {T,N,R<:AbstractUnitRange} = ZeroArray{T,N,R}(inds) +ZeroArrayPromise{T}(inds::Tuple{R,Vararg{R,N}}) where {T,N,R<:AbstractUnitRange} = ZeroArray{T,N+1,R}(inds) ZeroArrayPromise{T}(inds::NTuple{N,AbstractUnitRange}) where {T,N} = ZeroArrayPromise{T}(promote(inds...)) Base.eltype(::Type{ZeroArrayPromise{T}}) where {T} = T diff --git a/test/colorchannels.jl b/test/colorchannels.jl index 7e93e40..77e29fa 100644 --- a/test/colorchannels.jl +++ b/test/colorchannels.jl @@ -408,7 +408,7 @@ end @test @inferred(axes(v)) == (IdentityUnitRange(-1:1), IdentityUnitRange(-2:2)) @test @inferred(v[0,0]) === RGB(a[1,0,0], a[2,0,0], a[3,0,0]) a = OffsetArray(rand(3, 3, 5), 0:2, -1:1, -2:2) - @test_throws (VERSION >= v"1.6.0-DEV.1083" ? ArgumentError : DimensionMismatch) colorview(RGB, a) + @test_throws ArgumentError colorview(RGB, a) end @testset "Custom/divergent axis types" begin diff --git a/test/runtests.jl b/test/runtests.jl index f3a541e..4ab417d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,11 +11,11 @@ using Aqua, Documenter # for meta quality checks ambiguities=false, project_extras=true, deps_compat=true, - stale_deps= v"1.4" <= Base.VERSION < v"1.5", # we don't use AbstractFFTs on 1.5+, SnoopPrecompile on <1.4 + stale_deps=true, # FIXME? re-enable the `piracy` test - piracy=false, # Base.VERSION >= v"1.5", # need the register_error_hint for AbstractFFTs + piracy=false, # currently just `float` and `paddedviews` project_toml_formatting=true, - unbound_args=false, # FIXME: it fails when this is true + unbound_args=true, ) DocMeta.setdocmeta!(ImageCore, :DocTestSetup, :(using ImageCore); recursive=true) end diff --git a/test/show.jl b/test/show.jl index c521b16..ad8db2d 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1,13 +1,9 @@ using ImageCore, Colors, FixedPointNumbers, OffsetArrays, Test -if VERSION >= v"1.2.0-DEV.229" - sumsz(img) = Base.dims2string(size(img)) * ' ' -else - sumsz(img) = "" -end +sumsz(img) = Base.dims2string(size(img)) * ' ' -const rrstr = VERSION >= v"1.6.0-DEV.1083" ? "reshape, " : "" -rrdim(n) = VERSION >= v"1.6.0-DEV.1083" ? n-1 : n +const rrstr = "reshape, " +rrdim(n) = n-1 # N0f8 is shown as either N0f8 or Normed{UInt8, 8} # RGB is shown as ColorTypes.RGB or RGB @@ -25,8 +21,7 @@ RGB_str = typestring(RGB) v = view(rgb32, 2:3, :) @test summary(v) == "2×5 view(::Array{RGB{Float32},2}, 2:3, :) with eltype $(RGB_str){Float32}" a = channelview(rgb32) - @test summary(a) == (VERSION >= v"1.6.0-DEV.1083" ? "3×3×5 reinterpret(reshape, Float32, ::Array{RGB{Float32},2}) with eltype Float32" : - "3×3×5 reinterpret(Float32, ::Array{RGB{Float32},3})") + @test summary(a) == "3×3×5 reinterpret(reshape, Float32, ::Array{RGB{Float32},2}) with eltype Float32" num64 = rand(3,5) b = colorview(RGB, num64) str = summary(b) @@ -51,11 +46,10 @@ RGB_str = typestring(RGB) @test occursin("5×3 PermutedDimsArray(reinterpret", str) && occursin("N0f16", str) && occursin("::$(typeof(rand16))), (2, 1)", str) && occursin("with eltype $(N0f16_str)", str) g = channelview(rgb8) - etstr = VERSION >= v"1.6.0-DEV.1083" ? " with eltype" : "" str = summary(g) @test occursin("3×3×5 reinterpret($(rrstr)", str) && occursin("N0f8", str) && occursin("::Array{RGB{N0f8},$(rrdim(3))}", str) - VERSION >= v"1.6.0-DEV.1083" && @test occursin("with eltype", str) + @test occursin("with eltype", str) h = OffsetArray(rgb8, -1:1, -2:2) @test summary(h) == "$(sumsz(h))OffsetArray(::Array{RGB{N0f8},2}, -1:1, -2:2) with eltype $(RGB_str){$(N0f8_str)} with indices -1:1×-2:2" i = channelview(h)