Skip to content

Commit

Permalink
Use global validation on task load
Browse files Browse the repository at this point in the history
  • Loading branch information
richfitz committed Dec 18, 2023
1 parent 1158ac5 commit f27bae0
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
29 changes: 29 additions & 0 deletions R/environment.R
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,32 @@ discover_globals <- function(name, packages, sources, root) {
cli::cli_alert_success("Found {n} {cli::qty(n)}symbol{?s}")
res
}


check_globals <- function(globals, envir, call = call) {
if (length(globals) == 0) {
return()
}
values <- rlang::env_get_list(envir, names(globals), inherit = TRUE,
last = topenv())
hashes <- vcapply(values, rlang::hash)
err <- hashes != globals
if (any(err)) {
nms <- names(globals)[err]
n <- length(err)
hint <-
cli::cli_abort(
c("Unexpected value{?s} for global variable{?s}: {squote(nms)}",
i = paste(
"{cli::qty(n)}When we loaded your environment to run this task,",
"the value of {?this variable/these variables} differed from the",
"value we saw when saving the task originally.",
"{?This variable/These variables} were likely created when",
"sourcing your environment source scripts, so it's possible",
"that you changed these scripts since creating the task?"),
i = paste(
"Disable this check at task creation by setting the option",
"'hipercow.validate_globals' to FALSE")),
call = call)
}
}
1 change: 1 addition & 0 deletions R/task.R
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ task_eval <- function(id, envir = .GlobalEnv, root = NULL) {

result <- rlang::try_fetch({
environment_apply(data$environment, envir, root, top)
check_globals(data$variables$globals, envir, top)
withr::local_dir(file.path(root$path$root, data$path))
switch(
data$type,
Expand Down
29 changes: 27 additions & 2 deletions tests/testthat/test-task-expression.R
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ test_that("error on double quote", {
test_that("can run a task that uses variable from globals", {
path <- withr::local_tempfile()
root <- init_quietly(path)
writeLines(c("a <- 1", "b <- 2"), file.path(path, "src.R"))
writeLines("a <- 1", file.path(path, "src.R"))
suppressMessages(
hipercow_environment_create("foo", sources = "src.R", globals = "a",
root = path))
Expand All @@ -143,7 +143,7 @@ test_that("can run a task that uses variable from globals", {
test_that("can save information for global validation", {
path <- withr::local_tempfile()
root <- init_quietly(path)
writeLines(c("a <- 1", "b <- 2"), file.path(path, "src.R"))
writeLines("a <- 1", file.path(path, "src.R"))
suppressMessages(
hipercow_environment_create("foo", sources = "src.R", globals = "a",
root = path))
Expand All @@ -164,3 +164,28 @@ test_that("can save information for global validation", {
expect_equal(d$variables,
list(locals = list(b = 2), globals = c(a = rlang::hash(a))))
})


test_that("can validate globals on load", {
path <- withr::local_tempfile()
root <- init_quietly(path)
writeLines("a <- 2", file.path(path, "src.R"))
suppressMessages(
hipercow_environment_create("foo", sources = "src.R", globals = "a",
root = path))

a <- 2
withr::local_options(hipercow.validate_globals = TRUE)
id1 <- withr::with_dir(path,
task_create_expr(sqrt(a), environment = "foo"))
id2 <- withr::with_dir(path,
task_create_expr(sqrt(a), environment = "foo"))

env <- new.env(parent = topenv())
expect_true(task_eval(id1, env, root = path))
expect_equal(task_result(id1, root = path), sqrt(2))
writeLines("a <- 3", file.path(path, "src.R"))
expect_false(task_eval(id2, env, root = path))
err <- task_result(id2, root = path)
expect_match(err$message, "Unexpected value for global variable: 'a'")
})

0 comments on commit f27bae0

Please sign in to comment.