Skip to content

Commit

Permalink
Add option to suppress tidy evaluation in drake_plan()
Browse files Browse the repository at this point in the history
  • Loading branch information
wlandau committed Jan 30, 2018
1 parent 2d5bee1 commit c8d52c4
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 48 deletions.
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Version 5.1.0

- Evaluate the quasiquotation operator `!!` for the `...` argument to `drake_plan()`. Suppress this behavior for the commands passed through the `list` argument.
- Evaluate the quasiquotation operator `!!` for the `...` argument to `drake_plan()`. Suppress this behavior using `tidy_evaluation = FALSE` or by passing in commands passed through the `list` argument.
- Preprocess workflow plan commands with `rlang::expr()` before evaluating them. That means you can use the quasiquotation operator `!!` in your commands, and `make()` will evaluate them according to the tidy evaluation paradigm.
- Restructure `drake_example("basic")`, `drake_example("gsp")`, and `drake_example("packages")` to demonstrate how to set up the files for serious `drake` projects. More guidance was needed in light of [this issue](https://github.com/ropensci/drake/issues/193).
- Improve the examples of `drake_plan()` in the help file (`?drake_plan`).
Expand Down
22 changes: 19 additions & 3 deletions R/workplan.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
#' \code{...} argument. R will either convert all these quotes
#' to single quotes or double quotes. Literal quotes in the
#' \code{list} argument are left alone.
#' @param tidy_evaluation logical, whether to use tidy evaluation
#' such as quasiquotation
#' when evaluating commands passed through the free-form
#' \code{...} argument.
#' @examples
#' # Create example workflow plan data frames for make()
#' drake_plan(small = simulate(5), large = simulate(50))
Expand Down Expand Up @@ -80,24 +84,36 @@
#' # drake_plan() uses tidy evaluation to figure out your commands.
#' # For example, it respects the quasiquotation operator `!!`
#' # when it figures out what your code should be.
#' # Suppress this with the `list` argument.
#' # Suppress this with `tidy_evaluation = FALSE` or
#' # with the `list` argument.
#' my_variable <- 5
#' drake_plan(
#' a = !!my_variable,
#' b = !!my_variable + 1,
#' list = c(d = "!!my_variable")
#' )
#' drake_plan(
#' a = !!my_variable,
#' b = !!my_variable + 1,
#' list = c(d = "!!my_variable"),
#' tidy_evaluation = FALSE
#' )
#' # For instances of !! that remain unevaluated in the workflow plan,
#' # make() will run these commands in tidy fashion,
#' # evaluating the !! operator using the environment you provided.
drake_plan <- function(
...,
list = character(0),
file_targets = FALSE,
strings_in_dots = c("filenames", "literals")
strings_in_dots = c("filenames", "literals"),
tidy_evaluation = TRUE
){
strings_in_dots <- match.arg(strings_in_dots)
dots <- rlang::exprs(...) # Enables quasiquotation via rlang.
if (tidy_evaluation){
dots <- rlang::exprs(...) # Enables quasiquotation via rlang.
} else {
dots <- match.call(expand.dots = FALSE)$...
}
commands_dots <- lapply(dots, wide_deparse)
names(commands_dots) <- names(dots)
commands <- c(commands_dots, list)
Expand Down
11 changes: 10 additions & 1 deletion inst/examples/basic/interactive-tutorial.R
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,24 @@ my_plan <- rbind(report, my_datasets, my_analyses, results)
# For the commands you specify the free-form `...` argument,
# `drake_plan()` also supports tidy evaluation.
# For example, it supports quasiquotation with the `!!` argument.
# Use the `list` argument to suppress this behavior.
# Use `tidy_evaluation = FALSE` or the `list` argument
# to suppress this behavior.

my_variable <- 5

drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable")
)

drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable"),
tidy_evaluation = FALSE
)

# For instances of !! that remain in the workflow plan,
# make() will run these commands in tidy fashion,
# evaluating the !! operator using the environment you provided.
Expand Down
20 changes: 18 additions & 2 deletions man/drake_plan.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion tests/testthat/test-tidy-eval.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ drake_context("tidy eval")

# From Kendon Bell: https://github.com/ropensci/drake/issues/200
test_with_dir("drake_plan does tidy eval in `...` argument", {
my_variable <- 5
plan1 <- drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable")
)
)
plan2 <- data.frame(
target = c("a", "b", "d"),
command = c("5", "6", "!!my_variable"),
Expand All @@ -15,6 +16,22 @@ test_with_dir("drake_plan does tidy eval in `...` argument", {
expect_equal(plan1, plan2)
})

# From Alex Axthelm: https://github.com/ropensci/drake/issues/200
test_with_dir("drake_plan tidy eval can be disabled", {
plan1 <- drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable"),
tidy_evaluation = FALSE
)
plan2 <- data.frame(
target = c("a", "b", "d"),
command = c("!(!my_variable)", "!(!my_variable + 1)", "!!my_variable"),
stringsAsFactors = FALSE
)
expect_equal(plan1, plan2)
})

# From Kendon Bell: https://github.com/ropensci/drake/issues/200
test_with_dir("make() does tidy eval in commands", {
con <- dbug()
Expand Down
96 changes: 59 additions & 37 deletions tests/testthat/test-workflow-plan.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,73 +11,95 @@ test_with_dir("empty plan", {
})

test_with_dir("plan set 1", {
x <- drake_plan(
a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"))
y <- data.frame(
target = letters[1:4],
command = c("c", "'c'",
"d", "readRDS('e')"),
stringsAsFactors = F)
expect_equal(x, y)
for (tidy_evaluation in c(TRUE, FALSE)){
x <- drake_plan(
a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"),
tidy_evaluation = tidy_evaluation
)
y <- data.frame(
target = letters[1:4],
command = c("c", "'c'",
"d", "readRDS('e')"),
stringsAsFactors = F)
expect_equal(x, y)
}
})

test_with_dir("plan set 2", {
x <- drake_plan(a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"),
strings_in_dots = "literals")
y <- data.frame(
target = letters[1:4],
command = c("c", "\"c\"",
"d", "readRDS('e')"), stringsAsFactors = F)
expect_equal(x, y)
for (tidy_evaluation in c(TRUE, FALSE)){
x <- drake_plan(a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"),
strings_in_dots = "literals",
tidy_evaluation = tidy_evaluation)
y <- data.frame(
target = letters[1:4],
command = c("c", "\"c\"",
"d", "readRDS('e')"), stringsAsFactors = F)
expect_equal(x, y)
}
})

test_with_dir("plan set 3", {
for (tidy_evaluation in c(TRUE, FALSE)){
x <- drake_plan(
a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"),
strings_in_dots = "literals", file_targets = TRUE)
strings_in_dots = "literals", file_targets = TRUE,
tidy_evaluation = tidy_evaluation)
y <- data.frame(
target = drake::drake_quotes(letters[1:4], single = TRUE),
command = c("c", "\"c\"", "d", "readRDS('e')"),
stringsAsFactors = F)
expect_equal(x, y)
}
})

test_with_dir("plan set 4", {
x <- drake_plan(
a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"),
strings_in_dots = "filenames", file_targets = TRUE)
y <- data.frame(
target = drake::drake_quotes(letters[1:4], single = TRUE),
command = c("c", "'c'", "d", "readRDS('e')"), stringsAsFactors = F)
expect_equal(x, y)
expect_warning(check_plan(x, verbose = FALSE))
for (tidy_evaluation in c(TRUE, FALSE)){
x <- drake_plan(
a = c,
b = "c",
list = c(c = "d", d = "readRDS('e')"),
strings_in_dots = "filenames", file_targets = TRUE,
tidy_evaluation = tidy_evaluation)
y <- data.frame(
target = drake::drake_quotes(letters[1:4], single = TRUE),
command = c("c", "'c'", "d", "readRDS('e')"), stringsAsFactors = F)
expect_equal(x, y)
expect_warning(check_plan(x, verbose = FALSE))
}
})

test_with_dir("drake_plan() trims outer whitespace in target names", {
x <- drake_plan(list = c(` a` = 1, `b \t\n` = 2))
y <- drake_plan(a = 1, b = 2)
expect_equal(x$target, y$target)
for (tidy_evaluation in c(TRUE, FALSE)){
x <- drake_plan(list = c(` a` = 1, `b \t\n` = 2),
tidy_evaluation = tidy_evaluation)
y <- drake_plan(a = 1, b = 2, tidy_evaluation = tidy_evaluation)
expect_equal(x$target, y$target)
}
})

test_with_dir("make() and check_plan() trim outer whitespace in target names", {
x <- data.frame(target = c("a\n", " b", "c ", "\t d "),
command = 1)
command = 1)
expect_silent(make(x, verbose = FALSE, session_info = FALSE))
expect_equal(sort(cached()), letters[1:4])
stat <- c(a = "finished", b = "finished", c = "finished",
d = "finished")
d = "finished")
expect_equal(progress(), stat)

expect_warning(make(x, verbose = FALSE, targets = c("a",
"nobody_home"), session_info = FALSE))
expect_warning(
make(
x,
verbose = FALSE,
targets = c("a", "nobody_home"),
session_info = FALSE
)
)

x <- data.frame(target = c("a", " a"), command = 1)
expect_error(check_plan(x, verbose = FALSE))
Expand Down
10 changes: 9 additions & 1 deletion vignettes/caution.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,23 @@ make(my_plan)
readd(letter)
```

For the commands you specify the free-form `...` argument, `drake_plan()` also supports tidy evaluation. For example, it supports quasiquotation with the `!!` argument. Use the `list` argument to suppress this behavior.
For the commands you specify the free-form `...` argument, `drake_plan()` also supports tidy evaluation. For example, it supports quasiquotation with the `!!` argument. Use `tidy_evaluation = FALSE` or the `list` argument to suppress this behavior.

```{r testquasiquoplan}
my_variable <- 5
drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable")
)
drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable"),
tidy_evaluation = FALSE
)
```

For instances of `!!` that remain in the workflow plan, `make()` will run these commands in tidy fashion, evaluating the `!!` operator using the environment you provided.
Expand Down
10 changes: 9 additions & 1 deletion vignettes/drake.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,23 @@ whole_plan <- rbind(dataset_plan, analysis_plan)
whole_plan
```

For the commands you pass in with the free-form `...` argument, `drake_plan()` uses tidy evaluation. For example, it supports quasiquotation with the `!!` argument. Use the `list` argument to suppress this behavior.
For the commands you pass in with the free-form `...` argument, `drake_plan()` uses tidy evaluation. For example, it supports quasiquotation with the `!!` argument. Use `tidy_evaluation = FALSE` or the `list` argument to suppress this behavior.

```{r testquasiquoplan}
my_variable <- 5
drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable")
)
drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable"),
tidy_evaluation = FALSE
)
```

For instances of `!!` that remain in the workflow plan, `make()` will run these commands in tidy fashion, evaluating the `!!` operator using the environment you provided.
Expand Down
10 changes: 9 additions & 1 deletion vignettes/quickstart.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -483,15 +483,23 @@ make(my_plan)
readd(letter)
```

For the commands you specify the free-form `...` argument, `drake_plan()` also supports tidy evaluation. For example, it supports quasiquotation with the `!!` argument. Use the `list` argument to suppress this behavior.
For the commands you specify the free-form `...` argument, `drake_plan()` also supports tidy evaluation. For example, it supports quasiquotation with the `!!` argument. Use `tidy_evaluation = FALSE` or the `list` argument to suppress this behavior.

```{r testquasiquoplan}
my_variable <- 5
drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable")
)
drake_plan(
a = !!my_variable,
b = !!my_variable + 1,
list = c(d = "!!my_variable"),
tidy_evaluation = FALSE
)
```

For instances of `!!` that remain in the workflow plan, `make()` will run these commands in tidy fashion, evaluating the `!!` operator using the environment you provided.
Expand Down

0 comments on commit c8d52c4

Please sign in to comment.