diff -Nru r-cran-evaluate-0.14/debian/changelog r-cran-evaluate-0.15/debian/changelog --- r-cran-evaluate-0.14/debian/changelog 2020-05-30 09:55:56.000000000 +0000 +++ r-cran-evaluate-0.15/debian/changelog 2022-02-23 21:31:33.000000000 +0000 @@ -1,8 +1,10 @@ -r-cran-evaluate (0.14-2build1) groovy; urgency=medium +r-cran-evaluate (0.15-1) unstable; urgency=medium - * No-change rebuild against r-api-4.0 + * Team Upload. + * New upstream version 0.15 + * Bump Standards-Version to 4.6.0 (no changes needed) - -- Graham Inggs Sat, 30 May 2020 09:55:56 +0000 + -- Nilesh Patra Thu, 24 Feb 2022 03:01:33 +0530 r-cran-evaluate (0.14-2) unstable; urgency=medium diff -Nru r-cran-evaluate-0.14/debian/control r-cran-evaluate-0.15/debian/control --- r-cran-evaluate-0.14/debian/control 2020-05-15 19:34:40.000000000 +0000 +++ r-cran-evaluate-0.15/debian/control 2022-02-23 21:31:28.000000000 +0000 @@ -6,7 +6,7 @@ Build-Depends: debhelper-compat (= 12), dh-r, r-base-dev -Standards-Version: 4.5.0 +Standards-Version: 4.6.0 Vcs-Browser: https://salsa.debian.org/r-pkg-team/r-cran-evaluate Vcs-Git: https://salsa.debian.org/r-pkg-team/r-cran-evaluate.git Homepage: https://cran.r-project.org/package=evaluate diff -Nru r-cran-evaluate-0.14/DESCRIPTION r-cran-evaluate-0.15/DESCRIPTION --- r-cran-evaluate-0.14/DESCRIPTION 2019-05-28 15:50:02.000000000 +0000 +++ r-cran-evaluate-0.15/DESCRIPTION 2022-02-18 17:20:02.000000000 +0000 @@ -2,7 +2,7 @@ Type: Package Title: Parsing and Evaluation Tools that Provide More Details than the Default -Version: 0.14 +Version: 0.15 Authors@R: c( person("Hadley", "Wickham", role = "aut"), person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")), @@ -22,11 +22,11 @@ BugReports: https://github.com/r-lib/evaluate/issues Depends: R (>= 3.0.2) Imports: methods -Suggests: testthat, lattice, ggplot2 -RoxygenNote: 6.1.1 +Suggests: covr, ggplot2, lattice, testthat +RoxygenNote: 7.1.1 Encoding: UTF-8 NeedsCompilation: no -Packaged: 2019-05-28 15:30:02 UTC; yihui +Packaged: 2022-02-18 16:51:14 UTC; yihui Author: Hadley Wickham [aut], Yihui Xie [aut, cre] (), Michael Lawrence [ctb], @@ -39,4 +39,4 @@ Karolis Koncevičius [ctb] Maintainer: Yihui Xie Repository: CRAN -Date/Publication: 2019-05-28 15:50:02 UTC +Date/Publication: 2022-02-18 17:20:02 UTC diff -Nru r-cran-evaluate-0.14/man/create_traceback.Rd r-cran-evaluate-0.15/man/create_traceback.Rd --- r-cran-evaluate-0.14/man/create_traceback.Rd 2019-05-28 15:30:01.000000000 +0000 +++ r-cran-evaluate-0.15/man/create_traceback.Rd 2020-10-28 22:31:49.000000000 +0000 @@ -8,7 +8,7 @@ } \arguments{ \item{callstack}{stack of calls, as generated by (e.g.) -\code{\link[base:sys.calls]{base::sys.calls()}}} +\code{\link[base:sys.parent]{base::sys.calls()}}} } \description{ Generate a traceback from a list of calls. diff -Nru r-cran-evaluate-0.14/man/evaluate.Rd r-cran-evaluate-0.15/man/evaluate.Rd --- r-cran-evaluate-0.14/man/evaluate.Rd 2019-05-28 15:30:01.000000000 +0000 +++ r-cran-evaluate-0.15/man/evaluate.Rd 2020-10-28 22:31:49.000000000 +0000 @@ -4,9 +4,19 @@ \alias{evaluate} \title{Evaluate input and return all details of evaluation.} \usage{ -evaluate(input, envir = parent.frame(), enclos = NULL, debug = FALSE, - stop_on_error = 0L, keep_warning = TRUE, keep_message = TRUE, new_device = TRUE, - output_handler = default_output_handler, filename = NULL, include_timing = FALSE) +evaluate( + input, + envir = parent.frame(), + enclos = NULL, + debug = FALSE, + stop_on_error = 0L, + keep_warning = TRUE, + keep_message = TRUE, + new_device = TRUE, + output_handler = default_output_handler, + filename = NULL, + include_timing = FALSE +) } \arguments{ \item{input}{input object to be parsed and evaluated. May be a string, file diff -Nru r-cran-evaluate-0.14/man/inject_funs.Rd r-cran-evaluate-0.15/man/inject_funs.Rd --- r-cran-evaluate-0.14/man/inject_funs.Rd 2019-05-28 15:30:01.000000000 +0000 +++ r-cran-evaluate-0.15/man/inject_funs.Rd 2020-10-28 22:31:49.000000000 +0000 @@ -26,7 +26,7 @@ evaluate("system('R --version')") # replace the system() function -inject_funs(system = function(...) cat(base::system(..., intern = TRUE), sep = "\\n")) +inject_funs(system = function(...) cat(base::system(..., intern = TRUE), sep = "\n")) evaluate("system('R --version')") diff -Nru r-cran-evaluate-0.14/man/new_output_handler.Rd r-cran-evaluate-0.15/man/new_output_handler.Rd --- r-cran-evaluate-0.14/man/new_output_handler.Rd 2019-05-28 15:30:01.000000000 +0000 +++ r-cran-evaluate-0.15/man/new_output_handler.Rd 2022-02-18 05:07:51.000000000 +0000 @@ -5,8 +5,16 @@ \alias{output_handler} \title{Custom output handlers.} \usage{ -new_output_handler(source = identity, text = identity, graphics = identity, - message = identity, warning = identity, error = identity, value = render) +new_output_handler( + source = identity, + text = identity, + graphics = identity, + message = identity, + warning = identity, + error = identity, + value = render, + calling_handlers = list() +) } \arguments{ \item{source}{Function to handle the echoed source code under evaluation.} @@ -25,6 +33,10 @@ \item{value}{Function to handle the values returned from evaluation. If it only has one argument, only visible values are handled; if it has more arguments, the second argument indicates whether the value is visible.} + +\item{calling_handlers}{List of \link[=withCallingHandlers]{calling handlers}. +These handlers have precedence over the exiting handler installed +by \code{\link[=evaluate]{evaluate()}} when \code{stop_on_error} is set to 0.} } \value{ A new \code{output_handler} object diff -Nru r-cran-evaluate-0.14/MD5 r-cran-evaluate-0.15/MD5 --- r-cran-evaluate-0.14/MD5 2019-05-28 15:50:02.000000000 +0000 +++ r-cran-evaluate-0.15/MD5 2022-02-18 17:20:02.000000000 +0000 @@ -1,23 +1,23 @@ -ef31ab942273ee1a28459533767af3c6 *DESCRIPTION +a675c5a12575f58122afe175aa89daae *DESCRIPTION 4d85b280c584cd25a3295bc0fa7c49ce *LICENSE 437c0030837a125263825c691c0b90c7 *NAMESPACE -232478604fa704826fe8fda23adf74c9 *NEWS.md -c4b39f17eb9384b669a35136a3122d31 *R/eval.r -aafc2bed34385af43269af8e64f1e01e *R/graphics.r +b5bc71e80f17daffbcfe30a794e9be5d *NEWS.md +119d8afad32c5c91d91915ab767e6be6 *R/eval.r +a9d2e190e4ee3aaafc8e9e50f2b1a902 *R/graphics.r 4d6bfdb8870799394ccb6affc752f706 *R/hooks.r -434d218bc077ac10d65b3a011c564bb8 *R/output.r +e49ee24616ae8edcc2ca837553a76377 *R/output.r 4bc8214c0a1411ace37a2f36e9254e84 *R/parse.r 32eedee1c5ff92e7413a15b0f2bb5aff *R/replay.r 621066d5bd50b2af562db7ef5a6e58ce *R/traceback.r 596eff492e48e7f1eea0069751faa9b9 *R/watcher.r 3ec4352139763b1d987c384e5d2c54f3 *README.md -b6e6ee1f28ceac82a8557de5e7d9f80a *man/create_traceback.Rd -dd973be5e436f9fa50d708e7fc3cbead *man/evaluate.Rd +5e1bff56f053bcaabd64fb256f3998a1 *man/create_traceback.Rd +5ff9f354e8a6b788ef62f6cd0a49e9c8 *man/evaluate.Rd dcfdd8b3176035bca65f547574b18580 *man/flush_console.Rd -f0f10e028751e4d38a606050f1cca096 *man/inject_funs.Rd +f6b1577b5e154bf7145a63645099d7f2 *man/inject_funs.Rd 7bbb8ef6f236c5876ab4e4898e12efbd *man/is.message.Rd 9346c6d63cef05f64a62f61926b3123b *man/line_prompt.Rd -ed4f1e2bfc9a1d602485d785c4d86eba *man/new_output_handler.Rd +37234349b2f3b05198f9023da16e0086 *man/new_output_handler.Rd 212320089073cddb8a48e2b1ffd89c16 *man/parse_all.Rd e040e2e1d5bd114092351e827e42a68e *man/remove_hooks.Rd 4f7ec39a51becb946cc662dd7bff30ae *man/replay.Rd @@ -54,7 +54,7 @@ 4cbfd1ffe04ab0562a2514f22a2e049d *tests/testthat/plot.r 7df061829daeba528956cfd392bac1e7 *tests/testthat/raw-output.r 369084284055bfce832dc131c710e62b *tests/testthat/test-errors.r -be4eccb8aa6b6d3c810b94dc7095a8f5 *tests/testthat/test-evaluate.r +aff54fea8eac0750dc2171873a19bb85 *tests/testthat/test-evaluate.r 41bdf3d19acebc48429ac8120a79c757 *tests/testthat/test-graphics.r f558fc2fc0f097cdf455ad5cc1467240 *tests/testthat/test-output-handler.R f0dfe4d4709355498c1d03d06a149a7a *tests/testthat/test-output.r diff -Nru r-cran-evaluate-0.14/NEWS.md r-cran-evaluate-0.15/NEWS.md --- r-cran-evaluate-0.14/NEWS.md 2019-03-19 21:30:26.000000000 +0000 +++ r-cran-evaluate-0.15/NEWS.md 2022-02-18 05:08:51.000000000 +0000 @@ -1,3 +1,10 @@ +Version 0.15 +================================================================================ + +- `new_output_handler()` gains a `calling_handlers` argument. These are passed to `withCallingHandlers()` before `evaluate()` captures any conditions. + +- Fixed #106: do not assume that `is.atomic(NULL)` returns `TRUE` (thanks, @mmaechler). + Version 0.14 ================================================================================ diff -Nru r-cran-evaluate-0.14/R/eval.r r-cran-evaluate-0.15/R/eval.r --- r-cran-evaluate-0.14/R/eval.r 2019-03-19 21:13:56.000000000 +0000 +++ r-cran-evaluate-0.15/R/eval.r 2022-02-18 05:07:51.000000000 +0000 @@ -101,7 +101,7 @@ output_handler$source(source) return(list(source)) } - stopifnot(is.call(call) || is.language(call) || is.atomic(call)) + stopifnot(is.call(call) || is.language(call) || is.atomic(call) || is.null(call)) # Capture output w <- watchout(debug) @@ -190,12 +190,19 @@ for (i in seq_along(funs_names)) assign(funs_names[i], funs[[i]], envir) } + user_handlers <- output_handler$calling_handlers + multi_args <- length(formals(value_handler)) > 1 for (expr in call) { srcindex <- length(output) - time <- timing_fn(handle(ev <- withCallingHandlers( - withVisible(eval(expr, envir, enclos)), - warning = wHandler, error = eHandler, message = mHandler))) + time <- timing_fn(handle( + ev <- withCallingHandlers( + withVisible(eval_with_user_handlers(expr, envir, enclos, user_handlers)), + warning = wHandler, + error = eHandler, + message = mHandler + ) + )) handle_output(TRUE) if (!is.null(time)) attr(output[[srcindex]]$src, 'timing') <- time @@ -222,6 +229,24 @@ output } +eval_with_user_handlers <- function(expr, envir, enclos, calling_handlers) { + if (!length(calling_handlers)) { + return(eval(expr, envir, enclos)) + } + + if (!is.list(calling_handlers)) { + stop("`calling_handlers` must be a list", call. = FALSE) + } + + call <- as.call(c( + quote(withCallingHandlers), + quote(eval(expr, envir, enclos)), + calling_handlers + )) + + eval(call) +} + #' Inject functions into the environment of `evaluate()` #' #' Create functions in the environment specified in the `envir` argument of diff -Nru r-cran-evaluate-0.14/R/graphics.r r-cran-evaluate-0.15/R/graphics.r --- r-cran-evaluate-0.14/R/graphics.r 2016-11-29 18:00:13.000000000 +0000 +++ r-cran-evaluate-0.15/R/graphics.r 2020-06-23 21:58:47.000000000 +0000 @@ -5,7 +5,7 @@ #" This means that only the last plot of a series will be captured. #" #" @return \code{NULL} if plot is blank or unchanged, otherwise the output of -#" \code{\link[grDevices]{recordPlot}}. +#" \code{\link{recordPlot}}. plot_snapshot <- local({ last_plot <- NULL diff -Nru r-cran-evaluate-0.14/R/output.r r-cran-evaluate-0.15/R/output.r --- r-cran-evaluate-0.14/R/output.r 2019-02-11 04:09:32.000000000 +0000 +++ r-cran-evaluate-0.15/R/output.r 2022-02-18 05:07:51.000000000 +0000 @@ -54,13 +54,17 @@ #' @param value Function to handle the values returned from evaluation. If it #' only has one argument, only visible values are handled; if it has more #' arguments, the second argument indicates whether the value is visible. +#' @param calling_handlers List of [calling handlers][withCallingHandlers]. +#' These handlers have precedence over the exiting handler installed +#' by [evaluate()] when `stop_on_error` is set to 0. #' @return A new `output_handler` object #' @aliases output_handler #' @export new_output_handler <- function(source = identity, text = identity, graphics = identity, message = identity, warning = identity, - error = identity, value = render) { + error = identity, value = render, + calling_handlers = list()) { source <- match.fun(source) stopifnot(length(formals(source)) >= 1) text <- match.fun(text) @@ -76,10 +80,39 @@ value <- match.fun(value) stopifnot(length(formals(value)) >= 1) + check_handlers(calling_handlers) + structure(list(source = source, text = text, graphics = graphics, message = message, warning = warning, error = error, - value = value), + value = value, calling_handlers = calling_handlers), class = "output_handler") } +check_handlers <- function(x) { + if (!is.list(x)) { + stop_bad_handlers() + } + + if (!length(x)) { + return() + } + + names <- names(x) + if (!is.character(names) || anyNA(names) || any(names == "")) { + stop_bad_handlers() + } + + for (elt in x) { + if (!is.function(elt)) { + stop_bad_handlers() + } + } +} +stop_bad_handlers <- function() { + stop(simpleError( + "`calling_handlers` must be a named list of functions.", + call = call("new_output_handler") + )) +} + default_output_handler <- new_output_handler() diff -Nru r-cran-evaluate-0.14/tests/testthat/test-evaluate.r r-cran-evaluate-0.15/tests/testthat/test-evaluate.r --- r-cran-evaluate-0.14/tests/testthat/test-evaluate.r 2018-07-17 19:22:23.000000000 +0000 +++ r-cran-evaluate-0.15/tests/testthat/test-evaluate.r 2022-02-18 05:07:51.000000000 +0000 @@ -96,3 +96,39 @@ ev <- evaluate("# foo\n#bar") expect_equal(ev[[1]][["src"]], "# foo\n") }) + +test_that("user can register calling handlers", { + cnd <- structure(list(), class = c("foobar", "condition")) + hnd <- function(cnd) handled <<- cnd + + handled <- NULL + hnd <- function(cnd) handled <<- cnd + + out_hnd <- new_output_handler(calling_handlers = list(foobar = hnd)) + evaluate("signalCondition(cnd)", output_handler = out_hnd) + expect_s3_class(handled, "foobar") + + handled <- NULL + out_hnd <- new_output_handler(calling_handlers = list(error = hnd)) + evaluate("stop('tilt')", stop_on_error = 0, output_handler = out_hnd) + expect_s3_class(handled, "error") +}) + +test_that("calling handlers are checked", { + expect_error( + new_output_handler(calling_handlers = list(condition = 1)), + "must be" + ) + expect_error( + new_output_handler(calling_handlers = list(function(...) NULL)), + "must be" + ) + expect_error( + new_output_handler(calling_handlers = stats::setNames(list(function(...) NULL), NA)), + "must be" + ) + expect_error( + new_output_handler(calling_handlers = stats::setNames(list(function(...) NULL), "")), + "must be" + ) +})