From ed0f313e340f8bf791ad40a40c977c0e5134cd3b Mon Sep 17 00:00:00 2001 From: Ritchie Vink Date: Thu, 1 Aug 2024 11:29:39 +0200 Subject: [PATCH] fix(python): Respect `strict` argument (#17990) --- py-polars/src/conversion/any_value.rs | 15 +- .../tests/unit/constructors/test_structs.py | 149 ++++++++++++++++++ 2 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 py-polars/tests/unit/constructors/test_structs.py diff --git a/py-polars/src/conversion/any_value.rs b/py-polars/src/conversion/any_value.rs index 4201a3855f39..e7096010a069 100644 --- a/py-polars/src/conversion/any_value.rs +++ b/py-polars/src/conversion/any_value.rs @@ -274,13 +274,18 @@ pub(crate) fn py_object_to_any_value<'py>( } fn get_list(ob: &Bound<'_, PyAny>, strict: bool) -> PyResult> { - fn get_list_with_constructor(ob: &Bound<'_, PyAny>) -> PyResult> { + fn get_list_with_constructor( + ob: &Bound<'_, PyAny>, + strict: bool, + ) -> PyResult> { // Use the dedicated constructor. // This constructor is able to go via dedicated type constructors // so it can be much faster. let py = ob.py(); - let s = SERIES.call1(py, (ob,))?; - get_list_from_series(s.bind(py), true) + let kwargs = PyDict::new_bound(py); + kwargs.set_item("strict", strict)?; + let s = SERIES.call_bound(py, (ob,), Some(&kwargs))?; + get_list_from_series(s.bind(py), strict) } if ob.is_empty()? { @@ -303,7 +308,7 @@ pub(crate) fn py_object_to_any_value<'py>( // This path is only taken if there is no question about the data type. if dtype.is_primitive() && n_dtypes == 1 { - get_list_with_constructor(ob) + get_list_with_constructor(ob, strict) } else { // Push the rest. let length = list.len()?; @@ -325,7 +330,7 @@ pub(crate) fn py_object_to_any_value<'py>( } } else { // range will take this branch - get_list_with_constructor(ob) + get_list_with_constructor(ob, strict) } } diff --git a/py-polars/tests/unit/constructors/test_structs.py b/py-polars/tests/unit/constructors/test_structs.py new file mode 100644 index 000000000000..bd4f2f725ce6 --- /dev/null +++ b/py-polars/tests/unit/constructors/test_structs.py @@ -0,0 +1,149 @@ +import polars as pl + + +def test_constructor_non_strict_schema_17956() -> None: + schema = { + "logged_event": pl.Struct( + [ + pl.Field( + "completetask", + pl.Struct( + [ + pl.Field( + "parameters", + pl.List( + pl.Struct( + [ + pl.Field( + "numericarray", + pl.Struct( + [ + pl.Field( + "value", pl.List(pl.Float64) + ), + ] + ), + ), + ] + ) + ), + ), + ] + ), + ), + ] + ), + } + + data = { + "logged_event": { + "completetask": { + "parameters": [ + { + "numericarray": { + "value": [ + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 431, + 430.5, + 431, + 431, + 431, + ] + } + } + ] + } + } + } + + lazyframe = pl.LazyFrame( + [data], + schema=schema, + strict=False, + ) + assert lazyframe.collect().to_dict(as_series=False) == { + "logged_event": [ + { + "completetask": { + "parameters": [ + { + "numericarray": { + "value": [ + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 431.0, + 430.5, + 431.0, + 431.0, + 431.0, + ] + } + } + ] + } + } + ] + }