Unverified Commit 3fad53bc authored by James Lamb's avatar James Lamb Committed by GitHub
Browse files

[R-package] make finalize() in R6 classes private (#6833)

parent 604e2c5e
...@@ -53,7 +53,7 @@ Suggests: ...@@ -53,7 +53,7 @@ Suggests:
Depends: Depends:
R (>= 3.5) R (>= 3.5)
Imports: Imports:
R6 (>= 2.0), R6 (>= 2.4.0),
data.table (>= 1.9.6), data.table (>= 1.9.6),
graphics, graphics,
jsonlite (>= 1.0), jsonlite (>= 1.0),
......
...@@ -11,16 +11,6 @@ Booster <- R6::R6Class( ...@@ -11,16 +11,6 @@ Booster <- R6::R6Class(
record_evals = list(), record_evals = list(),
data_processor = NULL, data_processor = NULL,
# Finalize will free up the handles
finalize = function() {
.Call(
LGBM_BoosterFree_R
, private$handle
)
private$handle <- NULL
return(invisible(NULL))
},
# Initialize will create a starter booster # Initialize will create a starter booster
initialize = function(params = list(), initialize = function(params = list(),
train_set = NULL, train_set = NULL,
...@@ -711,6 +701,17 @@ Booster <- R6::R6Class( ...@@ -711,6 +701,17 @@ Booster <- R6::R6Class(
set_objective_to_none = FALSE, set_objective_to_none = FALSE,
train_set_version = 0L, train_set_version = 0L,
fast_predict_config = list(), fast_predict_config = list(),
# finalize() will free up the handles
finalize = function() {
.Call(
LGBM_BoosterFree_R
, private$handle
)
private$handle <- NULL
return(invisible(NULL))
},
# Predict data # Predict data
inner_predict = function(idx) { inner_predict = function(idx) {
......
...@@ -30,16 +30,6 @@ Dataset <- R6::R6Class( ...@@ -30,16 +30,6 @@ Dataset <- R6::R6Class(
cloneable = FALSE, cloneable = FALSE,
public = list( public = list(
# Finalize will free up the handles
finalize = function() {
.Call(
LGBM_DatasetFree_R
, private$handle
)
private$handle <- NULL
return(invisible(NULL))
},
# Initialize will create a starter dataset # Initialize will create a starter dataset
initialize = function(data, initialize = function(data,
params = list(), params = list(),
...@@ -210,7 +200,7 @@ Dataset <- R6::R6Class( ...@@ -210,7 +200,7 @@ Dataset <- R6::R6Class(
if (is.null(private$raw_data)) { if (is.null(private$raw_data)) {
stop(paste0( stop(paste0(
"Attempting to create a Dataset without any raw data. " "Attempting to create a Dataset without any raw data. "
, "This can happen if you have called Dataset$finalize() or if this Dataset was saved with saveRDS(). " , "This can happen if the Dataset's finalizer was called or if this Dataset was saved with saveRDS(). "
, "To avoid this error in the future, use lgb.Dataset.save() or " , "To avoid this error in the future, use lgb.Dataset.save() or "
, "Dataset$save_binary() to save lightgbm Datasets." , "Dataset$save_binary() to save lightgbm Datasets."
)) ))
...@@ -608,7 +598,7 @@ Dataset <- R6::R6Class( ...@@ -608,7 +598,7 @@ Dataset <- R6::R6Class(
# If updating failed but raw data is available, modify the params # If updating failed but raw data is available, modify the params
# on the R side and re-set ("deconstruct") the Dataset # on the R side and re-set ("deconstruct") the Dataset
private$params <- new_params private$params <- new_params
self$finalize() private$finalize()
}) })
} }
return(invisible(self)) return(invisible(self))
...@@ -649,7 +639,7 @@ Dataset <- R6::R6Class( ...@@ -649,7 +639,7 @@ Dataset <- R6::R6Class(
private$categorical_feature <- categorical_feature private$categorical_feature <- categorical_feature
# Finalize and return self # Finalize and return self
self$finalize() private$finalize()
return(invisible(self)) return(invisible(self))
}, },
...@@ -681,7 +671,7 @@ Dataset <- R6::R6Class( ...@@ -681,7 +671,7 @@ Dataset <- R6::R6Class(
private$reference <- reference private$reference <- reference
# Finalize and return self # Finalize and return self
self$finalize() private$finalize()
return(invisible(self)) return(invisible(self))
}, },
...@@ -713,6 +703,16 @@ Dataset <- R6::R6Class( ...@@ -713,6 +703,16 @@ Dataset <- R6::R6Class(
info = NULL, info = NULL,
version = 0L, version = 0L,
# finalize() will free up the handles
finalize = function() {
.Call(
LGBM_DatasetFree_R
, private$handle
)
private$handle <- NULL
return(invisible(NULL))
},
get_handle = function() { get_handle = function() {
# Get handle and construct if needed # Get handle and construct if needed
...@@ -749,7 +749,7 @@ Dataset <- R6::R6Class( ...@@ -749,7 +749,7 @@ Dataset <- R6::R6Class(
private$predictor <- predictor private$predictor <- predictor
# Finalize and return self # Finalize and return self
self$finalize() private$finalize()
return(invisible(self)) return(invisible(self))
} }
......
...@@ -8,24 +8,6 @@ Predictor <- R6::R6Class( ...@@ -8,24 +8,6 @@ Predictor <- R6::R6Class(
cloneable = FALSE, cloneable = FALSE,
public = list( public = list(
# Finalize will free up the handles
finalize = function() {
# Check the need for freeing handle
if (private$need_free_handle) {
.Call(
LGBM_BoosterFree_R
, private$handle
)
private$handle <- NULL
}
return(invisible(NULL))
},
# Initialize will create a starter model # Initialize will create a starter model
initialize = function(modelfile, params = list(), fast_predict_config = list()) { initialize = function(modelfile, params = list(), fast_predict_config = list()) {
private$params <- .params2str(params = params) private$params <- .params2str(params = params)
...@@ -531,5 +513,17 @@ Predictor <- R6::R6Class( ...@@ -531,5 +513,17 @@ Predictor <- R6::R6Class(
.equal_or_both_null(private$fast_predict_config$num_iteration, num_iteration) .equal_or_both_null(private$fast_predict_config$num_iteration, num_iteration)
) )
} }
# finalize() will free up the handles
, finalize = function() {
if (private$need_free_handle) {
.Call(
LGBM_BoosterFree_R
, private$handle
)
private$handle <- NULL
}
return(invisible(NULL))
}
) )
) )
...@@ -270,7 +270,7 @@ void _DatasetFinalizer(SEXP handle) { ...@@ -270,7 +270,7 @@ void _DatasetFinalizer(SEXP handle) {
SEXP LGBM_NullBoosterHandleError_R() { SEXP LGBM_NullBoosterHandleError_R() {
Rf_error( Rf_error(
"Attempting to use a Booster which no longer exists and/or cannot be restored. " "Attempting to use a Booster which no longer exists and/or cannot be restored. "
"This can happen if you have called Booster$finalize() " "This can happen if the Booster's finalizer was called "
"or if this Booster was saved through saveRDS() using 'serializable=FALSE'."); "or if this Booster was saved through saveRDS() using 'serializable=FALSE'.");
return R_NilValue; return R_NilValue;
} }
...@@ -285,7 +285,7 @@ void _AssertDatasetHandleNotNull(SEXP handle) { ...@@ -285,7 +285,7 @@ void _AssertDatasetHandleNotNull(SEXP handle) {
if (Rf_isNull(handle) || !R_ExternalPtrAddr(handle)) { if (Rf_isNull(handle) || !R_ExternalPtrAddr(handle)) {
Rf_error( Rf_error(
"Attempting to use a Dataset which no longer exists. " "Attempting to use a Dataset which no longer exists. "
"This can happen if you have called Dataset$finalize() or if this Dataset was saved with saveRDS(). " "This can happen if the Dataset's finalizer was called or if this Dataset was saved with saveRDS(). "
"To avoid this error in the future, use lgb.Dataset.save() or Dataset$save_binary() to save lightgbm Datasets."); "To avoid this error in the future, use lgb.Dataset.save() or Dataset$save_binary() to save lightgbm Datasets.");
} }
} }
......
library(Matrix) library(Matrix)
test_that("Predictor$finalize() should not fail", { test_that("Predictor's finalizer should not fail", {
X <- as.matrix(as.integer(iris[, "Species"]), ncol = 1L) X <- as.matrix(as.integer(iris[, "Species"]), ncol = 1L)
y <- iris[["Sepal.Length"]] y <- iris[["Sepal.Length"]]
dtrain <- lgb.Dataset(X, label = y) dtrain <- lgb.Dataset(X, label = y)
...@@ -21,11 +21,11 @@ test_that("Predictor$finalize() should not fail", { ...@@ -21,11 +21,11 @@ test_that("Predictor$finalize() should not fail", {
expect_false(.is_null_handle(predictor$.__enclos_env__$private$handle)) expect_false(.is_null_handle(predictor$.__enclos_env__$private$handle))
predictor$finalize() predictor$.__enclos_env__$private$finalize()
expect_true(.is_null_handle(predictor$.__enclos_env__$private$handle)) expect_true(.is_null_handle(predictor$.__enclos_env__$private$handle))
# calling finalize() a second time shouldn't cause any issues # calling finalize() a second time shouldn't cause any issues
predictor$finalize() predictor$.__enclos_env__$private$finalize()
expect_true(.is_null_handle(predictor$.__enclos_env__$private$handle)) expect_true(.is_null_handle(predictor$.__enclos_env__$private$handle))
}) })
......
...@@ -351,7 +351,7 @@ test_that("Dataset$update_params() works correctly for recognized Dataset parame ...@@ -351,7 +351,7 @@ test_that("Dataset$update_params() works correctly for recognized Dataset parame
} }
}) })
test_that("Dataset$finalize() should not fail on an already-finalized Dataset", { test_that("Dataset's finalizer should not fail on an already-finalized Dataset", {
dtest <- lgb.Dataset( dtest <- lgb.Dataset(
data = test_data data = test_data
, label = test_label , label = test_label
...@@ -361,11 +361,11 @@ test_that("Dataset$finalize() should not fail on an already-finalized Dataset", ...@@ -361,11 +361,11 @@ test_that("Dataset$finalize() should not fail on an already-finalized Dataset",
dtest$construct() dtest$construct()
expect_false(.is_null_handle(dtest$.__enclos_env__$private$handle)) expect_false(.is_null_handle(dtest$.__enclos_env__$private$handle))
dtest$finalize() dtest$.__enclos_env__$private$finalize()
expect_true(.is_null_handle(dtest$.__enclos_env__$private$handle)) expect_true(.is_null_handle(dtest$.__enclos_env__$private$handle))
# calling finalize() a second time shouldn't cause any issues # calling finalize() a second time shouldn't cause any issues
dtest$finalize() dtest$.__enclos_env__$private$finalize()
expect_true(.is_null_handle(dtest$.__enclos_env__$private$handle)) expect_true(.is_null_handle(dtest$.__enclos_env__$private$handle))
}) })
......
test_that("Booster$finalize() should not fail", { test_that("Booster's finalizer should not fail", {
X <- as.matrix(as.integer(iris[, "Species"]), ncol = 1L) X <- as.matrix(as.integer(iris[, "Species"]), ncol = 1L)
y <- iris[["Sepal.Length"]] y <- iris[["Sepal.Length"]]
dtrain <- lgb.Dataset(X, label = y) dtrain <- lgb.Dataset(X, label = y)
...@@ -15,11 +15,11 @@ test_that("Booster$finalize() should not fail", { ...@@ -15,11 +15,11 @@ test_that("Booster$finalize() should not fail", {
expect_false(.is_null_handle(bst$.__enclos_env__$private$handle)) expect_false(.is_null_handle(bst$.__enclos_env__$private$handle))
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_true(.is_null_handle(bst$.__enclos_env__$private$handle)) expect_true(.is_null_handle(bst$.__enclos_env__$private$handle))
# calling finalize() a second time shouldn't cause any issues # calling finalize() a second time shouldn't cause any issues
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_true(.is_null_handle(bst$.__enclos_env__$private$handle)) expect_true(.is_null_handle(bst$.__enclos_env__$private$handle))
}) })
...@@ -195,7 +195,7 @@ test_that("Loading a Booster from a text file works", { ...@@ -195,7 +195,7 @@ test_that("Loading a Booster from a text file works", {
lgb.save(bst, model_file) lgb.save(bst, model_file)
# finalize the booster and destroy it so you know we aren't cheating # finalize the booster and destroy it so you know we aren't cheating
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_null(bst$.__enclos_env__$private$handle) expect_null(bst$.__enclos_env__$private$handle)
rm(bst) rm(bst)
...@@ -238,7 +238,7 @@ test_that("boosters with linear models at leaves can be written to text file and ...@@ -238,7 +238,7 @@ test_that("boosters with linear models at leaves can be written to text file and
preds <- predict(bst, X) preds <- predict(bst, X)
model_file <- tempfile(fileext = ".model") model_file <- tempfile(fileext = ".model")
lgb.save(bst, model_file) lgb.save(bst, model_file)
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_null(bst$.__enclos_env__$private$handle) expect_null(bst$.__enclos_env__$private$handle)
rm(bst) rm(bst)
...@@ -275,7 +275,7 @@ test_that("Loading a Booster from a string works", { ...@@ -275,7 +275,7 @@ test_that("Loading a Booster from a string works", {
model_string <- bst$save_model_to_string() model_string <- bst$save_model_to_string()
# finalize the booster and destroy it so you know we aren't cheating # finalize the booster and destroy it so you know we aren't cheating
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_null(bst$.__enclos_env__$private$handle) expect_null(bst$.__enclos_env__$private$handle)
rm(bst) rm(bst)
...@@ -313,7 +313,7 @@ test_that("Saving a large model to string should work", { ...@@ -313,7 +313,7 @@ test_that("Saving a large model to string should work", {
expect_gt(nchar(model_string), 1024L * 1024L) expect_gt(nchar(model_string), 1024L * 1024L)
# finalize the booster and destroy it so you know we aren't cheating # finalize the booster and destroy it so you know we aren't cheating
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_null(bst$.__enclos_env__$private$handle) expect_null(bst$.__enclos_env__$private$handle)
rm(bst) rm(bst)
...@@ -383,7 +383,7 @@ test_that("If a string and a file are both passed to lgb.load() the file is used ...@@ -383,7 +383,7 @@ test_that("If a string and a file are both passed to lgb.load() the file is used
lgb.save(bst, model_file) lgb.save(bst, model_file)
# finalize the booster and destroy it so you know we aren't cheating # finalize the booster and destroy it so you know we aren't cheating
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_null(bst$.__enclos_env__$private$handle) expect_null(bst$.__enclos_env__$private$handle)
rm(bst) rm(bst)
...@@ -1508,7 +1508,7 @@ test_that("boosters with linear models at leaves can be written to RDS and re-lo ...@@ -1508,7 +1508,7 @@ test_that("boosters with linear models at leaves can be written to RDS and re-lo
preds <- predict(bst, X) preds <- predict(bst, X)
model_file <- tempfile(fileext = ".rds") model_file <- tempfile(fileext = ".rds")
saveRDS(bst, file = model_file) saveRDS(bst, file = model_file)
bst$finalize() bst$.__enclos_env__$private$finalize()
expect_null(bst$.__enclos_env__$private$handle) expect_null(bst$.__enclos_env__$private$handle)
rm(bst) rm(bst)
...@@ -1562,7 +1562,7 @@ test_that("Booster's print, show, and summary work correctly", { ...@@ -1562,7 +1562,7 @@ test_that("Booster's print, show, and summary work correctly", {
.has_expected_content_for_fitted_model(log_txt) .has_expected_content_for_fitted_model(log_txt)
#--- should not fail for finalized models ---# #--- should not fail for finalized models ---#
model$finalize() model$.__enclos_env__$private$finalize()
# print() # print()
log_txt <- capture.output({ log_txt <- capture.output({
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment