Skip to content

Commit

Permalink
transition remaining rlang warnings and errors to cli (#1162)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: topepo <[email protected]>
Co-authored-by: Emil Hvitfeldt <[email protected]>
  • Loading branch information
3 people authored Aug 29, 2024
1 parent 81d9536 commit dc9e188
Show file tree
Hide file tree
Showing 53 changed files with 361 additions and 214 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: parsnip
Title: A Common API to Modeling and Analysis Functions
Version: 1.2.1.9001
Version: 1.2.1.9002
Authors@R: c(
person("Max", "Kuhn", , "[email protected]", role = c("aut", "cre")),
person("Davis", "Vaughan", , "[email protected]", role = "aut"),
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

* Transitioned package errors and warnings to use cli (#1147 and #1148 by
@shum461, #1153 by @RobLBaker and @wright13, #1154 by @JamesHWade, #1160,
#1161).
#1161, #1081).

* `fit_xy()` currently raises an error for `gen_additive_mod()` model specifications as the default engine (`"mgcv"`) specifies smoothing terms in model formulas. However, some engines specify smooths via additional arguments, in which case the restriction on `fit_xy()` is excessive. parsnip will now only raise an error when fitting a `gen_additive_mod()` with `fit_xy()` when using the `"mgcv"` engine (#775).

Expand Down
20 changes: 11 additions & 9 deletions R/aaa_multi_predict.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#' @export
multi_predict <- function(object, ...) {
if (inherits(object$fit, "try-error")) {
rlang::warn("Model fit failed; cannot make predictions.")
cli::cli_warn("Model fit failed; cannot make predictions.")
return(NULL)
}
check_for_newdata(...)
Expand All @@ -28,17 +28,19 @@ multi_predict <- function(object, ...) {

#' @export
#' @rdname multi_predict
multi_predict.default <- function(object, ...)
rlang::abort(
glue::glue(
"No `multi_predict` method exists for objects with classes ",
glue::glue_collapse(glue::glue("'{class(object)}'"), sep = ", ")
)
)
multi_predict.default <- function(object, ...) {
cli::cli_abort(
"No {.fun multi_predict} method exists for objects with classes
{.cls {class(object)}}."
)
}

#' @export
predict.model_spec <- function(object, ...) {
rlang::abort("You must use `fit()` on your model specification before you can use `predict()`.")
cli::cli_abort(
"You must {.fun fit} your model specification
before you can use {.fun predict}."
)
}

#' Tools for models that predict on sub-models
Expand Down
2 changes: 1 addition & 1 deletion R/adds.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#' @export
add_rowindex <- function(x) {
if (!is.data.frame(x)) {
rlang::abort("`x` should be a data frame.")
cli::cli_abort("{.arg x} should be a data frame.")
}
x <- dplyr::mutate(x, .row = seq_len(nrow(x)))
x
Expand Down
31 changes: 21 additions & 10 deletions R/arguments.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ check_eng_args <- function(args, obj, core_args) {
if (length(common_args) > 0) {
args <- args[!(names(args) %in% common_args)]
common_args <- paste0(common_args, collapse = ", ")
rlang::warn(glue::glue("The following arguments cannot be manually modified ",
"and were removed: {common_args}."))
cli::cli_warn(
"The argument{?s} {.arg {common_args}} cannot be manually
modified and {?was/were} removed."
)
}
args
}
Expand Down Expand Up @@ -56,7 +58,7 @@ set_args <- function(object, ...) {
set_args.model_spec <- function(object, ...) {
the_dots <- enquos(...)
if (length(the_dots) == 0)
rlang::abort("Please pass at least one named argument.")
cli::cli_abort("Please pass at least one named argument.")
main_args <- names(object$args)
new_args <- names(the_dots)
for (i in new_args) {
Expand Down Expand Up @@ -262,7 +264,7 @@ make_xy_call <- function(object, target, env) {
none = rlang::expr(x),
data.frame = rlang::expr(maybe_data_frame(x)),
matrix = rlang::expr(maybe_matrix(x)),
rlang::abort(glue::glue("Invalid data type target: {target}."))
cli::cli_abort("Invalid data type target: {target}.")
)
if (uses_weights) {
object$method$fit$args[[ unname(data_args["weights"]) ]] <- rlang::expr(weights)
Expand Down Expand Up @@ -316,9 +318,13 @@ min_cols <- function(num_cols, source) {
p <- ncol(source)
}
if (num_cols > p) {
msg <- paste0(num_cols, " columns were requested but there were ", p,
" predictors in the data. ", p, " will be used.")
rlang::warn(msg)
cli::cli_warn(
c(
"!" = "{num_cols} column{?s} {?was/were} requested but there {cli::qty(p)} {?was/were}
{p} predictor{?s} in the data.",
"i" = "{p} predictor{?s} will be used."
)
)
num_cols <- p
}

Expand All @@ -335,9 +341,14 @@ min_rows <- function(num_rows, source, offset = 0) {
}

if (num_rows > n - offset) {
msg <- paste0(num_rows, " samples were requested but there were ", n,
" rows in the data. ", n - offset, " will be used.")
rlang::warn(msg)
cli::cli_warn(
c(
"!" = "{num_rows} sample{?s} {?was/were} requested but there were
{n} rows in the data.",
"i" = "{n - offset} sample{?s} will be used."
)
)

num_rows <- n - offset
}

Expand Down
7 changes: 6 additions & 1 deletion R/augment.R
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,12 @@ augment.model_fit <- function(x, new_data, eval_time = NULL, ...) {
"regression" = augment_regression(x, new_data),
"classification" = augment_classification(x, new_data),
"censored regression" = augment_censored(x, new_data, eval_time = eval_time),
rlang::abort(paste("Unknown mode:", x$spec$mode))
cli::cli_abort(
c(
"Unknown mode {.val {x$spec$mode}}.",
"i" = "Model mode should be one of {.or {.val {all_modes}}}."
)
)
)
tibble::new_tibble(res)
}
Expand Down
7 changes: 4 additions & 3 deletions R/autoplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ map_glmnet_coefs <- function(x) {
# work. If an object is loaded from a new session, they will need to load the
# package.
if (is.null(coefs)) {
rlang::abort("Please load the glmnet package before running `autoplot()`.")
cli::cli_abort(
"Please load the {.pkg glmnet} package before running {.fun autoplot}."
)
}
p <- x$dim[1]
if (is.list(coefs)) {
Expand Down Expand Up @@ -161,8 +163,7 @@ check_penalty_value <- function(x) {
cl <- match.call()
arg_val <- as.character(cl$x)
if (!is.vector(x) || length(x) != 1 || !is.numeric(x) || x < 0) {
msg <- paste0("Argument '", arg_val, "' should be a single, non-negative value.")
rlang::abort(msg)
cli::cli_abort("{.arg {arg_val}} should be a single, non-negative value.")
}
invisible(x)
}
Expand Down
7 changes: 3 additions & 4 deletions R/case_weights.R
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,9 @@ case_weights_allowed <- function(spec) {
get_from_env(paste0(mod_type, "_fit")) %>%
dplyr::filter(engine == mod_eng & mode == mod_mode)
if (nrow(model_info) != 1) {
rlang::abort(
glue::glue(
"Error in getting model information for model {mod_type} with engine {mod_eng} and mode {mod_mode}."
)
cli::cli_abort(
"Error in getting model information for model {mod_type} with
engine {mod_eng} and mode {mod_mode}."
)
}
# If weights are used, they are protected data arguments with the canonical
Expand Down
15 changes: 5 additions & 10 deletions R/condense_control.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,12 @@
condense_control <- function(x, ref) {
mismatch <- setdiff(names(ref), names(x))
if (length(mismatch)) {
rlang::abort(
cli::cli_abort(
c(
glue::glue(
"Object of class `{class(x)[1]}` cannot be coerced to ",
"object of class `{class(ref)[1]}`."
),
"The following arguments are missing:",
glue::glue_collapse(
glue::single_quote(mismatch),
sep = ", ", last = ", and "
)
"Object of class {.cls class(x)[1]} cannot be coerced to
object of class {.cls class(ref)[1]}.",
"i" = "{cli::qty(mismatch)} The argument{?s} {.arg {mismatch}}
{?is/are} missing."
)
)
}
Expand Down
8 changes: 4 additions & 4 deletions R/contr_one_hot.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
#' @export
contr_one_hot <- function(n, contrasts = TRUE, sparse = FALSE) {
if (sparse) {
rlang::warn("`sparse = TRUE` not implemented for `contr_one_hot()`.")
cli::cli_warn("{.code sparse = TRUE} not implemented for {.fun contr_one_hot}.")
}

if (!contrasts) {
rlang::warn("`contrasts = FALSE` not implemented for `contr_one_hot()`.")
cli::cli_warn("{.code contrasts = FALSE} not implemented for {.fun contr_one_hot}.")
}

if (is.character(n)) {
Expand All @@ -30,12 +30,12 @@ contr_one_hot <- function(n, contrasts = TRUE, sparse = FALSE) {
n <- as.integer(n)

if (length(n) != 1L) {
rlang::abort("`n` must have length 1 when an integer is provided.")
cli::cli_abort("{.arg n} must have length 1 when an integer is provided.")
}

names <- as.character(seq_len(n))
} else {
rlang::abort("`n` must be a character vector or an integer of size 1.")
cli::cli_abort("{.arg n} must be a character vector or an integer of size 1.")
}

out <- diag(n)
Expand Down
14 changes: 9 additions & 5 deletions R/control_parsnip.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ control_parsnip <- function(verbosity = 1L, catch = FALSE) {
res
}

check_control <- function(x) {
check_control <- function(x, call = rlang::caller_env()) {
if (!is.list(x))
rlang::abort("control should be a named list.")
cli::cli_abort("{.arg control} should be a named list.", call = call)
if (!isTRUE(all.equal(sort(names(x)), c("catch", "verbosity"))))
rlang::abort("control should be a named list with elements 'verbosity' and 'catch'.")
cli::cli_abort(
"{.arg control} should be a named list with elements {.field verbosity}
and {.field catch}.",
call = call
)
# based on ?is.integer
int_check <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
if (!int_check(x$verbosity))
rlang::abort("verbosity should be an integer.")
cli::cli_abort("{.arg verbosity} should be an integer.", call = call)
if (!is.logical(x$catch))
rlang::abort("catch should be a logical.")
cli::cli_abort("{.arg catch} should be a logical.", call = call)
x
}

Expand Down
58 changes: 33 additions & 25 deletions R/convert_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
composition = "data.frame",
remove_intercept = TRUE) {
if (!(composition %in% c("data.frame", "matrix"))) {
rlang::abort("`composition` should be either 'data.frame' or 'matrix'.")
cli::cli_abort(
"{.arg composition} should be either {.val data.frame} or {.val matrix}."
)
}

if (remove_intercept) {
Expand Down Expand Up @@ -74,7 +76,7 @@

w <- as.vector(model.weights(mod_frame))
if (!is.null(w) && !is.numeric(w)) {
rlang::abort("`weights` must be a numeric vector")
cli::cli_abort("{.arg weights} must be a numeric vector.")
}

# TODO: Do we actually use the offset when fitting?
Expand Down Expand Up @@ -151,7 +153,9 @@
na.action = na.pass,
composition = "data.frame") {
if (!(composition %in% c("data.frame", "matrix"))) {
rlang::abort("`composition` should be either 'data.frame' or 'matrix'.")
cli::cli_abort(
"{.arg composition} should be either {.val data.frame} or {.val matrix}."
)
}

mod_terms <- object$terms
Expand Down Expand Up @@ -218,7 +222,7 @@
y_name = "..y",
remove_intercept = TRUE) {
if (is.vector(x)) {
rlang::abort("`x` cannot be a vector.")
cli::cli_abort("{.arg x} cannot be a vector.")
}

if (remove_intercept) {
Expand Down Expand Up @@ -251,10 +255,10 @@

if (!is.null(weights)) {
if (!is.numeric(weights)) {
rlang::abort("`weights` must be a numeric vector")
cli::cli_abort("{.arg weights} must be a numeric vector.")
}
if (length(weights) != nrow(x)) {
rlang::abort(glue::glue("`weights` should have {nrow(x)} elements"))
cli::cli_abort("{.arg weights} should have {nrow(x)} elements.")
}

form <- patch_formula_environment_with_case_weights(
Expand Down Expand Up @@ -294,17 +298,17 @@ local_one_hot_contrasts <- function(frame = rlang::caller_env()) {
rlang::local_options(contrasts = contrasts, .frame = frame)
}

check_form_dots <- function(x) {
check_form_dots <- function(x, call = rlang::caller_env()) {
good_args <- c("subset", "weights")
good_names <- names(x) %in% good_args
if (any(!good_names)) {
rlang::abort(
glue::glue(
"These argument(s) cannot be used to create the data: ",
glue::glue_collapse(glue::glue("`{names(x)[!good_names]}`"), sep = ", "),
". Possible arguments are: ",
glue::glue_collapse(glue::glue("`{good_args}`"), sep = ", ")
)
cli::cli_abort(
c(
"The argument{?s} {.arg {names(x)[!good_names]}} cannot be used to create
the data.",
"Possible arguments are {.arg {.or {good_args}}."
),
call = call
)
}
invisible(NULL)
Expand Down Expand Up @@ -339,18 +343,21 @@ will_make_matrix <- function(y) {
all(can_convert)
}

check_dup_names <- function(x, y) {
check_dup_names <- function(x, y, call = rlang::caller_env()) {
if (is.vector(y))
return(invisible(NULL))

common_names <- intersect(colnames(x), colnames(y))
if (length(common_names) > 0)
rlang::abort(
glue::glue(
"`x` and `y` have at least one name in common: ",
glue::glue_collapse(glue::glue("'{common_names}'"), sep = ", ")
)
if (length(common_names) > 0) {
cli::cli_abort(
c(
"{.arg x} and {.arg y} have the name{?s} {.val {common_names}} in common.",
"i" = "Please ensure that {.arg x} and {.arg y} don't share any column names."
),
call = call
)
}

invisible(NULL)
}

Expand All @@ -369,10 +376,11 @@ maybe_matrix <- function(x) {
non_num_cols <- vapply(x, function(x) !is.numeric(x), logical(1))
if (any(non_num_cols)) {
non_num_cols <- names(non_num_cols)[non_num_cols]
non_num_cols <- glue::glue_collapse(glue::single_quote(non_num_cols), sep = ", ")
msg <- glue::glue("Some columns are non-numeric. The data cannot be ",
"converted to numeric matrix: {non_num_cols}.")
rlang::abort(msg)

cli::cli_abort(
"The column{?s} {.val {non_num_cols}} {?is/are} non-numeric, so the
data cannot be converted to a numeric matrix."
)
}
x <- maybe_sparse_matrix(x)
}
Expand Down
Loading

0 comments on commit dc9e188

Please sign in to comment.