Skip to content

Commit

Permalink
Prevent unnamed non-Field elements in pl$Struct()
Browse files Browse the repository at this point in the history
  • Loading branch information
etiennebacher committed Apr 22, 2024
1 parent 0a73217 commit a1faf84
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 32 deletions.
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## polars (development version)

### Breaking changes

- `pl$Struct()` now only accepts named inputs and objects of class `RPolarsField`.
For example, `pl$Struct(pl$Boolean)` doesn't work anymore and should be named
like `pl$Struct(a = pl$Boolean)` (#1053).

## polars 0.16.1

This is a small hot-fix release to update dependent Rust polars to 0.39.1 (#1042).
Expand Down
48 changes: 22 additions & 26 deletions R/datatype.R
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,15 @@ DataType_Duration = function(time_unit = "us") {
#' multiple ways to create columns of data type `Struct` in a `DataFrame` or
#' a `Series`, see the examples.
#'
#' @param ... RPolarsDataType objects
#' @return a list DataType with an inner DataType
#' @param ... Either named inputs of the form `field_name = datatype` or objects
#' of class `RPolarsField` created by [`pl$Field()`][pl_Field].
#' @return A Struct DataType containing a list of Fields
#' @examples
#' # create a Struct-DataType
#' pl$Struct(pl$Boolean)
#' pl$Struct(foo = pl$Int32, bar = pl$Float64)
#' pl$Struct(foo = pl$Int32, pl$Field("bar", pl$Boolean))
#'
#' # check if an element is any kind of Struct()
#' test = pl$Struct(pl$UInt64)
#' test = pl$Struct(a = pl$UInt64)
#' pl$same_outer_dt(test, pl$Struct())
#'
#' # `test` is a type of Struct, but it doesn't mean it is equal to an empty Struct
Expand Down Expand Up @@ -251,34 +251,30 @@ DataType_Duration = function(time_unit = "us") {
#'
#' out$schema
DataType_Struct = function(...) {
uw = \(res) unwrap(res, "in pl$Struct():")
err_message = Err_plain("`pl$Struct()` only accepts named inputs or input of class RPolarsField.")
result({
largs = list2(...)
if (length(largs) >= 1 && is.list(largs[[1]])) {
largs = largs[[1]]
element_name = "list element"
} else {
element_name = "positional argument"
}
mapply(
names(largs) %||% character(length(largs)),
largs,
seq_along(largs),
FUN = \(name, arg, i) {
if (inherits(arg, "RPolarsDataType")) {
return(pl$Field(name, arg))
}
if (inherits(arg, "RPolarsRField")) {
return(arg)
}
stop(sprintf(
"%s [%s] {name:'%s', value:%s} must either be a Field (pl$Field) or a named DataType",
element_name, i, name, arg
))
}, SIMPLIFY = FALSE
)
lapply(seq_along(largs), function(x) {
name = names(largs)[x]
dtype = largs[[x]]
if (inherits(dtype, "RPolarsRField")) {
return(dtype)
}
if (is.null(name)) {
err_message |> uw()
}
if (inherits(dtype, "RPolarsDataType")) {
return(pl$Field(name, dtype))
}
err_message |> uw()
})
}) |>
and_then(DataType$new_struct) |>
unwrap("in pl$Struct:")
uw()
}

#' Create Array DataType
Expand Down
10 changes: 5 additions & 5 deletions man/DataType_Struct.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/testthat/test-datatype.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test_that("plStruct", {
# wrong uses
expect_grepl_error(
pl$Struct(bin = pl$Binary, pl$Boolean, "abc"),
"must either be a Field"
"only accepts named inputs or input of class RPolarsField."
)
})

Expand Down

0 comments on commit a1faf84

Please sign in to comment.