diff --git a/README.md b/README.md index 94b7fa49f70..e9562bf7e12 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ fn main() -> PyResult<()> { let sys = py.import("sys")?; let version: String = sys.getattr("version")?.extract()?; - let locals = [("os", py.import("os")?)].into_py_dict(py); + let locals = [("os", py.import("os")?)].into_py_dict(py)?; let code = c_str!("os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"); let user: String = py.eval(code, None, Some(&locals))?.extract()?; diff --git a/guide/src/exception.md b/guide/src/exception.md index 4a1f1425d72..fd427a34fb2 100644 --- a/guide/src/exception.md +++ b/guide/src/exception.md @@ -23,15 +23,18 @@ use pyo3::exceptions::PyException; create_exception!(mymodule, CustomError, PyException); +# fn main() -> PyResult<()> { Python::with_gil(|py| { - let ctx = [("CustomError", py.get_type::())].into_py_dict(py); + let ctx = [("CustomError", py.get_type::())].into_py_dict(py)?; pyo3::py_run!( py, *ctx, "assert str(CustomError) == \"\"" ); pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)"); -}); +# Ok(()) +}) +# } ``` When using PyO3 to create an extension module, you can add the new exception to diff --git a/guide/src/migration.md b/guide/src/migration.md index fb212743702..75b102d1c40 100644 --- a/guide/src/migration.md +++ b/guide/src/migration.md @@ -45,23 +45,26 @@ let tup = PyTuple::new(py, [1, 2, 3]);
Click to expand -The `IntoPyDict::into_py_dict_bound` method has been renamed to `IntoPyDict::into_py_dict`. If you implemented `IntoPyDict` for your type, you should implement `into_py_dict` instead of `into_py_dict_bound`. The old name is still available but deprecated. +The `IntoPyDict::into_py_dict_bound` method has been renamed to `IntoPyDict::into_py_dict` and is now fallible. If you implemented `IntoPyDict` for your type, you should implement `into_py_dict` instead of `into_py_dict_bound`. The old name is still available but deprecated. Before: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyDict, IntoPyDict}; -# use pyo3::types::dict::PyDictItem; -impl IntoPyDict for I +# use std::collections::HashMap; + +struct MyMap(HashMap); + +impl IntoPyDict for MyMap where - T: PyDictItem, - I: IntoIterator, + K: ToPyObject, + V: ToPyObject, { fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { - let dict = PyDict::new(py); - for item in self { - dict.set_item(item.key(), item.value()) + let dict = PyDict::new_bound(py); + for (key, value) in self.0 { + dict.set_item(key, value) .expect("Failed to set_item on dict"); } dict @@ -71,22 +74,25 @@ where After: -```rust,ignore +```rust # use pyo3::prelude::*; # use pyo3::types::{PyDict, IntoPyDict}; -# use pyo3::types::dict::PyDictItem; -impl IntoPyDict for I +# use std::collections::HashMap; + +# #[allow(dead_code)] +# struct MyMap(HashMap); + +impl<'py, K, V> IntoPyDict<'py> for MyMap where - T: PyDictItem, - I: IntoIterator, + K: IntoPyObject<'py>, + V: IntoPyObject<'py>, { - fn into_py_dict(self, py: Python<'_>) -> Bound<'_, PyDict> { + fn into_py_dict(self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); - for item in self { - dict.set_item(item.key(), item.value()) - .expect("Failed to set_item on dict"); + for (key, value) in self.0 { + dict.set_item(key, value)?; } - dict + Ok(dict) } } ``` diff --git a/guide/src/module.md b/guide/src/module.md index 1b2aa49d8c9..1e274c7c953 100644 --- a/guide/src/module.md +++ b/guide/src/module.md @@ -90,7 +90,7 @@ fn func() -> String { # use pyo3::types::IntoPyDict; # use pyo3::ffi::c_str; # let parent_module = wrap_pymodule!(parent_module)(py); -# let ctx = [("parent_module", parent_module)].into_py_dict(py); +# let ctx = [("parent_module", parent_module)].into_py_dict(py).unwrap(); # # py.run(c_str!("assert parent_module.child_module.func() == 'func'"), None, Some(&ctx)).unwrap(); # }) diff --git a/guide/src/python-from-rust/calling-existing-code.md b/guide/src/python-from-rust/calling-existing-code.md index 812fb20e7ae..4eba33f11c3 100644 --- a/guide/src/python-from-rust/calling-existing-code.md +++ b/guide/src/python-from-rust/calling-existing-code.md @@ -131,7 +131,7 @@ def leaky_relu(x, slope=0.01): let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?; assert_eq!(relu_result, 0.0); - let kwargs = [("slope", 0.2)].into_py_dict(py); + let kwargs = [("slope", 0.2)].into_py_dict(py)?; let lrelu_result: f64 = activators .getattr("leaky_relu")? .call((-1.0,), Some(&kwargs))? diff --git a/guide/src/python-from-rust/function-calls.md b/guide/src/python-from-rust/function-calls.md index f1eb8025431..2e5cf3c589e 100644 --- a/guide/src/python-from-rust/function-calls.md +++ b/guide/src/python-from-rust/function-calls.md @@ -90,17 +90,17 @@ fn main() -> PyResult<()> { .into(); // call object with PyDict - let kwargs = [(key1, val1)].into_py_dict(py); + let kwargs = [(key1, val1)].into_py_dict(py)?; fun.call(py, (), Some(&kwargs))?; // pass arguments as Vec let kwargs = vec![(key1, val1), (key2, val2)]; - fun.call(py, (), Some(&kwargs.into_py_dict(py)))?; + fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?; // pass arguments as HashMap let mut kwargs = HashMap::<&str, i32>::new(); kwargs.insert(key1, 1); - fun.call(py, (), Some(&kwargs.into_py_dict(py)))?; + fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?; Ok(()) }) diff --git a/newsfragments/4493.changed.md b/newsfragments/4493.changed.md new file mode 100644 index 00000000000..efff3b6fa6e --- /dev/null +++ b/newsfragments/4493.changed.md @@ -0,0 +1 @@ +`IntoPyDict::into_py_dict` is now fallible due to `IntoPyObject` migration. \ No newline at end of file diff --git a/src/conversions/anyhow.rs b/src/conversions/anyhow.rs index 9e27985c152..d2cb3f3eb60 100644 --- a/src/conversions/anyhow.rs +++ b/src/conversions/anyhow.rs @@ -145,7 +145,7 @@ mod test_anyhow { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); + let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); @@ -164,7 +164,7 @@ mod test_anyhow { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); + let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); diff --git a/src/conversions/chrono.rs b/src/conversions/chrono.rs index ddd4e39d9e3..7f36961b9ea 100644 --- a/src/conversions/chrono.rs +++ b/src/conversions/chrono.rs @@ -1365,7 +1365,7 @@ mod tests { fn test_pyo3_offset_fixed_frompyobject_created_in_python(timestamp in 0..(i32::MAX as i64), timedelta in -86399i32..=86399i32) { Python::with_gil(|py| { - let globals = [("datetime", py.import("datetime").unwrap())].into_py_dict(py); + let globals = [("datetime", py.import("datetime").unwrap())].into_py_dict(py).unwrap(); let code = format!("datetime.datetime.fromtimestamp({}).replace(tzinfo=datetime.timezone(datetime.timedelta(seconds={})))", timestamp, timedelta); let t = py.eval(&CString::new(code).unwrap(), Some(&globals), None).unwrap(); diff --git a/src/conversions/eyre.rs b/src/conversions/eyre.rs index 5bfaddcbdc6..42d7a12c872 100644 --- a/src/conversions/eyre.rs +++ b/src/conversions/eyre.rs @@ -151,7 +151,7 @@ mod tests { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); + let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); @@ -170,7 +170,7 @@ mod tests { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); + let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); diff --git a/src/conversions/hashbrown.rs b/src/conversions/hashbrown.rs index a3fd61a6412..db42075adeb 100644 --- a/src/conversions/hashbrown.rs +++ b/src/conversions/hashbrown.rs @@ -23,9 +23,9 @@ use crate::{ dict::PyDictMethods, frozenset::PyFrozenSetMethods, set::{new_from_iter, try_new_from_iter, PySetMethods}, - IntoPyDict, PyDict, PyFrozenSet, PySet, + PyDict, PyFrozenSet, PySet, }, - Bound, BoundObject, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, + Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use std::{cmp, hash}; @@ -36,7 +36,11 @@ where H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.to_object(py), v.to_object(py)).unwrap(); + } + dict.into_any().unbind() } } @@ -47,10 +51,11 @@ where H: hash::BuildHasher, { fn into_py(self, py: Python<'_>) -> PyObject { - let iter = self - .into_iter() - .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.into_py(py), v.into_py(py)).unwrap(); + } + dict.into_any().unbind() } } @@ -67,10 +72,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -89,10 +91,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -187,6 +186,7 @@ where #[cfg(test)] mod tests { use super::*; + use crate::types::IntoPyDict; #[test] fn test_hashbrown_hashmap_to_python() { @@ -238,7 +238,7 @@ mod tests { let mut map = hashbrown::HashMap::::new(); map.insert(1, 1); - let py_map = map.into_py_dict(py); + let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( diff --git a/src/conversions/indexmap.rs b/src/conversions/indexmap.rs index 03aba0e0fc3..acb466c3d0a 100644 --- a/src/conversions/indexmap.rs +++ b/src/conversions/indexmap.rs @@ -89,7 +89,7 @@ use crate::conversion::IntoPyObject; use crate::types::*; -use crate::{Bound, BoundObject, FromPyObject, IntoPy, PyErr, PyObject, Python, ToPyObject}; +use crate::{Bound, FromPyObject, IntoPy, PyErr, PyObject, Python, ToPyObject}; use std::{cmp, hash}; impl ToPyObject for indexmap::IndexMap @@ -99,7 +99,11 @@ where H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.to_object(py), v.to_object(py)).unwrap(); + } + dict.into_any().unbind() } } @@ -110,10 +114,11 @@ where H: hash::BuildHasher, { fn into_py(self, py: Python<'_>) -> PyObject { - let iter = self - .into_iter() - .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.into_py(py), v.into_py(py)).unwrap(); + } + dict.into_any().unbind() } } @@ -130,10 +135,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -152,10 +154,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -237,7 +236,7 @@ mod test_indexmap { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); - let py_map = map.into_py_dict(py); + let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( @@ -266,7 +265,7 @@ mod test_indexmap { } } - let py_map = map.clone().into_py_dict(py); + let py_map = (&map).into_py_dict(py).unwrap(); let trip_map = py_map.extract::>().unwrap(); diff --git a/src/conversions/std/map.rs b/src/conversions/std/map.rs index 4aba5066ffe..582c56b613f 100644 --- a/src/conversions/std/map.rs +++ b/src/conversions/std/map.rs @@ -5,8 +5,8 @@ use crate::inspect::types::TypeInfo; use crate::{ conversion::IntoPyObject, instance::Bound, - types::{any::PyAnyMethods, dict::PyDictMethods, IntoPyDict, PyDict}, - BoundObject, FromPyObject, IntoPy, PyAny, PyErr, PyObject, Python, ToPyObject, + types::{any::PyAnyMethods, dict::PyDictMethods, PyDict}, + FromPyObject, IntoPy, PyAny, PyErr, PyObject, Python, ToPyObject, }; impl ToPyObject for collections::HashMap @@ -16,7 +16,11 @@ where H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.to_object(py), v.to_object(py)).unwrap(); + } + dict.into_any().unbind() } } @@ -26,7 +30,11 @@ where V: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.to_object(py), v.to_object(py)).unwrap(); + } + dict.into_any().unbind() } } @@ -37,10 +45,11 @@ where H: hash::BuildHasher, { fn into_py(self, py: Python<'_>) -> PyObject { - let iter = self - .into_iter() - .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.into_py(py), v.into_py(py)).unwrap(); + } + dict.into_any().unbind() } #[cfg(feature = "experimental-inspect")] @@ -62,10 +71,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -84,10 +90,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -99,10 +102,11 @@ where V: IntoPy, { fn into_py(self, py: Python<'_>) -> PyObject { - let iter = self - .into_iter() - .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + let dict = PyDict::new(py); + for (k, v) in self { + dict.set_item(k.into_py(py), v.into_py(py)).unwrap(); + } + dict.into_any().unbind() } #[cfg(feature = "experimental-inspect")] @@ -123,10 +127,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } @@ -144,10 +145,7 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { - dict.set_item( - k.into_pyobject(py).map_err(Into::into)?.into_bound(), - v.into_pyobject(py).map_err(Into::into)?.into_bound(), - )?; + dict.set_item(k, v)?; } Ok(dict) } diff --git a/src/exceptions.rs b/src/exceptions.rs index 4239fae0e41..6f0fa3e674c 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -61,10 +61,13 @@ macro_rules! impl_exception_boilerplate_bound { /// /// import_exception!(socket, gaierror); /// +/// # fn main() -> pyo3::PyResult<()> { /// Python::with_gil(|py| { -/// let ctx = [("gaierror", py.get_type::())].into_py_dict(py); +/// let ctx = [("gaierror", py.get_type::())].into_py_dict(py)?; /// pyo3::py_run!(py, *ctx, "import socket; assert gaierror is socket.gaierror"); -/// }); +/// # Ok(()) +/// }) +/// # } /// /// ``` #[macro_export] @@ -905,7 +908,7 @@ mod tests { Python::with_gil(|py| { let error_type = py.get_type::(); - let ctx = [("CustomError", error_type)].into_py_dict(py); + let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() @@ -932,7 +935,7 @@ mod tests { create_exception!(mymodule.exceptions, CustomError, PyException); Python::with_gil(|py| { let error_type = py.get_type::(); - let ctx = [("CustomError", error_type)].into_py_dict(py); + let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() @@ -951,7 +954,7 @@ mod tests { Python::with_gil(|py| { let error_type = py.get_type::(); - let ctx = [("CustomError", error_type)].into_py_dict(py); + let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() @@ -984,7 +987,7 @@ mod tests { Python::with_gil(|py| { let error_type = py.get_type::(); - let ctx = [("CustomError", error_type)].into_py_dict(py); + let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() diff --git a/src/impl_/extract_argument.rs b/src/impl_/extract_argument.rs index 098722060c6..cbf79a14707 100644 --- a/src/impl_/extract_argument.rs +++ b/src/impl_/extract_argument.rs @@ -802,7 +802,7 @@ mod tests { Python::with_gil(|py| { let args = PyTuple::empty(py); - let kwargs = [("foo", 0u8)].into_py_dict(py); + let kwargs = [("foo", 0u8)].into_py_dict(py).unwrap(); let err = unsafe { function_description .extract_arguments_tuple_dict::( @@ -833,7 +833,7 @@ mod tests { Python::with_gil(|py| { let args = PyTuple::empty(py); - let kwargs = [(1u8, 1u8)].into_py_dict(py); + let kwargs = [(1u8, 1u8)].into_py_dict(py).unwrap(); let err = unsafe { function_description .extract_arguments_tuple_dict::( diff --git a/src/instance.rs b/src/instance.rs index 2b19fd10c43..1e15624929e 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1960,7 +1960,7 @@ mod tests { assert_repr(obj.call1(py, ((('x', 1),),)).unwrap().bind(py), "{'x': 1}"); assert_repr( - obj.call(py, (), Some(&[('x', 1)].into_py_dict(py))) + obj.call(py, (), Some(&[('x', 1)].into_py_dict(py).unwrap())) .unwrap() .bind(py), "{'x': 1}", diff --git a/src/lib.rs b/src/lib.rs index 8181afb4347..8144ef740e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -242,7 +242,7 @@ //! let sys = py.import("sys")?; //! let version: String = sys.getattr("version")?.extract()?; //! -//! let locals = [("os", py.import("os")?)].into_py_dict(py); +//! let locals = [("os", py.import("os")?)].into_py_dict(py)?; //! let code = c_str!("os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"); //! let user: String = py.eval(code, None, Some(&locals))?.extract()?; //! diff --git a/src/macros.rs b/src/macros.rs index 6148d9662c5..936dbd43af0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -75,10 +75,13 @@ /// } /// } /// +/// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { -/// let locals = [("C", py.get_type::())].into_py_dict(py); +/// let locals = [("C", py.get_type::())].into_py_dict(py)?; /// pyo3::py_run!(py, *locals, "c = C()"); -/// }); +/// # Ok(()) +/// }) +/// # } /// ``` #[macro_export] macro_rules! py_run { @@ -102,7 +105,7 @@ macro_rules! py_run_impl { ($py:expr, $($val:ident)+, $code:expr) => {{ use $crate::types::IntoPyDict; use $crate::ToPyObject; - let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict($py); + let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict($py).unwrap(); $crate::py_run_impl!($py, *d, $code) }}; ($py:expr, *$dict:expr, $code:expr) => {{ diff --git a/src/marker.rs b/src/marker.rs index 92a154b3694..a5ba0436287 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -872,7 +872,7 @@ mod tests { .unwrap(); assert_eq!(v, 1); - let d = [("foo", 13)].into_py_dict(py); + let d = [("foo", 13)].into_py_dict(py).unwrap(); // Inject our own global namespace let v: i32 = py diff --git a/src/tests/common.rs b/src/tests/common.rs index 4e4d7fe98ee..caa4120b720 100644 --- a/src/tests/common.rs +++ b/src/tests/common.rs @@ -40,7 +40,7 @@ mod inner { // Case1: idents & no err_msg ($py:expr, $($val:ident)+, $code:expr, $err:ident) => {{ use pyo3::types::IntoPyDict; - let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict($py); + let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict($py).unwrap(); py_expect_exception!($py, *d, $code, $err) }}; // Case2: dict & no err_msg @@ -126,7 +126,7 @@ mod inner { f: impl FnOnce(&Bound<'py, PyList>) -> PyResult, ) -> PyResult { let warnings = py.import("warnings")?; - let kwargs = [("record", true)].into_py_dict(py); + let kwargs = [("record", true)].into_py_dict(py)?; let catch_warnings = warnings .getattr("catch_warnings")? .call((), Some(&kwargs))?; diff --git a/src/types/any.rs b/src/types/any.rs index 37b79720730..409630e12b2 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -1701,7 +1701,7 @@ class NonHeapNonDescriptorInt: fn test_call_with_kwargs() { Python::with_gil(|py| { let list = vec![3, 6, 5, 4, 7].to_object(py); - let dict = vec![("reverse", true)].into_py_dict(py); + let dict = vec![("reverse", true)].into_py_dict(py).unwrap(); list.call_method(py, "sort", (), Some(&dict)).unwrap(); assert_eq!(list.extract::>(py).unwrap(), vec![7, 6, 5, 4, 3]); }); diff --git a/src/types/dict.rs b/src/types/dict.rs index 2136158e89e..c4de7bae46a 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -6,7 +6,7 @@ use crate::instance::{Borrowed, Bound}; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyList}; -use crate::{ffi, Python, ToPyObject}; +use crate::{ffi, BoundObject, Python}; /// Represents a Python `dict`. /// @@ -130,7 +130,7 @@ pub trait PyDictMethods<'py>: crate::sealed::Sealed { /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where - K: ToPyObject; + K: IntoPyObject<'py>; /// Gets an item from the dictionary. /// @@ -139,22 +139,22 @@ pub trait PyDictMethods<'py>: crate::sealed::Sealed { /// To get a `KeyError` for non-existing keys, use `PyAny::get_item`. fn get_item(&self, key: K) -> PyResult>> where - K: ToPyObject; + K: IntoPyObject<'py>; /// Sets an item value. /// /// This is equivalent to the Python statement `self[key] = value`. fn set_item(&self, key: K, value: V) -> PyResult<()> where - K: ToPyObject, - V: ToPyObject; + K: IntoPyObject<'py>, + V: IntoPyObject<'py>; /// Deletes an item. /// /// This is equivalent to the Python statement `del self[key]`. fn del_item(&self, key: K) -> PyResult<()> where - K: ToPyObject; + K: IntoPyObject<'py>; /// Returns a list of dict keys. /// @@ -226,9 +226,9 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> { fn contains(&self, key: K) -> PyResult where - K: ToPyObject, + K: IntoPyObject<'py>, { - fn inner(dict: &Bound<'_, PyDict>, key: Bound<'_, PyAny>) -> PyResult { + fn inner(dict: &Bound<'_, PyDict>, key: &Bound<'_, PyAny>) -> PyResult { match unsafe { ffi::PyDict_Contains(dict.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), @@ -237,16 +237,22 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> { } let py = self.py(); - inner(self, key.to_object(py).into_bound(py)) + inner( + self, + &key.into_pyobject(py) + .map_err(Into::into)? + .into_any() + .as_borrowed(), + ) } fn get_item(&self, key: K) -> PyResult>> where - K: ToPyObject, + K: IntoPyObject<'py>, { fn inner<'py>( dict: &Bound<'py, PyDict>, - key: Bound<'_, PyAny>, + key: &Bound<'_, PyAny>, ) -> PyResult>> { let py = dict.py(); let mut result: *mut ffi::PyObject = std::ptr::null_mut(); @@ -260,18 +266,24 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> { } let py = self.py(); - inner(self, key.to_object(py).into_bound(py)) + inner( + self, + &key.into_pyobject(py) + .map_err(Into::into)? + .into_any() + .as_borrowed(), + ) } fn set_item(&self, key: K, value: V) -> PyResult<()> where - K: ToPyObject, - V: ToPyObject, + K: IntoPyObject<'py>, + V: IntoPyObject<'py>, { fn inner( dict: &Bound<'_, PyDict>, - key: Bound<'_, PyAny>, - value: Bound<'_, PyAny>, + key: &Bound<'_, PyAny>, + value: &Bound<'_, PyAny>, ) -> PyResult<()> { err::error_on_minusone(dict.py(), unsafe { ffi::PyDict_SetItem(dict.as_ptr(), key.as_ptr(), value.as_ptr()) @@ -281,23 +293,36 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> { let py = self.py(); inner( self, - key.to_object(py).into_bound(py), - value.to_object(py).into_bound(py), + &key.into_pyobject(py) + .map_err(Into::into)? + .into_any() + .as_borrowed(), + &value + .into_pyobject(py) + .map_err(Into::into)? + .into_any() + .as_borrowed(), ) } fn del_item(&self, key: K) -> PyResult<()> where - K: ToPyObject, + K: IntoPyObject<'py>, { - fn inner(dict: &Bound<'_, PyDict>, key: Bound<'_, PyAny>) -> PyResult<()> { + fn inner(dict: &Bound<'_, PyDict>, key: &Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(dict.py(), unsafe { ffi::PyDict_DelItem(dict.as_ptr(), key.as_ptr()) }) } let py = self.py(); - inner(self, key.to_object(py).into_bound(py)) + inner( + self, + &key.into_pyobject(py) + .map_err(Into::into)? + .into_any() + .as_borrowed(), + ) } fn keys(&self) -> Bound<'py, PyList> { @@ -529,73 +554,69 @@ mod borrowed_iter { } } +use crate::prelude::IntoPyObject; pub(crate) use borrowed_iter::BorrowedDictIter; /// Conversion trait that allows a sequence of tuples to be converted into `PyDict` /// Primary use case for this trait is `call` and `call_method` methods as keywords argument. -pub trait IntoPyDict: Sized { +pub trait IntoPyDict<'py>: Sized { /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed /// depends on implementation. - fn into_py_dict(self, py: Python<'_>) -> Bound<'_, PyDict>; + fn into_py_dict(self, py: Python<'py>) -> PyResult>; /// Deprecated name for [`IntoPyDict::into_py_dict`]. #[deprecated(since = "0.23.0", note = "renamed to `IntoPyDict::into_py_dict`")] #[inline] - fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { - self.into_py_dict(py) + fn into_py_dict_bound(self, py: Python<'py>) -> Bound<'py, PyDict> { + self.into_py_dict(py).unwrap() } } -impl IntoPyDict for I +impl<'py, T, I> IntoPyDict<'py> for I where - T: PyDictItem, + T: PyDictItem<'py>, I: IntoIterator, { - fn into_py_dict(self, py: Python<'_>) -> Bound<'_, PyDict> { + fn into_py_dict(self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); for item in self { - dict.set_item(item.key(), item.value()) - .expect("Failed to set_item on dict"); + let (key, value) = item.unpack(); + dict.set_item(key, value)?; } - dict + Ok(dict) } } /// Represents a tuple which can be used as a PyDict item. -pub trait PyDictItem { - type K: ToPyObject; - type V: ToPyObject; - fn key(&self) -> &Self::K; - fn value(&self) -> &Self::V; +trait PyDictItem<'py> { + type K: IntoPyObject<'py>; + type V: IntoPyObject<'py>; + fn unpack(self) -> (Self::K, Self::V); } -impl PyDictItem for (K, V) +impl<'py, K, V> PyDictItem<'py> for (K, V) where - K: ToPyObject, - V: ToPyObject, + K: IntoPyObject<'py>, + V: IntoPyObject<'py>, { type K = K; type V = V; - fn key(&self) -> &Self::K { - &self.0 - } - fn value(&self) -> &Self::V { - &self.1 + + fn unpack(self) -> (Self::K, Self::V) { + (self.0, self.1) } } -impl PyDictItem for &(K, V) +impl<'a, 'py, K, V> PyDictItem<'py> for &'a (K, V) where - K: ToPyObject, - V: ToPyObject, + &'a K: IntoPyObject<'py>, + &'a V: IntoPyObject<'py>, { - type K = K; - type V = V; - fn key(&self) -> &Self::K { - &self.0 - } - fn value(&self) -> &Self::V { - &self.1 + type K = &'a K; + type V = &'a V; + + fn unpack(self) -> (Self::K, Self::V) { + (&self.0, &self.1) } } @@ -603,12 +624,13 @@ where mod tests { use super::*; use crate::types::PyTuple; + use crate::ToPyObject; use std::collections::{BTreeMap, HashMap}; #[test] fn test_new() { Python::with_gil(|py| { - let dict = [(7, 32)].into_py_dict(py); + let dict = [(7, 32)].into_py_dict(py).unwrap(); assert_eq!( 32, dict.get_item(7i32) @@ -668,7 +690,7 @@ mod tests { #[test] fn test_copy() { Python::with_gil(|py| { - let dict = [(7, 32)].into_py_dict(py); + let dict = [(7, 32)].into_py_dict(py).unwrap(); let ndict = dict.copy().unwrap(); assert_eq!( @@ -1065,7 +1087,7 @@ mod tests { let mut map = HashMap::::new(); map.insert(1, 1); - let py_map = map.into_py_dict(py); + let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( @@ -1086,7 +1108,7 @@ mod tests { let mut map = BTreeMap::::new(); map.insert(1, 1); - let py_map = map.into_py_dict(py); + let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( @@ -1105,7 +1127,7 @@ mod tests { fn test_vec_into_dict() { Python::with_gil(|py| { let vec = vec![("a", 1), ("b", 2), ("c", 3)]; - let py_map = vec.into_py_dict(py); + let py_map = vec.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 3); assert_eq!( @@ -1124,7 +1146,7 @@ mod tests { fn test_slice_into_dict() { Python::with_gil(|py| { let arr = [("a", 1), ("b", 2), ("c", 3)]; - let py_map = arr.into_py_dict(py); + let py_map = arr.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 3); assert_eq!( @@ -1145,7 +1167,7 @@ mod tests { let mut map = HashMap::::new(); map.insert(1, 1); - let py_map = map.into_py_dict(py); + let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.as_mapping().len().unwrap(), 1); assert_eq!( @@ -1166,7 +1188,7 @@ mod tests { let mut map = HashMap::::new(); map.insert(1, 1); - let py_map = map.into_py_dict(py); + let py_map = map.into_py_dict(py).unwrap(); let py_mapping = py_map.into_mapping(); assert_eq!(py_mapping.len().unwrap(), 1); @@ -1180,7 +1202,7 @@ mod tests { map.insert("a", 1); map.insert("b", 2); map.insert("c", 3); - map.into_py_dict(py) + map.into_py_dict(py).unwrap() } #[test] @@ -1216,8 +1238,8 @@ mod tests { #[test] fn dict_update() { Python::with_gil(|py| { - let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict(py); - let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict(py); + let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict(py).unwrap(); + let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict(py).unwrap(); dict.update(other.as_mapping()).unwrap(); assert_eq!(dict.len(), 4); assert_eq!( @@ -1287,8 +1309,8 @@ mod tests { #[test] fn dict_update_if_missing() { Python::with_gil(|py| { - let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict(py); - let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict(py); + let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict(py).unwrap(); + let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict(py).unwrap(); dict.update_if_missing(other.as_mapping()).unwrap(); assert_eq!(dict.len(), 4); assert_eq!( diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index 75549f39718..4d396f9be68 100644 --- a/tests/test_buffer_protocol.rs +++ b/tests/test_buffer_protocol.rs @@ -57,7 +57,7 @@ fn test_buffer() { }, ) .unwrap(); - let env = [("ob", instance)].into_py_dict(py); + let env = [("ob", instance)].into_py_dict(py).unwrap(); py_assert!(py, *env, "bytes(ob) == b' 23'"); }); @@ -122,7 +122,7 @@ fn test_releasebuffer_unraisable_error() { let capture = UnraisableCapture::install(py); let instance = Py::new(py, ReleaseBufferError {}).unwrap(); - let env = [("ob", instance.clone_ref(py))].into_py_dict(py); + let env = [("ob", instance.clone_ref(py))].into_py_dict(py).unwrap(); assert!(capture.borrow(py).capture.is_none()); diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs index a6fb89831cc..a48354c47c8 100644 --- a/tests/test_class_basics.rs +++ b/tests/test_class_basics.rs @@ -249,7 +249,8 @@ fn class_with_hash() { ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_py(py)), ] - .into_py_dict(py); + .into_py_dict(py) + .unwrap(); py_assert!(py, *env, "hash(obj) == hsh"); }); diff --git a/tests/test_class_new.rs b/tests/test_class_new.rs index fb5ca91db81..75070bd274b 100644 --- a/tests/test_class_new.rs +++ b/tests/test_class_new.rs @@ -29,7 +29,7 @@ fn empty_class_with_new() { // Calling with arbitrary args or kwargs is not ok assert!(typeobj.call(("some", "args"), None).is_err()); assert!(typeobj - .call((), Some(&[("some", "kwarg")].into_py_dict(py))) + .call((), Some(&[("some", "kwarg")].into_py_dict(py).unwrap())) .is_err()); }); } diff --git a/tests/test_coroutine.rs b/tests/test_coroutine.rs index cdf01b8891e..89ab3d64a4b 100644 --- a/tests/test_coroutine.rs +++ b/tests/test_coroutine.rs @@ -72,7 +72,8 @@ fn test_coroutine_qualname() { ("my_fn", wrap_pyfunction!(my_fn, gil).unwrap().as_any()), ("MyClass", gil.get_type::().as_any()), ] - .into_py_dict(gil); + .into_py_dict(gil) + .unwrap(); py_run!(gil, *locals, &handle_windows(test)); }) } @@ -313,7 +314,9 @@ fn test_async_method_receiver() { assert False assert asyncio.run(coro3) == 1 "#; - let locals = [("Counter", gil.get_type::())].into_py_dict(gil); + let locals = [("Counter", gil.get_type::())] + .into_py_dict(gil) + .unwrap(); py_run!(gil, *locals, test); }); @@ -348,7 +351,9 @@ fn test_async_method_receiver_with_other_args() { assert asyncio.run(v.set_value(10)) == 10 assert asyncio.run(v.get_value_plus_with(1, 1)) == 12 "#; - let locals = [("Value", gil.get_type::())].into_py_dict(gil); + let locals = [("Value", gil.get_type::())] + .into_py_dict(gil) + .unwrap(); py_run!(gil, *locals, test); }); } diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index 2278d9ecc73..b1fad408dc5 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -13,7 +13,9 @@ fn _get_subclasses<'py>( // Import the class from Python and create some subclasses let datetime = py.import("datetime")?; - let locals = [(py_type, datetime.getattr(py_type)?)].into_py_dict(py); + let locals = [(py_type, datetime.getattr(py_type)?)] + .into_py_dict(py) + .unwrap(); let make_subclass_py = CString::new(format!("class Subklass({}):\n pass", py_type))?; @@ -135,7 +137,7 @@ fn test_datetime_utc() { let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap(); - let locals = [("dt", dt)].into_py_dict(py); + let locals = [("dt", dt)].into_py_dict(py).unwrap(); let offset: f32 = py .eval( diff --git a/tests/test_enum.rs b/tests/test_enum.rs index abe743ee9ca..5e994548edd 100644 --- a/tests/test_enum.rs +++ b/tests/test_enum.rs @@ -259,7 +259,8 @@ fn test_simple_enum_with_hash() { ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_py(py)), ] - .into_py_dict(py); + .into_py_dict(py) + .unwrap(); py_assert!(py, *env, "hash(obj) == hsh"); }); @@ -290,7 +291,8 @@ fn test_complex_enum_with_hash() { ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_py(py)), ] - .into_py_dict(py); + .into_py_dict(py) + .unwrap(); py_assert!(py, *env, "hash(obj) == hsh"); }); diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rs index 8966471abe2..d8cc3af20e6 100644 --- a/tests/test_getter_setter.rs +++ b/tests/test_getter_setter.rs @@ -85,7 +85,9 @@ fn class_with_properties() { py_run!(py, inst, "inst.from_any = 15"); py_run!(py, inst, "assert inst.get_num() == 15"); - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'"); }); } diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index d3980152120..2cce50bba25 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -21,7 +21,9 @@ struct SubclassAble {} #[test] fn subclass() { Python::with_gil(|py| { - let d = [("SubclassAble", py.get_type::())].into_py_dict(py); + let d = [("SubclassAble", py.get_type::())] + .into_py_dict(py) + .unwrap(); py.run( ffi::c_str!("class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)"), @@ -98,7 +100,7 @@ fn call_base_and_sub_methods() { fn mutation_fails() { Python::with_gil(|py| { let obj = Py::new(py, SubClass::new()).unwrap(); - let global = [("obj", obj)].into_py_dict(py); + let global = [("obj", obj)].into_py_dict(py).unwrap(); let e = py .run( ffi::c_str!("obj.base_set(lambda: obj.sub_set_and_ret(1))"), @@ -276,7 +278,7 @@ mod inheriting_native_type { fn custom_exception() { Python::with_gil(|py| { let cls = py.get_type::(); - let dict = [("cls", &cls)].into_py_dict(py); + let dict = [("cls", &cls)].into_py_dict(py).unwrap(); let res = py.run( ffi::c_str!("e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e"), None, diff --git a/tests/test_macro_docs.rs b/tests/test_macro_docs.rs index 964e762886d..42159be9d3c 100644 --- a/tests/test_macro_docs.rs +++ b/tests/test_macro_docs.rs @@ -23,7 +23,9 @@ impl MacroDocs { #[test] fn meth_doc() { Python::with_gil(|py| { - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_assert!( py, *d, diff --git a/tests/test_mapping.rs b/tests/test_mapping.rs index 1938c8837ff..ecb944e983e 100644 --- a/tests/test_mapping.rs +++ b/tests/test_mapping.rs @@ -71,7 +71,9 @@ impl Mapping { /// Return a dict with `m = Mapping(['1', '2', '3'])`. fn map_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { - let d = [("Mapping", py.get_type::())].into_py_dict(py); + let d = [("Mapping", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_run!(py, *d, "m = Mapping(['1', '2', '3'])"); d } diff --git a/tests/test_methods.rs b/tests/test_methods.rs index 2a9ffbec788..eb099bc0aa5 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -86,7 +86,9 @@ impl ClassMethod { #[test] fn class_method() { Python::with_gil(|py| { - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'"); py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'"); py_assert!( @@ -113,7 +115,9 @@ impl ClassMethodWithArgs { #[test] fn class_method_with_args() { Python::with_gil(|py| { - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_assert!( py, *d, @@ -144,7 +148,9 @@ fn static_method() { Python::with_gil(|py| { assert_eq!(StaticMethod::method(py), "StaticMethod.method()!"); - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_assert!(py, *d, "C.method() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C().method() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C.method.__doc__ == 'Test static method.'"); @@ -168,7 +174,9 @@ fn static_method_with_args() { Python::with_gil(|py| { assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2"); - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_assert!(py, *d, "C.method(1337) == '0x539'"); }); } @@ -677,7 +685,7 @@ impl MethDocs { #[test] fn meth_doc() { Python::with_gil(|py| { - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())].into_py_dict(py).unwrap(); py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'"); py_assert!( py, @@ -764,7 +772,7 @@ fn method_with_pyclassarg() { Python::with_gil(|py| { let obj1 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let obj2 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); - let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py); + let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py).unwrap(); py_run!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20"); diff --git a/tests/test_module.rs b/tests/test_module.rs index 6f19ad5763c..c33a8a27ee5 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -76,7 +76,8 @@ fn test_module_with_functions() { "module_with_functions", wrap_pymodule!(module_with_functions)(py), )] - .into_py_dict(py); + .into_py_dict(py) + .unwrap(); py_assert!( py, @@ -133,7 +134,8 @@ fn test_module_with_explicit_py_arg() { "module_with_explicit_py_arg", wrap_pymodule!(module_with_explicit_py_arg)(py), )] - .into_py_dict(py); + .into_py_dict(py) + .unwrap(); py_assert!(py, *d, "module_with_explicit_py_arg.double(3) == 6"); }); @@ -150,7 +152,9 @@ fn test_module_renaming() { use pyo3::wrap_pymodule; Python::with_gil(|py| { - let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict(py); + let d = [("different_name", wrap_pymodule!(some_name)(py))] + .into_py_dict(py) + .unwrap(); py_run!(py, *d, "assert different_name.__name__ == 'other_name'"); }); diff --git a/tests/test_sequence.rs b/tests/test_sequence.rs index 9ac8d6dbe89..fd7e9eb01c6 100644 --- a/tests/test_sequence.rs +++ b/tests/test_sequence.rs @@ -107,7 +107,9 @@ impl ByteSequence { /// Return a dict with `s = ByteSequence([1, 2, 3])`. fn seq_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { - let d = [("ByteSequence", py.get_type::())].into_py_dict(py); + let d = [("ByteSequence", py.get_type::())] + .into_py_dict(py) + .unwrap(); // Though we can construct `s` in Rust, let's test `__new__` works. py_run!(py, *d, "s = ByteSequence([1, 2, 3])"); d @@ -139,7 +141,9 @@ fn test_setitem() { #[test] fn test_delitem() { Python::with_gil(|py| { - let d = [("ByteSequence", py.get_type::())].into_py_dict(py); + let d = [("ByteSequence", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_run!( py, @@ -235,7 +239,9 @@ fn test_repeat() { #[test] fn test_inplace_repeat() { Python::with_gil(|py| { - let d = [("ByteSequence", py.get_type::())].into_py_dict(py); + let d = [("ByteSequence", py.get_type::())] + .into_py_dict(py) + .unwrap(); py_run!( py, diff --git a/tests/test_static_slots.rs b/tests/test_static_slots.rs index bd1cb0cdc8a..48d80a43856 100644 --- a/tests/test_static_slots.rs +++ b/tests/test_static_slots.rs @@ -38,7 +38,9 @@ impl Count5 { /// Return a dict with `s = Count5()`. fn test_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { - let d = [("Count5", py.get_type::())].into_py_dict(py); + let d = [("Count5", py.get_type::())] + .into_py_dict(py) + .unwrap(); // Though we can construct `s` in Rust, let's test `__new__` works. py_run!(py, *d, "s = Count5()"); d