diff --git a/crates/polars-plan/src/dsl/python_udf.rs b/crates/polars-plan/src/dsl/python_udf.rs index efefa5e228af..d30bbc5e29a6 100644 --- a/crates/polars-plan/src/dsl/python_udf.rs +++ b/crates/polars-plan/src/dsl/python_udf.rs @@ -6,6 +6,7 @@ use polars_core::error::*; use polars_core::frame::DataFrame; use polars_core::prelude::Series; use pyo3::prelude::*; +use pyo3::pybacked::PyBackedBytes; use pyo3::types::PyBytes; #[cfg(feature = "serde")] use serde::ser::Error; @@ -67,9 +68,9 @@ impl Serialize for PythonFunction { let dumped = pickle .call1((python_function,)) .map_err(|s| S::Error::custom(format!("cannot pickle {s}")))?; - let dumped = dumped.extract::<&PyBytes>().unwrap(); + let dumped = dumped.extract::().unwrap(); - serializer.serialize_bytes(dumped.as_bytes()) + serializer.serialize_bytes(&dumped) }) } } @@ -192,8 +193,8 @@ impl SeriesUdf for PythonUdfExpression { let dumped = pickle .call1((self.python_function.clone(),)) .map_err(from_pyerr)?; - let dumped = dumped.extract::<&PyBytes>().unwrap(); - buf.extend_from_slice(dumped.as_bytes()); + let dumped = dumped.extract::().unwrap(); + buf.extend_from_slice(&dumped); Ok(()) }) } diff --git a/py-polars/Cargo.toml b/py-polars/Cargo.toml index cb530b2d1445..200ccb34d6cd 100644 --- a/py-polars/Cargo.toml +++ b/py-polars/Cargo.toml @@ -27,7 +27,7 @@ ndarray = { workspace = true } num-traits = { workspace = true } numpy = { version = "0.21", default-features = false } once_cell = { workspace = true } -pyo3 = { workspace = true, features = ["abi3-py38", "extension-module", "multiple-pymethods", "gil-refs"] } +pyo3 = { workspace = true, features = ["abi3-py38", "extension-module", "multiple-pymethods"] } pyo3-built = { version = "0.5", optional = true } recursive = { workspace = true } serde_json = { workspace = true, optional = true } diff --git a/py-polars/src/conversion/any_value.rs b/py-polars/src/conversion/any_value.rs index 84da08f4d23f..7f42a69816a7 100644 --- a/py-polars/src/conversion/any_value.rs +++ b/py-polars/src/conversion/any_value.rs @@ -171,8 +171,8 @@ pub(crate) fn py_object_to_any_value<'py>( } fn get_bytes<'py>(ob: &Bound<'py, PyAny>, _strict: bool) -> PyResult> { - let value = ob.extract::<&'py [u8]>().unwrap(); - Ok(AnyValue::Binary(value)) + let value = ob.extract::>().unwrap(); + Ok(AnyValue::BinaryOwned(value)) } fn get_date(ob: &Bound<'_, PyAny>, _strict: bool) -> PyResult> { diff --git a/py-polars/src/conversion/mod.rs b/py-polars/src/conversion/mod.rs index cb6ed01d9463..b664392aab0f 100644 --- a/py-polars/src/conversion/mod.rs +++ b/py-polars/src/conversion/mod.rs @@ -275,27 +275,33 @@ impl ToPyObject for Wrap { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let py = ob.py(); - let name = ob.getattr(intern!(py, "name"))?.str()?.to_str()?; + let name = ob + .getattr(intern!(py, "name"))? + .str()? + .extract::()?; let dtype = ob .getattr(intern!(py, "dtype"))? .extract::>()?; - Ok(Wrap(Field::new(name, dtype.0))) + Ok(Wrap(Field::new(&name, dtype.0))) } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let py = ob.py(); let type_name = ob.get_type().qualname()?; let dtype = match &*type_name { "DataTypeClass" => { // just the class, not an object - let name = ob.getattr(intern!(py, "__name__"))?.str()?.to_str()?; - match name { + let name = ob + .getattr(intern!(py, "__name__"))? + .str()? + .extract::()?; + match &*name { "UInt8" => DataType::UInt8, "UInt16" => DataType::UInt16, "UInt32" => DataType::UInt32, @@ -429,16 +435,16 @@ impl ToPyObject for Wrap { } impl<'s> FromPyObject<'s> for Wrap> { - fn extract(ob: &'s PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'s, PyAny>) -> PyResult { let vals = ob.extract::>>>()?; let vals = vec_extract_wrapped(vals); Ok(Wrap(Row(vals))) } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { - let dict = ob.extract::<&PyDict>()?; +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + let dict = ob.downcast::()?; Ok(Wrap( dict.iter() @@ -528,7 +534,7 @@ impl From for ObjectValue { } impl<'a> FromPyObject<'a> for ObjectValue { - fn extract(ob: &'a PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult { Python::with_gil(|py| { Ok(ObjectValue { inner: ob.to_object(py), @@ -560,7 +566,7 @@ impl Default for ObjectValue { } impl<'a, T: NativeType + FromPyObject<'a>> FromPyObject<'a> for Wrap> { - fn extract(obj: &'a PyAny) -> PyResult { + fn extract_bound(obj: &Bound<'a, PyAny>) -> PyResult { let seq = obj.downcast::()?; let mut v = Vec::with_capacity(seq.len().unwrap_or(0)); for item in seq.iter()? { @@ -571,8 +577,8 @@ impl<'a, T: NativeType + FromPyObject<'a>> FromPyObject<'a> for Wrap> { } #[cfg(feature = "asof_join")] -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*(ob.extract::()?) { "backward" => AsofStrategy::Backward, "forward" => AsofStrategy::Forward, @@ -587,8 +593,8 @@ impl FromPyObject<'_> for Wrap { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*(ob.extract::()?) { "linear" => InterpolationMethod::Linear, "nearest" => InterpolationMethod::Nearest, @@ -603,8 +609,8 @@ impl FromPyObject<'_> for Wrap { } #[cfg(feature = "avro")] -impl FromPyObject<'_> for Wrap> { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap> { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "uncompressed" => None, "snappy" => Some(AvroCompression::Snappy), @@ -619,8 +625,8 @@ impl FromPyObject<'_> for Wrap> { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "physical" => CategoricalOrdering::Physical, "lexical" => CategoricalOrdering::Lexical, @@ -634,8 +640,8 @@ impl FromPyObject<'_> for Wrap { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "window" => StartBy::WindowBound, "datapoint" => StartBy::DataPoint, @@ -656,8 +662,8 @@ impl FromPyObject<'_> for Wrap { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "left" => ClosedWindow::Left, "right" => ClosedWindow::Right, @@ -674,8 +680,8 @@ impl FromPyObject<'_> for Wrap { } #[cfg(feature = "csv")] -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "utf8" => CsvEncoding::Utf8, "utf8-lossy" => CsvEncoding::LossyUtf8, @@ -690,8 +696,8 @@ impl FromPyObject<'_> for Wrap { } #[cfg(feature = "ipc")] -impl FromPyObject<'_> for Wrap> { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap> { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "uncompressed" => None, "lz4" => Some(IpcCompression::LZ4), @@ -706,8 +712,8 @@ impl FromPyObject<'_> for Wrap> { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let parsed = match &*ob.extract::()? { "inner" => JoinType::Inner, "left" => JoinType::Left, @@ -730,8 +736,8 @@ impl FromPyObject<'_> for Wrap { } } -impl FromPyObject<'_> for Wrap