diff --git a/apis/r/DESCRIPTION b/apis/r/DESCRIPTION index 48056b0e0e..b2f12104b8 100644 --- a/apis/r/DESCRIPTION +++ b/apis/r/DESCRIPTION @@ -6,7 +6,7 @@ Description: Interface for working with 'TileDB'-based Stack of Matrices, like those commonly used for single cell data analysis. It is documented at ; a formal specification available is at . -Version: 1.15.99.9 +Version: 1.15.99.10 Authors@R: c( person(given = "Aaron", family = "Wolen", role = c("cre", "aut"), email = "aaron@tiledb.com", diff --git a/apis/r/NEWS.md b/apis/r/NEWS.md index 9b2ef68912..4eac934637 100644 --- a/apis/r/NEWS.md +++ b/apis/r/NEWS.md @@ -17,6 +17,7 @@ * Fix `is_named_list` bug for half-named lists [#3183](https://github.com/single-cell-data/TileDB-SOMA/pull/3183) * Expose block/random writer for sparse arrays [#3204](https://github.com/single-cell-data/TileDB-SOMA/pull/3204) * Min-sizing for dataframes/arrays with new shape feature [#3208](https://github.com/single-cell-data/TileDB-SOMA/pull/3208) +* Proper prefixing for shape-related methods [#3237](https://github.com/single-cell-data/TileDB-SOMA/pull/3237) # tiledbsoma 1.14.1 diff --git a/apis/r/R/RcppExports.R b/apis/r/R/RcppExports.R index 7f73472cf0..4ae5d15dd7 100644 --- a/apis/r/R/RcppExports.R +++ b/apis/r/R/RcppExports.R @@ -238,16 +238,16 @@ c_schema <- function(uri, ctxxp) { .Call(`_tiledbsoma_c_schema`, uri, ctxxp) } -resize <- function(uri, new_shape, ctxxp) { - invisible(.Call(`_tiledbsoma_resize`, uri, new_shape, ctxxp)) +resize <- function(uri, new_shape, function_name_for_messages, ctxxp) { + invisible(.Call(`_tiledbsoma_resize`, uri, new_shape, function_name_for_messages, ctxxp)) } -resize_soma_joinid_shape <- function(uri, new_shape, ctxxp) { - invisible(.Call(`_tiledbsoma_resize_soma_joinid_shape`, uri, new_shape, ctxxp)) +resize_soma_joinid_shape <- function(uri, new_shape, function_name_for_messages, ctxxp) { + invisible(.Call(`_tiledbsoma_resize_soma_joinid_shape`, uri, new_shape, function_name_for_messages, ctxxp)) } -tiledbsoma_upgrade_shape <- function(uri, new_shape, ctxxp) { - invisible(.Call(`_tiledbsoma_tiledbsoma_upgrade_shape`, uri, new_shape, ctxxp)) +tiledbsoma_upgrade_shape <- function(uri, new_shape, function_name_for_messages, ctxxp) { + invisible(.Call(`_tiledbsoma_tiledbsoma_upgrade_shape`, uri, new_shape, function_name_for_messages, ctxxp)) } c_update_dataframe_schema <- function(uri, ctxxp, column_names_to_drop, add_cols_types, add_cols_enum_value_types, add_cols_enum_ordered) { diff --git a/apis/r/R/SOMADataFrame.R b/apis/r/R/SOMADataFrame.R index 88372e3891..41f17e0ea9 100644 --- a/apis/r/R/SOMADataFrame.R +++ b/apis/r/R/SOMADataFrame.R @@ -415,13 +415,14 @@ SOMADataFrame <- R6::R6Class( #' @param new_shape An integer, greater than or equal to 1 + the #' `soma_joinid` domain slot. #' @return No return value - resize_soma_joinid_shape = function(new_shape) { - + tiledbsoma_resize_soma_joinid_shape = function(new_shape) { stopifnot("'new_shape' must be an integer" = rlang::is_integerish(new_shape, n = 1) || (bit64::is.integer64(new_shape) && length(new_shape) == 1) ) # Checking slotwise new shape >= old shape, and <= max_shape, is already done in libtiledbsoma - invisible(resize_soma_joinid_shape(self$uri, new_shape, private$.soma_context)) + invisible( + resize_soma_joinid_shape( + self$uri, new_shape, .name_of_function(), private$.soma_context)) } ), diff --git a/apis/r/R/SOMANDArrayBase.R b/apis/r/R/SOMANDArrayBase.R index 22c6419aee..4ee664eb5a 100644 --- a/apis/r/R/SOMANDArrayBase.R +++ b/apis/r/R/SOMANDArrayBase.R @@ -108,7 +108,7 @@ SOMANDArrayBase <- R6::R6Class( (bit64::is.integer64(new_shape) && length(new_shape) == self$ndim()) ) # Checking slotwise new shape >= old shape, and <= max_shape, is already done in libtiledbsoma - resize(self$uri, new_shape, private$.soma_context) + resize(self$uri, new_shape, .name_of_function(), private$.soma_context) }, #' @description Allows the array to have a resizeable shape as described in the @@ -125,7 +125,7 @@ SOMANDArrayBase <- R6::R6Class( (bit64::is.integer64(shape) && length(shape) == self$ndim()) ) # Checking slotwise new shape >= old shape, and <= max_shape, is already done in libtiledbsoma - tiledbsoma_upgrade_shape(self$uri, shape, private$.soma_context) + tiledbsoma_upgrade_shape(self$uri, shape, .name_of_function(), private$.soma_context) } ), diff --git a/apis/r/R/utils.R b/apis/r/R/utils.R index 5ffe90390b..29268f502e 100644 --- a/apis/r/R/utils.R +++ b/apis/r/R/utils.R @@ -303,3 +303,22 @@ SOMA_ENCODING_VERSION <- "1.1.0" ##' @importFrom spdl setup ##' @useDynLib tiledbsoma, .registration=TRUE NULL + +# This is for internal logging purposes. Context: +# * We have R (and Python) code with function names the user invokes. +# * These call C++ functions which can throw their own error messages. +# * It's crucial that the C++ code "knows" the name of the function +# as typed by the user, not whatever (possibly out-of-date) guess +# the C++ code may have. +.name_of_function <- function() { + # Tricky bits: + # * This might be `obj$foo` + # * The sys.call can return a parse-tree component (typeof = language) + # with the '$', 'obj', and 'foo' -- hence the as.character + # * Even then there can be a second component returned like 'c(1)' + # -- hence the [[1]] + # * Then remove the 'obj$' from 'obj$foo' + name <- as.character(sys.call(sys.parent(n=1)))[[1]] + name <- sub('.*\\$', replacement = '', x = name) + return(name) +} diff --git a/apis/r/R/write_soma.R b/apis/r/R/write_soma.R index 6e1dc1353f..c5887db716 100644 --- a/apis/r/R/write_soma.R +++ b/apis/r/R/write_soma.R @@ -259,7 +259,7 @@ write_soma.data.frame <- function( } } if (ingest_mode %in% c('resume') && sdf$tiledbsoma_has_upgraded_domain()) { - sdf$resize_soma_joinid_shape(nrow(x)) + sdf$tiledbsoma_resize_soma_joinid_shape(nrow(x)) } if (!is.null(tbl)) { sdf$write(tbl) diff --git a/apis/r/src/RcppExports.cpp b/apis/r/src/RcppExports.cpp index 772071e714..30aab500f0 100644 --- a/apis/r/src/RcppExports.cpp +++ b/apis/r/src/RcppExports.cpp @@ -553,38 +553,41 @@ BEGIN_RCPP END_RCPP } // resize -void resize(const std::string& uri, Rcpp::NumericVector new_shape, Rcpp::XPtr ctxxp); -RcppExport SEXP _tiledbsoma_resize(SEXP uriSEXP, SEXP new_shapeSEXP, SEXP ctxxpSEXP) { +void resize(const std::string& uri, Rcpp::NumericVector new_shape, std::string function_name_for_messages, Rcpp::XPtr ctxxp); +RcppExport SEXP _tiledbsoma_resize(SEXP uriSEXP, SEXP new_shapeSEXP, SEXP function_name_for_messagesSEXP, SEXP ctxxpSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< const std::string& >::type uri(uriSEXP); Rcpp::traits::input_parameter< Rcpp::NumericVector >::type new_shape(new_shapeSEXP); + Rcpp::traits::input_parameter< std::string >::type function_name_for_messages(function_name_for_messagesSEXP); Rcpp::traits::input_parameter< Rcpp::XPtr >::type ctxxp(ctxxpSEXP); - resize(uri, new_shape, ctxxp); + resize(uri, new_shape, function_name_for_messages, ctxxp); return R_NilValue; END_RCPP } // resize_soma_joinid_shape -void resize_soma_joinid_shape(const std::string& uri, Rcpp::NumericVector new_shape, Rcpp::XPtr ctxxp); -RcppExport SEXP _tiledbsoma_resize_soma_joinid_shape(SEXP uriSEXP, SEXP new_shapeSEXP, SEXP ctxxpSEXP) { +void resize_soma_joinid_shape(const std::string& uri, Rcpp::NumericVector new_shape, std::string function_name_for_messages, Rcpp::XPtr ctxxp); +RcppExport SEXP _tiledbsoma_resize_soma_joinid_shape(SEXP uriSEXP, SEXP new_shapeSEXP, SEXP function_name_for_messagesSEXP, SEXP ctxxpSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< const std::string& >::type uri(uriSEXP); Rcpp::traits::input_parameter< Rcpp::NumericVector >::type new_shape(new_shapeSEXP); + Rcpp::traits::input_parameter< std::string >::type function_name_for_messages(function_name_for_messagesSEXP); Rcpp::traits::input_parameter< Rcpp::XPtr >::type ctxxp(ctxxpSEXP); - resize_soma_joinid_shape(uri, new_shape, ctxxp); + resize_soma_joinid_shape(uri, new_shape, function_name_for_messages, ctxxp); return R_NilValue; END_RCPP } // tiledbsoma_upgrade_shape -void tiledbsoma_upgrade_shape(const std::string& uri, Rcpp::NumericVector new_shape, Rcpp::XPtr ctxxp); -RcppExport SEXP _tiledbsoma_tiledbsoma_upgrade_shape(SEXP uriSEXP, SEXP new_shapeSEXP, SEXP ctxxpSEXP) { +void tiledbsoma_upgrade_shape(const std::string& uri, Rcpp::NumericVector new_shape, std::string function_name_for_messages, Rcpp::XPtr ctxxp); +RcppExport SEXP _tiledbsoma_tiledbsoma_upgrade_shape(SEXP uriSEXP, SEXP new_shapeSEXP, SEXP function_name_for_messagesSEXP, SEXP ctxxpSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< const std::string& >::type uri(uriSEXP); Rcpp::traits::input_parameter< Rcpp::NumericVector >::type new_shape(new_shapeSEXP); + Rcpp::traits::input_parameter< std::string >::type function_name_for_messages(function_name_for_messagesSEXP); Rcpp::traits::input_parameter< Rcpp::XPtr >::type ctxxp(ctxxpSEXP); - tiledbsoma_upgrade_shape(uri, new_shape, ctxxp); + tiledbsoma_upgrade_shape(uri, new_shape, function_name_for_messages, ctxxp); return R_NilValue; END_RCPP } @@ -816,9 +819,9 @@ static const R_CallMethodDef CallEntries[] = { {"_tiledbsoma_c_dimnames", (DL_FUNC) &_tiledbsoma_c_dimnames, 2}, {"_tiledbsoma_c_attrnames", (DL_FUNC) &_tiledbsoma_c_attrnames, 2}, {"_tiledbsoma_c_schema", (DL_FUNC) &_tiledbsoma_c_schema, 2}, - {"_tiledbsoma_resize", (DL_FUNC) &_tiledbsoma_resize, 3}, - {"_tiledbsoma_resize_soma_joinid_shape", (DL_FUNC) &_tiledbsoma_resize_soma_joinid_shape, 3}, - {"_tiledbsoma_tiledbsoma_upgrade_shape", (DL_FUNC) &_tiledbsoma_tiledbsoma_upgrade_shape, 3}, + {"_tiledbsoma_resize", (DL_FUNC) &_tiledbsoma_resize, 4}, + {"_tiledbsoma_resize_soma_joinid_shape", (DL_FUNC) &_tiledbsoma_resize_soma_joinid_shape, 4}, + {"_tiledbsoma_tiledbsoma_upgrade_shape", (DL_FUNC) &_tiledbsoma_tiledbsoma_upgrade_shape, 4}, {"_tiledbsoma_c_update_dataframe_schema", (DL_FUNC) &_tiledbsoma_c_update_dataframe_schema, 6}, {"_tiledbsoma_sr_setup", (DL_FUNC) &_tiledbsoma_sr_setup, 10}, {"_tiledbsoma_sr_complete", (DL_FUNC) &_tiledbsoma_sr_complete, 1}, diff --git a/apis/r/src/rinterface.cpp b/apis/r/src/rinterface.cpp index 0d4f3271d2..6682a225fc 100644 --- a/apis/r/src/rinterface.cpp +++ b/apis/r/src/rinterface.cpp @@ -421,6 +421,7 @@ SEXP c_schema(const std::string& uri, Rcpp::XPtr ctxxp) { void resize( const std::string& uri, Rcpp::NumericVector new_shape, + std::string function_name_for_messages, Rcpp::XPtr ctxxp) { // This function is solely for SparseNDArray and DenseNDArray for which the // dims are required by the SOMA spec to be of type int64. Domain-resize for @@ -428,7 +429,7 @@ void resize( // https://github.com/single-cell-data/TileDB-SOMA/issues/2407. auto sr = tdbs::SOMAArray::open(OpenMode::write, uri, ctxxp->ctxptr); std::vector new_shape_i64 = i64_from_rcpp_numeric(new_shape); - sr->resize(new_shape_i64, "resize"); + sr->resize(new_shape_i64, function_name_for_messages); sr->close(); } @@ -436,11 +437,12 @@ void resize( void resize_soma_joinid_shape( const std::string& uri, Rcpp::NumericVector new_shape, + std::string function_name_for_messages, Rcpp::XPtr ctxxp) { // This function is solely for SOMADataFrame. auto sr = tdbs::SOMADataFrame::open(uri, OpenMode::write, ctxxp->ctxptr); std::vector new_shape_i64 = i64_from_rcpp_numeric(new_shape); - sr->resize_soma_joinid_shape(new_shape_i64[0], "resize_soma_joinid_shape"); + sr->resize_soma_joinid_shape(new_shape_i64[0], function_name_for_messages); sr->close(); } @@ -448,6 +450,7 @@ void resize_soma_joinid_shape( void tiledbsoma_upgrade_shape( const std::string& uri, Rcpp::NumericVector new_shape, + std::string function_name_for_messages, Rcpp::XPtr ctxxp) { // This function is solely for SparseNDArray and DenseNDArray for which the // dims are required by the SOMA spec to be of type int64. Domain-resize for @@ -455,7 +458,7 @@ void tiledbsoma_upgrade_shape( // https://github.com/single-cell-data/TileDB-SOMA/issues/2407. auto sr = tdbs::SOMAArray::open(OpenMode::write, uri, ctxxp->ctxptr); std::vector new_shape_i64 = i64_from_rcpp_numeric(new_shape); - sr->upgrade_shape(new_shape_i64, "tiledbsoma_upgrade_shape"); + sr->upgrade_shape(new_shape_i64, function_name_for_messages); sr->close(); } diff --git a/apis/r/tests/testthat/test-shape.R b/apis/r/tests/testthat/test-shape.R index e4a11cc9f0..589f17454b 100644 --- a/apis/r/tests/testthat/test-shape.R +++ b/apis/r/tests/testthat/test-shape.R @@ -199,11 +199,11 @@ test_that("SOMADataFrame shape", { sdf <- SOMADataFrameOpen(uri, "WRITE") if (has_soma_joinid_dim) { # It's an error to downsize - expect_error(sdf$resize_soma_joinid_shape(new_shape)) + expect_error(sdf$tiledbsoma_resize_soma_joinid_shape(new_shape)) } else { # There is no problem when soma_joinid is not a dim -- - # sdf$resize_soma_joinid_shape is a no-op in that case - expect_no_condition(sdf$resize_soma_joinid_shape(new_shape)) + # sdf$tiledbsoma_resize_soma_joinid_shape is a no-op in that case + expect_no_condition(sdf$tiledbsoma_resize_soma_joinid_shape(new_shape)) } sdf$close() @@ -238,7 +238,7 @@ test_that("SOMADataFrame shape", { # Test resize sdf <- SOMADataFrameOpen(uri, "WRITE") - sdf$resize_soma_joinid_shape(new_shape) + sdf$tiledbsoma_resize_soma_joinid_shape(new_shape) sdf$close(); # Test writes out of old bounds, within new bounds, after resize diff --git a/apis/r/tests/testthat/test-write-soma-resume.R b/apis/r/tests/testthat/test-write-soma-resume.R index 79be4e91bb..4db132b7a1 100644 --- a/apis/r/tests/testthat/test-write-soma-resume.R +++ b/apis/r/tests/testthat/test-write-soma-resume.R @@ -166,7 +166,7 @@ test_that("Resume-mode data frames", { if (.new_shape_feature_flag_is_enabled()) { sdfp$reopen("WRITE") - sdfp$resize_soma_joinid_shape(nrow(co2)) + sdfp$tiledbsoma_resize_soma_joinid_shape(nrow(co2)) } expect_s3_class( diff --git a/libtiledbsoma/src/soma/soma_array.cc b/libtiledbsoma/src/soma/soma_array.cc index b9f664327c..2fe336fc55 100644 --- a/libtiledbsoma/src/soma/soma_array.cc +++ b/libtiledbsoma/src/soma/soma_array.cc @@ -1665,14 +1665,14 @@ void SOMAArray::_set_shape_helper( // Upgrading an array to install a current domain if (!_get_current_domain().is_empty()) { throw TileDBSOMAError(fmt::format( - "{}: array must not already have a shape", + "{}: array must not already have a shape: please upgrade it", function_name_for_messages)); } } else { // Expanding an array's current domain if (_get_current_domain().is_empty()) { throw TileDBSOMAError(fmt::format( - "{} array must already have a shape", + "{} array must already have a shape: please upgrade it", function_name_for_messages)); } }