Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Imports:
utils
Suggests:
bitops,
callr,
jsonlite,
mathjaxr,
pak,
Expand Down
49 changes: 32 additions & 17 deletions R/load-data.R
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this has the side effect of editing the user's search path, of course, but I think "it's fine".

it might wind up looking comparable to instead set up a shim environment between lazydata_env and package:base that copies {utils} exports, avoiding the somewhat hacky parent.env() code below.


# 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)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gemini went ahead and corrected that sys.source() returns NULL, thus the earlier code was not actually populating the names of the objects found.

Not sure the intended behavior; we could (a) just use the simpler approach where we ignore the names for .R files; (b) add a new regression test that the return value of load_data() is WAI; (c) do nothing

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)
Expand Down
15 changes: 15 additions & 0 deletions tests/testthat/test-load-data.R
Original file line number Diff line number Diff line change
@@ -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
)
})
7 changes: 7 additions & 0 deletions tests/testthat/testDataUtils/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions tests/testthat/testDataUtils/data/myData.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
myData <- read.csv(text = "a,b,c\n1,2,3\n")