From ee77d7aa13053b276ae8f7316337b1db56cb2288 Mon Sep 17 00:00:00 2001 From: Pablo Zubieta <8410335+pabloferz@users.noreply.github.com> Date: Tue, 6 Oct 2020 23:20:23 -0500 Subject: [PATCH 1/3] Add only as replacement for convert --- docs/src/index.md | 1 + src/anchoredinterval.jl | 30 ++++++++++++++++++------------ src/interval.jl | 22 +++++++++++++++++----- test/anchoredinterval.jl | 9 ++++----- test/interval.jl | 23 +++++++++++++---------- 5 files changed, 53 insertions(+), 32 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index c7bb368e..9f1951ec 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -263,6 +263,7 @@ Open Unbounded first last +only span isclosed isopen diff --git a/src/anchoredinterval.jl b/src/anchoredinterval.jl index b406cc37..b71653ea 100644 --- a/src/anchoredinterval.jl +++ b/src/anchoredinterval.jl @@ -176,23 +176,29 @@ span(interval::AnchoredInterval{P}) where P = abs(P) ##### CONVERSION ##### -# Allows an interval to be converted to a scalar when the set contained by the interval only -# contains a single element. +function Base.only(interval::AnchoredInterval{P}) where {P} + if isclosed(interval) && (sign(P) == 0 || first(interval) == last(interval)) + return first(interval) + else + throw(DomainError(interval, + "The interval is not closed with coinciding endpoints, " * + "did you meant to use `anchor(interval)`?" + )) + end +end + +# Remove in version 2.0.0 function Base.convert(::Type{T}, interval::AnchoredInterval{P,T}) where {P,T} + depwarn( + "`convert(::Type{T}, interval::AnchoredInterval{P, T})` is deprecated, " * + "use `only(interval::AnchoredInterval{P,T})` for closed intervals with " * + "coinciding endpoints or `anchor(interval)` otherwise.", + :convert, + ) if isclosed(interval) && (sign(P) == 0 || first(interval) == last(interval)) return first(interval) else - # Remove deprecation in version 2.0.0 - depwarn( - "`convert(T, interval::AnchoredInterval{P,T})` is deprecated for " * - "intervals which are not closed with coinciding endpoints. " * - "Use `anchor(interval)` instead.", - :convert, - ) return anchor(interval) - - # TODO: For when deprecation is removed - # throw(DomainError(interval, "The interval is not closed with coinciding endpoints")) end end diff --git a/src/interval.jl b/src/interval.jl index a674c2e6..efb317e1 100644 --- a/src/interval.jl +++ b/src/interval.jl @@ -233,11 +233,13 @@ function Base.maximum(interval::AbstractInterval{T,L,Open}; increment=nothing) w throw(BoundsError(interval, next_val)) end -##### CONVERSION ##### +""" + only(interval::AbstractInterval) -# Allows an interval to be converted to a scalar when the set contained by the interval only -# contains a single element. -function Base.convert(::Type{T}, interval::Interval{T}) where T +Returns the only element of a closed interval with coinciding endpoints (throws a +DomainError otherwise). +""" +function Base.only(interval::Interval) if first(interval) == last(interval) && isclosed(interval) return first(interval) else @@ -245,8 +247,18 @@ function Base.convert(::Type{T}, interval::Interval{T}) where T end end -##### DISPLAY ##### +##### CONVERSION ##### +function Base.convert(::Type{T}, interval::Interval{T}) where {T} + depwarn( + "`convert(::Type{T}, interval::Interval{T})` is deprecated, " * + "use `only(interval)` instead.", + :convert, + ) + return only(interval) +end + +##### DISPLAY ##### function Base.show(io::IO, interval::Interval{T,L,R}) where {T,L,R} if get(io, :compact, false) diff --git a/test/anchoredinterval.jl b/test/anchoredinterval.jl index 90858815..41fa85f6 100644 --- a/test/anchoredinterval.jl +++ b/test/anchoredinterval.jl @@ -114,17 +114,16 @@ using Intervals: Bounded, Ending, Beginning, canonicalize, isunbounded @testset "conversion" begin interval = AnchoredInterval{Hour(0)}(dt) - @test convert(DateTime, interval) == dt + @test only(interval) == dt he = HourEnding(dt) hb = HourBeginning(dt) - # Note: When the deprecation is dropped remove the deprecated tests and uncomment - # the DomainError tests + @test_throws DomainError only(he) + @test_throws DomainError only(hb) + @test (@test_deprecated convert(DateTime, he)) == anchor(he) @test (@test_deprecated convert(DateTime, hb)) == anchor(hb) - # @test_throws DomainError convert(DateTime, he) - # @test_throws DomainError convert(DateTime, hb) @test convert(Interval, he) == Interval{Open, Closed}(dt - Hour(1), dt) @test convert(Interval, hb) == Interval{Closed, Open}(dt, dt + Hour(1)) diff --git a/test/interval.jl b/test/interval.jl index 0025e14e..a017b47a 100644 --- a/test/interval.jl +++ b/test/interval.jl @@ -98,19 +98,22 @@ end @testset "conversion" begin - @test_throws DomainError convert(Int, Interval{Open, Open}(10, 10)) - @test_throws DomainError convert(Int, Interval{Open, Closed}(10, 10)) - @test_throws DomainError convert(Int, Interval{Closed, Open}(10, 10)) - @test convert(Int, Interval{Closed, Closed}(10, 10)) == 10 - @test_throws DomainError convert(Int, Interval{Closed, Closed}(10, 11)) + @test_throws DomainError only(Interval{Open, Open}(10, 10)) + @test_throws DomainError only(Interval{Open, Closed}(10, 10)) + @test_throws DomainError only(Interval{Closed, Open}(10, 10)) + @test only(Interval{Closed, Closed}(10, 10)) == 10 + @test_throws DomainError only(Interval{Closed, Closed}(10, 11)) + + @test (@test_deprecated convert(Int, Interval{Closed, Closed}(10, 10))) == 10 + @test_deprecated (@test_throws DomainError convert(Int, Interval{Closed, Closed}(10, 11))) for T in (Date, DateTime) dt = T(2013, 2, 13) - @test_throws DomainError convert(T, Interval{Open, Open}(dt, dt)) - @test_throws DomainError convert(T, Interval{Open, Closed}(dt, dt)) - @test_throws DomainError convert(T, Interval{Closed, Open}(dt, dt)) - @test convert(T, Interval{Closed, Closed}(dt, dt)) == dt - @test_throws DomainError convert(T, Interval{Closed, Closed}(dt, dt + Day(1))) + @test_throws DomainError only(Interval{Open, Open}(dt, dt)) + @test_throws DomainError only(Interval{Open, Closed}(dt, dt)) + @test_throws DomainError only(Interval{Closed, Open}(dt, dt)) + @test only(Interval{Closed, Closed}(dt, dt)) == dt + @test_throws DomainError only(Interval{Closed, Closed}(dt, dt + Day(1))) end end From 6452e0b25eca6c6a78b132abb618daa06ca55ee4 Mon Sep 17 00:00:00 2001 From: Pablo Zubieta <8410335+pabloferz@users.noreply.github.com> Date: Thu, 27 Jan 2022 17:55:43 -0600 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Curtis Vogt --- src/deprecated.jl | 8 ++++---- src/interval.jl | 4 ++-- test/interval.jl | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/deprecated.jl b/src/deprecated.jl index e91ae7c4..9beda72e 100644 --- a/src/deprecated.jl +++ b/src/deprecated.jl @@ -6,10 +6,10 @@ import Dates: Date, DateTime export Inclusivity, inclusivity include("inclusivity.jl") -@deprecate Date(interval::Interval{Date}) convert(Date, interval) -@deprecate DateTime(interval::Interval{DateTime}) convert(DateTime, interval) -@deprecate Date(interval::AnchoredInterval{P, Date} where P) convert(Date, interval) -@deprecate DateTime(interval::AnchoredInterval{P, DateTime} where P) convert(DateTime, interval) +@deprecate Date(interval::Interval{Date}) only(interval) +@deprecate DateTime(interval::Interval{DateTime}) only(interval) +@deprecate Date(interval::AnchoredInterval{P, Date} where P) only(interval) +@deprecate DateTime(interval::AnchoredInterval{P, DateTime} where P) only(interval) function Endpoint{T,D}(ep::T, included::Bool) where {T,D} diff --git a/src/interval.jl b/src/interval.jl index efb317e1..ebb5141f 100644 --- a/src/interval.jl +++ b/src/interval.jl @@ -237,9 +237,9 @@ end only(interval::AbstractInterval) Returns the only element of a closed interval with coinciding endpoints (throws a -DomainError otherwise). +`DomainError` otherwise). """ -function Base.only(interval::Interval) +function Base.only(interval::AbstractInterval) if first(interval) == last(interval) && isclosed(interval) return first(interval) else diff --git a/test/interval.jl b/test/interval.jl index a017b47a..7b5c877d 100644 --- a/test/interval.jl +++ b/test/interval.jl @@ -97,7 +97,7 @@ @test hash(a) == hash(b) end - @testset "conversion" begin + @testset "only" begin @test_throws DomainError only(Interval{Open, Open}(10, 10)) @test_throws DomainError only(Interval{Open, Closed}(10, 10)) @test_throws DomainError only(Interval{Closed, Open}(10, 10)) From 91671601717753c46addb37bcb64fecb602545bf Mon Sep 17 00:00:00 2001 From: Pablo Zubieta <8410335+pabloferz@users.noreply.github.com> Date: Sat, 19 Feb 2022 12:53:50 -0600 Subject: [PATCH 3/3] Group tests for `only` --- test/anchoredinterval.jl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/anchoredinterval.jl b/test/anchoredinterval.jl index 41fa85f6..e5a97567 100644 --- a/test/anchoredinterval.jl +++ b/test/anchoredinterval.jl @@ -112,16 +112,21 @@ using Intervals: Bounded, Ending, Beginning, canonicalize, isunbounded @test hash(a) == hash(b) end - @testset "conversion" begin + @testset "only" begin interval = AnchoredInterval{Hour(0)}(dt) + @test only(interval) == dt + @test_throws DomainError only(HourEnding(dt)) + @test_throws DomainError only(HourBeginning(dt)) + + @test (@test_deprecated convert(DateTime, interval)) == only(interval) + end + + @testset "conversion" begin he = HourEnding(dt) hb = HourBeginning(dt) - @test_throws DomainError only(he) - @test_throws DomainError only(hb) - @test (@test_deprecated convert(DateTime, he)) == anchor(he) @test (@test_deprecated convert(DateTime, hb)) == anchor(hb)