Skip to content

Commit cee5376

Browse files
author
Ryan Patrick Kyle
committed
✨ add support for debug mode tracebacks
1 parent e372c3c commit cee5376

File tree

1 file changed

+55
-14
lines changed

1 file changed

+55
-14
lines changed

R/utils.R

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -625,13 +625,47 @@ printCallStack <- function(call_stack, header=TRUE) {
625625
)
626626
}
627627

628+
stackTraceToHTML <- function(call_stack,
629+
throwing_call,
630+
error_message) {
631+
if(is.null(call_stack)) {
632+
return(NULL)
633+
}
634+
header <- " ### DashR Traceback (most recent/innermost call last) ###"
635+
636+
formattedStack <- c(paste0(
637+
" ",
638+
seq_along(
639+
call_stack
640+
),
641+
": ",
642+
call_stack,
643+
collapse="<br>"
644+
)
645+
)
646+
647+
template <- "<!DOCTYPE HTML><html><body><pre><h3>%s</h3><br>Error: %s: %s<br>%s</pre></body></html>"
648+
response <- sprintf(template,
649+
header,
650+
throwing_call,
651+
error_message,
652+
formattedStack)
653+
654+
# remove anonymous tags from call stack
655+
response <- gsub("<anonymous>", "&lt;anonymous&gt;", response)
656+
657+
return(response)
658+
}
659+
628660
# This function is essentially the R equivalent of a
629661
# Python decorator method; if debug mode is active,
630662
# it will wrap an expression using withCallingHandlers
631663
# and capture the call stack. By default, the call
632664
# stack will be "pruned" of error handling functions
633665
# for greater readability.
634666
getStackTrace <- function(expr, debug = FALSE, pruned_errors = TRUE) {
667+
tryenv <- new.env()
668+
browser()
635669
if(debug) {
636670
tryCatch(withCallingHandlers(
637671
expr,
@@ -689,26 +723,33 @@ getStackTrace <- function(expr, debug = FALSE, pruned_errors = TRUE) {
689723

690724
startIndex <- match(TRUE, lapply(functionsAsList, function(fn) fn == "getStackTrace"))
691725
functionsAsList <- functionsAsList[startIndex:stopIndex]
692-
warning(call. = FALSE, immediate. = TRUE, sprintf("Execution error in %s: %s",
693-
functionsAsList[[length(functionsAsList)]],
694-
conditionMessage(e)))
695-
printCallStack(removeHandlers(functionsAsList))
696-
} else {
697-
warning(call. = FALSE, immediate. = TRUE, sprintf("Execution error in %s: %s",
698-
functionsAsList[[length(functionsAsList)]],
699-
conditionMessage(e)))
700-
printCallStack(functionsAsList)
726+
functionsAsList <- removeHandlers(functionsAsList)
701727
}
702-
728+
browser()
729+
730+
warning(call. = FALSE, immediate. = TRUE, sprintf("Execution error in %s: %s",
731+
functionsAsList[[length(functionsAsList)]],
732+
conditionMessage(e)))
733+
734+
stack_message <- stackTraceToHTML(functionsAsList,
735+
functionsAsList[[length(functionsAsList)]],
736+
conditionMessage(e))
737+
738+
assign("stack_message", value=stack_message,
739+
envir=sys.frame(1)$private)
740+
741+
printCallStack(functionsAsList)
703742
}
704743
}
705744
),
706-
error = function(e) {write(crayon::yellow$bold("in debug mode, catching error as warning ..."), stderr())}
745+
error = function(e) {
746+
write(crayon::yellow$bold("in debug mode, catching error as warning ..."), stderr())
747+
}
707748
)
708-
} else {
709-
evalq(expr)
749+
} else {
750+
evalq(expr)
751+
}
710752
}
711-
}
712753

713754
# This helper function drops error
714755
# handling functions from the call

0 commit comments

Comments
 (0)