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
@@ -1,4 +1,3 @@
1
- use std::cell::RefCell;
2
1
  use std::path::PathBuf;
3
2
  use std::sync::Mutex;
4
3
 
@@ -7,13 +6,15 @@ use polars::io::RowIndex;
7
6
  use polars::io::csv::read::OwnedBatchedCsvReader;
8
7
  use polars::io::mmap::MmapBytesReader;
9
8
  use polars::prelude::*;
9
+ use polars_utils::open_file;
10
10
 
11
11
  use crate::conversion::*;
12
+ use crate::utils::EnterPolarsExt;
12
13
  use crate::{RbDataFrame, RbPolarsErr, RbResult};
13
14
 
14
15
  #[magnus::wrap(class = "Polars::RbBatchedCsv")]
15
16
  pub struct RbBatchedCsv {
16
- pub reader: RefCell<Mutex<OwnedBatchedCsvReader>>,
17
+ pub reader: Mutex<OwnedBatchedCsvReader>,
17
18
  }
18
19
 
19
20
  impl RbBatchedCsv {
@@ -26,27 +27,28 @@ impl RbBatchedCsv {
26
27
  let ignore_errors = bool::try_convert(arguments[3])?;
27
28
  let n_rows = Option::<usize>::try_convert(arguments[4])?;
28
29
  let skip_rows = usize::try_convert(arguments[5])?;
29
- let projection = Option::<Vec<usize>>::try_convert(arguments[6])?;
30
- let separator = String::try_convert(arguments[7])?;
31
- let rechunk = bool::try_convert(arguments[8])?;
32
- let columns = Option::<Vec<String>>::try_convert(arguments[9])?;
33
- let encoding = Wrap::<CsvEncoding>::try_convert(arguments[10])?;
34
- let n_threads = Option::<usize>::try_convert(arguments[11])?;
35
- let path = PathBuf::try_convert(arguments[12])?;
36
- let overwrite_dtype = Option::<Vec<(String, Wrap<DataType>)>>::try_convert(arguments[13])?;
37
- let overwrite_dtype_slice = Option::<Vec<Wrap<DataType>>>::try_convert(arguments[14])?;
38
- let low_memory = bool::try_convert(arguments[15])?;
39
- let comment_prefix = Option::<String>::try_convert(arguments[16])?;
40
- let quote_char = Option::<String>::try_convert(arguments[17])?;
41
- let null_values = Option::<Wrap<NullValues>>::try_convert(arguments[18])?;
42
- let missing_utf8_is_empty_string = bool::try_convert(arguments[19])?;
43
- let try_parse_dates = bool::try_convert(arguments[20])?;
44
- let skip_rows_after_header = usize::try_convert(arguments[21])?;
45
- let row_index = Option::<(String, IdxSize)>::try_convert(arguments[22])?;
46
- let eol_char = String::try_convert(arguments[23])?;
47
- let raise_if_empty = bool::try_convert(arguments[24])?;
48
- let truncate_ragged_lines = bool::try_convert(arguments[25])?;
49
- let decimal_comma = bool::try_convert(arguments[26])?;
30
+ let skip_lines = usize::try_convert(arguments[6])?;
31
+ let projection = Option::<Vec<usize>>::try_convert(arguments[7])?;
32
+ let separator = String::try_convert(arguments[8])?;
33
+ let rechunk = bool::try_convert(arguments[9])?;
34
+ let columns = Option::<Vec<String>>::try_convert(arguments[10])?;
35
+ let encoding = Wrap::<CsvEncoding>::try_convert(arguments[11])?;
36
+ let n_threads = Option::<usize>::try_convert(arguments[12])?;
37
+ let path = PathBuf::try_convert(arguments[13])?;
38
+ let schema_overrides = Option::<Vec<(String, Wrap<DataType>)>>::try_convert(arguments[14])?;
39
+ let overwrite_dtype_slice = Option::<Vec<Wrap<DataType>>>::try_convert(arguments[15])?;
40
+ let low_memory = bool::try_convert(arguments[16])?;
41
+ let comment_prefix = Option::<String>::try_convert(arguments[17])?;
42
+ let quote_char = Option::<String>::try_convert(arguments[18])?;
43
+ let null_values = Option::<Wrap<NullValues>>::try_convert(arguments[19])?;
44
+ let missing_utf8_is_empty_string = bool::try_convert(arguments[20])?;
45
+ let try_parse_dates = bool::try_convert(arguments[21])?;
46
+ let skip_rows_after_header = usize::try_convert(arguments[22])?;
47
+ let row_index = Option::<(String, IdxSize)>::try_convert(arguments[23])?;
48
+ let eol_char = String::try_convert(arguments[24])?;
49
+ let raise_if_empty = bool::try_convert(arguments[25])?;
50
+ let truncate_ragged_lines = bool::try_convert(arguments[26])?;
51
+ let decimal_comma = bool::try_convert(arguments[27])?;
50
52
  // end arguments
51
53
 
52
54
  let null_values = null_values.map(|w| w.0);
@@ -65,7 +67,7 @@ impl RbBatchedCsv {
65
67
  None
66
68
  };
67
69
 
68
- let overwrite_dtype = overwrite_dtype.map(|overwrite_dtype| {
70
+ let schema_overrides = schema_overrides.map(|overwrite_dtype| {
69
71
  overwrite_dtype
70
72
  .iter()
71
73
  .map(|(name, dtype)| {
@@ -82,13 +84,14 @@ impl RbBatchedCsv {
82
84
  .collect::<Vec<_>>()
83
85
  });
84
86
 
85
- let file = std::fs::File::open(path).map_err(RbPolarsErr::from)?;
87
+ let file = open_file(&path).map_err(RbPolarsErr::from)?;
86
88
  let reader = Box::new(file) as Box<dyn MmapBytesReader>;
87
89
  let reader = CsvReadOptions::default()
88
90
  .with_infer_schema_length(infer_schema_length)
89
91
  .with_has_header(has_header)
90
92
  .with_n_rows(n_rows)
91
93
  .with_skip_rows(skip_rows)
94
+ .with_skip_lines(skip_lines)
92
95
  .with_ignore_errors(ignore_errors)
93
96
  .with_projection(projection.map(Arc::new))
94
97
  .with_rechunk(rechunk)
@@ -97,6 +100,7 @@ impl RbBatchedCsv {
97
100
  .with_n_threads(n_threads)
98
101
  .with_dtype_overwrite(overwrite_dtype_slice.map(Arc::new))
99
102
  .with_low_memory(low_memory)
103
+ .with_schema_overwrite(schema_overrides.map(Arc::new))
100
104
  .with_skip_rows_after_header(skip_rows_after_header)
101
105
  .with_row_index(row_index)
102
106
  .with_raise_if_empty(raise_if_empty)
@@ -115,24 +119,16 @@ impl RbBatchedCsv {
115
119
  )
116
120
  .into_reader_with_file_handle(reader);
117
121
 
118
- let reader = reader
119
- .batched(overwrite_dtype.map(Arc::new))
120
- .map_err(RbPolarsErr::from)?;
122
+ let reader = reader.batched(None).map_err(RbPolarsErr::from)?;
121
123
 
122
124
  Ok(RbBatchedCsv {
123
- reader: RefCell::new(Mutex::new(reader)),
125
+ reader: Mutex::new(reader),
124
126
  })
125
127
  }
126
128
 
127
- pub fn next_batches(ruby: &Ruby, rb_self: &Self, n: usize) -> RbResult<Option<RArray>> {
128
- let reader = &rb_self.reader;
129
- let batches = reader
130
- .borrow()
131
- .lock()
132
- .map_err(|e| RbPolarsErr::Other(e.to_string()))?
133
- .next_batches(n)
134
- .map_err(RbPolarsErr::from)?;
135
-
136
- Ok(batches.map(|batches| ruby.ary_from_iter(batches.into_iter().map(RbDataFrame::from))))
129
+ pub fn next_batches(rb: &Ruby, self_: &Self, n: usize) -> RbResult<Option<RArray>> {
130
+ let reader = &self_.reader;
131
+ let batches = rb.enter_polars(move || reader.lock().unwrap().next_batches(n))?;
132
+ Ok(batches.map(|batches| rb.ary_from_iter(batches.into_iter().map(RbDataFrame::from))))
137
133
  }
138
134
  }
@@ -0,0 +1,7 @@
1
+ #[cfg(target_os = "linux")]
2
+ #[global_allocator]
3
+ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
4
+
5
+ #[cfg(target_os = "macos")]
6
+ #[global_allocator]
7
+ static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
@@ -0,0 +1 @@
1
+ pub mod allocator;
@@ -11,6 +11,7 @@ use polars_io::catalog::unity::schema::parse_type_json_str;
11
11
  use polars_io::pl_async;
12
12
 
13
13
  use crate::rb_modules::polars;
14
+ use crate::utils::EnterPolarsExt;
14
15
  use crate::utils::to_rb_err;
15
16
  use crate::{RbResult, RbValueError, Wrap};
16
17
 
@@ -29,8 +30,8 @@ macro_rules! rbdict_insert_keys {
29
30
  };
30
31
  }
31
32
 
32
- static CATALOG_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
33
- polars()
33
+ static CATALOG_INFO_CLS: Lazy<RClass> = Lazy::new(|rb| {
34
+ polars(rb)
34
35
  .const_get::<_, RClass>("Catalog")
35
36
  .unwrap()
36
37
  .const_get::<_, RModule>("Unity")
@@ -39,8 +40,8 @@ static CATALOG_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
39
40
  .unwrap()
40
41
  });
41
42
 
42
- static NAMESPACE_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
43
- polars()
43
+ static NAMESPACE_INFO_CLS: Lazy<RClass> = Lazy::new(|rb| {
44
+ polars(rb)
44
45
  .const_get::<_, RClass>("Catalog")
45
46
  .unwrap()
46
47
  .const_get::<_, RModule>("Unity")
@@ -49,8 +50,8 @@ static NAMESPACE_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
49
50
  .unwrap()
50
51
  });
51
52
 
52
- static TABLE_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
53
- polars()
53
+ static TABLE_INFO_CLS: Lazy<RClass> = Lazy::new(|rb| {
54
+ polars(rb)
54
55
  .const_get::<_, RClass>("Catalog")
55
56
  .unwrap()
56
57
  .const_get::<_, RModule>("Unity")
@@ -59,8 +60,8 @@ static TABLE_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
59
60
  .unwrap()
60
61
  });
61
62
 
62
- static COLUMN_INFO_CLS: Lazy<RClass> = Lazy::new(|_| {
63
- polars()
63
+ static COLUMN_INFO_CLS: Lazy<RClass> = Lazy::new(|rb| {
64
+ polars(rb)
64
65
  .const_get::<_, RClass>("Catalog")
65
66
  .unwrap()
66
67
  .const_get::<_, RModule>("Unity")
@@ -85,15 +86,15 @@ impl RbCatalogClient {
85
86
  builder.build().map(RbCatalogClient).map_err(to_rb_err)
86
87
  }
87
88
 
88
- pub fn list_catalogs(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
89
- let v = pl_async::get_runtime()
90
- .block_in_place_on(rb_self.client().list_catalogs())
91
- .map_err(to_rb_err)?;
89
+ pub fn list_catalogs(rb: &Ruby, self_: &Self) -> RbResult<Value> {
90
+ let v = rb.enter_polars(|| {
91
+ pl_async::get_runtime().block_in_place_on(self_.client().list_catalogs())
92
+ })?;
92
93
 
93
94
  let mut opt_err = None;
94
95
 
95
- let out = ruby.ary_from_iter(v.into_iter().map(|x| {
96
- let v = catalog_info_to_rbobject(ruby, x);
96
+ let out = rb.ary_from_iter(v.into_iter().map(|x| {
97
+ let v = catalog_info_to_rbobject(rb, x);
97
98
  if let Ok(v) = v {
98
99
  Some(v)
99
100
  } else {
@@ -107,15 +108,15 @@ impl RbCatalogClient {
107
108
  Ok(out.as_value())
108
109
  }
109
110
 
110
- pub fn list_namespaces(ruby: &Ruby, rb_self: &Self, catalog_name: String) -> RbResult<Value> {
111
- let v = pl_async::get_runtime()
112
- .block_in_place_on(rb_self.client().list_namespaces(&catalog_name))
113
- .map_err(to_rb_err)?;
111
+ pub fn list_namespaces(rb: &Ruby, self_: &Self, catalog_name: String) -> RbResult<Value> {
112
+ let v = rb.enter_polars(|| {
113
+ pl_async::get_runtime().block_in_place_on(self_.client().list_namespaces(&catalog_name))
114
+ })?;
114
115
 
115
116
  let mut opt_err = None;
116
117
 
117
- let out = ruby.ary_from_iter(v.into_iter().map(|x| {
118
- let v = namespace_info_to_rbobject(ruby, x);
118
+ let out = rb.ary_from_iter(v.into_iter().map(|x| {
119
+ let v = namespace_info_to_rbobject(rb, x);
119
120
  match v {
120
121
  Ok(v) => Some(v),
121
122
  Err(_) => {
@@ -131,20 +132,21 @@ impl RbCatalogClient {
131
132
  }
132
133
 
133
134
  pub fn list_tables(
134
- ruby: &Ruby,
135
- rb_self: &Self,
135
+ rb: &Ruby,
136
+ self_: &Self,
136
137
  catalog_name: String,
137
138
  namespace: String,
138
139
  ) -> RbResult<Value> {
139
- let v = pl_async::get_runtime()
140
- .block_in_place_on(rb_self.client().list_tables(&catalog_name, &namespace))
141
- .map_err(to_rb_err)?;
140
+ let v = rb.enter_polars(|| {
141
+ pl_async::get_runtime()
142
+ .block_in_place_on(self_.client().list_tables(&catalog_name, &namespace))
143
+ })?;
142
144
 
143
145
  let mut opt_err = None;
144
146
 
145
- let out = ruby
147
+ let out = rb
146
148
  .ary_from_iter(v.into_iter().map(|table_info| {
147
- let v = table_info_to_rbobject(ruby, table_info);
149
+ let v = table_info_to_rbobject(rb, table_info);
148
150
 
149
151
  if let Ok(v) = v {
150
152
  Some(v)
@@ -161,85 +163,100 @@ impl RbCatalogClient {
161
163
  }
162
164
 
163
165
  pub fn get_table_info(
164
- ruby: &Ruby,
165
- rb_self: &Self,
166
+ rb: &Ruby,
167
+ self_: &Self,
166
168
  table_name: String,
167
169
  catalog_name: String,
168
170
  namespace: String,
169
171
  ) -> RbResult<Value> {
170
- let table_info = pl_async::get_runtime()
171
- .block_in_place_on(rb_self.client().get_table_info(
172
- &table_name,
173
- &catalog_name,
174
- &namespace,
175
- ))
172
+ let table_info = rb
173
+ .enter_polars(|| {
174
+ pl_async::get_runtime().block_in_place_on(self_.client().get_table_info(
175
+ &table_name,
176
+ &catalog_name,
177
+ &namespace,
178
+ ))
179
+ })
176
180
  .map_err(to_rb_err)?;
177
181
 
178
- table_info_to_rbobject(ruby, table_info)
182
+ table_info_to_rbobject(rb, table_info)
179
183
  }
180
184
 
181
185
  pub fn create_catalog(
182
- ruby: &Ruby,
183
- rb_self: &Self,
186
+ rb: &Ruby,
187
+ self_: &Self,
184
188
  catalog_name: String,
185
189
  comment: Option<String>,
186
190
  storage_root: Option<String>,
187
191
  ) -> RbResult<Value> {
188
- let catalog_info = pl_async::get_runtime()
189
- .block_in_place_on(rb_self.client().create_catalog(
190
- &catalog_name,
191
- comment.as_deref(),
192
- storage_root.as_deref(),
193
- ))
192
+ let catalog_info = rb
193
+ .detach(|| {
194
+ pl_async::get_runtime().block_in_place_on(self_.client().create_catalog(
195
+ &catalog_name,
196
+ comment.as_deref(),
197
+ storage_root.as_deref(),
198
+ ))
199
+ })
194
200
  .map_err(to_rb_err)?;
195
201
 
196
- catalog_info_to_rbobject(ruby, catalog_info)
202
+ catalog_info_to_rbobject(rb, catalog_info)
197
203
  }
198
204
 
199
- pub fn delete_catalog(&self, catalog_name: String, force: bool) -> RbResult<()> {
200
- pl_async::get_runtime()
201
- .block_in_place_on(self.client().delete_catalog(&catalog_name, force))
202
- .map_err(to_rb_err)
205
+ pub fn delete_catalog(
206
+ rb: &Ruby,
207
+ self_: &Self,
208
+ catalog_name: String,
209
+ force: bool,
210
+ ) -> RbResult<()> {
211
+ rb.detach(|| {
212
+ pl_async::get_runtime()
213
+ .block_in_place_on(self_.client().delete_catalog(&catalog_name, force))
214
+ })
215
+ .map_err(to_rb_err)
203
216
  }
204
217
 
205
218
  pub fn create_namespace(
206
- ruby: &Ruby,
207
- rb_self: &Self,
219
+ rb: &Ruby,
220
+ self_: &Self,
208
221
  catalog_name: String,
209
222
  namespace: String,
210
223
  comment: Option<String>,
211
224
  storage_root: Option<String>,
212
225
  ) -> RbResult<Value> {
213
- let namespace_info = pl_async::get_runtime()
214
- .block_in_place_on(rb_self.client().create_namespace(
215
- &catalog_name,
216
- &namespace,
217
- comment.as_deref(),
218
- storage_root.as_deref(),
219
- ))
226
+ let namespace_info = rb
227
+ .detach(|| {
228
+ pl_async::get_runtime().block_in_place_on(self_.client().create_namespace(
229
+ &catalog_name,
230
+ &namespace,
231
+ comment.as_deref(),
232
+ storage_root.as_deref(),
233
+ ))
234
+ })
220
235
  .map_err(to_rb_err)?;
221
236
 
222
- namespace_info_to_rbobject(ruby, namespace_info)
237
+ namespace_info_to_rbobject(rb, namespace_info)
223
238
  }
224
239
 
225
240
  pub fn delete_namespace(
226
- &self,
241
+ rb: &Ruby,
242
+ self_: &Self,
227
243
  catalog_name: String,
228
244
  namespace: String,
229
245
  force: bool,
230
246
  ) -> RbResult<()> {
231
- pl_async::get_runtime()
232
- .block_in_place_on(
233
- self.client()
234
- .delete_namespace(&catalog_name, &namespace, force),
235
- )
236
- .map_err(to_rb_err)
247
+ rb.detach(|| {
248
+ pl_async::get_runtime().block_in_place_on(self_.client().delete_namespace(
249
+ &catalog_name,
250
+ &namespace,
251
+ force,
252
+ ))
253
+ })
254
+ .map_err(to_rb_err)
237
255
  }
238
256
 
239
- #[allow(clippy::too_many_arguments)]
240
257
  pub fn create_table(
241
- ruby: &Ruby,
242
- rb_self: &Self,
258
+ rb: &Ruby,
259
+ self_: &Self,
243
260
  catalog_name: String,
244
261
  namespace: String,
245
262
  table_name: String,
@@ -250,47 +267,52 @@ impl RbCatalogClient {
250
267
  storage_root: Option<String>,
251
268
  properties: Vec<(String, String)>,
252
269
  ) -> RbResult<Value> {
253
- let table_info = pl_async::get_runtime()
254
- .block_in_place_on(
255
- rb_self.client().create_table(
256
- &catalog_name,
257
- &namespace,
258
- &table_name,
259
- schema.as_ref().map(|x| &x.0),
260
- &TableType::from_str(&table_type)
261
- .map_err(|e| RbValueError::new_err(e.to_string()))?,
262
- data_source_format
263
- .as_deref()
264
- .map(DataSourceFormat::from_str)
265
- .transpose()
266
- .map_err(|e| RbValueError::new_err(e.to_string()))?
267
- .as_ref(),
268
- comment.as_deref(),
269
- storage_root.as_deref(),
270
- &mut properties.iter().map(|(a, b)| (a.as_str(), b.as_str())),
271
- ),
272
- )
273
- .map_err(to_rb_err)?;
274
-
275
- table_info_to_rbobject(ruby, table_info)
270
+ let table_info = rb.detach(|| {
271
+ pl_async::get_runtime()
272
+ .block_in_place_on(
273
+ self_.client().create_table(
274
+ &catalog_name,
275
+ &namespace,
276
+ &table_name,
277
+ schema.as_ref().map(|x| &x.0),
278
+ &TableType::from_str(&table_type)
279
+ .map_err(|e| RbValueError::new_err(e.to_string()))?,
280
+ data_source_format
281
+ .as_deref()
282
+ .map(DataSourceFormat::from_str)
283
+ .transpose()
284
+ .map_err(|e| RbValueError::new_err(e.to_string()))?
285
+ .as_ref(),
286
+ comment.as_deref(),
287
+ storage_root.as_deref(),
288
+ &mut properties.iter().map(|(a, b)| (a.as_str(), b.as_str())),
289
+ ),
290
+ )
291
+ .map_err(to_rb_err)
292
+ })?;
293
+
294
+ table_info_to_rbobject(rb, table_info)
276
295
  }
277
296
 
278
297
  pub fn delete_table(
279
- &self,
298
+ rb: &Ruby,
299
+ self_: &Self,
280
300
  catalog_name: String,
281
301
  namespace: String,
282
302
  table_name: String,
283
303
  ) -> RbResult<()> {
284
- pl_async::get_runtime()
285
- .block_in_place_on(
286
- self.client()
287
- .delete_table(&catalog_name, &namespace, &table_name),
288
- )
289
- .map_err(to_rb_err)
304
+ rb.detach(|| {
305
+ pl_async::get_runtime().block_in_place_on(self_.client().delete_table(
306
+ &catalog_name,
307
+ &namespace,
308
+ &table_name,
309
+ ))
310
+ })
311
+ .map_err(to_rb_err)
290
312
  }
291
313
 
292
- pub fn type_json_to_polars_type(ruby: &Ruby, type_json: String) -> RbResult<Value> {
293
- Ok(Wrap(parse_type_json_str(&type_json).map_err(to_rb_err)?).into_value_with(ruby))
314
+ pub fn type_json_to_polars_type(rb: &Ruby, type_json: String) -> RbResult<Value> {
315
+ Ok(Wrap(parse_type_json_str(&type_json).map_err(to_rb_err)?).into_value_with(rb))
294
316
  }
295
317
  }
296
318
 
@@ -11,7 +11,7 @@ use super::{ObjectValue, Wrap, struct_dict};
11
11
 
12
12
  use crate::exceptions::RbOverflowError;
13
13
  use crate::rb_modules::pl_utils;
14
- use crate::{RbErr, RbPolarsErr, RbResult, RbSeries};
14
+ use crate::{RbErr, RbPolarsErr, RbResult, RbSeries, RbValueError};
15
15
 
16
16
  impl IntoValue for Wrap<AnyValue<'_>> {
17
17
  fn into_value_with(self, ruby: &Ruby) -> Value {
@@ -49,7 +49,7 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
49
49
  AnyValue::CategoricalOwned(cat, map) | AnyValue::EnumOwned(cat, map) => unsafe {
50
50
  map.cat_to_str_unchecked(cat).into_value_with(ruby)
51
51
  },
52
- AnyValue::Date(v) => pl_utils().funcall("_to_ruby_date", (v,)).unwrap(),
52
+ AnyValue::Date(v) => pl_utils(ruby).funcall("_to_ruby_date", (v,)).unwrap(),
53
53
  AnyValue::Datetime(v, time_unit, time_zone) => {
54
54
  datetime_to_rb_object(v, time_unit, time_zone)
55
55
  }
@@ -58,11 +58,11 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
58
58
  }
59
59
  AnyValue::Duration(v, time_unit) => {
60
60
  let time_unit = time_unit.to_ascii();
61
- pl_utils()
61
+ pl_utils(ruby)
62
62
  .funcall("_to_ruby_duration", (v, time_unit))
63
63
  .unwrap()
64
64
  }
65
- AnyValue::Time(v) => pl_utils().funcall("_to_ruby_time", (v,)).unwrap(),
65
+ AnyValue::Time(v) => pl_utils(ruby).funcall("_to_ruby_time", (v,)).unwrap(),
66
66
  AnyValue::Array(v, _) | AnyValue::List(v) => RbSeries::new(v).to_a().as_value(),
67
67
  ref av @ AnyValue::Struct(_, _, flds) => struct_dict(ruby, av._iter_struct_av(), flds),
68
68
  AnyValue::StructOwned(payload) => struct_dict(ruby, payload.0.into_iter(), &payload.1),
@@ -79,7 +79,9 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
79
79
  AnyValue::Decimal(v, prec, scale) => {
80
80
  let mut buf = DecimalFmtBuffer::new();
81
81
  let s = buf.format_dec128(v, scale, false, false);
82
- pl_utils().funcall("_to_ruby_decimal", (prec, s)).unwrap()
82
+ pl_utils(ruby)
83
+ .funcall("_to_ruby_decimal", (prec, s))
84
+ .unwrap()
83
85
  }
84
86
  }
85
87
  }
@@ -198,14 +200,8 @@ pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<An
198
200
  Ok(AnyValue::Datetime(v, TimeUnit::Nanoseconds, None))
199
201
  }
200
202
 
201
- fn get_datetime(ob: Value, _strict: bool) -> RbResult<AnyValue<'static>> {
202
- let sec: i64 = ob.funcall("to_i", ())?;
203
- let nsec: i64 = ob.funcall("nsec", ())?;
204
- Ok(AnyValue::Datetime(
205
- sec * 1_000_000_000 + nsec,
206
- TimeUnit::Nanoseconds,
207
- None,
208
- ))
203
+ fn get_datetime(ob: Value, strict: bool) -> RbResult<AnyValue<'static>> {
204
+ get_time(ob.funcall("to_time", ())?, strict)
209
205
  }
210
206
 
211
207
  fn get_decimal(ob: Value, _strict: bool) -> RbResult<AnyValue<'static>> {
@@ -258,13 +254,13 @@ pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<An
258
254
  // call is_a? for ActiveSupport::TimeWithZone
259
255
  } else if ob.funcall::<_, _, bool>("is_a?", (ruby.class_time(),))? {
260
256
  get_time(ob, strict)
261
- } else if ob.is_kind_of(crate::rb_modules::datetime()) {
257
+ } else if ob.is_kind_of(crate::rb_modules::datetime(&ruby)) {
262
258
  get_datetime(ob, strict)
263
- } else if ob.is_kind_of(crate::rb_modules::date()) {
259
+ } else if ob.is_kind_of(crate::rb_modules::date(&ruby)) {
264
260
  get_date(ob, strict)
265
- } else if ob.is_kind_of(crate::rb_modules::bigdecimal()) {
261
+ } else if ob.is_kind_of(crate::rb_modules::bigdecimal(&ruby)) {
266
262
  get_decimal(ob, strict)
267
263
  } else {
268
- Err(RbPolarsErr::Other(format!("object type not supported {ob:?}")).into())
264
+ Err(RbValueError::new_err(format!("Cannot convert {ob}")))
269
265
  }
270
266
  }
@@ -74,7 +74,7 @@ impl IntoValue for Wrap<&StructChunked> {
74
74
 
75
75
  impl IntoValue for Wrap<&DurationChunked> {
76
76
  fn into_value_with(self, ruby: &Ruby) -> Value {
77
- let utils = pl_utils();
77
+ let utils = pl_utils(ruby);
78
78
  let time_unit = Wrap(self.0.time_unit()).into_value_with(ruby);
79
79
  let iter = self.0.physical().into_iter().map(|opt_v| {
80
80
  opt_v.map(|v| {
@@ -89,7 +89,7 @@ impl IntoValue for Wrap<&DurationChunked> {
89
89
 
90
90
  impl IntoValue for Wrap<&DatetimeChunked> {
91
91
  fn into_value_with(self, ruby: &Ruby) -> Value {
92
- let utils = pl_utils();
92
+ let utils = pl_utils(ruby);
93
93
  let time_unit = Wrap(self.0.time_unit()).into_value_with(ruby);
94
94
  let time_zone = self
95
95
  .0
@@ -109,7 +109,7 @@ impl IntoValue for Wrap<&DatetimeChunked> {
109
109
 
110
110
  impl IntoValue for Wrap<&TimeChunked> {
111
111
  fn into_value_with(self, ruby: &Ruby) -> Value {
112
- let utils = pl_utils();
112
+ let utils = pl_utils(ruby);
113
113
  let iter = self.0.physical().into_iter().map(|opt_v| {
114
114
  opt_v.map(|v| utils.funcall::<_, _, Value>("_to_ruby_time", (v,)).unwrap())
115
115
  });
@@ -119,7 +119,7 @@ impl IntoValue for Wrap<&TimeChunked> {
119
119
 
120
120
  impl IntoValue for Wrap<&DateChunked> {
121
121
  fn into_value_with(self, ruby: &Ruby) -> Value {
122
- let utils = pl_utils();
122
+ let utils = pl_utils(ruby);
123
123
  let iter = self.0.physical().into_iter().map(|opt_v| {
124
124
  opt_v.map(|v| utils.funcall::<_, _, Value>("_to_ruby_date", (v,)).unwrap())
125
125
  });
@@ -129,7 +129,7 @@ impl IntoValue for Wrap<&DateChunked> {
129
129
 
130
130
  impl IntoValue for Wrap<&DecimalChunked> {
131
131
  fn into_value_with(self, ruby: &Ruby) -> Value {
132
- let utils = pl_utils();
132
+ let utils = pl_utils(ruby);
133
133
  let rb_precision = self.0.precision().into_value_with(ruby);
134
134
  let mut buf = DecimalFmtBuffer::new();
135
135
  let iter = self.0.physical().into_iter().map(|opt_v| {
@@ -1,11 +1,12 @@
1
- use magnus::{Value, prelude::*};
1
+ use magnus::{Ruby, Value, prelude::*};
2
2
  use polars::prelude::*;
3
3
 
4
4
  use crate::rb_modules::pl_utils;
5
5
 
6
6
  pub fn datetime_to_rb_object(v: i64, tu: TimeUnit, tz: Option<&TimeZone>) -> Value {
7
+ let ruby = Ruby::get().unwrap();
7
8
  let tu = tu.to_ascii();
8
- pl_utils()
9
+ pl_utils(&ruby)
9
10
  .funcall("_to_ruby_datetime", (v, tu, tz.map(|v| v.to_string())))
10
11
  .unwrap()
11
12
  }