Skip to content

Commit 2a2878c

Browse files
authoredSep 30, 2024··
TOML: Avoid type-pirating Base.TOML.Parser (#55892)
Since stdlibs can be duplicated but Base never is, `Base.require_stdlib` makes type piracy even more complicated than it normally would be. To adapt, this changes `TOML.Parser` to be a type defined by the TOML stdlib, so that we can define methods on it without committing type-piracy and avoid problems like Pkg.jl#4017 Resolves JuliaLang/Pkg.jl#4017 (comment)
1 parent 4da0671 commit 2a2878c

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed
 

‎stdlib/TOML/src/TOML.jl

+30-13
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module Internals
2525
end
2626

2727
# https://github.com/JuliaLang/julia/issues/36605
28-
readstring(f::AbstractString) = isfile(f) ? read(f, String) : error(repr(f), ": No such file")
28+
_readstring(f::AbstractString) = isfile(f) ? read(f, String) : error(repr(f), ": No such file")
2929

3030
"""
3131
Parser()
@@ -36,12 +36,14 @@ explicitly create a `Parser` but instead one directly use use
3636
will however reuse some internal data structures which can be beneficial for
3737
performance if a larger number of small files are parsed.
3838
"""
39-
const Parser = Internals.Parser
39+
struct Parser
40+
_p::Internals.Parser{Dates}
41+
end
4042

4143
# Dates-enabled constructors
42-
Parser() = Parser{Dates}()
43-
Parser(io::IO) = Parser{Dates}(io)
44-
Parser(str::String; filepath=nothing) = Parser{Dates}(str; filepath)
44+
Parser() = Parser(Internals.Parser{Dates}())
45+
Parser(io::IO) = Parser(Internals.Parser{Dates}(io))
46+
Parser(str::String; filepath=nothing) = Parser(Internals.Parser{Dates}(str; filepath))
4547

4648
"""
4749
parsefile(f::AbstractString)
@@ -53,9 +55,9 @@ Parse file `f` and return the resulting table (dictionary). Throw a
5355
See also [`TOML.tryparsefile`](@ref).
5456
"""
5557
parsefile(f::AbstractString) =
56-
Internals.parse(Parser(readstring(f); filepath=abspath(f)))
58+
Internals.parse(Internals.Parser{Dates}(_readstring(f); filepath=abspath(f)))
5759
parsefile(p::Parser, f::AbstractString) =
58-
Internals.parse(Internals.reinit!(p, readstring(f); filepath=abspath(f)))
60+
Internals.parse(Internals.reinit!(p._p, _readstring(f); filepath=abspath(f)))
5961

6062
"""
6163
tryparsefile(f::AbstractString)
@@ -67,9 +69,9 @@ Parse file `f` and return the resulting table (dictionary). Return a
6769
See also [`TOML.parsefile`](@ref).
6870
"""
6971
tryparsefile(f::AbstractString) =
70-
Internals.tryparse(Parser(readstring(f); filepath=abspath(f)))
72+
Internals.tryparse(Internals.Parser{Dates}(_readstring(f); filepath=abspath(f)))
7173
tryparsefile(p::Parser, f::AbstractString) =
72-
Internals.tryparse(Internals.reinit!(p, readstring(f); filepath=abspath(f)))
74+
Internals.tryparse(Internals.reinit!(p._p, _readstring(f); filepath=abspath(f)))
7375

7476
"""
7577
parse(x::Union{AbstractString, IO})
@@ -80,10 +82,11 @@ Throw a [`ParserError`](@ref) upon failure.
8082
8183
See also [`TOML.tryparse`](@ref).
8284
"""
85+
parse(p::Parser) = Internals.parse(p._p)
8386
parse(str::AbstractString) =
84-
Internals.parse(Parser(String(str)))
87+
Internals.parse(Internals.Parser{Dates}(String(str)))
8588
parse(p::Parser, str::AbstractString) =
86-
Internals.parse(Internals.reinit!(p, String(str)))
89+
Internals.parse(Internals.reinit!(p._p, String(str)))
8790
parse(io::IO) = parse(read(io, String))
8891
parse(p::Parser, io::IO) = parse(p, read(io, String))
8992

@@ -96,10 +99,11 @@ Return a [`ParserError`](@ref) upon failure.
9699
97100
See also [`TOML.parse`](@ref).
98101
"""
102+
tryparse(p::Parser) = Internals.tryparse(p._p)
99103
tryparse(str::AbstractString) =
100-
Internals.tryparse(Parser(String(str)))
104+
Internals.tryparse(Internals.Parser{Dates}(String(str)))
101105
tryparse(p::Parser, str::AbstractString) =
102-
Internals.tryparse(Internals.reinit!(p, String(str)))
106+
Internals.tryparse(Internals.reinit!(p._p, String(str)))
103107
tryparse(io::IO) = tryparse(read(io, String))
104108
tryparse(p::Parser, io::IO) = tryparse(p, read(io, String))
105109

@@ -131,4 +135,17 @@ supported type.
131135
"""
132136
const print = Internals.Printer.print
133137

138+
public Parser, parsefile, tryparsefile, parse, tryparse, ParserError, print
139+
140+
# These methods are private Base interfaces, but we do our best to support them over
141+
# the TOML stdlib types anyway to minimize downstream breakage.
142+
Base.TOMLCache(p::Parser) = Base.TOMLCache(p._p, Dict{String, Base.CachedTOMLDict}())
143+
Base.TOMLCache(p::Parser, d::Base.CachedTOMLDict) = Base.TOMLCache(p._p, d)
144+
Base.TOMLCache(p::Parser, d::Dict{String, Dict{String, Any}}) = Base.TOMLCache(p._p, d)
145+
146+
Internals.reinit!(p::Parser, str::String; filepath::Union{Nothing, String}=nothing) =
147+
Internals.reinit!(p._p, str; filepath)
148+
Internals.parse(p::Parser) = Internals.parse(p._p)
149+
Internals.tryparse(p::Parser) = Internals.tryparse(p._p)
150+
134151
end

0 commit comments

Comments
 (0)
Please sign in to comment.