diff --git a/DESCRIPTION b/DESCRIPTION index c317f4e..5cdc2de 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -32,6 +32,7 @@ Imports: utils Suggests: bitops, + callr, jsonlite, mathjaxr, pak, diff --git a/R/load-data.R b/R/load-data.R index 299e345..d1cf222 100644 --- a/R/load-data.R +++ b/R/load-data.R @@ -22,23 +22,38 @@ load_data <- function(path = ".") { } path_data <- package_file("data", path = path) - if (file.exists(path_data)) { - paths <- dir(path_data, "\\.[rR][dD]a(ta)?$", full.names = TRUE) - paths <- changed_files(paths) - objs <- c(objs, unlist(lapply(paths, load, envir = lazydata_env))) - - paths <- dir(path_data, "\\.[rR]$", full.names = TRUE) - paths <- changed_files(paths) - objs <- c( - objs, - unlist(lapply( - paths, - sys.source, - envir = lazydata_env, - chdir = TRUE, - keep.source = TRUE - )) - ) + if (!file.exists(path_data)) { + return(invisible(objs)) + } + + paths_rda <- dir(path_data, "\\.[rR][dD]a(ta)?$", full.names = TRUE) + paths_rda <- changed_files(paths_rda) + objs <- c(objs, unlist(lapply(paths_rda, load, envir = lazydata_env))) + + paths_r <- dir(path_data, "\\.[rR]$", full.names = TRUE) + paths_r <- changed_files(paths_r) + if (length(paths_r) == 0) { + return(invisible(objs)) + } + + # always attach, as utils::data does. evalq to hide library from R CMD check + evalq(library(utils)) + + # We source the .R files into lazydata_env, but we want them to be + # able to find functions in the default packages like utils. + # By default lazydata_env inherits from base, bypassing the search path. + # We temporarily change its parent to .GlobalEnv so it can see the search path. + old_parent <- parent.env(lazydata_env) + parent.env(lazydata_env) <- .GlobalEnv + on.exit(parent.env(lazydata_env) <- old_parent, add = TRUE) + + # sys.source() returns invisible() so it doesn't return the names of the + # objects it creates. We'll need to find them ourselves. + for (path in paths_r) { + old_objs <- ls(lazydata_env, all.names = TRUE) + sys.source(path, envir = lazydata_env, chdir = TRUE, keep.source = TRUE) + new_objs <- ls(lazydata_env, all.names = TRUE) + objs <- c(objs, setdiff(new_objs, old_objs)) } invisible(objs) diff --git a/tests/testthat/test-load-data.R b/tests/testthat/test-load-data.R new file mode 100644 index 0000000..1c84626 --- /dev/null +++ b/tests/testthat/test-load-data.R @@ -0,0 +1,15 @@ +test_that("load_data can load .R files that use utils functions in a clean environment", { + pkg_path <- normalizePath(test_path("testDataUtils"), mustWork = TRUE) + + expect_equal( + callr::r( + function(pkg_path) { + pkgload::load_all(pkg_path) + testDataUtils::myData$a + }, + args = list(pkg_path = pkg_path), + env = c(R_DEFAULT_PACKAGES = "NULL") + ), + 1L + ) +}) diff --git a/tests/testthat/testDataUtils/DESCRIPTION b/tests/testthat/testDataUtils/DESCRIPTION new file mode 100644 index 0000000..5cb74df --- /dev/null +++ b/tests/testthat/testDataUtils/DESCRIPTION @@ -0,0 +1,7 @@ +Package: testDataUtils +Title: Test Package for load_data with utils +Version: 0.0.1 +Description: Test package. +License: MIT +Encoding: UTF-8 +LazyData: true diff --git a/tests/testthat/testDataUtils/data/myData.R b/tests/testthat/testDataUtils/data/myData.R new file mode 100644 index 0000000..ae63d58 --- /dev/null +++ b/tests/testthat/testDataUtils/data/myData.R @@ -0,0 +1 @@ +myData <- read.csv(text = "a,b,c\n1,2,3\n")