diff --git a/crates/polars-core/src/chunked_array/ops/any_value.rs b/crates/polars-core/src/chunked_array/ops/any_value.rs index f08b1b3e530d..7b01f66c8015 100644 --- a/crates/polars-core/src/chunked_array/ops/any_value.rs +++ b/crates/polars-core/src/chunked_array/ops/any_value.rs @@ -4,6 +4,7 @@ use polars_utils::sync::SyncPtr; #[cfg(feature = "object")] use crate::chunked_array::object::extension::polars_extension::PolarsExtension; use crate::prelude::*; +use crate::series::implementations::null::NullChunked; #[inline] #[allow(unused_variables)] @@ -282,3 +283,14 @@ impl ChunkAnyValue for ObjectChunked { } } } + +impl ChunkAnyValue for NullChunked { + #[inline] + unsafe fn get_any_value_unchecked(&self, _index: usize) -> AnyValue { + AnyValue::Null + } + + fn get_any_value(&self, _index: usize) -> PolarsResult { + Ok(AnyValue::Null) + } +} diff --git a/crates/polars-core/src/fmt.rs b/crates/polars-core/src/fmt.rs index 97fed1703701..59c69f8cdc95 100644 --- a/crates/polars-core/src/fmt.rs +++ b/crates/polars-core/src/fmt.rs @@ -149,52 +149,6 @@ fn format_object_array( } } -macro_rules! format_nullarray { - ($f:ident, $length:expr, $dtype:expr, $name:expr, $array_type:expr) => {{ - write!( - $f, - "shape: ({},)\n{}: '{}' [{}]\n[\n", - fmt_uint(&$length), - $array_type, - $name, - $dtype - )?; - let limit: usize = { - let limit = std::env::var(FMT_MAX_ROWS) - .as_deref() - .unwrap_or("") - .parse() - .map_or(LIMIT, |n: i64| if n < 0 { $length } else { n as usize }); - std::cmp::min(limit, $length.clone()) - }; - let write_fn = |v, f: &mut Formatter| -> fmt::Result { - write!(f, "\t{}\n", v)?; - - Ok(()) - }; - let v = "null"; - if (limit == 0 && $length > 0) || ($length > limit + 1) { - if limit > 0 { - for _i in 0..std::cmp::max((limit / 2), 1) { - write_fn(v, $f)?; - } - } - write!($f, "\t…\n")?; - if limit > 1 { - for _i in ($length - (limit + 1) / 2)..$length { - write_fn(v, $f)?; - } - } - } else { - for _i in 0..$length { - write_fn(v, $f)?; - } - } - - write!($f, "]") - }}; -} - impl Debug for ChunkedArray where T: PolarsNumericType, @@ -359,7 +313,7 @@ impl Debug for Series { "Series" ), DataType::Null => { - format_nullarray!(f, self.len(), "nullarray", self.name(), "Series") + format_array!(f, self.null().unwrap(), "null", self.name(), "Series") }, DataType::Binary => { format_array!(f, self.binary().unwrap(), "binary", self.name(), "Series") diff --git a/crates/polars-core/src/series/ops/downcast.rs b/crates/polars-core/src/series/ops/downcast.rs index adbae1532f5d..e632ecf78ea8 100644 --- a/crates/polars-core/src/series/ops/downcast.rs +++ b/crates/polars-core/src/series/ops/downcast.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use crate::series::implementations::null::NullChunked; macro_rules! unpack_chunked { ($series:expr, $expected:pat => $ca:ty, $name:expr) => { @@ -152,4 +153,9 @@ impl Series { } unpack_chunked!(self, DataType::Struct(_) => StructChunked, "Struct") } + + /// Unpack to [`ChunkedArray`] of dtype `[DataType::Null]` + pub fn null(&self) -> PolarsResult<&NullChunked> { + unpack_chunked!(self, DataType::Null => NullChunked, "Null") + } } diff --git a/py-polars/tests/unit/test_constructors.py b/py-polars/tests/unit/test_constructors.py index aa3ae6d0ebc7..12765aab0bb5 100644 --- a/py-polars/tests/unit/test_constructors.py +++ b/py-polars/tests/unit/test_constructors.py @@ -607,14 +607,24 @@ def test_init_ndarray(monkeypatch: Any) -> None: assert df2.rows() == [(1.0, 4.0), (2.5, None), (None, 6.5)] -def test_nullarray_print_format() -> None: +def test_null_array_print_format() -> None: pa_tbl_null = pa.table({"a": [None, None]}) df_null = pl.from_arrow(pa_tbl_null) - assert df_null.schema == {"a": pl.Null} - assert df_null.rows() == [(None,), (None,)] + assert df_null.shape == (2, 1) + assert df_null.dtypes == pl.Null # type: ignore[union-attr] + assert df_null.rows() == [(None,), (None,)] # type: ignore[union-attr] - expected_string = "shape: (2,)\nSeries: 'a' [nullarray]\n[\n\tnull\n\tnull\n]" - assert str(df_null["a"]) == expected_string + assert ( + str(df_null) == "shape: (2, 1)\n" + "┌──────┐\n" + "│ a │\n" + "│ --- │\n" + "│ null │\n" + "╞══════╡\n" + "│ null │\n" + "│ null │\n" + "└──────┘" + ) def test_init_arrow() -> None: