-
-
Notifications
You must be signed in to change notification settings - Fork 8
211 [.qenv
S3 method + replacement of @id
, @warnings
, and @messages
fields
#216
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
Merged
Merged
Changes from all commits
Commits
Show all changes
112 commits
Select commit
Hold shift + click to select a range
99ebe96
proposition of the implementation
m7pr 4b2b2fb
let qenv, eval_code and get_code work on @code that has length as the…
m7pr 2eab6d3
adjust tests
m7pr 8349eef
[skip style] [skip vbump] Restyle files
github-actions[bot] 984c439
Update R/qenv-get_code.R
m7pr a277b2d
fix join qenv tests
m7pr 5f77d9d
adjust warning messages
m7pr 8423110
fix R CMD checks just for now
m7pr cc17c8b
fix lintr
m7pr 2391170
Update tests/testthat/test-qenv_get_warnings.R
m7pr 3c8a070
Update tests/testthat/test-qenv_get_warnings.R
m7pr f8295f8
fix get_warnings
m7pr 069538f
move back to regular subset in examples without prefix
m7pr 9fad8dc
use `[.` instead of subset for qenv
m7pr 0b42371
document x
m7pr 2e53db4
[skip style] [skip vbump] Restyle files
github-actions[bot] 7844ee8
add a warning
m7pr 8eeeb40
Merge branch 'main' into 211_subset@main
m7pr 38bd16f
use fix shifted comments in extract comments
m7pr 8b0faa3
[skip style] [skip vbump] Restyle files
github-actions[bot] 56b5c8e
prototype of the function that divides the character code by calls, a…
m7pr dc12c33
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr 15a6cd7
[skip style] [skip vbump] Restyle files
github-actions[bot] 8ddff1b
clean examples from prototype script
m7pr 811092b
merge
m7pr f0b0e9e
[skip roxygen] [skip vbump] Roxygen Man Pages Auto Update
dependabot-preview[bot] a1a73fa
[skip style] [skip vbump] Restyle files
github-actions[bot] 35de66b
incorporate split_code into codebase
m7pr 760a5ed
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr 0ced369
[skip style] [skip vbump] Restyle files
github-actions[bot] 089514c
merge
m7pr dfd7657
merge
m7pr 80d877f
cleanup
m7pr 5e1bd45
[skip roxygen] [skip vbump] Roxygen Man Pages Auto Update
dependabot-preview[bot] 08bd2da
[skip style] [skip vbump] Restyle files
github-actions[bot] 166a8c1
Collate
m7pr a32939c
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr 88a8c04
fix tests
m7pr ae51d8a
[skip style] [skip vbump] Restyle files
github-actions[bot] abcab21
add warnings about skipped objects
m7pr a9e9c0e
[skip style] [skip vbump] Restyle files
github-actions[bot] ed60b32
WIP #70
gogonzo 84875c7
move @id, @warnings and @message to attributes of code and fix rest o…
m7pr 69c08d3
code split
gogonzo 29adf3a
use get_code_dependency in qenv
m7pr 43f45cf
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr 6d674ac
remove print
m7pr e1254e7
for cases with just one call, do not DROP matrix calss in call_breaks
m7pr 13b7f32
handle code with single call in split_code
m7pr 7d3138b
fix
gogonzo 39363c6
add drop FALSE to split_code
m7pr 043414a
fix warning messages for skipped objects
m7pr 9304459
fix some tests
m7pr 6338ce1
documentation changes for @names param - move to qenv-consrtuctor
m7pr 930503f
fix typos in tests
m7pr 0afef83
extract_calls do not drop @linksto tags
m7pr 86e5d95
first clone object, then return
m7pr d91395a
revert the state of the test
m7pr b175c58
fix tests for comments
m7pr 894f819
fix warnings test
m7pr 2971a17
update documentation for qenv slots
m7pr e251952
Merge branch 'main' into 211_subset@main
m7pr f18d55a
bring @param names documentation
m7pr 187350c
remove @ usage in vignette
m7pr a84f2bc
Update tests/testthat/test-qenv_extract.R
m7pr 084382a
adjust description in test
m7pr 6a5d149
fix descriptions in few more tests
m7pr 26efa3f
extend possible_names to hidden names in extract/subset function
m7pr 6f03292
assign `side_effects` and `occurrence` as attributes of `@code` (#223)
m7pr 4c7fa7a
[skip style] [skip vbump] Restyle files
github-actions[bot] 7bd1c2d
simplify get_warnings
m7pr 7fa2369
revert get_code so it returns vector of length 1 (concatened with \n)
m7pr 344f528
[skip style] [skip vbump] Restyle files
github-actions[bot] 20b2c8f
fix warning tests
m7pr 4e3aeee
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr b4e119c
no need to deparse
m7pr e28b937
extend comments testing and remove |>
m7pr c379419
[skip roxygen] [skip vbump] Roxygen Man Pages Auto Update
dependabot-preview[bot] 115ea51
[skip style] [skip vbump] Restyle files
github-actions[bot] 080e27f
substitute pasten with paste
m7pr 14e78ef
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr c3b25e6
skip the test that breaks on CI but not locally
m7pr 7cf13ac
fix the test where we dont want to eval the code
m7pr 109877d
[skip style] [skip vbump] Restyle files
github-actions[bot] 3e4582e
Update R/qenv-get_warnings.R
m7pr da9a69b
fix a test
m7pr 23d9057
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr ef00c58
adjust test so it does not load libraries
m7pr 6fcb8b9
Update tests/testthat/test-qenv_eval_code.R
m7pr 3ba65f2
treat empty calls or comments as separate calls
m7pr ac6d56f
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr 888faa8
[skip style] [skip vbump] Restyle files
github-actions[bot] fae2452
replace pasten with paste
m7pr 49d342b
preserve original src when available
gogonzo b967cdd
bquote not needed
gogonzo cd70b45
remove pipes
m7pr 4da6f65
fix lintr
m7pr ffa54c8
allow to pass ... trhough [. to get_code_dependency - needed in teal.…
m7pr 7f80156
fixes #217
gogonzo 7cbc93d
optimise get_messages/get_warnings
gogonzo b807058
Merge branch 'main' into 211_subset@main
gogonzo defa490
WIP - postmerge
gogonzo 0f20544
fix obvious
gogonzo db68da0
fix: constructor creates a locked environment
averissimo bc95670
yabadabadoo
gogonzo 6c5d5ab
use all.names = TRUE in as.list.environment
m7pr 140ed13
Merge branch '211_subset@main' of https://github.com/insightsengineer…
m7pr 173b3dd
fix warn for env and code in extract
gogonzo cc15b95
forbid names to be NA
gogonzo 0cc2351
fix tests
gogonzo 2a0f49b
names warning on subset
gogonzo ba1a552
fix for verified/unverified teal_data
gogonzo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,13 +24,16 @@ | |
) | ||
} | ||
|
||
shared_ids <- intersect(x@id, y@id) | ||
x_id <- get_code_attr(x, "id") | ||
y_id <- get_code_attr(y, "id") | ||
|
||
shared_ids <- intersect(x_id, y_id) | ||
if (length(shared_ids) == 0) { | ||
return(TRUE) | ||
} | ||
|
||
shared_in_x <- match(shared_ids, x@id) | ||
shared_in_y <- match(shared_ids, y@id) | ||
shared_in_x <- match(shared_ids, x_id) | ||
shared_in_y <- match(shared_ids, y_id) | ||
|
||
# indices of shared ids should be 1:n in both slots | ||
if (identical(shared_in_x, shared_in_y) && identical(shared_in_x, seq_along(shared_ids))) { | ||
|
@@ -86,11 +89,7 @@ c.qenv <- function(...) { | |
stop(join_validation) | ||
} | ||
|
||
id_unique <- !y@id %in% x@id | ||
x@id <- c(x@id, y@id[id_unique]) | ||
x@code <- c(x@code, y@code[id_unique]) | ||
x@warnings <- c(x@warnings, y@warnings[id_unique]) | ||
x@messages <- c(x@messages, y@messages[id_unique]) | ||
x@code <- union(x@code, y@code) | ||
|
||
# insert (and overwrite) objects from y to x | ||
[email protected] <- rlang::env_clone([email protected], parent = parent.env(.GlobalEnv)) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,23 +3,25 @@ | |
#' Reproducible class with environment and code. | ||
#' @name qenv-class | ||
#' @rdname qenv-class | ||
#' @slot code (`character`) representing code necessary to reproduce the environment | ||
#' @slot .xData (`environment`) environment with content was generated by the evaluation | ||
#' @slot code (`list` of `character`) representing code necessary to reproduce the environment. | ||
#' Read more in Code section. | ||
#' of the `code` slot. | ||
#' @slot id (`integer`) random identifier of the code element to make sure uniqueness | ||
#' when joining. | ||
#' @slot warnings (`character`) the warnings output when evaluating the code | ||
#' @slot messages (`character`) the messages output when evaluating the code | ||
#' | ||
#' @section Code: | ||
#' | ||
#' Each code element is a character representing one call. Each element has possible attributes: | ||
#' - `warnings` (`character`) the warnings output when evaluating the code element | ||
#' - `messages` (`character`) the messages output when evaluating the code element | ||
#' - `id (`integer`) random identifier of the code element to make sure uniqueness when joining | ||
#' - `dependency` (`character`) names of objects that appear in this call and gets affected by this call, | ||
#' separated by `<-` (objects on LHS of `<-` are affected by this line, and objects on RHS are affecting this line) | ||
#' | ||
#' @keywords internal | ||
#' @exportClass qenv | ||
setClass( | ||
"qenv", | ||
slots = c( | ||
code = "character", | ||
id = "integer", | ||
warnings = "character", | ||
messages = "character" | ||
), | ||
slots = c(code = "list"), | ||
contains = "environment" | ||
) | ||
|
||
|
@@ -28,27 +30,7 @@ setClass( | |
setMethod( | ||
"initialize", | ||
"qenv", | ||
function(.Object, # nolint: object_name. | ||
.xData, # nolint: object_name. | ||
code = character(0L), | ||
warnings = rep("", length(code)), | ||
messages = rep("", length(code)), | ||
id = integer(0L), | ||
...) { | ||
# # Pre-process parameters to ensure they are ready to be used by parent constructors | ||
stopifnot("`code` must be a character or language object." = any(is.language(code), is.character(code))) | ||
|
||
if (is.language(code)) { | ||
code <- paste(lang2calls(code), collapse = "\n") | ||
} | ||
if (length(code)) { | ||
code <- paste(code, collapse = "\n") | ||
} | ||
|
||
if (length(id) == 0L) { | ||
id <- sample.int(.Machine$integer.max, size = length(code)) | ||
} | ||
|
||
function(.Object, .xData, code = list(), ...) { # nolint: object_name. | ||
new_xdata <- if (rlang::is_missing(.xData)) { | ||
new.env(parent = parent.env(.GlobalEnv)) | ||
} else { | ||
|
@@ -60,28 +42,23 @@ setMethod( | |
# .xData needs to be unnamed as the `.environment` constructor allows at | ||
# most 1 unnamed formal argument of class `environment`. | ||
# See methods::findMethods("initialize")$.environment | ||
.Object <- methods::callNextMethod( # nolint: object_name. | ||
# Mandatory use of `xData` to build a correct .Object@.xData | ||
.Object, new_xdata, | ||
code = code, messages = messages, warnings = warnings, id = id, ... | ||
methods::callNextMethod( | ||
.Object, | ||
new_xdata, # Mandatory use of unnamed environment arg | ||
code = code, ... | ||
) | ||
|
||
.Object | ||
} | ||
) | ||
|
||
#' It takes a `qenv` class and returns `TRUE` if the input is valid | ||
#' @name qenv-class | ||
#' @keywords internal | ||
setValidity("qenv", function(object) { | ||
if (length(object@code) != length(object@id)) { | ||
"@code and @id slots must have the same length." | ||
} else if (length(object@code) != length(object@warnings)) { | ||
"@code and @warnings slots must have the same length" | ||
} else if (length(object@code) != length(object@messages)) { | ||
"@code and @messages slots must have the same length" | ||
} else if (any(duplicated(object@id))) { | ||
"@id contains duplicated values." | ||
ids <- lapply(object@code, "attr", "id") | ||
if (any(sapply(ids, is.null))) { | ||
"All @code slots must have an 'id' attribute" | ||
} else if (any(duplicated(unlist(ids)))) { | ||
"@code contains duplicated 'id' attributes." | ||
} else if (!environmentIsLocked([email protected])) { | ||
"@.xData must be locked." | ||
} else { | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,10 +32,7 @@ | |
setGeneric("concat", function(x, y) standardGeneric("concat")) | ||
|
||
setMethod("concat", signature = c("qenv", "qenv"), function(x, y) { | ||
y@id <- c(x@id, y@id) | ||
y@code <- c(x@code, y@code) | ||
y@warnings <- c(x@warnings, y@warnings) | ||
y@messages <- c(x@messages, y@messages) | ||
|
||
# insert (and overwrite) objects from y to x | ||
[email protected] <- rlang::env_clone([email protected], parent = parent.env(.GlobalEnv)) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,24 +28,27 @@ | |
setGeneric("eval_code", function(object, code) standardGeneric("eval_code")) | ||
|
||
setMethod("eval_code", signature = c("qenv", "character"), function(object, code) { | ||
id <- sample.int(.Machine$integer.max, size = 1) | ||
|
||
object@id <- c(object@id, id) | ||
parsed_code <- parse(text = code, keep.source = TRUE) | ||
gogonzo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[email protected] <- rlang::env_clone([email protected], parent = parent.env(.GlobalEnv)) | ||
code <- paste(code, collapse = "\n") | ||
object@code <- c(object@code, code) | ||
if (length(parsed_code) == 0) { | ||
# empty code, or just comments | ||
attr(code, "id") <- sample.int(.Machine$integer.max, size = 1) | ||
attr(code, "dependency") <- extract_dependency(parsed_code) # in case comment contains @linksto tag | ||
object@code <- c(object@code, list(code)) | ||
return(object) | ||
} | ||
code_split <- split_code(paste(code, collapse = "\n")) | ||
|
||
current_warnings <- "" | ||
current_messages <- "" | ||
for (i in seq_along(code_split)) { | ||
current_code <- code_split[[i]] | ||
current_call <- parse(text = current_code, keep.source = TRUE) | ||
|
||
parsed_code <- parse(text = code, keep.source = TRUE) | ||
for (single_call in parsed_code) { | ||
# Using withCallingHandlers to capture warnings and messages. | ||
# Using tryCatch to capture the error and abort further evaluation. | ||
x <- withCallingHandlers( | ||
tryCatch( | ||
{ | ||
eval(single_call, envir = [email protected]) | ||
eval(current_call, envir = [email protected]) | ||
if (!identical(parent.env([email protected]), parent.env(.GlobalEnv))) { | ||
# needed to make sure that @.xData is always a sibling of .GlobalEnv | ||
# could be changed when any new package is added to search path (through library or require call) | ||
|
@@ -58,30 +61,31 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code | |
message = sprintf( | ||
"%s \n when evaluating qenv code:\n%s", | ||
.ansi_strip(conditionMessage(e)), | ||
deparse1(single_call) | ||
current_code | ||
), | ||
class = c("qenv.error", "try-error", "simpleError"), | ||
trace = object@code | ||
trace = unlist(c(object@code, list(current_code))) | ||
) | ||
} | ||
), | ||
warning = function(w) { | ||
current_warnings <<- paste0(current_warnings, .ansi_strip(sprintf("> %s\n", conditionMessage(w)))) | ||
attr(current_code, "warning") <<- .ansi_strip(sprintf("> %s\n", conditionMessage(w))) | ||
invokeRestart("muffleWarning") | ||
}, | ||
message = function(m) { | ||
current_messages <<- paste0(current_messages, .ansi_strip(sprintf("> %s", conditionMessage(m)))) | ||
attr(current_code, "message") <<- .ansi_strip(sprintf("> %s", conditionMessage(m))) | ||
invokeRestart("muffleMessage") | ||
} | ||
) | ||
|
||
if (!is.null(x)) { | ||
return(x) | ||
} | ||
} | ||
|
||
object@warnings <- c(object@warnings, current_warnings) | ||
object@messages <- c(object@messages, current_messages) | ||
attr(current_code, "id") <- sample.int(.Machine$integer.max, size = 1) | ||
attr(current_code, "dependency") <- extract_dependency(current_call) | ||
object@code <- c(object@code, list(current_code)) | ||
} | ||
|
||
lockEnvironment([email protected], bindings = TRUE) | ||
object | ||
|
@@ -92,7 +96,12 @@ setMethod("eval_code", signature = c("qenv", "language"), function(object, code) | |
}) | ||
|
||
setMethod("eval_code", signature = c("qenv", "expression"), function(object, code) { | ||
eval_code(object, code = paste(vapply(lang2calls(code), deparse1, collapse = "\n", character(1L)), collapse = "\n")) | ||
srcref <- attr(code, "wholeSrcref") | ||
if (length(srcref)) { | ||
eval_code(object, code = paste(attr(code, "wholeSrcref"), collapse = "\n")) | ||
} else { | ||
eval_code(object, code = paste(lang2calls(code), collapse = "\n")) | ||
} | ||
gogonzo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
|
||
setMethod("eval_code", signature = c("qenv.error", "ANY"), function(object, code) { | ||
|
@@ -108,3 +117,7 @@ setMethod("eval_code", signature = c("qenv.error", "ANY"), function(object, code | |
chr | ||
} | ||
} | ||
|
||
get_code_attr <- function(qenv, attr) { | ||
unlist(lapply(qenv@code, function(x) attr(x, attr))) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#' | ||
#' @section Subsetting: | ||
#' `x[names]` subsets objects in `qenv` environment and limit the code to the necessary needed to build limited objects. | ||
#' `...` passes parameters to further methods. | ||
#' | ||
#' @param x (`qenv`) | ||
#' | ||
#' @examples | ||
#' | ||
m7pr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#' # Subsetting | ||
#' q <- qenv() | ||
#' q <- eval_code(q, "a <- 1;b<-2") | ||
#' q["a"] | ||
#' q[c("a", "b")] | ||
#' | ||
#' @rdname qenv | ||
#' | ||
#' @export | ||
`[.qenv` <- function(x, names, ...) { | ||
m7pr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
checkmate::assert_character(names, any.missing = FALSE) | ||
possible_names <- ls(get_env(x), all.names = TRUE) | ||
names_corrected <- intersect(names, possible_names) | ||
env <- if (length(names_corrected)) { | ||
names_missing <- setdiff(names, possible_names) | ||
if (length(names_missing)) { | ||
warning( | ||
sprintf( | ||
"Some 'names' do not exist in the environment of the '%s'. Skipping those: %s.", | ||
class(x)[1], | ||
paste(names_missing, collapse = ", ") | ||
) | ||
) | ||
} | ||
list2env(as.list(x, all.names = TRUE)[names_corrected], parent = parent.env(.GlobalEnv)) | ||
} else { | ||
warning( | ||
sprintf( | ||
"None of 'names' exist in the environment of the '%1$s'. Returning empty '%1$s'.", | ||
class(x)[1] | ||
), | ||
call. = FALSE | ||
) | ||
new.env(parent = parent.env(.GlobalEnv)) | ||
} | ||
lockEnvironment(env) | ||
[email protected] <- env | ||
|
||
normalized_names <- gsub("^`(.*)`$", "\\1", names) | ||
x@code <- get_code_dependency(x@code, names = normalized_names, ...) | ||
|
||
x | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.