Skip to content

Commit 71c4110

Browse files
authored
Use evaluate (#344)
Followup to insightsengineering/teal.code#258 - eval_code adds `attr(code, "outputs")` to the `teal_card` but skips the warnings and messages (conditions).
1 parent 0a90326 commit 71c4110

File tree

6 files changed

+71
-72
lines changed

6 files changed

+71
-72
lines changed

R/teal_card.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ c.teal_card <- function(...) {
104104
"Appended `teal_card` doesn't remove some of the elements from previous `teal_card`.\n",
105105
"Restoring original content and adding only new items to the end of the card."
106106
)
107-
modifyList(u, v)
107+
utils::modifyList(u, v)
108108
}
109109
} else {
110110
attrs <- utils::modifyList(attributes(u) %||% list(), attributes(v))

R/teal_report-eval_code.R

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#' @inherit teal.code::eval_code
22
#' @param object (`teal_report`)
3-
#' @param keep_output (`character` or `NULL`) Names of output objects in the environment
4-
#' that are will be added in the card for the reporter.
5-
#' These are shown in the card via the [tools::toHTML()] and [to_rmd()] implementations.
63
#' @param code_block_opts (`list`) Additional options for the R code chunk in R Markdown.
74
#' @return `teal_reporter` environment with the code evaluated and the outputs added
85
#' to the card or `qenv.error` if evaluation fails.
@@ -19,41 +16,32 @@
1916
setMethod(
2017
"eval_code",
2118
signature = c(object = "teal_report"),
22-
function(object, code, keep_output = NULL, code_block_opts = list(), ...) {
19+
function(object, code, code_block_opts = list(), ...) {
2320
new_object <- methods::callNextMethod(object = object, code = code, ...)
2421
if (inherits(new_object, "error")) {
2522
return(new_object)
2623
}
2724

28-
checkmate::assert(
29-
combine = "and",
30-
.var.name = "keep_output",
31-
checkmate::check_character(keep_output, null.ok = TRUE),
32-
checkmate::check_subset(keep_output, ls(new_object, all.names = TRUE), empty.ok = TRUE)
33-
)
34-
new_code <- .preprocess_code(code)
35-
if (length(new_code)) {
36-
teal_card(new_object) <- c(
37-
teal_card(new_object),
38-
do.call(code_chunk, args = c(list(code = new_code), code_block_opts))
39-
)
40-
teal_card(new_object) <- Reduce(
41-
function(result, this) {
42-
this_output <- new_object[[this]]
43-
c(
44-
result,
45-
structure(
46-
this_output,
47-
class = c("chunk_output", class(this_output))
48-
)
25+
new_blocks <- Reduce(
26+
function(items, code_elem) {
27+
this_chunk <- do.call(code_chunk, c(list(code = code_elem), code_block_opts))
28+
this_outs <- Filter( # intentionally remove warnings,messages from the generated report
29+
function(x) !inherits(x, "condition"),
30+
lapply(
31+
attr(code_elem, "outputs"),
32+
function(x) structure(x, class = c("chunk_output", class(x)))
4933
)
50-
},
51-
init = teal_card(new_object),
52-
x = keep_output
53-
)
34+
)
35+
c(items, list(this_chunk), this_outs)
36+
},
37+
init = list(),
38+
x = setdiff(new_object@code, object@code)
39+
)
40+
41+
42+
if (length(new_blocks)) {
43+
teal_card(new_object) <- c(teal_card(new_object), new_blocks)
5444
}
5545
new_object
5646
}
5747
)
58-
59-
.preprocess_code <- getFromNamespace(".preprocess_code", "teal.code")

R/toHTML.R

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,26 +94,34 @@ toHTML.default <- function(x, ...) {
9494
shiny::tags$pre(flextable::htmltools_value(to_flextable(x)))
9595
}
9696

97-
#' @method .toHTML gg
98-
#' @keywords internal
99-
.toHTML.gg <- function(x, ...) {
97+
.plot2html <- function(x, ...) {
10098
on.exit(unlink(tmpfile))
10199
tmpfile <- tempfile(fileext = ".png")
102-
ggplot2::ggsave(tmpfile, plot = x, width = 5, height = 4, dpi = 100)
100+
grDevices::png(filename = tmpfile)
101+
print(x)
102+
grDevices::dev.off()
103103
shiny::tags$img(src = knitr::image_uri(tmpfile))
104104
}
105105

106+
#' @method .toHTML recordedplot
107+
#' @keywords internal
108+
.toHTML.recordedplot <- .plot2html
109+
110+
106111
#' @method .toHTML trellis
107112
#' @keywords internal
108-
.toHTML.trellis <- function(x, ...) {
113+
.toHTML.trellis <- .plot2html
114+
115+
#' @method .toHTML gg
116+
#' @keywords internal
117+
.toHTML.gg <- function(x, ...) {
109118
on.exit(unlink(tmpfile))
110119
tmpfile <- tempfile(fileext = ".png")
111-
grDevices::png(filename = tmpfile)
112-
print(x)
113-
grDevices::dev.off()
120+
ggplot2::ggsave(tmpfile, plot = x, width = 5, height = 4, dpi = 100)
114121
shiny::tags$img(src = knitr::image_uri(tmpfile))
115122
}
116123

124+
117125
#' @method .toHTML grob
118126
#' @keywords internal
119127
.toHTML.grob <- function(x, ...) {

R/to_rmd.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ to_rmd.default <- function(block, output_dir, ...) {
242242
#' @keywords internal
243243
.to_rmd.trellis <- .content_to_rmd
244244

245+
#' @method .to_rmd recordedplot
246+
#' @keywords internal
247+
.to_rmd.recordedplot <- .content_to_rmd
248+
245249
#' @method .to_rmd grob
246250
#' @keywords internal
247251
.to_rmd.grob <- .content_to_rmd

man/eval_code-teal_report-method.Rd

Lines changed: 1 addition & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-teal_report-eval_code.R

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,56 @@
1-
testthat::describe("keep_output stores the objects in teal_card", {
2-
it("using eval_code and explicit reference", {
3-
q <- eval_code(teal_report(), "a <- 1L;b <- 2L;c <- 3L", keep_output = "b")
1+
testthat::describe("eval_code appends code_chunks to the teal_card", {
2+
it("code as code_chunk", {
3+
q <- eval_code(teal_report(), "a <- 1L;b <- 2L;c <- 3L")
44
testthat::expect_equal(
55
teal_card(q),
66
teal_card(
7-
code_chunk("a <- 1L;b <- 2L;c <- 3L"),
8-
structure(2L, class = c("chunk_output", "integer"))
7+
code_chunk("a <- 1L"),
8+
code_chunk("b <- 2L"),
9+
code_chunk("c <- 3L")
910
),
1011
ignore_attr = TRUE
1112
)
1213
})
1314

14-
it("using within and explicit reference", {
15-
q <- within(teal_report(),
16-
{
17-
a <- 1L
18-
b <- 2L
19-
c <- 3L
20-
},
21-
keep_output = "b"
22-
)
15+
it("code as code_chunk and its output as chunk_output", {
16+
q <- eval_code(teal_report(), "a <- 1L;a")
2317
testthat::expect_equal(
2418
teal_card(q),
25-
teal_card(
26-
code_chunk("a <- 1L\nb <- 2L\nc <- 3L"),
27-
structure(2L, class = c("chunk_output", "integer"))
19+
c(
20+
teal_card(),
21+
code_chunk("a <- 1L"),
22+
code_chunk("a"),
23+
structure(1L, class = c("chunk_output", "integer"))
2824
),
2925
ignore_attr = TRUE
3026
)
3127
})
3228

33-
it("with multiple explicit object references", {
34-
q <- eval_code(teal_report(), "a <- 1L;b <- 2L;c <- 3L", keep_output = c("a", "b"))
29+
it("code as code_chunk and condition is excluded from output", {
30+
q <- eval_code(teal_report(), "warning('test')")
3531
testthat::expect_equal(
3632
teal_card(q),
37-
teal_card(
38-
code_chunk("a <- 1L;b <- 2L;c <- 3L"),
39-
structure(1L, class = c("chunk_output", "integer")),
40-
structure(2L, class = c("chunk_output", "integer"))
41-
),
33+
c(teal_card(), code_chunk("warning('test')")),
4234
ignore_attr = TRUE
4335
)
4436
})
37+
})
4538

46-
it("without explicit reference returing none", {
47-
q <- eval_code(teal_report(), "a <- 1L;b <- 2L;c <- 3L", keep_output = character(0L))
39+
testthat::describe("within appends to teal_card", {
40+
it("code as code_chunk", {
41+
q <- within(teal_report(), {
42+
a <- 1L
43+
b <- 2L
44+
c <- 3L
45+
})
4846
testthat::expect_equal(
4947
teal_card(q),
50-
teal_card(code_chunk("a <- 1L;b <- 2L;c <- 3L")),
48+
c(
49+
teal_card(),
50+
code_chunk("a <- 1L"),
51+
code_chunk("b <- 2L"),
52+
code_chunk("c <- 3L")
53+
),
5154
ignore_attr = TRUE
5255
)
5356
})

0 commit comments

Comments
 (0)