polars-df 0.15.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +274 -0
- data/Cargo.lock +1465 -867
- data/Cargo.toml +3 -0
- data/LICENSE.txt +2 -2
- data/README.md +87 -37
- data/ext/polars/Cargo.toml +47 -16
- data/ext/polars/src/c_api/allocator.rs +7 -0
- data/ext/polars/src/c_api/mod.rs +1 -0
- data/ext/polars/src/catalog/mod.rs +1 -0
- data/ext/polars/src/catalog/unity.rs +470 -0
- data/ext/polars/src/conversion/any_value.rs +99 -84
- data/ext/polars/src/conversion/categorical.rs +30 -0
- data/ext/polars/src/conversion/chunked_array.rs +71 -62
- data/ext/polars/src/conversion/datetime.rs +63 -0
- data/ext/polars/src/conversion/mod.rs +796 -312
- data/ext/polars/src/dataframe/construction.rs +6 -18
- data/ext/polars/src/dataframe/export.rs +30 -39
- data/ext/polars/src/dataframe/general.rs +294 -362
- data/ext/polars/src/dataframe/io.rs +33 -150
- data/ext/polars/src/dataframe/map.rs +175 -0
- data/ext/polars/src/dataframe/mod.rs +37 -5
- data/ext/polars/src/dataframe/serde.rs +23 -8
- data/ext/polars/src/error.rs +44 -7
- data/ext/polars/src/exceptions.rs +21 -8
- data/ext/polars/src/expr/array.rs +86 -22
- data/ext/polars/src/expr/binary.rs +50 -1
- data/ext/polars/src/expr/bitwise.rs +39 -0
- data/ext/polars/src/expr/categorical.rs +20 -0
- data/ext/polars/src/expr/datatype.rs +51 -0
- data/ext/polars/src/expr/datetime.rs +99 -41
- data/ext/polars/src/expr/extension.rs +12 -0
- data/ext/polars/src/expr/general.rs +252 -128
- data/ext/polars/src/expr/list.rs +56 -60
- data/ext/polars/src/expr/meta.rs +30 -35
- data/ext/polars/src/expr/mod.rs +28 -6
- data/ext/polars/src/expr/name.rs +29 -14
- data/ext/polars/src/expr/rolling.rs +111 -3
- data/ext/polars/src/expr/selector.rs +219 -0
- data/ext/polars/src/expr/serde.rs +28 -0
- data/ext/polars/src/expr/string.rs +118 -20
- data/ext/polars/src/expr/struct.rs +14 -1
- data/ext/polars/src/file.rs +194 -86
- data/ext/polars/src/functions/aggregation.rs +13 -12
- data/ext/polars/src/functions/business.rs +2 -3
- data/ext/polars/src/functions/eager.rs +3 -2
- data/ext/polars/src/functions/io.rs +90 -18
- data/ext/polars/src/functions/lazy.rs +267 -118
- data/ext/polars/src/functions/meta.rs +8 -7
- data/ext/polars/src/functions/misc.rs +1 -1
- data/ext/polars/src/functions/mod.rs +2 -1
- data/ext/polars/src/functions/range.rs +88 -31
- data/ext/polars/src/functions/strings.rs +6 -0
- data/ext/polars/src/functions/utils.rs +8 -0
- data/ext/polars/src/interop/arrow/mod.rs +52 -1
- data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +37 -7
- data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
- data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
- data/ext/polars/src/interop/numo/to_numo_series.rs +72 -50
- data/ext/polars/src/io/cloud_options.rs +107 -0
- data/ext/polars/src/io/mod.rs +4 -0
- data/ext/polars/src/io/scan_options.rs +113 -0
- data/ext/polars/src/io/sink_options.rs +46 -0
- data/ext/polars/src/io/sink_output.rs +21 -0
- data/ext/polars/src/lazyframe/exitable.rs +39 -0
- data/ext/polars/src/lazyframe/general.rs +846 -368
- data/ext/polars/src/lazyframe/mod.rs +58 -5
- data/ext/polars/src/lazyframe/optflags.rs +59 -0
- data/ext/polars/src/lazyframe/serde.rs +36 -4
- data/ext/polars/src/lazyframe/sink.rs +46 -0
- data/ext/polars/src/lazygroupby.rs +38 -9
- data/ext/polars/src/lib.rs +574 -165
- data/ext/polars/src/map/lazy.rs +44 -74
- data/ext/polars/src/map/mod.rs +18 -254
- data/ext/polars/src/map/series.rs +241 -1087
- data/ext/polars/src/on_startup.rs +192 -9
- data/ext/polars/src/prelude.rs +1 -0
- data/ext/polars/src/rb_modules.rs +10 -57
- data/ext/polars/src/ruby/exceptions.rs +26 -0
- data/ext/polars/src/ruby/gvl.rs +104 -0
- data/ext/polars/src/ruby/lazy.rs +46 -0
- data/ext/polars/src/ruby/mod.rs +11 -0
- data/ext/polars/src/ruby/numo.rs +52 -0
- data/ext/polars/src/ruby/plan_callback.rs +198 -0
- data/ext/polars/src/ruby/rb_modules.rs +16 -0
- data/ext/polars/src/ruby/ruby_convert_registry.rs +51 -0
- data/ext/polars/src/ruby/ruby_function.rs +11 -0
- data/ext/polars/src/ruby/ruby_udf.rs +164 -0
- data/ext/polars/src/ruby/thread.rs +65 -0
- data/ext/polars/src/ruby/utils.rs +39 -0
- data/ext/polars/src/series/aggregation.rs +116 -91
- data/ext/polars/src/series/arithmetic.rs +16 -22
- data/ext/polars/src/series/comparison.rs +101 -222
- data/ext/polars/src/series/construction.rs +80 -70
- data/ext/polars/src/series/export.rs +98 -56
- data/ext/polars/src/series/general.rs +323 -440
- data/ext/polars/src/series/import.rs +22 -5
- data/ext/polars/src/series/map.rs +103 -0
- data/ext/polars/src/series/mod.rs +57 -15
- data/ext/polars/src/series/scatter.rs +139 -82
- data/ext/polars/src/sql.rs +16 -9
- data/ext/polars/src/testing/frame.rs +31 -0
- data/ext/polars/src/testing/mod.rs +5 -0
- data/ext/polars/src/testing/series.rs +31 -0
- data/ext/polars/src/timeout.rs +105 -0
- data/ext/polars/src/utils.rs +105 -4
- data/lib/polars/array_expr.rb +500 -22
- data/lib/polars/array_name_space.rb +384 -10
- data/lib/polars/batched_csv_reader.rb +48 -66
- data/lib/polars/binary_expr.rb +217 -0
- data/lib/polars/binary_name_space.rb +155 -1
- data/lib/polars/cat_expr.rb +224 -0
- data/lib/polars/cat_name_space.rb +132 -32
- data/lib/polars/catalog/unity/catalog_info.rb +20 -0
- data/lib/polars/catalog/unity/column_info.rb +31 -0
- data/lib/polars/catalog/unity/namespace_info.rb +21 -0
- data/lib/polars/catalog/unity/table_info.rb +50 -0
- data/lib/polars/catalog.rb +448 -0
- data/lib/polars/collect_batches.rb +22 -0
- data/lib/polars/config.rb +3 -3
- data/lib/polars/convert.rb +201 -36
- data/lib/polars/data_frame.rb +2851 -1017
- data/lib/polars/data_frame_plot.rb +173 -0
- data/lib/polars/data_type_expr.rb +52 -0
- data/lib/polars/data_type_group.rb +6 -0
- data/lib/polars/data_types.rb +118 -18
- data/lib/polars/date_time_expr.rb +426 -84
- data/lib/polars/date_time_name_space.rb +384 -111
- data/lib/polars/dynamic_group_by.rb +102 -10
- data/lib/polars/exceptions.rb +50 -5
- data/lib/polars/expr.rb +2159 -915
- data/lib/polars/extension_expr.rb +39 -0
- data/lib/polars/extension_name_space.rb +39 -0
- data/lib/polars/functions/aggregation/horizontal.rb +11 -6
- data/lib/polars/functions/aggregation/vertical.rb +2 -3
- data/lib/polars/functions/as_datatype.rb +290 -8
- data/lib/polars/functions/business.rb +95 -0
- data/lib/polars/functions/col.rb +6 -5
- data/lib/polars/functions/datatype.rb +62 -0
- data/lib/polars/functions/eager.rb +426 -24
- data/lib/polars/functions/escape_regex.rb +21 -0
- data/lib/polars/functions/lazy.rb +813 -195
- data/lib/polars/functions/lit.rb +21 -10
- data/lib/polars/functions/range/int_range.rb +74 -2
- data/lib/polars/functions/range/linear_space.rb +195 -0
- data/lib/polars/functions/range/time_range.rb +1 -1
- data/lib/polars/functions/repeat.rb +7 -12
- data/lib/polars/functions/whenthen.rb +2 -2
- data/lib/polars/group_by.rb +188 -58
- data/lib/polars/iceberg_dataset.rb +108 -0
- data/lib/polars/in_process_query.rb +37 -0
- data/lib/polars/io/cloud.rb +18 -0
- data/lib/polars/io/csv.rb +336 -128
- data/lib/polars/io/database.rb +19 -4
- data/lib/polars/io/delta.rb +134 -0
- data/lib/polars/io/iceberg.rb +34 -0
- data/lib/polars/io/ipc.rb +63 -63
- data/lib/polars/io/json.rb +16 -0
- data/lib/polars/io/lines.rb +172 -0
- data/lib/polars/io/ndjson.rb +176 -20
- data/lib/polars/io/parquet.rb +173 -95
- data/lib/polars/io/scan_options.rb +55 -0
- data/lib/polars/io/sink_options.rb +27 -0
- data/lib/polars/io/utils.rb +17 -0
- data/lib/polars/lazy_frame.rb +3017 -622
- data/lib/polars/lazy_group_by.rb +436 -2
- data/lib/polars/list_expr.rb +551 -59
- data/lib/polars/list_name_space.rb +465 -51
- data/lib/polars/meta_expr.rb +146 -24
- data/lib/polars/name_expr.rb +87 -2
- data/lib/polars/query_opt_flags.rb +264 -0
- data/lib/polars/rolling_group_by.rb +90 -5
- data/lib/polars/scan_cast_options.rb +86 -0
- data/lib/polars/schema.rb +128 -0
- data/lib/polars/selector.rb +245 -0
- data/lib/polars/selectors.rb +1048 -201
- data/lib/polars/series.rb +2522 -774
- data/lib/polars/series_plot.rb +72 -0
- data/lib/polars/slice.rb +1 -1
- data/lib/polars/sql_context.rb +13 -6
- data/lib/polars/string_cache.rb +19 -72
- data/lib/polars/string_expr.rb +561 -107
- data/lib/polars/string_name_space.rb +781 -109
- data/lib/polars/struct_expr.rb +139 -18
- data/lib/polars/struct_name_space.rb +19 -1
- data/lib/polars/testing.rb +24 -273
- data/lib/polars/utils/constants.rb +2 -0
- data/lib/polars/utils/construction/data_frame.rb +410 -0
- data/lib/polars/utils/construction/series.rb +350 -0
- data/lib/polars/utils/construction/utils.rb +9 -0
- data/lib/polars/utils/convert.rb +18 -8
- data/lib/polars/utils/deprecation.rb +11 -0
- data/lib/polars/utils/parse.rb +62 -9
- data/lib/polars/utils/reduce_balanced.rb +43 -0
- data/lib/polars/utils/serde.rb +22 -0
- data/lib/polars/utils/unstable.rb +19 -0
- data/lib/polars/utils/various.rb +86 -1
- data/lib/polars/utils.rb +63 -48
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +85 -2
- metadata +80 -28
- data/ext/polars/src/allocator.rs +0 -13
- data/ext/polars/src/batched_csv.rs +0 -138
- data/ext/polars/src/functions/string_cache.rs +0 -25
- data/ext/polars/src/map/dataframe.rs +0 -338
- data/lib/polars/plot.rb +0 -109
|
@@ -1,46 +1,48 @@
|
|
|
1
1
|
pub(crate) mod any_value;
|
|
2
|
+
mod categorical;
|
|
2
3
|
mod chunked_array;
|
|
4
|
+
mod datetime;
|
|
3
5
|
|
|
6
|
+
use std::collections::BTreeMap;
|
|
4
7
|
use std::fmt::{Debug, Display, Formatter};
|
|
5
8
|
use std::fs::File;
|
|
6
9
|
use std::hash::{Hash, Hasher};
|
|
7
|
-
use std::num::NonZeroUsize;
|
|
8
|
-
use std::path::PathBuf;
|
|
9
10
|
|
|
11
|
+
pub use categorical::RbCategories;
|
|
10
12
|
use magnus::{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
IntoValue, Module, RArray, RHash, Ruby, Symbol, TryConvert, Value, prelude::*, r_hash::ForEach,
|
|
14
|
+
try_convert::TryConvertOwned, value::Opaque,
|
|
13
15
|
};
|
|
14
16
|
use polars::chunked_array::object::PolarsObjectSafe;
|
|
15
17
|
use polars::chunked_array::ops::{FillNullLimit, FillNullStrategy};
|
|
16
18
|
use polars::datatypes::AnyValue;
|
|
19
|
+
use polars::frame::PivotColumnNaming;
|
|
17
20
|
use polars::frame::row::Row;
|
|
18
|
-
use polars::frame::NullStrategy;
|
|
19
21
|
use polars::io::avro::AvroCompression;
|
|
20
|
-
use polars::
|
|
22
|
+
use polars::prelude::default_values::{
|
|
23
|
+
DefaultFieldValues, IcebergIdentityTransformedPartitionFields,
|
|
24
|
+
};
|
|
25
|
+
use polars::prelude::deletion::DeletionFilesList;
|
|
21
26
|
use polars::prelude::*;
|
|
22
27
|
use polars::series::ops::NullBehavior;
|
|
28
|
+
use polars_buffer::Buffer;
|
|
29
|
+
use polars_compute::decimal::dec128_verify_prec_scale;
|
|
30
|
+
use polars_core::schema::iceberg::IcebergSchema;
|
|
23
31
|
use polars_core::utils::arrow::array::Array;
|
|
24
32
|
use polars_core::utils::materialize_dyn_int;
|
|
25
|
-
use polars_plan::
|
|
33
|
+
use polars_plan::dsl::ScanSources;
|
|
34
|
+
use polars_utils::compression::{BrotliLevel, GzipLevel, ZstdLevel};
|
|
26
35
|
use polars_utils::total_ord::{TotalEq, TotalHash};
|
|
27
36
|
|
|
28
|
-
use crate::file::{
|
|
37
|
+
use crate::file::{RubyScanSourceInput, get_ruby_scan_source_input};
|
|
29
38
|
use crate::object::OBJECT_NAME;
|
|
30
|
-
use crate::rb_modules::
|
|
31
|
-
use crate::
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
pub(crate) fn vec_extract_wrapped<T>(buf: Vec<Wrap<T>>) -> Vec<T> {
|
|
40
|
-
// Safety:
|
|
41
|
-
// Wrap is transparent.
|
|
42
|
-
unsafe { std::mem::transmute(buf) }
|
|
43
|
-
}
|
|
39
|
+
use crate::rb_modules::pl_series;
|
|
40
|
+
use crate::ruby::gvl::GvlExt;
|
|
41
|
+
use crate::ruby::utils::TryIntoValue;
|
|
42
|
+
use crate::utils::to_rb_err;
|
|
43
|
+
use crate::{
|
|
44
|
+
RbDataFrame, RbExpr, RbLazyFrame, RbPolarsErr, RbResult, RbSeries, RbTypeError, RbValueError,
|
|
45
|
+
};
|
|
44
46
|
|
|
45
47
|
#[repr(transparent)]
|
|
46
48
|
pub struct Wrap<T>(pub T);
|
|
@@ -68,24 +70,22 @@ pub(crate) fn get_rbseq(obj: Value) -> RbResult<(RArray, usize)> {
|
|
|
68
70
|
|
|
69
71
|
pub(crate) fn get_df(obj: Value) -> RbResult<DataFrame> {
|
|
70
72
|
let rbdf = obj.funcall::<_, _, &RbDataFrame>("_df", ())?;
|
|
71
|
-
Ok(rbdf.df.
|
|
73
|
+
Ok(rbdf.df.read().clone())
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
pub(crate) fn get_lf(obj: Value) -> RbResult<LazyFrame> {
|
|
75
77
|
let rbdf = obj.funcall::<_, _, &RbLazyFrame>("_ldf", ())?;
|
|
76
|
-
Ok(rbdf.ldf.
|
|
78
|
+
Ok(rbdf.ldf.read().clone())
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
pub(crate) fn get_series(obj: Value) -> RbResult<Series> {
|
|
80
82
|
let rbs = obj.funcall::<_, _, &RbSeries>("_s", ())?;
|
|
81
|
-
Ok(rbs.series.
|
|
83
|
+
Ok(rbs.series.read().clone())
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
pub(crate) fn to_series(s: RbSeries) -> Value {
|
|
85
|
-
let series =
|
|
86
|
-
series
|
|
87
|
-
.funcall::<_, _, Value>("_from_rbseries", (s,))
|
|
88
|
-
.unwrap()
|
|
86
|
+
pub(crate) fn to_series(rb: &Ruby, s: RbSeries) -> RbResult<Value> {
|
|
87
|
+
let series = pl_series(rb);
|
|
88
|
+
series.funcall::<_, _, Value>("_from_rbseries", (s,))
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
impl TryConvert for Wrap<PlSmallStr> {
|
|
@@ -117,151 +117,175 @@ impl TryConvert for Wrap<NullValues> {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
fn struct_dict<'a>(
|
|
121
|
-
|
|
120
|
+
fn struct_dict<'a>(
|
|
121
|
+
ruby: &Ruby,
|
|
122
|
+
vals: impl Iterator<Item = AnyValue<'a>>,
|
|
123
|
+
flds: &[Field],
|
|
124
|
+
) -> RbResult<Value> {
|
|
125
|
+
let dict = ruby.hash_new();
|
|
122
126
|
for (fld, val) in flds.iter().zip(vals) {
|
|
123
|
-
dict.aset(fld.name().as_str(), Wrap(val)
|
|
127
|
+
dict.aset(fld.name().as_str(), Wrap(val).try_into_value_with(ruby)?)?;
|
|
124
128
|
}
|
|
125
|
-
dict.
|
|
129
|
+
Ok(dict.as_value())
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
impl
|
|
129
|
-
fn
|
|
130
|
-
|
|
132
|
+
impl TryIntoValue for Wrap<Series> {
|
|
133
|
+
fn try_into_value_with(self, ruby: &Ruby) -> RbResult<Value> {
|
|
134
|
+
to_series(ruby, RbSeries::new(self.0))
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
impl TryIntoValue for Wrap<DataType> {
|
|
139
|
+
fn try_into_value_with(self, ruby: &Ruby) -> RbResult<Value> {
|
|
140
|
+
let pl = crate::rb_modules::polars(ruby);
|
|
131
141
|
|
|
132
142
|
match self.0 {
|
|
133
143
|
DataType::Int8 => {
|
|
134
|
-
let class = pl.const_get::<_, Value>("Int8")
|
|
135
|
-
class.funcall("new", ())
|
|
144
|
+
let class = pl.const_get::<_, Value>("Int8")?;
|
|
145
|
+
class.funcall("new", ())
|
|
136
146
|
}
|
|
137
147
|
DataType::Int16 => {
|
|
138
|
-
let class = pl.const_get::<_, Value>("Int16")
|
|
139
|
-
class.funcall("new", ())
|
|
148
|
+
let class = pl.const_get::<_, Value>("Int16")?;
|
|
149
|
+
class.funcall("new", ())
|
|
140
150
|
}
|
|
141
151
|
DataType::Int32 => {
|
|
142
|
-
let class = pl.const_get::<_, Value>("Int32")
|
|
143
|
-
class.funcall("new", ())
|
|
152
|
+
let class = pl.const_get::<_, Value>("Int32")?;
|
|
153
|
+
class.funcall("new", ())
|
|
144
154
|
}
|
|
145
155
|
DataType::Int64 => {
|
|
146
|
-
let class = pl.const_get::<_, Value>("Int64")
|
|
147
|
-
class.funcall("new", ())
|
|
156
|
+
let class = pl.const_get::<_, Value>("Int64")?;
|
|
157
|
+
class.funcall("new", ())
|
|
158
|
+
}
|
|
159
|
+
DataType::Int128 => {
|
|
160
|
+
let class = pl.const_get::<_, Value>("Int128")?;
|
|
161
|
+
class.funcall("new", ())
|
|
148
162
|
}
|
|
149
163
|
DataType::UInt8 => {
|
|
150
|
-
let class = pl.const_get::<_, Value>("UInt8")
|
|
151
|
-
class.funcall("new", ())
|
|
164
|
+
let class = pl.const_get::<_, Value>("UInt8")?;
|
|
165
|
+
class.funcall("new", ())
|
|
152
166
|
}
|
|
153
167
|
DataType::UInt16 => {
|
|
154
|
-
let class = pl.const_get::<_, Value>("UInt16")
|
|
155
|
-
class.funcall("new", ())
|
|
168
|
+
let class = pl.const_get::<_, Value>("UInt16")?;
|
|
169
|
+
class.funcall("new", ())
|
|
156
170
|
}
|
|
157
171
|
DataType::UInt32 => {
|
|
158
|
-
let class = pl.const_get::<_, Value>("UInt32")
|
|
159
|
-
class.funcall("new", ())
|
|
172
|
+
let class = pl.const_get::<_, Value>("UInt32")?;
|
|
173
|
+
class.funcall("new", ())
|
|
160
174
|
}
|
|
161
175
|
DataType::UInt64 => {
|
|
162
|
-
let class = pl.const_get::<_, Value>("UInt64")
|
|
163
|
-
class.funcall("new", ())
|
|
176
|
+
let class = pl.const_get::<_, Value>("UInt64")?;
|
|
177
|
+
class.funcall("new", ())
|
|
178
|
+
}
|
|
179
|
+
DataType::UInt128 => {
|
|
180
|
+
let class = pl.const_get::<_, Value>("UInt128")?;
|
|
181
|
+
class.funcall("new", ())
|
|
182
|
+
}
|
|
183
|
+
DataType::Float16 => {
|
|
184
|
+
let class = pl.const_get::<_, Value>("Float16")?;
|
|
185
|
+
class.funcall("new", ())
|
|
164
186
|
}
|
|
165
187
|
DataType::Float32 => {
|
|
166
|
-
let class = pl.const_get::<_, Value>("Float32")
|
|
167
|
-
class.funcall("new", ())
|
|
188
|
+
let class = pl.const_get::<_, Value>("Float32")?;
|
|
189
|
+
class.funcall("new", ())
|
|
168
190
|
}
|
|
169
191
|
DataType::Float64 | DataType::Unknown(UnknownKind::Float) => {
|
|
170
|
-
let class = pl.const_get::<_, Value>("Float64")
|
|
171
|
-
class.funcall("new", ())
|
|
192
|
+
let class = pl.const_get::<_, Value>("Float64")?;
|
|
193
|
+
class.funcall("new", ())
|
|
172
194
|
}
|
|
173
195
|
DataType::Decimal(precision, scale) => {
|
|
174
|
-
let class = pl.const_get::<_, Value>("Decimal")
|
|
175
|
-
class
|
|
176
|
-
.funcall::<_, _, Value>("new", (precision, scale))
|
|
177
|
-
.unwrap()
|
|
196
|
+
let class = pl.const_get::<_, Value>("Decimal")?;
|
|
197
|
+
class.funcall::<_, _, Value>("new", (precision, scale))
|
|
178
198
|
}
|
|
179
199
|
DataType::Boolean => {
|
|
180
|
-
let class = pl.const_get::<_, Value>("Boolean")
|
|
181
|
-
class.funcall("new", ())
|
|
200
|
+
let class = pl.const_get::<_, Value>("Boolean")?;
|
|
201
|
+
class.funcall("new", ())
|
|
182
202
|
}
|
|
183
203
|
DataType::String | DataType::Unknown(UnknownKind::Str) => {
|
|
184
|
-
let class = pl.const_get::<_, Value>("String")
|
|
185
|
-
class.funcall("new", ())
|
|
204
|
+
let class = pl.const_get::<_, Value>("String")?;
|
|
205
|
+
class.funcall("new", ())
|
|
186
206
|
}
|
|
187
207
|
DataType::Binary => {
|
|
188
|
-
let class = pl.const_get::<_, Value>("Binary")
|
|
189
|
-
class.funcall("new", ())
|
|
208
|
+
let class = pl.const_get::<_, Value>("Binary")?;
|
|
209
|
+
class.funcall("new", ())
|
|
190
210
|
}
|
|
191
211
|
DataType::Array(inner, size) => {
|
|
192
|
-
let class = pl.const_get::<_, Value>("Array")
|
|
193
|
-
let inner = Wrap(*inner)
|
|
212
|
+
let class = pl.const_get::<_, Value>("Array")?;
|
|
213
|
+
let inner = Wrap(*inner).try_into_value_with(ruby)?;
|
|
194
214
|
let args = (inner, size);
|
|
195
|
-
class.funcall::<_, _, Value>("new", args)
|
|
215
|
+
class.funcall::<_, _, Value>("new", args)
|
|
196
216
|
}
|
|
197
217
|
DataType::List(inner) => {
|
|
198
|
-
let class = pl.const_get::<_, Value>("List")
|
|
199
|
-
let inner = Wrap(*inner)
|
|
200
|
-
class.funcall::<_, _, Value>("new", (inner,))
|
|
218
|
+
let class = pl.const_get::<_, Value>("List")?;
|
|
219
|
+
let inner = Wrap(*inner).try_into_value_with(ruby)?;
|
|
220
|
+
class.funcall::<_, _, Value>("new", (inner,))
|
|
201
221
|
}
|
|
202
222
|
DataType::Date => {
|
|
203
|
-
let class = pl.const_get::<_, Value>("Date")
|
|
204
|
-
class.funcall("new", ())
|
|
223
|
+
let class = pl.const_get::<_, Value>("Date")?;
|
|
224
|
+
class.funcall("new", ())
|
|
205
225
|
}
|
|
206
226
|
DataType::Datetime(tu, tz) => {
|
|
207
|
-
let datetime_class = pl.const_get::<_, Value>("Datetime")
|
|
208
|
-
datetime_class
|
|
209
|
-
|
|
210
|
-
.
|
|
227
|
+
let datetime_class = pl.const_get::<_, Value>("Datetime")?;
|
|
228
|
+
datetime_class.funcall::<_, _, Value>(
|
|
229
|
+
"new",
|
|
230
|
+
(tu.to_ascii(), tz.as_deref().map(|x| x.as_str())),
|
|
231
|
+
)
|
|
211
232
|
}
|
|
212
233
|
DataType::Duration(tu) => {
|
|
213
|
-
let duration_class = pl.const_get::<_, Value>("Duration")
|
|
214
|
-
duration_class
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
let
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
let
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
234
|
+
let duration_class = pl.const_get::<_, Value>("Duration")?;
|
|
235
|
+
duration_class.funcall::<_, _, Value>("new", (tu.to_ascii(),))
|
|
236
|
+
}
|
|
237
|
+
DataType::Object(_) => {
|
|
238
|
+
let class = pl.const_get::<_, Value>("Object")?;
|
|
239
|
+
class.funcall("new", ())
|
|
240
|
+
}
|
|
241
|
+
DataType::Categorical(cats, _) => {
|
|
242
|
+
let categories_class = pl.const_get::<_, Value>("Categories")?;
|
|
243
|
+
let categorical_class = pl.const_get::<_, Value>("Categorical")?;
|
|
244
|
+
let categories: Value = categories_class
|
|
245
|
+
.funcall("_from_rb_categories", (RbCategories::from(cats.clone()),))?;
|
|
246
|
+
let kwargs = ruby.hash_new();
|
|
247
|
+
kwargs.aset(ruby.to_symbol("categories"), categories)?;
|
|
248
|
+
categorical_class.funcall("new", (kwargs,))
|
|
249
|
+
}
|
|
250
|
+
DataType::Enum(_, mapping) => {
|
|
251
|
+
let categories = unsafe {
|
|
252
|
+
StringChunked::from_chunks(
|
|
253
|
+
PlSmallStr::from_static("category"),
|
|
254
|
+
vec![mapping.to_arrow(true)],
|
|
255
|
+
)
|
|
256
|
+
};
|
|
257
|
+
let class = pl.const_get::<_, Value>("Enum")?;
|
|
258
|
+
let series = to_series(ruby, categories.into_series().into())?;
|
|
259
|
+
class.funcall::<_, _, Value>("new", (series,))
|
|
235
260
|
}
|
|
236
261
|
DataType::Time => {
|
|
237
|
-
let class = pl.const_get::<_, Value>("Time")
|
|
238
|
-
class.funcall("new", ())
|
|
262
|
+
let class = pl.const_get::<_, Value>("Time")?;
|
|
263
|
+
class.funcall("new", ())
|
|
239
264
|
}
|
|
240
265
|
DataType::Struct(fields) => {
|
|
241
|
-
let field_class = pl.const_get::<_, Value>("Field")
|
|
266
|
+
let field_class = pl.const_get::<_, Value>("Field")?;
|
|
242
267
|
let iter = fields.iter().map(|fld| {
|
|
243
268
|
let name = fld.name().as_str();
|
|
244
|
-
let dtype = Wrap(fld.dtype().clone());
|
|
245
|
-
field_class
|
|
246
|
-
.funcall::<_, _, Value>("new", (name, dtype))
|
|
247
|
-
.unwrap()
|
|
269
|
+
let dtype = Wrap(fld.dtype().clone()).try_into_value_with(ruby);
|
|
270
|
+
dtype.and_then(|dt| field_class.funcall::<_, _, Value>("new", (name, dt)))
|
|
248
271
|
});
|
|
249
|
-
let fields =
|
|
250
|
-
let struct_class = pl.const_get::<_, Value>("Struct")
|
|
251
|
-
struct_class
|
|
252
|
-
.funcall::<_, _, Value>("new", (fields,))
|
|
253
|
-
.unwrap()
|
|
272
|
+
let fields = ruby.ary_try_from_iter(iter)?;
|
|
273
|
+
let struct_class = pl.const_get::<_, Value>("Struct")?;
|
|
274
|
+
struct_class.funcall::<_, _, Value>("new", (fields,))
|
|
254
275
|
}
|
|
255
276
|
DataType::Null => {
|
|
256
|
-
let class = pl.const_get::<_, Value>("Null")
|
|
257
|
-
class.funcall("new", ())
|
|
277
|
+
let class = pl.const_get::<_, Value>("Null")?;
|
|
278
|
+
class.funcall("new", ())
|
|
279
|
+
}
|
|
280
|
+
DataType::Extension(_typ, _storage) => {
|
|
281
|
+
todo!();
|
|
258
282
|
}
|
|
259
283
|
DataType::Unknown(UnknownKind::Int(v)) => {
|
|
260
|
-
Wrap(materialize_dyn_int(v).dtype()).
|
|
284
|
+
Wrap(materialize_dyn_int(v).dtype()).try_into_value_with(ruby)
|
|
261
285
|
}
|
|
262
286
|
DataType::Unknown(_) => {
|
|
263
|
-
let class = pl.const_get::<_, Value>("Unknown")
|
|
264
|
-
class.funcall("new", ())
|
|
287
|
+
let class = pl.const_get::<_, Value>("Unknown")?;
|
|
288
|
+
class.funcall("new", ())
|
|
265
289
|
}
|
|
266
290
|
DataType::BinaryOffset => {
|
|
267
291
|
unimplemented!()
|
|
@@ -270,24 +294,24 @@ impl IntoValue for Wrap<DataType> {
|
|
|
270
294
|
}
|
|
271
295
|
}
|
|
272
296
|
|
|
297
|
+
enum CategoricalOrdering {
|
|
298
|
+
Lexical,
|
|
299
|
+
}
|
|
300
|
+
|
|
273
301
|
impl IntoValue for Wrap<CategoricalOrdering> {
|
|
274
|
-
fn into_value_with(self,
|
|
275
|
-
|
|
276
|
-
CategoricalOrdering::Physical => "physical",
|
|
277
|
-
CategoricalOrdering::Lexical => "lexical",
|
|
278
|
-
};
|
|
279
|
-
ordering.into_value()
|
|
302
|
+
fn into_value_with(self, ruby: &Ruby) -> Value {
|
|
303
|
+
"lexical".into_value_with(ruby)
|
|
280
304
|
}
|
|
281
305
|
}
|
|
282
306
|
|
|
283
307
|
impl IntoValue for Wrap<TimeUnit> {
|
|
284
|
-
fn into_value_with(self,
|
|
308
|
+
fn into_value_with(self, ruby: &Ruby) -> Value {
|
|
285
309
|
let tu = match self.0 {
|
|
286
310
|
TimeUnit::Nanoseconds => "ns",
|
|
287
311
|
TimeUnit::Microseconds => "us",
|
|
288
312
|
TimeUnit::Milliseconds => "ms",
|
|
289
313
|
};
|
|
290
|
-
tu.
|
|
314
|
+
tu.into_value_with(ruby)
|
|
291
315
|
}
|
|
292
316
|
}
|
|
293
317
|
|
|
@@ -301,93 +325,120 @@ impl TryConvert for Wrap<Field> {
|
|
|
301
325
|
|
|
302
326
|
impl TryConvert for Wrap<DataType> {
|
|
303
327
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
304
|
-
let
|
|
328
|
+
let ruby = Ruby::get_with(ob);
|
|
329
|
+
let dtype = if ob.is_kind_of(ruby.class_class()) {
|
|
305
330
|
let name = ob.funcall::<_, _, String>("name", ())?;
|
|
306
331
|
match name.as_str() {
|
|
307
|
-
"Polars::UInt8" => DataType::UInt8,
|
|
308
|
-
"Polars::UInt16" => DataType::UInt16,
|
|
309
|
-
"Polars::UInt32" => DataType::UInt32,
|
|
310
|
-
"Polars::UInt64" => DataType::UInt64,
|
|
311
332
|
"Polars::Int8" => DataType::Int8,
|
|
312
333
|
"Polars::Int16" => DataType::Int16,
|
|
313
334
|
"Polars::Int32" => DataType::Int32,
|
|
314
335
|
"Polars::Int64" => DataType::Int64,
|
|
336
|
+
"Polars::Int128" => DataType::Int64,
|
|
337
|
+
"Polars::UInt8" => DataType::UInt8,
|
|
338
|
+
"Polars::UInt16" => DataType::UInt16,
|
|
339
|
+
"Polars::UInt32" => DataType::UInt32,
|
|
340
|
+
"Polars::UInt64" => DataType::UInt64,
|
|
341
|
+
"Polars::UInt128" => DataType::UInt128,
|
|
342
|
+
"Polars::Float16" => DataType::Float16,
|
|
343
|
+
"Polars::Float32" => DataType::Float32,
|
|
344
|
+
"Polars::Float64" => DataType::Float64,
|
|
345
|
+
"Polars::Boolean" => DataType::Boolean,
|
|
315
346
|
"Polars::String" => DataType::String,
|
|
316
347
|
"Polars::Binary" => DataType::Binary,
|
|
317
|
-
"Polars::
|
|
318
|
-
"Polars::
|
|
319
|
-
|
|
348
|
+
"Polars::Categorical" => DataType::from_categories(Categories::global()),
|
|
349
|
+
"Polars::Enum" => {
|
|
350
|
+
DataType::from_frozen_categories(FrozenCategories::new([]).unwrap())
|
|
351
|
+
}
|
|
320
352
|
"Polars::Date" => DataType::Date,
|
|
321
|
-
"Polars::Datetime" => DataType::Datetime(TimeUnit::Microseconds, None),
|
|
322
353
|
"Polars::Time" => DataType::Time,
|
|
354
|
+
"Polars::Datetime" => DataType::Datetime(TimeUnit::Microseconds, None),
|
|
323
355
|
"Polars::Duration" => DataType::Duration(TimeUnit::Microseconds),
|
|
324
|
-
"Polars::Decimal" =>
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
356
|
+
"Polars::Decimal" => {
|
|
357
|
+
return Err(RbTypeError::new_err(
|
|
358
|
+
"Decimal without precision/scale set is not a valid Polars datatype",
|
|
359
|
+
));
|
|
360
|
+
}
|
|
328
361
|
"Polars::List" => DataType::List(Box::new(DataType::Null)),
|
|
362
|
+
"Polars::Array" => DataType::Array(Box::new(DataType::Null), 0),
|
|
363
|
+
"Polars::Struct" => DataType::Struct(vec![]),
|
|
329
364
|
"Polars::Null" => DataType::Null,
|
|
365
|
+
"Polars::Object" => DataType::Object(OBJECT_NAME),
|
|
330
366
|
"Polars::Unknown" => DataType::Unknown(Default::default()),
|
|
331
367
|
dt => {
|
|
332
|
-
return Err(
|
|
333
|
-
"{dt} is not a
|
|
334
|
-
)))
|
|
368
|
+
return Err(RbTypeError::new_err(format!(
|
|
369
|
+
"'{dt}' is not a Polars data type",
|
|
370
|
+
)));
|
|
335
371
|
}
|
|
336
372
|
}
|
|
337
|
-
} else
|
|
338
|
-
let
|
|
373
|
+
} else {
|
|
374
|
+
let cls = ob.class();
|
|
375
|
+
let name = unsafe { cls.name() }.into_owned();
|
|
339
376
|
match name.as_str() {
|
|
340
377
|
"Polars::Int8" => DataType::Int8,
|
|
341
378
|
"Polars::Int16" => DataType::Int16,
|
|
342
379
|
"Polars::Int32" => DataType::Int32,
|
|
343
380
|
"Polars::Int64" => DataType::Int64,
|
|
381
|
+
"Polars::Int128" => DataType::Int128,
|
|
344
382
|
"Polars::UInt8" => DataType::UInt8,
|
|
345
383
|
"Polars::UInt16" => DataType::UInt16,
|
|
346
384
|
"Polars::UInt32" => DataType::UInt32,
|
|
347
385
|
"Polars::UInt64" => DataType::UInt64,
|
|
386
|
+
"Polars::UInt128" => DataType::UInt128,
|
|
387
|
+
"Polars::Float16" => DataType::Float16,
|
|
388
|
+
"Polars::Float32" => DataType::Float32,
|
|
389
|
+
"Polars::Float64" => DataType::Float64,
|
|
390
|
+
"Polars::Boolean" => DataType::Boolean,
|
|
348
391
|
"Polars::String" => DataType::String,
|
|
349
392
|
"Polars::Binary" => DataType::Binary,
|
|
350
|
-
"Polars::Boolean" => DataType::Boolean,
|
|
351
393
|
"Polars::Categorical" => {
|
|
352
|
-
let
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
DataType::Categorical(None, ordering)
|
|
394
|
+
let categories: Value = ob.funcall("categories", ())?;
|
|
395
|
+
let rb_categories: &RbCategories = categories.funcall("_categories", ())?;
|
|
396
|
+
DataType::from_categories(rb_categories.categories().clone())
|
|
356
397
|
}
|
|
357
398
|
"Polars::Enum" => {
|
|
358
|
-
let categories = ob.funcall("categories", ())
|
|
399
|
+
let categories: Value = ob.funcall("categories", ())?;
|
|
359
400
|
let s = get_series(categories)?;
|
|
360
401
|
let ca = s.str().map_err(RbPolarsErr::from)?;
|
|
361
402
|
let categories = ca.downcast_iter().next().unwrap().clone();
|
|
362
|
-
|
|
403
|
+
assert!(!categories.has_nulls());
|
|
404
|
+
DataType::from_frozen_categories(
|
|
405
|
+
FrozenCategories::new(categories.values_iter()).unwrap(),
|
|
406
|
+
)
|
|
363
407
|
}
|
|
364
408
|
"Polars::Date" => DataType::Date,
|
|
365
409
|
"Polars::Time" => DataType::Time,
|
|
366
|
-
"Polars::Float32" => DataType::Float32,
|
|
367
|
-
"Polars::Float64" => DataType::Float64,
|
|
368
|
-
"Polars::Null" => DataType::Null,
|
|
369
|
-
"Polars::Unknown" => DataType::Unknown(Default::default()),
|
|
370
|
-
"Polars::Duration" => {
|
|
371
|
-
let time_unit: Value = ob.funcall("time_unit", ()).unwrap();
|
|
372
|
-
let time_unit = Wrap::<TimeUnit>::try_convert(time_unit)?.0;
|
|
373
|
-
DataType::Duration(time_unit)
|
|
374
|
-
}
|
|
375
410
|
"Polars::Datetime" => {
|
|
376
|
-
let time_unit: Value = ob.funcall("time_unit", ())
|
|
411
|
+
let time_unit: Value = ob.funcall("time_unit", ())?;
|
|
377
412
|
let time_unit = Wrap::<TimeUnit>::try_convert(time_unit)?.0;
|
|
378
413
|
let time_zone: Option<String> = ob.funcall("time_zone", ())?;
|
|
379
|
-
DataType::Datetime(
|
|
414
|
+
DataType::Datetime(
|
|
415
|
+
time_unit,
|
|
416
|
+
TimeZone::opt_try_new(time_zone.as_deref()).map_err(RbPolarsErr::from)?,
|
|
417
|
+
)
|
|
418
|
+
}
|
|
419
|
+
"Polars::Duration" => {
|
|
420
|
+
let time_unit: Value = ob.funcall("time_unit", ())?;
|
|
421
|
+
let time_unit = Wrap::<TimeUnit>::try_convert(time_unit)?.0;
|
|
422
|
+
DataType::Duration(time_unit)
|
|
380
423
|
}
|
|
381
424
|
"Polars::Decimal" => {
|
|
382
425
|
let precision = ob.funcall("precision", ())?;
|
|
383
426
|
let scale = ob.funcall("scale", ())?;
|
|
384
|
-
|
|
427
|
+
dec128_verify_prec_scale(precision, scale).map_err(to_rb_err)?;
|
|
428
|
+
DataType::Decimal(precision, scale)
|
|
385
429
|
}
|
|
386
430
|
"Polars::List" => {
|
|
387
|
-
let inner: Value = ob.funcall("inner", ())
|
|
431
|
+
let inner: Value = ob.funcall("inner", ())?;
|
|
388
432
|
let inner = Wrap::<DataType>::try_convert(inner)?;
|
|
389
433
|
DataType::List(Box::new(inner.0))
|
|
390
434
|
}
|
|
435
|
+
"Polars::Array" => {
|
|
436
|
+
let inner: Value = ob.funcall("inner", ())?;
|
|
437
|
+
let size: Value = ob.funcall("size", ())?;
|
|
438
|
+
let inner = Wrap::<DataType>::try_convert(inner)?;
|
|
439
|
+
let size = usize::try_convert(size)?;
|
|
440
|
+
DataType::Array(Box::new(inner.0), size)
|
|
441
|
+
}
|
|
391
442
|
"Polars::Struct" => {
|
|
392
443
|
let arr: RArray = ob.funcall("fields", ())?;
|
|
393
444
|
let mut fields = Vec::with_capacity(arr.len());
|
|
@@ -396,42 +447,13 @@ impl TryConvert for Wrap<DataType> {
|
|
|
396
447
|
}
|
|
397
448
|
DataType::Struct(fields)
|
|
398
449
|
}
|
|
450
|
+
"Polars::Null" => DataType::Null,
|
|
451
|
+
"Polars::Object" => DataType::Object(OBJECT_NAME),
|
|
452
|
+
"Polars::Unknown" => DataType::Unknown(Default::default()),
|
|
399
453
|
dt => {
|
|
400
454
|
return Err(RbTypeError::new_err(format!(
|
|
401
|
-
"
|
|
402
|
-
|
|
403
|
-
)))
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
} else {
|
|
407
|
-
match String::try_convert(ob)?.as_str() {
|
|
408
|
-
"u8" => DataType::UInt8,
|
|
409
|
-
"u16" => DataType::UInt16,
|
|
410
|
-
"u32" => DataType::UInt32,
|
|
411
|
-
"u64" => DataType::UInt64,
|
|
412
|
-
"i8" => DataType::Int8,
|
|
413
|
-
"i16" => DataType::Int16,
|
|
414
|
-
"i32" => DataType::Int32,
|
|
415
|
-
"i64" => DataType::Int64,
|
|
416
|
-
"str" => DataType::String,
|
|
417
|
-
"bin" => DataType::Binary,
|
|
418
|
-
"bool" => DataType::Boolean,
|
|
419
|
-
"cat" => DataType::Categorical(None, Default::default()),
|
|
420
|
-
"date" => DataType::Date,
|
|
421
|
-
"datetime" => DataType::Datetime(TimeUnit::Microseconds, None),
|
|
422
|
-
"f32" => DataType::Float32,
|
|
423
|
-
"time" => DataType::Time,
|
|
424
|
-
"dur" => DataType::Duration(TimeUnit::Microseconds),
|
|
425
|
-
"f64" => DataType::Float64,
|
|
426
|
-
"obj" => DataType::Object(OBJECT_NAME, None),
|
|
427
|
-
"list" => DataType::List(Box::new(DataType::Boolean)),
|
|
428
|
-
"null" => DataType::Null,
|
|
429
|
-
"unk" => DataType::Unknown(Default::default()),
|
|
430
|
-
_ => {
|
|
431
|
-
return Err(RbValueError::new_err(format!(
|
|
432
|
-
"{} is not a supported DataType.",
|
|
433
|
-
ob
|
|
434
|
-
)))
|
|
455
|
+
"'{dt}' is not a Polars data type",
|
|
456
|
+
)));
|
|
435
457
|
}
|
|
436
458
|
}
|
|
437
459
|
};
|
|
@@ -455,7 +477,7 @@ impl TryConvert for Wrap<StatisticsOptions> {
|
|
|
455
477
|
_ => {
|
|
456
478
|
return Err(RbTypeError::new_err(format!(
|
|
457
479
|
"'{key}' is not a valid statistic option",
|
|
458
|
-
)))
|
|
480
|
+
)));
|
|
459
481
|
}
|
|
460
482
|
}
|
|
461
483
|
Ok(ForEach::Continue)
|
|
@@ -478,7 +500,7 @@ impl<'s> TryConvert for Wrap<Row<'s>> {
|
|
|
478
500
|
|
|
479
501
|
impl TryConvert for Wrap<Schema> {
|
|
480
502
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
481
|
-
let dict =
|
|
503
|
+
let dict: RHash = ob.funcall("to_h", ())?;
|
|
482
504
|
|
|
483
505
|
let mut schema = Vec::new();
|
|
484
506
|
dict.foreach(|key: String, val: Wrap<DataType>| {
|
|
@@ -490,6 +512,60 @@ impl TryConvert for Wrap<Schema> {
|
|
|
490
512
|
}
|
|
491
513
|
}
|
|
492
514
|
|
|
515
|
+
impl TryConvert for Wrap<ArrowSchema> {
|
|
516
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
517
|
+
let ruby = Ruby::get_with(ob);
|
|
518
|
+
// TODO improve
|
|
519
|
+
let ob = RHash::try_convert(ob)?;
|
|
520
|
+
let fields: RArray = ob.aref(ruby.to_symbol("fields"))?;
|
|
521
|
+
let mut arrow_schema = ArrowSchema::with_capacity(fields.len());
|
|
522
|
+
for f in fields {
|
|
523
|
+
let f = RHash::try_convert(f)?;
|
|
524
|
+
let name: String = f.aref(ruby.to_symbol("name"))?;
|
|
525
|
+
let rb_dtype: String = f.aref(ruby.to_symbol("type"))?;
|
|
526
|
+
let dtype = match rb_dtype.as_str() {
|
|
527
|
+
"null" => ArrowDataType::Null,
|
|
528
|
+
"boolean" => ArrowDataType::Boolean,
|
|
529
|
+
"int8" => ArrowDataType::Int8,
|
|
530
|
+
"int16" => ArrowDataType::Int16,
|
|
531
|
+
"int32" => ArrowDataType::Int32,
|
|
532
|
+
"int64" => ArrowDataType::Int64,
|
|
533
|
+
"uint8" => ArrowDataType::UInt8,
|
|
534
|
+
"uint16" => ArrowDataType::UInt16,
|
|
535
|
+
"uint32" => ArrowDataType::UInt32,
|
|
536
|
+
"uint64" => ArrowDataType::UInt64,
|
|
537
|
+
"float16" => ArrowDataType::Float16,
|
|
538
|
+
"float32" => ArrowDataType::Float32,
|
|
539
|
+
"float64" => ArrowDataType::Float64,
|
|
540
|
+
"date32" => ArrowDataType::Date32,
|
|
541
|
+
"date64" => ArrowDataType::Date64,
|
|
542
|
+
"binary" => ArrowDataType::Binary,
|
|
543
|
+
"large_binary" => ArrowDataType::LargeBinary,
|
|
544
|
+
"string" => ArrowDataType::Utf8,
|
|
545
|
+
"large_string" => ArrowDataType::LargeUtf8,
|
|
546
|
+
"binary_view" => ArrowDataType::BinaryView,
|
|
547
|
+
"string_view" => ArrowDataType::Utf8View,
|
|
548
|
+
"unknown" => ArrowDataType::Unknown,
|
|
549
|
+
_ => todo!(),
|
|
550
|
+
};
|
|
551
|
+
let is_nullable = f.aref(ruby.to_symbol("nullable"))?;
|
|
552
|
+
let rb_metadata: RHash = f.aref(ruby.to_symbol("metadata"))?;
|
|
553
|
+
let mut metadata = BTreeMap::new();
|
|
554
|
+
rb_metadata.foreach(|k: String, v: String| {
|
|
555
|
+
metadata.insert(k.into(), v.into());
|
|
556
|
+
Ok(ForEach::Continue)
|
|
557
|
+
})?;
|
|
558
|
+
arrow_schema
|
|
559
|
+
.try_insert(
|
|
560
|
+
name.clone().into(),
|
|
561
|
+
ArrowField::new(name.into(), dtype, is_nullable).with_metadata(metadata),
|
|
562
|
+
)
|
|
563
|
+
.map_err(to_rb_err)?;
|
|
564
|
+
}
|
|
565
|
+
Ok(Wrap(arrow_schema))
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
493
569
|
impl TryConvert for Wrap<ScanSources> {
|
|
494
570
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
495
571
|
let list = RArray::try_convert(ob)?;
|
|
@@ -499,9 +575,9 @@ impl TryConvert for Wrap<ScanSources> {
|
|
|
499
575
|
}
|
|
500
576
|
|
|
501
577
|
enum MutableSources {
|
|
502
|
-
Paths(Vec<
|
|
578
|
+
Paths(Vec<PlRefPath>),
|
|
503
579
|
Files(Vec<File>),
|
|
504
|
-
Buffers(Vec<
|
|
580
|
+
Buffers(Vec<Buffer<u8>>),
|
|
505
581
|
}
|
|
506
582
|
|
|
507
583
|
let num_items = list.len();
|
|
@@ -540,7 +616,7 @@ impl TryConvert for Wrap<ScanSources> {
|
|
|
540
616
|
return Err(RbTypeError::new_err(
|
|
541
617
|
"Cannot combine in-memory bytes, paths and files for scan sources"
|
|
542
618
|
.to_string(),
|
|
543
|
-
))
|
|
619
|
+
));
|
|
544
620
|
}
|
|
545
621
|
}
|
|
546
622
|
}
|
|
@@ -553,6 +629,16 @@ impl TryConvert for Wrap<ScanSources> {
|
|
|
553
629
|
}
|
|
554
630
|
}
|
|
555
631
|
|
|
632
|
+
impl TryIntoValue for Wrap<Schema> {
|
|
633
|
+
fn try_into_value_with(self, ruby: &Ruby) -> RbResult<Value> {
|
|
634
|
+
let dict = ruby.hash_new();
|
|
635
|
+
for (k, v) in self.0.iter() {
|
|
636
|
+
dict.aset(k.as_str(), Wrap(v.clone()).try_into_value_with(ruby)?)?;
|
|
637
|
+
}
|
|
638
|
+
Ok(dict.as_value())
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
556
642
|
#[derive(Clone)]
|
|
557
643
|
pub struct ObjectValue {
|
|
558
644
|
pub inner: Opaque<Value>,
|
|
@@ -560,18 +646,17 @@ pub struct ObjectValue {
|
|
|
560
646
|
|
|
561
647
|
impl Debug for ObjectValue {
|
|
562
648
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
563
|
-
f
|
|
564
|
-
.field("inner", &self.to_value())
|
|
565
|
-
.finish()
|
|
649
|
+
write!(f, "{}", self)
|
|
566
650
|
}
|
|
567
651
|
}
|
|
568
652
|
|
|
569
653
|
impl Hash for ObjectValue {
|
|
570
654
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
571
|
-
let h =
|
|
572
|
-
.
|
|
573
|
-
|
|
574
|
-
|
|
655
|
+
let h = Ruby::attach(|rb| {
|
|
656
|
+
rb.get_inner(self.inner)
|
|
657
|
+
.funcall::<_, _, isize>("hash", ())
|
|
658
|
+
.expect("should be hashable")
|
|
659
|
+
});
|
|
575
660
|
state.write_isize(h)
|
|
576
661
|
}
|
|
577
662
|
}
|
|
@@ -580,7 +665,11 @@ impl Eq for ObjectValue {}
|
|
|
580
665
|
|
|
581
666
|
impl PartialEq for ObjectValue {
|
|
582
667
|
fn eq(&self, other: &Self) -> bool {
|
|
583
|
-
|
|
668
|
+
Ruby::attach(|ruby| {
|
|
669
|
+
ruby.get_inner(self.inner)
|
|
670
|
+
.eql(ruby.get_inner(other.inner))
|
|
671
|
+
.unwrap_or(false)
|
|
672
|
+
})
|
|
584
673
|
}
|
|
585
674
|
}
|
|
586
675
|
|
|
@@ -601,7 +690,10 @@ impl TotalHash for ObjectValue {
|
|
|
601
690
|
|
|
602
691
|
impl Display for ObjectValue {
|
|
603
692
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
604
|
-
|
|
693
|
+
Ruby::attach(|rb| {
|
|
694
|
+
let v = rb.get_inner(self.inner);
|
|
695
|
+
write!(f, "{}", v)
|
|
696
|
+
})
|
|
605
697
|
}
|
|
606
698
|
}
|
|
607
699
|
|
|
@@ -629,12 +721,6 @@ impl From<&dyn PolarsObjectSafe> for &ObjectValue {
|
|
|
629
721
|
}
|
|
630
722
|
}
|
|
631
723
|
|
|
632
|
-
impl ObjectValue {
|
|
633
|
-
pub fn to_value(&self) -> Value {
|
|
634
|
-
self.clone().into_value()
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
724
|
impl IntoValue for ObjectValue {
|
|
639
725
|
fn into_value_with(self, ruby: &Ruby) -> Value {
|
|
640
726
|
ruby.get_inner(self.inner)
|
|
@@ -643,9 +729,9 @@ impl IntoValue for ObjectValue {
|
|
|
643
729
|
|
|
644
730
|
impl Default for ObjectValue {
|
|
645
731
|
fn default() -> Self {
|
|
646
|
-
ObjectValue {
|
|
647
|
-
inner:
|
|
648
|
-
}
|
|
732
|
+
Ruby::attach(|rb| ObjectValue {
|
|
733
|
+
inner: rb.qnil().as_value().into(),
|
|
734
|
+
})
|
|
649
735
|
}
|
|
650
736
|
}
|
|
651
737
|
|
|
@@ -658,7 +744,7 @@ impl TryConvert for Wrap<AsofStrategy> {
|
|
|
658
744
|
v => {
|
|
659
745
|
return Err(RbValueError::new_err(format!(
|
|
660
746
|
"asof `strategy` must be one of {{'backward', 'forward', 'nearest'}}, got {v}",
|
|
661
|
-
)))
|
|
747
|
+
)));
|
|
662
748
|
}
|
|
663
749
|
};
|
|
664
750
|
Ok(Wrap(parsed))
|
|
@@ -673,7 +759,7 @@ impl TryConvert for Wrap<InterpolationMethod> {
|
|
|
673
759
|
v => {
|
|
674
760
|
return Err(RbValueError::new_err(format!(
|
|
675
761
|
"method must be one of {{'linear', 'nearest'}}, got {v}",
|
|
676
|
-
)))
|
|
762
|
+
)));
|
|
677
763
|
}
|
|
678
764
|
};
|
|
679
765
|
Ok(Wrap(parsed))
|
|
@@ -688,9 +774,8 @@ impl TryConvert for Wrap<Option<AvroCompression>> {
|
|
|
688
774
|
"deflate" => Some(AvroCompression::Deflate),
|
|
689
775
|
v => {
|
|
690
776
|
return Err(RbValueError::new_err(format!(
|
|
691
|
-
"compression must be one of {{'uncompressed', 'snappy', 'deflate'}}, got {}"
|
|
692
|
-
|
|
693
|
-
)))
|
|
777
|
+
"compression must be one of {{'uncompressed', 'snappy', 'deflate'}}, got {v}"
|
|
778
|
+
)));
|
|
694
779
|
}
|
|
695
780
|
};
|
|
696
781
|
Ok(Wrap(parsed))
|
|
@@ -700,13 +785,18 @@ impl TryConvert for Wrap<Option<AvroCompression>> {
|
|
|
700
785
|
impl TryConvert for Wrap<CategoricalOrdering> {
|
|
701
786
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
702
787
|
let parsed = match String::try_convert(ob)?.as_str() {
|
|
703
|
-
"physical" => CategoricalOrdering::Physical,
|
|
704
788
|
"lexical" => CategoricalOrdering::Lexical,
|
|
789
|
+
"physical" => {
|
|
790
|
+
polars_warn!(
|
|
791
|
+
Deprecation,
|
|
792
|
+
"physical ordering is deprecated, will use lexical ordering instead"
|
|
793
|
+
);
|
|
794
|
+
CategoricalOrdering::Lexical
|
|
795
|
+
}
|
|
705
796
|
v => {
|
|
706
797
|
return Err(RbValueError::new_err(format!(
|
|
707
|
-
"ordering must be one of {{'physical', 'lexical'}}, got {}"
|
|
708
|
-
|
|
709
|
-
)))
|
|
798
|
+
"ordering must be one of {{'physical', 'lexical'}}, got {v}"
|
|
799
|
+
)));
|
|
710
800
|
}
|
|
711
801
|
};
|
|
712
802
|
Ok(Wrap(parsed))
|
|
@@ -722,7 +812,7 @@ impl TryConvert for Wrap<StartBy> {
|
|
|
722
812
|
v => {
|
|
723
813
|
return Err(RbValueError::new_err(format!(
|
|
724
814
|
"closed must be one of {{'window', 'datapoint', 'monday'}}, got {v}",
|
|
725
|
-
)))
|
|
815
|
+
)));
|
|
726
816
|
}
|
|
727
817
|
};
|
|
728
818
|
Ok(Wrap(parsed))
|
|
@@ -738,9 +828,23 @@ impl TryConvert for Wrap<ClosedWindow> {
|
|
|
738
828
|
"none" => ClosedWindow::None,
|
|
739
829
|
v => {
|
|
740
830
|
return Err(RbValueError::new_err(format!(
|
|
741
|
-
"closed must be one of {{'left', 'right', 'both', 'none'}}, got {}"
|
|
742
|
-
|
|
743
|
-
|
|
831
|
+
"closed must be one of {{'left', 'right', 'both', 'none'}}, got {v}"
|
|
832
|
+
)));
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
Ok(Wrap(parsed))
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
impl TryConvert for Wrap<RoundMode> {
|
|
840
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
841
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
842
|
+
"half_to_even" => RoundMode::HalfToEven,
|
|
843
|
+
"half_away_from_zero" => RoundMode::HalfAwayFromZero,
|
|
844
|
+
v => {
|
|
845
|
+
return Err(RbValueError::new_err(format!(
|
|
846
|
+
"`mode` must be one of {{'half_to_even', 'half_away_from_zero'}}, got {v}",
|
|
847
|
+
)));
|
|
744
848
|
}
|
|
745
849
|
};
|
|
746
850
|
Ok(Wrap(parsed))
|
|
@@ -754,9 +858,8 @@ impl TryConvert for Wrap<CsvEncoding> {
|
|
|
754
858
|
"utf8-lossy" => CsvEncoding::LossyUtf8,
|
|
755
859
|
v => {
|
|
756
860
|
return Err(RbValueError::new_err(format!(
|
|
757
|
-
"encoding must be one of {{'utf8', 'utf8-lossy'}}, got {}"
|
|
758
|
-
|
|
759
|
-
)))
|
|
861
|
+
"encoding must be one of {{'utf8', 'utf8-lossy'}}, got {v}"
|
|
862
|
+
)));
|
|
760
863
|
}
|
|
761
864
|
};
|
|
762
865
|
Ok(Wrap(parsed))
|
|
@@ -768,12 +871,11 @@ impl TryConvert for Wrap<Option<IpcCompression>> {
|
|
|
768
871
|
let parsed = match String::try_convert(ob)?.as_str() {
|
|
769
872
|
"uncompressed" => None,
|
|
770
873
|
"lz4" => Some(IpcCompression::LZ4),
|
|
771
|
-
"zstd" => Some(IpcCompression::ZSTD),
|
|
874
|
+
"zstd" => Some(IpcCompression::ZSTD(Default::default())),
|
|
772
875
|
v => {
|
|
773
876
|
return Err(RbValueError::new_err(format!(
|
|
774
|
-
"compression must be one of {{'uncompressed', 'lz4', 'zstd'}}, got {}"
|
|
775
|
-
|
|
776
|
-
)))
|
|
877
|
+
"compression must be one of {{'uncompressed', 'lz4', 'zstd'}}, got {v}"
|
|
878
|
+
)));
|
|
777
879
|
}
|
|
778
880
|
};
|
|
779
881
|
Ok(Wrap(parsed))
|
|
@@ -791,9 +893,8 @@ impl TryConvert for Wrap<JoinType> {
|
|
|
791
893
|
"cross" => JoinType::Cross,
|
|
792
894
|
v => {
|
|
793
895
|
return Err(RbValueError::new_err(format!(
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
)))
|
|
896
|
+
"how must be one of {{'inner', 'left', 'full', 'semi', 'anti', 'cross'}}, got {v}"
|
|
897
|
+
)));
|
|
797
898
|
}
|
|
798
899
|
};
|
|
799
900
|
Ok(Wrap(parsed))
|
|
@@ -809,7 +910,7 @@ impl TryConvert for Wrap<Label> {
|
|
|
809
910
|
v => {
|
|
810
911
|
return Err(RbValueError::new_err(format!(
|
|
811
912
|
"`label` must be one of {{'left', 'right', 'datapoint'}}, got {v}",
|
|
812
|
-
)))
|
|
913
|
+
)));
|
|
813
914
|
}
|
|
814
915
|
};
|
|
815
916
|
Ok(Wrap(parsed))
|
|
@@ -823,9 +924,8 @@ impl TryConvert for Wrap<ListToStructWidthStrategy> {
|
|
|
823
924
|
"max_width" => ListToStructWidthStrategy::MaxWidth,
|
|
824
925
|
v => {
|
|
825
926
|
return Err(RbValueError::new_err(format!(
|
|
826
|
-
"n_field_strategy must be one of {{'first_non_null', 'max_width'}}, got {}"
|
|
827
|
-
|
|
828
|
-
)))
|
|
927
|
+
"n_field_strategy must be one of {{'first_non_null', 'max_width'}}, got {v}"
|
|
928
|
+
)));
|
|
829
929
|
}
|
|
830
930
|
};
|
|
831
931
|
Ok(Wrap(parsed))
|
|
@@ -840,7 +940,7 @@ impl TryConvert for Wrap<NonExistent> {
|
|
|
840
940
|
v => {
|
|
841
941
|
return Err(RbValueError::new_err(format!(
|
|
842
942
|
"`non_existent` must be one of {{'null', 'raise'}}, got {v}",
|
|
843
|
-
)))
|
|
943
|
+
)));
|
|
844
944
|
}
|
|
845
945
|
};
|
|
846
946
|
Ok(Wrap(parsed))
|
|
@@ -854,9 +954,8 @@ impl TryConvert for Wrap<NullBehavior> {
|
|
|
854
954
|
"ignore" => NullBehavior::Ignore,
|
|
855
955
|
v => {
|
|
856
956
|
return Err(RbValueError::new_err(format!(
|
|
857
|
-
"null behavior must be one of {{'drop', 'ignore'}}, got {}"
|
|
858
|
-
|
|
859
|
-
)))
|
|
957
|
+
"null behavior must be one of {{'drop', 'ignore'}}, got {v}"
|
|
958
|
+
)));
|
|
860
959
|
}
|
|
861
960
|
};
|
|
862
961
|
Ok(Wrap(parsed))
|
|
@@ -870,9 +969,8 @@ impl TryConvert for Wrap<NullStrategy> {
|
|
|
870
969
|
"propagate" => NullStrategy::Propagate,
|
|
871
970
|
v => {
|
|
872
971
|
return Err(RbValueError::new_err(format!(
|
|
873
|
-
"null strategy must be one of {{'ignore', 'propagate'}}, got {}"
|
|
874
|
-
|
|
875
|
-
)))
|
|
972
|
+
"null strategy must be one of {{'ignore', 'propagate'}}, got {v}"
|
|
973
|
+
)));
|
|
876
974
|
}
|
|
877
975
|
};
|
|
878
976
|
Ok(Wrap(parsed))
|
|
@@ -888,9 +986,8 @@ impl TryConvert for Wrap<ParallelStrategy> {
|
|
|
888
986
|
"none" => ParallelStrategy::None,
|
|
889
987
|
v => {
|
|
890
988
|
return Err(RbValueError::new_err(format!(
|
|
891
|
-
"parallel must be one of {{'auto', 'columns', 'row_groups', 'none'}}, got {}"
|
|
892
|
-
|
|
893
|
-
)))
|
|
989
|
+
"parallel must be one of {{'auto', 'columns', 'row_groups', 'none'}}, got {v}"
|
|
990
|
+
)));
|
|
894
991
|
}
|
|
895
992
|
};
|
|
896
993
|
Ok(Wrap(parsed))
|
|
@@ -907,9 +1004,8 @@ impl TryConvert for Wrap<QuantileMethod> {
|
|
|
907
1004
|
"midpoint" => QuantileMethod::Midpoint,
|
|
908
1005
|
v => {
|
|
909
1006
|
return Err(RbValueError::new_err(format!(
|
|
910
|
-
"interpolation must be one of {{'lower', 'higher', 'nearest', 'linear', 'midpoint'}}, got {}"
|
|
911
|
-
|
|
912
|
-
)))
|
|
1007
|
+
"interpolation must be one of {{'lower', 'higher', 'nearest', 'linear', 'midpoint'}}, got {v}"
|
|
1008
|
+
)));
|
|
913
1009
|
}
|
|
914
1010
|
};
|
|
915
1011
|
Ok(Wrap(parsed))
|
|
@@ -927,9 +1023,42 @@ impl TryConvert for Wrap<RankMethod> {
|
|
|
927
1023
|
"random" => RankMethod::Random,
|
|
928
1024
|
v => {
|
|
929
1025
|
return Err(RbValueError::new_err(format!(
|
|
930
|
-
"method must be one of {{'min', 'max', 'average', 'dense', 'ordinal', 'random'}}, got {}"
|
|
931
|
-
|
|
932
|
-
|
|
1026
|
+
"method must be one of {{'min', 'max', 'average', 'dense', 'ordinal', 'random'}}, got {v}"
|
|
1027
|
+
)));
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
Ok(Wrap(parsed))
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
impl TryConvert for Wrap<RollingRankMethod> {
|
|
1035
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1036
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1037
|
+
"min" => RollingRankMethod::Min,
|
|
1038
|
+
"max" => RollingRankMethod::Max,
|
|
1039
|
+
"average" => RollingRankMethod::Average,
|
|
1040
|
+
"dense" => RollingRankMethod::Dense,
|
|
1041
|
+
"random" => RollingRankMethod::Random,
|
|
1042
|
+
v => {
|
|
1043
|
+
return Err(RbValueError::new_err(format!(
|
|
1044
|
+
"rank `method` must be one of {{'min', 'max', 'average', 'dense', 'random'}}, got {v}",
|
|
1045
|
+
)));
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
Ok(Wrap(parsed))
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
impl TryConvert for Wrap<Roll> {
|
|
1053
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1054
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1055
|
+
"raise" => Roll::Raise,
|
|
1056
|
+
"forward" => Roll::Forward,
|
|
1057
|
+
"backward" => Roll::Backward,
|
|
1058
|
+
v => {
|
|
1059
|
+
return Err(RbValueError::new_err(format!(
|
|
1060
|
+
"`roll` must be one of {{'raise', 'forward', 'backward'}}, got {v}",
|
|
1061
|
+
)));
|
|
933
1062
|
}
|
|
934
1063
|
};
|
|
935
1064
|
Ok(Wrap(parsed))
|
|
@@ -944,57 +1073,58 @@ impl TryConvert for Wrap<TimeUnit> {
|
|
|
944
1073
|
"ms" => TimeUnit::Milliseconds,
|
|
945
1074
|
v => {
|
|
946
1075
|
return Err(RbValueError::new_err(format!(
|
|
947
|
-
"time unit must be one of {{'ns', 'us', 'ms'}}, got {}"
|
|
948
|
-
|
|
949
|
-
)))
|
|
1076
|
+
"time unit must be one of {{'ns', 'us', 'ms'}}, got {v}"
|
|
1077
|
+
)));
|
|
950
1078
|
}
|
|
951
1079
|
};
|
|
952
1080
|
Ok(Wrap(parsed))
|
|
953
1081
|
}
|
|
954
1082
|
}
|
|
955
1083
|
|
|
1084
|
+
unsafe impl TryConvertOwned for Wrap<TimeUnit> {}
|
|
1085
|
+
|
|
956
1086
|
impl TryConvert for Wrap<UniqueKeepStrategy> {
|
|
957
1087
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
958
1088
|
let parsed = match String::try_convert(ob)?.as_str() {
|
|
959
1089
|
"first" => UniqueKeepStrategy::First,
|
|
960
1090
|
"last" => UniqueKeepStrategy::Last,
|
|
1091
|
+
"none" => UniqueKeepStrategy::None,
|
|
1092
|
+
"any" => UniqueKeepStrategy::Any,
|
|
961
1093
|
v => {
|
|
962
1094
|
return Err(RbValueError::new_err(format!(
|
|
963
|
-
"keep must be one of {{'first', 'last'}}, got {}",
|
|
964
|
-
|
|
965
|
-
)))
|
|
1095
|
+
"`keep` must be one of {{'first', 'last', 'any', 'none'}}, got {v}",
|
|
1096
|
+
)));
|
|
966
1097
|
}
|
|
967
1098
|
};
|
|
968
1099
|
Ok(Wrap(parsed))
|
|
969
1100
|
}
|
|
970
1101
|
}
|
|
971
1102
|
|
|
972
|
-
impl TryConvert for Wrap<
|
|
1103
|
+
impl TryConvert for Wrap<SearchSortedSide> {
|
|
973
1104
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
974
1105
|
let parsed = match String::try_convert(ob)?.as_str() {
|
|
975
|
-
"
|
|
976
|
-
"
|
|
1106
|
+
"any" => SearchSortedSide::Any,
|
|
1107
|
+
"left" => SearchSortedSide::Left,
|
|
1108
|
+
"right" => SearchSortedSide::Right,
|
|
977
1109
|
v => {
|
|
978
1110
|
return Err(RbValueError::new_err(format!(
|
|
979
|
-
"
|
|
980
|
-
|
|
981
|
-
)))
|
|
1111
|
+
"side must be one of {{'any', 'left', 'right'}}, got {v}",
|
|
1112
|
+
)));
|
|
982
1113
|
}
|
|
983
1114
|
};
|
|
984
1115
|
Ok(Wrap(parsed))
|
|
985
1116
|
}
|
|
986
1117
|
}
|
|
987
1118
|
|
|
988
|
-
impl TryConvert for Wrap<
|
|
1119
|
+
impl TryConvert for Wrap<PivotColumnNaming> {
|
|
989
1120
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
990
1121
|
let parsed = match String::try_convert(ob)?.as_str() {
|
|
991
|
-
"
|
|
992
|
-
"
|
|
993
|
-
"right" => SearchSortedSide::Right,
|
|
1122
|
+
"auto" => PivotColumnNaming::Auto,
|
|
1123
|
+
"combine" => PivotColumnNaming::Combine,
|
|
994
1124
|
v => {
|
|
995
1125
|
return Err(RbValueError::new_err(format!(
|
|
996
|
-
"
|
|
997
|
-
)))
|
|
1126
|
+
"`column_naming` must be one of {{'auto', 'combine'}}, got {v}",
|
|
1127
|
+
)));
|
|
998
1128
|
}
|
|
999
1129
|
};
|
|
1000
1130
|
Ok(Wrap(parsed))
|
|
@@ -1011,7 +1141,7 @@ impl TryConvert for Wrap<ClosedInterval> {
|
|
|
1011
1141
|
v => {
|
|
1012
1142
|
return Err(RbValueError::new_err(format!(
|
|
1013
1143
|
"`closed` must be one of {{'both', 'left', 'right', 'none'}}, got {v}",
|
|
1014
|
-
)))
|
|
1144
|
+
)));
|
|
1015
1145
|
}
|
|
1016
1146
|
};
|
|
1017
1147
|
Ok(Wrap(parsed))
|
|
@@ -1026,8 +1156,8 @@ impl TryConvert for Wrap<WindowMapping> {
|
|
|
1026
1156
|
"explode" => WindowMapping::Explode,
|
|
1027
1157
|
v => {
|
|
1028
1158
|
return Err(RbValueError::new_err(format!(
|
|
1029
|
-
|
|
1030
|
-
|
|
1159
|
+
"`mapping_strategy` must be one of {{'group_to_rows', 'join', 'explode'}}, got {v}",
|
|
1160
|
+
)));
|
|
1031
1161
|
}
|
|
1032
1162
|
};
|
|
1033
1163
|
Ok(Wrap(parsed))
|
|
@@ -1044,7 +1174,25 @@ impl TryConvert for Wrap<JoinValidation> {
|
|
|
1044
1174
|
v => {
|
|
1045
1175
|
return Err(RbValueError::new_err(format!(
|
|
1046
1176
|
"`validate` must be one of {{'m:m', 'm:1', '1:m', '1:1'}}, got {v}",
|
|
1047
|
-
)))
|
|
1177
|
+
)));
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
Ok(Wrap(parsed))
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
impl TryConvert for Wrap<MaintainOrderJoin> {
|
|
1185
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1186
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1187
|
+
"none" => MaintainOrderJoin::None,
|
|
1188
|
+
"left" => MaintainOrderJoin::Left,
|
|
1189
|
+
"right" => MaintainOrderJoin::Right,
|
|
1190
|
+
"left_right" => MaintainOrderJoin::LeftRight,
|
|
1191
|
+
"right_left" => MaintainOrderJoin::RightLeft,
|
|
1192
|
+
v => {
|
|
1193
|
+
return Err(RbValueError::new_err(format!(
|
|
1194
|
+
"`maintain_order` must be one of {{'none', 'left', 'right', 'left_right', 'right_left'}}, got {v}",
|
|
1195
|
+
)));
|
|
1048
1196
|
}
|
|
1049
1197
|
};
|
|
1050
1198
|
Ok(Wrap(parsed))
|
|
@@ -1061,16 +1209,163 @@ impl TryConvert for Wrap<QuoteStyle> {
|
|
|
1061
1209
|
v => {
|
|
1062
1210
|
return Err(RbValueError::new_err(format!(
|
|
1063
1211
|
"`quote_style` must be one of {{'always', 'necessary', 'non_numeric', 'never'}}, got {v}",
|
|
1064
|
-
)))
|
|
1065
|
-
}
|
|
1212
|
+
)));
|
|
1213
|
+
}
|
|
1066
1214
|
};
|
|
1067
1215
|
Ok(Wrap(parsed))
|
|
1068
1216
|
}
|
|
1069
1217
|
}
|
|
1070
1218
|
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1219
|
+
impl TryConvert for Wrap<SetOperation> {
|
|
1220
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1221
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1222
|
+
"union" => SetOperation::Union,
|
|
1223
|
+
"difference" => SetOperation::Difference,
|
|
1224
|
+
"intersection" => SetOperation::Intersection,
|
|
1225
|
+
"symmetric_difference" => SetOperation::SymmetricDifference,
|
|
1226
|
+
v => {
|
|
1227
|
+
return Err(RbValueError::new_err(format!(
|
|
1228
|
+
"set operation must be one of {{'union', 'difference', 'intersection', 'symmetric_difference'}}, got {v}",
|
|
1229
|
+
)));
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
Ok(Wrap(parsed))
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
impl TryConvert for Wrap<CastColumnsPolicy> {
|
|
1237
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1238
|
+
if ob.is_nil() {
|
|
1239
|
+
let out = Wrap(CastColumnsPolicy::ERROR_ON_MISMATCH);
|
|
1240
|
+
return Ok(out);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
let mut integer_upcast = false;
|
|
1244
|
+
let mut integer_to_float_cast = false;
|
|
1245
|
+
|
|
1246
|
+
let integer_cast_object: Value = ob.funcall("integer_cast", ())?;
|
|
1247
|
+
|
|
1248
|
+
parse_multiple_options("integer_cast", integer_cast_object, |v| {
|
|
1249
|
+
match v {
|
|
1250
|
+
"upcast" => integer_upcast = true,
|
|
1251
|
+
"allow-float" => integer_to_float_cast = true,
|
|
1252
|
+
"forbid" => {}
|
|
1253
|
+
v => {
|
|
1254
|
+
return Err(RbValueError::new_err(format!(
|
|
1255
|
+
"unknown option for integer_cast: {v}"
|
|
1256
|
+
)));
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
Ok(())
|
|
1261
|
+
})?;
|
|
1262
|
+
|
|
1263
|
+
let mut float_upcast = false;
|
|
1264
|
+
let mut float_downcast = false;
|
|
1265
|
+
|
|
1266
|
+
let float_cast_object: Value = ob.funcall("float_cast", ())?;
|
|
1267
|
+
|
|
1268
|
+
parse_multiple_options("float_cast", float_cast_object, |v| {
|
|
1269
|
+
match v {
|
|
1270
|
+
"forbid" => {}
|
|
1271
|
+
"upcast" => float_upcast = true,
|
|
1272
|
+
"downcast" => float_downcast = true,
|
|
1273
|
+
v => {
|
|
1274
|
+
return Err(RbValueError::new_err(format!(
|
|
1275
|
+
"unknown option for float_cast: {v}"
|
|
1276
|
+
)));
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
Ok(())
|
|
1281
|
+
})?;
|
|
1282
|
+
|
|
1283
|
+
let mut datetime_nanoseconds_downcast = false;
|
|
1284
|
+
let mut datetime_convert_timezone = false;
|
|
1285
|
+
|
|
1286
|
+
let datetime_cast_object: Value = ob.funcall("datetime_cast", ())?;
|
|
1287
|
+
|
|
1288
|
+
parse_multiple_options("datetime_cast", datetime_cast_object, |v| {
|
|
1289
|
+
match v {
|
|
1290
|
+
"forbid" => {}
|
|
1291
|
+
"nanosecond-downcast" => datetime_nanoseconds_downcast = true,
|
|
1292
|
+
"convert-timezone" => datetime_convert_timezone = true,
|
|
1293
|
+
v => {
|
|
1294
|
+
return Err(RbValueError::new_err(format!(
|
|
1295
|
+
"unknown option for datetime_cast: {v}"
|
|
1296
|
+
)));
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
|
|
1300
|
+
Ok(())
|
|
1301
|
+
})?;
|
|
1302
|
+
|
|
1303
|
+
let missing_struct_fields =
|
|
1304
|
+
match &*ob.funcall::<_, _, String>("missing_struct_fields", ())? {
|
|
1305
|
+
"insert" => MissingColumnsPolicy::Insert,
|
|
1306
|
+
"raise" => MissingColumnsPolicy::Raise,
|
|
1307
|
+
v => {
|
|
1308
|
+
return Err(RbValueError::new_err(format!(
|
|
1309
|
+
"unknown option for missing_struct_fields: {v}"
|
|
1310
|
+
)));
|
|
1311
|
+
}
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
let extra_struct_fields = match &*ob.funcall::<_, _, String>("extra_struct_fields", ())? {
|
|
1315
|
+
"ignore" => ExtraColumnsPolicy::Ignore,
|
|
1316
|
+
"raise" => ExtraColumnsPolicy::Raise,
|
|
1317
|
+
v => {
|
|
1318
|
+
return Err(RbValueError::new_err(format!(
|
|
1319
|
+
"unknown option for extra_struct_fields: {v}"
|
|
1320
|
+
)));
|
|
1321
|
+
}
|
|
1322
|
+
};
|
|
1323
|
+
|
|
1324
|
+
let categorical_to_string =
|
|
1325
|
+
match &*ob.funcall::<_, _, String>("categorical_to_string", ())? {
|
|
1326
|
+
"allow" => true,
|
|
1327
|
+
"forbid" => false,
|
|
1328
|
+
v => {
|
|
1329
|
+
return Err(RbValueError::new_err(format!(
|
|
1330
|
+
"unknown option for categorical_to_string: {v}"
|
|
1331
|
+
)));
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1335
|
+
return Ok(Wrap(CastColumnsPolicy {
|
|
1336
|
+
integer_upcast,
|
|
1337
|
+
integer_to_float_cast,
|
|
1338
|
+
float_upcast,
|
|
1339
|
+
float_downcast,
|
|
1340
|
+
datetime_nanoseconds_downcast,
|
|
1341
|
+
datetime_microseconds_downcast: false,
|
|
1342
|
+
datetime_convert_timezone,
|
|
1343
|
+
null_upcast: true,
|
|
1344
|
+
categorical_to_string,
|
|
1345
|
+
missing_struct_fields,
|
|
1346
|
+
extra_struct_fields,
|
|
1347
|
+
}));
|
|
1348
|
+
|
|
1349
|
+
fn parse_multiple_options(
|
|
1350
|
+
parameter_name: &'static str,
|
|
1351
|
+
rb_object: Value,
|
|
1352
|
+
mut parser_func: impl FnMut(&str) -> RbResult<()>,
|
|
1353
|
+
) -> RbResult<()> {
|
|
1354
|
+
if let Ok(v) = String::try_convert(rb_object) {
|
|
1355
|
+
parser_func(&v)?;
|
|
1356
|
+
} else if let Ok(v) = RArray::try_convert(rb_object) {
|
|
1357
|
+
for v in v {
|
|
1358
|
+
parser_func(&String::try_convert(v)?)?;
|
|
1359
|
+
}
|
|
1360
|
+
} else {
|
|
1361
|
+
return Err(RbValueError::new_err(format!(
|
|
1362
|
+
"unknown type for {parameter_name}: {rb_object}"
|
|
1363
|
+
)));
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
Ok(())
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1074
1369
|
}
|
|
1075
1370
|
|
|
1076
1371
|
pub fn parse_fill_null_strategy(
|
|
@@ -1086,10 +1381,9 @@ pub fn parse_fill_null_strategy(
|
|
|
1086
1381
|
"zero" => FillNullStrategy::Zero,
|
|
1087
1382
|
"one" => FillNullStrategy::One,
|
|
1088
1383
|
e => {
|
|
1089
|
-
return Err(
|
|
1090
|
-
"strategy must be one of {{'forward', 'backward', 'min', 'max', 'mean', 'zero', 'one'}}, got {}",
|
|
1091
|
-
|
|
1092
|
-
)))
|
|
1384
|
+
return Err(RbValueError::new_err(format!(
|
|
1385
|
+
"`strategy` must be one of {{'forward', 'backward', 'min', 'max', 'mean', 'zero', 'one'}}, got {e}",
|
|
1386
|
+
)));
|
|
1093
1387
|
}
|
|
1094
1388
|
};
|
|
1095
1389
|
Ok(parsed)
|
|
@@ -1106,16 +1400,15 @@ pub fn parse_parquet_compression(
|
|
|
1106
1400
|
compression_level
|
|
1107
1401
|
.map(|lvl| {
|
|
1108
1402
|
GzipLevel::try_new(lvl as u8)
|
|
1109
|
-
.map_err(|e| RbValueError::new_err(format!("{:?}"
|
|
1403
|
+
.map_err(|e| RbValueError::new_err(format!("{e:?}")))
|
|
1110
1404
|
})
|
|
1111
1405
|
.transpose()?,
|
|
1112
1406
|
),
|
|
1113
|
-
"lzo" => ParquetCompression::Lzo,
|
|
1114
1407
|
"brotli" => ParquetCompression::Brotli(
|
|
1115
1408
|
compression_level
|
|
1116
1409
|
.map(|lvl| {
|
|
1117
1410
|
BrotliLevel::try_new(lvl as u32)
|
|
1118
|
-
.map_err(|e| RbValueError::new_err(format!("{:?}"
|
|
1411
|
+
.map_err(|e| RbValueError::new_err(format!("{e:?}")))
|
|
1119
1412
|
})
|
|
1120
1413
|
.transpose()?,
|
|
1121
1414
|
),
|
|
@@ -1123,30 +1416,19 @@ pub fn parse_parquet_compression(
|
|
|
1123
1416
|
"zstd" => ParquetCompression::Zstd(
|
|
1124
1417
|
compression_level
|
|
1125
1418
|
.map(|lvl| {
|
|
1126
|
-
ZstdLevel::try_new(lvl)
|
|
1127
|
-
.map_err(|e| RbValueError::new_err(format!("{:?}", e)))
|
|
1419
|
+
ZstdLevel::try_new(lvl).map_err(|e| RbValueError::new_err(format!("{e:?}")))
|
|
1128
1420
|
})
|
|
1129
1421
|
.transpose()?,
|
|
1130
1422
|
),
|
|
1131
1423
|
e => {
|
|
1132
1424
|
return Err(RbValueError::new_err(format!(
|
|
1133
|
-
"compression must be one of {{'uncompressed', 'snappy', 'gzip', 'lzo', 'brotli', 'lz4', 'zstd'}}, got {}"
|
|
1134
|
-
|
|
1135
|
-
)))
|
|
1425
|
+
"compression must be one of {{'uncompressed', 'snappy', 'gzip', 'lzo', 'brotli', 'lz4', 'zstd'}}, got {e}"
|
|
1426
|
+
)));
|
|
1136
1427
|
}
|
|
1137
1428
|
};
|
|
1138
1429
|
Ok(parsed)
|
|
1139
1430
|
}
|
|
1140
1431
|
|
|
1141
|
-
impl TryConvert for Wrap<NonZeroUsize> {
|
|
1142
|
-
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1143
|
-
let v = usize::try_convert(ob)?;
|
|
1144
|
-
NonZeroUsize::new(v)
|
|
1145
|
-
.map(Wrap)
|
|
1146
|
-
.ok_or(RbValueError::new_err("must be non-zero"))
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
1432
|
pub(crate) fn strings_to_pl_smallstr<I, S>(container: I) -> Vec<PlSmallStr>
|
|
1151
1433
|
where
|
|
1152
1434
|
I: IntoIterator<Item = S>,
|
|
@@ -1182,3 +1464,205 @@ impl TryConvert for RbCompatLevel {
|
|
|
1182
1464
|
}))
|
|
1183
1465
|
}
|
|
1184
1466
|
}
|
|
1467
|
+
|
|
1468
|
+
impl TryConvert for Wrap<UnicodeForm> {
|
|
1469
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1470
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1471
|
+
"NFC" => UnicodeForm::NFC,
|
|
1472
|
+
"NFKC" => UnicodeForm::NFKC,
|
|
1473
|
+
"NFD" => UnicodeForm::NFD,
|
|
1474
|
+
"NFKD" => UnicodeForm::NFKD,
|
|
1475
|
+
v => {
|
|
1476
|
+
return Err(RbValueError::new_err(format!(
|
|
1477
|
+
"`form` must be one of {{'NFC', 'NFKC', 'NFD', 'NFKD'}}, got {v}",
|
|
1478
|
+
)));
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
Ok(Wrap(parsed))
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
impl TryConvert for Wrap<Option<KeyValueMetadata>> {
|
|
1486
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1487
|
+
if ob.is_nil() {
|
|
1488
|
+
return Ok(Wrap(None));
|
|
1489
|
+
}
|
|
1490
|
+
todo!();
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
unsafe impl TryConvertOwned for Wrap<Option<KeyValueMetadata>> {}
|
|
1495
|
+
|
|
1496
|
+
impl TryConvert for Wrap<Option<TimeZone>> {
|
|
1497
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1498
|
+
let tz = Option::<Wrap<PlSmallStr>>::try_convert(ob)?;
|
|
1499
|
+
|
|
1500
|
+
let tz = tz.map(|x| x.0);
|
|
1501
|
+
|
|
1502
|
+
Ok(Wrap(TimeZone::opt_try_new(tz).map_err(RbPolarsErr::from)?))
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
unsafe impl TryConvertOwned for Wrap<Option<TimeZone>> {}
|
|
1507
|
+
|
|
1508
|
+
impl TryConvert for Wrap<UpcastOrForbid> {
|
|
1509
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1510
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1511
|
+
"upcast" => UpcastOrForbid::Upcast,
|
|
1512
|
+
"forbid" => UpcastOrForbid::Forbid,
|
|
1513
|
+
v => {
|
|
1514
|
+
return Err(RbValueError::new_err(format!(
|
|
1515
|
+
"cast parameter must be one of {{'upcast', 'forbid'}}, got {v}",
|
|
1516
|
+
)));
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
Ok(Wrap(parsed))
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
impl TryConvert for Wrap<ExtraColumnsPolicy> {
|
|
1524
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1525
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1526
|
+
"ignore" => ExtraColumnsPolicy::Ignore,
|
|
1527
|
+
"raise" => ExtraColumnsPolicy::Raise,
|
|
1528
|
+
v => {
|
|
1529
|
+
return Err(RbValueError::new_err(format!(
|
|
1530
|
+
"extra column/field parameter must be one of {{'ignore', 'raise'}}, got {v}",
|
|
1531
|
+
)));
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
Ok(Wrap(parsed))
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
impl TryConvert for Wrap<MissingColumnsPolicy> {
|
|
1539
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1540
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1541
|
+
"insert" => MissingColumnsPolicy::Insert,
|
|
1542
|
+
"raise" => MissingColumnsPolicy::Raise,
|
|
1543
|
+
v => {
|
|
1544
|
+
return Err(RbValueError::new_err(format!(
|
|
1545
|
+
"missing column/field parameter must be one of {{'insert', 'raise'}}, got {v}",
|
|
1546
|
+
)));
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
Ok(Wrap(parsed))
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
impl TryConvert for Wrap<MissingColumnsPolicyOrExpr> {
|
|
1554
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1555
|
+
if let Ok(rbexpr) = <&RbExpr>::try_convert(ob) {
|
|
1556
|
+
return Ok(Wrap(MissingColumnsPolicyOrExpr::InsertWith(
|
|
1557
|
+
rbexpr.inner.clone(),
|
|
1558
|
+
)));
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
let parsed = match String::try_convert(ob)?.as_str() {
|
|
1562
|
+
"insert" => MissingColumnsPolicyOrExpr::Insert,
|
|
1563
|
+
"raise" => MissingColumnsPolicyOrExpr::Raise,
|
|
1564
|
+
v => {
|
|
1565
|
+
return Err(RbValueError::new_err(format!(
|
|
1566
|
+
"missing column/field parameter must be one of {{'insert', 'raise', expression}}, got {v}",
|
|
1567
|
+
)));
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1570
|
+
Ok(Wrap(parsed))
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
impl TryConvert for Wrap<ColumnMapping> {
|
|
1575
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1576
|
+
let (column_mapping_type, ob) = <(String, Value)>::try_convert(ob)?;
|
|
1577
|
+
|
|
1578
|
+
Ok(Wrap(match column_mapping_type.as_str() {
|
|
1579
|
+
"iceberg-column-mapping" => {
|
|
1580
|
+
let arrow_schema = Wrap::<ArrowSchema>::try_convert(ob)?;
|
|
1581
|
+
ColumnMapping::Iceberg(Arc::new(
|
|
1582
|
+
IcebergSchema::from_arrow_schema(&arrow_schema.0).map_err(to_rb_err)?,
|
|
1583
|
+
))
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
v => {
|
|
1587
|
+
return Err(RbValueError::new_err(format!(
|
|
1588
|
+
"unknown column mapping type: {v}"
|
|
1589
|
+
)));
|
|
1590
|
+
}
|
|
1591
|
+
}))
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
impl TryConvert for Wrap<DeletionFilesList> {
|
|
1596
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1597
|
+
let (deletion_file_type, ob) = <(String, Value)>::try_convert(ob)?;
|
|
1598
|
+
|
|
1599
|
+
Ok(Wrap(match deletion_file_type.as_str() {
|
|
1600
|
+
"iceberg-position-delete" => {
|
|
1601
|
+
let dict = RHash::try_convert(ob)?;
|
|
1602
|
+
|
|
1603
|
+
let mut out = PlIndexMap::new();
|
|
1604
|
+
|
|
1605
|
+
dict.foreach(|k: usize, v: RArray| {
|
|
1606
|
+
let files = v
|
|
1607
|
+
.into_iter()
|
|
1608
|
+
.map(|x| {
|
|
1609
|
+
let x = String::try_convert(x)?;
|
|
1610
|
+
Ok(x)
|
|
1611
|
+
})
|
|
1612
|
+
.collect::<RbResult<Arc<[String]>>>()?;
|
|
1613
|
+
|
|
1614
|
+
if !files.is_empty() {
|
|
1615
|
+
out.insert(k, files);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
Ok(ForEach::Continue)
|
|
1619
|
+
})?;
|
|
1620
|
+
|
|
1621
|
+
DeletionFilesList::IcebergPositionDelete(Arc::new(out))
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
v => {
|
|
1625
|
+
return Err(RbValueError::new_err(format!(
|
|
1626
|
+
"unknown deletion file type: {v}"
|
|
1627
|
+
)));
|
|
1628
|
+
}
|
|
1629
|
+
}))
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
impl TryConvert for Wrap<DefaultFieldValues> {
|
|
1634
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
|
1635
|
+
let (default_values_type, ob) = <(String, Value)>::try_convert(ob)?;
|
|
1636
|
+
|
|
1637
|
+
Ok(Wrap(match &*default_values_type {
|
|
1638
|
+
"iceberg" => {
|
|
1639
|
+
let dict = RHash::try_convert(ob)?;
|
|
1640
|
+
|
|
1641
|
+
let mut out = PlIndexMap::new();
|
|
1642
|
+
|
|
1643
|
+
dict.foreach(|k: u32, v: Value| {
|
|
1644
|
+
let v: Result<Column, String> = if let Ok(s) = get_series(v) {
|
|
1645
|
+
Ok(s.into_column())
|
|
1646
|
+
} else {
|
|
1647
|
+
let err_msg = String::try_convert(v)?;
|
|
1648
|
+
Err(err_msg)
|
|
1649
|
+
};
|
|
1650
|
+
|
|
1651
|
+
out.insert(k, v);
|
|
1652
|
+
|
|
1653
|
+
Ok(ForEach::Continue)
|
|
1654
|
+
})?;
|
|
1655
|
+
|
|
1656
|
+
DefaultFieldValues::Iceberg(Arc::new(IcebergIdentityTransformedPartitionFields(
|
|
1657
|
+
out,
|
|
1658
|
+
)))
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
v => {
|
|
1662
|
+
return Err(RbValueError::new_err(format!(
|
|
1663
|
+
"unknown deletion file type: {v}"
|
|
1664
|
+
)));
|
|
1665
|
+
}
|
|
1666
|
+
}))
|
|
1667
|
+
}
|
|
1668
|
+
}
|