Infiltrator.jl 1.0 is out now! There were a few substantial changes and a bunch of QOL improvements:
Added an @exfiltrate macro to export all local variables into a global storage space (or safehouse). This is also available as a command from the infil> REPL.
Switched from a debug> prompt to infil> to make it easier to distinguish from Debugger.jl.
Assignment/function definitions in the infil> REPL now assign into the safehouse instead of doing nothing. It’s not possible to overwrite local variables though.
The safehouse (or Infiltrator.store) can be used to access exfiltrated variables directly via safehouse.yourvariable.
Infiltrator.set_store!(Main) (or any other module) allows you to exfiltrate variables directly to that module, but is discouraged because you might end up overwriting global variables.
Added a @withstore macro that evaluates its argument with all variables in the safehouse defined so @withstore yourvariable will work appropriately. Note that this is for interactive use only.
@stop in the infil> REPL is now called @toggle and, well, toggles the current infiltration point.
Added a @continue command to continue to the next infiltration point or stop if there is none (same functionality as exiting the REPL mode with ^D).
Added an @exit command to stop the current infiltration session, where a session lasts until the code invoked in the Julia REPL has finished running. This uses the REPL hooks introduced in Julia 1.5, so you’ll need to manually call Infiltrator.end_session!() on previous versions after using @exit.
Error stack traces are now truncated properly.
@locals outputs much less (typically only one line per local variable).
I am a long-time user of Exfiltrator.jl, and am pleased that Infiltrator.jl supersedes Exfiltrator.jl’s functionality. To emulate Exfiltrator.@exfiltrate, just do
Infiltrator.set_store!(Main)
in the REPL before running your code, and Infiltrator.@exfiltrate will work the same.
Seeing new functionalities, maybe I am too greedy, but two questions (possible enhancements?) came immediately to my mind:
is there a way to list breakpoints, with their enabled/disabled status?
is there a way to re-enable a previously disabled breakpoint other than the one in which the code is currently? (Or, better? toggle any other known breakpoint?)
Again, many thanks and bravos for the wonderful (and I am sure very useful) package !
Kinda.
You can list all disabled infiltration points with getfield(safehouse, :disabled) and pop! them out of that Set. Infiltrator.clear_disabled!() just calls empty! on it.
There’s no list of non-disabled infiltration points anywhere though.
It’s not really feasible to discover which infiltration points exist/may be called by your code beforehand. So while there is interest (at least you asked for it ) I don’t see a good way to implement that functionality. It would be possible to collect all infiltration points after running your code once, but that seems to be of dubious utility.
Couldn’t you just register a line number node during macroexpansion? E.g.
julia> const locs = LineNumberNode[]
LineNumberNode[]
julia> macro foo()
push!(locs, __source__)
nothing
end
@foo (macro with 1 method)
julia> function f(x)
@foo
x + 1
end
f (generic function with 1 method)
julia> function bar()
@foo
f(1) * 2
end
bar (generic function with 1 method)
Dang, I just started using Infiltrator, and it is a lifesaver! To be able to run fully compiled code so that MCMC is fast, but then break and see what the heck is going on! That’s fantastic. Thanks for this piece of code! Needs to be in a pinned “tips-and-tricks” post.