From 3edecb9e4396320e70c10b0d014dc1d99e49ccc3 Mon Sep 17 00:00:00 2001 From: m7pr Date: Thu, 27 Nov 2025 15:40:17 +0100 Subject: [PATCH 1/9] fix pipe --- R/call_utils.R | 42 ++++++++++++++++++++++++++++++++++++++++++ R/merge_datasets.R | 6 ++++++ 2 files changed, 48 insertions(+) diff --git a/R/call_utils.R b/R/call_utils.R index 8811c04a0..04573fde9 100644 --- a/R/call_utils.R +++ b/R/call_utils.R @@ -374,3 +374,45 @@ calls_combine_by <- function(operator, calls) { f = function(x, y) call(operator, x, y) ) } + +#' Check if a call or list of calls uses the pipe operator (%>%) +#' +#' Recursively searches through a call or list of calls to determine +#' if the pipe operator `%>%` is used anywhere. +#' +#' @param x (`call`, `name`, or `list` of calls) The call(s) to check. +#' +#' @return `logical(1)` `TRUE` if `%>%` is found, `FALSE` otherwise. +#' +#' @keywords internal +#' +call_uses_pipe <- function(x) { + if (is.null(x)) { + return(FALSE) + } + + if (is.call(x)) { + # Check if this call is the pipe operator + # Handle both quote(`%>%`) and as.name("%>%") cases + pipe_symbol <- quote(`%>%`) + pipe_name <- as.name("%>%") + if (identical(x[[1]], pipe_symbol) || identical(x[[1]], pipe_name)) { + return(TRUE) + } + # Recursively check all arguments (skip first element which is the function name) + if (length(x) > 1) { + return(any(vapply(x[-1], call_uses_pipe, logical(1), USE.NAMES = FALSE))) + } + return(FALSE) + } + + if (is.list(x)) { + # Check all elements in the list + if (length(x) > 0) { + return(any(vapply(x, call_uses_pipe, logical(1), USE.NAMES = FALSE))) + } + return(FALSE) + } + + FALSE +} \ No newline at end of file diff --git a/R/merge_datasets.R b/R/merge_datasets.R index d19e19745..168744575 100644 --- a/R/merge_datasets.R +++ b/R/merge_datasets.R @@ -154,6 +154,12 @@ merge_datasets <- function(selector_list, datasets, join_keys, merge_function = all_calls_expression <- c(dplyr_calls, anl_merge_calls, anl_relabel_call) + # Ensure dplyr is loaded if any of the generated calls use the pipe operator + if (call_uses_pipe(all_calls_expression)) { + library_dplyr_call <- call("library", "dplyr") + all_calls_expression <- c(list(library_dplyr_call), all_calls_expression) + } + # keys in each merged_selector_list element should be identical # so take first one keys <- merged_selector_list[[1]]$keys From f9e8f77cef197ddb114738f36cbb23fb8275ee93 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:38:07 +0000 Subject: [PATCH 2/9] [skip style] [skip vbump] Restyle files --- R/call_utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/call_utils.R b/R/call_utils.R index 04573fde9..5044724f6 100644 --- a/R/call_utils.R +++ b/R/call_utils.R @@ -415,4 +415,4 @@ call_uses_pipe <- function(x) { } FALSE -} \ No newline at end of file +} From 6dfba22c09a1bda5d07bca7b6996024348672c25 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:41:05 +0000 Subject: [PATCH 3/9] [skip roxygen] [skip vbump] Roxygen Man Pages Auto Update --- DESCRIPTION | 2 +- man/call_uses_pipe.Rd | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 man/call_uses_pipe.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 6d5247c24..f1f60a1d8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -58,4 +58,4 @@ Encoding: UTF-8 Language: en-US LazyData: true Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 diff --git a/man/call_uses_pipe.Rd b/man/call_uses_pipe.Rd new file mode 100644 index 000000000..255a7f959 --- /dev/null +++ b/man/call_uses_pipe.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/call_utils.R +\name{call_uses_pipe} +\alias{call_uses_pipe} +\title{Check if a call or list of calls uses the pipe operator (\%>\%)} +\usage{ +call_uses_pipe(x) +} +\arguments{ +\item{x}{(\code{call}, \code{name}, or \code{list} of calls) The call(s) to check.} +} +\value{ +\code{logical(1)} \code{TRUE} if \verb{\%>\%} is found, \code{FALSE} otherwise. +} +\description{ +Recursively searches through a call or list of calls to determine +if the pipe operator \verb{\%>\%} is used anywhere. +} +\keyword{internal} From 8566bfb0b4b08063d7e771d389c6ca8c4a613091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Revilla=20Sancho?= Date: Mon, 1 Dec 2025 12:29:11 +0100 Subject: [PATCH 4/9] Simplify the function --- R/call_utils.R | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/R/call_utils.R b/R/call_utils.R index 5044724f6..d1b933bfb 100644 --- a/R/call_utils.R +++ b/R/call_utils.R @@ -387,31 +387,20 @@ calls_combine_by <- function(operator, calls) { #' @keywords internal #' call_uses_pipe <- function(x) { - if (is.null(x)) { - return(FALSE) - } if (is.call(x)) { - # Check if this call is the pipe operator + # Check if there is the pipe operator # Handle both quote(`%>%`) and as.name("%>%") cases - pipe_symbol <- quote(`%>%`) - pipe_name <- as.name("%>%") - if (identical(x[[1]], pipe_symbol) || identical(x[[1]], pipe_name)) { - return(TRUE) - } - # Recursively check all arguments (skip first element which is the function name) - if (length(x) > 1) { - return(any(vapply(x[-1], call_uses_pipe, logical(1), USE.NAMES = FALSE))) - } - return(FALSE) + return(any(grepl("%>%", x, fixed = TRUE))) } - if (is.list(x)) { + if (is.list(x) && length(x)) { # Check all elements in the list - if (length(x) > 0) { - return(any(vapply(x, call_uses_pipe, logical(1), USE.NAMES = FALSE))) + for (call_x in x) { + if (call_uses_pipe(call_x)) { + return(TRUE) + } } - return(FALSE) } FALSE From eddd1309107aea22b5272bd190c39595ac3b0f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Revilla=20Sancho?= Date: Mon, 1 Dec 2025 12:29:23 +0100 Subject: [PATCH 5/9] Change package added --- R/merge_datasets.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/merge_datasets.R b/R/merge_datasets.R index 168744575..e80dd7a97 100644 --- a/R/merge_datasets.R +++ b/R/merge_datasets.R @@ -156,7 +156,7 @@ merge_datasets <- function(selector_list, datasets, join_keys, merge_function = # Ensure dplyr is loaded if any of the generated calls use the pipe operator if (call_uses_pipe(all_calls_expression)) { - library_dplyr_call <- call("library", "dplyr") + library_dplyr_call <- call("library", as.name("magrittr")) all_calls_expression <- c(list(library_dplyr_call), all_calls_expression) } From 06a3310a480d004b50ce67d20fd3efdba90dd7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Revilla=20Sancho?= Date: Mon, 1 Dec 2025 12:41:08 +0100 Subject: [PATCH 6/9] Fix tests to accomodate to the new expression at the beginning. --- tests/testthat/test-dplyr_call_examples.R | 1 + tests/testthat/test-merge_expression_srv.R | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-dplyr_call_examples.R b/tests/testthat/test-dplyr_call_examples.R index be0405162..cca037f81 100644 --- a/tests/testthat/test-dplyr_call_examples.R +++ b/tests/testthat/test-dplyr_call_examples.R @@ -3372,6 +3372,7 @@ testthat::test_that("Universal example", { paste(merged_datasets$expr), paste( c( + "library(magrittr)", "ANL_1 <- X %>% dplyr::select(A, B, D, E)", "ANL_2 <- Y %>% dplyr::select(A, B, C, G) %>% dplyr::rename(y.G = G)", "ANL_3 <- Z %>% dplyr::select(D, C, F, G) %>% dplyr::rename(z.G = G)", diff --git a/tests/testthat/test-merge_expression_srv.R b/tests/testthat/test-merge_expression_srv.R index 3d8101aed..caa3f3b14 100644 --- a/tests/testthat/test-merge_expression_srv.R +++ b/tests/testthat/test-merge_expression_srv.R @@ -208,9 +208,10 @@ testthat::test_that("merge_expression_srv returns merge expression when passing args = list(selector_list = selector_list, datasets = data_list, join_keys = join_keys), expr = { testthat::expect_true(inherits(session$returned()$expr, "list")) - testthat::expect_true(inherits(session$returned()$expr[[1]], "<-")) + testthat::expect_true(inherits(session$returned()$expr[[2]], "<-")) testthat::expect_identical( c( + "library(magrittr)", "ANL_1 <- ADSL %>% dplyr::select(STUDYID, USUBJID, AGE)", "ANL_2 <- ADLB %>% dplyr::select(STUDYID, USUBJID, AVAL, CHG)", "ANL <- ANL_1", From cd0ba2b938ae6854e301ca1cf66940ffc8b9dd9d Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 11:51:27 +0000 Subject: [PATCH 7/9] [skip style] [skip vbump] Restyle files --- R/call_utils.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/call_utils.R b/R/call_utils.R index d1b933bfb..66fe96c25 100644 --- a/R/call_utils.R +++ b/R/call_utils.R @@ -387,7 +387,6 @@ calls_combine_by <- function(operator, calls) { #' @keywords internal #' call_uses_pipe <- function(x) { - if (is.call(x)) { # Check if there is the pipe operator # Handle both quote(`%>%`) and as.name("%>%") cases From 294aa7a477d7eac110f1cf032c4cfd96d28ba28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Revilla=20Sancho?= Date: Mon, 1 Dec 2025 15:03:25 +0100 Subject: [PATCH 8/9] Rename function --- R/call_utils.R | 4 ++-- R/merge_datasets.R | 2 +- man/{call_uses_pipe.Rd => call_uses_magrittr_pipe.Rd} | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename man/{call_uses_pipe.Rd => call_uses_magrittr_pipe.Rd} (85%) diff --git a/R/call_utils.R b/R/call_utils.R index d1b933bfb..ac24db323 100644 --- a/R/call_utils.R +++ b/R/call_utils.R @@ -386,7 +386,7 @@ calls_combine_by <- function(operator, calls) { #' #' @keywords internal #' -call_uses_pipe <- function(x) { +call_uses_magrittr_pipe <- function(x) { if (is.call(x)) { # Check if there is the pipe operator @@ -397,7 +397,7 @@ call_uses_pipe <- function(x) { if (is.list(x) && length(x)) { # Check all elements in the list for (call_x in x) { - if (call_uses_pipe(call_x)) { + if (Recall(call_x)) { return(TRUE) } } diff --git a/R/merge_datasets.R b/R/merge_datasets.R index e80dd7a97..2b4752a5d 100644 --- a/R/merge_datasets.R +++ b/R/merge_datasets.R @@ -155,7 +155,7 @@ merge_datasets <- function(selector_list, datasets, join_keys, merge_function = all_calls_expression <- c(dplyr_calls, anl_merge_calls, anl_relabel_call) # Ensure dplyr is loaded if any of the generated calls use the pipe operator - if (call_uses_pipe(all_calls_expression)) { + if (call_uses_magrittr_pipe(all_calls_expression)) { library_dplyr_call <- call("library", as.name("magrittr")) all_calls_expression <- c(list(library_dplyr_call), all_calls_expression) } diff --git a/man/call_uses_pipe.Rd b/man/call_uses_magrittr_pipe.Rd similarity index 85% rename from man/call_uses_pipe.Rd rename to man/call_uses_magrittr_pipe.Rd index 255a7f959..33b1b8133 100644 --- a/man/call_uses_pipe.Rd +++ b/man/call_uses_magrittr_pipe.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/call_utils.R -\name{call_uses_pipe} -\alias{call_uses_pipe} +\name{call_uses_magrittr_pipe} +\alias{call_uses_magrittr_pipe} \title{Check if a call or list of calls uses the pipe operator (\%>\%)} \usage{ -call_uses_pipe(x) +call_uses_magrittr_pipe(x) } \arguments{ \item{x}{(\code{call}, \code{name}, or \code{list} of calls) The call(s) to check.} From 4846e0d3bfd6f79b5d3538aa7e1ba4e90de23632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Revilla=20Sancho?= Date: Mon, 1 Dec 2025 15:05:21 +0100 Subject: [PATCH 9/9] Styler --- R/call_utils.R | 1 - R/data_extract_filter_module.R | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/R/call_utils.R b/R/call_utils.R index ac24db323..9731e96e7 100644 --- a/R/call_utils.R +++ b/R/call_utils.R @@ -387,7 +387,6 @@ calls_combine_by <- function(operator, calls) { #' @keywords internal #' call_uses_magrittr_pipe <- function(x) { - if (is.call(x)) { # Check if there is the pipe operator # Handle both quote(`%>%`) and as.name("%>%") cases diff --git a/R/data_extract_filter_module.R b/R/data_extract_filter_module.R index d87a6d85a..00bcea1c4 100644 --- a/R/data_extract_filter_module.R +++ b/R/data_extract_filter_module.R @@ -70,7 +70,7 @@ data_extract_filter_srv <- function(id, datasets, filter) { # when the filter is initialized with a delayed spec, the choices and selected are NULL # here delayed are resolved and the values are set up # Begin by resolving delayed choices. - if (inherits(filter$selected, "delayed_choices")) { + if (inherits(filter$selected, "delayed_choices")) { filter$selected <- filter$selected(filter$choices) } teal.widgets::updateOptionalSelectInput( @@ -106,7 +106,6 @@ data_extract_filter_srv <- function(id, datasets, filter) { } else { choices[1] } - } else { choices <- character(0) selected <- character(0)