From cd18da9d7c29cec40c9b70a3534f930992be8c8e Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 9 May 2023 22:41:23 +0200 Subject: [PATCH 01/13] Make `quarto_render()` wrapable --- R/render.R | 12 +++++++++++- tests/testthat/test-render.R | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/R/render.R b/R/render.R index abf6c84e..6c75ec34 100644 --- a/R/render.R +++ b/R/render.R @@ -86,8 +86,18 @@ quarto_render <- function(input = NULL, if (as_job && rstudioapi::isAvailable()) { message("Rendering project as background job (use as_job = FALSE to override)") script <- tempfile(fileext = ".R") + render_args <- rlang::call_args(sys.call()) + render_args <- mapply( + function(arg, arg_name) paste0( + arg_name, + "="[nchar(arg_name) > 0L], + deparse1(eval(arg, envir = parent.frame(n = 3L))) + ), + render_args, + names(render_args) + ) writeLines( - c("library(quarto)", deparse(sys.call())), + paste0("quarto::quarto_render(", paste0(render_args, collapse = ", "),")"), script ) rstudioapi::jobRunScript( diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 45a835a9..b3161c16 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -11,3 +11,18 @@ test_that("R Markdown documents can be rendered", { expect_true(file.exists("test.html")) unlink("test-render.html") }) + + +test_that("`quarto_render()` is wrapable", { + skip_if(is.null(quarto_path())) + skip_if_not_installed("rstudioapi") + skip_if_not_installed("rprojroot") + skip_if(!rstudioapi::isAvailable()) + dir <- rprojroot::find_testthat_root_file() + input <- file.path(dir, "test.Rmd") + output <- file.path(dir, "test.html") + wrapper <- function(path) quarto_render(path, quiet = TRUE) + wrapper(input) + expect_true(file.exists(output)) + unlink(output) +}) From 332dd4a298e0697b72cce981f4597af1a0309b93 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 9 May 2023 22:41:45 +0200 Subject: [PATCH 02/13] Cosmetic fixes --- R/publish.R | 2 +- R/render.R | 3 +-- tests/testthat/test-render.R | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/R/publish.R b/R/publish.R index 00f90e88..d19c703f 100644 --- a/R/publish.R +++ b/R/publish.R @@ -269,7 +269,7 @@ find_app_primary_doc <- function(dir) { break } } - return (primary_doc) + return(primary_doc) } } return(NULL) diff --git a/R/render.R b/R/render.R index 6c75ec34..1709af57 100644 --- a/R/render.R +++ b/R/render.R @@ -106,10 +106,9 @@ quarto_render <- function(input = NULL, workingDir = getwd(), importEnv = TRUE ) - return (invisible(NULL)) + return(invisible(NULL)) } - # build args args <- c("render", input) if (!missing(output_format)) { diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index b3161c16..4f839b59 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -1,4 +1,3 @@ - test_that("An error is reported when Quarto is not installed", { skip_if(!is.null(quarto_path())) expect_error(quarto_render("test.Rmd")) From 50bf4f2dd5ac222e325cc5d3cfefb6eb2e898efa Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 9 May 2023 23:16:33 +0200 Subject: [PATCH 03/13] Avoid rlang --- R/render.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/render.R b/R/render.R index 1709af57..37587907 100644 --- a/R/render.R +++ b/R/render.R @@ -86,7 +86,7 @@ quarto_render <- function(input = NULL, if (as_job && rstudioapi::isAvailable()) { message("Rendering project as background job (use as_job = FALSE to override)") script <- tempfile(fileext = ".R") - render_args <- rlang::call_args(sys.call()) + render_args <- as.list(sys.call()[-1L]) render_args <- mapply( function(arg, arg_name) paste0( arg_name, From 878873eb39277515437b3316469d66623a758ef0 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 9 May 2023 23:16:45 +0200 Subject: [PATCH 04/13] Fix test --- tests/testthat/test-render.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 4f839b59..62909d17 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -12,7 +12,7 @@ test_that("R Markdown documents can be rendered", { }) -test_that("`quarto_render()` is wrapable", { +test_that("`quarto_render(as_job = TRUE)` is wrapable", { skip_if(is.null(quarto_path())) skip_if_not_installed("rstudioapi") skip_if_not_installed("rprojroot") @@ -20,7 +20,9 @@ test_that("`quarto_render()` is wrapable", { dir <- rprojroot::find_testthat_root_file() input <- file.path(dir, "test.Rmd") output <- file.path(dir, "test.html") - wrapper <- function(path) quarto_render(path, quiet = TRUE) + wrapper <- function(path) quarto_render(path, quiet = TRUE, as_job = TRUE) + # wait for background job to finish (10s should be conservative enough) + Sys.sleep(10) wrapper(input) expect_true(file.exists(output)) unlink(output) From 037a92ac63ea8e25c121a4462200b1c66017cb6d Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 9 May 2023 23:21:35 +0200 Subject: [PATCH 05/13] Fix order in test --- tests/testthat/test-render.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 62909d17..68aed5fe 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -21,9 +21,9 @@ test_that("`quarto_render(as_job = TRUE)` is wrapable", { input <- file.path(dir, "test.Rmd") output <- file.path(dir, "test.html") wrapper <- function(path) quarto_render(path, quiet = TRUE, as_job = TRUE) + wrapper(input) # wait for background job to finish (10s should be conservative enough) Sys.sleep(10) - wrapper(input) expect_true(file.exists(output)) unlink(output) }) From f4568c3695f7a7110a42208eba259d184487ea9e Mon Sep 17 00:00:00 2001 From: Salim B Date: Fri, 26 May 2023 21:59:04 +0200 Subject: [PATCH 06/13] Tweak test --- tests/testthat/test-render.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 68aed5fe..60ae3ae9 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -16,7 +16,7 @@ test_that("`quarto_render(as_job = TRUE)` is wrapable", { skip_if(is.null(quarto_path())) skip_if_not_installed("rstudioapi") skip_if_not_installed("rprojroot") - skip_if(!rstudioapi::isAvailable()) + skip_if_not(rstudioapi::isAvailable()) dir <- rprojroot::find_testthat_root_file() input <- file.path(dir, "test.Rmd") output <- file.path(dir, "test.html") From 0665e5a37343320276233cf432f0b2f21bd2ca1a Mon Sep 17 00:00:00 2001 From: Salim B Date: Fri, 26 May 2023 21:59:17 +0200 Subject: [PATCH 07/13] Cosmetic fix --- R/render.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/render.R b/R/render.R index 37587907..7aed8b1f 100644 --- a/R/render.R +++ b/R/render.R @@ -97,7 +97,7 @@ quarto_render <- function(input = NULL, names(render_args) ) writeLines( - paste0("quarto::quarto_render(", paste0(render_args, collapse = ", "),")"), + paste0("quarto::quarto_render(", paste0(render_args, collapse = ", "), ")"), script ) rstudioapi::jobRunScript( From 1438bd0aa56b69316ccb1aa8f983aa84fbceb4fb Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 13 Oct 2023 16:18:11 +0200 Subject: [PATCH 08/13] Use temp file infrastructure for tests --- tests/testthat/test-render.R | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index f6e67952..5471eb41 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -46,19 +46,21 @@ test_that("metadata-file and metadata are merged in quarto_render", { ) }) - test_that("`quarto_render(as_job = TRUE)` is wrapable", { - skip_if(is.null(quarto_path())) + skip_on_cran() # this is to test inside RStudio IDE interactively + skip_if_no_quarto() skip_if_not_installed("rstudioapi") - skip_if_not_installed("rprojroot") skip_if_not(rstudioapi::isAvailable()) - dir <- rprojroot::find_testthat_root_file() - input <- file.path(dir, "test.Rmd") - output <- file.path(dir, "test.html") - wrapper <- function(path) quarto_render(path, quiet = TRUE, as_job = TRUE) - wrapper(input) + qmd <- local_qmd_file(c("content")) + withr::local_dir(dirname(qmd)) + output <- basename( + withr::local_file(xfun::with_ext(qmd, ".native")) + ) + wrapper <- function(path, out, format) { + quarto_render(path, output_file = out, output_format = format, quiet = TRUE, as_job = TRUE) + } + wrapper(basename(qmd), output, "native") # wait for background job to finish (10s should be conservative enough) Sys.sleep(10) expect_true(file.exists(output)) - unlink(output) }) From 7885339e861f293ff94576e1740ae7c5538c1f94 Mon Sep 17 00:00:00 2001 From: Salim B Date: Thu, 7 Mar 2024 14:43:17 +0100 Subject: [PATCH 09/13] Tweak test --- tests/testthat/test-render.R | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index f443c268..21b823f8 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -61,16 +61,26 @@ test_that("quarto_args in quarto_render", { }) test_that("`quarto_render(as_job = TRUE)` is wrapable", { - skip_if(is.null(quarto_path())) + # this tests background jobs, a feature only available in interactive RStudio IDE sesssions + skip_on_cran() + skip_if_no_quarto() skip_if_not(rstudioapi::isAvailable()) - skip_if_not_installed("rprojroot") - dir <- rprojroot::find_testthat_root_file() - input <- file.path(dir, "test.Rmd") - output <- file.path(dir, "test.html") - wrapper <- function(path) quarto_render(path, quiet = TRUE, as_job = TRUE) - wrapper(input) + qmd <- local_qmd_file(c("content")) + withr::local_dir(dirname(qmd)) + output <- basename( + withr::local_file(xfun::with_ext(qmd, ".native")) + ) + wrapper <- function(path, out, format) { + quarto_render( + input = path, + output_file = out, + output_format = format, + quiet = TRUE, + as_job = TRUE + ) + } + wrapper(basename(qmd), output, "native") # wait for background job to finish (10s should be conservative enough) Sys.sleep(10) expect_true(file.exists(output)) - unlink(output) }) From 8056d93189170fb5ea5d578594394be1c09e0794 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 10 Jun 2025 14:05:37 +0200 Subject: [PATCH 10/13] correctly skip test fixup correct function name --- tests/testthat/test-render.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 920af5b5..1bb1cc71 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -70,7 +70,12 @@ test_that("`quarto_render(as_job = TRUE)` is wrapable", { # this tests background jobs, a feature only available in interactive RStudio IDE sesssions skip_on_cran() skip_if_no_quarto() - skip_if_not(rstudioapi::isAvailable()) + skip_if_not( + rstudioapi::isAvailable() && + rstudioapi::hasFun("runScriptJob") && + in_rstudio(), + message = "quarto_render(as_job = TRUE) is only available in RStudio IDE sessions with job support." + ) qmd <- local_qmd_file(c("content")) withr::local_dir(dirname(qmd)) output <- basename( From c9a0fd67d42be8e0f322a8b29f5f465fa940f8d9 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 10 Jun 2025 14:07:55 +0200 Subject: [PATCH 11/13] Add note to test --- tests/testthat/test-render.R | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 1bb1cc71..755ec440 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -68,6 +68,7 @@ test_that("quarto_args in quarto_render", { test_that("`quarto_render(as_job = TRUE)` is wrapable", { # this tests background jobs, a feature only available in interactive RStudio IDE sesssions + # This is here for manual testing. This test should not run otherwise. skip_on_cran() skip_if_no_quarto() skip_if_not( From 3c17e0e8cccd2456b1ed2c0fe63d86bda7ce5d5b Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 10 Jun 2025 14:21:44 +0200 Subject: [PATCH 12/13] add test for message checking we are in job part --- tests/testthat/test-render.R | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index 755ec440..745ff81d 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -91,7 +91,10 @@ test_that("`quarto_render(as_job = TRUE)` is wrapable", { as_job = TRUE ) } - wrapper(basename(qmd), output, "native") + expect_message( + wrapper(basename(qmd), output, "native"), + "Rendering project as background job" + ) # wait for background job to finish (10s should be conservative enough) Sys.sleep(10) expect_true(file.exists(output)) From d93854b1ea153470713a4c1da7b90d8538f9d86a Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 10 Jun 2025 14:21:56 +0200 Subject: [PATCH 13/13] bump version --- DESCRIPTION | 2 +- NEWS.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index ec70d591..697890c0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: quarto Title: R Interface to 'Quarto' Markdown Publishing System -Version: 1.4.4.9011 +Version: 1.4.4.9012 Authors@R: c( person("JJ", "Allaire", , "jj@posit.co", role = "aut", comment = c(ORCID = "0000-0003-0174-9868")), diff --git a/NEWS.md b/NEWS.md index 57661bb4..8fbf4c80 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # quarto (development version) +- Make `quarto_render(as_job = TRUE)` wrapable (thanks, @salim-b, #105). + - Quarto CLI will now correctly use the same R version than the one used to run functions in this package (#204). - Add `quarto_available()` function to check if Quarto CLI is found (thanks, @hadley, #187).