diff --git a/NAMESPACE b/NAMESPACE index 5aa01e8e..9353ae42 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -112,6 +112,7 @@ S3method(print,PlRWhen__bundle) S3method(print,polars_data_frame) S3method(print,polars_dtype) S3method(print,polars_expr) +S3method(print,polars_info) S3method(print,polars_lazy_frame) S3method(print,polars_object) S3method(print,polars_series) @@ -146,5 +147,6 @@ export(is_polars_lf) export(is_polars_selector) export(is_polars_series) export(pl) +export(polars_info) import(rlang) useDynLib(neopolars, .registration = TRUE) diff --git a/R/000-wrappers.R b/R/000-wrappers.R index 1360fbc9..640bc6c8 100644 --- a/R/000-wrappers.R +++ b/R/000-wrappers.R @@ -38,6 +38,16 @@ NULL } +`rust_polars_version` <- function() { + .Call(savvy_rust_polars_version__impl) +} + + +`thread_pool_size` <- function() { + .Call(savvy_thread_pool_size__impl) +} + + `all_horizontal` <- function(`exprs`) { .savvy_wrap_PlRExpr(.Call(savvy_all_horizontal__impl, `exprs`)) } diff --git a/R/polars_info.R b/R/polars_info.R new file mode 100644 index 00000000..c5a50cc2 --- /dev/null +++ b/R/polars_info.R @@ -0,0 +1,38 @@ +#' @export +polars_info <- function() { + # Similar to arrow::arrow_info() + out <- list( + versions = list( + r_package = as.character(utils::packageVersion("polars")), + rust_crate = rust_polars_version() + ), + thread_pool_size = thread_pool_size() + # TODO-REWRITE: enable those + # features = cargo_rpolars_feature_info(), + # code_completion = .polars_autocompletion$mode %||% "deactivated" + ) + structure(out, class = "polars_info") +} + +#' @noRd +#' @export +print.polars_info <- function(x, ...) { + # Copied from the arrow package + # https://github.com/apache/arrow/blob/6f3bd2524c2abe3a4a278fc1c62fc5c49b56cab3/r/R/arrow-info.R#L149-L157 + print_key_values <- function(title, vals, ...) { + df <- data.frame(vals, ...) + names(df) <- "" + + cat(title, ":", sep = "") + print(df) + cat("\n") + } + + cat("Polars R package version : ", format(x$versions$r_package), "\n", sep = "") + cat("Rust Polars crate version: ", format(x$versions$rust_crate), "\n", sep = "") + cat("\n") + cat("Thread pool size:", x$thread_pool_size, "\n") + # cat("\n") + # print_key_values("Features", unlist(x$features)) + # cat("Code completion:", x$code_completion, "\n") +} diff --git a/src/init.c b/src/init.c index 274c52b9..4cb7f45d 100644 --- a/src/init.c +++ b/src/init.c @@ -34,6 +34,16 @@ SEXP handle_result(SEXP res_) { return (SEXP)res; } +SEXP savvy_rust_polars_version__impl(void) { + SEXP res = savvy_rust_polars_version__ffi(); + return handle_result(res); +} + +SEXP savvy_thread_pool_size__impl(void) { + SEXP res = savvy_thread_pool_size__ffi(); + return handle_result(res); +} + SEXP savvy_all_horizontal__impl(SEXP c_arg__exprs) { SEXP res = savvy_all_horizontal__ffi(c_arg__exprs); return handle_result(res); @@ -2516,6 +2526,8 @@ SEXP savvy_PlRWhen_then__impl(SEXP self__, SEXP c_arg__statement) { static const R_CallMethodDef CallEntries[] = { + {"savvy_rust_polars_version__impl", (DL_FUNC) &savvy_rust_polars_version__impl, 0}, + {"savvy_thread_pool_size__impl", (DL_FUNC) &savvy_thread_pool_size__impl, 0}, {"savvy_all_horizontal__impl", (DL_FUNC) &savvy_all_horizontal__impl, 1}, {"savvy_any_horizontal__impl", (DL_FUNC) &savvy_any_horizontal__impl, 1}, {"savvy_max_horizontal__impl", (DL_FUNC) &savvy_max_horizontal__impl, 1}, diff --git a/src/rust/api.h b/src/rust/api.h index 2d625e2b..225f3cbf 100644 --- a/src/rust/api.h +++ b/src/rust/api.h @@ -1,3 +1,5 @@ +SEXP savvy_rust_polars_version__ffi(void); +SEXP savvy_thread_pool_size__ffi(void); SEXP savvy_all_horizontal__ffi(SEXP c_arg__exprs); SEXP savvy_any_horizontal__ffi(SEXP c_arg__exprs); SEXP savvy_max_horizontal__ffi(SEXP c_arg__exprs); diff --git a/src/rust/src/info.rs b/src/rust/src/info.rs new file mode 100644 index 00000000..5fd33c13 --- /dev/null +++ b/src/rust/src/info.rs @@ -0,0 +1,11 @@ +use savvy::{savvy, Result, Sexp}; + +#[savvy] +fn rust_polars_version() -> Result { + polars::VERSION.try_into() +} + +#[savvy] +fn thread_pool_size() -> Result { + (polars_core::POOL.current_num_threads() as i32).try_into() +} diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 57766103..23fe6dc0 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -6,6 +6,7 @@ mod datatypes; mod error; mod expr; mod functions; +mod info; mod lazyframe; mod lazygroupby; mod map; diff --git a/tests/testthat/_snaps/polars_info.md b/tests/testthat/_snaps/polars_info.md new file mode 100644 index 00000000..c8e84284 --- /dev/null +++ b/tests/testthat/_snaps/polars_info.md @@ -0,0 +1,10 @@ +# print polars_info() + + Code + info + Output + Polars R package version : 999.999.999 + Rust Polars crate version: 999.999.999 + + Thread pool size: 1 + diff --git a/tests/testthat/test-polars_info.R b/tests/testthat/test-polars_info.R new file mode 100644 index 00000000..c8d84163 --- /dev/null +++ b/tests/testthat/test-polars_info.R @@ -0,0 +1,31 @@ +patrick::with_parameters_test_that("polars_info() features are logical", + { + expect_type(feature, "logical") + expect_length(feature, 1) + }, + feature = polars_info()$features +) + +test_that("print polars_info()", { + info <- polars_info() + + expect_type(info$versions$r_package, "character") + expect_type(info$versions$rust_crate, "character") + + # Ensure static version for snapshot test + info$versions$r_package <- "999.999.999" + info$versions$rust_crate <- "999.999.999" + + # Ensure the thread_pool_size is 1 for snapshot test + info$thread_pool_size <- 1 + + # Ensure all features are FALSE for snapshot test + for (feature in names(info$features)) { + info$features[[feature]] <- FALSE + } + + # Ensure code_completion is deactivated for snapshot test + info$code_completion <- "deactivated" + + expect_snapshot(info) +})