You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by th...@apache.org on 2023/07/20 11:37:52 UTC
[arrow] branch main updated: GH-36720: [R] stringr modifier functions cannot be called with namespace prefix (#36758)
This is an automated email from the ASF dual-hosted git repository.
thisisnic pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 819b7d5ce7 GH-36720: [R] stringr modifier functions cannot be called with namespace prefix (#36758)
819b7d5ce7 is described below
commit 819b7d5ce7febb4af9ea6f69947244f46403ce53
Author: Nic Crane <th...@gmail.com>
AuthorDate: Thu Jul 20 12:37:44 2023 +0100
GH-36720: [R] stringr modifier functions cannot be called with namespace prefix (#36758)
### Rationale for this change
Bug in implementation of string modified functions caused them to be swallowed when prefixed with stringr namespace
### What changes are included in this PR?
Strips out the `stringr::` prefix when expressions contain `stringr::fixed`, `stringr::coll`, `string::boundary` or `stringr::regex`
### Are these changes tested?
Yes
### Are there any user-facing changes?
Yes
* Closes: #36720
Lead-authored-by: Nic Crane <th...@gmail.com>
Co-authored-by: Dewey Dunnington <de...@dunnington.ca>
Signed-off-by: Nic Crane <th...@gmail.com>
---
r/NAMESPACE | 1 +
r/R/arrow-package.R | 2 +-
r/R/dplyr-funcs-string.R | 18 ++++++++++++++++++
r/tests/testthat/test-dplyr-funcs-string.R | 30 ++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/r/NAMESPACE b/r/NAMESPACE
index aa7b30252b..7eaa51bc57 100644
--- a/r/NAMESPACE
+++ b/r/NAMESPACE
@@ -443,6 +443,7 @@ importFrom(rlang,as_label)
importFrom(rlang,as_quosure)
importFrom(rlang,call2)
importFrom(rlang,call_args)
+importFrom(rlang,call_name)
importFrom(rlang,caller_env)
importFrom(rlang,check_dots_empty)
importFrom(rlang,check_dots_empty0)
diff --git a/r/R/arrow-package.R b/r/R/arrow-package.R
index 79871d8735..8f44f8936b 100644
--- a/r/R/arrow-package.R
+++ b/r/R/arrow-package.R
@@ -27,7 +27,7 @@
#' @importFrom rlang is_list call2 is_empty as_function as_label arg_match is_symbol is_call call_args
#' @importFrom rlang quo_set_env quo_get_env is_formula quo_is_call f_rhs parse_expr f_env new_quosure
#' @importFrom rlang new_quosures expr_text caller_env check_dots_empty check_dots_empty0 dots_list is_string inform
-#' @importFrom rlang is_bare_list
+#' @importFrom rlang is_bare_list call_name
#' @importFrom tidyselect vars_pull eval_select eval_rename
#' @importFrom glue glue
#' @useDynLib arrow, .registration = TRUE
diff --git a/r/R/dplyr-funcs-string.R b/r/R/dplyr-funcs-string.R
index 436083d9de..b4becb4081 100644
--- a/r/R/dplyr-funcs-string.R
+++ b/r/R/dplyr-funcs-string.R
@@ -56,15 +56,33 @@ get_stringr_pattern_options <- function(pattern) {
)
}
}
+
ensure_opts <- function(opts) {
if (is.character(opts)) {
opts <- list(pattern = opts, fixed = FALSE, ignore_case = FALSE)
}
opts
}
+
+ pattern <- clean_pattern_namespace(pattern)
+
ensure_opts(eval(pattern))
}
+# Ensure that e.g. stringr::regex and regex both work within patterns
+clean_pattern_namespace <- function(pattern) {
+ modifier_funcs <- c("fixed", "regex", "coll", "boundary")
+ if (is_call(pattern, modifier_funcs, ns = "stringr")) {
+ function_called <- call_name(pattern[1])
+
+ if (function_called %in% modifier_funcs) {
+ pattern[1] <- call2(function_called)
+ }
+ }
+
+ pattern
+}
+
#' Does this string contain regex metacharacters?
#'
#' @param string String to be tested
diff --git a/r/tests/testthat/test-dplyr-funcs-string.R b/r/tests/testthat/test-dplyr-funcs-string.R
index 0dc834dbfe..fc202bfb3a 100644
--- a/r/tests/testthat/test-dplyr-funcs-string.R
+++ b/r/tests/testthat/test-dplyr-funcs-string.R
@@ -1466,3 +1466,33 @@ test_that("str_remove and str_remove_all", {
df
)
})
+
+test_that("GH-36720: stringr modifier functions can be called with namespace prefix", {
+ df <- tibble(x = c("Foo", "bar"))
+ compare_dplyr_binding(
+ .input %>%
+ transmute(x = str_replace_all(x, stringr::regex("^f", ignore_case = TRUE), "baz")) %>%
+ collect(),
+ df
+ )
+
+ compare_dplyr_binding(
+ .input %>%
+ filter(str_detect(x, stringr::fixed("f", ignore_case = TRUE), negate = TRUE)) %>%
+ collect(),
+ df
+ )
+
+ x <- Expression$field_ref("x")
+
+ expect_error(
+ call_binding("str_detect", x, stringr::boundary(type = "character")),
+ "Pattern modifier `boundary()` not supported in Arrow",
+ fixed = TRUE
+ )
+ expect_error(
+ call_binding("str_replace_all", x, stringr::coll("o", locale = "en"), "รณ"),
+ "Pattern modifier `coll()` not supported in Arrow",
+ fixed = TRUE
+ )
+})