Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ export(join)
export(new_qenv)
export(qenv)
exportClasses(qenv)
exportMethods("[[")
exportMethods(concat)
exportMethods(eval_code)
exportMethods(get_code)
exportMethods(get_var)
exportMethods(get_warnings)
exportMethods(join)
exportMethods(new_qenv)
exportMethods(show)
import(grDevices)
importFrom(lifecycle,badge)
Expand Down
24 changes: 15 additions & 9 deletions R/qenv-concat.R
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#' Concatenate two `qenv` objects
#' Concatenate Two `qenv` Objects
#'
#' Combine two `qenv` objects by simple concatenate their environments and the code.
#'
#' We recommend to use the `join` method to have a stricter control
#' in case `x` and `y` contain duplicated bindings and code.
#' RHS argument content has priority over the LHS one.
#'
#' @param x (`qenv`)
#' @param y (`qenv`)
#' @include qenv-errors.R
#'
#' @return `qenv` object.
#'
#' @examples
#' q <- qenv()
#' q1 <- eval_code(q, expression(iris1 <- iris, mtcars1 <- mtcars))
Expand All @@ -16,11 +19,18 @@
#' q2 <- eval_code(q2, "mtcars2 <- mtcars")
#' qq <- concat(q1, q2)
#' get_code(qq)
#'
#' @include qenv-errors.R
#'
#' @name concat
#' @rdname concat
#' @aliases concat,qenv,qenv-method
#' @aliases concat,qenv.error,ANY-method
#' @aliases concat,qenv,qenv.error-method
#'
#' @export
setGeneric("concat", function(x, y) standardGeneric("concat"))

#' @rdname concat
#' @export
setMethod("concat", signature = c("qenv", "qenv"), function(x, y) {
y@id <- c(x@id, y@id)
y@code <- c(x@code, y@code)
Expand All @@ -33,14 +43,10 @@ setMethod("concat", signature = c("qenv", "qenv"), function(x, y) {
y
})

#' @rdname concat
#' @export
setMethod("concat", signature = c("qenv.error"), function(x, y) {
setMethod("concat", signature = c("qenv.error", "ANY"), function(x, y) {
x
})

#' @rdname concat
#' @export
setMethod("concat", signature = c("qenv", "qenv.error"), function(x, y) {
y
})
20 changes: 12 additions & 8 deletions R/qenv-constructor.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#' Initialize `qenv` object
#' Code Tracking With `qenv` Object
#'
#' Create an empty `qenv` object.
#' @description
#' `r badge("stable")`
#'
#' Create a `qenv` object and evaluate code in it to track code history.
#'
#' @details
Comment thread
chlebowa marked this conversation as resolved.
#'
#' `qenv()` instantiates a `qenv` with an empty environment.
#' Any changes must be made by evaluating code in it with `eval_code` or `within`, thereby ensuring reproducibility.
#'
#' `new_qenv()` (deprecated and not recommended)
#' `new_qenv()` (`r badge("deprecated")` and not recommended)
#' can instantiate a `qenv` object with data in the environment and code registered.
#'
#' @name qenv
Expand All @@ -14,7 +19,7 @@
#' # create empty qenv
#' qenv()
#'
#' @return `qenv` object.
#' @return `qenv` and `new_qenv` return a `qenv` object.
#'
#' @export
qenv <- function() {
Expand All @@ -41,13 +46,15 @@ qenv <- function() {
#' @aliases new_qenv,environment,language-method
#' @aliases new_qenv,environment,missing-method
#' @aliases new_qenv,missing,missing-method
#'
#' @seealso [`get_var()`], [`get_warnings()`], [`join()`], [`concat()`]
#'
#' @export
setGeneric("new_qenv", function(env = new.env(parent = parent.env(.GlobalEnv)), code = character()) {
lifecycle::deprecate_warn(when = " 0.4.2", what = "new_qenv()", with = "qenv()", always = TRUE)
Comment thread
chlebowa marked this conversation as resolved.
standardGeneric("new_qenv")
})

#' @export
setMethod(
"new_qenv",
signature = c(env = "environment", code = "expression"),
Expand All @@ -56,7 +63,6 @@ setMethod(
}
)

#' @export
setMethod(
"new_qenv",
signature = c(env = "environment", code = "character"),
Expand All @@ -72,7 +78,6 @@ setMethod(
}
)

#' @export
setMethod(
"new_qenv",
signature = c(env = "environment", code = "language"),
Expand All @@ -81,7 +86,6 @@ setMethod(
}
)

#' @export
setMethod(
"new_qenv",
signature = c(code = "missing", env = "missing"),
Expand Down
39 changes: 19 additions & 20 deletions R/qenv-eval_code.R
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
#' Evaluate the code in the `qenv` environment
#' Evaluate Code in `qenv`
#'
#' Given code is evaluated in the `qenv` environment and appended to the `code` slot. This means
#' that state of the environment is always a result of the stored code (if `qenv` was initialized)
#' with reproducible code.
#'
#' @name eval_code
#' @details
#' `eval_code` evaluates given code in the `qenv` environment and appends it to the `code` slot.
#' Thus, if the `qenv` had been instantiated empty, contents of the environment are always a result of the stored code.
#'
#' @param object (`qenv`)
#' @param code (`character` or `language`) code to evaluate. Also accepts and stores comments
#' @param code (`character` or `language`) code to evaluate. If `character`, comments are retained.
#'
#' @return
#' `eval_code` returns a `qenv` object with `expr` evaluated or `qenv.error` if evaluation fails.
#'
#' @examples
#' # evaluate code in qenv
#' q <- qenv()
#' q1 <- eval_code(q, quote(a <- 1))
#' q2 <- eval_code(q1, quote(library(checkmate)))
#' q3 <- eval_code(q2, quote(assert_number(a)))
#' q <- eval_code(q, "a <- 1")
#' q <- eval_code(q, quote(library(checkmate)))
#' q <- eval_code(q, expression(assert_number(a)))
#'
#' @return `qenv` object.
#' @name eval_code
#' @rdname qenv
#' @aliases eval_code,qenv,character-method
#' @aliases eval_code,qenv,language-method
#' @aliases eval_code,qenv,expression-method
#' @aliases eval_code,qenv.error,ANY-method
#'
#' @export
setGeneric("eval_code", function(object, code) standardGeneric("eval_code"))

#' @rdname eval_code
#' @export
setMethod("eval_code", signature = c("qenv", "character"), function(object, code) {
id <- sample.int(.Machine$integer.max, size = 1)

Expand Down Expand Up @@ -83,21 +88,15 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code
object
})

#' @rdname eval_code
#' @export
setMethod("eval_code", signature = c("qenv", "language"), function(object, code) {
eval_code(object, code = format_expression(code))
})

#' @rdname eval_code
#' @export
setMethod("eval_code", signature = c("qenv", "expression"), function(object, code) {
eval_code(object, code = format_expression(code))
})

#' @rdname eval_code
#' @export
setMethod("eval_code", signature = "qenv.error", function(object, code) {
setMethod("eval_code", signature = c("qenv.error", "ANY"), function(object, code) {
object
})

Expand Down
34 changes: 19 additions & 15 deletions R/qenv-get_code.R
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
#' Get code from `qenv`
#' Get Code From `qenv`
#'
#' @details
#' `get_code` retrieves the code stored in the `qenv`. `...` passes arguments to methods.
#'
#' @name get_code
#' @param object (`qenv`)
#' @param deparse (`logical(1)`) if the returned code should be converted to character.
#' @param ... arguments passed to methods.
#' @return named `character` with the reproducible code.
#' @param deparse (`logical(1)`) flag specifying whether to return code as `character` or `expression`.
#' @param ... see `Details`
#'
#' @return
#' `get_code` returns the traced code (from `@code` slot) in the form specified by `deparse`.
#'
#' @examples
#' q <- qenv()
#' q1 <- eval_code(q, code = quote(a <- 1))
#' q2 <- eval_code(q1, code = quote(b <- a))
#' q3 <- eval_code(q2, code = quote(d <- 2))
#' get_code(q3)
#' get_code(q3, deparse = FALSE)
#' # retrieve code
#' get_code(q)
#' get_code(q, deparse = FALSE)
#'
#' @name get_code
#' @rdname qenv
#' @aliases get_code,qenv-method
#' @aliases get_code,qenv.error-method
#'
#' @export
setGeneric("get_code", function(object, deparse = TRUE, ...) {
# this line forces evaluation of object before passing to the generic
Expand All @@ -23,8 +31,6 @@ setGeneric("get_code", function(object, deparse = TRUE, ...) {
standardGeneric("get_code")
})

#' @rdname get_code
#' @export
setMethod("get_code", signature = "qenv", function(object, deparse = TRUE) {
checkmate::assert_flag(deparse)
if (deparse) {
Expand All @@ -34,8 +40,6 @@ setMethod("get_code", signature = "qenv", function(object, deparse = TRUE) {
}
})

#' @rdname get_code
#' @export
setMethod("get_code", signature = "qenv.error", function(object, ...) {
stop(
errorCondition(
Expand Down
35 changes: 15 additions & 20 deletions R/qenv-get_var.R
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
#' Get object from the `qenv` environment
#' Get Object From `qenv`
#'
#' Retrieve variables from the `qenv` environment.
#'
#' @param object,x (`qenv`)
#' @param var,i (`character(1)`) variable name.
#'
#' Get object from the `qenv` environment.
#' @param object (`qenv`)
#' @param var (`character(1)`) name of the variable to pull from the environment.
#' @name get_var
#' @return The value of required variable (`var`) within `qenv` object.
#'
#' @examples
#' q <- qenv()
#' q1 <- eval_code(q, code = quote(a <- 1))
#' q2 <- eval_code(q1, code = "b <- a")
#' get_var(q2, "b")
#' q2[["b"]]
#'
#' @name get_var
#' @rdname get_var
#' @aliases get_var,qenv,character-method
#' @aliases get_var,qenv.error,ANY-method
#'
#' @export
setGeneric("get_var", function(object, var) {
grDevices::pdf(nullfile())
on.exit(grDevices::dev.off())
standardGeneric("get_var")
})


#' @rdname get_var
#' @export
setMethod("get_var", signature = c("qenv", "character"), function(object, var) {
tryCatch(
get(var, envir = object@env),
Expand All @@ -32,29 +36,20 @@ setMethod("get_var", signature = c("qenv", "character"), function(object, var) {
)
})

#' @rdname get_var
#' @export
setMethod("get_var", signature = "qenv.error", function(object, var) {
setMethod("get_var", signature = c("qenv.error", "ANY"), function(object, var) {
stop(errorCondition(
list(message = conditionMessage(object)),
class = c("validation", "try-error", "simpleError")
))
})


#' @param x (`qenv`)
#' @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("[[", signature = c("qenv", "ANY", "missing"), function(x, i, j, ...) {
setMethod("[[", signature = c("qenv", "ANY"), function(x, i) {
get_var(x, i)
})

#' @rdname get_var
#' @export
`[[.qenv.error` <- function(x, i, j, ...) {
`[[.qenv.error` <- function(x, i) {
stop(errorCondition(
list(message = conditionMessage(x)),
class = c("validation", "try-error", "simpleError")
Expand Down
28 changes: 15 additions & 13 deletions R/qenv-get_warnings.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#' Get the warnings of `qenv` object
#' Get Warnings From `qenv` Object
#'
#' Retrieve all warnings raised during code evaluation in a `qenv`.
#'
#' @param object (`qenv`)
#'
#' @return `character` containing warning information or `NULL` if no warnings
#' @export
#' @return `character` containing warning information or `NULL` if no warnings.
#'
#' @examples
#' data_q <- qenv()
Expand All @@ -13,6 +14,13 @@
#' bquote(p <- hist(iris_data[, .("Sepal.Length")], ff = ""))
#' )
#' cat(get_warnings(warning_qenv))
#'
#' @name get_warnings
#' @rdname get_warnings
#' @aliases get_warnings,qenv-method
#' @aliases get_warnings,qenv.error-method
#' @aliases get_warnings,NULL-method
#'
#' @export
setGeneric("get_warnings", function(object) {
# this line forces evaluation of object before passing to the generic
Expand All @@ -24,14 +32,6 @@ setGeneric("get_warnings", function(object) {
standardGeneric("get_warnings")
})

#' @rdname get_warnings
#' @export
setMethod("get_warnings", signature = c("qenv.error"), function(object) {
NULL
})

#' @rdname get_warnings
#' @export
setMethod("get_warnings", signature = c("qenv"), function(object) {
if (all(object@warnings == "")) {
return(NULL)
Expand All @@ -56,8 +56,10 @@ setMethod("get_warnings", signature = c("qenv"), function(object) {
)
})

#' @rdname get_warnings
#' @export
setMethod("get_warnings", signature = c("qenv.error"), function(object) {
NULL
})

setMethod("get_warnings", "NULL", function(object) {
NULL
})
Loading