Developer reference

Developer reference

Internal global variables

Configuration-related variables

These are set during execution of Revise's __init__ function.

Revise.watching_filesConstant.
Revise.watching_files[]

Returns true if we watch files rather than their containing directory. FreeBSD and NFS-mounted systems should watch files, otherwise we prefer to watch directories.

source
Revise.polling_filesConstant.
Revise.polling_files[]

Returns true if we should poll the filesystem for changes to the files that define loaded code. It is preferable to avoid polling, instead relying on operating system notifications via FileWatching.watch_file. However, NFS-mounted filesystems (and perhaps others) do not support file-watching, so for code stored on such filesystems you should turn polling on.

See the documentation for the JULIA_REVISE_POLL environment variable.

source
Revise.tracking_Main_includes[]

Returns true if files directly included from the REPL should be tracked. The default is false. See the documentation regarding the JULIA_REVISE_INCLUDE environment variable to customize it.

source

Path-related variables

Revise.juliadirConstant.
Revise.juliadir

Constant specifying full path to julia top-level source directory. This should be reliable even for local builds, cross-builds, and binary installs.

source
Revise.basesrccacheConstant.
Revise.basesrccache

Full path to the running Julia's cache of source code defining Base.

source
Revise.basebuilddirConstant.
Revise.basebuilddir

Julia's top-level directory when Julia was built, as recorded by the entries in Base._included_files.

source

Internal state management

Revise.pkgdatasConstant.
Revise.pkgdatas

pkgdatas is the core information that tracks the relationship between source code and julia objects, and allows re-evaluation of code in the proper module scope. It is a dictionary indexed by PkgId: pkgdatas[id] returns a value of type Revise.PkgData.

source
Revise.watched_filesConstant.
Revise.watched_files

Global variable, watched_files[dirname] returns the collection of files in dirname that we're monitoring for changes. The returned value has type Revise.WatchList.

This variable allows us to watch directories rather than files, reducing the burden on the OS.

source
Revise.revision_queueConstant.
Revise.revision_queue

Global variable, revision_queue holds (pkgdata,filename) pairs that we need to revise, meaning that these files have changed since we last processed a revision. This list gets populated by callbacks that watch directories for updates.

source
Revise.included_filesConstant.
Revise.included_files

Global variable, included_files gets populated by callbacks we register with include. It's used to track non-precompiled packages and, optionally, user scripts (see docs on JULIA_REVISE_INCLUDE).

source

Types

A RelocatableExpr wraps an Expr to ensure that comparisons between RelocatableExprs ignore line numbering information. This allows one to detect that two expressions are the same no matter where they appear in a file.

source
ModuleExprsSigs

For a particular source file, the corresponding ModuleExprsSigs is a mapping mod=>exprs=>sigs of the expressions exprs found in mod and the signatures sigs that arise from them. Specifically, if mes is a ModuleExprsSigs, then mes[mod][ex] is a list of signatures that result from evaluating ex in mod. It is possible that this returns nothing, which can mean either that ex does not define any methods or that the signatures have not yet been cached.

The first mod key is guaranteed to be the module into which this file was included.

To create a ModuleExprsSigs from a source file, see Revise.parse_source.

source
Revise.FileInfoType.
FileInfo(mexs::ModuleExprsSigs, cachefile="")

Structure to hold the per-module expressions found when parsing a single file. mexs holds the Revise.ModuleExprsSigs for the file.

Optionally, a FileInfo can also record the path to a cache file holding the original source code. This is applicable only for precompiled modules and Base. (This cache file is distinct from the original source file that might be edited by the developer, and it will always hold the state of the code when the package was precompiled or Julia's Base was built.) When a cache is available, mexs will be empty until the file gets edited: the original source code gets parsed only when a revision needs to be made.

Source cache files greatly reduce the overhead of using Revise.

source
Revise.PkgDataType.
PkgData(id, path, fileinfos::Dict{String,FileInfo})

A structure holding the data required to handle a particular package. path is the top-level directory defining the package, and fileinfos holds the Revise.FileInfo for each file defining the package.

For the PkgData associated with Main (e.g., for files loaded with includet), the corresponding path entry will be empty.

source
Revise.WatchList

A struct for holding files that live inside a directory. Some platforms (OSX) have trouble watching too many files. So we watch parent directories, and keep track of which files in them should be tracked.

Fields:

  • timestamp: mtime of last update
  • trackedfiles: Set of filenames, generally expressed as a relative path
source
Rescheduler(f, args)

To facilitate precompilation and reduce latency, we replace

function watch_manifest(mfile)
    wait_changed(mfile)
    # stuff
    @async watch_manifest(mfile)
end

@async watch_manifest(mfile)

with a rescheduling type:

fresched = Rescheduler(watch_manifest, (mfile,))
schedule(Task(fresched))

where now watch_manifest(mfile) should return true if the task should be rescheduled after completion, and false otherwise.

source
MethodSummary(method)

Create a portable summary of a method. In particular, a MethodSummary can be saved to a JLD2 file.

source

Function reference

Functions called during initialization of Revise

Revise.async_steal_repl_backend()

Wait for the REPL to complete its initialization, and then call Revise.steal_repl_backend. This is necessary because code registered with atreplinit runs before the REPL is initialized, and there is no corresponding way to register code to run after it is complete.

source
steal_repl_backend(backend = Base.active_repl_backend)

Replace the REPL's normal backend with one that calls revise before executing any REPL input.

source

Functions called when you load a new package

Revise.watch_packageFunction.
watch_package(id::Base.PkgId)

Start watching a package for changes to the files that define it. This function gets called via a callback registered with Base.require, at the completion of module-loading by using or import.

source
parse_pkg_files(id::PkgId)

This function gets called by watch_package and runs when a package is first loaded. Its job is to organize the files and expressions defining the module so that later we can detect and process revisions.

source
Revise.init_watchingFunction.
Revise.init_watching(files)
Revise.init_watching(pkgdata::PkgData, files)

For every filename in files, monitor the filesystem for updates. When the file is updated, either Revise.revise_dir_queued or Revise.revise_file_queued will be called.

Use the pkgdata version if the files are supplied using relative paths.

source

Monitoring for changes

These functions get called on each directory or file that you monitor for revisions. These block execution until the file(s) are updated, so you should only call them from within an @async block. They work recursively: once an update has been detected and execution resumes, they schedule a revision (see Revise.revision_queue) and then call themselves on the same directory or file to wait for the next set of changes.

revise_dir_queued(pkgdata::PkgData, dirname)

Wait for one or more of the files registered in Revise.watched_files[dirname] to be modified, and then queue the corresponding files on Revise.revision_queue. This is generally called via a Revise.Rescheduler.

source
revise_file_queued(pkgdata::PkgData, filename)

Wait for modifications to filename, and then queue the corresponding files on Revise.revision_queue. This is generally called via a Revise.Rescheduler.

This is used only on platforms (like BSD) which cannot use Revise.revise_dir_queued.

source

Evaluating changes (revising) and computing diffs

revise is the primary entry point for implementing changes. Additionally,

Revise.revise_file_now(pkgdata::PkgData, file)

Process revisions to file. This parses file and computes an expression-level diff between the current state of the file and its most recently evaluated state. It then deletes any removed methods and re-evaluates any changed expressions. Note that generally it is better to use revise as it properly handles methods that move from one file to another.

id must be a key in Revise.pkgdatas, and file a key in Revise.pkgdatas[id].fileinfos.

source

Interchange between methods and signatures

Revise.get_methodFunction.
method = get_method(sigt)

Get the method method with signature-type sigt. This is used to provide the method to Base.delete_method.

If sigt does not correspond to a method, returns nothing.

Examples

julia> mymethod(::Int) = 1
mymethod (generic function with 1 method)

julia> mymethod(::AbstractFloat) = 2
mymethod (generic function with 2 methods)

julia> Revise.get_method(Tuple{typeof(mymethod), Int})
mymethod(::Int64) in Main at REPL[0]:1

julia> Revise.get_method(Tuple{typeof(mymethod), Float64})
mymethod(::AbstractFloat) in Main at REPL[1]:1

julia> Revise.get_method(Tuple{typeof(mymethod), Number})
source
Revise.get_defFunction.
success = get_def(method::Method)

As needed, load the source file necessary for extracting the code defining method. The source-file defining method must be tracked. If it is in Base, this will execute track(Base) if necessary.

This is a callback function used by CodeTracking.jl's definition.

source

Parsing source code

Revise.parse_sourceFunction.
mexs = parse_source(filename::AbstractString, mod::Module)

Parse the source filename, returning a ModuleExprsSigs mexs. mod is the "parent" module for the file (i.e., the one that included the file); if filename defines more module(s) then these will all have separate entries in mexs.

If parsing filename fails, nothing is returned.

source
Revise.parse_source!Function.
parse_source!(mexs::ModuleExprsSigs, filename, mod::Module)

Top-level parsing of filename as included into module mod. Successfully-parsed expressions will be added to mexs. Returns mexs if parsing finished successfully, otherwise nothing is returned.

See also Revise.parse_source.

source
success = parse_source!(mod_exprs_sigs::ModuleExprsSigs, src::AbstractString, filename::AbstractString, mod::Module)

Parse a string src obtained by reading file as a single string. pos is the 1-based byte offset from which to begin parsing src.

See also Revise.parse_source.

source

Modules and paths

Revise.modulefilesFunction.
parentfile, included_files = modulefiles(mod::Module)

Return the parentfile in which mod was defined, as well as a list of any other files that were included to define mod. If this operation is unsuccessful, (nothing, nothing) is returned.

All files are returned as absolute paths.

source

Git integration

Revise.git_sourceFunction.
Revise.git_source(file::AbstractString, reference)

Read the source-text for file from a git commit reference. The reference may be a string, Symbol, or LibGit2.Tree.

Example:

Revise.git_source("/path/to/myfile.jl", "HEAD")
Revise.git_source("/path/to/myfile.jl", :abcd1234)  # by commit SHA
source
Revise.git_filesFunction.
files = git_files(repo)

Return the list of files checked into repo.

source
Revise.git_repoFunction.
repo, repo_path = git_repo(path::AbstractString)

Return the repo::LibGit2.GitRepo containing the file or directory path. path does not necessarily need to be the top-level directory of the repository. Also returns the repo_path of the top-level directory for the repository.

source

Distributed computing

Revise.init_workerFunction.
Revise.init_worker(p)

Define methods on worker p that Revise needs in order to perform revisions on p. Revise itself does not need to be running on p.

source