polars-df 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/Cargo.lock +597 -599
  4. data/Cargo.toml +1 -0
  5. data/README.md +8 -7
  6. data/ext/polars/Cargo.toml +20 -10
  7. data/ext/polars/src/batched_csv.rs +27 -28
  8. data/ext/polars/src/conversion.rs +135 -106
  9. data/ext/polars/src/dataframe.rs +140 -131
  10. data/ext/polars/src/error.rs +0 -5
  11. data/ext/polars/src/expr/binary.rs +18 -6
  12. data/ext/polars/src/expr/categorical.rs +8 -1
  13. data/ext/polars/src/expr/datetime.rs +10 -12
  14. data/ext/polars/src/expr/general.rs +129 -286
  15. data/ext/polars/src/expr/list.rs +17 -9
  16. data/ext/polars/src/{expr.rs → expr/mod.rs} +4 -2
  17. data/ext/polars/src/expr/name.rs +44 -0
  18. data/ext/polars/src/expr/rolling.rs +201 -0
  19. data/ext/polars/src/expr/string.rs +94 -67
  20. data/ext/polars/src/file.rs +3 -3
  21. data/ext/polars/src/functions/aggregation.rs +35 -0
  22. data/ext/polars/src/functions/eager.rs +7 -31
  23. data/ext/polars/src/functions/io.rs +10 -10
  24. data/ext/polars/src/functions/lazy.rs +66 -41
  25. data/ext/polars/src/functions/meta.rs +30 -0
  26. data/ext/polars/src/functions/misc.rs +8 -0
  27. data/ext/polars/src/functions/mod.rs +5 -0
  28. data/ext/polars/src/functions/random.rs +6 -0
  29. data/ext/polars/src/functions/range.rs +41 -0
  30. data/ext/polars/src/functions/string_cache.rs +11 -0
  31. data/ext/polars/src/functions/whenthen.rs +7 -7
  32. data/ext/polars/src/lazyframe.rs +74 -60
  33. data/ext/polars/src/lib.rs +175 -91
  34. data/ext/polars/src/{apply → map}/dataframe.rs +29 -34
  35. data/ext/polars/src/{apply → map}/mod.rs +5 -5
  36. data/ext/polars/src/{apply → map}/series.rs +18 -22
  37. data/ext/polars/src/object.rs +0 -30
  38. data/ext/polars/src/on_startup.rs +32 -0
  39. data/ext/polars/src/rb_modules.rs +22 -7
  40. data/ext/polars/src/series/aggregation.rs +3 -0
  41. data/ext/polars/src/series/construction.rs +5 -5
  42. data/ext/polars/src/series/export.rs +4 -4
  43. data/ext/polars/src/{series.rs → series/mod.rs} +28 -45
  44. data/ext/polars/src/series/{set_at_idx.rs → scatter.rs} +38 -22
  45. data/ext/polars/src/sql.rs +46 -0
  46. data/ext/polars/src/utils.rs +1 -1
  47. data/lib/polars/config.rb +530 -0
  48. data/lib/polars/data_frame.rb +182 -145
  49. data/lib/polars/data_types.rb +4 -1
  50. data/lib/polars/date_time_expr.rb +23 -28
  51. data/lib/polars/date_time_name_space.rb +17 -37
  52. data/lib/polars/dynamic_group_by.rb +2 -2
  53. data/lib/polars/expr.rb +398 -110
  54. data/lib/polars/functions.rb +29 -37
  55. data/lib/polars/group_by.rb +38 -55
  56. data/lib/polars/io.rb +40 -5
  57. data/lib/polars/lazy_frame.rb +116 -89
  58. data/lib/polars/lazy_functions.rb +40 -68
  59. data/lib/polars/lazy_group_by.rb +7 -8
  60. data/lib/polars/list_expr.rb +12 -8
  61. data/lib/polars/list_name_space.rb +2 -2
  62. data/lib/polars/name_expr.rb +198 -0
  63. data/lib/polars/rolling_group_by.rb +2 -2
  64. data/lib/polars/series.rb +315 -43
  65. data/lib/polars/sql_context.rb +194 -0
  66. data/lib/polars/string_expr.rb +114 -60
  67. data/lib/polars/string_name_space.rb +19 -4
  68. data/lib/polars/struct_expr.rb +1 -1
  69. data/lib/polars/struct_name_space.rb +1 -1
  70. data/lib/polars/utils.rb +25 -13
  71. data/lib/polars/version.rb +1 -1
  72. data/lib/polars.rb +3 -0
  73. metadata +23 -11
  74. /data/ext/polars/src/{apply → map}/lazy.rs +0 -0
@@ -1,4 +1,4 @@
1
- use magnus::{class, IntoValue, RArray, TryConvert, Value};
1
+ use magnus::{class, prelude::*, typed_data::Obj, IntoValue, RArray, TryConvert, Value};
2
2
  use polars::prelude::*;
3
3
  use polars_core::frame::row::{rows_to_schema_first_non_null, Row};
4
4
  use polars_core::series::SeriesIter;
@@ -34,20 +34,20 @@ pub fn apply_lambda_unknown<'a>(
34
34
  null_count += 1;
35
35
  continue;
36
36
  } else if out.is_kind_of(class::true_class()) || out.is_kind_of(class::false_class()) {
37
- let first_value = out.try_convert::<bool>().ok();
37
+ let first_value = bool::try_convert(out).ok();
38
38
  return Ok((
39
- RbSeries::new(
39
+ Obj::wrap(RbSeries::new(
40
40
  apply_lambda_with_bool_out_type(df, lambda, null_count, first_value)
41
41
  .into_series(),
42
- )
43
- .into(),
42
+ ))
43
+ .as_value(),
44
44
  false,
45
45
  ));
46
46
  } else if out.is_kind_of(class::float()) {
47
- let first_value = out.try_convert::<f64>().ok();
47
+ let first_value = f64::try_convert(out).ok();
48
48
 
49
49
  return Ok((
50
- RbSeries::new(
50
+ Obj::wrap(RbSeries::new(
51
51
  apply_lambda_with_primitive_out_type::<Float64Type>(
52
52
  df,
53
53
  lambda,
@@ -55,14 +55,14 @@ pub fn apply_lambda_unknown<'a>(
55
55
  first_value,
56
56
  )
57
57
  .into_series(),
58
- )
59
- .into(),
58
+ ))
59
+ .as_value(),
60
60
  false,
61
61
  ));
62
62
  } else if out.is_kind_of(class::integer()) {
63
- let first_value = out.try_convert::<i64>().ok();
63
+ let first_value = i64::try_convert(out).ok();
64
64
  return Ok((
65
- RbSeries::new(
65
+ Obj::wrap(RbSeries::new(
66
66
  apply_lambda_with_primitive_out_type::<Int64Type>(
67
67
  df,
68
68
  lambda,
@@ -70,12 +70,12 @@ pub fn apply_lambda_unknown<'a>(
70
70
  first_value,
71
71
  )
72
72
  .into_series(),
73
- )
74
- .into(),
73
+ ))
74
+ .as_value(),
75
75
  false,
76
76
  ));
77
77
  // } else if out.is_kind_of(class::string()) {
78
- // let first_value = out.try_convert::<String>().ok();
78
+ // let first_value = String::try_convert(out).ok();
79
79
  // return Ok((
80
80
  // RbSeries::new(
81
81
  // apply_lambda_with_utf8_out_type(df, lambda, null_count, first_value)
@@ -85,25 +85,21 @@ pub fn apply_lambda_unknown<'a>(
85
85
  // false,
86
86
  // ));
87
87
  } else if out.respond_to("_s", true)? {
88
- let rb_rbseries: Value = out.funcall("_s", ()).unwrap();
89
- let series = rb_rbseries
90
- .try_convert::<&RbSeries>()
91
- .unwrap()
92
- .series
93
- .borrow();
88
+ let rb_rbseries: Obj<RbSeries> = out.funcall("_s", ()).unwrap();
89
+ let series = rb_rbseries.series.borrow();
94
90
  let dt = series.dtype();
95
91
  return Ok((
96
- RbSeries::new(
92
+ Obj::wrap(RbSeries::new(
97
93
  apply_lambda_with_list_out_type(df, lambda, null_count, Some(&series), dt)?
98
94
  .into_series(),
99
- )
100
- .into(),
95
+ ))
96
+ .as_value(),
101
97
  false,
102
98
  ));
103
- } else if out.try_convert::<Wrap<Row<'a>>>().is_ok() {
104
- let first_value = out.try_convert::<Wrap<Row<'a>>>().unwrap().0;
99
+ } else if Wrap::<Row<'a>>::try_convert(out).is_ok() {
100
+ let first_value = Wrap::<Row<'a>>::try_convert(out).unwrap().0;
105
101
  return Ok((
106
- RbDataFrame::from(
102
+ Obj::wrap(RbDataFrame::from(
107
103
  apply_lambda_with_rows_output(
108
104
  df,
109
105
  lambda,
@@ -112,8 +108,8 @@ pub fn apply_lambda_unknown<'a>(
112
108
  inference_size,
113
109
  )
114
110
  .map_err(RbPolarsErr::from)?,
115
- )
116
- .into(),
111
+ ))
112
+ .as_value(),
117
113
  true,
118
114
  ));
119
115
  } else if out.is_kind_of(class::array()) {
@@ -143,7 +139,7 @@ where
143
139
  let iter = iters.iter_mut().map(|it| Wrap(it.next().unwrap()));
144
140
  let tpl = (RArray::from_iter(iter),);
145
141
  match lambda.funcall::<_, _, Value>("call", tpl) {
146
- Ok(val) => val.try_convert::<T>().ok(),
142
+ Ok(val) => T::try_convert(val).ok(),
147
143
  Err(e) => panic!("ruby function failed {}", e),
148
144
  }
149
145
  })
@@ -191,7 +187,7 @@ pub fn apply_lambda_with_utf8_out_type(
191
187
  lambda: Value,
192
188
  init_null_count: usize,
193
189
  first_value: Option<&str>,
194
- ) -> Utf8Chunked {
190
+ ) -> StringChunked {
195
191
  let skip = usize::from(first_value.is_some());
196
192
  if init_null_count == df.height() {
197
193
  ChunkedArray::full_null("apply", df.height())
@@ -219,8 +215,7 @@ pub fn apply_lambda_with_list_out_type(
219
215
  let tpl = (RArray::from_iter(iter),);
220
216
  match lambda.funcall::<_, _, Value>("call", tpl) {
221
217
  Ok(val) => match val.funcall::<_, _, Value>("_s", ()) {
222
- Ok(val) => val
223
- .try_convert::<&RbSeries>()
218
+ Ok(val) => Obj::<RbSeries>::try_convert(val)
224
219
  .ok()
225
220
  .map(|ps| ps.series.borrow().clone()),
226
221
  Err(_) => {
@@ -257,11 +252,11 @@ pub fn apply_lambda_with_rows_output<'a>(
257
252
  let tpl = (RArray::from_iter(iter),);
258
253
  match lambda.funcall::<_, _, Value>("call", tpl) {
259
254
  Ok(val) => {
260
- match val.try_convert::<RArray>().ok() {
255
+ match RArray::try_convert(val).ok() {
261
256
  Some(tuple) => {
262
257
  row_buf.0.clear();
263
258
  for v in tuple.each() {
264
- let v = v.unwrap().try_convert::<Wrap<AnyValue>>().unwrap().0;
259
+ let v = Wrap::<AnyValue>::try_convert(v.unwrap()).unwrap().0;
265
260
  row_buf.0.push(v);
266
261
  }
267
262
  let ptr = &row_buf as *const Row;
@@ -2,7 +2,7 @@ pub mod dataframe;
2
2
  pub mod lazy;
3
3
  pub mod series;
4
4
 
5
- use magnus::{RHash, Value};
5
+ use magnus::{prelude::*, RHash, Value};
6
6
  use polars::chunked_array::builder::get_list_builder;
7
7
  use polars::prelude::*;
8
8
  use polars_core::export::rayon::prelude::*;
@@ -68,7 +68,7 @@ fn iterator_to_struct(
68
68
  }
69
69
  }
70
70
  Some(dict) => {
71
- let dict = dict.try_convert::<RHash>()?;
71
+ let dict = RHash::try_convert(dict)?;
72
72
  if dict.len() != struct_width {
73
73
  return Err(crate::error::ComputeError::new_err(
74
74
  format!("Cannot create struct type.\n> The struct dtype expects {} fields, but it got a dict with {} fields.", struct_width, dict.len())
@@ -78,7 +78,7 @@ fn iterator_to_struct(
78
78
  // the first item determines the output name
79
79
  todo!()
80
80
  // for ((_, val), field_items) in dict.iter().zip(&mut items) {
81
- // let item = val.try_convert::<Wrap<AnyValue>>()?;
81
+ // let item = Wrap::<AnyValue>::try_convert(val)?;
82
82
  // field_items.push(item.0)
83
83
  // }
84
84
  }
@@ -198,11 +198,11 @@ fn iterator_to_utf8(
198
198
  first_value: Option<&str>,
199
199
  name: &str,
200
200
  capacity: usize,
201
- ) -> Utf8Chunked {
201
+ ) -> StringChunked {
202
202
  let first_value = first_value.map(|v| v.to_string());
203
203
 
204
204
  // safety: we know the iterators len
205
- let mut ca: Utf8Chunked = unsafe {
205
+ let mut ca: StringChunked = unsafe {
206
206
  if init_null_count > 0 {
207
207
  (0..init_null_count)
208
208
  .map(|_| None)
@@ -1,4 +1,4 @@
1
- use magnus::{class, IntoValue, RHash, TryConvert, Value};
1
+ use magnus::{class, prelude::*, typed_data::Obj, IntoValue, RHash, TryConvert, Value};
2
2
  use polars::prelude::*;
3
3
 
4
4
  use super::*;
@@ -14,12 +14,12 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
14
14
  null_count: usize,
15
15
  ) -> RbResult<RbSeries> {
16
16
  if out.is_kind_of(class::true_class()) || out.is_kind_of(class::false_class()) {
17
- let first_value = out.try_convert::<bool>().unwrap();
17
+ let first_value = bool::try_convert(out).unwrap();
18
18
  applyer
19
19
  .apply_lambda_with_bool_out_type(lambda, null_count, Some(first_value))
20
20
  .map(|ca| ca.into_series().into())
21
21
  } else if out.is_kind_of(class::float()) {
22
- let first_value = out.try_convert::<f64>().unwrap();
22
+ let first_value = f64::try_convert(out).unwrap();
23
23
  applyer
24
24
  .apply_lambda_with_primitive_out_type::<Float64Type>(
25
25
  lambda,
@@ -28,7 +28,7 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
28
28
  )
29
29
  .map(|ca| ca.into_series().into())
30
30
  } else if out.is_kind_of(class::string()) {
31
- let first_value = out.try_convert::<String>().unwrap();
31
+ let first_value = String::try_convert(out).unwrap();
32
32
  applyer
33
33
  .apply_lambda_with_utf8_out_type(lambda, null_count, Some(first_value.as_str()))
34
34
  .map(|ca| ca.into_series().into())
@@ -37,13 +37,13 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
37
37
  } else if out.is_kind_of(class::array()) {
38
38
  todo!()
39
39
  } else if out.is_kind_of(class::hash()) {
40
- let first = out.try_convert::<Wrap<AnyValue<'_>>>()?;
40
+ let first = Wrap::<AnyValue<'_>>::try_convert(out)?;
41
41
  applyer.apply_to_struct(lambda, null_count, first.0)
42
42
  }
43
43
  // this succeeds for numpy ints as well, where checking if it is pyint fails
44
44
  // we do this later in the chain so that we don't extract integers from string chars.
45
- else if out.try_convert::<i64>().is_ok() {
46
- let first_value = out.try_convert::<i64>().unwrap();
45
+ else if i64::try_convert(out).is_ok() {
46
+ let first_value = i64::try_convert(out).unwrap();
47
47
  applyer
48
48
  .apply_lambda_with_primitive_out_type::<Int64Type>(
49
49
  lambda,
@@ -51,7 +51,7 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
51
51
  Some(first_value),
52
52
  )
53
53
  .map(|ca| ca.into_series().into())
54
- } else if let Ok(av) = out.try_convert::<Wrap<AnyValue>>() {
54
+ } else if let Ok(av) = Wrap::<AnyValue>::try_convert(out) {
55
55
  applyer
56
56
  .apply_extract_any_values(lambda, null_count, av.0)
57
57
  .map(|s| s.into())
@@ -101,7 +101,7 @@ pub trait ApplyLambda<'a> {
101
101
  lambda: Value,
102
102
  init_null_count: usize,
103
103
  first_value: Option<&str>,
104
- ) -> RbResult<Utf8Chunked>;
104
+ ) -> RbResult<StringChunked>;
105
105
 
106
106
  /// Apply a lambda with list output type
107
107
  fn apply_lambda_with_list_out_type(
@@ -141,7 +141,7 @@ where
141
141
  S: TryConvert,
142
142
  {
143
143
  match call_lambda(lambda, in_val) {
144
- Ok(out) => out.try_convert::<S>(),
144
+ Ok(out) => S::try_convert(out),
145
145
  Err(e) => panic!("ruby function failed {}", e),
146
146
  }
147
147
  }
@@ -151,13 +151,9 @@ where
151
151
  T: IntoValue,
152
152
  {
153
153
  let out: Value = lambda.funcall("call", (in_val,))?;
154
- let py_series: Value = out.funcall("_s", ())?;
155
- Ok(py_series
156
- .try_convert::<&RbSeries>()
157
- .unwrap()
158
- .series
159
- .borrow()
160
- .clone())
154
+ let py_series: Obj<RbSeries> = out.funcall("_s", ())?;
155
+ let tmp = py_series.series.borrow();
156
+ Ok(tmp.clone())
161
157
  }
162
158
 
163
159
  impl<'a> ApplyLambda<'a> for BooleanChunked {
@@ -289,7 +285,7 @@ impl<'a> ApplyLambda<'a> for BooleanChunked {
289
285
  lambda: Value,
290
286
  init_null_count: usize,
291
287
  first_value: Option<&str>,
292
- ) -> RbResult<Utf8Chunked> {
288
+ ) -> RbResult<StringChunked> {
293
289
  let skip = usize::from(first_value.is_some());
294
290
  if init_null_count == self.len() {
295
291
  Ok(ChunkedArray::full_null(self.name(), self.len()))
@@ -566,7 +562,7 @@ where
566
562
  lambda: Value,
567
563
  init_null_count: usize,
568
564
  first_value: Option<&str>,
569
- ) -> RbResult<Utf8Chunked> {
565
+ ) -> RbResult<StringChunked> {
570
566
  let skip = usize::from(first_value.is_some());
571
567
  if init_null_count == self.len() {
572
568
  Ok(ChunkedArray::full_null(self.name(), self.len()))
@@ -709,7 +705,7 @@ where
709
705
  }
710
706
  }
711
707
 
712
- impl<'a> ApplyLambda<'a> for Utf8Chunked {
708
+ impl<'a> ApplyLambda<'a> for StringChunked {
713
709
  fn apply_lambda_unknown(&'a self, lambda: Value) -> RbResult<RbSeries> {
714
710
  let mut null_count = 0;
715
711
  for opt_v in self.into_iter() {
@@ -838,7 +834,7 @@ impl<'a> ApplyLambda<'a> for Utf8Chunked {
838
834
  lambda: Value,
839
835
  init_null_count: usize,
840
836
  first_value: Option<&str>,
841
- ) -> RbResult<Utf8Chunked> {
837
+ ) -> RbResult<StringChunked> {
842
838
  let skip = usize::from(first_value.is_some());
843
839
  if init_null_count == self.len() {
844
840
  Ok(ChunkedArray::full_null(self.name(), self.len()))
@@ -1083,7 +1079,7 @@ impl<'a> ApplyLambda<'a> for StructChunked {
1083
1079
  lambda: Value,
1084
1080
  init_null_count: usize,
1085
1081
  first_value: Option<&str>,
1086
- ) -> RbResult<Utf8Chunked> {
1082
+ ) -> RbResult<StringChunked> {
1087
1083
  let names = self.fields().iter().map(|s| s.name()).collect::<Vec<_>>();
1088
1084
 
1089
1085
  let skip = usize::from(first_value.is_some());
@@ -1,31 +1 @@
1
- use std::any::Any;
2
- use std::sync::Arc;
3
-
4
- use magnus::IntoValue;
5
- use polars_core::chunked_array::object::builder::ObjectChunkedBuilder;
6
- use polars_core::chunked_array::object::registry;
7
- use polars_core::chunked_array::object::registry::AnonymousObjectBuilder;
8
- use polars_core::prelude::AnyValue;
9
-
10
- use crate::prelude::ObjectValue;
11
- use crate::Wrap;
12
-
13
1
  pub(crate) const OBJECT_NAME: &str = "object";
14
-
15
- pub(crate) fn register_object_builder() {
16
- if !registry::is_object_builder_registered() {
17
- let object_builder = Box::new(|name: &str, capacity: usize| {
18
- Box::new(ObjectChunkedBuilder::<ObjectValue>::new(name, capacity))
19
- as Box<dyn AnonymousObjectBuilder>
20
- });
21
-
22
- let object_converter = Arc::new(|av: AnyValue| {
23
- let object = ObjectValue {
24
- inner: Wrap(av).into_value(),
25
- };
26
- Box::new(object) as Box<dyn Any>
27
- });
28
-
29
- registry::register_object_builder(object_builder, object_converter)
30
- }
31
- }
@@ -0,0 +1,32 @@
1
+ use std::any::Any;
2
+ use std::sync::Arc;
3
+
4
+ use magnus::IntoValue;
5
+ use polars::prelude::*;
6
+ use polars_core::chunked_array::object::builder::ObjectChunkedBuilder;
7
+ use polars_core::chunked_array::object::registry;
8
+ use polars_core::chunked_array::object::registry::AnonymousObjectBuilder;
9
+ use polars_core::prelude::AnyValue;
10
+
11
+ use crate::prelude::ObjectValue;
12
+ use crate::Wrap;
13
+
14
+ pub(crate) fn register_object_builder() {
15
+ if !registry::is_object_builder_registered() {
16
+ let object_builder = Box::new(|name: &str, capacity: usize| {
17
+ Box::new(ObjectChunkedBuilder::<ObjectValue>::new(name, capacity))
18
+ as Box<dyn AnonymousObjectBuilder>
19
+ });
20
+
21
+ let object_converter = Arc::new(|av: AnyValue| {
22
+ let object = ObjectValue {
23
+ inner: Wrap(av).into_value().into(),
24
+ };
25
+ Box::new(object) as Box<dyn Any>
26
+ });
27
+
28
+ let object_size = std::mem::size_of::<ObjectValue>();
29
+ let physical_dtype = ArrowDataType::FixedSizeBinary(object_size);
30
+ registry::register_object_builder(object_builder, object_converter, physical_dtype)
31
+ }
32
+ }
@@ -1,25 +1,40 @@
1
- use magnus::{class, memoize, Module, RClass, RModule};
1
+ use magnus::{value::Lazy, Module, RClass, RModule, Ruby};
2
+
3
+ static POLARS: Lazy<RModule> = Lazy::new(|ruby| ruby.class_object().const_get("Polars").unwrap());
2
4
 
3
5
  pub(crate) fn polars() -> RModule {
4
- *memoize!(RModule: class::object().const_get("Polars").unwrap())
6
+ Ruby::get().unwrap().get_inner(&POLARS)
5
7
  }
6
8
 
9
+ static SERIES: Lazy<RClass> =
10
+ Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Series").unwrap());
11
+
7
12
  pub(crate) fn series() -> RClass {
8
- *memoize!(RClass: polars().const_get("Series").unwrap())
13
+ Ruby::get().unwrap().get_inner(&SERIES)
9
14
  }
10
15
 
16
+ static UTILS: Lazy<RModule> = Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Utils").unwrap());
17
+
11
18
  pub(crate) fn utils() -> RModule {
12
- *memoize!(RModule: polars().const_get("Utils").unwrap())
19
+ Ruby::get().unwrap().get_inner(&UTILS)
13
20
  }
14
21
 
22
+ static BIGDECIMAL: Lazy<RClass> =
23
+ Lazy::new(|ruby| ruby.class_object().const_get("BigDecimal").unwrap());
24
+
15
25
  pub(crate) fn bigdecimal() -> RClass {
16
- *memoize!(RClass: class::object().const_get("BigDecimal").unwrap())
26
+ Ruby::get().unwrap().get_inner(&BIGDECIMAL)
17
27
  }
18
28
 
29
+ static DATE: Lazy<RClass> = Lazy::new(|ruby| ruby.class_object().const_get("Date").unwrap());
30
+
19
31
  pub(crate) fn date() -> RClass {
20
- *memoize!(RClass: class::object().const_get("Date").unwrap())
32
+ Ruby::get().unwrap().get_inner(&DATE)
21
33
  }
22
34
 
35
+ static DATETIME: Lazy<RClass> =
36
+ Lazy::new(|ruby| ruby.class_object().const_get("DateTime").unwrap());
37
+
23
38
  pub(crate) fn datetime() -> RClass {
24
- *memoize!(RClass: class::object().const_get("DateTime").unwrap())
39
+ Ruby::get().unwrap().get_inner(&DATETIME)
25
40
  }
@@ -17,6 +17,7 @@ impl RbSeries {
17
17
  self.series
18
18
  .borrow()
19
19
  .max_as_series()
20
+ .map_err(RbPolarsErr::from)?
20
21
  .get(0)
21
22
  .map_err(RbPolarsErr::from)?,
22
23
  )
@@ -48,6 +49,7 @@ impl RbSeries {
48
49
  self.series
49
50
  .borrow()
50
51
  .min_as_series()
52
+ .map_err(RbPolarsErr::from)?
51
53
  .get(0)
52
54
  .map_err(RbPolarsErr::from)?,
53
55
  )
@@ -75,6 +77,7 @@ impl RbSeries {
75
77
  self.series
76
78
  .borrow()
77
79
  .sum_as_series()
80
+ .map_err(RbPolarsErr::from)?
78
81
  .get(0)
79
82
  .map_err(RbPolarsErr::from)?,
80
83
  )
@@ -1,4 +1,4 @@
1
- use magnus::RArray;
1
+ use magnus::{prelude::*, RArray};
2
2
  use polars_core::prelude::*;
3
3
 
4
4
  use crate::conversion::{slice_extract_wrapped, vec_extract_wrapped, Wrap};
@@ -16,7 +16,7 @@ impl RbSeries {
16
16
  if item.is_nil() {
17
17
  builder.append_null()
18
18
  } else {
19
- match item.try_convert::<bool>() {
19
+ match bool::try_convert(*item) {
20
20
  Ok(val) => builder.append_value(val),
21
21
  Err(e) => {
22
22
  if strict {
@@ -49,7 +49,7 @@ where
49
49
  if item.is_nil() {
50
50
  builder.append_null()
51
51
  } else {
52
- match item.try_convert::<T::Native>() {
52
+ match T::Native::try_convert(*item) {
53
53
  Ok(val) => builder.append_value(val),
54
54
  Err(e) => {
55
55
  if strict {
@@ -92,7 +92,7 @@ init_method_opt!(new_opt_f64, Float64Type, f64);
92
92
  fn vec_wrap_any_value<'s>(arr: RArray) -> RbResult<Vec<Wrap<AnyValue<'s>>>> {
93
93
  let mut val = Vec::with_capacity(arr.len());
94
94
  for v in arr.each() {
95
- val.push(v?.try_convert()?);
95
+ val.push(Wrap::<AnyValue<'s>>::try_convert(v?)?);
96
96
  }
97
97
  Ok(val)
98
98
  }
@@ -106,7 +106,7 @@ impl RbSeries {
106
106
  Ok(s.into())
107
107
  }
108
108
 
109
- pub fn new_str(name: String, val: Wrap<Utf8Chunked>, _strict: bool) -> Self {
109
+ pub fn new_str(name: String, val: Wrap<StringChunked>, _strict: bool) -> Self {
110
110
  let mut s = val.0.into_series();
111
111
  s.rename(&name);
112
112
  RbSeries::new(s)
@@ -1,4 +1,4 @@
1
- use magnus::{class, Module, RArray, RClass, RModule, Value};
1
+ use magnus::{class, prelude::*, Module, RArray, RClass, RModule, Value};
2
2
  use polars_core::prelude::*;
3
3
 
4
4
  use crate::{raise_err, RbPolarsErr, RbResult, RbSeries};
@@ -9,11 +9,11 @@ impl RbSeries {
9
9
  pub fn to_numo(&self) -> RbResult<Value> {
10
10
  let s = &self.series.borrow();
11
11
  match s.dtype() {
12
- DataType::Utf8 => {
13
- let ca = s.utf8().unwrap();
12
+ DataType::String => {
13
+ let ca = s.str().unwrap();
14
14
 
15
15
  // TODO make more efficient
16
- let np_arr = RArray::from_iter(ca.into_iter());
16
+ let np_arr = RArray::from_iter(ca);
17
17
  class::object()
18
18
  .const_get::<_, RModule>("Numo")?
19
19
  .const_get::<_, RClass>("RObject")?