Skip to content

Commit 7f80156

Browse files
committed
fixes #217
1 parent ffa54c8 commit 7f80156

17 files changed

+415
-274
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Collate:
6161
'qenv-extract.R'
6262
'qenv-get_code.R'
6363
'qenv-get_env.R'
64+
'qenv-get_messages.r'
6465
'qenv-get_var.R'
6566
'qenv-get_warnings.R'
6667
'qenv-join.R'

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export(dev_suppress)
99
export(eval_code)
1010
export(get_code)
1111
export(get_env)
12+
export(get_messages)
1213
export(get_var)
1314
export(get_warnings)
1415
export(join)

R/qenv-get_code.R

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#'
1010
#'
1111
#' @section Extracting dataset-specific code:
12-
#' When `names` for `get_code` is specified, the code returned will be limited to the lines needed to _create_
13-
#' the requested objects. The code stored in the `@code` slot is analyzed statically to determine
12+
#' When `names` for `get_code` is specified, the code returned will be limited to the lines needed to _create_
13+
#' the requested objects. The code stored in the `qenv` is analyzed statically to determine
1414
#' which lines the objects of interest depend upon. The analysis works well when objects are created
1515
#' with standard infix assignment operators (see `?assignOps`) but it can fail in some situations.
1616
#'
@@ -74,7 +74,7 @@
7474
#' - creating and evaluating language objects, _e.g._ `eval(<call>)`
7575
#'
7676
#' @return
77-
#' `get_code` returns the traced code (from `@code` slot) in the form specified by `deparse`.
77+
#' `get_code` returns the traced code in the form specified by `deparse`.
7878
#'
7979
#' @examples
8080
#' # retrieve code
@@ -97,12 +97,7 @@
9797
#'
9898
#' @export
9999
setGeneric("get_code", function(object, deparse = TRUE, names = NULL, ...) {
100-
# this line forces evaluation of object before passing to the generic
101-
# needed for error handling to work properly
102-
grDevices::pdf(nullfile())
103-
on.exit(grDevices::dev.off())
104-
object
105-
100+
dev_suppress(object)
106101
standardGeneric("get_code")
107102
})
108103

R/qenv-get_env.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#' Access environment included in `qenv`
22
#'
3-
#' The access of environment included in `qenv@env` allows to e.g. list object names included in `qenv@env` slot.
3+
#' The access of environment included in the `qenv` that contains all data objects.
44
#'
5-
#' @param object (`qenv`)
5+
#' @param object (`qenv`).
66
#'
7-
#' @return An `environment` stored in `qenv@env` slot.
7+
#' @return An `environment` stored in `qenv` with all data objects.
88
#'
99
#' @examples
1010
#' q <- qenv()

R/qenv-get_messages.r

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#' Get messages from `qenv` object
2+
#'
3+
#' Retrieve all messages raised during code evaluation in a `qenv`.
4+
#'
5+
#' @param object (`qenv`)
6+
#'
7+
#' @return `character` containing warning information or `NULL` if no messages.
8+
#'
9+
#' @examples
10+
#' data_q <- qenv()
11+
#' data_q <- eval_code(data_q, "iris_data <- iris")
12+
#' warning_qenv <- eval_code(
13+
#' data_q,
14+
#' bquote(p <- hist(iris_data[, .("Sepal.Length")], ff = ""))
15+
#' )
16+
#' cat(get_messages(warning_qenv))
17+
#'
18+
#' @name get_messages
19+
#' @rdname get_messages
20+
#' @aliases get_messages,qenv-method
21+
#' @aliases get_messages,qenv.error-method
22+
#' @aliases get_messages,NULL-method
23+
#'
24+
#' @export
25+
setGeneric("get_messages", function(object) {
26+
dev_suppress(object)
27+
standardGeneric("get_messages")
28+
})
29+
30+
setMethod("get_messages", signature = "qenv", function(object) {
31+
messages <- lapply(object@code, "attr", "message")
32+
idx_warn <- which(sapply(messages, function(x) !is.null(x) && !identical(x, "")))
33+
if (!any(idx_warn)) {
34+
return(NULL)
35+
}
36+
messages <- messages[idx_warn]
37+
code <- object@code[idx_warn]
38+
39+
lines <- mapply(
40+
function(warn, expr) {
41+
sprintf("%swhen running code:\n%s", warn, expr)
42+
},
43+
warn = messages,
44+
expr = code
45+
)
46+
47+
sprintf(
48+
"~~~ messages ~~~\n\n%s\n\n~~~ Trace ~~~\n\n%s",
49+
paste(lines, collapse = "\n\n"),
50+
paste(get_code(object), collapse = "\n")
51+
)
52+
})
53+
54+
setMethod("get_messages", signature = "qenv.error", function(object) {
55+
NULL
56+
})
57+
58+
setMethod("get_messages", "NULL", function(object) {
59+
NULL
60+
})

R/qenv-get_var.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
#'
2222
#' @export
2323
setGeneric("get_var", function(object, var) {
24-
grDevices::pdf(nullfile())
25-
on.exit(grDevices::dev.off())
24+
dev_suppress(object)
2625
standardGeneric("get_var")
2726
})
2827

R/qenv-get_warnings.R

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,43 +23,35 @@
2323
#'
2424
#' @export
2525
setGeneric("get_warnings", function(object) {
26-
# this line forces evaluation of object before passing to the generic
27-
# needed for error handling to work properly
28-
grDevices::pdf(nullfile())
29-
on.exit(grDevices::dev.off())
30-
object
31-
26+
dev_suppress(object)
3227
standardGeneric("get_warnings")
3328
})
3429

35-
setMethod("get_warnings", signature = c("qenv"), function(object) {
30+
setMethod("get_warnings", signature = "qenv", function(object) {
3631
warnings <- lapply(object@code, "attr", "warning")
37-
idx_warn <- which(sapply(warnings, Negate(is.null)))
38-
warnings <- warnings[idx_warn]
39-
code <- object@code[idx_warn]
40-
if (length(warnings) == 0) {
32+
idx_warn <- which(sapply(warnings, function(x) !is.null(x) && !identical(x, "")))
33+
if (!any(idx_warn)) {
4134
return(NULL)
4235
}
36+
warnings <- warnings[idx_warn]
37+
code <- object@code[idx_warn]
4338

4439
lines <- mapply(
4540
function(warn, expr) {
46-
if (warn == "") {
47-
return(NULL)
48-
}
49-
sprintf("%swhen running code:\n%s", warn, paste(lang2calls(expr), collapse = "\n"))
41+
sprintf("%swhen running code:\n%s", warn, expr)
5042
},
5143
warn = warnings,
5244
expr = code
5345
)
54-
lines <- Filter(Negate(is.null), lines)
5546

56-
paste0(
57-
sprintf("~~~ Warnings ~~~\n\n%s\n\n", paste(lines, collapse = "\n\n")),
58-
sprintf("~~~ Trace ~~~\n\n%s", paste(get_code(object), collapse = "\n"))
47+
sprintf(
48+
"~~~ Warnings ~~~\n\n%s\n\n~~~ Trace ~~~\n\n%s",
49+
paste(lines, collapse = "\n\n"),
50+
paste(get_code(object), collapse = "\n")
5951
)
6052
})
6153

62-
setMethod("get_warnings", signature = c("qenv.error"), function(object) {
54+
setMethod("get_warnings", signature = "qenv.error", function(object) {
6355
NULL
6456
})
6557

R/qenv-join.R

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
#' In this example, `mtcars1` object exists in both `x` and `y` objects but the content are not identical.
2222
#' `mtcars1` in the `x qenv` object has more columns than `mtcars1` in the `y qenv` object (only has one column).
2323
#'
24-
#' 2. `join()` will look for identical `@id` values in both `qenv` objects.
25-
#' The index position of these `@id`s must be the same to determine the evaluation order.
24+
#' 2. `join()` will look for identical code elements in both `qenv` objects.
25+
#' The index position of these code elements must be the same to determine the evaluation order.
2626
#' Otherwise, `join()` will throw an error message.
2727
#'
2828
#' Example:
@@ -45,11 +45,8 @@
4545
#' # Error message will occur
4646
#'
4747
#' # Check the order of evaluation based on the id slot
48-
#' shared_ids <- intersect(q@id, z@id)
49-
#' match(shared_ids, q@id) # Output: 1 3
50-
#' match(shared_ids, z@id) # Output: 1 2
5148
#' ```
52-
#' The error occurs because the index position of identical `@id` between the two objects is not the same.
49+
#' The error occurs because the index position of common code elements in the two objects is not the same.
5350
#'
5451
#' 3. The usage of temporary variable in the code expression could cause `join()` to fail.
5552
#'
@@ -72,10 +69,6 @@
7269
#' )
7370
#' q <- join(x,y)
7471
#' # Error message will occur
75-
#'
76-
#' # Check the value of temporary variable i in both objects
77-
#' x@env$i # Output: 2
78-
#' y@env$i # Output: 3
7972
#' ```
8073
#' `join()` fails to provide a proper result because of the temporary variable `i` exists
8174
#' in both objects but has different value.

R/utils-get_code_dependency.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ get_code_dependency <- function(code, names, check_names = TRUE) {
2929
checkmate::assert_list(code, "character")
3030
checkmate::assert_character(names, any.missing = FALSE)
3131

32-
if (length(code) == 0) {
33-
return(code)
34-
}
35-
3632
graph <- lapply(code, attr, "dependency")
3733

3834
if (check_names) {
@@ -46,6 +42,10 @@ get_code_dependency <- function(code, names, check_names = TRUE) {
4642
}
4743
}
4844

45+
if (length(code) == 0) {
46+
return(code)
47+
}
48+
4949
ind <- unlist(lapply(names, function(x) graph_parser(x, graph)))
5050

5151
lib_ind <- detect_libraries(graph)

man/get_env.Rd

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

0 commit comments

Comments
 (0)