Skip to content

Commit

Permalink
Start on #440
Browse files Browse the repository at this point in the history
  • Loading branch information
wlandau-lilly committed Jul 4, 2018
1 parent 2002653 commit 3112ee7
Show file tree
Hide file tree
Showing 20 changed files with 144 additions and 265 deletions.
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export(available_hash_algos)
export(backend)
export(bind_plans)
export(build_clustermq)
export(build_drake_graph)
export(build_graph)
export(build_times)
export(built)
Expand Down
22 changes: 15 additions & 7 deletions R/config.R
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,7 @@
#'
#' @param graph An `igraph` object from the previous `make()`.
#' Supplying a pre-built graph could save time.
#' The graph is constructed by [build_drake_graph()].
#' You can also get one from \code{\link{config}(my_plan)$graph}.
#' You can also get one from \code{\link{drake_config}(my_plan)$graph}.
#' Overrides `skip_imports`.
#'
#' @param trigger Name of the trigger to apply to all targets.
Expand Down Expand Up @@ -356,6 +355,10 @@
#' (`make(parallelism = x)`, where `x` could be `"mclapply"`,
#' `"parLapply"`, or `"future_lapply"`).
#'
#' @param meta an environment used as a hash table for quickly
#' looking up target/import-level metadata. You can supply a `meta`
#' from a previous `config` with this argument.
#'
#' @examples
#' \dontrun{
#' test_with_dir("Quarantine side effects.", {
Expand Down Expand Up @@ -416,7 +419,8 @@ drake_config <- function(
pruning_strategy = c("speed", "memory"),
makefile_path = "Makefile",
console_log_file = NULL,
ensure_workers = TRUE
ensure_workers = TRUE,
meta = NULL
){
force(envir)
unlink(console_log_file)
Expand Down Expand Up @@ -454,10 +458,14 @@ drake_config <- function(
)
seed <- choose_seed(supplied = seed, cache = cache)
trigger <- match.arg(arg = trigger, choices = triggers())
if (is.null(meta)){
meta <- initialize_meta_lookup(
plan = plan, targets = targets, envir = envir,
verbose = verbose, jobs = jobs, console_log_file = console_log_file
)
}
if (is.null(graph)){
graph <- build_drake_graph(plan = plan, targets = targets,
envir = envir, verbose = verbose, jobs = jobs,
sanitize_plan = FALSE, console_log_file = console_log_file)
graph <- build_igraph(targets = targets, meta = meta, jobs = jobs)
} else {
graph <- prune_drake_graph(graph = graph, to = targets, jobs = jobs)
}
Expand All @@ -471,7 +479,7 @@ drake_config <- function(
jobs_imports = jobs["imports"], jobs_targets = jobs["targets"],
verbose = verbose, hook = hook,
prepend = prepend, prework = prework, command = command,
args = args, recipe_command = recipe_command, graph = graph,
args = args, recipe_command = recipe_command, graph = graph, meta = meta,
short_hash_algo = cache$get("short_hash_algo", namespace = "config"),
long_hash_algo = cache$get("long_hash_algo", namespace = "config"),
seed = seed, trigger = trigger,
Expand Down
9 changes: 5 additions & 4 deletions R/dependencies.R
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,12 @@ tracked <- function(
verbose = drake::default_verbose()
){
force(envir)
graph <- build_drake_graph(
config <- drake_config(
plan = plan, targets = targets, envir = envir,
jobs = jobs, verbose = verbose
verbose = verbose, jobs = jobs,
cache = storr::storr_environment()
)
V(graph)$name
V(config$graph)$name
}

dependencies <- function(targets, config, reverse = FALSE){
Expand All @@ -231,7 +232,7 @@ import_dependencies <- function(expr){
# Imported functions can't have file_out() deps # nolint
# or target dependencies from knitr code chunks.
# However, file_in()s are totally fine. # nolint
deps$file_out <- deps$loadd <- deps$readd <- deps$strings <- NULL
deps$file_out <- deps$strings <- NULL
deps
}

Expand Down
27 changes: 15 additions & 12 deletions R/deprecate.R
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,18 @@ backend <- function(...){
}

#' @title Deprecated function `build_graph`
#' @description Use [build_drake_graph()] instead.
#' @description Use `drake_config()$graph` instead.
#' @details Deprecated on 2017-11-12.
#' @export
#' @keywords internal
#' @seealso [build_drake_graph()]
#' @return The same return value as [build_drake_graph()].
#' @param plan Same as for [build_drake_graph()].
#' @param targets Same as for [build_drake_graph()].
#' @param envir Same as for [build_drake_graph()].
#' @param verbose Same as for [build_drake_graph()].
#' @param jobs Same as for [build_drake_graph()].
#' @aliases build_drake_graph
#' @seealso [drake_config()]
#' @return The same return value as `drake_config()$graph`.
#' @param plan Same as for `drake_config()$graph`.
#' @param targets Same as for `drake_config()$graph`.
#' @param envir Same as for `drake_config()$graph`.
#' @param verbose Same as for `drake_config()$graph`.
#' @param jobs Same as for `drake_config()$graph`.
#' @examples
#' # See ?as_drake_filename for examples.
build_graph <- function(
Expand All @@ -130,15 +131,17 @@ build_graph <- function(
msg = paste(
"drake::build_graph() is deprecated",
"due to possible name conflicts.",
"Use build_drake_graph() instead."
"Use `drake_config()$graph` instead."
)
)
build_drake_graph(
drake_config(
plan = plan, targets = targets, envir = envir, verbose = verbose,
jobs = jobs
)
jobs = jobs, cache = storr::storr_environment()
)$graph
}

build_drake_graph <- build_graph

#' @title Deprecated function `check`
#' @description Use [check_plan()] instead.
#' @details Deprecated on 2017-11-12.
Expand Down
2 changes: 1 addition & 1 deletion R/drake_graph_info.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#' one for edges, and one for
#' the legend nodes. The list also contains the
#' default title of the graph.
#' @seealso [vis_drake_graph()], [build_drake_graph()]
#' @seealso [vis_drake_graph()]
#' @param config a [drake_config()] configuration list.
#' You can get one as a return value from [make()] as well.
#'
Expand Down
102 changes: 12 additions & 90 deletions R/graph.R
Original file line number Diff line number Diff line change
@@ -1,106 +1,29 @@
#' @title Create the `igraph` dependency network of your project.
#' @description This function returns an igraph object representing how
#' the targets in your workflow plan data frame
#' depend on each other.
#' (`help(package = "igraph")`). To plot the graph, call
#' to [plot.igraph()] on your graph, or just use
#' [vis_drake_graph()] from the start.
#' @seealso [vis_drake_graph()]
#' @export
#' @return An igraph object representing
#' the workflow plan dependency network.
#' @inheritParams drake_config
#' @param sanitize_plan logical, whether to sanitize the workflow plan first.
#' @examples
#' \dontrun{
#' test_with_dir("Quarantine side effects.", {
#' load_mtcars_example() # Get the code with drake_example("mtcars").
#' # Make the igraph network connecting all the targets and imports.
#' g <- build_drake_graph(my_plan)
#' class(g) # "igraph"
#' })
#' }
build_drake_graph <- function(
plan = read_drake_plan(),
targets = drake::possible_targets(plan),
envir = parent.frame(),
verbose = drake::default_verbose(),
jobs = 1,
sanitize_plan = TRUE,
console_log_file = NULL
){
force(envir)
if (sanitize_plan){
plan <- sanitize_plan(plan)
}
targets <- sanitize_targets(plan, targets)
imports <- as.list(envir)
unload_conflicts(
imports = names(imports),
targets = plan$target,
envir = envir,
verbose = verbose
)
import_names <- setdiff(names(imports), targets)
imports <- imports[import_names]
config <- list(verbose = verbose, console_log_file = console_log_file)
console_many_targets(
targets = names(imports),
pattern = "connect",
type = "import",
config = config
)
imports_edges <- lightly_parallelize(
X = seq_along(imports),
FUN = function(i){
imports_edges(name = import_names[[i]], value = imports[[i]])
},
jobs = jobs
)
console_many_targets(
targets = plan$target,
pattern = "connect",
type = "target",
config = config
)
commands_edges <- lightly_parallelize(
X = seq_len(nrow(plan)),
FUN = function(i){
commands_edges(target = plan$target[i], command = plan$command[i])
},
jobs = jobs
)
c(imports_edges, commands_edges) %>%
build_igraph <- function(targets, meta, jobs){
as.list(meta) %>%
purrr::map(.f = target_meta_to_edges) %>%
do.call(what = rbind) %>%
igraph::graph_from_data_frame() %>%
prune_drake_graph(to = targets, jobs = jobs) %>%
igraph::simplify(remove.multiple = TRUE, remove.loops = TRUE)
}

commands_edges <- function(target, command){
deps <- command_dependencies(command)
code_deps_to_edges(target = target, deps = deps)
}

imports_edges <- function(name, value){
deps <- import_dependencies(value)
code_deps_to_edges(target = name, deps = deps)
}

code_deps_to_edges <- function(target, deps){
inputs <- clean_dependency_list(deps[setdiff(names(deps), "file_out")])
target_meta_to_edges <- function(deps){
name <- deps$name
deps <- deps[
c("globals", "namespaced", "file_in", "knitr_in", "loadd", "readd")]
inputs <- clean_dependency_list(deps)
edges <- NULL
if (length(inputs)){
data.frame(from = inputs, to = target, stringsAsFactors = FALSE)
data.frame(from = inputs, to = name, stringsAsFactors = FALSE)
} else {
# Loops will be removed.
data.frame(from = target, to = target, stringsAsFactors = FALSE)
data.frame(from = name, to = name, stringsAsFactors = FALSE)
}
}

#' @title Prune the dependency network of your project.
#' @export
#' @seealso [build_drake_graph()], [config()],
#' @seealso [config()],
#' [make()]
#' @description `igraph` objects are used
#' internally to represent the dependency network of your workflow.
Expand All @@ -120,8 +43,7 @@ code_deps_to_edges <- function(target, deps){
#' test_with_dir("Quarantine side effects.", {
#' load_mtcars_example() # Get the code with drake_example("mtcars").
#' # Build the igraph object representing the workflow dependency network.
#' # You could also use drake_config(my_plan)$graph
#' graph <- build_drake_graph(my_plan)
#' graph <- drake_config(my_plan)$graph
#' # The default plotting is not the greatest,
#' # but you will get the idea.
#' plot(graph)
Expand Down
51 changes: 50 additions & 1 deletion R/meta.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,53 @@
#' @title Compute the initial pre-build metadata of a target or import.
initialize_meta_lookup <- function(
plan, targets, envir, verbose, jobs, console_log_file
){
imports <- as.list(envir)
unload_conflicts(
imports = names(imports),
targets = plan$target,
envir = envir,
verbose = verbose
)
import_names <- setdiff(names(imports), targets)
imports <- imports[import_names]
config <- list(verbose = verbose, console_log_file = console_log_file)
console_many_targets(
targets = names(imports),
pattern = "connect",
type = "import",
config = config
)
import_deps <- lightly_parallelize(
X = names(imports),
FUN = function(name){
out <- import_dependencies(imports[[name]])
out$name <- name
out
},
jobs = jobs
)
names(import_deps) <- names(imports)
console_many_targets(
targets = plan$target,
pattern = "connect",
type = "target",
config = config
)
command_deps <- lightly_parallelize(
X = seq_len(nrow(plan)),
FUN = function(i){
out <- command_dependencies(plan$command[i])
out$name <- plan$target[i]
out
},
jobs = jobs
)
names(command_deps) <- plan$target
list2env(c(import_deps, command_deps), parent = emptyenv(), hash = TRUE)
}

#' @title Compute the initial pre-build trigger-related
#' metadata of a target or import.
#' @description The metadata helps determine if the
#' target is up to date or outdated. The metadata of imports
#' is used to compute the metadata of targets.
Expand Down
2 changes: 1 addition & 1 deletion R/vis_drake_graph.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#' [drake_graph_info()] and [render_drake_graph()].
#' @export
#' @aliases drake_graph
#' @seealso [build_drake_graph()]
#' @seealso [drake_graph_info()], [render_drake_graph()]
#' @return A visNetwork graph.
#' @inheritParams drake_graph_info
#' @inheritParams render_drake_graph
Expand Down
1 change: 0 additions & 1 deletion _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ reference:
- '`plan_summaries`'
- title: Network graphs and visualization
contents:
- '`build_drake_graph`'
- '`drake_palette`'
- '`drake_graph_info`'
- '`legend_nodes`'
Expand Down
Loading

1 comment on commit 3112ee7

@lintr-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/testthat/test-graph.R:91:1: style: lines should not be more than 80 characters.

con <- drake_config(my_plan, targets = c("small", "large"), graph = con0$graph)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Please sign in to comment.