Skip to content
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

mutate() doesn't seem to signal warning conditions properly #7663

Open
jmbarbone opened this issue Feb 20, 2025 · 2 comments
Open

mutate() doesn't seem to signal warning conditions properly #7663

jmbarbone opened this issue Feb 20, 2025 · 2 comments

Comments

@jmbarbone
Copy link

jmbarbone commented Feb 20, 2025

mutate() doesn't seem to signal named warning conditions for calling handlers to pick up.

Example: function emits a custom condition, and that specific class can't be suppressed.

library(dplyr, warn.conflicts = FALSE)

foo_warn <- function(x) {
  warning(my_warning)
  x
}

my_warning <- structure(
  list(message = "MY_WARNING", call = NULL),
  class = c("my_warning", "warning", "condition")
)

df <- data.frame(x = 1, y = 2)

suppressWarnings(
  mutate(df, x = foo_warn(x)),
  "my_warning"
)
#> Warning: There was 1 warning in `mutate()`.
#> ℹ In argument: `x = foo_warn(x)`.
#> Caused by warning:
#> ! MY_WARNING
#>   x y
#> 1 1 2

# my_warningis never signaled, handlers can't pick it up
withCallingHandlers(
  mutate(df, x = foo_warn(x)),
  my_warning = function(c) {
    stop("condition signaled")
  }
)
#> Warning: There was 1 warning in `mutate()`.
#> ℹ In argument: `x = foo_warn(x)`.
#> Caused by warning:
#> ! MY_WARNING
#>   x y
#> 1 1 2

# but removing the `warning` class is at least a work-around
# 
foo_cond <- function(x) {
  warning(my_condition)
  x
}

my_condition <- structure(
  list(message = "MY_CONDITION", call = NULL),
  class = c("my_condition", "condition")
)

withCallingHandlers(
  mutate(df, x = foo_cond(x)),
  my_condition = function(c) {
    stop("condition signaled")
  }
)
#> Error in (function (c) : condition signaled

Created on 2025-02-20 with reprex v2.1.1

@philibe
Copy link

philibe commented Feb 21, 2025

And with warning parameter ?:

library(dplyr, warn.conflicts = FALSE)

foo_warn <- function(x) {
  warning(my_warning)
  x
}

my_warning <- structure(
  list(message = "MY_WARNING", call = NULL),
  class = c("my_warning", "warning", "condition")
)

df <- data.frame(x = 1, y = 2)


withCallingHandlers(
  mutate(df, x = foo_warn(x)),
  warning=function(w)  {
    print(w)
    stop("condition signaled")
  }, 
  error = function(e) {
    print(e)
    e
  }
)
#> <warning/rlang_warning>
#> Warning:
#> There was 1 warning in `mutate()`.
#> ℹ In argument: `x = foo_warn(x)`.
#> Caused by warning:
#> ! MY_WARNING
#> <simpleError in (function (w) {    print(w)    stop("condition signaled")})(structure(list(message = "There was 1 warning in `mutate()`.\nℹ In argument: `x = foo_warn(x)`.\nCaused by warning:\n! MY_WARNING",     parent = NULL, call = NULL, footer = character(0)), class = c("rlang_warning", "warning", "condition"))): condition signaled>
#> Error in (function (w) : condition signaled
withCallingHandlers(
  df,
  warning=function(w)  {
    print(w)
    stop("condition signaled")
  }, 
  error = function(e) {
    print(e)
    e
  }
)
#>   x y
#> 1 1 2

Created on 2025-02-21 with reprex v2.1.1

@jmbarbone
Copy link
Author

@philibe , the problem is that the my_warning class can't be specifically suppressed/captured. withCallingHandlers() can pick up on specific classes of conditions. withCallingHandlers() is sensitive to the order of ...,

library(dplyr, warn.conflicts = FALSE)

foo_warn <- function(x) {
  warning(my_warning)
  x
}

my_warning <- structure(
  list(message = "MY_WARNING", call = NULL),
  class = c("my_warning", "warning", "condition")
)

df <- data.frame(x = 1, y = 2)

# muffles any condition with a 'warning' class
suppressWarnings(
  mutate(df, x = foo_warn(x))
)
#>   x y
#> 1 1 2

# specificially tries to muffle 'my_warning' conditions
suppressWarnings(
  mutate(df, x = foo_warn(x)),
  "my_warning"
)
#> Warning: There was 1 warning in `mutate()`.
#> ℹ In argument: `x = foo_warn(x)`.
#> Caused by warning:
#> ! MY_WARNING
#>   x y
#> 1 1 2

# the 'my_warning' condition replaced with an 'rlang_warning' condition
tryCatch(
  mutate(df, x = foo_warn(x)),
  warning = str
)
#> List of 4
#>  $ message: chr "There was 1 warning in `mutate()`.\nℹ In argument: `x = foo_warn(x)`.\nCaused by warning:\n! MY_WARNING"
#>  $ parent : NULL
#>  $ call   : NULL
#>  $ footer : chr(0) 
#>  - attr(*, "class")= chr [1:3] "rlang_warning" "warning" "condition"

# order of the calling handlers is important
try(withCallingHandlers(
  foo_warn(1),
  my_warning = function(c) stop("'my_warning' hit"),
  warning = function(c) stop("'warning' hit")
))
#> Error in (function (c)  : 'my_warning' hit

try(withCallingHandlers(
  foo_warn(1),
  warning = function(c) stop("'warning' hit"),
  my_warning = function(c) stop("'my_warning' hit")
))
#> Error in (function (c)  : 'warning' hit

# 'rlang_warning' signaled before 'my_warning'
withCallingHandlers(
  mutate(df, x = foo_warn(x)),
  my_warning = function(c) stop("'my_warning' hit"),
  rlang_warning = function(c) stop("'rlang_warning' hit"),
  warning = function(c) stop("'warning' hit")
)
#> Error in (function (c) : 'rlang_warning' hit

Created on 2025-02-21 with reprex v2.1.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants