Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

59 error handling simpler #65

Merged
merged 22 commits into from
Sep 15, 2022
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by roxygen2: do not edit by hand

S3method("[[",quosure.error)
export(chunk)
export(chunk_call)
export(chunk_comment)
Expand Down Expand Up @@ -42,7 +43,9 @@ exportMethods(get_code)
exportMethods(get_var)
exportMethods(join)
exportMethods(new_quosure)
exportMethods(show)
import(shiny)
importFrom(R6,R6Class)
importFrom(lifecycle,badge)
importFrom(methods,show)
importFrom(styler,style_text)
4 changes: 2 additions & 2 deletions R/get_eval_details.R
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ get_eval_details_srv <- function(id, chunks) {
span()
),
`if`(
eval_info_summary["errors"] > 0,
get_number_in_box(eval_info_summary["errors"], box_color = "#ff0000", char_color = "#ffffff"),
eval_info_summary["quosure.error"] > 0,
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
get_number_in_box(eval_info_summary["quosure.error"], box_color = "#ff0000", char_color = "#ffffff"),
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
span()
)
)
Expand Down
3 changes: 2 additions & 1 deletion R/quosure-class.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ setClass(
)

#' It takes a `Quosure` class and returns TRUE if the input is valid
#' @name Quosure-class
#' @keywords internal
setValidity("Quosure", function(object) {
if (length(object@code) != length(object@id)) {
Expand All @@ -25,4 +26,4 @@ setValidity("Quosure", function(object) {
} else {
TRUE
}
})
})
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 2 additions & 0 deletions R/quosure-errors.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# needed to handle try-e
setOldClass("quosure.error")
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
74 changes: 41 additions & 33 deletions R/quosure-eval_code.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,55 @@ setGeneric("eval_code", function(object, code, name = "code") {

#' @rdname eval_code
#' @export
setMethod(
"eval_code",
signature = c("Quosure", "character"),
function(object, code, name) {
checkmate::assert_string(name)
if (is.null(names(code))) {
code <- paste(code, collapse = "\n")
names(code) <- name
}
id <- sample.int(.Machine$integer.max, size = length(code))
object@id <- c(object@id, id)
object@code <- .keep_code_name_unique(object@code, code)
setMethod("eval_code", signature = c("Quosure", "character"), function(object, code, name) {
checkmate::assert_string(name)
if (is.null(names(code))) {
code <- paste(code, collapse = "\n")
names(code) <- name
}
id <- sample.int(.Machine$integer.max, size = length(code))

evaluated_code <- object@code
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved

object@id <- c(object@id, id)
object@code <- .keep_code_name_unique(object@code, code)

# need to copy the objects from old env to new env
# to avoid updating environments in the separate objects
object@env <- .copy_env(object@env)
# need to copy the objects from old env to new env
# to avoid updating environments in the separate objects
object@env <- .copy_env(object@env)
tryCatch({
eval(parse(text = code), envir = object@env)
lockEnvironment(object@env)
object
}
)
},
error = function(e) {
errorCondition(
message = sprintf(
"%s \n when evaluating a Quosure code:\n %s",
conditionMessage(e),
paste(code, collapse = "\n ")
),
class = c("quosure.error", "try-error", "simpleError")
)
})
})

#' @rdname eval_code
#' @export
setMethod(
"eval_code",
signature = c("Quosure", "expression"),
function(object, code, name) {
code_char <- as.character(code)
eval_code(object, code_char, name = name)
}
)
setMethod("eval_code", signature = c("Quosure", "expression"), function(object, code, name) {
code_char <- as.character(code)
eval_code(object, code_char, name = name)
})

#' @rdname eval_code
#' @export
setMethod(
"eval_code",
signature = c("Quosure", "language"),
function(object, code, name) {
code_char <- as.expression(code)
eval_code(object, code_char, name = name)
}
)
setMethod("eval_code", signature = c("Quosure", "language"), function(object, code, name) {
code_char <- as.expression(code)
eval_code(object, code_char, name = name)
})

#' @rdname eval_code
#' @export
setMethod("eval_code", signature = "quosure.error", function(object, code, name) {
object
})
7 changes: 7 additions & 0 deletions R/quosure-get_code.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#'
#' @export
setGeneric("get_code", function(object) {
object
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
standardGeneric("get_code")
})

Expand All @@ -20,3 +21,9 @@ setGeneric("get_code", function(object) {
setMethod("get_code", signature = "Quosure", function(object) {
object@code
})

#' @rdname get_code
#' @export
setMethod("get_code", signature = "quosure.error", function(object) {
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
object
})
15 changes: 14 additions & 1 deletion R/quosure-get_var.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,25 @@ setMethod("get_var", signature = c("Quosure", "character"), function(object, var
get(var, envir = object@env)
})

#' @rdname get_var
#' @export
setMethod("get_var", signature = "quosure.error", function(object, var) {
object
})


#' @param x (`Quosure`)
#' @param i (`character`) name of the binding in environment (name of the variable)
#' @param j not used
#' @param ... not used
#' @rdname get_var
#' @export
setMethod("[[", c("Quosure", "ANY", "missing"), function(x, i, j, ...) {
setMethod("[[", signature = c("Quosure", "ANY", "missing"), function(x, i, j, ...) {
get_var(x, i)
})

#' @rdname get_var
#' @export
`[[.quosure.error` <- function(x, i, j, ...) {
x
}
12 changes: 12 additions & 0 deletions R/quosure-join.R
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ setMethod("join", signature = c("Quosure", "Quosure"), function(x, y) {
x
})

#' @rdname join
#' @export
setMethod("join", signature = "quosure.error", function(x, y) {
x
})

#' @rdname join
#' @export
setMethod("join", signature = c("Quosure", "quosure.error"), function(x, y) {
y
})

#' If two `Quosure` can be joined
#'
#' Checks if two `Quosure` objects can be combined.
Expand Down
20 changes: 20 additions & 0 deletions R/quosure-show.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#' Show the `Quosure` object
#'
#' Prints the `Quosure` object
#' @param object (`Quosure`)
#' @return nothing
#' @importFrom methods show
#' @examples
#' q1 <- new_quosure(code = "print('a')", env = new.env())
#' q1
#' @export
setMethod("show", "Quosure", function(object) {
obs <- names(as.list(object@env))
if (length(obs) > 0) {
cat(paste("A quosure object containing:", paste(obs, collapse = ", ")))
} else {
cat("A quosure object containing no objects")
}
})


1 change: 1 addition & 0 deletions R/quosure-utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
}
stats::setNames(combined, make.unique(names(combined)))
}

3 changes: 3 additions & 0 deletions man/eval_code.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions man/get_code.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions man/get_var.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions man/join.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions man/show-Quosure-method.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions tests/testthat/test-eval_code.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ testthat::test_that("eval_code doesn't have access to environment where it's cal
a <- 1L
q1 <- new_quosure("a <- 1", env = environment())
b <- 2L
testthat::expect_error(eval_code(q1, "d <- b"), "object 'b' not found")
testthat::expect_s3_class(eval_code(q1, "d <- b"), c("quosure.error", "try-error", "error", "condition"))
})

testthat::test_that("@env in quosure is always a sibling of .GlobalEnv", {
Expand All @@ -30,15 +30,15 @@ testthat::test_that("library have to be called separately before using function
testthat::expect_identical(parent.env(q2@env), parent.env(.GlobalEnv))

detach("package:checkmate", unload = TRUE)
testthat::expect_error(
testthat::expect_s3_class(
eval_code(
new_quosure(),
as.expression(c(
quote(library(checkmate)),
quote(assert_number(1))
))
),
"could not find function \"assert_number\""
"quosure.error"
)
})

Expand Down