polars-df 0.25.1 → 0.26.1
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 +32 -1
- data/Cargo.lock +278 -106
- data/Cargo.toml +0 -3
- data/LICENSE.txt +1 -1
- data/README.md +7 -3
- data/ext/polars/Cargo.toml +18 -18
- data/ext/polars/src/catalog/unity.rs +15 -20
- data/ext/polars/src/conversion/any_value.rs +25 -24
- data/ext/polars/src/conversion/chunked_array.rs +58 -56
- data/ext/polars/src/conversion/datetime.rs +58 -7
- data/ext/polars/src/conversion/mod.rs +205 -142
- data/ext/polars/src/dataframe/export.rs +15 -12
- data/ext/polars/src/dataframe/general.rs +5 -4
- data/ext/polars/src/dataframe/map.rs +6 -4
- data/ext/polars/src/error.rs +1 -1
- data/ext/polars/src/expr/array.rs +0 -24
- data/ext/polars/src/expr/datatype.rs +3 -2
- data/ext/polars/src/expr/datetime.rs +4 -4
- data/ext/polars/src/expr/general.rs +27 -15
- data/ext/polars/src/expr/list.rs +0 -26
- data/ext/polars/src/functions/business.rs +2 -2
- data/ext/polars/src/functions/io.rs +4 -3
- data/ext/polars/src/functions/lazy.rs +58 -46
- data/ext/polars/src/functions/meta.rs +6 -5
- data/ext/polars/src/functions/mod.rs +0 -1
- data/ext/polars/src/functions/utils.rs +4 -2
- data/ext/polars/src/interop/arrow/mod.rs +4 -2
- data/ext/polars/src/interop/arrow/to_rb.rs +17 -12
- data/ext/polars/src/interop/numo/to_numo_series.rs +26 -25
- data/ext/polars/src/io/scan_options.rs +6 -3
- data/ext/polars/src/io/sink_options.rs +2 -0
- data/ext/polars/src/lazyframe/general.rs +32 -16
- data/ext/polars/src/lazyframe/optflags.rs +2 -1
- data/ext/polars/src/lib.rs +21 -37
- data/ext/polars/src/map/lazy.rs +5 -2
- data/ext/polars/src/map/series.rs +19 -18
- data/ext/polars/src/on_startup.rs +16 -7
- data/ext/polars/src/ruby/capsule.rs +27 -0
- data/ext/polars/src/ruby/mod.rs +1 -0
- data/ext/polars/src/ruby/numo.rs +3 -4
- data/ext/polars/src/ruby/rb_modules.rs +2 -4
- data/ext/polars/src/ruby/ruby_udf.rs +7 -9
- data/ext/polars/src/ruby/utils.rs +12 -1
- data/ext/polars/src/series/aggregation.rs +13 -1
- data/ext/polars/src/series/export.rs +38 -38
- data/ext/polars/src/series/general.rs +4 -3
- data/ext/polars/src/series/map.rs +3 -2
- data/ext/polars/src/series/scatter.rs +4 -4
- data/ext/polars/src/utils.rs +31 -7
- data/lib/polars/array_expr.rb +23 -7
- data/lib/polars/array_name_space.rb +16 -2
- data/lib/polars/binary_name_space.rb +32 -0
- data/lib/polars/data_frame.rb +83 -11
- data/lib/polars/date_time_expr.rb +91 -3
- data/lib/polars/date_time_name_space.rb +7 -1
- data/lib/polars/expr.rb +122 -44
- data/lib/polars/functions/aggregation/horizontal.rb +4 -4
- data/lib/polars/functions/business.rb +2 -2
- data/lib/polars/functions/eager.rb +80 -7
- data/lib/polars/functions/lazy.rb +5 -2
- data/lib/polars/iceberg_dataset.rb +81 -14
- data/lib/polars/io/csv.rb +27 -5
- data/lib/polars/io/delta.rb +4 -0
- data/lib/polars/io/ipc.rb +1 -1
- data/lib/polars/io/lines.rb +4 -4
- data/lib/polars/io/sink_options.rb +4 -2
- data/lib/polars/lazy_frame.rb +97 -14
- data/lib/polars/list_expr.rb +21 -7
- data/lib/polars/list_name_space.rb +16 -2
- data/lib/polars/query_opt_flags.rb +22 -5
- data/lib/polars/schema.rb +9 -0
- data/lib/polars/selectors.rb +1 -1
- data/lib/polars/series.rb +106 -19
- data/lib/polars/sql_context.rb +2 -2
- data/lib/polars/string_cache.rb +19 -72
- data/lib/polars/string_expr.rb +1 -7
- data/lib/polars/string_name_space.rb +1 -7
- data/lib/polars/utils/construction/series.rb +8 -3
- data/lib/polars/utils/convert.rb +16 -6
- data/lib/polars/utils/parse.rb +7 -0
- data/lib/polars/utils/reduce_balanced.rb +43 -0
- data/lib/polars/utils/various.rb +5 -0
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +5 -1
- metadata +4 -17
- data/ext/polars/src/functions/string_cache.rs +0 -24
|
@@ -2,7 +2,7 @@ use std::hash::BuildHasher;
|
|
|
2
2
|
|
|
3
3
|
use arrow::bitmap::MutableBitmap;
|
|
4
4
|
use either::Either;
|
|
5
|
-
use magnus::{
|
|
5
|
+
use magnus::{RArray, Ruby, Value, prelude::*, value::Opaque};
|
|
6
6
|
use polars::prelude::*;
|
|
7
7
|
|
|
8
8
|
use crate::conversion::*;
|
|
@@ -10,6 +10,7 @@ use crate::prelude::strings_to_pl_smallstr;
|
|
|
10
10
|
use crate::rb_modules::pl_utils;
|
|
11
11
|
use crate::ruby::exceptions::RbIndexError;
|
|
12
12
|
use crate::ruby::gvl::GvlExt;
|
|
13
|
+
use crate::ruby::utils::TryIntoValue;
|
|
13
14
|
use crate::series::ToRbSeries;
|
|
14
15
|
use crate::series::to_series;
|
|
15
16
|
use crate::utils::EnterPolarsExt;
|
|
@@ -144,13 +145,13 @@ impl RbDataFrame {
|
|
|
144
145
|
Ok(())
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
pub fn dtypes(ruby: &Ruby, self_: &Self) -> RArray {
|
|
148
|
+
pub fn dtypes(ruby: &Ruby, self_: &Self) -> RbResult<RArray> {
|
|
148
149
|
let df = self_.df.read();
|
|
149
150
|
let iter = df
|
|
150
151
|
.columns()
|
|
151
152
|
.iter()
|
|
152
|
-
.map(|s| Wrap(s.dtype().clone()).
|
|
153
|
-
ruby.
|
|
153
|
+
.map(|s| Wrap(s.dtype().clone()).try_into_value_with(ruby));
|
|
154
|
+
ruby.ary_try_from_iter(iter)
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
pub fn n_chunks(&self) -> usize {
|
|
@@ -5,7 +5,7 @@ use polars_core::utils::CustomIterTools;
|
|
|
5
5
|
use super::*;
|
|
6
6
|
use crate::error::RbPolarsErr;
|
|
7
7
|
use crate::prelude::*;
|
|
8
|
-
use crate::ruby::utils::to_pl_err;
|
|
8
|
+
use crate::ruby::utils::{TryIntoValue, to_pl_err};
|
|
9
9
|
use crate::series::construction::series_from_objects;
|
|
10
10
|
use crate::{RbResult, RbSeries, raise_err};
|
|
11
11
|
|
|
@@ -28,9 +28,11 @@ impl RbDataFrame {
|
|
|
28
28
|
drop(df); // Release lock before calling lambda.
|
|
29
29
|
|
|
30
30
|
let lambda_result_iter = (0..height).map(move |_| {
|
|
31
|
-
let iter = iters
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
let iter = iters
|
|
32
|
+
.iter_mut()
|
|
33
|
+
.map(|it| Wrap(it.next().unwrap()).try_into_value_with(rb));
|
|
34
|
+
rb.ary_try_from_iter(iter)
|
|
35
|
+
.and_then(|tpl| lambda.funcall::<_, _, Value>("call", (tpl,)))
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
// Simple case: return type set.
|
data/ext/polars/src/error.rs
CHANGED
|
@@ -63,7 +63,7 @@ impl From<RbPolarsErr> for Error {
|
|
|
63
63
|
PolarsError::StructFieldNotFound(name) => {
|
|
64
64
|
StructFieldNotFoundError::new_err(name.to_string())
|
|
65
65
|
}
|
|
66
|
-
PolarsError::Context { .. } => {
|
|
66
|
+
PolarsError::Context { .. } | PolarsError::ExprContext { .. } => {
|
|
67
67
|
let tmp = RbPolarsErr::Polars(err.context_trace());
|
|
68
68
|
RbErr::from(tmp)
|
|
69
69
|
}
|
|
@@ -38,30 +38,10 @@ impl RbExpr {
|
|
|
38
38
|
self.inner.clone().arr().median().into()
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
pub fn arr_unique(&self, maintain_order: bool) -> Self {
|
|
42
|
-
if maintain_order {
|
|
43
|
-
self.inner.clone().arr().unique_stable().into()
|
|
44
|
-
} else {
|
|
45
|
-
self.inner.clone().arr().unique().into()
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
pub fn arr_n_unique(&self) -> Self {
|
|
50
|
-
self.inner.clone().arr().n_unique().into()
|
|
51
|
-
}
|
|
52
|
-
|
|
53
41
|
pub fn arr_to_list(&self) -> Self {
|
|
54
42
|
self.inner.clone().arr().to_list().into()
|
|
55
43
|
}
|
|
56
44
|
|
|
57
|
-
pub fn arr_all(&self) -> Self {
|
|
58
|
-
self.inner.clone().arr().all().into()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
pub fn arr_any(&self) -> Self {
|
|
62
|
-
self.inner.clone().arr().any().into()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
45
|
pub fn arr_sort(&self, descending: bool, nulls_last: bool) -> Self {
|
|
66
46
|
self.inner
|
|
67
47
|
.clone()
|
|
@@ -74,10 +54,6 @@ impl RbExpr {
|
|
|
74
54
|
.into()
|
|
75
55
|
}
|
|
76
56
|
|
|
77
|
-
pub fn arr_reverse(&self) -> Self {
|
|
78
|
-
self.inner.clone().arr().reverse().into()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
57
|
pub fn arr_arg_min(&self) -> Self {
|
|
82
58
|
self.inner.clone().arr().arg_min().into()
|
|
83
59
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
use magnus::{
|
|
1
|
+
use magnus::{RArray, Ruby, TryConvert, Value};
|
|
2
2
|
use polars::prelude::{DataType, DataTypeExpr, PlSmallStr, Schema};
|
|
3
3
|
|
|
4
4
|
use crate::prelude::Wrap;
|
|
5
|
+
use crate::ruby::utils::TryIntoValue;
|
|
5
6
|
use crate::{RbExpr, RbPolarsErr, RbResult};
|
|
6
7
|
|
|
7
8
|
#[magnus::wrap(class = "Polars::RbDataTypeExpr")]
|
|
@@ -36,7 +37,7 @@ impl RbDataTypeExpr {
|
|
|
36
37
|
.inner
|
|
37
38
|
.into_datatype(&schema.0)
|
|
38
39
|
.map_err(RbPolarsErr::from)?;
|
|
39
|
-
|
|
40
|
+
Wrap(dtype).try_into_value_with(ruby)
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
pub fn struct_with_fields(rb_fields: RArray) -> RbResult<Self> {
|
|
@@ -8,13 +8,13 @@ impl RbExpr {
|
|
|
8
8
|
&self,
|
|
9
9
|
n: &RbExpr,
|
|
10
10
|
week_mask: [bool; 7],
|
|
11
|
-
holidays:
|
|
11
|
+
holidays: &RbExpr,
|
|
12
12
|
roll: Wrap<Roll>,
|
|
13
13
|
) -> Self {
|
|
14
14
|
self.inner
|
|
15
15
|
.clone()
|
|
16
16
|
.dt()
|
|
17
|
-
.add_business_days(n.inner.clone(), week_mask, holidays, roll.0)
|
|
17
|
+
.add_business_days(n.inner.clone(), week_mask, holidays.inner.clone(), roll.0)
|
|
18
18
|
.into()
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -133,11 +133,11 @@ impl RbExpr {
|
|
|
133
133
|
self.clone().inner.dt().year().into()
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
pub fn dt_is_business_day(&self, week_mask: [bool; 7], holidays:
|
|
136
|
+
pub fn dt_is_business_day(&self, week_mask: [bool; 7], holidays: &RbExpr) -> Self {
|
|
137
137
|
self.inner
|
|
138
138
|
.clone()
|
|
139
139
|
.dt()
|
|
140
|
-
.is_business_day(week_mask, holidays)
|
|
140
|
+
.is_business_day(week_mask, holidays.inner.clone())
|
|
141
141
|
.into()
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -5,13 +5,13 @@ use polars::lazy::dsl;
|
|
|
5
5
|
use polars::prelude::*;
|
|
6
6
|
use polars::series::ops::NullBehavior;
|
|
7
7
|
use polars_core::chunked_array::cast::CastOptions;
|
|
8
|
-
use
|
|
8
|
+
use polars_plan::plans::AExprSorted;
|
|
9
9
|
|
|
10
10
|
use super::datatype::RbDataTypeExpr;
|
|
11
11
|
use super::selector::RbSelector;
|
|
12
12
|
use crate::conversion::{Wrap, parse_fill_null_strategy};
|
|
13
13
|
use crate::expr::ToExprs;
|
|
14
|
-
use crate::{RbExpr, RbPolarsErr, RbResult};
|
|
14
|
+
use crate::{RbDataType, RbExpr, RbPolarsErr, RbResult};
|
|
15
15
|
|
|
16
16
|
impl RbExpr {
|
|
17
17
|
pub fn add(&self, rhs: &Self) -> RbResult<Self> {
|
|
@@ -182,8 +182,8 @@ impl RbExpr {
|
|
|
182
182
|
self.inner.clone().item(allow_empty).into()
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
pub fn implode(&self) -> Self {
|
|
186
|
-
self.inner.clone().implode().into()
|
|
185
|
+
pub fn implode(&self, maintain_order: bool) -> Self {
|
|
186
|
+
self.inner.clone().implode(maintain_order).into()
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
pub fn quantile(&self, quantile: &Self, interpolation: Wrap<QuantileMethod>) -> Self {
|
|
@@ -366,8 +366,11 @@ impl RbExpr {
|
|
|
366
366
|
.into()
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
pub fn gather(&self, idx: &Self) -> Self {
|
|
370
|
-
self.inner
|
|
369
|
+
pub fn gather(&self, idx: &Self, null_on_oob: bool) -> Self {
|
|
370
|
+
self.inner
|
|
371
|
+
.clone()
|
|
372
|
+
.gather(idx.inner.clone(), null_on_oob)
|
|
373
|
+
.into()
|
|
371
374
|
}
|
|
372
375
|
|
|
373
376
|
pub fn get(&self, idx: &Self, null_on_oob: bool) -> Self {
|
|
@@ -530,6 +533,10 @@ impl RbExpr {
|
|
|
530
533
|
self.clone().inner.round_sig_figs(digits).into()
|
|
531
534
|
}
|
|
532
535
|
|
|
536
|
+
pub fn truncate(&self, decimals: u32) -> Self {
|
|
537
|
+
self.inner.clone().truncate(decimals).into()
|
|
538
|
+
}
|
|
539
|
+
|
|
533
540
|
pub fn floor(&self) -> Self {
|
|
534
541
|
self.inner.clone().floor().into()
|
|
535
542
|
}
|
|
@@ -727,8 +734,11 @@ impl RbExpr {
|
|
|
727
734
|
self.inner.clone().dot(other.inner.clone()).into()
|
|
728
735
|
}
|
|
729
736
|
|
|
730
|
-
pub fn reinterpret(&self, signed: bool) -> Self {
|
|
731
|
-
self.inner
|
|
737
|
+
pub fn reinterpret(&self, signed: Option<bool>, dtype: Option<RbDataType>) -> Self {
|
|
738
|
+
self.inner
|
|
739
|
+
.clone()
|
|
740
|
+
.reinterpret(signed, dtype.map(|dt| dt.0))
|
|
741
|
+
.into()
|
|
732
742
|
}
|
|
733
743
|
|
|
734
744
|
pub fn mode(&self, maintain_order: bool) -> Self {
|
|
@@ -904,6 +914,10 @@ impl RbExpr {
|
|
|
904
914
|
self.inner.clone().all(drop_nulls).into()
|
|
905
915
|
}
|
|
906
916
|
|
|
917
|
+
pub fn is_empty(&self, ignore_nulls: bool) -> Self {
|
|
918
|
+
self.inner.clone().is_empty(ignore_nulls).into()
|
|
919
|
+
}
|
|
920
|
+
|
|
907
921
|
pub fn log(&self, base: &RbExpr) -> Self {
|
|
908
922
|
self.inner.clone().log(base.inner.clone()).into()
|
|
909
923
|
}
|
|
@@ -924,13 +938,11 @@ impl RbExpr {
|
|
|
924
938
|
self.inner.clone().hash(seed, seed_1, seed_2, seed_3).into()
|
|
925
939
|
}
|
|
926
940
|
|
|
927
|
-
pub fn set_sorted_flag(&self, descending: bool) -> Self {
|
|
928
|
-
let
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
};
|
|
933
|
-
self.inner.clone().set_sorted_flag(is_sorted).into()
|
|
941
|
+
pub fn set_sorted_flag(&self, descending: bool, nulls_last: bool) -> Self {
|
|
942
|
+
let sortedness = AExprSorted::default()
|
|
943
|
+
.with_desc(Some(descending))
|
|
944
|
+
.with_nulls_last(Some(nulls_last));
|
|
945
|
+
self.inner.clone().set_sorted_flag(sortedness).into()
|
|
934
946
|
}
|
|
935
947
|
|
|
936
948
|
pub fn replace(&self, old: &Self, new: &Self) -> Self {
|
data/ext/polars/src/expr/list.rs
CHANGED
|
@@ -7,14 +7,6 @@ use crate::conversion::Wrap;
|
|
|
7
7
|
use crate::{RbExpr, RbResult};
|
|
8
8
|
|
|
9
9
|
impl RbExpr {
|
|
10
|
-
pub fn list_all(&self) -> Self {
|
|
11
|
-
self.inner.clone().list().all().into()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
pub fn list_any(&self) -> Self {
|
|
15
|
-
self.inner.clone().list().any().into()
|
|
16
|
-
}
|
|
17
|
-
|
|
18
10
|
pub fn list_arg_max(&self) -> Self {
|
|
19
11
|
self.inner.clone().list().arg_max().into()
|
|
20
12
|
}
|
|
@@ -103,10 +95,6 @@ impl RbExpr {
|
|
|
103
95
|
self.inner.clone().list().min().into()
|
|
104
96
|
}
|
|
105
97
|
|
|
106
|
-
pub fn list_reverse(&self) -> Self {
|
|
107
|
-
self.inner.clone().list().reverse().into()
|
|
108
|
-
}
|
|
109
|
-
|
|
110
98
|
pub fn list_shift(&self, periods: &RbExpr) -> Self {
|
|
111
99
|
self.inner
|
|
112
100
|
.clone()
|
|
@@ -213,20 +201,6 @@ impl RbExpr {
|
|
|
213
201
|
.into())
|
|
214
202
|
}
|
|
215
203
|
|
|
216
|
-
pub fn list_n_unique(&self) -> Self {
|
|
217
|
-
self.inner.clone().list().n_unique().into()
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
pub fn list_unique(&self, maintain_order: bool) -> Self {
|
|
221
|
-
let e = self.inner.clone();
|
|
222
|
-
|
|
223
|
-
if maintain_order {
|
|
224
|
-
e.list().unique_stable().into()
|
|
225
|
-
} else {
|
|
226
|
-
e.list().unique().into()
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
204
|
pub fn list_set_operation(&self, other: &RbExpr, operation: Wrap<SetOperation>) -> Self {
|
|
231
205
|
let e = self.inner.clone().list();
|
|
232
206
|
match operation.0 {
|
|
@@ -6,9 +6,9 @@ pub fn business_day_count(
|
|
|
6
6
|
start: &RbExpr,
|
|
7
7
|
end: &RbExpr,
|
|
8
8
|
week_mask: [bool; 7],
|
|
9
|
-
holidays:
|
|
9
|
+
holidays: &RbExpr,
|
|
10
10
|
) -> RbExpr {
|
|
11
11
|
let start = start.inner.clone();
|
|
12
12
|
let end = end.inner.clone();
|
|
13
|
-
dsl::business_day_count(start, end, week_mask, holidays).into()
|
|
13
|
+
dsl::business_day_count(start, end, week_mask, holidays.inner.clone()).into()
|
|
14
14
|
}
|
|
@@ -8,6 +8,7 @@ use crate::conversion::Wrap;
|
|
|
8
8
|
use crate::file::{EitherRustRubyFile, get_either_file};
|
|
9
9
|
use crate::io::cloud_options::OptRbCloudOptions;
|
|
10
10
|
use crate::ruby::gvl::GvlExt;
|
|
11
|
+
use crate::ruby::utils::TryIntoValue;
|
|
11
12
|
use crate::{RbPolarsErr, RbResult};
|
|
12
13
|
|
|
13
14
|
pub fn read_ipc_schema(rb: &Ruby, rb_f: Value) -> RbResult<RHash> {
|
|
@@ -32,7 +33,6 @@ pub fn read_parquet_metadata(
|
|
|
32
33
|
) -> RbResult<RHash> {
|
|
33
34
|
use std::io::Cursor;
|
|
34
35
|
|
|
35
|
-
use polars_io::pl_async::get_runtime;
|
|
36
36
|
use polars_parquet::read::read_metadata;
|
|
37
37
|
use polars_parquet::read::schema::read_custom_key_value_metadata;
|
|
38
38
|
|
|
@@ -53,7 +53,7 @@ pub fn read_parquet_metadata(
|
|
|
53
53
|
use polars_error::PolarsResult;
|
|
54
54
|
|
|
55
55
|
rb.detach(|| {
|
|
56
|
-
|
|
56
|
+
polars_core::runtime::ASYNC.block_on(async {
|
|
57
57
|
let mut reader =
|
|
58
58
|
ParquetObjectStore::from_uri(p, cloud_options.as_ref(), None).await?;
|
|
59
59
|
let result = reader.get_metadata().await?;
|
|
@@ -97,9 +97,10 @@ pub fn read_parquet_schema(rb_f: Value) -> RbResult<RHash> {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
fn fields_to_rbdict(schema: &ArrowSchema, dict: &RHash) -> RbResult<()> {
|
|
100
|
+
let ruby = &Ruby::get_with(*dict);
|
|
100
101
|
for field in schema.iter_values() {
|
|
101
102
|
let dt = Wrap(polars::prelude::DataType::from_arrow_field(field));
|
|
102
|
-
dict.aset(field.name.as_str(), dt)?;
|
|
103
|
+
dict.aset(field.name.as_str(), dt.try_into_value_with(ruby)?)?;
|
|
103
104
|
}
|
|
104
105
|
Ok(())
|
|
105
106
|
}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
use magnus::encoding::EncodingCapable;
|
|
2
|
-
use magnus::{
|
|
2
|
+
use magnus::{
|
|
3
|
+
Float, Integer, RArray, RString, Ruby, Value, prelude::*, typed_data::Obj, value::Qfalse,
|
|
4
|
+
value::Qtrue,
|
|
5
|
+
};
|
|
3
6
|
use polars::lazy::dsl;
|
|
4
7
|
use polars::prelude::*;
|
|
8
|
+
use polars_plan::plans::DynLiteralValue;
|
|
5
9
|
|
|
10
|
+
use crate::conversion::any_value::rb_object_to_any_value;
|
|
6
11
|
use crate::conversion::{Wrap, get_lf, get_rbseq};
|
|
7
12
|
use crate::expr::ToExprs;
|
|
8
13
|
use crate::expr::datatype::RbDataTypeExpr;
|
|
9
14
|
use crate::lazyframe::RbOptFlags;
|
|
15
|
+
use crate::ruby::exceptions::{RbTypeError, RbValueError};
|
|
10
16
|
use crate::ruby::plan_callback::PlanCallbackExt;
|
|
11
17
|
use crate::ruby::ruby_function::RubyObject;
|
|
12
18
|
use crate::ruby::thread::start_background_ruby_thread;
|
|
13
19
|
use crate::utils::EnterPolarsExt;
|
|
14
|
-
use crate::{RbDataFrame, RbExpr, RbLazyFrame, RbPolarsErr, RbResult, RbSeries,
|
|
20
|
+
use crate::{RbDataFrame, RbExpr, RbLazyFrame, RbPolarsErr, RbResult, RbSeries, map};
|
|
15
21
|
|
|
16
22
|
macro_rules! set_unwrapped_or_0 {
|
|
17
23
|
($($var:ident),+ $(,)?) => {
|
|
@@ -378,34 +384,28 @@ pub fn fold(
|
|
|
378
384
|
.into())
|
|
379
385
|
}
|
|
380
386
|
|
|
381
|
-
pub fn lit(value: Value, allow_object: bool, is_scalar: bool) -> RbResult<RbExpr> {
|
|
387
|
+
pub fn lit(rb: &Ruby, value: Value, allow_object: bool, is_scalar: bool) -> RbResult<RbExpr> {
|
|
382
388
|
let ruby = Ruby::get_with(value);
|
|
383
|
-
if value
|
|
384
|
-
Ok(dsl::lit(
|
|
385
|
-
} else if
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
}
|
|
399
|
-
} else if let Some(v) = Float::from_value(value) {
|
|
400
|
-
Ok(dsl::lit(v.to_f64()).into())
|
|
401
|
-
} else if let Some(v) = RString::from_value(value) {
|
|
402
|
-
if v.enc_get() == ruby.utf8_encindex() {
|
|
403
|
-
Ok(dsl::lit(v.to_string()?).into())
|
|
389
|
+
if Qtrue::from_value(value).is_some() {
|
|
390
|
+
Ok(dsl::lit(true).into())
|
|
391
|
+
} else if Qfalse::from_value(value).is_some() {
|
|
392
|
+
Ok(dsl::lit(false).into())
|
|
393
|
+
} else if let Some(int) = Integer::from_value(value) {
|
|
394
|
+
let v = i128::try_convert(int.as_value())
|
|
395
|
+
.map_err(|e| polars_err!(InvalidOperation: "integer too large for Polars: {e}"))
|
|
396
|
+
.map_err(RbPolarsErr::from)?;
|
|
397
|
+
Ok(Expr::Literal(LiteralValue::Dyn(DynLiteralValue::Int(v))).into())
|
|
398
|
+
} else if let Some(float) = Float::from_value(value) {
|
|
399
|
+
let val = f64::try_convert(float.as_value())?;
|
|
400
|
+
Ok(Expr::Literal(LiteralValue::Dyn(DynLiteralValue::Float(val))).into())
|
|
401
|
+
} else if let Some(rbstr) = RString::from_value(value) {
|
|
402
|
+
if rbstr.enc_get() == ruby.utf8_encindex() {
|
|
403
|
+
Ok(dsl::lit(rbstr.to_string()?).into())
|
|
404
404
|
} else {
|
|
405
|
-
Ok(dsl::lit(unsafe {
|
|
405
|
+
Ok(dsl::lit(unsafe { rbstr.as_slice() }).into())
|
|
406
406
|
}
|
|
407
|
-
} else if let Ok(series) =
|
|
408
|
-
let s = series.series.
|
|
407
|
+
} else if let Ok(series) = <&RbSeries>::try_convert(value) {
|
|
408
|
+
let s = series.clone().series.into_inner();
|
|
409
409
|
if is_scalar {
|
|
410
410
|
let av = s
|
|
411
411
|
.get(0)
|
|
@@ -413,17 +413,39 @@ pub fn lit(value: Value, allow_object: bool, is_scalar: bool) -> RbResult<RbExpr
|
|
|
413
413
|
let av = av.into_static();
|
|
414
414
|
Ok(dsl::lit(Scalar::new(s.dtype().clone(), av)).into())
|
|
415
415
|
} else {
|
|
416
|
-
Ok(dsl::lit(s
|
|
416
|
+
Ok(dsl::lit(s).into())
|
|
417
417
|
}
|
|
418
418
|
} else if value.is_nil() {
|
|
419
419
|
Ok(dsl::lit(Null {}).into())
|
|
420
|
-
} else if allow_object {
|
|
421
|
-
todo!()
|
|
422
420
|
} else {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
421
|
+
let raise = || {
|
|
422
|
+
RbTypeError::new_err(format!(
|
|
423
|
+
"cannot create expression literal for value of type {}.\
|
|
424
|
+
\n\nHint: Pass `allow_object: true` to accept any value and create a literal of type Object.",
|
|
425
|
+
unsafe { value.classname() },
|
|
426
|
+
))
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
let av = rb_object_to_any_value(value, true, allow_object).map_err(|_| raise())?;
|
|
430
|
+
match av {
|
|
431
|
+
AnyValue::ObjectOwned(_) => {
|
|
432
|
+
// Check again for object allowance as for cached addresses this is not checked.
|
|
433
|
+
if allow_object {
|
|
434
|
+
let s = RbSeries::new_object(
|
|
435
|
+
rb,
|
|
436
|
+
"".to_string(),
|
|
437
|
+
rb.ary_new_from_values(&[value]),
|
|
438
|
+
false,
|
|
439
|
+
)?
|
|
440
|
+
.series
|
|
441
|
+
.into_inner();
|
|
442
|
+
Ok(dsl::lit(s).into())
|
|
443
|
+
} else {
|
|
444
|
+
Err(raise())
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
_ => Ok(Expr::Literal(LiteralValue::from(av)).into()),
|
|
448
|
+
}
|
|
427
449
|
}
|
|
428
450
|
}
|
|
429
451
|
|
|
@@ -461,7 +483,7 @@ pub fn reduce(
|
|
|
461
483
|
.into())
|
|
462
484
|
}
|
|
463
485
|
|
|
464
|
-
pub fn repeat(value: &RbExpr, n: &RbExpr, dtype: Option<Wrap<DataType>>) ->
|
|
486
|
+
pub fn repeat(value: &RbExpr, n: &RbExpr, dtype: Option<Wrap<DataType>>) -> RbExpr {
|
|
465
487
|
let mut value = value.inner.clone();
|
|
466
488
|
let n = n.inner.clone();
|
|
467
489
|
|
|
@@ -469,17 +491,7 @@ pub fn repeat(value: &RbExpr, n: &RbExpr, dtype: Option<Wrap<DataType>>) -> RbRe
|
|
|
469
491
|
value = value.cast(dtype.0);
|
|
470
492
|
}
|
|
471
493
|
|
|
472
|
-
|
|
473
|
-
let av = lv.to_any_value().unwrap();
|
|
474
|
-
// Integer inputs that fit in Int32 are parsed as such
|
|
475
|
-
if let DataType::Int64 = av.dtype() {
|
|
476
|
-
let int_value = av.try_extract::<i64>().unwrap();
|
|
477
|
-
if int_value >= i32::MIN as i64 && int_value <= i32::MAX as i64 {
|
|
478
|
-
value = value.cast(DataType::Int32);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
Ok(dsl::repeat(value, n).into())
|
|
494
|
+
dsl::repeat(value, n).into()
|
|
483
495
|
}
|
|
484
496
|
|
|
485
497
|
pub fn spearman_rank_corr(a: &RbExpr, b: &RbExpr, propagate_nans: bool) -> RbExpr {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
use magnus::{
|
|
1
|
+
use magnus::{Ruby, Value};
|
|
2
2
|
use polars_core;
|
|
3
|
-
use polars_core::POOL;
|
|
4
3
|
use polars_core::fmt::FloatFmt;
|
|
5
4
|
use polars_core::prelude::IDX_DTYPE;
|
|
5
|
+
use polars_core::runtime::RAYON;
|
|
6
6
|
|
|
7
7
|
use crate::conversion::Wrap;
|
|
8
|
+
use crate::ruby::utils::TryIntoValue;
|
|
8
9
|
use crate::{RbResult, RbValueError};
|
|
9
10
|
|
|
10
|
-
pub fn get_index_type(ruby: &Ruby) -> Value {
|
|
11
|
-
Wrap(IDX_DTYPE).
|
|
11
|
+
pub fn get_index_type(ruby: &Ruby) -> RbResult<Value> {
|
|
12
|
+
Wrap(IDX_DTYPE).try_into_value_with(ruby)
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
pub fn thread_pool_size() -> usize {
|
|
15
|
-
|
|
16
|
+
RAYON.current_num_threads()
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
pub fn set_float_fmt(fmt: String) -> RbResult<()> {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
use magnus::prelude::*;
|
|
2
|
-
use magnus::{RHash, Value};
|
|
2
|
+
use magnus::{RHash, Ruby, Value};
|
|
3
3
|
use polars::prelude::{ArrowDataType, DataType};
|
|
4
4
|
use polars_error::polars_err;
|
|
5
5
|
|
|
6
6
|
use crate::interop::arrow::to_rust::normalize_arrow_fields;
|
|
7
7
|
use crate::prelude::Wrap;
|
|
8
|
+
use crate::ruby::utils::TryIntoValue;
|
|
8
9
|
use crate::series::import_schema_rbcapsule;
|
|
9
10
|
use crate::utils::to_rb_err;
|
|
10
11
|
use crate::{RbResult, RbValueError};
|
|
@@ -16,6 +17,7 @@ pub fn init_polars_schema_from_arrow_c_schema(
|
|
|
16
17
|
polars_schema: RHash,
|
|
17
18
|
schema_object: Value,
|
|
18
19
|
) -> RbResult<()> {
|
|
20
|
+
let ruby = &Ruby::get_with(polars_schema);
|
|
19
21
|
let schema_capsule = schema_object.funcall("arrow_c_schema", ())?;
|
|
20
22
|
|
|
21
23
|
let field = import_schema_rbcapsule(schema_capsule)?;
|
|
@@ -33,7 +35,7 @@ pub fn init_polars_schema_from_arrow_c_schema(
|
|
|
33
35
|
let dtype = DataType::from_arrow_field(&field);
|
|
34
36
|
|
|
35
37
|
let name = field.name.as_str();
|
|
36
|
-
let dtype = Wrap(dtype)
|
|
38
|
+
let dtype = Wrap(dtype).try_into_value_with(ruby)?;
|
|
37
39
|
|
|
38
40
|
if polars_schema.get(name).is_some() {
|
|
39
41
|
return Err(to_rb_err(polars_err!(
|
|
@@ -6,20 +6,12 @@ use polars::frame::DataFrame;
|
|
|
6
6
|
use polars::prelude::{ArrayRef, ArrowField, PlSmallStr, PolarsResult, SchemaExt};
|
|
7
7
|
use polars::series::Series;
|
|
8
8
|
use polars_core::utils::arrow;
|
|
9
|
+
use std::ffi::CString;
|
|
9
10
|
|
|
10
11
|
use crate::RbResult;
|
|
12
|
+
use crate::ruby::capsule::RbCapsule;
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
pub struct RbArrowArrayStream {
|
|
14
|
-
pub(crate) stream: ffi::ArrowArrayStream,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
impl RbArrowArrayStream {
|
|
18
|
-
pub fn to_i(&self) -> usize {
|
|
19
|
-
(&self.stream as *const _) as usize
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
14
|
+
// TODO switch to RbCapsule in 0.27.0
|
|
23
15
|
#[magnus::wrap(class = "Polars::ArrowSchema")]
|
|
24
16
|
pub struct RbArrowSchema {
|
|
25
17
|
pub(crate) schema: ffi::ArrowSchema,
|
|
@@ -31,11 +23,24 @@ impl RbArrowSchema {
|
|
|
31
23
|
}
|
|
32
24
|
}
|
|
33
25
|
|
|
26
|
+
pub(crate) fn series_to_stream(series: &Series, ruby: &Ruby) -> RbResult<Value> {
|
|
27
|
+
let field = series.field().to_arrow(CompatLevel::newest());
|
|
28
|
+
let series = series.clone();
|
|
29
|
+
let iter = Box::new(
|
|
30
|
+
(0..series.n_chunks()).map(move |i| Ok(series.to_arrow(i, CompatLevel::newest()))),
|
|
31
|
+
) as _;
|
|
32
|
+
|
|
33
|
+
let stream = ffi::export_iterator(iter, field);
|
|
34
|
+
let stream_capsule_name = CString::new("arrow_array_stream").unwrap();
|
|
35
|
+
Ok(RbCapsule::new(stream, Some(stream_capsule_name)).into_value_with(ruby))
|
|
36
|
+
}
|
|
37
|
+
|
|
34
38
|
pub(crate) fn dataframe_to_stream(df: &DataFrame, ruby: &Ruby) -> RbResult<Value> {
|
|
35
39
|
let iter = Box::new(DataFrameStreamIterator::new(df));
|
|
36
40
|
let field = iter.field();
|
|
37
41
|
let stream = ffi::export_iterator(iter, field);
|
|
38
|
-
|
|
42
|
+
let stream_capsule_name = CString::new("arrow_array_stream").unwrap();
|
|
43
|
+
Ok(RbCapsule::new(stream, Some(stream_capsule_name)).into_value_with(ruby))
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
pub(crate) fn polars_schema_to_rbcapsule(
|