Skip to content

Commit

Permalink
fix #13059, reload and require deprecations
Browse files Browse the repository at this point in the history
- reload was not actually deprecated

- require(::String) now does almost exactly what it did in 0.3 (via copying
  the code). However the deprecation is oriented to the use case where the
  argument is a file path to load once, as this is not easily replaced by
  `using`.

(cherry picked from commit d3bc374)
  • Loading branch information
JeffBezanson authored and tkelman committed Sep 13, 2015
1 parent acacc1a commit 3b43bd8
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 24 deletions.
30 changes: 9 additions & 21 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -659,9 +659,16 @@ end
return a
end

@noinline function require(mod::AbstractString)
## require ##

include("require.jl")
@noinline function require(f::AbstractString)
if !(endswith(f,".jl") || contains(f,path_separator))
# for require("Name") this function shouldn't be needed at all
error("use `using` or `import` to load packages")
end
depwarn("`require` is deprecated, use `using` or `import` instead", :require)
require(symbol(require_filename(mod)))
OldRequire.require(f)
end
@noinline function require(f::AbstractString, fs::AbstractString...)
require(f)
Expand All @@ -670,25 +677,6 @@ end
end
end
export require
@noinline function require_filename(name::AbstractString)
# This function can be deleted when the deprecation for `require`
# is deleted.
# While we could also strip off the absolute path, the user may be
# deliberately directing to a different file than what got
# cached. So this takes a conservative approach.
if endswith(name, ".jl")
tmp = name[1:end-3]
for prefix in LOAD_CACHE_PATH
path = joinpath(prefix, tmp*".ji")
if isfile(path)
return tmp
end
end
end
name
end
const reload = require
export reload

## ropes for efficient concatenation, etc. ##

Expand Down
2 changes: 1 addition & 1 deletion base/docs/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6419,7 +6419,7 @@ ordschur!(::LinAlg.GeneralizedSchur,select)

doc"""
```rst
.. Base.compilecache(module::Symbol)
.. Base.compilecache(module::ByteString)
Creates a precompiled cache file for module (see help for ``require``) and all of its dependencies. This can be used to reduce package load times. Cache files are stored in ``LOAD_CACHE_PATH[1]``, which defaults to ``~/.julia/lib/VERSION``. See :ref:`Module initialization and precompilation <man-modules-initialization-precompilation>` for important notes.
```
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,7 @@ export
include,
include_string,
include_dependency,
reload,

# RTS internals
finalizer,
Expand Down
35 changes: 34 additions & 1 deletion base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ end

# to synchronize multiple tasks trying to import/using something
const package_locks = Dict{Symbol,Condition}()
const package_loaded = Set{Symbol}()

# used to optionally track dependencies when requiring a module:
const _require_dependencies = Tuple{ByteString,Float64}[]
Expand Down Expand Up @@ -163,6 +162,40 @@ function __precompile__(isprecompilable::Bool=true)
end
end

function require_filename(name::AbstractString)
# This function can be deleted when the deprecation for `require`
# is deleted.
# While we could also strip off the absolute path, the user may be
# deliberately directing to a different file than what got
# cached. So this takes a conservative approach.
if endswith(name, ".jl")
tmp = name[1:end-3]
for prefix in LOAD_CACHE_PATH
path = joinpath(prefix, tmp*".ji")
if isfile(path)
return tmp
end
end
end
name
end

doc"""
reload(name::AbstractString)
Force reloading of a package, even if it has been loaded before. This is intended for use
during package development as code is modified.
"""
function reload(name::AbstractString)
if isfile(name) || contains(name,path_separator)
# for reload("path/file.jl") just ask for include instead
error("use `include` instead of `reload` to load source files")
else
# reload("Package") is ok
require(symbol(require_filename(name)))
end
end

# require always works in Main scope and loads files from node 1
toplevel_load = true
function require(mod::Symbol)
Expand Down
133 changes: 133 additions & 0 deletions base/require.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# deprecated require
module OldRequire

function find_in_path(name::AbstractString)
isabspath(name) && return name
isfile(name) && return abspath(name)
base = name
if endswith(name,".jl")
base = name[1:end-3]
else
name = string(base,".jl")
isfile(name) && return abspath(name)
end
for prefix in [Pkg.dir(), LOAD_PATH]
path = joinpath(prefix, name)
isfile(path) && return abspath(path)
path = joinpath(prefix, base, "src", name)
isfile(path) && return abspath(path)
path = joinpath(prefix, name, "src", name)
isfile(path) && return abspath(path)
end
return nothing
end

find_in_node1_path(name) = myid()==1 ?
find_in_path(name) : remotecall_fetch(1, find_in_path, name)

# Store list of files and their load time
package_list = (ByteString=>Float64)[]
# to synchronize multiple tasks trying to require something
package_locks = (ByteString=>Any)[]

# only broadcast top-level (not nested) requires and reloads
toplevel_load = true

require(fname::AbstractString) = require(bytestring(fname))
require(f::AbstractString, fs::AbstractString...) = (require(f); for x in fs require(x); end)

function require(name::ByteString)
path = find_in_node1_path(name)
path == nothing && error("$name not found")

if myid() == 1 && toplevel_load
refs = { @spawnat p _require(path) for p in filter(x->x!=1, procs()) }
_require(path)
for r in refs; wait(r); end
else
_require(path)
end
nothing
end

function _require(path)
global toplevel_load
if haskey(package_list,path)
wait(package_locks[path])
else
last = toplevel_load
toplevel_load = false
try
reload_path(path)
finally
toplevel_load = last
end
end
end

# remote/parallel load

function source_path(default::Union(AbstractString,Nothing)="")
t = current_task()
while true
s = t.storage
if !is(s, nothing) && haskey(s, :SOURCE_PATH)
return s[:SOURCE_PATH]
end
if is(t, t.parent)
return default
end
t = t.parent
end
end

function include_from_node1(path::AbstractString)
prev = source_path(nothing)
path = (prev == nothing) ? abspath(path) : joinpath(dirname(prev),path)
tls = task_local_storage()
tls[:SOURCE_PATH] = path
local result
try
if myid()==1
# sleep a bit to process file requests from other nodes
nprocs()>1 && sleep(0.005)
result = Core.include(path)
nprocs()>1 && sleep(0.005)
else
result = include_string(remotecall_fetch(1, readall, path), path)
end
finally
if prev == nothing
delete!(tls, :SOURCE_PATH)
else
tls[:SOURCE_PATH] = prev
end
end
result
end

function reload_path(path::AbstractString)
had = haskey(package_list, path)
if !had
package_locks[path] = RemoteRef()
end
package_list[path] = time()
tls = task_local_storage()
prev = pop!(tls, :SOURCE_PATH, nothing)
try
eval(Main, :(Base.include_from_node1($path)))
catch e
had || delete!(package_list, path)
rethrow(e)
finally
if prev != nothing
tls[:SOURCE_PATH] = prev
end
end
if !isready(package_locks[path])
put!(package_locks[path],nothing)
end
nothing
end

end # module
8 changes: 7 additions & 1 deletion doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ Getting Around
Return a string with the contents of the operating system clipboard ("paste").

.. function:: reload(name::AbstractString)

.. Docstring generated from Julia source
Force reloading of a package, even if it has been loaded before. This is intended for use during package development as code is modified.

.. function:: require(module::Symbol)

.. Docstring generated from Julia source
Expand All @@ -122,7 +128,7 @@ Getting Around

When searching for files, ``require`` first looks in the current working directory, then looks for package code under ``Pkg.dir()``\ , then tries paths in the global array ``LOAD_PATH``\ .

.. function:: Base.compilecache(module::Symbol)
.. function:: Base.compilecache(module::ByteString)

.. Docstring generated from Julia source
Expand Down

0 comments on commit 3b43bd8

Please sign in to comment.