1: Safely set autos
If you would like to account for potential syntax errors when
sourcing in your autos
, you can wrap
rprofile()
in purrr::safely()
. This function
will attempt to set the autos and return a list containing the result
and any error that occurred.
Let’s show an example. First we’ll make an example configuration file
that will automatically source your autos. We’ll intentionally add a
syntax error to show how safely()
works.
Here is our configuration file, which will automatically source the
autos from the DEV
and PROD
directories:
default:
autos:
projects: !expr list(
"DEV" = file.path("demo", "DEV", "username", "project1", "functions"),
"PROD" = file.path("demo", "PROD", "project1", "functions")
)
We will do a little work here to create the directory, place a script
into the directory. We’ll add a syntax error by leaving off a closing
}
in test_error.R
script in the PROD
folder.
# create the temp directory
dir <- fs::file_temp()
dir.create(dir)
dir.create(file.path(dir, "/demo/PROD/project1/functions"), recursive = TRUE)
# write a function to the folder with an error
file_conn <- file(file.path(dir, "/demo/PROD/project1/functions/test_error.R"))
writeLines(
"test <- function(){print('test')", file_conn)
close(file_conn)
# write the config
config_path <- file.path(dir, "_envsetup.yml")
file_conn <- file(config_path)
writeLines(
paste0(
"default:
autos:
PROD: '", dir,"/demo/PROD/project1/functions'"
), file_conn)
close(file_conn)
So if we call rprofile()
passing in this config file, we
will get an error because of the syntax error in
test_error.R
:
library(envsetup)
#>
#> Attaching package: 'envsetup'
#> The following object is masked from 'package:base':
#>
#> library
envsetup_config <- config::get(file = config_path)
rprofile(envsetup_config)
#> Attaching paths to envsetup:paths
#> Error in `map2()`:
#> ℹ In index: 1.
#> ℹ With name: PROD.
#> Caused by error in `map()`:
#> ℹ In index: 1.
#> Caused by error in `parse()`:
#> ! 2:0: unexpected end of input
#> 1: test <- function(){print('test')
#> ^
To handle this error, we can use purrr::safely()
to wrap
the rprofile()
function. This will allow us to catch the
error and handle it gracefully.
safely_rprofile <- purrr::safely(rprofile)
ret <- safely_rprofile(envsetup_config)
#> Attaching paths to envsetup:paths
We still have an error, but safely allow the setup to continue. We
can check the result of the safely_rprofile()
function to
see if there was an error, identify the issue and correct the syntax
error in the function.
# check for errors and return if any occurred
if(!is.null(ret$error)) {
print(ret$error)
}
#> <error/purrr_error_indexed>
#> Error in `map2()`:
#> ℹ In index: 1.
#> ℹ With name: PROD.
#> Caused by error in `map()`:
#> ℹ In index: 1.
#> Caused by error in `parse()`:
#> ! 2:0: unexpected end of input
#> 1: test <- function(){print('test')
#> ^
#> ---
#> Backtrace:
#> ▆
#> 1. └─purrr (local) safely_rprofile(envsetup_config)
#> 2. ├─purrr:::capture_error(.f(...), otherwise, quiet)
#> 3. │ └─base::tryCatch(...)
#> 4. │ └─base (local) tryCatchList(expr, classes, parentenv, handlers)
#> 5. │ └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
#> 6. │ └─base (local) doTryCatch(return(expr), name, parentenv, handler)
#> 7. └─envsetup (local) .f(...)
#> 8. └─envsetup:::set_autos(config$autos)
#> 9. └─purrr::walk2(...)
#> 10. └─purrr::map2(.x, .y, .f, ..., .progress = .progress)
#> 11. └─purrr:::map2_("list", .x, .y, .f, ..., .progress = .progress)
#> 12. ├─purrr:::with_indexed_errors(...)
#> 13. │ └─base::withCallingHandlers(...)
#> 14. ├─purrr:::call_with_cleanup(...)
#> 15. └─envsetup (local) .f(.x[[i]], .y[[i]], ...)
#> 16. └─envsetup:::attach_auto(.x, .y)
#> 17. └─purrr::walk(...)
#> 18. └─purrr::map(.x, .f, ..., .progress = .progress)
#> 19. └─purrr:::map_("list", .x, .f, ..., .progress = .progress)
#> 20. ├─purrr:::with_indexed_errors(...)
#> 21. │ └─base::withCallingHandlers(...)
#> 22. ├─purrr:::call_with_cleanup(...)
#> 23. └─base (local) .f(.x[[i]], ...)
#> 24. └─base::parse(n = -1, file = file, srcfile = NULL, keep.source = FALSE)