diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION index 4f414c9f..7051de84 100644 --- a/CRAN-SUBMISSION +++ b/CRAN-SUBMISSION @@ -1,3 +1,3 @@ -Version: 3.2.0 -Date: 2026-06-23 16:43:46 UTC -SHA: 9892d5abc8c9278acd19835059bbe78ff887c7bc +Version: 3.4.0 +Date: 2026-07-02 16:27:59 UTC +SHA: 16c8b4d791827785b68e78279b89c183b9d35d09 diff --git a/DESCRIPTION b/DESCRIPTION index 3265a54a..1b0912ad 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: ggRandomForests Type: Package Title: Visually Exploring Random Forests -Version: 3.4.0 -Date: 2026-07-01 +Version: 3.4.1 +Date: 2026-07-02 Authors@R: person("John", "Ehrlinger", role = c("aut", "cre"), email = "john.ehrlinger@gmail.com") diff --git a/NAMESPACE b/NAMESPACE index 18ad9d3d..2dd6191d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -24,7 +24,9 @@ S3method(gg_beta_uvarpro,default) S3method(gg_beta_uvarpro,uvarpro) S3method(gg_beta_varpro,default) S3method(gg_beta_varpro,varpro) +S3method(gg_brier,default) S3method(gg_brier,rfsrc) +S3method(gg_error,default) S3method(gg_error,randomForest) S3method(gg_error,randomForest.formula) S3method(gg_error,rfsrc) @@ -32,6 +34,7 @@ S3method(gg_isopro,default) S3method(gg_isopro,isopro) S3method(gg_ivarpro,default) S3method(gg_ivarpro,varpro) +S3method(gg_rfsrc,default) S3method(gg_rfsrc,randomForest) S3method(gg_rfsrc,rfsrc) S3method(gg_roc,default) @@ -41,8 +44,10 @@ S3method(gg_sdependent,default) S3method(gg_sdependent,uvarpro) S3method(gg_survival,default) S3method(gg_survival,rfsrc) +S3method(gg_variable,default) S3method(gg_variable,randomForest) S3method(gg_variable,rfsrc) +S3method(gg_vimp,default) S3method(gg_vimp,randomForest) S3method(gg_vimp,rfsrc) S3method(plot,gg_beta_uvarpro) diff --git a/NEWS.md b/NEWS.md index 47420706..730f3485 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,15 @@ Package: ggRandomForests -Version: 3.4.0 +Version: 3.4.1 + +ggRandomForests v3.4.1 +====================== +* The remaining `rfsrc`/`randomForest` wrappers -- `gg_error()`, `gg_vimp()`, + `gg_variable()`, `gg_rfsrc()`, and `gg_brier()` -- now have `default` S3 + methods, so a wrong-class input gives a clear "expected an 'rfsrc' or + 'randomForest' object" error (naming the class it got) instead of R's generic + "no applicable method". This finishes the dispatch-consistency pass started + for the varPro family in 3.4.0. (`gg_roc()` keeps its existing + `gg_roc.rfsrc` default, which accepts rfsrc-shaped objects.) ggRandomForests v3.4.0 ====================== diff --git a/R/gg_brier.R b/R/gg_brier.R index 7559df61..fde3398d 100644 --- a/R/gg_brier.R +++ b/R/gg_brier.R @@ -119,6 +119,13 @@ gg_brier <- function(object, ...) { UseMethod("gg_brier", object) } +#' @export +gg_brier.default <- function(object, ...) { + stop("gg_brier: expected an 'rfsrc' survival object from ", + "randomForestSRC::rfsrc(); got an object of class ", + paste(class(object), collapse = "/"), ".", call. = FALSE) +} + #' @export gg_brier.rfsrc <- function(object, subset = NULL, diff --git a/R/gg_error.R b/R/gg_error.R index e8c8948f..4283cd63 100644 --- a/R/gg_error.R +++ b/R/gg_error.R @@ -204,6 +204,13 @@ gg_error <- function(object, ...) { UseMethod("gg_error", object) } + +#' @export +gg_error.default <- function(object, ...) { + stop("gg_error: expected an 'rfsrc' or 'randomForest' object; ", + "got an object of class ", paste(class(object), collapse = "/"), ".", + call. = FALSE) +} #' @export gg_error.rfsrc <- function(object, ...) { ## Check that the input object is of the correct type. diff --git a/R/gg_rfsrc.R b/R/gg_rfsrc.R index 802bfa02..b73940af 100644 --- a/R/gg_rfsrc.R +++ b/R/gg_rfsrc.R @@ -454,6 +454,13 @@ gg_rfsrc <- function(object, UseMethod("gg_rfsrc", object) } +#' @export +gg_rfsrc.default <- function(object, oob = TRUE, by, ...) { + stop("gg_rfsrc: expected an 'rfsrc' or 'randomForest' object; ", + "got an object of class ", paste(class(object), collapse = "/"), ".", + call. = FALSE) +} + #' @export gg_rfsrc.randomForest <- function(object, oob = TRUE, diff --git a/R/gg_variable.R b/R/gg_variable.R index 7981c015..e9d3d6f1 100644 --- a/R/gg_variable.R +++ b/R/gg_variable.R @@ -159,6 +159,13 @@ gg_variable <- function(object, ...) { UseMethod("gg_variable", object) } + +#' @export +gg_variable.default <- function(object, ...) { + stop("gg_variable: expected an 'rfsrc' or 'randomForest' object; ", + "got an object of class ", paste(class(object), collapse = "/"), ".", + call. = FALSE) +} #' @export gg_variable.rfsrc <- function(object, ...) { diff --git a/R/gg_vimp.R b/R/gg_vimp.R index b53309d0..5dcffc99 100644 --- a/R/gg_vimp.R +++ b/R/gg_vimp.R @@ -190,6 +190,13 @@ gg_vimp <- function(object, nvar, ...) { UseMethod("gg_vimp", object) } + +#' @export +gg_vimp.default <- function(object, nvar, ...) { + stop("gg_vimp: expected an 'rfsrc' or 'randomForest' object; ", + "got an object of class ", paste(class(object), collapse = "/"), ".", + call. = FALSE) +} #' @export gg_vimp.rfsrc <- function(object, nvar, ...) { # Validate that the object is an rfsrc grow or predict result. diff --git a/tests/testthat/test_default_dispatch.R b/tests/testthat/test_default_dispatch.R new file mode 100644 index 00000000..e087300e --- /dev/null +++ b/tests/testthat/test_default_dispatch.R @@ -0,0 +1,15 @@ +# Wrong-class inputs to the rfsrc/randomForest wrappers must error via their +# default S3 methods with a clear message. Fit-free, so these run on CRAN. + +test_that("rfsrc/randomForest wrappers error on non-model input", { + bad <- data.frame(a = 1:3) + + expect_error(gg_error(bad), "expected an 'rfsrc' or 'randomForest' object") + expect_error(gg_vimp(bad), "expected an 'rfsrc' or 'randomForest' object") + expect_error(gg_variable(bad), "expected an 'rfsrc' or 'randomForest' object") + expect_error(gg_rfsrc(bad), "expected an 'rfsrc' or 'randomForest' object") + expect_error(gg_brier(bad), "expected an 'rfsrc' survival object") + + # The error names the class it actually got. + expect_error(gg_error(1:3), "got an object of class integer") +})