Skip to content

Commit c12a74b

Browse files
Merge pull request #20120 from JuliaLang/sk/loadhook2
minimal hook into loading needed for Pkg3 (take 2)
2 parents b3cbcc2 + 708a757 commit c12a74b

File tree

6 files changed

+63
-155
lines changed

6 files changed

+63
-155
lines changed

base/REPLCompletions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ function completions(string, pos)
494494
s = string[startpos:pos]
495495
if dotpos <= startpos
496496
for dir in [Pkg.dir(); LOAD_PATH; pwd()]
497-
isdir(dir) || continue
497+
dir isa AbstractString && isdir(dir) || continue
498498
for pname in readdir(dir)
499499
if pname[1] != '.' && pname != "METADATA" &&
500500
pname != "REQUIRE" && startswith(pname, s)

base/initdefs.jl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,23 @@ isinteractive() = (is_interactive::Bool)
3030
"""
3131
LOAD_PATH
3232
33-
An array of paths (as strings) where the `require` function looks for code.
33+
An array of paths as strings or custom loader objects for the `require`
34+
function and `using` and `import` statements to consider when loading
35+
code. To create a custom loader type, define the type and then add
36+
appropriate methods to the `Base.load_hook` function with the following
37+
signature:
38+
39+
Base.load_hook(loader::Loader, name::String, found::Any)
40+
41+
The `loader` argument is the current value in `LOAD_PATH`, `name` is the
42+
name of the module to load, and `found` is the path of any previously
43+
found code to provide `name`. If no provider has been found earlier in
44+
`LOAD_PATH` then the value of `found` will be `nothing`. Custom loader
45+
functionality is experimental and may break or change in Julia 1.0.
3446
"""
35-
const LOAD_PATH = String[]
36-
47+
const LOAD_PATH = Any[]
3748
const LOAD_CACHE_PATH = String[]
49+
3850
function init_load_path()
3951
vers = "v$(VERSION.major).$(VERSION.minor)"
4052
if haskey(ENV, "JULIA_LOAD_PATH")

base/loading.jl

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,26 @@ else
8080
end
8181
end
8282

83-
function try_path(prefix::String, base::String, name::String)
84-
path = joinpath(prefix, name)
83+
function load_hook(prefix::String, name::String, ::Void)
84+
name_jl = "$name.jl"
85+
path = joinpath(prefix, name_jl)
8586
isfile_casesensitive(path) && return abspath(path)
86-
path = joinpath(prefix, base, "src", name)
87+
path = joinpath(prefix, name_jl, "src", name_jl)
8788
isfile_casesensitive(path) && return abspath(path)
88-
path = joinpath(prefix, name, "src", name)
89+
path = joinpath(prefix, name, "src", name_jl)
8990
isfile_casesensitive(path) && return abspath(path)
9091
return nothing
9192
end
93+
load_hook(prefix::String, name::String, path::String) = path
94+
load_hook(prefix, name::String, ::Any) =
95+
throw(ArgumentError("unrecognized custom loader in LOAD_PATH: $prefix"))
96+
97+
_str(x::AbstractString) = String(x)
98+
_str(x) = x
9299

93100
# `wd` is a working directory to search. defaults to current working directory.
94101
# if `wd === nothing`, no extra path is searched.
95-
function find_in_path(name::String, wd)
102+
function find_in_path(name::String, wd::Union{Void,String})
96103
isabspath(name) && return name
97104
base = name
98105
if endswith(name,".jl")
@@ -103,15 +110,15 @@ function find_in_path(name::String, wd)
103110
if wd !== nothing
104111
isfile_casesensitive(joinpath(wd,name)) && return joinpath(wd,name)
105112
end
106-
p = try_path(Pkg.dir(), base, name)
107-
p !== nothing && return p
108-
for prefix in LOAD_PATH
109-
p = try_path(prefix, base, name)
110-
p !== nothing && return p
113+
path = nothing
114+
path = _str(load_hook(_str(Pkg.dir()), base, path))
115+
for dir in LOAD_PATH
116+
path = _str(load_hook(_str(dir), base, path))
111117
end
112-
return nothing
118+
return path
113119
end
114-
find_in_path(name::AbstractString, wd = pwd()) = find_in_path(String(name), wd)
120+
find_in_path(name::AbstractString, wd::AbstractString = pwd()) =
121+
find_in_path(String(name), String(wd))
115122

116123
function find_in_node_path(name::String, srcpath, node::Int=1)
117124
if myid() == node

base/pkg/entry.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,9 +600,11 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
600600
# are serialized to errfile for later retrieval into errs[pkg]
601601
errfile = tempname()
602602
close(open(errfile, "w")) # create empty file
603+
# TODO: serialize the same way the load cache does, not with strings
604+
LOAD_PATH = filter(x -> x isa AbstractString, Base.LOAD_PATH)
603605
code = """
604606
empty!(Base.LOAD_PATH)
605-
append!(Base.LOAD_PATH, $(repr(Base.LOAD_PATH)))
607+
append!(Base.LOAD_PATH, $(repr(LOAD_PATH)))
606608
empty!(Base.LOAD_CACHE_PATH)
607609
append!(Base.LOAD_CACHE_PATH, $(repr(Base.LOAD_CACHE_PATH)))
608610
empty!(Base.DL_LOAD_PATH)

base/require.jl

Lines changed: 0 additions & 135 deletions
This file was deleted.

test/loading.jl

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,29 @@ mktempdir() do dir
4040
end
4141
end
4242

43-
let paddedname = "Ztest_sourcepath.jl"
44-
filename = SubString(paddedname, 2, length(paddedname))
45-
@test Base.find_in_path(filename) == abspath(paddedname[2:end])
43+
SAVED_LOAD_PATH = copy(LOAD_PATH)
44+
empty!(LOAD_PATH)
45+
dir = abspath(@__DIR__)
46+
push!(LOAD_PATH, dir)
47+
48+
@test Base.find_in_path("test_sourcepath") == joinpath(dir, "test_sourcepath.jl")
49+
@test Base.find_in_path(GenericString("test_sourcepath")) == joinpath(dir, "test_sourcepath.jl")
50+
LOAD_PATH[end] = GenericString(LOAD_PATH[end])
51+
@test Base.find_in_path("test_sourcepath") == joinpath(dir, "test_sourcepath.jl")
52+
53+
immutable CustomLoader
54+
path::String
4655
end
56+
push!(LOAD_PATH, CustomLoader("abc"))
57+
let name = randstring(20)
58+
@test_throws ArgumentError Base.find_in_path(name, nothing)
59+
Base.load_hook(prefix::CustomLoader, name::String, found) = joinpath(prefix.path, name)
60+
@test Base.find_in_path(name, nothing) == joinpath("abc", name)
61+
end
62+
@test Base.find_in_path("test_sourcepath", nothing) == joinpath("abc", "test_sourcepath")
63+
Base.load_hook(prefix::CustomLoader, name::String, found::String) = found
64+
@test Base.find_in_path("test_sourcepath", nothing) == joinpath(dir, "test_sourcepath.jl")
65+
66+
empty!(LOAD_PATH)
67+
append!(LOAD_PATH, SAVED_LOAD_PATH)
68+
@test LOAD_PATH == SAVED_LOAD_PATH

0 commit comments

Comments
 (0)