In this new set of features, I am trying to steer drake
away from the user's global environment. This is challenging because users can define arbitrarily nested code files. Let's say a user defines files packages.R
, functions.R
, and master.R
as below.
writeLines("library(MASS)", "packages.R")
writeLines("util <- function() {'utility'}", "functions.R")
writeLines(c("source('packages.R')", "source('functions.R')"), "master.R")
cat(readLines("packages.R"), sep = "\n")
#> library(MASS)
cat(readLines("functions.R"), sep = "\n")
#> util <- function() {'utility'}
cat(readLines("master.R"), sep = "\n")
#> source('packages.R')
#> source('functions.R')
As the developer, I am looking for a way to run master.R
such that none of the new data objects ends up in the global environment. My initial attempts do not succeed.
Current behavior
envir <- new.env(parent = globalenv())
source("master.R", local = envir)
ls(envir)
#> character(0)
ls()
#> [1] "envir" "util"
Desired result
envir <- new.env(parent = globalenv())
# Run master.R
ls(envir)
#> [1] "util"
ls()
#> [1] "envir"
Constraints
- I am not allowed to modify the code inside
packages.R
,functions.R
, ormaster.R
. As the developer, I only have control over the# Run master.R
line above. - Sourcing the files in the global environment and then manually copying to a different environment is fraught with closure and lexical scoping pitfalls, so I would strongly prefer to stay away from that.