diff --git a/Project.toml b/Project.toml index 2f7ecb71..e6e56702 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" Missings = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" +Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/deprecated.jl b/src/deprecated.jl index 38e4fcf5..3bf5accf 100644 --- a/src/deprecated.jl +++ b/src/deprecated.jl @@ -10,77 +10,87 @@ @deprecate CategoricalMatrix(::Type{T}, m::Int, n::Int; ordered=false) where {T} CategoricalMatrix{T}(m, n, ordered=ordered) -# Only define methods for Nullables while they're in Base, otherwise we don't care -if VERSION < v"0.7.0-DEV.3017" - Base.convert(::Type{Nullable{S}}, x::CategoricalValue{Nullable}) where {S} = - convert(Nullable{S}, get(x)) - Base.convert(::Type{Nullable}, x::CategoricalValue{S}) where {S} = convert(Nullable{S}, x) - Base.convert(::Type{Nullable{CategoricalValue{Nullable{T}}}}, - x::CategoricalValue{Nullable{T}}) where {T} = - Nullable(x) -end +@deprecate CategoricalArray(dims::Int...; ordered=false) CategoricalArray(undef, dims...; ordered=ordered) -if VERSION < v"0.7.0-DEV.2581" - CategoricalArray(dims::Int...; ordered=false) = - CategoricalArray{String}(dims, ordered=ordered) +@deprecate CategoricalArray{T, N, R}(dims::NTuple{N,Int}; ordered=false) where {T, N, R} CategoricalArray{T, N, R}(undef, dims; ordered=ordered) - function CategoricalArray{T, N, R}(dims::NTuple{N,Int}; - ordered=false) where {T, N, R} - C = catvaluetype(T, R) - V = leveltype(C) - S = T >: Missing ? Union{V, Missing} : V - CategoricalArray{S, N}(zeros(R, dims), CategoricalPool{V, R, C}(ordered)) - end +@deprecate CategoricalArray{T, N}(dims::NTuple{N,Int}; ordered=false) where {T, N} CategoricalArray{T, N}(undef, dims; ordered=ordered) +@deprecate CategoricalArray{T}(dims::NTuple{N,Int}; ordered=false) where {T, N} CategoricalArray{T}(undef, dims; ordered=ordered) +@deprecate CategoricalArray{T, 1}(m::Int; ordered=false) where {T} CategoricalArray{T, 1}(undef, m; ordered=ordered) +@deprecate CategoricalArray{T, 2}(m::Int, n::Int; ordered=false) where {T} CategoricalArray{T, 2}(undef, m, n; ordered=ordered) +@deprecate CategoricalArray{T, 1, R}(m::Int; ordered=false) where {T, R} CategoricalArray{T, 1, R}(undef, m; ordered=ordered) +# R <: Integer is required to prevent default constructor from being called instead +@deprecate CategoricalArray{T, 2, R}(m::Int, n::Int; ordered=false) where {T, R <: Integer} CategoricalArray{T, 2, R}(undef, m, n; ordered=ordered) +@deprecate CategoricalArray{T, 3, R}(m::Int, n::Int, o::Int; ordered=false) where {T, R} CategoricalArray{T, 3, R}(undef, m, n, o; ordered=ordered) +@deprecate CategoricalArray{T}(m::Int; ordered=false) where {T} CategoricalArray{T}(undef, m; ordered=ordered) +@deprecate CategoricalArray{T}(m::Int, n::Int; ordered=false) where {T} CategoricalArray{T}(undef, m, n; ordered=ordered) +@deprecate CategoricalArray{T}(m::Int, n::Int, o::Int; ordered=false) where {T} CategoricalArray{T}(undef, m, n, o; ordered=ordered) - CategoricalArray{T, N}(dims::NTuple{N,Int}; ordered=false) where {T, N} = - CategoricalArray{T, N, DefaultRefType}(dims, ordered=ordered) - CategoricalArray{T}(dims::NTuple{N,Int}; ordered=false) where {T, N} = - CategoricalArray{T, N}(dims, ordered=ordered) - CategoricalArray{T, 1}(m::Int; ordered=false) where {T} = - CategoricalArray{T, 1}((m,), ordered=ordered) - CategoricalArray{T, 2}(m::Int, n::Int; ordered=false) where {T} = - CategoricalArray{T, 2}((m, n), ordered=ordered) - CategoricalArray{T, 1, R}(m::Int; ordered=false) where {T, R} = - CategoricalArray{T, 1, R}((m,), ordered=ordered) - # R <: Integer is required to prevent default constructor from being called instead - CategoricalArray{T, 2, R}(m::Int, n::Int; ordered=false) where {T, R <: Integer} = - CategoricalArray{T, 2, R}((m, n), ordered=ordered) - CategoricalArray{T, 3, R}(m::Int, n::Int, o::Int; ordered=false) where {T, R} = - CategoricalArray{T, 3, R}((m, n, o), ordered=ordered) - CategoricalArray{T}(m::Int; ordered=false) where {T} = - CategoricalArray{T}((m,), ordered=ordered) - CategoricalArray{T}(m::Int, n::Int; ordered=false) where {T} = - CategoricalArray{T}((m, n), ordered=ordered) - CategoricalArray{T}(m::Int, n::Int, o::Int; ordered=false) where {T} = - CategoricalArray{T}((m, n, o), ordered=ordered) +@deprecate CategoricalVector(m::Integer; ordered=false) CategoricalVector(undef, m; ordered=ordered) +@deprecate CategoricalVector{T}(m::Int; ordered=false) where {T} CategoricalVector{T}(undef, m; ordered=ordered) - CategoricalVector(m::Integer; ordered=false) = CategoricalArray(m, ordered=ordered) - CategoricalVector{T}(m::Int; ordered=false) where {T} = - CategoricalArray{T}((m,), ordered=ordered) +@deprecate CategoricalMatrix(m::Int, n::Int; ordered=false) CategoricalMatrix(undef, m, n; ordered=ordered) +@deprecate CategoricalMatrix{T}(m::Int, n::Int; ordered=false) where {T} CategoricalMatrix{T}(undef, m::Int, n::Int; ordered=ordered) - CategoricalMatrix(m::Int, n::Int; ordered=false) = CategoricalArray(m, n, ordered=ordered) - CategoricalMatrix{T}(m::Int, n::Int; ordered=false) where {T} = - CategoricalArray{T}((m, n), ordered=ordered) -else - @deprecate CategoricalArray(dims::Int...; ordered=false) CategoricalArray(undef, dims...; ordered=ordered) +# AbstractString interface for CategoricalString +import Base: eltype, length, lastindex, sizeof, nextind, prevind, + iterate, getindex, codeunit, ascii, isvalid, match, collect, reverse, + ncodeunits, isempty, firstindex, lpad, rpad, occursin, startswith, endswith, + repeat, split, rsplit, strip, lstrip, rstrip, eachmatch, + uppercase, lowercase, titlecase, uppercasefirst, lowercasefirst, + chop, chomp, escape_string, textwidth, isascii +# NOTE: drop dependency on Unicode when removing these deprecations +import Unicode: normalize, graphemes +@deprecate eltype(x::CategoricalString) eltype(String(x)) +@deprecate length(x::CategoricalString) length(String(x)) +@deprecate lastindex(x::CategoricalString) lastindex(String(x)) +@deprecate sizeof(x::CategoricalString) sizeof(String(x)) +@deprecate nextind(x::CategoricalString, i::Int) nextind(String(x), i) +@deprecate prevind(x::CategoricalString, i::Int) prevind(String(x), i) +@deprecate iterate(x::CategoricalString) iterate(String(x)) +@deprecate iterate(x::CategoricalString, i::Int) iterate(String(x), i) +@deprecate getindex(x::CategoricalString, i::Int) getindex(String(x), i) +@deprecate codeunit(x::CategoricalString, i::Integer) codeunit(String(x), i) +@deprecate ascii(x::CategoricalString) ascii(String(x)) +@deprecate isvalid(x::CategoricalString) isvalid(String(x)) +@deprecate isvalid(x::CategoricalString, i::Integer) isvalid(String(x), i) +@deprecate match(r::Regex, s::CategoricalString, + idx::Integer=firstindex(s), add_opts::UInt32=UInt32(0); kwargs...) match(r, String(s), idx, add_opts; kwargs...) +@deprecate collect(x::CategoricalString) collect(String(x)) +@deprecate reverse(x::CategoricalString) reverse(String(x)) +@deprecate ncodeunits(x::CategoricalString) ncodeunits(String(x)) - @deprecate CategoricalArray{T, N, R}(dims::NTuple{N,Int}; ordered=false) where {T, N, R} CategoricalArray{T, N, R}(undef, dims; ordered=ordered) - - @deprecate CategoricalArray{T, N}(dims::NTuple{N,Int}; ordered=false) where {T, N} CategoricalArray{T, N}(undef, dims; ordered=ordered) - @deprecate CategoricalArray{T}(dims::NTuple{N,Int}; ordered=false) where {T, N} CategoricalArray{T}(undef, dims; ordered=ordered) - @deprecate CategoricalArray{T, 1}(m::Int; ordered=false) where {T} CategoricalArray{T, 1}(undef, m; ordered=ordered) - @deprecate CategoricalArray{T, 2}(m::Int, n::Int; ordered=false) where {T} CategoricalArray{T, 2}(undef, m, n; ordered=ordered) - @deprecate CategoricalArray{T, 1, R}(m::Int; ordered=false) where {T, R} CategoricalArray{T, 1, R}(undef, m; ordered=ordered) - # R <: Integer is required to prevent default constructor from being called instead - @deprecate CategoricalArray{T, 2, R}(m::Int, n::Int; ordered=false) where {T, R <: Integer} CategoricalArray{T, 2, R}(undef, m, n; ordered=ordered) - @deprecate CategoricalArray{T, 3, R}(m::Int, n::Int, o::Int; ordered=false) where {T, R} CategoricalArray{T, 3, R}(undef, m, n, o; ordered=ordered) - @deprecate CategoricalArray{T}(m::Int; ordered=false) where {T} CategoricalArray{T}(undef, m; ordered=ordered) - @deprecate CategoricalArray{T}(m::Int, n::Int; ordered=false) where {T} CategoricalArray{T}(undef, m, n; ordered=ordered) - @deprecate CategoricalArray{T}(m::Int, n::Int, o::Int; ordered=false) where {T} CategoricalArray{T}(undef, m, n, o; ordered=ordered) - - @deprecate CategoricalVector(m::Integer; ordered=false) CategoricalVector(undef, m; ordered=ordered) - @deprecate CategoricalVector{T}(m::Int; ordered=false) where {T} CategoricalVector{T}(undef, m; ordered=ordered) - - @deprecate CategoricalMatrix(m::Int, n::Int; ordered=false) CategoricalMatrix(undef, m, n; ordered=ordered) - @deprecate CategoricalMatrix{T}(m::Int, n::Int; ordered=false) where {T} CategoricalMatrix{T}(undef, m::Int, n::Int; ordered=ordered) -end +# Methods which are not strictly necessary +# but which allow giving a single and accurate deprecation warning +@deprecate isempty(x::CategoricalString) isempty(String(x)) +@deprecate firstindex(x::CategoricalString) firstindex(String(x)) +@deprecate normalize(x::CategoricalString, s::Symbol) normalize(String(x), s) +@deprecate graphemes(x::CategoricalString) graphemes(String(x)) +@deprecate length(x::CategoricalString, i::Int, j::Int) length(String(x), i, j) +@deprecate repeat(x::CategoricalString, i::Integer) repeat(String(x), i) +@deprecate eachmatch(r::Regex, x::CategoricalString; overlap=false) eachmatch(r, String(x), overlap=overlap) +@deprecate lpad(x::CategoricalString, n::Integer, c::Union{AbstractChar,AbstractString}=' ') lpad(String(x), n) +@deprecate rpad(x::CategoricalString, n::Integer, c::Union{AbstractChar,AbstractString}=' ') rpad(String(x), n) +@deprecate occursin(x::CategoricalString, y::AbstractString) occursin(String(x), y) +@deprecate occursin(x::AbstractString, y::CategoricalString) occursin(x, String(y)) +@deprecate occursin(x::Regex, y::CategoricalString) occursin(x, String(y)) +@deprecate occursin(x::AbstractChar, y::CategoricalString) occursin(x, String(y)) +@deprecate startswith(x::CategoricalString, y::AbstractString) startswith(String(x), y) +@deprecate startswith(x::AbstractString, y::CategoricalString) startswith(x, String(y)) +@deprecate endswith(x::CategoricalString, y::AbstractString) endswith(String(x), y) +@deprecate endswith(x::AbstractString, y::CategoricalString) endswith(x, String(y)) +@deprecate split(x::CategoricalString; kwargs...) split(String(x); kwargs...) +@deprecate rsplit(x::CategoricalString; kwargs...) rsplit(String(x); kwargs...) +@deprecate strip(x::CategoricalString) strip(String(x)) +@deprecate lstrip(x::CategoricalString) lstrip(String(x)) +@deprecate rstrip(x::CategoricalString) rstrip(String(x)) +@deprecate lowercase(x::CategoricalString) lowercase(String(x)) +@deprecate uppercase(x::CategoricalString) uppercase(String(x)) +@deprecate lowercasefirst(x::CategoricalString) lowercasefirst(String(x)) +@deprecate uppercasefirst(x::CategoricalString) uppercasefirst(String(x)) +@deprecate titlecase(x::CategoricalString) titlecase(String(x)) +@deprecate chop(x::CategoricalString; kwargs...) chop(String(x); kwargs...) +@deprecate chomp(x::CategoricalString) chomp(String(x)) +@deprecate textwidth(x::CategoricalString) textwidth(String(x)) +@deprecate isascii(x::CategoricalString) isascii(String(x)) +@deprecate escape_string(x::CategoricalString) escape_string(String(x)) \ No newline at end of file diff --git a/src/value.jl b/src/value.jl index d19484f1..34cef216 100644 --- a/src/value.jl +++ b/src/value.jl @@ -218,35 +218,6 @@ Base.:<(::Missing, ::CatValue) = missing # JSON of CatValue is JSON of the value it refers to JSON.lower(x::CatValue) = JSON.lower(get(x)) -# AbstractString interface for CategoricalString +# Efficient method equivalent to the fallback Base.string(x::CategoricalString) = get(x) -Base.eltype(x::CategoricalString) = Char -Base.length(x::CategoricalString) = length(get(x)) -Compat.lastindex(x::CategoricalString) = lastindex(get(x)) -Base.sizeof(x::CategoricalString) = sizeof(get(x)) -Base.nextind(x::CategoricalString, i::Int) = nextind(get(x), i) -Base.prevind(x::CategoricalString, i::Int) = prevind(get(x), i) -if VERSION > v"0.7.0-DEV.5126" - Base.iterate(x::CategoricalString) = iterate(get(x)) - Base.iterate(x::CategoricalString, i::Int) = iterate(get(x), i) -else - Base.next(x::CategoricalString, i::Int) = next(get(x), i) -end -Base.getindex(x::CategoricalString, i::Int) = getindex(get(x), i) -Base.codeunit(x::CategoricalString, i::Integer) = codeunit(get(x), i) -Base.ascii(x::CategoricalString) = ascii(get(x)) -Base.isvalid(x::CategoricalString) = isvalid(get(x)) -Base.isvalid(x::CategoricalString, i::Integer) = isvalid(get(x), i) -Base.match(r::Regex, s::CategoricalString, - idx::Integer=firstindex(s), add_opts::UInt32=UInt32(0)) = - match(r, get(s), idx, add_opts) -if VERSION > v"0.7.0-DEV.3526" -else - Base.matchall(r::Regex, s::CategoricalString; overlap::Bool=false) = - matchall(r, get(s), overlap) - Base.matchall(r::Regex, s::CategoricalString, overlap::Bool) = - matchall(r, get(s), overlap) -end -Base.collect(x::CategoricalString) = collect(get(x)) -Base.reverse(x::CategoricalString) = reverse(get(x)) -Compat.ncodeunits(x::CategoricalString) = ncodeunits(get(x)) +Base.String(x::CategoricalString) = get(x) \ No newline at end of file diff --git a/test/08_string.jl b/test/08_string.jl index c5e15f94..c8bee3a8 100644 --- a/test/08_string.jl +++ b/test/08_string.jl @@ -41,20 +41,14 @@ using CategoricalArrays @test sizeof(v1) === 0 @test sizeof(v2) === 5 - if VERSION >= v"0.7.0-DEV.2949" - @test_throws BoundsError nextind(v1, 1) - else - @test nextind(v1, 1) === 2 - end + @test_throws BoundsError nextind(v1, 1) @test nextind(v2, 4) === 6 @test prevind(v1, 1) === 0 @test prevind(v2, 6) === 4 - if VERSION >= v"0.7.0-DEV.3583" - @test firstindex(v1) === 1 - @test firstindex(v2) === 1 - end + @test firstindex(v1) === 1 + @test firstindex(v2) === 1 @test lastindex(v1) === 0 @test lastindex(v2) === 4 @@ -65,11 +59,7 @@ using CategoricalArrays @test v2[2] === 'a' @test v2[4] === 'é' @test_throws BoundsError v1[1] - if VERSION >= v"0.7.0-DEV.2949" - @test_throws StringIndexError v2[5] - else - @test_throws UnicodeError v2[5] - end + @test_throws StringIndexError v2[5] @test codeunit(v2, 2) === 0x61 @test codeunit(v2, 5) === 0xa9 @@ -92,19 +82,11 @@ using CategoricalArrays @test isvalid(v2, 4) @test !isvalid(v2, 5) - if VERSION >= v"0.7.0-DEV.2949" - @test_throws BoundsError length(v1, 0, 0) - @test length(v2, 1, 4) === 4 + @test_throws BoundsError length(v1, 0, 0) + @test length(v2, 1, 4) === 4 - @test_throws BoundsError nextind(v1, 1, 1) - @test nextind(v2, 1, 2) === 3 - else - @test_throws BoundsError ind2chr(v1, 0) - @test ind2chr(v2, 4) === 4 - - @test_throws BoundsError chr2ind(v1, 1) - @test chr2ind(v2, 2) === 2 - end + @test_throws BoundsError nextind(v1, 1, 1) + @test nextind(v2, 1, 2) === 3 @test string(v1) == "" @test string(v2) == "café" @@ -140,12 +122,7 @@ using CategoricalArrays @test collect((m.match for m ∈ eachmatch(r"af", v1))) == [] @test collect((m.match for m ∈ eachmatch(r"af", v2))) == ["af"] - if VERSION > v"0.7.0-DEV.3526" - @test collect((m.match for m ∈ eachmatch(r"af", v2, overlap=true))) == ["af"] - else - @test matchall(r"af", v2, overlap=true) == ["af"] - @test matchall(r"af", v2, true) == ["af"] - end + @test collect((m.match for m ∈ eachmatch(r"af", v2, overlap=true))) == ["af"] @test lpad(v1, 1) == " " @test lpad(v2, 1) == "café" @@ -225,7 +202,7 @@ using CategoricalArrays @test join([v1, "a"]) == "a" @test join([v1, "a"], v2) == "caféa" - if VERSION >= v"1.0.4" # Previous versions throw a BoundsError + if VERSION >= v"1.1.1" # Previous versions throw a BoundsError @test chop(v1) == "" end @test chop(v2) == "caf"