Skip to content

Commit 0211c83

Browse files
vtjnashKristofferC
authored andcommitted
[TOML] remove Dates hack, replace with explicit usage (#54755)
This hack will cease functioning soon (#54739), so it must be removed so that packages can stop relying on it. As an aid, now provide some basic conversion and printing support for the Base.TOML variants of this as well such that users can round-trip the contents (if they are well-formed as a date/time). (cherry picked from commit 2ce12e9)
1 parent 5bccb82 commit 0211c83

File tree

5 files changed

+46
-24
lines changed

5 files changed

+46
-24
lines changed

base/toml_parser.jl

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ module TOML
99

1010
using Base: IdSet
1111

12-
# In case we do not have the Dates stdlib available
1312
# we parse DateTime into these internal structs,
13+
# unless a different DateTime library is passed to the Parser constructor
1414
# note that these do not do any argument checking
1515
struct Date
1616
year::Int
@@ -85,12 +85,10 @@ mutable struct Parser
8585
# Filled in in case we are parsing a file to improve error messages
8686
filepath::Union{String, Nothing}
8787

88-
# Gets populated with the Dates stdlib if it exists
88+
# Optionally populate with the Dates stdlib to change the type of Date types returned
8989
Dates::Union{Module, Nothing}
9090
end
9191

92-
const DATES_PKGID = Base.PkgId(Base.UUID("ade2ca70-3891-5945-98fb-dc099432e06a"), "Dates")
93-
9492
function Parser(str::String; filepath=nothing)
9593
root = TOMLDict()
9694
l = Parser(
@@ -109,7 +107,7 @@ function Parser(str::String; filepath=nothing)
109107
IdSet{TOMLDict}(), # defined_tables
110108
root,
111109
filepath,
112-
isdefined(Base, :maybe_root_module) ? Base.maybe_root_module(DATES_PKGID) : nothing,
110+
nothing
113111
)
114112
startup(l)
115113
return l
@@ -151,8 +149,6 @@ end
151149
# Errors #
152150
##########
153151

154-
throw_internal_error(msg) = error("internal TOML parser error: $msg")
155-
156152
# Many functions return a ParserError. We want this to bubble up
157153
# all the way and have this error be returned to the user
158154
# if the parse is called with `raise=false`. This macro
@@ -900,7 +896,7 @@ end
900896
function parse_float(l::Parser, contains_underscore)::Err{Float64}
901897
s = take_string_or_substring(l, contains_underscore)
902898
v = Base.tryparse(Float64, s)
903-
v === nothing && return(ParserError(ErrGenericValueError))
899+
v === nothing && return ParserError(ErrGenericValueError)
904900
return v
905901
end
906902

@@ -909,8 +905,8 @@ function parse_int(l::Parser, contains_underscore, base=nothing)::Err{Int64}
909905
v = try
910906
Base.parse(Int64, s; base=base)
911907
catch e
912-
e isa Base.OverflowError && return(ParserError(ErrOverflowError))
913-
error("internal parser error: did not correctly discredit $(repr(s)) as an int")
908+
e isa Base.OverflowError && return ParserError(ErrOverflowError)
909+
rethrow()
914910
end
915911
return v
916912
end
@@ -932,8 +928,8 @@ for (name, T1, T2, n1, n2) in (("integer", Int64, Int128, 17, 33),
932928
Base.parse(BigInt, s; base)
933929
end
934930
catch e
935-
e isa Base.OverflowError && return(ParserError(ErrOverflowError))
936-
error("internal parser error: did not correctly discredit $(repr(s)) as an int")
931+
e isa Base.OverflowError && return ParserError(ErrOverflowError)
932+
rethrow()
937933
end
938934
return v
939935
end
@@ -1030,8 +1026,9 @@ function try_return_datetime(p, year, month, day, h, m, s, ms)
10301026
if Dates !== nothing
10311027
try
10321028
return Dates.DateTime(year, month, day, h, m, s, ms)
1033-
catch
1034-
return ParserError(ErrParsingDateTime)
1029+
catch ex
1030+
ex isa ArgumentError && return ParserError(ErrParsingDateTime)
1031+
rethrow()
10351032
end
10361033
else
10371034
return DateTime(year, month, day, h, m, s, ms)
@@ -1043,8 +1040,9 @@ function try_return_date(p, year, month, day)
10431040
if Dates !== nothing
10441041
try
10451042
return Dates.Date(year, month, day)
1046-
catch
1047-
return ParserError(ErrParsingDateTime)
1043+
catch ex
1044+
ex isa ArgumentError && return ParserError(ErrParsingDateTime)
1045+
rethrow()
10481046
end
10491047
else
10501048
return Date(year, month, day)
@@ -1065,8 +1063,9 @@ function try_return_time(p, h, m, s, ms)
10651063
if Dates !== nothing
10661064
try
10671065
return Dates.Time(h, m, s, ms)
1068-
catch
1069-
return ParserError(ErrParsingDateTime)
1066+
catch ex
1067+
ex isa ArgumentError && return ParserError(ErrParsingDateTime)
1068+
rethrow()
10701069
end
10711070
else
10721071
return Time(h, m, s, ms)

stdlib/Dates/src/types.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,3 +492,8 @@ end
492492

493493
Base.OrderStyle(::Type{<:AbstractTime}) = Base.Ordered()
494494
Base.ArithmeticStyle(::Type{<:AbstractTime}) = Base.ArithmeticWraps()
495+
496+
# minimal Base.TOML support
497+
Date(d::Base.TOML.Date) = Date(d.year, d.month, d.day)
498+
Time(t::Base.TOML.Time) = Time(t.hour, t.minute, t.second, t.ms)
499+
DateTime(dt::Base.TOML.DateTime) = DateTime(Date(dt.date), Time(dt.time))

stdlib/TOML/Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ version = "1.0.3"
66
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
77

88
[compat]
9+
Dates = "1.11.0"
910
julia = "1.6"
1011

1112
[extras]
1213
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
13-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1414
Tar = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
15+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1516
p7zip_jll = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
1617

1718
[targets]

stdlib/TOML/src/TOML.jl

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and to serialize Julia data structures to TOML format.
77
"""
88
module TOML
99

10+
using Dates
11+
1012
module Internals
1113
# The parser is defined in Base
1214
using Base.TOML: Parser, parse, tryparse, ParserError, isvalid_barekey_char, reinit!
@@ -36,6 +38,17 @@ performance if a larger number of small files are parsed.
3638
"""
3739
const Parser = Internals.Parser
3840

41+
"""
42+
DTParser()
43+
44+
Constructor for a TOML `Parser` which returns date and time objects from Dates.
45+
"""
46+
function DTParser(args...; kwargs...)
47+
parser = Parser(args...; kwargs...)
48+
parser.Dates = Dates
49+
return parser
50+
end
51+
3952
"""
4053
parsefile(f::AbstractString)
4154
parsefile(p::Parser, f::AbstractString)
@@ -46,7 +59,7 @@ Parse file `f` and return the resulting table (dictionary). Throw a
4659
See also [`TOML.tryparsefile`](@ref).
4760
"""
4861
parsefile(f::AbstractString) =
49-
Internals.parse(Parser(readstring(f); filepath=abspath(f)))
62+
Internals.parse(DTParser(readstring(f); filepath=abspath(f)))
5063
parsefile(p::Parser, f::AbstractString) =
5164
Internals.parse(Internals.reinit!(p, readstring(f); filepath=abspath(f)))
5265

@@ -60,7 +73,7 @@ Parse file `f` and return the resulting table (dictionary). Return a
6073
See also [`TOML.parsefile`](@ref).
6174
"""
6275
tryparsefile(f::AbstractString) =
63-
Internals.tryparse(Parser(readstring(f); filepath=abspath(f)))
76+
Internals.tryparse(DTParser(readstring(f); filepath=abspath(f)))
6477
tryparsefile(p::Parser, f::AbstractString) =
6578
Internals.tryparse(Internals.reinit!(p, readstring(f); filepath=abspath(f)))
6679

@@ -74,7 +87,7 @@ Throw a [`ParserError`](@ref) upon failure.
7487
See also [`TOML.tryparse`](@ref).
7588
"""
7689
parse(str::AbstractString) =
77-
Internals.parse(Parser(String(str)))
90+
Internals.parse(DTParser(String(str)))
7891
parse(p::Parser, str::AbstractString) =
7992
Internals.parse(Internals.reinit!(p, String(str)))
8093
parse(io::IO) = parse(read(io, String))
@@ -90,7 +103,7 @@ Return a [`ParserError`](@ref) upon failure.
90103
See also [`TOML.parse`](@ref).
91104
"""
92105
tryparse(str::AbstractString) =
93-
Internals.tryparse(Parser(String(str)))
106+
Internals.tryparse(DTParser(String(str)))
94107
tryparse(p::Parser, str::AbstractString) =
95108
Internals.tryparse(Internals.reinit!(p, String(str)))
96109
tryparse(io::IO) = tryparse(read(io, String))

stdlib/TOML/src/print.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ function print_toml_escaped(io::IO, s::AbstractString)
3434
end
3535

3636
const MbyFunc = Union{Function, Nothing}
37-
const TOMLValue = Union{AbstractVector, AbstractDict, Dates.DateTime, Dates.Time, Dates.Date, Bool, Integer, AbstractFloat, AbstractString}
37+
const TOMLValue = Union{AbstractVector, AbstractDict, Bool, Integer, AbstractFloat, AbstractString,
38+
Dates.DateTime, Dates.Time, Dates.Date, Base.TOML.DateTime, Base.TOML.Time, Base.TOML.Date}
3839

3940

4041
########
@@ -89,6 +90,9 @@ function printvalue(f::MbyFunc, io::IO, value::AbstractVector, sorted::Bool)
8990
end
9091

9192
function printvalue(f::MbyFunc, io::IO, value::TOMLValue, sorted::Bool)
93+
value isa Base.TOML.DateTime && (value = Dates.DateTime(value))
94+
value isa Base.TOML.Time && (value = Dates.Time(value))
95+
value isa Base.TOML.Date && (value = Dates.Date(value))
9296
value isa Dates.DateTime ? Base.print(io, Dates.format(value, Dates.dateformat"YYYY-mm-dd\THH:MM:SS.sss\Z")) :
9397
value isa Dates.Time ? Base.print(io, Dates.format(value, Dates.dateformat"HH:MM:SS.sss")) :
9498
value isa Dates.Date ? Base.print(io, Dates.format(value, Dates.dateformat"YYYY-mm-dd")) :

0 commit comments

Comments
 (0)