Skip to content

Commit 9a54b50

Browse files
committed
Fixed Object type for DataFrame, take 2
1 parent 998d968 commit 9a54b50

File tree

4 files changed

+63
-15
lines changed

4 files changed

+63
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- Added `storage_options` and `retries` options to `sink_ipc` method
55
- Added experimental support for Iceberg
66
- Added experimental `cast_options` option to `scan_parquet` method
7-
- Fixed `Object` type for `Series`
7+
- Fixed `Object` type
88

99
## 0.21.1 (2025-08-18)
1010

ext/polars/src/dataframe/mod.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ mod general;
44
mod io;
55
mod serde;
66

7+
use magnus::{DataTypeFunctions, TypedData, gc};
78
use polars::prelude::*;
89
use std::cell::RefCell;
910

10-
#[magnus::wrap(class = "Polars::RbDataFrame")]
11+
use crate::series::mark_series;
12+
13+
#[derive(TypedData)]
14+
#[magnus(class = "Polars::RbDataFrame", mark)]
1115
pub struct RbDataFrame {
1216
pub df: RefCell<DataFrame>,
1317
}
@@ -25,3 +29,23 @@ impl RbDataFrame {
2529
}
2630
}
2731
}
32+
33+
impl DataTypeFunctions for RbDataFrame {
34+
fn mark(&self, marker: &gc::Marker) {
35+
// this is really, really not ideal, as objects will not be marked if unable to borrow
36+
// currently, this should only happen for write_* methods,
37+
// which should refuse to write Object datatype, and therefore be safe,
38+
// since GC will not have a chance to run
39+
if let Ok(df) = self.df.try_borrow() {
40+
for column in df.get_columns() {
41+
if let DataType::Object(_) = column.dtype() {
42+
match column {
43+
Column::Series(s) => mark_series(marker, s),
44+
Column::Partitioned(s) => mark_series(marker, s.partitions()),
45+
Column::Scalar(s) => mark_series(marker, &s.as_single_value_series()),
46+
}
47+
}
48+
}
49+
}
50+
}
51+
}

ext/polars/src/series/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,19 @@ pub fn to_rbseries(s: Vec<Column>) -> RArray {
5050
)
5151
}
5252

53-
impl DataTypeFunctions for RbSeries {
54-
fn mark(&self, marker: &gc::Marker) {
55-
let series = self.series.borrow();
56-
if let DataType::Object(_) = series.dtype() {
57-
for i in 0..series.len() {
58-
let obj: Option<&ObjectValue> = series.get_object(i).map(|any| any.into());
59-
if let Some(o) = obj {
60-
marker.mark(o.inner);
61-
}
53+
pub fn mark_series(marker: &gc::Marker, series: &Series) {
54+
if let DataType::Object(_) = series.dtype() {
55+
for i in 0..series.len() {
56+
let obj: Option<&ObjectValue> = series.get_object(i).map(|any| any.into());
57+
if let Some(o) = obj {
58+
marker.mark(o.inner);
6259
}
6360
}
6461
}
6562
}
63+
64+
impl DataTypeFunctions for RbSeries {
65+
fn mark(&self, marker: &gc::Marker) {
66+
mark_series(marker, &self.series.borrow());
67+
}
68+
}

test/types_test.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,35 @@ def test_object
193193

194194
df = Polars::DataFrame.new({a: [Object.new]})
195195
GC.start
196-
# TODO fix
197-
# assert df.inspect
196+
assert df.inspect
198197
assert df.to_a
199198

200199
df = Polars::DataFrame.new({a: [Object.new, Object.new]})
201200
GC.start
202-
# TODO fix
203-
# assert df.inspect
201+
assert df.inspect
202+
assert df.to_a
203+
end
204+
205+
# only fully tested in stress mode
206+
def test_object_stress
207+
df = Polars::DataFrame.new({a: [Object.new]})
208+
io = StringIO.new
209+
assert_raises(Polars::ComputeError) do
210+
df.write_csv(io)
211+
end
212+
assert_raises(Polars::ComputeError) do
213+
df.write_parquet(io)
214+
end
215+
assert_raises(Polars::ComputeError) do
216+
df.write_json(io)
217+
end
218+
assert_raises(Polars::ComputeError) do
219+
df.write_ndjson(io)
220+
end
221+
assert_raises(Polars::ComputeError) do
222+
df.write_ipc(io)
223+
end
224+
assert df.inspect
204225
assert df.to_a
205226
end
206227

0 commit comments

Comments
 (0)