Skip to content

Commit 7da7ce0

Browse files
committed
test subclasses
1 parent 06438fc commit 7da7ce0

File tree

5 files changed

+82
-11
lines changed

5 files changed

+82
-11
lines changed

r/R/convert-array.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ convert_fallback_other <- function(array, offset, length, to) {
142142
#' @export
143143
convert_array.nanoarrow_vctr <- function(array, to, ...) {
144144
schema <- attr(to, "schema", exact = TRUE)
145-
as_nanoarrow_vctr(array, schema = schema)
145+
if (is.null(schema)) {
146+
schema <- infer_nanoarrow_schema(array)
147+
}
148+
149+
new_nanoarrow_vctr(list(array), schema, class(to))
146150
}
147151

148152
#' @export

r/R/vctr.R

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717

1818
#' Experimental Arrow encoded arrays as R vectors
1919
#'
20-
#' @param x An object that works with [as_nanoarrow_array_stream()]. Most
21-
#' spatial objects in R already work with this method.
20+
#' @param x An object that works with [as_nanoarrow_array_stream()].
21+
#' @param subclass An optional subclass of nanoarrow_vctr to prepend to the
22+
#' final class name.
2223
#' @param ... Passed to [as_nanoarrow_array_stream()]
2324
#' @param schema An optional `schema`
2425
#'
@@ -29,14 +30,14 @@
2930
#' array <- as_nanoarrow_array(1:5)
3031
#' as_nanoarrow_vctr(array)
3132
#'
32-
as_nanoarrow_vctr <- function(x, ..., schema = NULL) {
33+
as_nanoarrow_vctr <- function(x, ..., schema = NULL, subclass = character()) {
3334
if (inherits(x, "nanoarrow_vctr") && is.null(schema)) {
3435
return(x)
3536
}
3637

3738
stream <- as_nanoarrow_array_stream(x, ..., schema = schema)
3839
chunks <- collect_array_stream(stream, validate = FALSE)
39-
new_nanoarrow_vctr(chunks, stream$get_schema())
40+
new_nanoarrow_vctr(chunks, stream$get_schema(), subclass)
4041
}
4142

4243
#' @rdname as_nanoarrow_vctr
@@ -102,7 +103,12 @@ format.nanoarrow_vctr <- function(x, ...) {
102103
}
103104

104105
size_stable_format <- function(x, ...) {
105-
if (inherits(x, "data.frame")) {
106+
if (inherits(x, "nanoarrow_vctr")) {
107+
# Extension types could have a default convert that gives a nanoarrow_vctr.
108+
# If this is the case, they should be returning a subclass with a format
109+
# method that ensures we don't get here.
110+
rep(sprintf("<%s[%d]>", class(x)[1], seq_along(x)))
111+
} else if (inherits(x, "data.frame")) {
106112
cols <- lapply(x, size_stable_format, ...)
107113
cols <- Map(paste, names(x), cols, sep = ": ")
108114
rows <- do.call(paste, c(cols, list(sep = ", ")))
@@ -258,7 +264,13 @@ print.nanoarrow_vctr <- function(x, ...) {
258264
stream <- as_nanoarrow_array_stream(utils::head(x, n_values))
259265
converted_head <- convert_array_stream(stream)
260266

261-
print(converted_head)
267+
if (inherits(converted_head, "nanoarrow_vctr")) {
268+
converted_head <- format(converted_head)
269+
print(converted_head, quote = FALSE)
270+
} else {
271+
print(converted_head)
272+
}
273+
262274
if (more_values >= 2) {
263275
cat(sprintf("...and %d more values\n", more_values))
264276
} else if (more_values >= 1) {

r/man/as_nanoarrow_vctr.Rd

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

r/tests/testthat/test-convert-array.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,22 @@ test_that("batched convert to vector works for nanoarrow_vctr()", {
216216
)
217217
})
218218

219+
test_that("batched convert to vector works for nanoarrow_vctr() keeps subclass", {
220+
vctr_ptype <- nanoarrow_vctr(subclass = "some_subclass")
221+
222+
empty_stream <- basic_array_stream(list(), schema = na_string())
223+
empty_vctr <- convert_array_stream(empty_stream, vctr_ptype)
224+
expect_s3_class(empty_vctr, "some_subclass")
225+
226+
stream1 <- basic_array_stream(list(c("")))
227+
vctr1 <- convert_array_stream(stream1, vctr_ptype)
228+
expect_s3_class(vctr1, "some_subclass")
229+
230+
stream2 <- basic_array_stream(list(c(""), c("")))
231+
vctr2 <- convert_array_stream(stream2, vctr_ptype)
232+
expect_s3_class(vctr2, "some_subclass")
233+
})
234+
219235
test_that("convert to vector works for struct-style vectors", {
220236
array <- as_nanoarrow_array(as.POSIXlt("2021-01-01", tz = "America/Halifax"))
221237
expect_identical(

r/tests/testthat/test-extension.R

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,40 @@ test_that("as_nanoarrow_array() dispatches on registered extension spec", {
114114
"some_ext"
115115
)
116116
})
117+
118+
test_that("extensions can infer a schema of a nanoarrow_vctr() subclass", {
119+
register_nanoarrow_extension(
120+
"some_ext",
121+
nanoarrow_extension_spec(subclass = "vctr_spec_class")
122+
)
123+
on.exit(unregister_nanoarrow_extension("some_ext"))
124+
125+
infer_nanoarrow_ptype_extension.vctr_spec_class <- function(spec, x, ...) {
126+
nanoarrow_vctr(subclass = "some_vctr_subclass")
127+
}
128+
129+
s3_register(
130+
"nanoarrow::infer_nanoarrow_ptype_extension",
131+
"vctr_spec_class",
132+
infer_nanoarrow_ptype_extension.vctr_spec_class
133+
)
134+
135+
expect_identical(
136+
infer_nanoarrow_ptype(na_extension(na_string(), "some_ext")),
137+
nanoarrow_vctr(subclass = "some_vctr_subclass")
138+
)
139+
140+
ext_array <- nanoarrow_extension_array(c("one", "two", "three"), "some_ext")
141+
vctr <- convert_array(ext_array)
142+
expect_s3_class(vctr, "some_vctr_subclass")
143+
144+
# Ensure that registering a default conversion that returns a nanoarrow_vctr
145+
# does not result in infinite recursion when printing or formatting it.
146+
# An extension that does this should provide these methods for the subclass
147+
# they return.
148+
expect_length(format(vctr), length(vctr))
149+
expect_output(
150+
expect_identical(print(vctr), vctr),
151+
"some_vctr_subclass"
152+
)
153+
})

0 commit comments

Comments
 (0)