From 0b7abee146b8d35aaffcf242d02d05b83337a8b5 Mon Sep 17 00:00:00 2001 From: Noam Ross Date: Fri, 11 Aug 2023 12:19:29 -0400 Subject: [PATCH] project workflow improvements - Use capsule for easier renv management - Create a separate sandbox targets project - Load multiple .env files - Use .env_user for setting USE_CAPSULE and TAR_PROJECT) - .gitignore stuff appropriately to retain outputs and keep meta files - Add all_targets() convenience function --- .Rprofile | 23 +++++++++++++++-------- .gitignore | 12 +++++++----- R/utils.R | 29 +++++++++++++++++++++++++++++ _targets.R | 18 +++++++----------- _targets_sandbox.R | 13 +++++++++++++ targets.yaml | 6 ++++++ 6 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 R/utils.R create mode 100644 _targets_sandbox.R create mode 100644 targets.yaml diff --git a/.Rprofile b/.Rprofile index 68d6a25..f13c8ce 100644 --- a/.Rprofile +++ b/.Rprofile @@ -1,17 +1,24 @@ -if (file.exists(".env")) { - try(readRenviron(".env")) -} else { - message("No .env file") +for (env_file in list.files(all.files = TRUE, pattern = "^\\.env.*")) { + try(readRenviron(env_file), silent = TRUE) } + # Put the project library *outside* the project #Sys.setenv(RENV_PATHS_LIBRARY_ROOT = file.path(normalizePath("~/.renv-project-libraries", mustWork = FALSE))) -if (file.exists("renv/activate.R")) { - source("renv/activate.R") +if(Sys.getenv("USE_CAPSULE") %in% c("1", "TRUE", "true")) { + if (interactive() && file.exists("renv.lock")) { + message("renv library not loaded (found env var USE_CAPSULE=", Sys.getenv("USE_CAPSULE"), "). Use `capsule` functions (see https://github.com/MilesMcBain/capsule)") + if(require(capsule, quietly = TRUE)) { + capsule::whinge() + } else { + message('Install {capsule} with install.packages("capsule", repos = c(mm = "https://milesmcbain.r-universe.dev", getOption("repos")))') + } + } } else { - message("No renv/activate.R") -} + source("renv/activate.R") +} + # Use the local user's .Rprofile when interactive. # Good for keeping local preferences, but not always reproducible. diff --git a/.gitignore b/.gitignore index 34d29e5..59a636f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,12 +3,14 @@ .RData .Ruserdata .DS_Store -_targets/objects -_targets.yaml +.env_user +_targets/ +_targets/* +!_targets/meta/meta +_targets_sandbox/ +_targets_sandbox/* +!_targets_sandbox/meta/meta nohup.out -outputs/ -!outputs/.gitkeep -!outputs/example_report.html data/archive data/**/*.csv.gz data/**/*.grib diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..929c908 --- /dev/null +++ b/R/utils.R @@ -0,0 +1,29 @@ +#' Collect all targets and lists of targets in the environment +all_targets <- function(env = parent.env(environment()), type = "tar_target") { + rfn <- function(obj) inherits(obj, type) || (is.list(obj) && all(vapply(obj, rfn, logical(1)))) + objs <- ls(env) + out <- list() + for(o in objs) { + obj <- get(o, envir = env) + if (rfn(obj)) { + out[[length(out) + 1]] <- obj + } + } + return(out) +} + +# TODO: convenience functions for reading targets from S3 +# Need to figure out the best way for these to work with both regular and +# file-type targets, which should emerge from working with them in the sandbox +# tar_read_s3 <- function(target_name, bucket = Sys.getenv("AWS_BUCKET_ID"), +# prefix = "_targets") { +# ## if target_name does not exist, convert the symbol to character +# if (!exists(target_name)) { +# target_name <- as.character(substitute(target_name)) +# } +# +# } +# +# tar_load_s3 <- function(target_name, ...) { +# +# } \ No newline at end of file diff --git a/_targets.R b/_targets.R index 2df25bb..1aca922 100644 --- a/_targets.R +++ b/_targets.R @@ -1,3 +1,9 @@ +# Re-record current dependencies for CAPSULE users +if(Sys.getenv("USE_CAPSULE") %in% c("1", "TRUE", "true")) + capsule::capshot(c("packages.R", + list.files(pattern = "_targets.*\\.(r|R)$", full.names = TRUE), + list.files("R", pattern = "\\.(R|r)$", full.names = TRUE))) + # Load packages (in packages.R) and load project-specific functions in R folder suppressPackageStartupMessages(source("packages.R")) for (f in list.files(here::here("R"), full.names = TRUE)) source (f) @@ -234,14 +240,4 @@ test_targets <- tar_plan( ) # List targets ----------------------------------------------------------------- - -list( - static_targets, - dynamic_targets, - data_targets, - model_targets, - deploy_targets, - plot_targets, - report_targets, - test_targets -) +all_targets() diff --git a/_targets_sandbox.R b/_targets_sandbox.R new file mode 100644 index 0000000..febcc7b --- /dev/null +++ b/_targets_sandbox.R @@ -0,0 +1,13 @@ +# Re-record current dependencies for CAPSULE users +if(Sys.getenv("USE_CAPSULE") %in% c("1", "TRUE", "true")) + capsule::capshot(c("packages.R", + list.files(pattern = "_targets.*\\.(r|R)$", full.names = TRUE), + list.files("R", pattern = "\\.(R|r)$", full.names = TRUE))) + +# Load packages (in packages.R) and load project-specific functions in R folder +suppressPackageStartupMessages(source("packages.R")) +for (f in list.files(here::here("R"), full.names = TRUE)) source (f) + + + +all_targets() \ No newline at end of file diff --git a/targets.yaml b/targets.yaml new file mode 100644 index 0000000..7d47d67 --- /dev/null +++ b/targets.yaml @@ -0,0 +1,6 @@ +main: + store: _targets + script: _targets.R +sandbox: + store: _targets_sandbox + script: _targets_sandbox.R