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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +127 -1
- data/Cargo.lock +72 -58
- data/README.md +31 -27
- data/ext/polars/Cargo.toml +15 -6
- data/ext/polars/src/batched_csv.rs +35 -39
- data/ext/polars/src/c_api/allocator.rs +7 -0
- data/ext/polars/src/c_api/mod.rs +1 -0
- data/ext/polars/src/catalog/unity.rs +123 -101
- data/ext/polars/src/conversion/any_value.rs +13 -17
- data/ext/polars/src/conversion/chunked_array.rs +5 -5
- data/ext/polars/src/conversion/datetime.rs +3 -2
- data/ext/polars/src/conversion/mod.rs +50 -45
- data/ext/polars/src/dataframe/export.rs +13 -13
- data/ext/polars/src/dataframe/general.rs +223 -223
- data/ext/polars/src/dataframe/io.rs +27 -141
- data/ext/polars/src/dataframe/mod.rs +13 -5
- data/ext/polars/src/dataframe/serde.rs +1 -1
- data/ext/polars/src/error.rs +44 -7
- data/ext/polars/src/exceptions.rs +45 -12
- data/ext/polars/src/expr/array.rs +12 -0
- data/ext/polars/src/expr/datatype.rs +2 -2
- data/ext/polars/src/expr/datetime.rs +4 -5
- data/ext/polars/src/expr/general.rs +49 -13
- data/ext/polars/src/expr/list.rs +4 -0
- data/ext/polars/src/expr/meta.rs +8 -3
- data/ext/polars/src/expr/mod.rs +22 -6
- data/ext/polars/src/expr/name.rs +19 -8
- data/ext/polars/src/expr/rolling.rs +50 -1
- data/ext/polars/src/expr/string.rs +0 -1
- data/ext/polars/src/expr/struct.rs +7 -2
- data/ext/polars/src/file.rs +136 -103
- data/ext/polars/src/functions/aggregation.rs +9 -8
- data/ext/polars/src/functions/io.rs +81 -10
- data/ext/polars/src/functions/lazy.rs +95 -21
- data/ext/polars/src/functions/mod.rs +2 -0
- data/ext/polars/src/functions/range.rs +19 -3
- data/ext/polars/src/functions/strings.rs +6 -0
- data/ext/polars/src/functions/utils.rs +6 -0
- data/ext/polars/src/interop/arrow/mod.rs +50 -1
- data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +30 -0
- data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
- data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
- data/ext/polars/src/interop/numo/to_numo_series.rs +1 -1
- data/ext/polars/src/lazyframe/exitable.rs +39 -0
- data/ext/polars/src/lazyframe/general.rs +340 -236
- data/ext/polars/src/lazyframe/mod.rs +46 -10
- data/ext/polars/src/lazyframe/optflags.rs +5 -4
- data/ext/polars/src/lazyframe/serde.rs +11 -3
- data/ext/polars/src/lazyframe/sink.rs +10 -5
- data/ext/polars/src/lazygroupby.rs +6 -7
- data/ext/polars/src/lib.rs +141 -76
- data/ext/polars/src/map/dataframe.rs +12 -12
- data/ext/polars/src/map/lazy.rs +7 -5
- data/ext/polars/src/map/mod.rs +15 -8
- data/ext/polars/src/map/series.rs +3 -3
- data/ext/polars/src/on_startup.rs +16 -8
- data/ext/polars/src/prelude.rs +1 -0
- data/ext/polars/src/rb_modules.rs +19 -49
- data/ext/polars/src/series/aggregation.rs +79 -140
- data/ext/polars/src/series/arithmetic.rs +16 -22
- data/ext/polars/src/series/comparison.rs +101 -222
- data/ext/polars/src/series/construction.rs +17 -18
- data/ext/polars/src/series/export.rs +1 -1
- data/ext/polars/src/series/general.rs +254 -289
- data/ext/polars/src/series/import.rs +17 -0
- data/ext/polars/src/series/map.rs +178 -160
- data/ext/polars/src/series/mod.rs +28 -12
- data/ext/polars/src/series/scatter.rs +12 -9
- data/ext/polars/src/sql.rs +16 -9
- data/ext/polars/src/testing/frame.rs +31 -0
- data/ext/polars/src/testing/mod.rs +5 -0
- data/ext/polars/src/testing/series.rs +31 -0
- data/ext/polars/src/timeout.rs +105 -0
- data/ext/polars/src/utils.rs +159 -1
- data/lib/polars/array_expr.rb +81 -12
- data/lib/polars/array_name_space.rb +74 -7
- data/lib/polars/batched_csv_reader.rb +21 -21
- data/lib/polars/binary_name_space.rb +1 -1
- data/lib/polars/cat_expr.rb +7 -7
- data/lib/polars/config.rb +1 -1
- data/lib/polars/convert.rb +189 -34
- data/lib/polars/data_frame.rb +1066 -831
- data/lib/polars/data_frame_plot.rb +173 -0
- data/lib/polars/data_type_group.rb +1 -0
- data/lib/polars/data_types.rb +31 -12
- data/lib/polars/date_time_expr.rb +51 -69
- data/lib/polars/date_time_name_space.rb +80 -112
- data/lib/polars/dynamic_group_by.rb +7 -7
- data/lib/polars/exceptions.rb +50 -10
- data/lib/polars/expr.rb +470 -517
- data/lib/polars/functions/aggregation/horizontal.rb +0 -1
- data/lib/polars/functions/aggregation/vertical.rb +2 -3
- data/lib/polars/functions/as_datatype.rb +290 -8
- data/lib/polars/functions/eager.rb +204 -10
- data/lib/polars/functions/escape_regex.rb +21 -0
- data/lib/polars/functions/lazy.rb +409 -169
- data/lib/polars/functions/lit.rb +17 -1
- data/lib/polars/functions/range/int_range.rb +74 -2
- data/lib/polars/functions/range/linear_space.rb +77 -0
- data/lib/polars/functions/range/time_range.rb +1 -1
- data/lib/polars/functions/repeat.rb +3 -12
- data/lib/polars/functions/whenthen.rb +2 -2
- data/lib/polars/group_by.rb +72 -20
- data/lib/polars/iceberg_dataset.rb +1 -6
- data/lib/polars/in_process_query.rb +37 -0
- data/lib/polars/io/cloud.rb +18 -0
- data/lib/polars/io/csv.rb +265 -126
- data/lib/polars/io/database.rb +0 -1
- data/lib/polars/io/delta.rb +15 -7
- data/lib/polars/io/ipc.rb +24 -17
- data/lib/polars/io/ndjson.rb +161 -24
- data/lib/polars/io/parquet.rb +101 -38
- data/lib/polars/lazy_frame.rb +849 -558
- data/lib/polars/lazy_group_by.rb +327 -2
- data/lib/polars/list_expr.rb +94 -16
- data/lib/polars/list_name_space.rb +88 -24
- data/lib/polars/meta_expr.rb +42 -1
- data/lib/polars/name_expr.rb +41 -4
- data/lib/polars/query_opt_flags.rb +198 -2
- data/lib/polars/rolling_group_by.rb +3 -3
- data/lib/polars/schema.rb +21 -3
- data/lib/polars/selector.rb +37 -2
- data/lib/polars/selectors.rb +45 -9
- data/lib/polars/series.rb +1156 -728
- data/lib/polars/series_plot.rb +72 -0
- data/lib/polars/slice.rb +1 -1
- data/lib/polars/sql_context.rb +11 -4
- data/lib/polars/string_expr.rb +59 -68
- data/lib/polars/string_name_space.rb +51 -87
- data/lib/polars/struct_expr.rb +36 -18
- data/lib/polars/testing.rb +24 -273
- data/lib/polars/utils/constants.rb +2 -0
- data/lib/polars/utils/construction/data_frame.rb +410 -0
- data/lib/polars/utils/construction/series.rb +364 -0
- data/lib/polars/utils/construction/utils.rb +9 -0
- data/lib/polars/utils/deprecation.rb +11 -0
- data/lib/polars/utils/serde.rb +8 -3
- data/lib/polars/utils/unstable.rb +19 -0
- data/lib/polars/utils/various.rb +59 -0
- data/lib/polars/utils.rb +46 -47
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +47 -1
- metadata +25 -6
- data/ext/polars/src/allocator.rs +0 -13
- data/lib/polars/plot.rb +0 -109
data/ext/polars/src/expr/mod.rs
CHANGED
|
@@ -15,7 +15,7 @@ mod serde;
|
|
|
15
15
|
mod string;
|
|
16
16
|
mod r#struct;
|
|
17
17
|
|
|
18
|
-
use magnus::{RArray, prelude::*};
|
|
18
|
+
use magnus::{RArray, Ruby, prelude::*};
|
|
19
19
|
use polars::lazy::dsl::Expr;
|
|
20
20
|
|
|
21
21
|
use crate::RbResult;
|
|
@@ -32,10 +32,26 @@ impl From<Expr> for RbExpr {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
pub
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
pub(crate) trait ToExprs {
|
|
36
|
+
fn to_exprs(self) -> RbResult<Vec<Expr>>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl ToExprs for RArray {
|
|
40
|
+
fn to_exprs(self) -> RbResult<Vec<Expr>> {
|
|
41
|
+
let mut exprs = Vec::new();
|
|
42
|
+
for item in self.into_iter() {
|
|
43
|
+
exprs.push(<&RbExpr>::try_convert(item)?.inner.clone());
|
|
44
|
+
}
|
|
45
|
+
Ok(exprs)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub(crate) trait ToRbExprs {
|
|
50
|
+
fn to_rbexprs(self, rb: &Ruby) -> RArray;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
impl ToRbExprs for Vec<Expr> {
|
|
54
|
+
fn to_rbexprs(self, rb: &Ruby) -> RArray {
|
|
55
|
+
rb.ary_from_iter(self.iter().map(|e| RbExpr::from(e.clone())))
|
|
39
56
|
}
|
|
40
|
-
Ok(exprs)
|
|
41
57
|
}
|
data/ext/polars/src/expr/name.rs
CHANGED
|
@@ -3,6 +3,7 @@ use polars::prelude::*;
|
|
|
3
3
|
use polars_utils::format_pl_smallstr;
|
|
4
4
|
|
|
5
5
|
use crate::RbExpr;
|
|
6
|
+
use crate::utils::RubyAttach;
|
|
6
7
|
|
|
7
8
|
impl RbExpr {
|
|
8
9
|
pub fn name_keep(&self) -> Self {
|
|
@@ -12,14 +13,16 @@ impl RbExpr {
|
|
|
12
13
|
pub fn name_map(&self, lambda: Proc) -> Self {
|
|
13
14
|
let lambda = Opaque::from(lambda);
|
|
14
15
|
let func = PlanCallback::new(move |name: PlSmallStr| {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
Ruby::attach(|rb| {
|
|
17
|
+
let lambda = rb.get_inner(lambda);
|
|
18
|
+
let out = lambda.call::<_, String>((name.as_str(),));
|
|
19
|
+
match out {
|
|
20
|
+
Ok(out) => Ok(format_pl_smallstr!("{}", out)),
|
|
21
|
+
Err(e) => Err(PolarsError::ComputeError(
|
|
22
|
+
format!("Ruby function in 'name.map' produced an error: {e}.").into(),
|
|
23
|
+
)),
|
|
24
|
+
}
|
|
25
|
+
})
|
|
23
26
|
});
|
|
24
27
|
self.inner.clone().name().map(func).into()
|
|
25
28
|
}
|
|
@@ -40,6 +43,14 @@ impl RbExpr {
|
|
|
40
43
|
self.inner.clone().name().to_uppercase().into()
|
|
41
44
|
}
|
|
42
45
|
|
|
46
|
+
pub fn name_replace(&self, pattern: String, value: String, literal: bool) -> Self {
|
|
47
|
+
self.inner
|
|
48
|
+
.clone()
|
|
49
|
+
.name()
|
|
50
|
+
.replace(&pattern, &value, literal)
|
|
51
|
+
.into()
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
pub fn name_prefix_fields(&self, prefix: String) -> Self {
|
|
44
55
|
self.inner.clone().name().prefix_fields(&prefix).into()
|
|
45
56
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use polars::prelude::*;
|
|
2
2
|
|
|
3
|
-
use crate::RbExpr;
|
|
4
3
|
use crate::conversion::Wrap;
|
|
4
|
+
use crate::{RbExpr, RbPolarsErr, RbResult};
|
|
5
5
|
|
|
6
6
|
impl RbExpr {
|
|
7
7
|
pub fn rolling_sum(
|
|
@@ -319,6 +319,55 @@ impl RbExpr {
|
|
|
319
319
|
.into()
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
pub fn rolling_rank(
|
|
323
|
+
&self,
|
|
324
|
+
window_size: usize,
|
|
325
|
+
method: Wrap<RollingRankMethod>,
|
|
326
|
+
seed: Option<u64>,
|
|
327
|
+
min_samples: Option<usize>,
|
|
328
|
+
center: bool,
|
|
329
|
+
) -> Self {
|
|
330
|
+
let min_samples = min_samples.unwrap_or(window_size);
|
|
331
|
+
let options = RollingOptionsFixedWindow {
|
|
332
|
+
window_size,
|
|
333
|
+
min_periods: min_samples,
|
|
334
|
+
weights: None,
|
|
335
|
+
center,
|
|
336
|
+
fn_params: Some(RollingFnParams::Rank {
|
|
337
|
+
method: method.0,
|
|
338
|
+
seed,
|
|
339
|
+
}),
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
self.inner.clone().rolling_rank(options).into()
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
pub fn rolling_rank_by(
|
|
346
|
+
&self,
|
|
347
|
+
by: &RbExpr,
|
|
348
|
+
window_size: String,
|
|
349
|
+
method: Wrap<RollingRankMethod>,
|
|
350
|
+
seed: Option<u64>,
|
|
351
|
+
min_samples: usize,
|
|
352
|
+
closed: Wrap<ClosedWindow>,
|
|
353
|
+
) -> RbResult<Self> {
|
|
354
|
+
let options = RollingOptionsDynamicWindow {
|
|
355
|
+
window_size: Duration::try_parse(&window_size).map_err(RbPolarsErr::from)?,
|
|
356
|
+
min_periods: min_samples,
|
|
357
|
+
closed_window: closed.0,
|
|
358
|
+
fn_params: Some(RollingFnParams::Rank {
|
|
359
|
+
method: method.0,
|
|
360
|
+
seed,
|
|
361
|
+
}),
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
Ok(self
|
|
365
|
+
.inner
|
|
366
|
+
.clone()
|
|
367
|
+
.rolling_rank_by(by.inner.clone(), options)
|
|
368
|
+
.into())
|
|
369
|
+
}
|
|
370
|
+
|
|
322
371
|
pub fn rolling_skew(
|
|
323
372
|
&self,
|
|
324
373
|
window_size: usize,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use magnus::RArray;
|
|
2
2
|
|
|
3
|
-
use crate::
|
|
3
|
+
use crate::expr::ToExprs;
|
|
4
|
+
use crate::{RbExpr, RbResult};
|
|
4
5
|
|
|
5
6
|
impl RbExpr {
|
|
6
7
|
pub fn struct_field_by_index(&self, index: i64) -> Self {
|
|
@@ -11,6 +12,10 @@ impl RbExpr {
|
|
|
11
12
|
self.inner.clone().struct_().field_by_name(&name).into()
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
pub fn struct_multiple_fields(&self, names: Vec<String>) -> Self {
|
|
16
|
+
self.inner.clone().struct_().field_by_names(&names).into()
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
pub fn struct_rename_fields(&self, names: Vec<String>) -> Self {
|
|
15
20
|
self.inner.clone().struct_().rename_fields(names).into()
|
|
16
21
|
}
|
|
@@ -20,7 +25,7 @@ impl RbExpr {
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
pub fn struct_with_fields(&self, fields: RArray) -> RbResult<Self> {
|
|
23
|
-
let fields =
|
|
28
|
+
let fields = fields.to_exprs()?;
|
|
24
29
|
let e = self.inner.clone().struct_().with_fields(fields);
|
|
25
30
|
Ok(e.into())
|
|
26
31
|
}
|
data/ext/polars/src/file.rs
CHANGED
|
@@ -4,69 +4,90 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
|
|
4
4
|
use std::path::PathBuf;
|
|
5
5
|
|
|
6
6
|
use magnus::{Error, RString, Ruby, Value, prelude::*, value::Opaque};
|
|
7
|
-
use polars::io::cloud::CloudOptions;
|
|
8
7
|
use polars::io::mmap::MmapBytesReader;
|
|
9
8
|
use polars::prelude::PlPath;
|
|
10
9
|
use polars::prelude::file::DynWriteable;
|
|
11
10
|
use polars::prelude::sync_on_close::SyncOnCloseType;
|
|
12
|
-
use polars_utils::
|
|
11
|
+
use polars_utils::create_file;
|
|
12
|
+
use polars_utils::file::{ClosableFile, WriteClose};
|
|
13
13
|
use polars_utils::mmap::MemSlice;
|
|
14
14
|
|
|
15
|
-
use crate::RbResult;
|
|
16
15
|
use crate::error::RbPolarsErr;
|
|
17
16
|
use crate::prelude::resolve_homedir;
|
|
17
|
+
use crate::utils::RubyAttach;
|
|
18
|
+
use crate::{RbErr, RbResult};
|
|
18
19
|
|
|
19
|
-
#[derive(Clone)]
|
|
20
20
|
pub struct RbFileLikeObject {
|
|
21
21
|
inner: Opaque<Value>,
|
|
22
|
+
expects_str: bool,
|
|
23
|
+
has_flush: bool,
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
impl WriteClose for RbFileLikeObject {}
|
|
27
|
+
|
|
24
28
|
impl DynWriteable for RbFileLikeObject {
|
|
25
29
|
fn as_dyn_write(&self) -> &(dyn io::Write + Send + 'static) {
|
|
26
30
|
self as _
|
|
27
31
|
}
|
|
32
|
+
|
|
28
33
|
fn as_mut_dyn_write(&mut self) -> &mut (dyn io::Write + Send + 'static) {
|
|
29
34
|
self as _
|
|
30
35
|
}
|
|
36
|
+
|
|
31
37
|
fn close(self: Box<Self>) -> io::Result<()> {
|
|
32
38
|
Ok(())
|
|
33
39
|
}
|
|
40
|
+
|
|
34
41
|
fn sync_on_close(&mut self, _sync_on_close: SyncOnCloseType) -> io::Result<()> {
|
|
35
42
|
Ok(())
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
|
|
46
|
+
impl Clone for RbFileLikeObject {
|
|
47
|
+
fn clone(&self) -> Self {
|
|
48
|
+
Ruby::attach(|_rb| Self {
|
|
49
|
+
// TODO clone
|
|
50
|
+
inner: self.inner,
|
|
51
|
+
expects_str: self.expects_str,
|
|
52
|
+
has_flush: self.has_flush,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
39
57
|
/// Wraps a `Value`, and implements read, seek, and write for it.
|
|
40
58
|
impl RbFileLikeObject {
|
|
41
59
|
/// Creates an instance of a `RbFileLikeObject` from a `Value`.
|
|
42
60
|
/// To assert the object has the required methods methods,
|
|
43
61
|
/// instantiate it with `RbFileLikeObject::require`
|
|
44
|
-
pub fn new(object: Value) -> Self {
|
|
62
|
+
pub fn new(object: Value, expects_str: bool, has_flush: bool) -> Self {
|
|
45
63
|
RbFileLikeObject {
|
|
46
64
|
inner: object.into(),
|
|
65
|
+
expects_str,
|
|
66
|
+
has_flush,
|
|
47
67
|
}
|
|
48
68
|
}
|
|
49
69
|
|
|
50
|
-
pub fn
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
.unwrap()
|
|
57
|
-
.get_inner(self.inner)
|
|
58
|
-
.funcall::<_, _, RString>("read", ())
|
|
59
|
-
.expect("no read method found");
|
|
60
|
-
|
|
61
|
-
let buf = unsafe { bytes.as_slice() }.to_vec();
|
|
70
|
+
pub(crate) fn to_memslice(&self) -> MemSlice {
|
|
71
|
+
Ruby::attach(|rb| {
|
|
72
|
+
let bytes = rb
|
|
73
|
+
.get_inner(self.inner)
|
|
74
|
+
.funcall::<_, _, RString>("read", ())
|
|
75
|
+
.expect("no read method found");
|
|
62
76
|
|
|
63
|
-
|
|
77
|
+
let b = unsafe { bytes.as_slice() }.to_vec();
|
|
78
|
+
MemSlice::from_vec(b)
|
|
79
|
+
})
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
/// Same as `RbFileLikeObject::new`, but validates that the underlying
|
|
67
83
|
/// ruby object has a `read`, `write`, and `seek` methods in respect to parameters.
|
|
68
84
|
/// Will return a `TypeError` if object does not have `read`, `seek`, and `write` methods.
|
|
69
|
-
pub fn
|
|
85
|
+
pub fn ensure_requirements(
|
|
86
|
+
object: Value,
|
|
87
|
+
read: bool,
|
|
88
|
+
write: bool,
|
|
89
|
+
seek: bool,
|
|
90
|
+
) -> RbResult<Self> {
|
|
70
91
|
let ruby = Ruby::get_with(object);
|
|
71
92
|
|
|
72
93
|
if read && !object.respond_to("read", false)? {
|
|
@@ -90,48 +111,61 @@ impl RbFileLikeObject {
|
|
|
90
111
|
));
|
|
91
112
|
}
|
|
92
113
|
|
|
93
|
-
|
|
114
|
+
// TODO fix
|
|
115
|
+
let expects_str = false;
|
|
116
|
+
let has_flush = object.respond_to("write", false)?;
|
|
117
|
+
Ok(RbFileLikeObject::new(object, expects_str, has_flush))
|
|
94
118
|
}
|
|
95
119
|
}
|
|
96
120
|
|
|
97
121
|
/// Extracts a string repr from, and returns an IO error to send back to rust.
|
|
98
|
-
fn rberr_to_io_err(e:
|
|
99
|
-
io::Error::other(e.to_string())
|
|
122
|
+
fn rberr_to_io_err(e: RbErr) -> io::Error {
|
|
123
|
+
Ruby::attach(|_rb| io::Error::other(e.to_string()))
|
|
100
124
|
}
|
|
101
125
|
|
|
102
126
|
impl Read for RbFileLikeObject {
|
|
103
127
|
fn read(&mut self, mut buf: &mut [u8]) -> Result<usize, io::Error> {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
128
|
+
Ruby::attach(|rb| {
|
|
129
|
+
let bytes = rb
|
|
130
|
+
.get_inner(self.inner)
|
|
131
|
+
.funcall::<_, _, RString>("read", (buf.len(),))
|
|
132
|
+
.map_err(rberr_to_io_err)?;
|
|
109
133
|
|
|
110
|
-
|
|
134
|
+
buf.write_all(unsafe { bytes.as_slice() })?;
|
|
111
135
|
|
|
112
|
-
|
|
136
|
+
Ok(bytes.len())
|
|
137
|
+
})
|
|
113
138
|
}
|
|
114
139
|
}
|
|
115
140
|
|
|
116
141
|
impl Write for RbFileLikeObject {
|
|
117
142
|
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
|
|
118
|
-
let
|
|
119
|
-
let rbbytes = ruby.str_from_slice(buf);
|
|
143
|
+
let expects_str = self.expects_str;
|
|
120
144
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
145
|
+
Ruby::attach(|rb| {
|
|
146
|
+
if expects_str {
|
|
147
|
+
todo!();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let rbbytes = rb.str_from_slice(buf);
|
|
151
|
+
|
|
152
|
+
let number_bytes_written = rb
|
|
153
|
+
.get_inner(self.inner)
|
|
154
|
+
.funcall::<_, _, usize>("write", (rbbytes,))
|
|
155
|
+
.map_err(rberr_to_io_err)?;
|
|
125
156
|
|
|
126
|
-
|
|
157
|
+
Ok(number_bytes_written)
|
|
158
|
+
})
|
|
127
159
|
}
|
|
128
160
|
|
|
129
161
|
fn flush(&mut self) -> Result<(), io::Error> {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
162
|
+
if self.has_flush {
|
|
163
|
+
Ruby::attach(|rb| {
|
|
164
|
+
rb.get_inner(self.inner)
|
|
165
|
+
.funcall::<_, _, Value>("flush", ())
|
|
166
|
+
.map_err(rberr_to_io_err)
|
|
167
|
+
})?;
|
|
168
|
+
}
|
|
135
169
|
|
|
136
170
|
Ok(())
|
|
137
171
|
}
|
|
@@ -139,19 +173,21 @@ impl Write for RbFileLikeObject {
|
|
|
139
173
|
|
|
140
174
|
impl Seek for RbFileLikeObject {
|
|
141
175
|
fn seek(&mut self, pos: SeekFrom) -> Result<u64, io::Error> {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
176
|
+
Ruby::attach(|rb| {
|
|
177
|
+
let (whence, offset) = match pos {
|
|
178
|
+
SeekFrom::Start(i) => (0, i as i64),
|
|
179
|
+
SeekFrom::Current(i) => (1, i),
|
|
180
|
+
SeekFrom::End(i) => (2, i),
|
|
181
|
+
};
|
|
147
182
|
|
|
148
|
-
|
|
183
|
+
let inner = rb.get_inner(self.inner);
|
|
149
184
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
185
|
+
inner
|
|
186
|
+
.funcall::<_, _, Value>("seek", (offset, whence))
|
|
187
|
+
.map_err(rberr_to_io_err)?;
|
|
153
188
|
|
|
154
|
-
|
|
189
|
+
inner.funcall("tell", ()).map_err(rberr_to_io_err)
|
|
190
|
+
})
|
|
155
191
|
}
|
|
156
192
|
}
|
|
157
193
|
|
|
@@ -174,17 +210,18 @@ impl EitherRustRubyFile {
|
|
|
174
210
|
}
|
|
175
211
|
}
|
|
176
212
|
|
|
177
|
-
|
|
213
|
+
#[allow(dead_code)]
|
|
214
|
+
fn into_scan_source_input(self) -> RubyScanSourceInput {
|
|
178
215
|
match self {
|
|
179
|
-
|
|
180
|
-
|
|
216
|
+
EitherRustRubyFile::Rb(f) => RubyScanSourceInput::Buffer(f.to_memslice()),
|
|
217
|
+
EitherRustRubyFile::Rust(f) => RubyScanSourceInput::File(f),
|
|
181
218
|
}
|
|
182
219
|
}
|
|
183
220
|
|
|
184
|
-
pub fn
|
|
221
|
+
pub(crate) fn into_writeable(self) -> Box<dyn DynWriteable> {
|
|
185
222
|
match self {
|
|
186
|
-
|
|
187
|
-
|
|
223
|
+
Self::Rb(f) => Box::new(f),
|
|
224
|
+
Self::Rust(f) => Box::new(f),
|
|
188
225
|
}
|
|
189
226
|
}
|
|
190
227
|
}
|
|
@@ -193,52 +230,61 @@ pub enum RubyScanSourceInput {
|
|
|
193
230
|
Buffer(MemSlice),
|
|
194
231
|
Path(PlPath),
|
|
195
232
|
#[allow(dead_code)]
|
|
196
|
-
File(
|
|
233
|
+
File(ClosableFile),
|
|
197
234
|
}
|
|
198
235
|
|
|
199
236
|
pub(crate) fn try_get_rbfile(
|
|
237
|
+
_rb: &Ruby,
|
|
200
238
|
rb_f: Value,
|
|
201
239
|
write: bool,
|
|
202
240
|
) -> RbResult<(EitherRustRubyFile, Option<PathBuf>)> {
|
|
203
|
-
let f = RbFileLikeObject::
|
|
241
|
+
let f = RbFileLikeObject::ensure_requirements(rb_f, !write, write, !write)?;
|
|
204
242
|
Ok((EitherRustRubyFile::Rb(f), None))
|
|
205
243
|
}
|
|
206
244
|
|
|
207
245
|
pub fn get_ruby_scan_source_input(rb_f: Value, write: bool) -> RbResult<RubyScanSourceInput> {
|
|
208
|
-
|
|
209
|
-
let
|
|
210
|
-
|
|
211
|
-
if p.
|
|
246
|
+
Ruby::attach(|_rb| {
|
|
247
|
+
if let Ok(s) = String::try_convert(rb_f) {
|
|
248
|
+
let mut file_path = PlPath::new(&s);
|
|
249
|
+
if let Some(p) = file_path.as_ref().as_local_path()
|
|
250
|
+
&& p.starts_with("~/")
|
|
251
|
+
{
|
|
212
252
|
file_path = PlPath::Local(resolve_homedir(&p).into());
|
|
213
253
|
}
|
|
254
|
+
Ok(RubyScanSourceInput::Path(file_path))
|
|
255
|
+
} else {
|
|
256
|
+
let f = RbFileLikeObject::ensure_requirements(rb_f, !write, write, !write)?;
|
|
257
|
+
Ok(RubyScanSourceInput::Buffer(f.to_memslice()))
|
|
214
258
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
pub fn get_either_buffer_or_path(
|
|
263
|
+
rb_f: Value,
|
|
264
|
+
write: bool,
|
|
265
|
+
) -> RbResult<(EitherRustRubyFile, Option<PathBuf>)> {
|
|
266
|
+
Ruby::attach(|rb| {
|
|
267
|
+
if let Ok(rstring) = RString::try_convert(rb_f) {
|
|
268
|
+
let s = unsafe { rstring.as_str() }?;
|
|
269
|
+
let file_path = std::path::Path::new(&s);
|
|
270
|
+
let file_path = resolve_homedir(&file_path);
|
|
271
|
+
let f = if write {
|
|
272
|
+
create_file(&file_path).map_err(RbPolarsErr::from)?
|
|
273
|
+
} else {
|
|
274
|
+
polars_utils::open_file(&file_path).map_err(RbPolarsErr::from)?
|
|
275
|
+
};
|
|
276
|
+
Ok((EitherRustRubyFile::Rust(f.into()), Some(file_path)))
|
|
277
|
+
} else {
|
|
278
|
+
try_get_rbfile(rb, rb_f, write)
|
|
279
|
+
}
|
|
280
|
+
})
|
|
222
281
|
}
|
|
223
282
|
|
|
224
283
|
///
|
|
225
284
|
/// # Arguments
|
|
226
|
-
/// * `
|
|
227
|
-
pub fn get_either_file(rb_f: Value,
|
|
228
|
-
|
|
229
|
-
let s = unsafe { rstring.as_str() }?;
|
|
230
|
-
let file_path = std::path::Path::new(&s);
|
|
231
|
-
let file_path = resolve_homedir(&file_path);
|
|
232
|
-
let f = if truncate {
|
|
233
|
-
File::create(file_path).map_err(RbPolarsErr::from)?
|
|
234
|
-
} else {
|
|
235
|
-
polars_utils::open_file(&file_path).map_err(RbPolarsErr::from)?
|
|
236
|
-
};
|
|
237
|
-
Ok(EitherRustRubyFile::Rust(f.into()))
|
|
238
|
-
} else {
|
|
239
|
-
let f = RbFileLikeObject::with_requirements(rb_f, !truncate, truncate, !truncate)?;
|
|
240
|
-
Ok(EitherRustRubyFile::Rb(f))
|
|
241
|
-
}
|
|
285
|
+
/// * `write` - open for writing; will truncate existing file and create new file if not.
|
|
286
|
+
pub fn get_either_file(rb_f: Value, write: bool) -> RbResult<EitherRustRubyFile> {
|
|
287
|
+
Ok(get_either_buffer_or_path(rb_f, write)?.0)
|
|
242
288
|
}
|
|
243
289
|
|
|
244
290
|
pub fn get_file_like(f: Value, truncate: bool) -> RbResult<Box<dyn FileLike>> {
|
|
@@ -265,22 +311,9 @@ pub fn get_mmap_bytes_reader_and_path<'a>(
|
|
|
265
311
|
) -> RbResult<(Box<dyn MmapBytesReader + 'a>, Option<PathBuf>)> {
|
|
266
312
|
match rb_f {
|
|
267
313
|
RbReadBytes::Bytes(v) => Ok((Box::new(Cursor::new(unsafe { v.as_slice() })), None)),
|
|
268
|
-
RbReadBytes::Other(v) => {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
Ruby::get().unwrap().exception_runtime_error(),
|
|
273
|
-
e.to_string(),
|
|
274
|
-
)
|
|
275
|
-
})?;
|
|
276
|
-
Ok((Box::new(f), Some(path)))
|
|
277
|
-
}
|
|
314
|
+
RbReadBytes::Other(v) => match get_either_buffer_or_path(*v, false)? {
|
|
315
|
+
(EitherRustRubyFile::Rust(f), path) => Ok((Box::new(f), path)),
|
|
316
|
+
(EitherRustRubyFile::Rb(f), path) => Ok((Box::new(Cursor::new(f.to_memslice())), path)),
|
|
317
|
+
},
|
|
278
318
|
}
|
|
279
319
|
}
|
|
280
|
-
|
|
281
|
-
pub fn try_get_writeable(
|
|
282
|
-
rb_f: Value,
|
|
283
|
-
_cloud_options: Option<&CloudOptions>,
|
|
284
|
-
) -> RbResult<Box<dyn Write>> {
|
|
285
|
-
Ok(get_either_file(rb_f, true)?.into_dyn_writeable())
|
|
286
|
-
}
|
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
use magnus::RArray;
|
|
2
2
|
use polars::lazy::dsl;
|
|
3
3
|
|
|
4
|
-
use crate::
|
|
5
|
-
use crate::
|
|
4
|
+
use crate::error::RbPolarsErr;
|
|
5
|
+
use crate::expr::ToExprs;
|
|
6
|
+
use crate::{RbExpr, RbResult};
|
|
6
7
|
|
|
7
8
|
pub fn all_horizontal(exprs: RArray) -> RbResult<RbExpr> {
|
|
8
|
-
let exprs =
|
|
9
|
+
let exprs = exprs.to_exprs()?;
|
|
9
10
|
let e = dsl::all_horizontal(exprs).map_err(RbPolarsErr::from)?;
|
|
10
11
|
Ok(e.into())
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
pub fn any_horizontal(exprs: RArray) -> RbResult<RbExpr> {
|
|
14
|
-
let exprs =
|
|
15
|
+
let exprs = exprs.to_exprs()?;
|
|
15
16
|
let e = dsl::any_horizontal(exprs).map_err(RbPolarsErr::from)?;
|
|
16
17
|
Ok(e.into())
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
pub fn max_horizontal(exprs: RArray) -> RbResult<RbExpr> {
|
|
20
|
-
let exprs =
|
|
21
|
+
let exprs = exprs.to_exprs()?;
|
|
21
22
|
let e = dsl::max_horizontal(exprs).map_err(RbPolarsErr::from)?;
|
|
22
23
|
Ok(e.into())
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
pub fn min_horizontal(exprs: RArray) -> RbResult<RbExpr> {
|
|
26
|
-
let exprs =
|
|
27
|
+
let exprs = exprs.to_exprs()?;
|
|
27
28
|
let e = dsl::min_horizontal(exprs).map_err(RbPolarsErr::from)?;
|
|
28
29
|
Ok(e.into())
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
pub fn sum_horizontal(exprs: RArray, ignore_nulls: bool) -> RbResult<RbExpr> {
|
|
32
|
-
let exprs =
|
|
33
|
+
let exprs = exprs.to_exprs()?;
|
|
33
34
|
let e = dsl::sum_horizontal(exprs, ignore_nulls).map_err(RbPolarsErr::from)?;
|
|
34
35
|
Ok(e.into())
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
pub fn mean_horizontal(exprs: RArray, ignore_nulls: bool) -> RbResult<RbExpr> {
|
|
38
|
-
let exprs =
|
|
39
|
+
let exprs = exprs.to_exprs()?;
|
|
39
40
|
let e = dsl::mean_horizontal(exprs, ignore_nulls).map_err(RbPolarsErr::from)?;
|
|
40
41
|
Ok(e.into())
|
|
41
42
|
}
|