-
-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into test@bslib@main
- Loading branch information
Showing
14 changed files
with
345 additions
and
217 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
Type: Package | ||
Package: teal | ||
Title: Exploratory Web Apps for Analyzing Clinical Trials Data | ||
Version: 0.15.2.9063 | ||
Date: 2024-09-17 | ||
Version: 0.15.2.9064 | ||
Date: 2024-09-23 | ||
Authors@R: c( | ||
person("Dawid", "Kaledkowski", , "[email protected]", role = c("aut", "cre"), | ||
comment = c(ORCID = "0000-0001-9533-457X")), | ||
|
@@ -42,13 +42,10 @@ Depends: | |
Imports: | ||
bslib (>= 0.8.0), | ||
checkmate (>= 2.1.0), | ||
future (>= 1.33.2), | ||
jsonlite, | ||
lifecycle (>= 0.2.0), | ||
logger (>= 0.2.0), | ||
methods, | ||
promises (>= 1.3.0), | ||
renv (>= 1.0.7), | ||
rlang (>= 1.0.0), | ||
shinyjs, | ||
stats, | ||
|
@@ -59,8 +56,10 @@ Imports: | |
utils | ||
Suggests: | ||
knitr (>= 1.42), | ||
mirai (>= 1.1.1), | ||
MultiAssayExperiment, | ||
R6, | ||
renv (>= 1.0.7), | ||
rmarkdown (>= 2.23), | ||
rvest, | ||
shinytest2, | ||
|
@@ -73,15 +72,15 @@ VignetteBuilder: | |
RdMacros: | ||
lifecycle | ||
Config/Needs/verdepcheck: rstudio/shiny, insightsengineering/teal.data, | ||
insightsengineering/teal.slice, mllg/checkmate, | ||
HenrikBengtsson/future, jeroen/jsonlite, r-lib/lifecycle, | ||
daroczig/logger, rstudio/promises, rstudio/renv, r-lib/rlang, | ||
daattali/shinyjs, insightsengineering/teal.code, | ||
insightsengineering/teal.logger, insightsengineering/teal.reporter, | ||
insightsengineering/teal.widgets, rstudio/bslib, yihui/knitr, | ||
bioc::MultiAssayExperiment, r-lib/R6, rstudio/rmarkdown, | ||
tidyverse/rvest, rstudio/shinytest2, rstudio/shinyvalidate, | ||
r-lib/testthat, r-lib/withr, yaml=vubiostat/r-yaml | ||
insightsengineering/teal.slice, mllg/checkmate, jeroen/jsonlite, | ||
r-lib/lifecycle, daroczig/logger, shikokuchuo/mirai, | ||
shikokuchuo/nanonext, rstudio/renv, r-lib/rlang, daattali/shinyjs, | ||
insightsengineering/teal.code, insightsengineering/teal.logger, | ||
insightsengineering/teal.reporter, insightsengineering/teal.widgets, | ||
rstudio/bslib, yihui/knitr, bioc::MultiAssayExperiment, r-lib/R6, | ||
rstudio/rmarkdown, tidyverse/rvest, rstudio/shinytest2, | ||
rstudio/shinyvalidate, r-lib/testthat, r-lib/withr, | ||
yaml=vubiostat/r-yaml | ||
Config/Needs/website: insightsengineering/nesttemplate | ||
Encoding: UTF-8 | ||
Language: en-US | ||
|
@@ -106,6 +105,7 @@ Collate: | |
'module_snapshot_manager.R' | ||
'module_teal.R' | ||
'module_teal_data.R' | ||
'module_teal_lockfile.R' | ||
'module_teal_with_splash.R' | ||
'module_transform_data.R' | ||
'reporter_previewer_module.R' | ||
|
@@ -116,7 +116,6 @@ Collate: | |
'teal_data_module-eval_code.R' | ||
'teal_data_module-within.R' | ||
'teal_data_utils.R' | ||
'teal_lockfile.R' | ||
'teal_reporter.R' | ||
'teal_slices-store.R' | ||
'teal_slices.R' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
# teal 0.15.2.9063 | ||
# teal 0.15.2.9064 | ||
|
||
### New features | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
#' Generate lockfile for application's environment reproducibility | ||
#' | ||
#' @param lockfile_path (`character`) path to the lockfile. | ||
#' | ||
#' @section Different ways of creating lockfile: | ||
#' `teal` leverages [renv::snapshot()], which offers multiple methods for lockfile creation. | ||
#' | ||
#' - **Working directory lockfile**: `teal`, by default, will create an `implicit` type lockfile that uses | ||
#' `renv::dependencies()` to detect all R packages in the current project's working directory. | ||
#' - **`DESCRIPTION`-based lockfile**: To generate a lockfile based on a `DESCRIPTION` file in your working | ||
#' directory, set `renv::settings$snapshot.type("explicit")`. The naming convention for `type` follows | ||
#' `renv::snapshot()`. For the `"explicit"` type, refer to `renv::settings$package.dependency.fields()` for the | ||
#' `DESCRIPTION` fields included in the lockfile. | ||
#' - **Custom files-based lockfile**: To specify custom files as the basis for the lockfile, set | ||
#' `renv::settings$snapshot.type("custom")` and configure the `renv.snapshot.filter` option. | ||
#' | ||
#' @section lockfile usage: | ||
#' After creating the lockfile, you can restore the application's environment using `renv::restore()`. | ||
#' | ||
#' @seealso [renv::snapshot()], [renv::restore()]. | ||
#' | ||
#' @return `NULL` | ||
#' | ||
#' @name module_teal_lockfile | ||
#' @rdname module_teal_lockfile | ||
#' | ||
#' @keywords internal | ||
NULL | ||
|
||
#' @rdname module_teal_lockfile | ||
ui_teal_lockfile <- function(id) { | ||
ns <- NS(id) | ||
shiny::tagList( | ||
tags$span("", id = ns("lockFileStatus")), | ||
shinyjs::disabled(downloadLink(ns("lockFileLink"), "Download lockfile")) | ||
) | ||
} | ||
|
||
#' @rdname module_teal_lockfile | ||
srv_teal_lockfile <- function(id) { | ||
moduleServer(id, function(input, output, session) { | ||
logger::log_debug("Initialize srv_teal_lockfile.") | ||
enable_lockfile_download <- function() { | ||
shinyjs::html("lockFileStatus", "Application lockfile ready.") | ||
shinyjs::hide("lockFileStatus", anim = TRUE) | ||
shinyjs::enable("lockFileLink") | ||
output$lockFileLink <- shiny::downloadHandler( | ||
filename = function() { | ||
"renv.lock" | ||
}, | ||
content = function(file) { | ||
file.copy(lockfile_path, file) | ||
file | ||
}, | ||
contentType = "application/json" | ||
) | ||
} | ||
disable_lockfile_download <- function() { | ||
warning("Lockfile creation failed.", call. = FALSE) | ||
shinyjs::html("lockFileStatus", "Lockfile creation failed.") | ||
shinyjs::hide("lockFileLink") | ||
} | ||
|
||
shiny::onStop(function() { | ||
if (file.exists(lockfile_path) && !shiny::isRunning()) { | ||
logger::log_debug("Removing lockfile after shutting down the app") | ||
file.remove(lockfile_path) | ||
} | ||
}) | ||
|
||
lockfile_path <- "teal_app.lock" | ||
mode <- getOption("teal.lockfile.mode", default = "") | ||
|
||
if (!(mode %in% c("auto", "enabled", "disabled"))) { | ||
stop("'teal.lockfile.mode' option can only be one of \"auto\", \"disabled\" or \"disabled\". ") | ||
} | ||
|
||
if (mode == "disabled") { | ||
logger::log_debug("'teal.lockfile.mode' option is set to 'disabled'. Hiding lockfile download button.") | ||
shinyjs::hide("lockFileLink") | ||
return(NULL) | ||
} | ||
|
||
if (file.exists(lockfile_path)) { | ||
logger::log_debug("Lockfile has already been created for this app - skipping automatic creation.") | ||
enable_lockfile_download() | ||
return(NULL) | ||
} | ||
|
||
if (mode == "auto" && .is_disabled_lockfile_scenario()) { | ||
logger::log_debug( | ||
"Automatic lockfile creation disabled. Execution scenario satisfies teal:::.is_disabled_lockfile_scenario()." | ||
) | ||
shinyjs::hide("lockFileLink") | ||
return(NULL) | ||
} | ||
|
||
if (!.is_lockfile_deps_installed()) { | ||
warning("Automatic lockfile creation disabled. `mirai` and `renv` packages must be installed.") | ||
shinyjs::hide("lockFileLink") | ||
return(NULL) | ||
} | ||
|
||
# - Will be run only if the lockfile doesn't exist (see the if-s above) | ||
# - We render to the tempfile because the process might last after session is closed and we don't | ||
# want to make a "teal_app.renv" then. This is why we copy only during active session. | ||
process <- .teal_lockfile_process_invoke(lockfile_path) | ||
observeEvent(process$status(), { | ||
if (process$status() %in% c("initial", "running")) { | ||
shinyjs::html("lockFileStatus", "Creating lockfile...") | ||
} else if (process$status() == "success") { | ||
result <- process$result() | ||
if (any(grepl("Lockfile written to", result$out))) { | ||
logger::log_debug("Lockfile containing { length(result$res$Packages) } packages created.") | ||
if (any(grepl("(WARNING|ERROR):", result$out))) { | ||
warning("Lockfile created with warning(s) or error(s):", call. = FALSE) | ||
for (i in result$out) { | ||
warning(i, call. = FALSE) | ||
} | ||
} | ||
enable_lockfile_download() | ||
} else { | ||
disable_lockfile_download() | ||
} | ||
} else if (process$status() == "error") { | ||
disable_lockfile_download() | ||
} | ||
}) | ||
|
||
NULL | ||
}) | ||
} | ||
|
||
utils::globalVariables(c("opts", "sysenv", "libpaths", "wd", "lockfilepath", "run")) # needed for mirai call | ||
#' @rdname module_teal_lockfile | ||
.teal_lockfile_process_invoke <- function(lockfile_path) { | ||
mirai_obj <- NULL | ||
process <- shiny::ExtendedTask$new(function() { | ||
m <- mirai::mirai( | ||
{ | ||
options(opts) | ||
do.call(Sys.setenv, sysenv) | ||
.libPaths(libpaths) | ||
setwd(wd) | ||
run(lockfile_path = lockfile_path) | ||
}, | ||
run = .renv_snapshot, | ||
lockfile_path = lockfile_path, | ||
opts = options(), | ||
libpaths = .libPaths(), | ||
sysenv = as.list(Sys.getenv()), | ||
wd = getwd() | ||
) | ||
mirai_obj <<- m | ||
m | ||
}) | ||
|
||
shiny::onStop(function() { | ||
if (mirai::unresolved(mirai_obj)) { | ||
logger::log_debug("Terminating a running lockfile process...") | ||
mirai::stop_mirai(mirai_obj) # this doesn't stop running - renv will be created even if session is closed | ||
} | ||
}) | ||
|
||
suppressWarnings({ # 'package:stats' may not be available when loading | ||
process$invoke() | ||
}) | ||
|
||
logger::log_debug("Lockfile creation started based on { getwd() }.") | ||
|
||
process | ||
} | ||
|
||
#' @rdname module_teal_lockfile | ||
.renv_snapshot <- function(lockfile_path) { | ||
out <- utils::capture.output( | ||
res <- renv::snapshot( | ||
lockfile = lockfile_path, | ||
prompt = FALSE, | ||
force = TRUE, | ||
type = renv::settings$snapshot.type() # see the section "Different ways of creating lockfile" above here | ||
) | ||
) | ||
|
||
list(out = out, res = res) | ||
} | ||
|
||
#' @rdname module_teal_lockfile | ||
.is_lockfile_deps_installed <- function() { | ||
requireNamespace("mirai", quietly = TRUE) && requireNamespace("renv", quietly = TRUE) | ||
} | ||
|
||
#' @rdname module_teal_lockfile | ||
.is_disabled_lockfile_scenario <- function() { | ||
identical(Sys.getenv("CALLR_IS_RUNNING"), "true") || # inside callr process | ||
identical(Sys.getenv("TESTTHAT"), "true") || # inside devtools::test | ||
!identical(Sys.getenv("QUARTO_PROJECT_ROOT"), "") || # inside Quarto process | ||
( | ||
("CheckExEnv" %in% search()) || any(c("_R_CHECK_TIMINGS_", "_R_CHECK_LICENSE_") %in% names(Sys.getenv())) | ||
) # inside R CMD CHECK | ||
} |
Oops, something went wrong.