From 967c1c540bf2a8113266ece20569d2a3164c67ee Mon Sep 17 00:00:00 2001 From: m7pr Date: Mon, 28 Oct 2024 14:09:17 +0100 Subject: [PATCH 01/37] `[.teal_data` S3 method --- DESCRIPTION | 1 + NAMESPACE | 1 + R/teal_data-extract.R | 38 ++++++++++++++++++++++++++++++++++++++ man/teal_data.Rd | 30 ++++++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 R/teal_data-extract.R diff --git a/DESCRIPTION b/DESCRIPTION index 25d9bb0c3..0cbeefdbb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -73,6 +73,7 @@ Collate: 'teal.data.R' 'teal_data-class.R' 'teal_data-datanames.R' + 'teal_data-extract.R' 'teal_data-get_code.R' 'teal_data-show.R' 'teal_data.R' diff --git a/NAMESPACE b/NAMESPACE index 71db8957b..603ad524e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,7 @@ # Generated by roxygen2: do not edit by hand S3method("[",join_keys) +S3method("[",teal_data) S3method("[<-",join_keys) S3method("[[<-",join_keys) S3method("join_keys<-",join_keys) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R new file mode 100644 index 000000000..fb9c856b6 --- /dev/null +++ b/R/teal_data-extract.R @@ -0,0 +1,38 @@ +#' +#' @section Subsetting: +#' `x[names]` subsets objects in `teal_data` environment and limit the code to the necessary needed to build limited +#' objects. +#' +#' @param names (`character`) names of objects included in `teal_subset` to subset +#' @param x (`teal_data`) +#' +#' @examples +#' +#' # Subsetting +#' data <- teal_data() +#' data <- eval_code(data, "a <- 1;b<-2") +#' data["a"] +#' data[c("a", "b")] +#' +#' join_keys(data) <- join_keys(join_key("a", "b", "x")) +#' join_keys(data["a"]) # should show empty keys +#' join_keys(data["b"]) +#' join_keys(data)["a"] # should show empty keys +#' join_keys(data)["b"] +#' +#' @rdname teal_data +#' +#' @export +`[.teal_data` <- function(x, names) { + checkmate::assert_class(names, "character") + names_in_env <- intersect(names, ls(get_env(x))) + if (!length(names_in_env)) { + return(teal_data()) + } + + subset_qenv <- getFromNamespace("[.qenv", "teal.code") + x <- subset_qenv(x, names_in_env) + x@join_keys <- x@join_keys[names_in_env] + + x +} diff --git a/man/teal_data.Rd b/man/teal_data.Rd index b249aece4..0ac641980 100644 --- a/man/teal_data.Rd +++ b/man/teal_data.Rd @@ -1,12 +1,19 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/teal_data.R -\name{teal_data} +% Please edit documentation in R/teal_data-extract.R, R/teal_data.R +\name{[.teal_data} +\alias{[.teal_data} \alias{teal_data} \title{Comprehensive data integration function for \code{teal} applications} \usage{ +\method{[}{teal_data}(x, names) + teal_data(..., join_keys = teal.data::join_keys(), code = character(0), check) } \arguments{ +\item{x}{(\code{teal_data})} + +\item{names}{(\code{character}) names of objects included in \code{teal_subset} to subset} + \item{...}{any number of objects (presumably data objects) provided as \code{name = value} pairs.} \item{join_keys}{(\code{join_keys} or single \code{join_key_set}) @@ -27,7 +34,26 @@ A \code{teal_data} object. Universal function to pass data to teal application. } +\section{Subsetting}{ + +\code{x[names]} subsets objects in \code{teal_data} environment and limit the code to the necessary needed to build limited +objects. +} + \examples{ + +# Subsetting +data <- teal_data() +data <- eval_code(data, "a <- 1;b<-2") +data["a"] +data[c("a", "b")] + +join_keys(data) <- join_keys(join_key("a", "b", "x")) +join_keys(data["a"]) # should show empty keys +join_keys(data["b"]) +join_keys(data)["a"] # should show empty keys +join_keys(data)["b"] + teal_data(x1 = iris, x2 = mtcars) } From 362b9823c35240e54c33bc5db1838363dc75bc91 Mon Sep 17 00:00:00 2001 From: m7pr Date: Mon, 28 Oct 2024 14:15:19 +0100 Subject: [PATCH 02/37] provide prefix for utils:: --- R/teal_data-extract.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index fb9c856b6..a3e8ae4ad 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -30,7 +30,7 @@ return(teal_data()) } - subset_qenv <- getFromNamespace("[.qenv", "teal.code") + subset_qenv <- utils::getFromNamespace("[.qenv", "teal.code") x <- subset_qenv(x, names_in_env) x@join_keys <- x@join_keys[names_in_env] From a2610a3036406fa6a6cf074b46522c22d310b232 Mon Sep 17 00:00:00 2001 From: m7pr Date: Tue, 29 Oct 2024 09:36:06 +0100 Subject: [PATCH 03/37] fixing rdname --- R/teal_data-extract.R | 4 +--- man/teal_data-class.Rd | 33 ++++++++++++++++++++++++++++++++- man/teal_data.Rd | 30 ++---------------------------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index a3e8ae4ad..01a074994 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -1,5 +1,5 @@ #' -#' @section Subsetting: +#' @describeIn teal_data Subsetting #' `x[names]` subsets objects in `teal_data` environment and limit the code to the necessary needed to build limited #' objects. #' @@ -20,8 +20,6 @@ #' join_keys(data)["a"] # should show empty keys #' join_keys(data)["b"] #' -#' @rdname teal_data -#' #' @export `[.teal_data` <- function(x, names) { checkmate::assert_class(names, "character") diff --git a/man/teal_data-class.Rd b/man/teal_data-class.Rd index ef1c1decb..3398afcdc 100644 --- a/man/teal_data-class.Rd +++ b/man/teal_data-class.Rd @@ -1,9 +1,18 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/teal_data-class.R +% Please edit documentation in R/teal_data-class.R, R/teal_data-extract.R \docType{class} \name{teal_data-class} \alias{teal_data-class} +\alias{[.teal_data} \title{Reproducible data} +\usage{ +\method{[}{teal_data}(x, names) +} +\arguments{ +\item{x}{(\code{teal_data})} + +\item{names}{(\code{character}) names of objects included in \code{teal_subset} to subset} +} \description{ Reproducible data container class. Inherits code tracking behavior from \code{\link[teal.code:qenv-class]{teal.code::qenv}}. } @@ -15,6 +24,13 @@ These slots should never be accessed directly, use the provided get/set function As code is evaluated in \code{teal_data}, messages and warnings are stored in their respective slots. If errors are raised, a \code{qenv.error} object is returned. } +\section{Functions}{ +\itemize{ +\item \code{[}: Subsetting +\code{x[names]} subsets objects in \code{teal_data} environment and limit the code to the necessary needed to build limited +objects. + +}} \section{Slots}{ \describe{ @@ -44,4 +60,19 @@ Access or modify with \code{\link[=datanames]{datanames()}}.} Used internally. See \code{\link[=verify]{verify()}} for more details.} }} +\examples{ + +# Subsetting +data <- teal_data() +data <- eval_code(data, "a <- 1;b<-2") +data["a"] +data[c("a", "b")] + +join_keys(data) <- join_keys(join_key("a", "b", "x")) +join_keys(data["a"]) # should show empty keys +join_keys(data["b"]) +join_keys(data)["a"] # should show empty keys +join_keys(data)["b"] + +} \keyword{internal} diff --git a/man/teal_data.Rd b/man/teal_data.Rd index 0ac641980..b249aece4 100644 --- a/man/teal_data.Rd +++ b/man/teal_data.Rd @@ -1,19 +1,12 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/teal_data-extract.R, R/teal_data.R -\name{[.teal_data} -\alias{[.teal_data} +% Please edit documentation in R/teal_data.R +\name{teal_data} \alias{teal_data} \title{Comprehensive data integration function for \code{teal} applications} \usage{ -\method{[}{teal_data}(x, names) - teal_data(..., join_keys = teal.data::join_keys(), code = character(0), check) } \arguments{ -\item{x}{(\code{teal_data})} - -\item{names}{(\code{character}) names of objects included in \code{teal_subset} to subset} - \item{...}{any number of objects (presumably data objects) provided as \code{name = value} pairs.} \item{join_keys}{(\code{join_keys} or single \code{join_key_set}) @@ -34,26 +27,7 @@ A \code{teal_data} object. Universal function to pass data to teal application. } -\section{Subsetting}{ - -\code{x[names]} subsets objects in \code{teal_data} environment and limit the code to the necessary needed to build limited -objects. -} - \examples{ - -# Subsetting -data <- teal_data() -data <- eval_code(data, "a <- 1;b<-2") -data["a"] -data[c("a", "b")] - -join_keys(data) <- join_keys(join_key("a", "b", "x")) -join_keys(data["a"]) # should show empty keys -join_keys(data["b"]) -join_keys(data)["a"] # should show empty keys -join_keys(data)["b"] - teal_data(x1 = iris, x2 = mtcars) } From c01612fdcc780e65984e6c10d2f285bd42041edc Mon Sep 17 00:00:00 2001 From: m7pr Date: Tue, 29 Oct 2024 09:54:52 +0100 Subject: [PATCH 04/37] rename teal_data.R to teal_data-constructor.R --- DESCRIPTION | 2 +- R/{teal_data.R => teal_data-constructor.R} | 3 ++ R/teal_data-extract.R | 4 ++- man/teal_data-class.Rd | 33 +--------------------- man/teal_data.Rd | 28 +++++++++++++++++- 5 files changed, 35 insertions(+), 35 deletions(-) rename R/{teal_data.R => teal_data-constructor.R} (98%) diff --git a/DESCRIPTION b/DESCRIPTION index 0cbeefdbb..b040448d1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -72,11 +72,11 @@ Collate: 'join_keys.R' 'teal.data.R' 'teal_data-class.R' + 'teal_data-constructor.R' 'teal_data-datanames.R' 'teal_data-extract.R' 'teal_data-get_code.R' 'teal_data-show.R' - 'teal_data.R' 'testhat-helpers.R' 'topological_sort.R' 'verify.R' diff --git a/R/teal_data.R b/R/teal_data-constructor.R similarity index 98% rename from R/teal_data.R rename to R/teal_data-constructor.R index ea32e624a..128c3b49e 100644 --- a/R/teal_data.R +++ b/R/teal_data-constructor.R @@ -21,6 +21,9 @@ #' #' @export #' +#' @name teal_data +#' @rdname teal_data +#' #' @examples #' teal_data(x1 = iris, x2 = mtcars) #' diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 01a074994..a3e8ae4ad 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -1,5 +1,5 @@ #' -#' @describeIn teal_data Subsetting +#' @section Subsetting: #' `x[names]` subsets objects in `teal_data` environment and limit the code to the necessary needed to build limited #' objects. #' @@ -20,6 +20,8 @@ #' join_keys(data)["a"] # should show empty keys #' join_keys(data)["b"] #' +#' @rdname teal_data +#' #' @export `[.teal_data` <- function(x, names) { checkmate::assert_class(names, "character") diff --git a/man/teal_data-class.Rd b/man/teal_data-class.Rd index 3398afcdc..ef1c1decb 100644 --- a/man/teal_data-class.Rd +++ b/man/teal_data-class.Rd @@ -1,18 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/teal_data-class.R, R/teal_data-extract.R +% Please edit documentation in R/teal_data-class.R \docType{class} \name{teal_data-class} \alias{teal_data-class} -\alias{[.teal_data} \title{Reproducible data} -\usage{ -\method{[}{teal_data}(x, names) -} -\arguments{ -\item{x}{(\code{teal_data})} - -\item{names}{(\code{character}) names of objects included in \code{teal_subset} to subset} -} \description{ Reproducible data container class. Inherits code tracking behavior from \code{\link[teal.code:qenv-class]{teal.code::qenv}}. } @@ -24,13 +15,6 @@ These slots should never be accessed directly, use the provided get/set function As code is evaluated in \code{teal_data}, messages and warnings are stored in their respective slots. If errors are raised, a \code{qenv.error} object is returned. } -\section{Functions}{ -\itemize{ -\item \code{[}: Subsetting -\code{x[names]} subsets objects in \code{teal_data} environment and limit the code to the necessary needed to build limited -objects. - -}} \section{Slots}{ \describe{ @@ -60,19 +44,4 @@ Access or modify with \code{\link[=datanames]{datanames()}}.} Used internally. See \code{\link[=verify]{verify()}} for more details.} }} -\examples{ - -# Subsetting -data <- teal_data() -data <- eval_code(data, "a <- 1;b<-2") -data["a"] -data[c("a", "b")] - -join_keys(data) <- join_keys(join_key("a", "b", "x")) -join_keys(data["a"]) # should show empty keys -join_keys(data["b"]) -join_keys(data)["a"] # should show empty keys -join_keys(data)["b"] - -} \keyword{internal} diff --git a/man/teal_data.Rd b/man/teal_data.Rd index b249aece4..c55e2a0d6 100644 --- a/man/teal_data.Rd +++ b/man/teal_data.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/teal_data.R +% Please edit documentation in R/teal_data-constructor.R, R/teal_data-extract.R \name{teal_data} \alias{teal_data} +\alias{[.teal_data} \title{Comprehensive data integration function for \code{teal} applications} \usage{ teal_data(..., join_keys = teal.data::join_keys(), code = character(0), check) + +\method{[}{teal_data}(x, names) } \arguments{ \item{...}{any number of objects (presumably data objects) provided as \code{name = value} pairs.} @@ -18,6 +21,10 @@ Note this code is not executed and the \code{teal_data} may not be reproducible} \item{check}{(\code{logical}) \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Use \code{\link[=verify]{verify()}} to verify code reproducibility .} + +\item{x}{(\code{teal_data})} + +\item{names}{(\code{character}) names of objects included in \code{teal_subset} to subset} } \value{ A \code{teal_data} object. @@ -27,7 +34,26 @@ A \code{teal_data} object. Universal function to pass data to teal application. } +\section{Subsetting}{ + +\code{x[names]} subsets objects in \code{teal_data} environment and limit the code to the necessary needed to build limited +objects. +} + \examples{ teal_data(x1 = iris, x2 = mtcars) + +# Subsetting +data <- teal_data() +data <- eval_code(data, "a <- 1;b<-2") +data["a"] +data[c("a", "b")] + +join_keys(data) <- join_keys(join_key("a", "b", "x")) +join_keys(data["a"]) # should show empty keys +join_keys(data["b"]) +join_keys(data)["a"] # should show empty keys +join_keys(data)["b"] + } From fd4fe27d6757d457987a7d5bd5d4e2ab3dfa266e Mon Sep 17 00:00:00 2001 From: m7pr Date: Tue, 29 Oct 2024 10:16:00 +0100 Subject: [PATCH 05/37] an attempt with NextMethod --- R/teal_data-extract.R | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index a3e8ae4ad..64d569bce 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -29,9 +29,20 @@ if (!length(names_in_env)) { return(teal_data()) } + # From ?NextMethod + # To pass `names` to `NextMethod` - it looks like it needs to be called `names` + # and created in the environment of the function that calls `NextMehod`. - subset_qenv <- utils::getFromNamespace("[.qenv", "teal.code") - x <- subset_qenv(x, names_in_env) + # NextMethod works by creating a special call frame for the next method. If no new arguments are supplied, the + # arguments will be the same in number, order and name as those to the current method but their values will be + # promises to evaluate their name in the current method and environment. Any named arguments matched to ... are + # handled specially: they either replace existing arguments of the same name or are appended to the argument list. + # They are passed on as the promise that was supplied as an argument to the current environment. + # (S does this differently!) If they have been evaluated in the current (or a previous environment) they remain + # evaluated. (This is a complex area, and subject to change: see the draft ‘R Language Definition’.) + + names <- names_in_env + x <- NextMethod("`[`", x) x@join_keys <- x@join_keys[names_in_env] x From f7894e55f3fed4c282df2a2db72c98a4e47bb3e0 Mon Sep 17 00:00:00 2001 From: m7pr Date: Tue, 29 Oct 2024 10:21:12 +0100 Subject: [PATCH 06/37] add a warning --- R/teal_data-extract.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 64d569bce..0df590254 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -27,6 +27,7 @@ checkmate::assert_class(names, "character") names_in_env <- intersect(names, ls(get_env(x))) if (!length(names_in_env)) { + warning("None of `names` elements exist in `teal_data`. Returning empty `teal_data`.") return(teal_data()) } # From ?NextMethod From e53afc8976dc4aeb7d3a26d0cf95b336e62d83a1 Mon Sep 17 00:00:00 2001 From: m7pr Date: Tue, 29 Oct 2024 11:21:20 +0100 Subject: [PATCH 07/37] extend vignettes with `[` for teal_data --- vignettes/teal-data.Rmd | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/vignettes/teal-data.Rmd b/vignettes/teal-data.Rmd index 687b136d9..be619f0e7 100644 --- a/vignettes/teal-data.Rmd +++ b/vignettes/teal-data.Rmd @@ -30,18 +30,25 @@ my_data <- within( { data1 <- data.frame(id = 1:10, x = 11:20) data2 <- data.frame(id = 1:10, x = 21:30) + data3 <- data.frame(id = 1:10, x = 31:40) } ) # get objects stored in teal_data my_data[["data1"]] -my_data[["data1"]] +my_data[["data2"]] + +# limit objects stored in teal_data +my_data[c("data1", "data3")] # get reproducible code get_code(my_data) +# get code just for specific object +get_code(my_data, names = "data2") + # get or set datanames -datanames(my_data) <- c("data1", "data2") +datanames(my_data) <- c("data1", "data2", "data3") datanames(my_data) # print @@ -93,4 +100,7 @@ join_keys(my_data) <- join_keys( ) join_keys(my_data) + +# join_keys for limited object +join_keys(my_data["child"]) ``` From 1ea9d8f4c2514c1e4c0764fed4ae704739ef5775 Mon Sep 17 00:00:00 2001 From: m7pr Date: Tue, 29 Oct 2024 11:33:29 +0100 Subject: [PATCH 08/37] write tests for [.teal_data --- tests/testthat/test-extract.R | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/testthat/test-extract.R diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R new file mode 100644 index 000000000..21506c4f0 --- /dev/null +++ b/tests/testthat/test-extract.R @@ -0,0 +1,16 @@ +testthat::test_that("`[.` returns empty teal_data for improper names", { + data <- teal_data(x = 1, a = 2) + testthat::expect_equal(data["y"], teal_data()) +}) + +testthat::test_that("`[.` returns limited join_keys", { + data <- teal_data(a = 1, b = 2) + + join_keys(data) <- join_keys(join_key("a", "b", "x")) + empty_join_keys <- join_keys() + attr(empty_join_keys, "names") <- character(0) + testthat::expect_equal( + join_keys(data["a"]), # By default named list || names() is character(0) + empty_join_keys # By default unnamed list || names() is NULL + ) +}) From 220e46c21bcf19ab4f3bed53730e45f9c24d5dd1 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:35:26 +0000 Subject: [PATCH 09/37] [skip style] [skip vbump] Restyle files --- tests/testthat/test-extract.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 21506c4f0..e2af8bfb9 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -10,7 +10,7 @@ testthat::test_that("`[.` returns limited join_keys", { empty_join_keys <- join_keys() attr(empty_join_keys, "names") <- character(0) testthat::expect_equal( - join_keys(data["a"]), # By default named list || names() is character(0) - empty_join_keys # By default unnamed list || names() is NULL + join_keys(data["a"]), # By default named list || names() is character(0) + empty_join_keys # By default unnamed list || names() is NULL ) }) From 5f17af01828ed28f7d65bf37088972b6f619af1a Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 30 Oct 2024 11:10:59 +0100 Subject: [PATCH 10/37] extned tests for different input class --- tests/testthat/test-extract.R | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 21506c4f0..557575ea5 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -3,6 +3,26 @@ testthat::test_that("`[.` returns empty teal_data for improper names", { testthat::expect_equal(data["y"], teal_data()) }) +testthat::test_that("`[.` handles empty names", { + data <- teal_data(x = 1, a = 2) + testthat::expect_equal(data[character(0)], teal_data()) +}) + +testthat::test_that("`[.` handles names as NA_character_", { + data <- teal_data(x = 1, a = 2) + testthat::expect_equal(data[NA_character_], teal_data()) +}) + +testthat::test_that("`[.` thorws warnings if names is NULL", { + data <- teal_data(x = 1, a = 2) + testthat::expect_error(data[NULL], "Assertion on 'names' failed: Must inherit from class 'character'") +}) + +testthat::test_that("`[.` thorws warnings if names is numeric", { + data <- teal_data(x = 1, a = 2) + testthat::expect_error(data[1], "Assertion on 'names' failed: Must inherit from class 'character'") +}) + testthat::test_that("`[.` returns limited join_keys", { data <- teal_data(a = 1, b = 2) From 39d9f37dc73f6152234ed5b41ae6a7619d0863eb Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 30 Oct 2024 11:17:04 +0100 Subject: [PATCH 11/37] remove NextMethod comments --- R/teal_data-extract.R | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 0df590254..5794e8a04 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -25,26 +25,14 @@ #' @export `[.teal_data` <- function(x, names) { checkmate::assert_class(names, "character") - names_in_env <- intersect(names, ls(get_env(x))) - if (!length(names_in_env)) { + names <- intersect(names, ls(get_env(x))) + if (!length(names)) { warning("None of `names` elements exist in `teal_data`. Returning empty `teal_data`.") return(teal_data()) } - # From ?NextMethod - # To pass `names` to `NextMethod` - it looks like it needs to be called `names` - # and created in the environment of the function that calls `NextMehod`. - # NextMethod works by creating a special call frame for the next method. If no new arguments are supplied, the - # arguments will be the same in number, order and name as those to the current method but their values will be - # promises to evaluate their name in the current method and environment. Any named arguments matched to ... are - # handled specially: they either replace existing arguments of the same name or are appended to the argument list. - # They are passed on as the promise that was supplied as an argument to the current environment. - # (S does this differently!) If they have been evaluated in the current (or a previous environment) they remain - # evaluated. (This is a complex area, and subject to change: see the draft ‘R Language Definition’.) - - names <- names_in_env - x <- NextMethod("`[`", x) - x@join_keys <- x@join_keys[names_in_env] + x <- NextMethod("`[`", x) # takes 'names' from function's environment + x@join_keys <- x@join_keys[names] x } From b6c69554cd7f78deb842d8a7711849cc1bd8558e Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 30 Oct 2024 11:17:14 +0100 Subject: [PATCH 12/37] extend tests with expect_warning --- tests/testthat/test-extract.R | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 17034ec24..b1a07e93d 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -1,16 +1,22 @@ testthat::test_that("`[.` returns empty teal_data for improper names", { data <- teal_data(x = 1, a = 2) - testthat::expect_equal(data["y"], teal_data()) + testthat::expect_warning( + testthat::expect_equal(data["y"], teal_data()) + ) }) testthat::test_that("`[.` handles empty names", { data <- teal_data(x = 1, a = 2) - testthat::expect_equal(data[character(0)], teal_data()) + testthat::expect_warning( + testthat::expect_equal(data[character(0)], teal_data()) + ) }) testthat::test_that("`[.` handles names as NA_character_", { data <- teal_data(x = 1, a = 2) - testthat::expect_equal(data[NA_character_], teal_data()) + testthat::expect_warning( + testthat::expect_equal(data[NA_character_], teal_data()) + ) }) testthat::test_that("`[.` thorws warnings if names is NULL", { From 009bbc0464e055b85a5f31d39523d844b777d186 Mon Sep 17 00:00:00 2001 From: Marcin <133694481+m7pr@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:27:56 +0100 Subject: [PATCH 13/37] Update R/teal_data-extract.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Dawid Kałędkowski Signed-off-by: Marcin <133694481+m7pr@users.noreply.github.com> --- R/teal_data-extract.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 5794e8a04..e867034c3 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -24,7 +24,7 @@ #' #' @export `[.teal_data` <- function(x, names) { - checkmate::assert_class(names, "character") + checkmate::assert_character(names) names <- intersect(names, ls(get_env(x))) if (!length(names)) { warning("None of `names` elements exist in `teal_data`. Returning empty `teal_data`.") From fc0d0c093e8f4b3e3a4e635cc3aea10b7c7624fc Mon Sep 17 00:00:00 2001 From: Marcin <133694481+m7pr@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:28:24 +0100 Subject: [PATCH 14/37] Update tests/testthat/test-extract.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Dawid Kałędkowski Signed-off-by: Marcin <133694481+m7pr@users.noreply.github.com> --- tests/testthat/test-extract.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index b1a07e93d..d93ce33c6 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -19,7 +19,7 @@ testthat::test_that("`[.` handles names as NA_character_", { ) }) -testthat::test_that("`[.` thorws warnings if names is NULL", { +testthat::test_that("`[.` throws warning if names is NULL", { data <- teal_data(x = 1, a = 2) testthat::expect_error(data[NULL], "Assertion on 'names' failed: Must inherit from class 'character'") }) From f74635a762876a39997a678b8e7fb85f1c857f88 Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 30 Oct 2024 14:33:26 +0100 Subject: [PATCH 15/37] remove unneeded roxygen2 tags --- R/teal_data-constructor.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/R/teal_data-constructor.R b/R/teal_data-constructor.R index 128c3b49e..b950eb740 100644 --- a/R/teal_data-constructor.R +++ b/R/teal_data-constructor.R @@ -21,8 +21,6 @@ #' #' @export #' -#' @name teal_data -#' @rdname teal_data #' #' @examples #' teal_data(x1 = iris, x2 = mtcars) From d3eb3950bd5ace29153e70b2bf3f30b09b027b73 Mon Sep 17 00:00:00 2001 From: Marcin <133694481+m7pr@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:34:59 +0100 Subject: [PATCH 16/37] Update R/teal_data-constructor.R Signed-off-by: Marcin <133694481+m7pr@users.noreply.github.com> --- R/teal_data-constructor.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/teal_data-constructor.R b/R/teal_data-constructor.R index b950eb740..ea32e624a 100644 --- a/R/teal_data-constructor.R +++ b/R/teal_data-constructor.R @@ -21,7 +21,6 @@ #' #' @export #' -#' #' @examples #' teal_data(x1 = iris, x2 = mtcars) #' From 5839f0df8b7dbc056d384b5a223ec0e2a9a5e040 Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 30 Oct 2024 14:51:47 +0100 Subject: [PATCH 17/37] warn about skipped names --- R/teal_data-extract.R | 13 ++++++++++++- tests/testthat/test-extract.R | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index e867034c3..a987c2558 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -25,12 +25,23 @@ #' @export `[.teal_data` <- function(x, names) { checkmate::assert_character(names) - names <- intersect(names, ls(get_env(x))) + possible_names <- ls(get_env(x)) + names_warn <- setdiff(names, possible_names) + names <- intersect(names, possible_names) if (!length(names)) { warning("None of `names` elements exist in `teal_data`. Returning empty `teal_data`.") return(teal_data()) } + if (length(names_warn)) { + warning( + sprintf( + "Some elements of `names` do not exist in `teal_data`. Skipping those: %s.", + paste(names_warn, collapse = ", ") + ) + ) + } + x <- NextMethod("`[`", x) # takes 'names' from function's environment x@join_keys <- x@join_keys[names] diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index d93ce33c6..3a53bdd4b 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -1,7 +1,16 @@ -testthat::test_that("`[.` returns empty teal_data for improper names", { +testthat::test_that("`[.` returns empty teal_data for names not in teal_data", { data <- teal_data(x = 1, a = 2) testthat::expect_warning( - testthat::expect_equal(data["y"], teal_data()) + testthat::expect_equal(data["y"], teal_data()), + "None of `names` elements exist in `teal_data`. Returning empty `teal_data`." + ) +}) + +testthat::test_that("`[.` returns limited teal_data for some names not in teal_data", { + data <- teal_data(x = 1, a = 2) + testthat::expect_warning( + testthat::expect_equal(data[c("y", "a")], data["a"]), + "Some elements of `names` do not exist in `teal_data`. Skipping those: y." ) }) @@ -21,12 +30,12 @@ testthat::test_that("`[.` handles names as NA_character_", { testthat::test_that("`[.` throws warning if names is NULL", { data <- teal_data(x = 1, a = 2) - testthat::expect_error(data[NULL], "Assertion on 'names' failed: Must inherit from class 'character'") + testthat::expect_error(data[NULL], "Assertion on 'names' failed: Must be of type 'character', not 'NULL'.") }) testthat::test_that("`[.` thorws warnings if names is numeric", { data <- teal_data(x = 1, a = 2) - testthat::expect_error(data[1], "Assertion on 'names' failed: Must inherit from class 'character'") + testthat::expect_error(data[1], "Assertion on 'names' failed: Must be of type 'character', not 'double'.") }) testthat::test_that("`[.` returns limited join_keys", { From 269b77b56ff4c277ef6a7b71b829449fc586a1dd Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 30 Oct 2024 14:58:51 +0100 Subject: [PATCH 18/37] move tests to teal.code --- tests/testthat/test-extract.R | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 3a53bdd4b..6788d122b 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -1,18 +1,3 @@ -testthat::test_that("`[.` returns empty teal_data for names not in teal_data", { - data <- teal_data(x = 1, a = 2) - testthat::expect_warning( - testthat::expect_equal(data["y"], teal_data()), - "None of `names` elements exist in `teal_data`. Returning empty `teal_data`." - ) -}) - -testthat::test_that("`[.` returns limited teal_data for some names not in teal_data", { - data <- teal_data(x = 1, a = 2) - testthat::expect_warning( - testthat::expect_equal(data[c("y", "a")], data["a"]), - "Some elements of `names` do not exist in `teal_data`. Skipping those: y." - ) -}) testthat::test_that("`[.` handles empty names", { data <- teal_data(x = 1, a = 2) From 1c2f05a723bce116c7dc1160c0b80b7a020e8ba5 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:01:01 +0000 Subject: [PATCH 19/37] [skip style] [skip vbump] Restyle files --- tests/testthat/test-extract.R | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 6788d122b..9d7779a51 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -1,4 +1,3 @@ - testthat::test_that("`[.` handles empty names", { data <- teal_data(x = 1, a = 2) testthat::expect_warning( From 5b1e1a8760eb31f6b8bea0887f6768b6dc1ad84c Mon Sep 17 00:00:00 2001 From: m7pr Date: Thu, 31 Oct 2024 15:12:11 +0100 Subject: [PATCH 20/37] simplify teal_code extract as it reuses qenv extract --- R/teal_data-extract.R | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index a987c2558..e737044ff 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -24,26 +24,7 @@ #' #' @export `[.teal_data` <- function(x, names) { - checkmate::assert_character(names) - possible_names <- ls(get_env(x)) - names_warn <- setdiff(names, possible_names) - names <- intersect(names, possible_names) - if (!length(names)) { - warning("None of `names` elements exist in `teal_data`. Returning empty `teal_data`.") - return(teal_data()) - } - - if (length(names_warn)) { - warning( - sprintf( - "Some elements of `names` do not exist in `teal_data`. Skipping those: %s.", - paste(names_warn, collapse = ", ") - ) - ) - } - x <- NextMethod("`[`", x) # takes 'names' from function's environment x@join_keys <- x@join_keys[names] - x } From a93b2d45551864852dffd5a1e9e6df8d22ea85ef Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 6 Nov 2024 09:39:31 +0100 Subject: [PATCH 21/37] add .raw_data to names that need to be extracted --- R/teal_data-extract.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index e737044ff..5cffdaa72 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -24,7 +24,9 @@ #' #' @export `[.teal_data` <- function(x, names) { + names_no_raw <- names + names <- c(names, ".raw_data") x <- NextMethod("`[`", x) # takes 'names' from function's environment - x@join_keys <- x@join_keys[names] + x@join_keys <- x@join_keys[names_no_raw] x } From a0d4890b7816b614ba353be8db2175ccfb6c39ed Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 6 Nov 2024 10:17:54 +0100 Subject: [PATCH 22/37] update teal.data constructor after changes in the code structure in qenv in teal.code --- R/teal_data-class.R | 50 +++++++++++++++++++++++++++++++++--------- man/teal_data-class.Rd | 25 +++++++++++++-------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/R/teal_data-class.R b/R/teal_data-class.R index 3015797b9..f62c196b5 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -17,13 +17,10 @@ setOldClass("join_keys") #' @slot env (`environment`) environment containing data sets and possibly auxiliary variables. #' Access variables with [get_var()] or [`[[`]. #' No setter provided. Evaluate code to add variables into `@env`. -#' @slot code (`character`) vector representing code necessary to reproduce the contents of `@env`. +#' @slot code (`list` of `character`) representing code necessary to reproduce the contents of `@env`. #' Access with [get_code()]. #' No setter provided. Evaluate code to append code to the slot. -#' @slot id (`integer`) random identifier assigned to each element of `@code`. Used internally. -#' @slot warnings (`character`) vector of warnings raised when evaluating code. -#' Access with [get_warnings()]. -#' @slot messages (`character`) vector of messages raised when evaluating code. +#' Read more in Code section. #' @slot join_keys (`join_keys`) object specifying joining keys for data sets in `@env`. #' Access or modify with [join_keys()]. #' @slot datanames (`character`) vector of names of data sets in `@env`. @@ -32,6 +29,15 @@ setOldClass("join_keys") #' @slot verified (`logical(1)`) flag signifying that code in `@code` has been proven to yield contents of `@env`. #' Used internally. See [`verify()`] for more details. #' +#' @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) +#' #' @import teal.code #' @keywords internal setClass( @@ -77,20 +83,44 @@ new_teal_data <- function(data, } verified <- (length(code) == 0L && length(data) == 0L) - id <- sample.int(.Machine$integer.max, size = length(code)) - new_env <- rlang::env_clone(list2env(data), parent = parent.env(.GlobalEnv)) lockEnvironment(new_env, bindings = TRUE) + # GO WITH BELOW OR + # apply eval_code(code) in here + # but eval_code() works on an object and teal_data/qenv does not exist YET + attr(code, "id") <- sample.int(.Machine$integer.max, 1) + if (length(code)) { + split_code <- teal.code:::split_code(code) + split_code <- lapply(split_code, function(current_code) { + attr(current_code, "id") <- sample.int(.Machine$integer.max, 1) + current_call <- parse(text = trimws(current_code), keep.source = TRUE) + pd <- utils::getParseData(current_call) + pd <- teal.code:::normalize_pd(pd) + call_pd <- teal.code:::extract_calls(pd)[[1]] + + attr(current_code, "dependency") <- + c(teal.code:::extract_side_effects(call_pd), teal.code:::extract_occurrence(call_pd)) + current_code + }) + } else { + split_code <- list(character(0)) + # TODO: do we assign + # attr(split_code[[1]], "id") <- sample.int() ? + # TODO: do we need + # attr(split_code[[1]], "dependency") <- cahracter(0) ? + } + + # TODO: + # warnings are empty and messages are empty + # should we reconsider `@verified` field and should we reconsider eval_code in here? + datanames <- .get_sorted_datanames(datanames = datanames, join_keys = join_keys, env = new_env) methods::new( "teal_data", env = new_env, code = code, - warnings = rep("", length(code)), - messages = rep("", length(code)), - id = id, join_keys = join_keys, datanames = datanames, verified = verified diff --git a/man/teal_data-class.Rd b/man/teal_data-class.Rd index ef1c1decb..3d4f754d8 100644 --- a/man/teal_data-class.Rd +++ b/man/teal_data-class.Rd @@ -22,16 +22,10 @@ If errors are raised, a \code{qenv.error} object is returned. Access variables with \code{\link[=get_var]{get_var()}} or [\code{[[}]. No setter provided. Evaluate code to add variables into \verb{@env}.} -\item{\code{code}}{(\code{character}) vector representing code necessary to reproduce the contents of \verb{@env}. +\item{\code{code}}{(\code{list} of \code{character}) representing code necessary to reproduce the contents of \verb{@env}. Access with \code{\link[=get_code]{get_code()}}. -No setter provided. Evaluate code to append code to the slot.} - -\item{\code{id}}{(\code{integer}) random identifier assigned to each element of \verb{@code}. Used internally.} - -\item{\code{warnings}}{(\code{character}) vector of warnings raised when evaluating code. -Access with \code{\link[=get_warnings]{get_warnings()}}.} - -\item{\code{messages}}{(\code{character}) vector of messages raised when evaluating code.} +No setter provided. Evaluate code to append code to the slot. +Read more in Code section.} \item{\code{join_keys}}{(\code{join_keys}) object specifying joining keys for data sets in \verb{@env}. Access or modify with \code{\link[=join_keys]{join_keys()}}.} @@ -44,4 +38,17 @@ Access or modify with \code{\link[=datanames]{datanames()}}.} Used internally. See \code{\link[=verify]{verify()}} for more details.} }} +\section{Code}{ + + +Each code element is a character representing one call. Each element has possible attributes: +\itemize{ +\item \code{warnings} (\code{character}) the warnings output when evaluating the code element +\item \code{messages} (\code{character}) the messages output when evaluating the code element +\item \verb{id (}integer`) random identifier of the code element to make sure uniqueness when joining +\item \code{dependency} (\code{character}) names of objects that appear in this call and gets affected by this call, +separated by \verb{<-} (objects on LHS of \verb{<-} are affected by this line, and objects on RHS are affecting this line) +} +} + \keyword{internal} From ee056355e7e64152e842a246442c8613b4eedeb5 Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 6 Nov 2024 11:11:02 +0100 Subject: [PATCH 23/37] use getFromNamespace instead of teal.code::: --- R/teal_data-class.R | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/R/teal_data-class.R b/R/teal_data-class.R index f62c196b5..fda891851 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -91,16 +91,21 @@ new_teal_data <- function(data, # but eval_code() works on an object and teal_data/qenv does not exist YET attr(code, "id") <- sample.int(.Machine$integer.max, 1) if (length(code)) { - split_code <- teal.code:::split_code(code) + split_code <- getFromNamespace("split_code", "teal.code") + extract_calls <- getFromNamespace("extract_calls", "teal.code") + extract_side_effects <- getFromNamespace("extract_side_effects", "teal.code") + extract_occurrence <- getFromNamespace("extract_occurrence", "teal.code") + + split_code <- split_code(code) split_code <- lapply(split_code, function(current_code) { attr(current_code, "id") <- sample.int(.Machine$integer.max, 1) current_call <- parse(text = trimws(current_code), keep.source = TRUE) pd <- utils::getParseData(current_call) pd <- teal.code:::normalize_pd(pd) - call_pd <- teal.code:::extract_calls(pd)[[1]] + call_pd <- extract_calls(pd)[[1]] attr(current_code, "dependency") <- - c(teal.code:::extract_side_effects(call_pd), teal.code:::extract_occurrence(call_pd)) + c(extract_side_effects(call_pd), extract_occurrence(call_pd)) current_code }) } else { From 84f8ceb6e22fda0761d3245039f66b67c52d82b1 Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 6 Nov 2024 11:48:20 +0100 Subject: [PATCH 24/37] use code2list wrapper from teal.code --- R/teal_data-class.R | 36 +----------------------------------- R/zzz.R | 1 + 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/R/teal_data-class.R b/R/teal_data-class.R index fda891851..19a68c096 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -86,46 +86,12 @@ new_teal_data <- function(data, new_env <- rlang::env_clone(list2env(data), parent = parent.env(.GlobalEnv)) lockEnvironment(new_env, bindings = TRUE) - # GO WITH BELOW OR - # apply eval_code(code) in here - # but eval_code() works on an object and teal_data/qenv does not exist YET - attr(code, "id") <- sample.int(.Machine$integer.max, 1) - if (length(code)) { - split_code <- getFromNamespace("split_code", "teal.code") - extract_calls <- getFromNamespace("extract_calls", "teal.code") - extract_side_effects <- getFromNamespace("extract_side_effects", "teal.code") - extract_occurrence <- getFromNamespace("extract_occurrence", "teal.code") - - split_code <- split_code(code) - split_code <- lapply(split_code, function(current_code) { - attr(current_code, "id") <- sample.int(.Machine$integer.max, 1) - current_call <- parse(text = trimws(current_code), keep.source = TRUE) - pd <- utils::getParseData(current_call) - pd <- teal.code:::normalize_pd(pd) - call_pd <- extract_calls(pd)[[1]] - - attr(current_code, "dependency") <- - c(extract_side_effects(call_pd), extract_occurrence(call_pd)) - current_code - }) - } else { - split_code <- list(character(0)) - # TODO: do we assign - # attr(split_code[[1]], "id") <- sample.int() ? - # TODO: do we need - # attr(split_code[[1]], "dependency") <- cahracter(0) ? - } - - # TODO: - # warnings are empty and messages are empty - # should we reconsider `@verified` field and should we reconsider eval_code in here? - datanames <- .get_sorted_datanames(datanames = datanames, join_keys = join_keys, env = new_env) methods::new( "teal_data", env = new_env, - code = code, + code = code2list(code), join_keys = join_keys, datanames = datanames, verified = verified diff --git a/R/zzz.R b/R/zzz.R index b1dfb9432..156dd3fdf 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,2 +1,3 @@ # use non-exported function from teal.code lang2calls <- getFromNamespace("lang2calls", "teal.code") +code2list <- getFromNamespace("code2list", "teal.code") From b465322f75dc18bee33d0102078806e6b0644e5e Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 6 Nov 2024 12:12:56 +0100 Subject: [PATCH 25/37] create code2list in teal.daata --- R/teal_data-class.R | 25 +++++++++++++++++++++++++ R/zzz.R | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/R/teal_data-class.R b/R/teal_data-class.R index 19a68c096..4e446f174 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -97,3 +97,28 @@ new_teal_data <- function(data, verified = verified ) } + + +#' Reshape code to the list +#' +#' List will be divided by the calls. Each element of the list contains `id` and `dependency` attributes. +#' +#' @param code `character` with the code. +#' +#' @return list of `character`s of the length equal to the number of calls in `code`. +#' +#' @keywords internal +#' @noRd +code2list <- function(code) { + checkmate::assert_character(code, null.ok = TRUE) + if (length(code)) { + lapply(split_code(code), function(current_code) { + attr(current_code, "id") <- sample.int(.Machine$integer.max, 1) + parsed_code <- parse(text = trimws(current_code), keep.source = TRUE) + attr(current_code, "dependency") <- extract_dependency(parsed_code) + current_code + }) + } else { + list(character(0)) + } +} diff --git a/R/zzz.R b/R/zzz.R index 156dd3fdf..7f78c9dff 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,3 +1,4 @@ # use non-exported function from teal.code lang2calls <- getFromNamespace("lang2calls", "teal.code") -code2list <- getFromNamespace("code2list", "teal.code") +extract_dependency <- getFromNamespace("extract_dependency", "teal.code") +split_code <- getFromNamespace("split_code", "teal.code") From d629a043d0ab882a388d7375c5f2daa93ca27545 Mon Sep 17 00:00:00 2001 From: m7pr Date: Wed, 6 Nov 2024 12:20:14 +0100 Subject: [PATCH 26/37] revert names to not add .raw_data --- R/teal_data-extract.R | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 5cffdaa72..e737044ff 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -24,9 +24,7 @@ #' #' @export `[.teal_data` <- function(x, names) { - names_no_raw <- names - names <- c(names, ".raw_data") x <- NextMethod("`[`", x) # takes 'names' from function's environment - x@join_keys <- x@join_keys[names_no_raw] + x@join_keys <- x@join_keys[names] x } From a8dd885b05ab929712dc7b4290f7f6f49c9e620b Mon Sep 17 00:00:00 2001 From: m7pr Date: Fri, 8 Nov 2024 09:57:45 +0100 Subject: [PATCH 27/37] fix tests and improve [.teal_data --- R/teal_data-extract.R | 3 ++- tests/testthat/test-extract.R | 16 ++++++++++------ tests/testthat/test-teal_data.R | 13 +++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index e737044ff..fa3175ac7 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -24,7 +24,8 @@ #' #' @export `[.teal_data` <- function(x, names) { - x <- NextMethod("`[`", x) # takes 'names' from function's environment + x <- NextMethod("`[`", x, check_names = FALSE) # takes 'names' from function's environment + if (inherits(x, "qenv")) return(teal_data()) # all 'names' not in object x@join_keys <- x@join_keys[names] x } diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 9d7779a51..9e46d6553 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -14,22 +14,26 @@ testthat::test_that("`[.` handles names as NA_character_", { testthat::test_that("`[.` throws warning if names is NULL", { data <- teal_data(x = 1, a = 2) - testthat::expect_error(data[NULL], "Assertion on 'names' failed: Must be of type 'character', not 'NULL'.") + testthat::expect_error( + data[NULL], + "Assertion on 'names' failed: Must inherit from class 'character', but has class 'NULL'." + ) }) testthat::test_that("`[.` thorws warnings if names is numeric", { data <- teal_data(x = 1, a = 2) - testthat::expect_error(data[1], "Assertion on 'names' failed: Must be of type 'character', not 'double'.") + testthat::expect_error( + data[1], + "Assertion on 'names' failed: Must inherit from class 'character', but has class 'numeric'." + ) }) testthat::test_that("`[.` returns limited join_keys", { data <- teal_data(a = 1, b = 2) join_keys(data) <- join_keys(join_key("a", "b", "x")) - empty_join_keys <- join_keys() - attr(empty_join_keys, "names") <- character(0) testthat::expect_equal( - join_keys(data["a"]), # By default named list || names() is character(0) - empty_join_keys # By default unnamed list || names() is NULL + join_keys(data["a"]), + join_keys() ) }) diff --git a/tests/testthat/test-teal_data.R b/tests/testthat/test-teal_data.R index 8391f72e2..15a3214ad 100644 --- a/tests/testthat/test-teal_data.R +++ b/tests/testthat/test-teal_data.R @@ -2,11 +2,8 @@ testthat::test_that("teal_data allows to initialize empty teal_data object", { testthat::expect_s4_class(teal_data(), "teal_data") }) -testthat::test_that("empty teal_data returns empty code, id, wartnings and messages and verified=TRUE", { - testthat::expect_identical(teal_data()@code, character(0)) - testthat::expect_identical(teal_data()@id, integer(0)) - testthat::expect_identical(teal_data()@messages, character(0)) - testthat::expect_identical(teal_data()@warnings, character(0)) +testthat::test_that("empty teal_data returns empty code and verified=TRUE", { + testthat::expect_identical(teal_data()@code, list(character(0))) testthat::expect_identical(teal_data()@verified, TRUE) }) @@ -79,16 +76,16 @@ testthat::test_that("teal_data accepts code as language", { testthat::test_that("teal_data code unfolds code-block wrapped in '{'", { testthat::expect_identical( - teal_data(iris1 = iris, code = quote({ + get_code(teal_data(iris1 = iris, code = quote({ iris1 <- iris - }))@code, + }))), "iris1 <- iris" ) }) testthat::test_that("teal_data code is concatenated into single string", { testthat::expect_identical( - teal_data(iris1 = iris, code = c("iris1 <- iris", "iris2 <- iris1"))@code, + get_code(teal_data(iris1 = iris, code = c("iris1 <- iris", "iris2 <- iris1"))), "iris1 <- iris\niris2 <- iris1" ) }) From 1121dc0b91dee524619eb8638b534de248f02b73 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 08:59:46 +0000 Subject: [PATCH 28/37] [skip style] [skip vbump] Restyle files --- R/teal_data-extract.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index fa3175ac7..792c5ca04 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -25,7 +25,9 @@ #' @export `[.teal_data` <- function(x, names) { x <- NextMethod("`[`", x, check_names = FALSE) # takes 'names' from function's environment - if (inherits(x, "qenv")) return(teal_data()) # all 'names' not in object + if (inherits(x, "qenv")) { + return(teal_data()) + } # all 'names' not in object x@join_keys <- x@join_keys[names] x } From 9aa4d94278b41459478a18841fbf289108ec31bd Mon Sep 17 00:00:00 2001 From: m7pr Date: Fri, 8 Nov 2024 10:09:23 +0100 Subject: [PATCH 29/37] Empty-Commit From 0669e3e8226f3317dcaf51829fd04d70769ee096 Mon Sep 17 00:00:00 2001 From: m7pr Date: Fri, 8 Nov 2024 11:05:12 +0100 Subject: [PATCH 30/37] bulletprove teal_data's code2list --- R/teal_data-class.R | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/R/teal_data-class.R b/R/teal_data-class.R index 4e446f174..39253a07b 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -111,7 +111,11 @@ new_teal_data <- function(data, #' @noRd code2list <- function(code) { checkmate::assert_character(code, null.ok = TRUE) - if (length(code)) { + if (length(code) == 0) return(list()) + + parsed_code <- parse(text = code, keep.source = TRUE) + + if (length(parsed_code)) { lapply(split_code(code), function(current_code) { attr(current_code, "id") <- sample.int(.Machine$integer.max, 1) parsed_code <- parse(text = trimws(current_code), keep.source = TRUE) @@ -119,6 +123,9 @@ code2list <- function(code) { current_code }) } else { - list(character(0)) + # empty code like "", 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 + list(code) } } From 98d61949031ecabc967995febda969fc2ae59e70 Mon Sep 17 00:00:00 2001 From: m7pr Date: Fri, 8 Nov 2024 11:06:03 +0100 Subject: [PATCH 31/37] remove trimws --- R/teal_data-class.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/teal_data-class.R b/R/teal_data-class.R index 39253a07b..bc647256d 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -118,7 +118,7 @@ code2list <- function(code) { if (length(parsed_code)) { lapply(split_code(code), function(current_code) { attr(current_code, "id") <- sample.int(.Machine$integer.max, 1) - parsed_code <- parse(text = trimws(current_code), keep.source = TRUE) + parsed_code <- parse(text = current_code, keep.source = TRUE) attr(current_code, "dependency") <- extract_dependency(parsed_code) current_code }) From 2b9da8e089451f3dd59a9d2aa52d3aababe3a261 Mon Sep 17 00:00:00 2001 From: go_gonzo Date: Fri, 8 Nov 2024 13:32:03 +0100 Subject: [PATCH 32/37] postmerge fixes --- R/join_keys-extract.R | 6 +++--- R/teal_data-class.R | 2 +- R/teal_data-get_code.R | 2 +- R/teal_data-names.R | 8 ++++---- man/join_keys.Rd | 6 +++--- man/teal_data-class.Rd | 14 ++------------ tests/testthat/test-teal_data.R | 2 +- tests/testthat/test-verify.R | 2 +- 8 files changed, 16 insertions(+), 26 deletions(-) diff --git a/R/join_keys-extract.R b/R/join_keys-extract.R index 46e2c73b1..a533c5045 100644 --- a/R/join_keys-extract.R +++ b/R/join_keys-extract.R @@ -2,9 +2,9 @@ #' @order 2 #' #' @section Functions: -#' - `x[datanames]`: Returns a subset of the `join_keys` object for -#' given `datanames`, including parent `datanames` and symmetric mirror keys between -#' `datanames` in the result. +#' - `x[names]`: Returns a subset of the `join_keys` object for +#' given `names`, including parent `names` and symmetric mirror keys between +#' `names` in the result. #' - `x[i, j]`: Returns join keys between datasets `i` and `j`, #' including implicit keys inferred from their relationship with a parent. #' diff --git a/R/teal_data-class.R b/R/teal_data-class.R index 460f9b798..85ce9e3bc 100644 --- a/R/teal_data-class.R +++ b/R/teal_data-class.R @@ -18,7 +18,7 @@ setOldClass("join_keys") #' auxiliary variables. #' Access variables with [get()], [`$`], [get_var()] or [`[[`]. #' No setter provided. Evaluate code to add variables into `@.xData`. -#' @slot code (`list` of `character`) representing code necessary to reproduce the contents of `@env`. +#' @slot code (`list` of `character`) representing code necessary to reproduce the contents of `qenv`. #' Access with [get_code()]. #' No setter provided. Evaluate code to append code to the slot. #' @slot join_keys (`join_keys`) object specifying joining keys for data sets in diff --git a/R/teal_data-get_code.R b/R/teal_data-get_code.R index 23002590d..52c237a71 100644 --- a/R/teal_data-get_code.R +++ b/R/teal_data-get_code.R @@ -121,7 +121,7 @@ setMethod("get_code", } if (!is.null(names) && lifecycle::is_present(datanames)) { - stop("Please use either 'names' (recommended) or 'datanames' parameter.") + stop("'names' shouldn't be specified with deprecated 'datanames' parameter.") } checkmate::assert_character(names, min.len = 1L, null.ok = TRUE) diff --git a/R/teal_data-names.R b/R/teal_data-names.R index 32e9d71de..1c28ccd56 100644 --- a/R/teal_data-names.R +++ b/R/teal_data-names.R @@ -24,18 +24,18 @@ names.teal_data <- function(x) { # Sorting from `ls` can be safely done as environments don't have any order # nor support numeric-index subsetting envir <- as.environment(x) - .get_sorted_names(ls(envir = envir), join_keys(x), envir) + .get_sorted_names(names = ls(envir = envir), join_keys = join_keys(x), env = envir) } #' @export length.teal.data <- function(x) length(ls(x)) #' @keywords internal -.get_sorted_names <- function(datanames, join_keys, env) { - child_parent <- sapply(datanames, parent, x = join_keys, USE.NAMES = TRUE, simplify = FALSE) +.get_sorted_names <- function(names, join_keys, env) { + child_parent <- sapply(names, parent, x = join_keys, USE.NAMES = TRUE, simplify = FALSE) union( intersect(unlist(topological_sort(child_parent)), ls(env, all.names = TRUE)), - datanames + names ) } diff --git a/man/join_keys.Rd b/man/join_keys.Rd index bc1e9a15f..df13905bf 100644 --- a/man/join_keys.Rd +++ b/man/join_keys.Rd @@ -101,9 +101,9 @@ in a parent-child relationship and the mapping is automatically mirrored between \section{Functions}{ \itemize{ -\item \code{x[datanames]}: Returns a subset of the \code{join_keys} object for -given \code{datanames}, including parent \code{datanames} and symmetric mirror keys between -\code{datanames} in the result. +\item \code{x[names]}: Returns a subset of the \code{join_keys} object for +given \code{names}, including parent \code{names} and symmetric mirror keys between +\code{names} in the result. \item \code{x[i, j]}: Returns join keys between datasets \code{i} and \code{j}, including implicit keys inferred from their relationship with a parent. } diff --git a/man/teal_data-class.Rd b/man/teal_data-class.Rd index ce613ff60..86da5a14c 100644 --- a/man/teal_data-class.Rd +++ b/man/teal_data-class.Rd @@ -23,19 +23,9 @@ auxiliary variables. Access variables with \code{\link[=get]{get()}}, \code{\link{$}}, \code{\link[=get_var]{get_var()}} or [\code{[[}]. No setter provided. Evaluate code to add variables into \verb{@.xData}.} -\item{\code{code}}{(\code{character}) vector representing code necessary to reproduce the -contents of \verb{@.xData}. +\item{\code{code}}{(\code{list} of \code{character}) representing code necessary to reproduce the contents of \code{qenv}. Access with \code{\link[=get_code]{get_code()}}. -No setter provided. Evaluate code to append code to the slot. -Read more in Code section.} - -\item{\code{id}}{(\code{integer}) random identifier assigned to each element of \verb{@code}. -Used internally.} - -\item{\code{warnings}}{(\code{character}) vector of warnings raised when evaluating code. -Access with \code{\link[=get_warnings]{get_warnings()}}.} - -\item{\code{messages}}{(\code{character}) vector of messages raised when evaluating code.} +No setter provided. Evaluate code to append code to the slot.} \item{\code{join_keys}}{(\code{join_keys}) object specifying joining keys for data sets in \verb{@.xData}. diff --git a/tests/testthat/test-teal_data.R b/tests/testthat/test-teal_data.R index 46439c7d8..268bf11c3 100644 --- a/tests/testthat/test-teal_data.R +++ b/tests/testthat/test-teal_data.R @@ -3,7 +3,7 @@ testthat::test_that("teal_data allows to initialize empty teal_data object", { }) testthat::test_that("empty teal_data returns empty code and verified=TRUE", { - testthat::expect_identical(teal_data()@code, list(character(0))) + testthat::expect_identical(teal_data()@code, list()) testthat::expect_identical(teal_data()@verified, TRUE) }) diff --git a/tests/testthat/test-verify.R b/tests/testthat/test-verify.R index 4e15fb696..f80537895 100644 --- a/tests/testthat/test-verify.R +++ b/tests/testthat/test-verify.R @@ -20,7 +20,7 @@ testthat::test_that("verify returns the same object with changed @verified field testthat::expect_identical(teal.code::get_env(tdata2_ver), teal.code::get_env(tdata2)) }) -testthat::test_that("verify raises error if @code does not restore objects in @env", { +testthat::test_that("verify raises error if @code does not restore objects in @.xData", { tdata3 <- teal_data(x1 = iris, code = "x1 = mtcars") testthat::expect_error(verify(tdata3), "Code verification failed.") From 5c3bb7c4886ee681423c543704ad92f324f21c6e Mon Sep 17 00:00:00 2001 From: m7pr Date: Fri, 8 Nov 2024 14:18:23 +0100 Subject: [PATCH 33/37] O M G --- R/teal_data-extract.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 792c5ca04..7d062e862 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -25,9 +25,9 @@ #' @export `[.teal_data` <- function(x, names) { x <- NextMethod("`[`", x, check_names = FALSE) # takes 'names' from function's environment - if (inherits(x, "qenv")) { + if (!inherits(x, "teal_data")) { return(teal_data()) - } # all 'names' not in object + } # all 'names' not in object, and teal.code::`[.qenv` returns qenv() x@join_keys <- x@join_keys[names] x } From 4900c3a9f26f20c5e8ba0d23ac4057940550866b Mon Sep 17 00:00:00 2001 From: m7pr Date: Fri, 8 Nov 2024 16:23:48 +0100 Subject: [PATCH 34/37] fix last test --- tests/testthat/test-extract.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 9e46d6553..aea512da2 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -32,8 +32,10 @@ testthat::test_that("`[.` returns limited join_keys", { data <- teal_data(a = 1, b = 2) join_keys(data) <- join_keys(join_key("a", "b", "x")) + empty_join_keys <- join_keys() + attr(empty_join_keys, "names") <- character(0) testthat::expect_equal( join_keys(data["a"]), - join_keys() + empty_join_keys ) }) From 0c5e6772d62150a10c39f919b2155b8c4cdcc780 Mon Sep 17 00:00:00 2001 From: go_gonzo Date: Fri, 8 Nov 2024 16:33:18 +0100 Subject: [PATCH 35/37] fix --- R/teal_data-extract.R | 3 --- tests/testthat/test-extract.R | 17 +++++------------ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 7d062e862..369257427 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -25,9 +25,6 @@ #' @export `[.teal_data` <- function(x, names) { x <- NextMethod("`[`", x, check_names = FALSE) # takes 'names' from function's environment - if (!inherits(x, "teal_data")) { - return(teal_data()) - } # all 'names' not in object, and teal.code::`[.qenv` returns qenv() x@join_keys <- x@join_keys[names] x } diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index aea512da2..6c67a3891 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -5,18 +5,16 @@ testthat::test_that("`[.` handles empty names", { ) }) -testthat::test_that("`[.` handles names as NA_character_", { +testthat::test_that("`[.` fails with names being NA_character_", { data <- teal_data(x = 1, a = 2) - testthat::expect_warning( - testthat::expect_equal(data[NA_character_], teal_data()) - ) + testthat::expect_error(data[NA_character_]) }) testthat::test_that("`[.` throws warning if names is NULL", { data <- teal_data(x = 1, a = 2) testthat::expect_error( data[NULL], - "Assertion on 'names' failed: Must inherit from class 'character', but has class 'NULL'." + "Assertion on 'names' failed: Must be of type 'character', not 'NULL'." ) }) @@ -24,7 +22,7 @@ testthat::test_that("`[.` thorws warnings if names is numeric", { data <- teal_data(x = 1, a = 2) testthat::expect_error( data[1], - "Assertion on 'names' failed: Must inherit from class 'character', but has class 'numeric'." + "Assertion on 'names' failed: Must be of type 'character', not 'double'." ) }) @@ -32,10 +30,5 @@ testthat::test_that("`[.` returns limited join_keys", { data <- teal_data(a = 1, b = 2) join_keys(data) <- join_keys(join_key("a", "b", "x")) - empty_join_keys <- join_keys() - attr(empty_join_keys, "names") <- character(0) - testthat::expect_equal( - join_keys(data["a"]), - empty_join_keys - ) + testthat::expect_length(join_keys(data["a"]), 0) }) From 159b6dde86d958d9f64678f30d227bf3b9451a26 Mon Sep 17 00:00:00 2001 From: go_gonzo Date: Fri, 8 Nov 2024 18:09:35 +0100 Subject: [PATCH 36/37] fix tests --- tests/testthat/test-extract.R | 42 ++++++++++++----------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/tests/testthat/test-extract.R b/tests/testthat/test-extract.R index 6c67a3891..0541b9685 100644 --- a/tests/testthat/test-extract.R +++ b/tests/testthat/test-extract.R @@ -1,34 +1,20 @@ -testthat::test_that("`[.` handles empty names", { - data <- teal_data(x = 1, a = 2) - testthat::expect_warning( - testthat::expect_equal(data[character(0)], teal_data()) - ) -}) - -testthat::test_that("`[.` fails with names being NA_character_", { - data <- teal_data(x = 1, a = 2) - testthat::expect_error(data[NA_character_]) +testthat::test_that("`[.` subsets join_keys also", { + data <- teal_data(a = 1, b = 2) + join_keys(data) <- join_keys(join_key("a", "b", "x")) + testthat::expect_length(join_keys(data["a"]), 0) }) -testthat::test_that("`[.` throws warning if names is NULL", { - data <- teal_data(x = 1, a = 2) - testthat::expect_error( - data[NULL], - "Assertion on 'names' failed: Must be of type 'character', not 'NULL'." - ) +testthat::test_that("`[.` preserves @verified field", { + testthat::expect_false(teal_data(a = 1, b = 2)["a"]@verified) + testthat::expect_true(within(teal_data(), a <- 1)["a"]@verified) }) -testthat::test_that("`[.` thorws warnings if names is numeric", { - data <- teal_data(x = 1, a = 2) - testthat::expect_error( - data[1], - "Assertion on 'names' failed: Must be of type 'character', not 'double'." +testthat::test_that("`[.` warns and subsets if names are present in code", { + data <- teal_data(a = 1, b = 2, code = "a <- 1; b <- 2; c <- 3; d <- 4") + testthat::expect_warning( + subset <- data[c("a", "c", "d")], + "Some 'names' do not exist in the environment of the 'teal_data'. Skipping those: c, d." ) -}) - -testthat::test_that("`[.` returns limited join_keys", { - data <- teal_data(a = 1, b = 2) - - join_keys(data) <- join_keys(join_key("a", "b", "x")) - testthat::expect_length(join_keys(data["a"]), 0) + testthat::expect_identical(subset@code, data@code[c(1, 3, 4)]) + testthat::expect_identical(as.list(subset), as.list(data)[1]) }) From a24bac3c1f4e1132a8eb91be2f690dfd938d0aac Mon Sep 17 00:00:00 2001 From: go_gonzo Date: Fri, 8 Nov 2024 18:51:53 +0100 Subject: [PATCH 37/37] fix for unverified --- R/teal_data-extract.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/teal_data-extract.R b/R/teal_data-extract.R index 369257427..dfa719a5c 100644 --- a/R/teal_data-extract.R +++ b/R/teal_data-extract.R @@ -24,7 +24,7 @@ #' #' @export `[.teal_data` <- function(x, names) { - x <- NextMethod("`[`", x, check_names = FALSE) # takes 'names' from function's environment + x <- NextMethod("`[`", x, check_code_names = x@verified) # unverified doesn't need warning for code inconsistency x@join_keys <- x@join_keys[names] x }