tidyverse / purrr

A functional programming toolkit for R

Home Page:https://purrr.tidyverse.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`map()` and friends don't present reticulate python exceptions

t-kalinowski opened this issue · comments

purrr::map(1:2, \(i) reticulate::py_eval("raise Exception()"))
#> Error in `cnd_type()`:
#> ! `cnd` is not a condition object.
#> Backtrace:
#>      ▆
#>   1. ├─purrr::map(1:2, function(i) reticulate::py_eval("raise Exception()"))
#>   2. │ └─purrr:::map_("list", .x, .f, ..., .progress = .progress)
#>   3. │   ├─purrr:::with_indexed_errors(...)
#>   4. │   │ └─base::withCallingHandlers(...)
#>   5. │   ├─purrr:::call_with_cleanup(...)
#>   6. │   └─global .f(.x[[i]], ...)
#>   7. │     └─reticulate::py_eval("raise Exception()")
#>   8. │       └─reticulate:::py_eval_impl(code, convert) at reticulate/R/python.R:1319:3
#>   9. ├─base::stop(`<python.builtin.SyntaxError>`) at reticulate/R/RcppExports.R:226:5
#>  10. ├─purrr (local) `<fn>`(`<python.builtin.SyntaxError>`)
#>  11. │ └─cli::cli_abort(...)
#>  12. │   └─rlang::abort(...)
#>  13. │     └─rlang:::signal_abort(cnd, .file)
#>  14. │       └─base::signalCondition(cnd)
#>  15. │         ├─base::conditionMessage(cond)
#>  16. │         └─rlang:::conditionMessage.rlang_error(cond)
#>  17. │           └─rlang::cnd_message(c)
#>  18. │             └─rlang:::cnd_message_format_prefixed(cnd, parent = TRUE, warning = warning)
#>  19. │               └─rlang::cnd_type(cnd)
#>  20. └─rlang::abort(message = message)

Compare w/ base lapply

lapply(1:2, \(i) reticulate::py_eval("raise Exception()"))
#> invalid syntax (reticulate_eval, line 1)

Actually, reprex appears to change the way exceptions are presented, this is what I actually see in Console:

> lapply(1:2, \(i) reticulate::py_eval("raise Exception()"))
Error in py_eval_impl(code, convert) :   File "reticulate_eval", line 1
    raise Exception()
    ^^^^^
SyntaxError: invalid syntax
Run `reticulate::py_last_error()` for details.

The exception object from reticulate is a valid condition, it fulfills the condition contract, it just has more stuff.

e <- tryCatch(reticulate::py_eval("raise Exception()"), error = identity)
class(e)
#> [1] "python.builtin.SyntaxError"   "python.builtin.Exception"    
#> [3] "python.builtin.BaseException" "python.builtin.object"       
#> [5] "error"                        "condition"
conditionMessage(e)
#> [1] "  File \"reticulate_eval\", line 1\n    raise Exception()\n    ^^^^^\nSyntaxError: invalid syntax\nRun `reticulate::py_last_error()` for details."
e$message
#> [1] "  File \"reticulate_eval\", line 1\n    raise Exception()\n    ^^^^^\nSyntaxError: invalid syntax\nRun `reticulate::py_last_error()` for details."
conditionCall(e)
#> py_eval_impl(code, convert)
e$call
#> py_eval_impl(code, convert)

e
#> SyntaxError('invalid syntax', ('reticulate_eval', 1, 1, 'raise Exception()', 1, 6))

typeof(e)
#> [1] "environment"
names(e)
#>  [1] "args"                "call"                "end_lineno"         
#>  [4] "end_offset"          "filename"            "lineno"             
#>  [7] "msg"                 "offset"              "print_file_and_line"
#> [10] "text"                "trace"               "with_traceback"

# The actual error comes from rlang::cnd_type()
rlang::cnd_type(e)
#> Error in `rlang::cnd_type()`:
#> ! `cnd` is not a condition object.
#> Backtrace:
#>     ▆
#>  1. ├─rlang::cnd_type(e)
#>  2. └─rlang::abort(message = message)

Created on 2023-10-13 with reprex v2.0.2

https://github.com/r-lib/rlang/blob/7a78dc3f0d5b2fb73289f820e39afb5c4d665802/src/internal/exported.c#L28-L38

Moving to rlang since it looks like the fix is needed there.

...

Oh I can't move it automatically; moving manually instead.