diff --git a/R/as_polars.R b/R/as_polars.R index 80536629d..3dc2f3ed0 100644 --- a/R/as_polars.R +++ b/R/as_polars.R @@ -420,19 +420,39 @@ as_polars_series.nanoarrow_array = function(x, name = NULL, ...) { } +#' @param experimental If `TRUE`, use experimental Arrow C stream interface inside the function. +#' This argument is experimental and may be removed in the future. #' @rdname as_polars_series #' @export -as_polars_series.nanoarrow_array_stream = function(x, name = NULL, ...) { +as_polars_series.nanoarrow_array_stream = function(x, name = NULL, ..., experimental = FALSE) { on.exit(x$release()) - stream_out = polars_allocate_array_stream() - nanoarrow::nanoarrow_pointer_export(x, stream_out) + if (isTRUE(experimental)) { + stream_out = polars_allocate_array_stream() + nanoarrow::nanoarrow_pointer_export(x, stream_out) - .pr$Series$import_stream( - name %||% "", - stream_out - ) |> - unwrap("in as_polars_series():") + .pr$Series$import_stream( + name %||% "", + stream_out + ) |> + unwrap("in as_polars_series():") + } else { + list_of_arrays = nanoarrow::collect_array_stream(x, validate = FALSE) + + if (length(list_of_arrays) < 1L) { + # TODO: support 0-length array stream + out = pl$Series(name = name) + } else { + out = as_polars_series.nanoarrow_array(list_of_arrays[[1L]], name = name) + lapply( + list_of_arrays[-1L], + \(array) .pr$Series$append_mut(out, as_polars_series.nanoarrow_array(array)) + ) |> + invisible() + } + + out + } } diff --git a/man/as_polars_series.Rd b/man/as_polars_series.Rd index 3050db228..6cffd5ccd 100644 --- a/man/as_polars_series.Rd +++ b/man/as_polars_series.Rd @@ -47,7 +47,7 @@ as_polars_series(x, name = NULL, ...) \method{as_polars_series}{nanoarrow_array}(x, name = NULL, ...) -\method{as_polars_series}{nanoarrow_array_stream}(x, name = NULL, ...) +\method{as_polars_series}{nanoarrow_array_stream}(x, name = NULL, ..., experimental = FALSE) \method{as_polars_series}{clock_time_point}(x, name = NULL, ...) @@ -67,6 +67,9 @@ will be used if \code{x} has no name.} \item{...}{Additional arguments passed to methods.} \item{rechunk}{A logical flag (default \code{TRUE}). Make sure that all data is in contiguous memory.} + +\item{experimental}{If \code{TRUE}, use experimental Arrow C stream interface inside the function. +This argument is experimental and may be removed in the future.} } \value{ a \link[=Series_class]{Series} diff --git a/tests/testthat/test-as_polars.R b/tests/testthat/test-as_polars.R index 33bd38683..5dbf1835b 100644 --- a/tests/testthat/test-as_polars.R +++ b/tests/testthat/test-as_polars.R @@ -470,15 +470,23 @@ test_that("as_polars_df and pl$DataFrame for data.frame has list column", { test_that("automatically rechunked for struct array stream", { skip_if_not_installed("nanoarrow") - s_int = nanoarrow::basic_array_stream( + s_int_exp = nanoarrow::basic_array_stream( list( nanoarrow::as_nanoarrow_array(1:5), nanoarrow::as_nanoarrow_array(6:10) ) ) |> - as_polars_series() + as_polars_series(experimental = TRUE) + + s_struct_exp = nanoarrow::basic_array_stream( + list( + nanoarrow::as_nanoarrow_array(mtcars[1:5, ]), + nanoarrow::as_nanoarrow_array(mtcars[6:10, ]) + ) + ) |> + as_polars_series(experimental = TRUE) - s_struct = nanoarrow::basic_array_stream( + s_struct_stable = nanoarrow::basic_array_stream( list( nanoarrow::as_nanoarrow_array(mtcars[1:5, ]), nanoarrow::as_nanoarrow_array(mtcars[6:10, ]) @@ -486,6 +494,7 @@ test_that("automatically rechunked for struct array stream", { ) |> as_polars_series() - expect_identical(s_int$n_chunks(), 2) - expect_identical(s_struct$n_chunks(), 1) + expect_identical(s_int_exp$n_chunks(), 2) + expect_identical(s_struct_exp$n_chunks(), 1) + expect_identical(s_struct_stable$n_chunks(), 2) })