polars-df 0.23.0 → 0.24.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.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +127 -1
  3. data/Cargo.lock +72 -58
  4. data/README.md +31 -27
  5. data/ext/polars/Cargo.toml +15 -6
  6. data/ext/polars/src/batched_csv.rs +35 -39
  7. data/ext/polars/src/c_api/allocator.rs +7 -0
  8. data/ext/polars/src/c_api/mod.rs +1 -0
  9. data/ext/polars/src/catalog/unity.rs +123 -101
  10. data/ext/polars/src/conversion/any_value.rs +13 -17
  11. data/ext/polars/src/conversion/chunked_array.rs +5 -5
  12. data/ext/polars/src/conversion/datetime.rs +3 -2
  13. data/ext/polars/src/conversion/mod.rs +50 -45
  14. data/ext/polars/src/dataframe/export.rs +13 -13
  15. data/ext/polars/src/dataframe/general.rs +223 -223
  16. data/ext/polars/src/dataframe/io.rs +27 -141
  17. data/ext/polars/src/dataframe/mod.rs +13 -5
  18. data/ext/polars/src/dataframe/serde.rs +1 -1
  19. data/ext/polars/src/error.rs +44 -7
  20. data/ext/polars/src/exceptions.rs +45 -12
  21. data/ext/polars/src/expr/array.rs +12 -0
  22. data/ext/polars/src/expr/datatype.rs +2 -2
  23. data/ext/polars/src/expr/datetime.rs +4 -5
  24. data/ext/polars/src/expr/general.rs +49 -13
  25. data/ext/polars/src/expr/list.rs +4 -0
  26. data/ext/polars/src/expr/meta.rs +8 -3
  27. data/ext/polars/src/expr/mod.rs +22 -6
  28. data/ext/polars/src/expr/name.rs +19 -8
  29. data/ext/polars/src/expr/rolling.rs +50 -1
  30. data/ext/polars/src/expr/string.rs +0 -1
  31. data/ext/polars/src/expr/struct.rs +7 -2
  32. data/ext/polars/src/file.rs +136 -103
  33. data/ext/polars/src/functions/aggregation.rs +9 -8
  34. data/ext/polars/src/functions/io.rs +81 -10
  35. data/ext/polars/src/functions/lazy.rs +95 -21
  36. data/ext/polars/src/functions/mod.rs +2 -0
  37. data/ext/polars/src/functions/range.rs +19 -3
  38. data/ext/polars/src/functions/strings.rs +6 -0
  39. data/ext/polars/src/functions/utils.rs +6 -0
  40. data/ext/polars/src/interop/arrow/mod.rs +50 -1
  41. data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +30 -0
  42. data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
  43. data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
  44. data/ext/polars/src/interop/numo/to_numo_series.rs +1 -1
  45. data/ext/polars/src/lazyframe/exitable.rs +39 -0
  46. data/ext/polars/src/lazyframe/general.rs +340 -236
  47. data/ext/polars/src/lazyframe/mod.rs +46 -10
  48. data/ext/polars/src/lazyframe/optflags.rs +5 -4
  49. data/ext/polars/src/lazyframe/serde.rs +11 -3
  50. data/ext/polars/src/lazyframe/sink.rs +10 -5
  51. data/ext/polars/src/lazygroupby.rs +6 -7
  52. data/ext/polars/src/lib.rs +141 -76
  53. data/ext/polars/src/map/dataframe.rs +12 -12
  54. data/ext/polars/src/map/lazy.rs +7 -5
  55. data/ext/polars/src/map/mod.rs +15 -8
  56. data/ext/polars/src/map/series.rs +3 -3
  57. data/ext/polars/src/on_startup.rs +16 -8
  58. data/ext/polars/src/prelude.rs +1 -0
  59. data/ext/polars/src/rb_modules.rs +19 -49
  60. data/ext/polars/src/series/aggregation.rs +79 -140
  61. data/ext/polars/src/series/arithmetic.rs +16 -22
  62. data/ext/polars/src/series/comparison.rs +101 -222
  63. data/ext/polars/src/series/construction.rs +17 -18
  64. data/ext/polars/src/series/export.rs +1 -1
  65. data/ext/polars/src/series/general.rs +254 -289
  66. data/ext/polars/src/series/import.rs +17 -0
  67. data/ext/polars/src/series/map.rs +178 -160
  68. data/ext/polars/src/series/mod.rs +28 -12
  69. data/ext/polars/src/series/scatter.rs +12 -9
  70. data/ext/polars/src/sql.rs +16 -9
  71. data/ext/polars/src/testing/frame.rs +31 -0
  72. data/ext/polars/src/testing/mod.rs +5 -0
  73. data/ext/polars/src/testing/series.rs +31 -0
  74. data/ext/polars/src/timeout.rs +105 -0
  75. data/ext/polars/src/utils.rs +159 -1
  76. data/lib/polars/array_expr.rb +81 -12
  77. data/lib/polars/array_name_space.rb +74 -7
  78. data/lib/polars/batched_csv_reader.rb +21 -21
  79. data/lib/polars/binary_name_space.rb +1 -1
  80. data/lib/polars/cat_expr.rb +7 -7
  81. data/lib/polars/config.rb +1 -1
  82. data/lib/polars/convert.rb +189 -34
  83. data/lib/polars/data_frame.rb +1066 -831
  84. data/lib/polars/data_frame_plot.rb +173 -0
  85. data/lib/polars/data_type_group.rb +1 -0
  86. data/lib/polars/data_types.rb +31 -12
  87. data/lib/polars/date_time_expr.rb +51 -69
  88. data/lib/polars/date_time_name_space.rb +80 -112
  89. data/lib/polars/dynamic_group_by.rb +7 -7
  90. data/lib/polars/exceptions.rb +50 -10
  91. data/lib/polars/expr.rb +470 -517
  92. data/lib/polars/functions/aggregation/horizontal.rb +0 -1
  93. data/lib/polars/functions/aggregation/vertical.rb +2 -3
  94. data/lib/polars/functions/as_datatype.rb +290 -8
  95. data/lib/polars/functions/eager.rb +204 -10
  96. data/lib/polars/functions/escape_regex.rb +21 -0
  97. data/lib/polars/functions/lazy.rb +409 -169
  98. data/lib/polars/functions/lit.rb +17 -1
  99. data/lib/polars/functions/range/int_range.rb +74 -2
  100. data/lib/polars/functions/range/linear_space.rb +77 -0
  101. data/lib/polars/functions/range/time_range.rb +1 -1
  102. data/lib/polars/functions/repeat.rb +3 -12
  103. data/lib/polars/functions/whenthen.rb +2 -2
  104. data/lib/polars/group_by.rb +72 -20
  105. data/lib/polars/iceberg_dataset.rb +1 -6
  106. data/lib/polars/in_process_query.rb +37 -0
  107. data/lib/polars/io/cloud.rb +18 -0
  108. data/lib/polars/io/csv.rb +265 -126
  109. data/lib/polars/io/database.rb +0 -1
  110. data/lib/polars/io/delta.rb +15 -7
  111. data/lib/polars/io/ipc.rb +24 -17
  112. data/lib/polars/io/ndjson.rb +161 -24
  113. data/lib/polars/io/parquet.rb +101 -38
  114. data/lib/polars/lazy_frame.rb +849 -558
  115. data/lib/polars/lazy_group_by.rb +327 -2
  116. data/lib/polars/list_expr.rb +94 -16
  117. data/lib/polars/list_name_space.rb +88 -24
  118. data/lib/polars/meta_expr.rb +42 -1
  119. data/lib/polars/name_expr.rb +41 -4
  120. data/lib/polars/query_opt_flags.rb +198 -2
  121. data/lib/polars/rolling_group_by.rb +3 -3
  122. data/lib/polars/schema.rb +21 -3
  123. data/lib/polars/selector.rb +37 -2
  124. data/lib/polars/selectors.rb +45 -9
  125. data/lib/polars/series.rb +1156 -728
  126. data/lib/polars/series_plot.rb +72 -0
  127. data/lib/polars/slice.rb +1 -1
  128. data/lib/polars/sql_context.rb +11 -4
  129. data/lib/polars/string_expr.rb +59 -68
  130. data/lib/polars/string_name_space.rb +51 -87
  131. data/lib/polars/struct_expr.rb +36 -18
  132. data/lib/polars/testing.rb +24 -273
  133. data/lib/polars/utils/constants.rb +2 -0
  134. data/lib/polars/utils/construction/data_frame.rb +410 -0
  135. data/lib/polars/utils/construction/series.rb +364 -0
  136. data/lib/polars/utils/construction/utils.rb +9 -0
  137. data/lib/polars/utils/deprecation.rb +11 -0
  138. data/lib/polars/utils/serde.rb +8 -3
  139. data/lib/polars/utils/unstable.rb +19 -0
  140. data/lib/polars/utils/various.rb +59 -0
  141. data/lib/polars/utils.rb +46 -47
  142. data/lib/polars/version.rb +1 -1
  143. data/lib/polars.rb +47 -1
  144. metadata +25 -6
  145. data/ext/polars/src/allocator.rs +0 -13
  146. data/lib/polars/plot.rb +0 -109
@@ -12,7 +12,7 @@ fn to_series(v: Value, name: &str) -> PolarsResult<Series> {
12
12
  _ => {
13
13
  let data = ruby.ary_new();
14
14
  data.push(v).unwrap();
15
- let res = pl_series().funcall::<_, _, Value>("new", (name.to_string(), data));
15
+ let res = pl_series(&ruby).funcall::<_, _, Value>("new", (name.to_string(), data));
16
16
 
17
17
  match res {
18
18
  Ok(ruby_s) => ruby_s.funcall::<_, _, &RbSeries>("_s", ()).unwrap(),
@@ -26,17 +26,19 @@ fn to_series(v: Value, name: &str) -> PolarsResult<Series> {
26
26
  }
27
27
  };
28
28
  // Finally get the actual Series
29
- Ok(rb_rbseries.series.borrow().clone())
29
+ Ok(rb_rbseries.series.read().clone())
30
30
  }
31
31
 
32
32
  pub fn binary_lambda(lambda: Value, a: Series, b: Series) -> PolarsResult<Option<Series>> {
33
+ let ruby = Ruby::get_with(lambda);
34
+
33
35
  // create a RbSeries struct/object for Ruby
34
36
  let rbseries_a = RbSeries::new(a);
35
37
  let rbseries_b = RbSeries::new(b);
36
38
 
37
39
  // Wrap this RbSeries object in the Ruby side Series wrapper
38
- let ruby_series_wrapper_a: Value = pl_utils().funcall("wrap_s", (rbseries_a,)).unwrap();
39
- let ruby_series_wrapper_b: Value = pl_utils().funcall("wrap_s", (rbseries_b,)).unwrap();
40
+ let ruby_series_wrapper_a: Value = pl_utils(&ruby).funcall("wrap_s", (rbseries_a,)).unwrap();
41
+ let ruby_series_wrapper_b: Value = pl_utils(&ruby).funcall("wrap_s", (rbseries_b,)).unwrap();
40
42
 
41
43
  // call the lambda and get a Ruby side Series wrapper
42
44
  let result_series_wrapper: Value =
@@ -64,7 +66,7 @@ pub fn binary_lambda(lambda: Value, a: Series, b: Series) -> PolarsResult<Option
64
66
  };
65
67
 
66
68
  // Finally get the actual Series
67
- let binding = rbseries.series.borrow();
69
+ let binding = rbseries.series.read();
68
70
  Ok(Some(binding.clone()))
69
71
  }
70
72
 
@@ -2,13 +2,14 @@ pub mod dataframe;
2
2
  pub mod lazy;
3
3
  pub mod series;
4
4
 
5
- use magnus::{RHash, Value, prelude::*};
5
+ use magnus::{RHash, Ruby, Value, prelude::*};
6
6
  use polars::chunked_array::builder::get_list_builder;
7
7
  use polars::prelude::*;
8
8
  use polars_core::POOL;
9
9
  use polars_core::utils::CustomIterTools;
10
10
  use rayon::prelude::*;
11
11
 
12
+ use crate::utils::EnterPolarsExt;
12
13
  use crate::{ObjectValue, RbPolarsErr, RbResult, RbSeries, RbValueError, Wrap};
13
14
 
14
15
  pub trait RbPolarsNumericType: PolarsNumericType {}
@@ -17,10 +18,12 @@ impl RbPolarsNumericType for UInt8Type {}
17
18
  impl RbPolarsNumericType for UInt16Type {}
18
19
  impl RbPolarsNumericType for UInt32Type {}
19
20
  impl RbPolarsNumericType for UInt64Type {}
21
+ impl RbPolarsNumericType for UInt128Type {}
20
22
  impl RbPolarsNumericType for Int8Type {}
21
23
  impl RbPolarsNumericType for Int16Type {}
22
24
  impl RbPolarsNumericType for Int32Type {}
23
25
  impl RbPolarsNumericType for Int64Type {}
26
+ impl RbPolarsNumericType for Int128Type {}
24
27
  impl RbPolarsNumericType for Float32Type {}
25
28
  impl RbPolarsNumericType for Float64Type {}
26
29
 
@@ -41,6 +44,8 @@ fn iterator_to_struct(
41
44
  name: PlSmallStr,
42
45
  capacity: usize,
43
46
  ) -> RbResult<RbSeries> {
47
+ let rb = Ruby::get().unwrap();
48
+
44
49
  let (vals, flds) = match &first_value {
45
50
  av @ AnyValue::Struct(_, _, flds) => (av._iter_struct_av().collect::<Vec<_>>(), &**flds),
46
51
  AnyValue::StructOwned(payload) => (payload.0.clone(), &*payload.1),
@@ -97,13 +102,15 @@ fn iterator_to_struct(
97
102
  }
98
103
  }
99
104
 
100
- let fields = POOL.install(|| {
101
- items
102
- .par_iter()
103
- .zip(flds)
104
- .map(|(av, fld)| Series::new(fld.name().clone(), av))
105
- .collect::<Vec<_>>()
106
- });
105
+ let fields = rb.enter_polars_ok(|| {
106
+ POOL.install(|| {
107
+ items
108
+ .par_iter()
109
+ .zip(flds)
110
+ .map(|(av, fld)| Series::new(fld.name().clone(), av))
111
+ .collect::<Vec<_>>()
112
+ })
113
+ })?;
107
114
 
108
115
  Ok(
109
116
  StructChunked::from_series(name, fields[0].len(), fields.iter())
@@ -34,7 +34,7 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
34
34
  .map(|ca| ca.into_series().into())
35
35
  } else if out.respond_to("_s", true)? {
36
36
  let rb_rbseries: &RbSeries = out.funcall("_s", ()).unwrap();
37
- let series = rb_rbseries.series.borrow();
37
+ let series = rb_rbseries.series.read();
38
38
  let dt = series.dtype();
39
39
  applyer
40
40
  .apply_lambda_with_list_out_type(lambda, null_count, &series, dt)
@@ -153,8 +153,8 @@ where
153
153
  T: IntoValue,
154
154
  {
155
155
  let out: Value = lambda.funcall("call", (in_val,))?;
156
- let py_series: Obj<RbSeries> = out.funcall("_s", ())?;
157
- let tmp = py_series.series.borrow();
156
+ let rb_series: Obj<RbSeries> = out.funcall("_s", ())?;
157
+ let tmp = rb_series.series.read();
158
158
  Ok(tmp.clone())
159
159
  }
160
160
 
@@ -9,20 +9,24 @@ use polars_core::chunked_array::object::registry;
9
9
  use polars_core::chunked_array::object::registry::AnonymousObjectBuilder;
10
10
  use polars_core::prelude::AnyValue;
11
11
  use polars_error::PolarsWarning;
12
+ use polars_error::signals::register_polars_keyboard_interrupt_hook;
12
13
 
13
14
  use crate::Wrap;
14
15
  use crate::prelude::ObjectValue;
15
16
  use crate::rb_modules::pl_utils;
17
+ use crate::utils::RubyAttach;
16
18
 
17
19
  fn warning_function(msg: &str, _warning: PolarsWarning) {
18
- if let Err(e) = pl_utils().funcall::<_, _, Value>("_polars_warn", (msg.to_string(),)) {
19
- eprintln!("{e}")
20
- }
20
+ Ruby::attach(|rb| {
21
+ if let Err(e) = pl_utils(rb).funcall::<_, _, Value>("_polars_warn", (msg.to_string(),)) {
22
+ eprintln!("{e}")
23
+ }
24
+ })
21
25
  }
22
26
 
23
27
  static POLARS_REGISTRY_INIT_LOCK: OnceLock<()> = OnceLock::new();
24
28
 
25
- pub(crate) fn register_startup_deps() {
29
+ pub(crate) fn register_startup_deps(catch_keyboard_interrupt: bool) {
26
30
  POLARS_REGISTRY_INIT_LOCK.get_or_init(|| {
27
31
  let object_builder = Box::new(|name: PlSmallStr, capacity: usize| {
28
32
  Box::new(ObjectChunkedBuilder::<ObjectValue>::new(name, capacity))
@@ -30,13 +34,13 @@ pub(crate) fn register_startup_deps() {
30
34
  });
31
35
 
32
36
  let object_converter = Arc::new(|av: AnyValue| {
33
- let object = ObjectValue {
34
- inner: Wrap(av).into_value_with(&Ruby::get().unwrap()).into(),
35
- };
37
+ let object = Ruby::attach(|rb| ObjectValue {
38
+ inner: Wrap(av).into_value_with(rb).into(),
39
+ });
36
40
  Box::new(object) as Box<dyn Any>
37
41
  });
38
42
  let rbobject_converter = Arc::new(|av: AnyValue| {
39
- let object = Wrap(av).into_value_with(&Ruby::get().unwrap());
43
+ let object = Ruby::attach(|rb| Wrap(av).into_value_with(rb));
40
44
  Box::new(object) as Box<dyn Any>
41
45
  });
42
46
 
@@ -50,5 +54,9 @@ pub(crate) fn register_startup_deps() {
50
54
  );
51
55
  // Register warning function for `polars_warn!`.
52
56
  polars_error::set_warning_function(warning_function);
57
+
58
+ if catch_keyboard_interrupt {
59
+ register_polars_keyboard_interrupt_hook();
60
+ }
53
61
  });
54
62
  }
@@ -1,3 +1,4 @@
1
1
  pub use polars::prelude::*;
2
2
 
3
3
  pub use crate::conversion::*;
4
+ pub(crate) use crate::rb_modules;
@@ -1,64 +1,34 @@
1
- use magnus::{ExceptionClass, Module, RClass, RModule, Ruby, value::Lazy};
1
+ use magnus::{Module, RClass, RModule, Ruby, value::Lazy};
2
2
 
3
- static POLARS: Lazy<RModule> = Lazy::new(|ruby| ruby.class_object().const_get("Polars").unwrap());
3
+ static POLARS: Lazy<RModule> = Lazy::new(|rb| rb.class_object().const_get("Polars").unwrap());
4
+ static UTILS: Lazy<RModule> = Lazy::new(|rb| rb.get_inner(&POLARS).const_get("Utils").unwrap());
5
+ static SERIES: Lazy<RClass> = Lazy::new(|rb| rb.get_inner(&POLARS).const_get("Series").unwrap());
4
6
 
5
- pub(crate) fn polars() -> RModule {
6
- Ruby::get().unwrap().get_inner(&POLARS)
7
+ pub(crate) fn polars(rb: &Ruby) -> RModule {
8
+ rb.get_inner(&POLARS)
7
9
  }
8
10
 
9
- static SERIES: Lazy<RClass> =
10
- Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Series").unwrap());
11
-
12
- pub(crate) fn pl_series() -> RClass {
13
- Ruby::get().unwrap().get_inner(&SERIES)
11
+ pub(crate) fn pl_utils(rb: &Ruby) -> RModule {
12
+ rb.get_inner(&UTILS)
14
13
  }
15
14
 
16
- static UTILS: Lazy<RModule> = Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Utils").unwrap());
17
-
18
- pub(crate) fn pl_utils() -> RModule {
19
- Ruby::get().unwrap().get_inner(&UTILS)
15
+ pub(crate) fn pl_series(rb: &Ruby) -> RClass {
16
+ rb.get_inner(&SERIES)
20
17
  }
21
18
 
22
19
  static BIGDECIMAL: Lazy<RClass> =
23
- Lazy::new(|ruby| ruby.class_object().const_get("BigDecimal").unwrap());
20
+ Lazy::new(|rb| rb.class_object().const_get("BigDecimal").unwrap());
21
+ static DATE: Lazy<RClass> = Lazy::new(|rb| rb.class_object().const_get("Date").unwrap());
22
+ static DATETIME: Lazy<RClass> = Lazy::new(|rb| rb.class_object().const_get("DateTime").unwrap());
24
23
 
25
- pub(crate) fn bigdecimal() -> RClass {
26
- Ruby::get().unwrap().get_inner(&BIGDECIMAL)
24
+ pub(crate) fn bigdecimal(rb: &Ruby) -> RClass {
25
+ rb.get_inner(&BIGDECIMAL)
27
26
  }
28
27
 
29
- static DATE: Lazy<RClass> = Lazy::new(|ruby| ruby.class_object().const_get("Date").unwrap());
30
-
31
- pub(crate) fn date() -> RClass {
32
- Ruby::get().unwrap().get_inner(&DATE)
28
+ pub(crate) fn date(rb: &Ruby) -> RClass {
29
+ rb.get_inner(&DATE)
33
30
  }
34
31
 
35
- static DATETIME: Lazy<RClass> =
36
- Lazy::new(|ruby| ruby.class_object().const_get("DateTime").unwrap());
37
-
38
- pub(crate) fn datetime() -> RClass {
39
- Ruby::get().unwrap().get_inner(&DATETIME)
40
- }
41
-
42
- static ERROR: Lazy<ExceptionClass> =
43
- Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Error").unwrap());
44
-
45
- pub(crate) fn error() -> ExceptionClass {
46
- Ruby::get().unwrap().get_inner(&ERROR)
47
- }
48
-
49
- static COMPUTE_ERROR: Lazy<ExceptionClass> =
50
- Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("ComputeError").unwrap());
51
-
52
- pub(crate) fn compute_error() -> ExceptionClass {
53
- Ruby::get().unwrap().get_inner(&COMPUTE_ERROR)
54
- }
55
-
56
- static INVALID_OPERATION_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
57
- ruby.get_inner(&POLARS)
58
- .const_get("InvalidOperationError")
59
- .unwrap()
60
- });
61
-
62
- pub(crate) fn invalid_operation_error() -> ExceptionClass {
63
- Ruby::get().unwrap().get_inner(&INVALID_OPERATION_ERROR)
32
+ pub(crate) fn datetime(rb: &Ruby) -> RClass {
33
+ rb.get_inner(&DATETIME)
64
34
  }
@@ -1,185 +1,124 @@
1
- use crate::error::RbPolarsErr;
1
+ use DataType::*;
2
+ use magnus::{IntoValue, Ruby, Value};
3
+ use polars::prelude::*;
4
+
2
5
  use crate::prelude::*;
3
- use crate::utils::to_rb_err;
6
+ use crate::utils::EnterPolarsExt;
4
7
  use crate::{RbResult, RbSeries};
5
- use magnus::{IntoValue, Ruby, Value};
6
8
 
7
- fn scalar_to_rb(scalar: RbResult<Scalar>) -> RbResult<Value> {
8
- let ruby = Ruby::get().unwrap();
9
- Ok(Wrap(scalar?.as_any_value()).into_value_with(&ruby))
9
+ fn scalar_to_rb(scalar: RbResult<Scalar>, rb: &Ruby) -> RbResult<Value> {
10
+ Ok(Wrap(scalar?.as_any_value()).into_value_with(rb))
10
11
  }
11
12
 
12
13
  impl RbSeries {
13
- pub fn any(&self, ignore_nulls: bool) -> RbResult<Option<bool>> {
14
- let binding = self.series.borrow();
15
- let s = binding.bool().map_err(RbPolarsErr::from)?;
16
- Ok(if ignore_nulls {
17
- Some(s.any())
18
- } else {
19
- s.any_kleene()
14
+ pub fn any(rb: &Ruby, self_: &Self, ignore_nulls: bool) -> RbResult<Option<bool>> {
15
+ rb.enter_polars(|| {
16
+ let s = self_.series.read();
17
+ let s = s.bool()?;
18
+ PolarsResult::Ok(if ignore_nulls {
19
+ Some(s.any())
20
+ } else {
21
+ s.any_kleene()
22
+ })
20
23
  })
21
24
  }
22
25
 
23
- pub fn all(&self, ignore_nulls: bool) -> RbResult<Option<bool>> {
24
- let binding = self.series.borrow();
25
- let s = binding.bool().map_err(RbPolarsErr::from)?;
26
- Ok(if ignore_nulls {
27
- Some(s.all())
28
- } else {
29
- s.all_kleene()
26
+ pub fn all(rb: &Ruby, self_: &Self, ignore_nulls: bool) -> RbResult<Option<bool>> {
27
+ rb.enter_polars(|| {
28
+ let s = self_.series.read();
29
+ let s = s.bool()?;
30
+ PolarsResult::Ok(if ignore_nulls {
31
+ Some(s.all())
32
+ } else {
33
+ s.all_kleene()
34
+ })
30
35
  })
31
36
  }
32
37
 
33
- pub fn arg_max(&self) -> Option<usize> {
34
- self.series.borrow().arg_max()
38
+ pub fn arg_max(rb: &Ruby, self_: &Self) -> RbResult<Option<usize>> {
39
+ rb.enter_polars_ok(|| self_.series.read().arg_max())
35
40
  }
36
41
 
37
- pub fn arg_min(&self) -> Option<usize> {
38
- self.series.borrow().arg_min()
42
+ pub fn arg_min(rb: &Ruby, self_: &Self) -> RbResult<Option<usize>> {
43
+ rb.enter_polars_ok(|| self_.series.read().arg_min())
39
44
  }
40
45
 
41
- pub fn max(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
42
- Ok(Wrap(
43
- rb_self
44
- .series
45
- .borrow()
46
- .max_reduce()
47
- .map_err(RbPolarsErr::from)?
48
- .as_any_value(),
49
- )
50
- .into_value_with(ruby))
46
+ pub fn min(rb: &Ruby, self_: &Self) -> RbResult<Value> {
47
+ scalar_to_rb(rb.enter_polars(|| self_.series.read().min_reduce()), rb)
51
48
  }
52
49
 
53
- pub fn mean(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
54
- match rb_self.series.borrow().dtype() {
55
- DataType::Boolean => Ok(Wrap(
56
- rb_self
57
- .series
58
- .borrow()
59
- .cast(&DataType::UInt8)
60
- .unwrap()
61
- .mean_reduce()
62
- .map_err(to_rb_err)?
63
- .as_any_value(),
64
- )
65
- .into_value_with(ruby)),
50
+ pub fn max(rb: &Ruby, self_: &Self) -> RbResult<Value> {
51
+ scalar_to_rb(rb.enter_polars(|| self_.series.read().max_reduce()), rb)
52
+ }
53
+
54
+ pub fn mean(rb: &Ruby, self_: &Self) -> RbResult<Value> {
55
+ let s = self_.series.read();
56
+ match s.dtype() {
57
+ Boolean => scalar_to_rb(
58
+ rb.enter_polars(|| s.cast(&DataType::UInt8).unwrap().mean_reduce()),
59
+ rb,
60
+ ),
66
61
  // For non-numeric output types we require mean_reduce.
67
- dt if dt.is_temporal() => Ok(Wrap(
68
- rb_self
69
- .series
70
- .borrow()
71
- .mean_reduce()
72
- .map_err(to_rb_err)?
73
- .as_any_value(),
74
- )
75
- .into_value_with(ruby)),
76
- _ => Ok(rb_self.series.borrow().mean().into_value_with(ruby)),
62
+ dt if dt.is_temporal() => scalar_to_rb(rb.enter_polars(|| s.mean_reduce()), rb),
63
+ _ => Ok(s.mean().into_value_with(rb)),
77
64
  }
78
65
  }
79
66
 
80
- pub fn median(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
81
- match rb_self.series.borrow().dtype() {
82
- DataType::Boolean => Ok(Wrap(
83
- rb_self
84
- .series
85
- .borrow()
86
- .cast(&DataType::UInt8)
87
- .unwrap()
88
- .median_reduce()
89
- .map_err(RbPolarsErr::from)?
90
- .as_any_value(),
91
- )
92
- .into_value_with(ruby)),
67
+ pub fn median(rb: &Ruby, self_: &Self) -> RbResult<Value> {
68
+ let s = self_.series.read();
69
+ match s.dtype() {
70
+ Boolean => scalar_to_rb(
71
+ rb.enter_polars(|| s.cast(&DataType::UInt8).unwrap().median_reduce()),
72
+ rb,
73
+ ),
93
74
  // For non-numeric output types we require median_reduce.
94
- dt if dt.is_temporal() => Ok(Wrap(
95
- rb_self
96
- .series
97
- .borrow()
98
- .median_reduce()
99
- .map_err(RbPolarsErr::from)?
100
- .as_any_value(),
101
- )
102
- .into_value_with(ruby)),
103
- _ => Ok(rb_self.series.borrow().median().into_value_with(ruby)),
75
+ dt if dt.is_temporal() => scalar_to_rb(rb.enter_polars(|| s.median_reduce()), rb),
76
+ _ => Ok(s.median().into_value_with(rb)),
104
77
  }
105
78
  }
106
79
 
107
- pub fn min(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
108
- Ok(Wrap(
109
- rb_self
110
- .series
111
- .borrow()
112
- .min_reduce()
113
- .map_err(RbPolarsErr::from)?
114
- .as_any_value(),
115
- )
116
- .into_value_with(ruby))
117
- }
118
-
119
80
  pub fn quantile(
120
- ruby: &Ruby,
121
- rb_self: &Self,
81
+ rb: &Ruby,
82
+ self_: &Self,
122
83
  quantile: f64,
123
84
  interpolation: Wrap<QuantileMethod>,
124
85
  ) -> RbResult<Value> {
125
- let bind = rb_self
126
- .series
127
- .borrow()
128
- .quantile_reduce(quantile, interpolation.0);
129
- let sc = bind.map_err(RbPolarsErr::from)?;
130
-
131
- Ok(Wrap(sc.as_any_value()).into_value_with(ruby))
132
- }
133
-
134
- pub fn sum(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
135
- Ok(Wrap(
136
- rb_self
137
- .series
138
- .borrow()
139
- .sum_reduce()
140
- .map_err(RbPolarsErr::from)?
141
- .as_any_value(),
86
+ scalar_to_rb(
87
+ rb.enter_polars(|| {
88
+ self_
89
+ .series
90
+ .read()
91
+ .quantile_reduce(quantile, interpolation.0)
92
+ }),
93
+ rb,
142
94
  )
143
- .into_value_with(ruby))
144
95
  }
145
96
 
146
- pub fn first(&self) -> RbResult<Value> {
147
- scalar_to_rb(Ok(self.series.borrow().first()))
97
+ pub fn sum(rb: &Ruby, self_: &Self) -> RbResult<Value> {
98
+ scalar_to_rb(rb.enter_polars(|| self_.series.read().sum_reduce()), rb)
99
+ }
100
+
101
+ pub fn first(rb: &Ruby, self_: &Self) -> RbResult<Value> {
102
+ scalar_to_rb(rb.enter_polars_ok(|| self_.series.read().first()), rb)
148
103
  }
149
104
 
150
- pub fn last(&self) -> RbResult<Value> {
151
- scalar_to_rb(Ok(self.series.borrow().last()))
105
+ pub fn last(rb: &Ruby, self_: &Self) -> RbResult<Value> {
106
+ scalar_to_rb(rb.enter_polars_ok(|| self_.series.read().last()), rb)
152
107
  }
153
108
 
154
- pub fn approx_n_unique(&self) -> RbResult<IdxSize> {
155
- Ok(self
156
- .series
157
- .borrow()
158
- .approx_n_unique()
159
- .map_err(RbPolarsErr::from)?)
109
+ pub fn approx_n_unique(rb: &Ruby, self_: &Self) -> RbResult<IdxSize> {
110
+ rb.enter_polars(|| self_.series.read().approx_n_unique())
160
111
  }
161
112
 
162
- pub fn bitwise_and(&self) -> RbResult<Value> {
163
- scalar_to_rb(Ok(self
164
- .series
165
- .borrow()
166
- .and_reduce()
167
- .map_err(RbPolarsErr::from)?))
113
+ pub fn bitwise_and(rb: &Ruby, self_: &Self) -> RbResult<Value> {
114
+ scalar_to_rb(rb.enter_polars(|| self_.series.read().and_reduce()), rb)
168
115
  }
169
116
 
170
- pub fn bitwise_or(&self) -> RbResult<Value> {
171
- scalar_to_rb(Ok(self
172
- .series
173
- .borrow()
174
- .or_reduce()
175
- .map_err(RbPolarsErr::from)?))
117
+ pub fn bitwise_or(rb: &Ruby, self_: &Self) -> RbResult<Value> {
118
+ scalar_to_rb(rb.enter_polars(|| self_.series.read().or_reduce()), rb)
176
119
  }
177
120
 
178
- pub fn bitwise_xor(&self) -> RbResult<Value> {
179
- scalar_to_rb(Ok(self
180
- .series
181
- .borrow()
182
- .xor_reduce()
183
- .map_err(RbPolarsErr::from)?))
121
+ pub fn bitwise_xor(rb: &Ruby, self_: &Self) -> RbResult<Value> {
122
+ scalar_to_rb(rb.enter_polars(|| self_.series.read().xor_reduce()), rb)
184
123
  }
185
124
  }
@@ -1,34 +1,28 @@
1
- use crate::{RbPolarsErr, RbResult, RbSeries};
1
+ use magnus::Ruby;
2
+
3
+ use super::RbSeries;
4
+ use crate::RbResult;
5
+ use crate::utils::EnterPolarsExt;
2
6
 
3
7
  impl RbSeries {
4
- pub fn add(&self, other: &RbSeries) -> RbResult<Self> {
5
- Ok((&*self.series.borrow() + &*other.series.borrow())
6
- .map(Into::into)
7
- .map_err(RbPolarsErr::from)?)
8
+ pub fn add(rb: &Ruby, self_: &Self, other: &RbSeries) -> RbResult<Self> {
9
+ rb.enter_polars_series(|| &*self_.series.read() + &*other.series.read())
8
10
  }
9
11
 
10
- pub fn sub(&self, other: &RbSeries) -> RbResult<Self> {
11
- Ok((&*self.series.borrow() - &*other.series.borrow())
12
- .map(Into::into)
13
- .map_err(RbPolarsErr::from)?)
12
+ pub fn sub(rb: &Ruby, self_: &Self, other: &RbSeries) -> RbResult<Self> {
13
+ rb.enter_polars_series(|| &*self_.series.read() - &*other.series.read())
14
14
  }
15
15
 
16
- pub fn mul(&self, other: &RbSeries) -> RbResult<Self> {
17
- Ok((&*self.series.borrow() * &*other.series.borrow())
18
- .map(Into::into)
19
- .map_err(RbPolarsErr::from)?)
16
+ pub fn mul(rb: &Ruby, self_: &Self, other: &RbSeries) -> RbResult<Self> {
17
+ rb.enter_polars_series(|| &*self_.series.read() * &*other.series.read())
20
18
  }
21
19
 
22
- pub fn div(&self, other: &RbSeries) -> RbResult<Self> {
23
- Ok((&*self.series.borrow() / &*other.series.borrow())
24
- .map(Into::into)
25
- .map_err(RbPolarsErr::from)?)
20
+ pub fn div(rb: &Ruby, self_: &Self, other: &RbSeries) -> RbResult<Self> {
21
+ rb.enter_polars_series(|| &*self_.series.read() / &*other.series.read())
26
22
  }
27
23
 
28
- pub fn rem(&self, other: &RbSeries) -> RbResult<Self> {
29
- Ok((&*self.series.borrow() % &*other.series.borrow())
30
- .map(Into::into)
31
- .map_err(RbPolarsErr::from)?)
24
+ pub fn rem(rb: &Ruby, self_: &Self, other: &RbSeries) -> RbResult<Self> {
25
+ rb.enter_polars_series(|| &*self_.series.read() % &*other.series.read())
32
26
  }
33
27
  }
34
28
 
@@ -36,7 +30,7 @@ macro_rules! impl_arithmetic {
36
30
  ($name:ident, $type:ty, $operand:tt) => {
37
31
  impl RbSeries {
38
32
  pub fn $name(&self, other: $type) -> RbResult<Self> {
39
- Ok(RbSeries::new(&*self.series.borrow() $operand other))
33
+ Ok(RbSeries::new(&*self.series.read() $operand other))
40
34
  }
41
35
  }
42
36
  };