Skip to content

Commit 5400fe1

Browse files
authored
feat(errors): improved error handling via error classes, encpapsulation returns the condition objects (#141)
1 parent 39387df commit 5400fe1

File tree

16 files changed

+502
-76
lines changed

16 files changed

+502
-76
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,5 @@ revdep
4343
docs/
4444
cran-comments.md
4545
CRAN-SUBMISSION
46+
47+
.vscode/

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Collate:
5656
'chunk.R'
5757
'compose.R'
5858
'compute_mode.R'
59+
'conditions.R'
5960
'count_missing.R'
6061
'crate.R'
6162
'cross_join.R'

NAMESPACE

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ S3method(discard,default)
1111
S3method(distinct_values,default)
1212
S3method(distinct_values,factor)
1313
S3method(distinct_values,logical)
14+
S3method(format,Mlr3Error)
15+
S3method(format,Mlr3Warning)
1416
S3method(hash_input,"function")
1517
S3method(hash_input,data.table)
1618
S3method(hash_input,default)
@@ -81,6 +83,13 @@ export(discard)
8183
export(distinct_values)
8284
export(encapsulate)
8385
export(enframe)
86+
export(error_config)
87+
export(error_input)
88+
export(error_learner)
89+
export(error_learner_predict)
90+
export(error_learner_train)
91+
export(error_mlr3)
92+
export(error_timeout)
8493
export(every)
8594
export(extract_vars)
8695
export(format_bib)
@@ -165,6 +174,9 @@ export(topo_sort)
165174
export(transpose_list)
166175
export(unnest)
167176
export(walk)
177+
export(warning_config)
178+
export(warning_input)
179+
export(warning_mlr3)
168180
export(warningf)
169181
export(which_max)
170182
export(which_min)

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# mlr3misc (development version)
22

3+
## New features:
4+
5+
* Added various new functions for improved error handling.
6+
* `encapsulate()` now returns the specific condition objects along the logs, allowing for
7+
improved error handling on the caller side.
8+
39
# mlr3misc 0.18.0
410

511
* feat: Added `"mirai"` as encapsulation method to `encapsulate()`.

R/conditions.R

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#' @title Error Classes
2+
#' @name mlr_conditions
3+
#' @description
4+
#' Condition classes for mlr3.
5+
#'
6+
#' @section Formatting:
7+
#' It is also possible to use formatting options as defined in [`cli::cli_bullets`].
8+
#'
9+
#' @section Errors:
10+
#' * `error_mlr3()` for the base `Mlr3Error` class.
11+
#' * `error_config()` for the `Mlr3ErrorConfig` class, which signals that a user has misconfigured
12+
#' something (e.g. invalid learner configuration).
13+
#' * `error_input()` for the `Mlr3ErrorInput` if an invalid input was provided.
14+
#' method.
15+
#' * `error_timeout()` for the `Mlr3ErrorTimeout`, signalling a timeout (encapsulation).
16+
#' * `error_learner()` for the `Mlr3ErrorLearner`, signalling a learner error.
17+
#' * `error_learner_train()` for the `Mlr3ErrorLearner`, signalling a learner training error.
18+
#' * `error_learner_predict()` for the `Mlr3ErrorLearner`, signalling a learner prediction error.
19+
#'
20+
#' @section Warnings:
21+
#' * `warning_mlr3()` for the base `Mlr3Warning` class.
22+
#' * `warning_config()` for the `Mlr3WarningConfig` class, which signals that a user might have
23+
#' misconfigured something.
24+
#' * `warning_input()` for the `Mlr3WarningInput` if an invalid input might have been provided.
25+
#'
26+
#' @param msg (`character(1)`)\cr
27+
#' Error message.
28+
#' @param ... (any)\cr
29+
#' Passed to [`sprintf()`].
30+
#' @param class (`character`)\cr
31+
#' Additional class(es).
32+
#' @param signal (`logical(1)`)\cr
33+
#' If `TRUE`, the condition object is returned.
34+
#' @export
35+
error_config = function(msg, ..., class = NULL, signal = TRUE) {
36+
error_mlr3(msg, ..., class = "Mlr3ErrorConfig", signal = signal)
37+
}
38+
39+
#' @rdname mlr_conditions
40+
#' @export
41+
error_input = function(msg, ..., class = NULL, signal = TRUE) {
42+
error_mlr3(msg, ..., class = "Mlr3ErrorInput", signal = signal)
43+
}
44+
45+
#' @rdname mlr_conditions
46+
#' @export
47+
error_timeout = function(signal = TRUE) {
48+
error_mlr3("reached elapsed time limit", class = "Mlr3ErrorTimeout", signal = signal)
49+
}
50+
51+
#' @rdname mlr_conditions
52+
#' @export
53+
error_mlr3 = function(msg, ..., class = NULL, signal = TRUE) {
54+
cond = errorCondition(sprintf(msg, ...), class = c(class, "Mlr3Error"))
55+
cond$message = format(cond)
56+
if (signal) {
57+
return(stop(cond))
58+
}
59+
cond
60+
}
61+
62+
#' @rdname mlr_conditions
63+
#' @export
64+
warning_mlr3 = function(msg, ..., class = NULL, signal = TRUE) {
65+
cond = warningCondition(sprintf(msg, ...), class = c(class, "Mlr3Warning"))
66+
cond$message = format(cond)
67+
if (signal) {
68+
return(warning(cond))
69+
}
70+
cond
71+
}
72+
73+
#' @rdname mlr_conditions
74+
#' @export
75+
warning_config = function(msg, ..., class = NULL, signal = TRUE) {
76+
warning_mlr3(msg, ..., class = c(class, "Mlr3WarningConfig"), signal = signal)
77+
}
78+
79+
#' @rdname mlr_conditions
80+
#' @export
81+
warning_input = function(msg, ..., class = NULL, signal = TRUE) {
82+
warning_mlr3(msg, ..., class = c(class, "Mlr3WarningInput"), signal = signal)
83+
}
84+
85+
86+
#' @export
87+
format.Mlr3Error = function(x, ...) {
88+
message = if (!is.null(names(x$message))) {
89+
# error message is already a cli list
90+
message = c(x$message, paste0("Class: ", class(x)[1L]))
91+
names(message) = c(names(x$message), ">")
92+
cli::format_bullets_raw(message)
93+
} else {
94+
cli::format_bullets_raw(c(
95+
"x" = x$message,
96+
">" = paste0("Class: ", class(x)[1L])
97+
))
98+
}
99+
paste0("\n", paste0(message, collapse = "\n"), "\n")
100+
}
101+
102+
#' @export
103+
format.Mlr3Warning = format.Mlr3Error
104+
105+
#' @rdname mlr_conditions
106+
#' @export
107+
error_learner = function(msg, ..., class = NULL, signal = TRUE) {
108+
error_mlr3(msg, ..., class = c(class, "Mlr3ErrorLearner"), signal = signal)
109+
}
110+
111+
#' @rdname mlr_conditions
112+
#' @export
113+
error_learner_train = function(msg, ..., class = NULL, signal = TRUE) {
114+
error_learner(msg, ..., class = c(class, "Mlr3ErrorLearnerTrain"), signal = signal)
115+
}
116+
117+
#' @rdname mlr_conditions
118+
#' @export
119+
error_learner_predict = function(msg, ..., class = NULL, signal = TRUE) {
120+
error_learner(msg, ..., class = c(class, "Mlr3ErrorLearnerPredict"), signal = signal)
121+
}

0 commit comments

Comments
 (0)