Skip to content
Merged
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
91 changes: 91 additions & 0 deletions Manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# This file is machine-generated - editing it directly is not advised

[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[CodeTracking]]
deps = ["InteractiveUtils", "Test", "UUIDs"]
git-tree-sha1 = "7e19dccd5667e0a8d9327ac76966977dbc0df85f"
uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
version = "0.5.0"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[JuliaInterpreter]]
deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"]
git-tree-sha1 = "8aeee3235a4c995493475be2cc27e26ab234c72e"
repo-rev = "master"
repo-url = "https://github.com/JuliaDebug/JuliaInterpreter.jl.git"
uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"
version = "0.4.0"

[[LibGit2]]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[LoweredCodeUtils]]
deps = ["JuliaInterpreter", "Test"]
git-tree-sha1 = "51e3d512848f96e0017338e1e7e3485ee2730e6e"
uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
version = "0.3.0"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[OrderedCollections]]
deps = ["Random", "Serialization", "Test"]
git-tree-sha1 = "85619a3f3e17bb4761fe1b1fd47f0e979f964d5b"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.0.2"

[[Pkg]]
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[Test]]
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
8 changes: 4 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ LoweredCodeUtils = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[compat]
CodeTracking = "0.4, 0.5"
JuliaInterpreter = "0.2, 0.3"
JuliaInterpreter = "0.2, 0.3, 0.4"
LoweredCodeUtils = "0.3"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Example = "7876af07-990d-54b4-ab0e-23690620f79a"
EponymTuples = "97e2ac4a-e175-5f49-beb1-4d6866a6cdc3"
Example = "7876af07-990d-54b4-ab0e-23690620f79a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "Example", "EponymTuples"]
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
julia 1.0
OrderedCollections
CodeTracking 0.4 0.6
JuliaInterpreter 0.2 0.4
JuliaInterpreter 0.2 0.5
LoweredCodeUtils 0.3 0.4
32 changes: 19 additions & 13 deletions src/Revise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ function eval_new!(exs_sigs_new::ExprsSigs, exs_sigs_old, mod::Module)
# try
sigs = eval_with_signatures(mod, ex) # All signatures defined by `ex`
for p in workers()
p == myid() && continue
try # don't error if `mod` isn't defined on the worker
remotecall(Core.eval, p, mod, ex)
catch
Expand Down Expand Up @@ -337,18 +338,18 @@ push_expr!(methodinfo::CodeTrackingMethodInfo, mod::Module, ex::Expr) = (push!(m
pop_expr!(methodinfo::CodeTrackingMethodInfo) = (pop!(methodinfo.exprstack); methodinfo)

# Eval and insert into CodeTracking data
function eval_with_signatures(mod, ex::Expr; define=true)
function eval_with_signatures(mod, ex::Expr; define=true, kwargs...)
methodinfo = CodeTrackingMethodInfo(ex)
docexprs = Dict{Module,Vector{Expr}}()
methods_by_execution!(finish_and_return!, methodinfo, docexprs, mod, ex; define=define)
methods_by_execution!(finish_and_return!, methodinfo, docexprs, mod, ex; define=define, kwargs...)
return methodinfo.allsigs
end

function instantiate_sigs!(modexsigs::ModuleExprsSigs)
function instantiate_sigs!(modexsigs::ModuleExprsSigs; define=false, kwargs...)
for (mod, exsigs) in modexsigs
for rex in keys(exsigs)
is_doc_expr(rex.ex) && continue
sigs = eval_with_signatures(mod, rex.ex; define=false)
sigs = eval_with_signatures(mod, rex.ex; define=define, kwargs...)
exsigs[rex.ex] = sigs
end
end
Expand Down Expand Up @@ -579,12 +580,12 @@ Watch `file` for updates and [`revise`](@ref) loaded code with any
changes. `mod` is the module into which `file` is evaluated; if omitted,
it defaults to `Main`.
"""
function track(mod::Module, file::AbstractString)
function track(mod::Module, file::AbstractString; define=false, skip_include=true)
isfile(file) || error(file, " is not a file")
file = normpath(abspath(file))
fm = parse_source(file, mod)
if fm !== nothing
instantiate_sigs!(fm)
instantiate_sigs!(fm; define=define, skip_include=skip_include)
id = PkgId(mod)
if !haskey(pkgdatas, id)
pkgdatas[id] = PkgData(id, pathof(mod))
Expand All @@ -603,18 +604,23 @@ track(file::AbstractString) = track(Main, file)
"""
includet(filename)

Load `filename` and track any future changes to it.
`includet` is deliberately non-recursive, so if `filename` loads any other files,
they will not be automatically tracked.
(See [`Revise.track`](@ref) to set it up manually.)
Load `filename` and track any future changes to it. `includet` is simply shorthand for

Revise.track(Main, filename; skip_include=false)

`includet` is intended for "user scripts," e.g., a file you use locally for a specific
purpose such as loading a specific data set or performing some kind of analysis.
Do not use `includet` for packages, as those should be handled by `using` or `import`.
purpose such as loading a specific data set or performing a particular analysis.
Do *not* use `includet` for packages, as those should be handled by `using` or `import`.
(If you're working with code in Base or one of Julia's standard libraries, use
`Revise.track(mod)` instead, where `mod` is the module.)
If `using` and `import` aren't working, you may have packages in a non-standard location;
try fixing it with something like `push!(LOAD_PATH, "/path/to/my/private/repos")`.

`includet` is deliberately non-recursive, so if `filename` loads any other files,
they will not be automatically tracked.
(See [`Revise.track`](@ref) to set it up manually.)
"""
includet(file::AbstractString) = (Base.include(Main, file); track(Main, file))
includet(file::AbstractString) = track(Main, file; define=true, skip_include=false)

"""
Revise.silence(pkg)
Expand Down
12 changes: 6 additions & 6 deletions src/lowered.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ add_signature!(methodinfo::MethodInfo, @nospecialize(sig), ln) = push!(methodinf
push_expr!(methodinfo::MethodInfo, mod::Module, ex::Expr) = methodinfo
pop_expr!(methodinfo::MethodInfo) = methodinfo

function methods_by_execution(mod::Module, ex::Expr; define=true)
function methods_by_execution(mod::Module, ex::Expr; kwargs...)
methodinfo = MethodInfo()
docexprs = Dict{Module,Vector{Expr}}()
value = methods_by_execution!(finish_and_return!, methodinfo, docexprs, mod, ex; define=define)
value = methods_by_execution!(finish_and_return!, methodinfo, docexprs, mod, ex; kwargs...)
return methodinfo, docexprs
end

function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod::Module, ex::Expr; define=true)
function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod::Module, ex::Expr; kwargs...)
# We have to turn off all active breakpoints, https://github.com/timholy/CodeTracking.jl/issues/27
bps = filter(bp->bp[].isactive, JuliaInterpreter._breakpoints)
for bp in bps
Expand All @@ -43,7 +43,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
try
frame = prepare_thunk(mod, ex)
frame === nothing && return nothing
ret = methods_by_execution!(recurse, methodinfo, docexprs, frame; define=define)
ret = methods_by_execution!(recurse, methodinfo, docexprs, frame; kwargs...)
catch err
isa(err, InterruptException) && rethrow(err)
@warn "error evaluating in module $mod: $ex" exception=(err, catch_backtrace())
Expand All @@ -56,7 +56,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
return ret
end

function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, frame; define=true)
function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, frame; define=true, skip_include=true)
mod = moduleof(frame)
signatures = [] # temporary for method signature storage
pc = frame.pc
Expand Down Expand Up @@ -141,7 +141,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
end
assign_this!(frame, value)
pc = next_or_nothing!(frame)
elseif f === getfield(mod, :include) || f === Base.include || f === Core.include
elseif skip_include && (f === getfield(mod, :include) || f === Base.include || f === Core.include)
# Skip include calls, otherwise we load new code
assign_this!(frame, nothing) # FIXME: the file might return something different from `nothing`
pc = next_or_nothing!(frame)
Expand Down
2 changes: 1 addition & 1 deletion src/pkgs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ function maybe_parse_from_cache!(pkgdata::PkgData, file::AbstractString)
return add_definitions_from_repl(file)
end
fi = fileinfo(pkgdata, file)
if isempty(fi.modexsigs)
if isempty(fi.modexsigs) && !isempty(fi.cachefile)
# Source was never parsed, get it from the precompile cache
src = read_from_cache(pkgdata, file)
filep = joinpath(basedir(pkgdata), file)
Expand Down
29 changes: 29 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,35 @@ revise_f(x) = 2
includet(srcfile)
@test basename(srcfile) ∈ Revise.watched_files[dirname(srcfile)].trackedfiles
push!(to_remove, srcfile)

# Double-execution (issue #263)
srcfile = joinpath(tempdir(), randtmp()*".jl")
open(srcfile, "w") do io
print(io, """
println("executed")
""")
end
logfile = joinpath(tempdir(), randtmp()*".log")
open(logfile, "w") do io
redirect_stdout(io) do
includet(srcfile)
end
end
lines = readlines(logfile)
@test length(lines) == 1 && chomp(lines[1]) == "executed"
sleep(0.1)
open(srcfile, "w") do io
print(io, """
println("executed again")
""")
end
open(logfile, "w") do io
redirect_stdout(io) do
yry()
end
end
lines = readlines(logfile)
@test length(lines) == 1 && chomp(lines[1]) == "executed again"
end

@testset "Auto-track user scripts" begin
Expand Down