Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate tryparse(T, s) in favor of parse(Union{T, Void}, s) #25131

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,9 @@ Deprecated or removed

* `sub2ind` and `ind2sub` are deprecated in favor of using `CartesianIndices` and `LinearIndices` ([#24715]).

* `tryparse(T, s[, base])` has been deprecated in favor of `parse(Union{T, Void}, s[, base])`
([#25130]).

Command-line option changes
---------------------------

Expand Down Expand Up @@ -1784,3 +1787,4 @@ Command-line option changes
[#24869]: https://github.com/JuliaLang/julia/issues/24869
[#25021]: https://github.com/JuliaLang/julia/issues/25021
[#25088]: https://github.com/JuliaLang/julia/issues/25088
[#25130]: https://github.com/JuliaLang/julia/issues/25130
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ color_normal = text_colors[:normal]

function repl_color(key, default)
env_str = get(ENV, key, "")
c = tryparse(Int, env_str)
c = parse(Union{Int, Void}, env_str)
c_conv = coalesce(c, Symbol(env_str))
haskey(text_colors, c_conv) ? c_conv : default
end
Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3411,6 +3411,9 @@ end
# PR #25113
@deprecate_binding CartesianRange CartesianIndices

@deprecate tryparse(T::Type, str::AbstractString) parse(Union{T, Void}, str)
@deprecate tryparse(T::Type, str::AbstractString, base::Integer) parse(Union{T, Void}, str, base)

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
1 change: 0 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ export
fldmod1,
flipsign,
float,
tryparse,
floor,
fma,
frexp,
Expand Down
6 changes: 3 additions & 3 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,12 @@ macro big_str(s)
end
print(bf, s[end])
seekstart(bf)
n = tryparse(BigInt, String(take!(bf)))
n = parse(Union{BigInt, Void}, String(take!(bf)))
n === nothing || return n
else
n = tryparse(BigInt, s)
n = parse(Union{BigInt, Void}, s)
n === nothing || return n
n = tryparse(BigFloat, s)
n = parse(Union{BigFloat, Void}, s)
n === nothing || return n
end
message = "invalid number format $s for BigInt or BigFloat"
Expand Down
6 changes: 3 additions & 3 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import
eps, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2,
cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding,
setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero,
setrounding, maxintfloat, widen, significand, frexp, parse, iszero,
isone, big

import Base.Rounding: rounding_raw, setrounding_raw
Expand Down Expand Up @@ -121,8 +121,8 @@ convert(::Type{BigFloat}, x::Union{UInt8,UInt16,UInt32}) = BigFloat(convert(Culo
convert(::Type{BigFloat}, x::Union{Float16,Float32}) = BigFloat(Float64(x))
convert(::Type{BigFloat}, x::Rational) = BigFloat(numerator(x)) / BigFloat(denominator(x))

function tryparse(::Type{BigFloat}, s::AbstractString, base::Int=0)
!isempty(s) && Base.Unicode.isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base)
function parse(::Type{Union{BigFloat, Void}}, s::AbstractString, base::Int=0)
!isempty(s) && Base.Unicode.isspace(s[end]) && return parse(Union{BigFloat, Void}, rstrip(s), base)
z = BigFloat()
err = ccall((:mpfr_set_str, :libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, Int32), z, s, base, ROUNDING_MODE[])
err == 0 ? z : nothing
Expand Down
36 changes: 24 additions & 12 deletions base/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,23 @@ end
end

"""
tryparse(type, str, [base])
parse(::Type{Union{T, Void}}, str, [base])

Like [`parse`](@ref), but returns either a value of the requested type,
Like [`parse`](@ref), but returns either a value of the requested type `T`,
or [`nothing`](@ref) if the string does not contain a valid number.

# Examples
```jldoctest
julia> parse(Union{Int, Void}, "1")
1

julia> parse(Union{Int, Void}, "a") === nothing
true
```
"""
tryparse(::Type{T}, s::AbstractString, base::Integer) where {T<:Integer} =
parse(::Type{Union{T, Void}}, s::AbstractString, base::Integer) where {T<:Integer} =
tryparse_internal(T, s, start(s), endof(s), check_valid_base(base), false)
tryparse(::Type{T}, s::AbstractString) where {T<:Integer} =
parse(::Type{Union{T, Void}}, s::AbstractString) where {T<:Integer} =
tryparse_internal(T, s, start(s), endof(s), 0, false)

function parse(::Type{T}, s::AbstractString, base::Integer) where T<:Integer
Expand All @@ -222,12 +231,12 @@ end

## string to float functions ##

function tryparse(::Type{Float64}, s::String)
function parse(::Type{Union{Float64, Void}}, s::String)
hasvalue, val = ccall(:jl_try_substrtod, Tuple{Bool, Float64},
(Ptr{UInt8},Csize_t,Csize_t), s, 0, sizeof(s))
hasvalue ? val : nothing
end
function tryparse(::Type{Float64}, s::SubString{String})
function parse(::Type{Union{Float64, Void}}, s::SubString{String})
hasvalue, val = ccall(:jl_try_substrtod, Tuple{Bool, Float64},
(Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset, s.ncodeunits)
hasvalue ? val : nothing
Expand All @@ -242,12 +251,12 @@ function tryparse_internal(::Type{Float64}, s::SubString{String}, startpos::Int,
(Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset+startpos-1, endpos-startpos+1)
hasvalue ? val : nothing
end
function tryparse(::Type{Float32}, s::String)
function parse(::Type{Union{Float32, Void}}, s::String)
hasvalue, val = ccall(:jl_try_substrtof, Tuple{Bool, Float32},
(Ptr{UInt8},Csize_t,Csize_t), s, 0, sizeof(s))
hasvalue ? val : nothing
end
function tryparse(::Type{Float32}, s::SubString{String})
function parse(::Type{Union{Float32, Void}}, s::SubString{String})
hasvalue, val = ccall(:jl_try_substrtof, Tuple{Bool, Float32},
(Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset, s.ncodeunits)
hasvalue ? val : nothing
Expand All @@ -262,9 +271,10 @@ function tryparse_internal(::Type{Float32}, s::SubString{String}, startpos::Int,
(Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset+startpos-1, endpos-startpos+1)
hasvalue ? val : nothing
end
tryparse(::Type{T}, s::AbstractString) where {T<:Union{Float32,Float64}} = tryparse(T, String(s))
tryparse(::Type{Float16}, s::AbstractString) =
convert(Union{Float16, Void}, tryparse(Float32, s))
parse(::Type{Union{T, Void}}, s::AbstractString) where {T<:Union{Float32,Float64}} =
parse(Union{T, Void}, String(s))
parse(::Type{Union{Float16, Void}}, s::AbstractString) =
convert(Union{Float16, Void}, parse(Union{Float32, Void}, s))
tryparse_internal(::Type{Float16}, s::AbstractString, startpos::Int, endpos::Int) =
convert(Union{Float16, Void}, tryparse_internal(Float32, s, startpos, endpos))

Expand Down Expand Up @@ -331,7 +341,9 @@ tryparse_internal(T::Type{<:Complex}, s::AbstractString, i::Int, e::Int, raise::

# fallback methods for tryparse_internal
tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int) where T<:Real =
startpos == start(s) && endpos == endof(s) ? tryparse(T, s) : tryparse(T, SubString(s, startpos, endpos))
startpos == start(s) && endpos == endof(s) ?
parse(Union{T, Void}, s) :
parse(Union{T, Void}, SubString(s, startpos, endpos))
function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, raise::Bool) where T<:Real
result = tryparse_internal(T, s, startpos, endpos)
if raise && result === nothing
Expand Down
2 changes: 1 addition & 1 deletion base/repl/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ function setup_interface(
"^Q" => (s, o...) -> begin
linfos = Base.LAST_SHOWN_LINE_INFOS
str = String(take!(LineEdit.buffer(s)))
n = tryparse(Int, str)
n = parse(Union{Int, Void}, str)
n === nothing && @goto writeback
if n <= 0 || n > length(linfos) || startswith(linfos[n][1], "./REPL")
@goto writeback
Expand Down
2 changes: 1 addition & 1 deletion doc/src/stdlib/numbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Base.digits
Base.digits!
Base.bitstring
Base.parse(::Type, ::Any, ::Any)
Base.tryparse
Base.parse(::Type{Union{T, Void}}, ::AbstractString, ::Integer) where {T<:Integer}
Base.big
Base.signed
Base.unsigned
Expand Down
4 changes: 3 additions & 1 deletion stdlib/Dates/src/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,9 @@ function Base.parse(::Type{T}, str::AbstractString, df::DateFormat=default_forma
T(values...)
end

function Base.tryparse(::Type{T}, str::AbstractString, df::DateFormat=default_format(T)) where T<:TimeType
function Base.parse(::Type{Union{T, Void}},
str::AbstractString,
df::DateFormat=default_format(T)) where T<:TimeType
pos, len = start(str), endof(str)
values, pos = tryparsenext_internal(T, str, pos, len, df, false)
if values === nothing
Expand Down
5 changes: 3 additions & 2 deletions stdlib/Dates/src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,10 @@ daysinmonth(y,m) = DAYSINMONTH[m] + (m == 2 && isleapyear(y))
### UTILITIES ###

# These are necessary because the type constructors for TimeType subtypes can
# throw, and we want to be able to use tryparse without requiring a try/catch.
# throw, and we want to be able to use parse(Union{T, Void}, ...) without
# requiring a try/catch.
# This is made easier by providing a helper function that checks arguments, so
# we can validate arguments in tryparse.
# we can validate arguments in parse(Union{T, Void}, ...).

"""
validargs(::Type{<:TimeType}, args...) -> Union{ArgumentError, Void}
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Dates/test/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ end
end
end
# Issue #21504
@test tryparse(Dates.Date, "0-1000") === nothing
@test parse(Union{Dates.Date, Void}, "0-1000") === nothing

@testset "parse milliseconds, Issue #22100" begin
@test Dates.DateTime("2017-Mar-17 00:00:00.0000", "y-u-d H:M:S.s") == Dates.DateTime(2017, 3, 17)
Expand Down
6 changes: 6 additions & 0 deletions test/ambiguous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,12 @@ end
pop!(need_to_handle_undef_sparam, which(Base.nonmissingtype, Tuple{Type{Union{Missing, T}} where T}))
pop!(need_to_handle_undef_sparam, which(Base.convert, (Type{Union{Some{T}, Void}} where T, Some)))
pop!(need_to_handle_undef_sparam, which(Base.convert, (Type{Union{T, Void}} where T, Some)))
using Dates
pop!(need_to_handle_undef_sparam, which(Base.parse, (Type{Union{Void, T}} where T<:Union{Float32, Float64}, AbstractString)))
pop!(need_to_handle_undef_sparam, which(Base.parse, (Type{Union{Void, T}} where T<:Dates.TimeType, AbstractString)))
pop!(need_to_handle_undef_sparam, which(Base.parse, (Type{Union{Void, T}} where T<:Integer, AbstractString, Integer)))
pop!(need_to_handle_undef_sparam, which(Base.parse, (Type{Union{Void, T}} where T<:Dates.TimeType, AbstractString, Dates.DateFormat)))
pop!(need_to_handle_undef_sparam, which(Base.parse, (Type{Union{Void, T}} where T<:Integer, AbstractString)))
@test need_to_handle_undef_sparam == Set()
end
end
Expand Down
14 changes: 7 additions & 7 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -212,22 +212,22 @@ end
@test parse(Int, "2") === 2
@test parse(Bool, "true") === true
@test parse(Bool, "false") === false
@test tryparse(Bool, "true") === true
@test tryparse(Bool, "false") === false
@test parse(Union{Bool, Void}, "true") === true
@test parse(Union{Bool, Void}, "false") === false
@test_throws ArgumentError parse(Int, "2", 1)
@test_throws ArgumentError parse(Int, "2", 63)

# issue #17333: tryparse should still throw on invalid base
# issue #17333: parse(Union{T, Void}, ...) should still throw on invalid base
for T in (Int32, BigInt), base in (0,1,100)
@test_throws ArgumentError tryparse(T, "0", base)
@test_throws ArgumentError parse(Union{T, Void}, "0", base)
end

# error throwing branch from #10560
@test_throws ArgumentError Base.tryparse_internal(Bool, "foo", 1, 2, 10, true)

@test tryparse(Float64, "1.23") === 1.23
@test tryparse(Float32, "1.23") === 1.23f0
@test tryparse(Float16, "1.23") === Float16(1.23)
@test parse(Union{Float64, Void}, "1.23") === 1.23
@test parse(Union{Float32, Void}, "1.23") === 1.23f0
@test parse(Union{Float16, Void}, "1.23") === Float16(1.23)

# parsing complex numbers (#22250)
@testset "complex parsing" begin
Expand Down
2 changes: 1 addition & 1 deletion test/spawn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ end
# test for proper handling of FD exhaustion
if Sys.isunix()
let ps = Pipe[]
ulimit_n = tryparse(Int, readchomp(`sh -c 'ulimit -n'`))
ulimit_n = parse(Union{Int, Void}, readchomp(`sh -c 'ulimit -n'`))
try
for i = 1 : 100 * coalesce(ulimit_n, 1000)
p = Pipe()
Expand Down
18 changes: 9 additions & 9 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,14 @@ end
for T in [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128]
for i in [typemax(T), typemin(T)]
s = "$i"
@test tryparse(T, s) == i
@test parse(Union{T, Void}, s) == i
end
end

for T in [Int8, Int16, Int32, Int64, Int128]
for i in [typemax(T), typemin(T)]
f = "$(i)0"
@test tryparse(T, f) === nothing
@test parse(Union{T, Void}, f) === nothing
end
end
end
Expand All @@ -284,21 +284,21 @@ end
@test unsafe_string(sp,5) == "abcde"
@test typeof(unsafe_string(sp)) == String

@test tryparse(BigInt, "1234567890") == BigInt(1234567890)
@test tryparse(BigInt, "1234567890-") === nothing
@test parse(Union{BigInt, Void}, "1234567890") == BigInt(1234567890)
@test parse(Union{BigInt, Void}, "1234567890-") === nothing

@test tryparse(Float64, "64") == 64.0
@test tryparse(Float64, "64o") === nothing
@test tryparse(Float32, "32") == 32.0f0
@test tryparse(Float32, "32o") === nothing
@test parse(Union{Float64, Void}, "64") == 64.0
@test parse(Union{Float64, Void}, "64o") === nothing
@test parse(Union{Float32, Void}, "32") == 32.0f0
@test parse(Union{Float32, Void}, "32o") === nothing
end

@testset "issue #10994: handle embedded NUL chars for string parsing" begin
for T in [BigInt, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128]
@test_throws ArgumentError parse(T, "1\0")
end
for T in [BigInt, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Float64, Float32]
@test tryparse(T, "1\0") === nothing
@test parse(Union{T, Void}, "1\0") === nothing
end
let s = Base.Unicode.normalize("tést",:NFKC)
@test unsafe_string(Base.unsafe_convert(Cstring, Base.cconvert(Cstring, s))) == s
Expand Down