From fbd896b75142037a5b223ae04f437c7b5939089c Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 30 Dec 2023 22:57:26 +0000 Subject: [PATCH] add bound dict constructors & py.run variants --- CHANGELOG.md | 2 +- README.md | 4 +- guide/src/class.md | 26 ++-- guide/src/class/numeric.md | 2 +- guide/src/class/protocols.md | 4 +- guide/src/conversions/traits.md | 4 +- guide/src/ecosystem/logging.md | 2 +- guide/src/exception.md | 6 +- guide/src/features.md | 2 +- guide/src/memory.md | 16 +- guide/src/migration.md | 14 +- guide/src/module.md | 4 +- guide/src/python_from_rust.md | 30 ++-- pyo3-benches/benches/bench_any.rs | 11 +- pyo3-benches/benches/bench_bigint.rs | 27 ++-- pyo3-benches/benches/bench_decimal.rs | 8 +- pyo3-benches/benches/bench_dict.rs | 22 +-- pyo3-benches/benches/bench_extract.rs | 35 ++--- pyo3-benches/benches/bench_tuple.rs | 18 +-- src/buffer.rs | 1 + src/conversions/anyhow.rs | 8 +- src/conversions/chrono.rs | 20 ++- src/conversions/eyre.rs | 8 +- src/conversions/hashbrown.rs | 8 +- src/conversions/indexmap.rs | 9 +- src/conversions/num_bigint.rs | 22 ++- src/conversions/rust_decimal.rs | 32 ++-- src/conversions/smallvec.rs | 4 +- src/conversions/std/array.rs | 10 +- src/conversions/std/map.rs | 8 +- src/conversions/std/num.rs | 30 ++-- src/conversions/std/slice.rs | 4 +- src/err/mod.rs | 8 +- src/exceptions.rs | 74 +++++----- src/ffi/tests.rs | 27 ++-- src/gil.rs | 10 +- src/impl_/extract_argument.rs | 6 +- src/instance.rs | 10 +- src/lib.rs | 4 +- src/macros.rs | 44 ++++-- src/marker.rs | 102 +++++++++---- src/marshal.rs | 7 +- src/pycell.rs | 4 +- src/pyclass_init.rs | 4 +- src/sync.rs | 15 +- src/tests/common.rs | 14 +- src/tests/hygiene/pyfunction.rs | 2 +- src/types/any.rs | 22 +-- src/types/bytearray.rs | 16 +- src/types/bytes.rs | 1 + src/types/datetime.rs | 8 +- src/types/dict.rs | 66 +++++++-- src/types/ellipsis.rs | 3 +- src/types/function.rs | 4 +- src/types/iterator.rs | 9 +- src/types/list.rs | 1 + src/types/mod.rs | 2 +- src/types/none.rs | 3 +- src/types/notimplemented.rs | 5 +- src/types/sequence.rs | 1 + src/types/set.rs | 1 + src/types/string.rs | 1 + src/types/traceback.rs | 3 +- tests/test_anyhow.rs | 12 +- tests/test_append_to_inittab.rs | 2 +- tests/test_arithmetics.rs | 172 +++++++++++----------- tests/test_buffer_protocol.rs | 4 +- tests/test_class_basics.rs | 26 ++-- tests/test_class_new.rs | 12 +- tests/test_coroutine.rs | 32 ++-- tests/test_datetime.rs | 22 +-- tests/test_dict_iter.rs | 2 +- tests/test_enum.rs | 12 +- tests/test_exceptions.rs | 6 +- tests/test_frompyobject.rs | 36 ++--- tests/test_gc.rs | 12 +- tests/test_getter_setter.rs | 48 +++--- tests/test_inheritance.rs | 40 ++--- tests/test_macro_docs.rs | 2 +- tests/test_mapping.rs | 14 +- tests/test_methods.rs | 158 ++++++++++---------- tests/test_module.rs | 8 +- tests/test_no_imports.rs | 34 ++--- tests/test_proto_methods.rs | 32 ++-- tests/test_pyfunction.rs | 8 +- tests/test_sequence.rs | 32 ++-- tests/test_static_slots.rs | 8 +- tests/test_super.rs | 2 +- tests/test_unsendable_dict.rs | 8 +- tests/test_various.rs | 6 +- tests/ui/invalid_result_conversion.stderr | 2 +- tests/ui/wrong_aspyref_lifetimes.rs | 2 +- 92 files changed, 900 insertions(+), 732 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97ce9a00537..33ac7644c3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1290,7 +1290,7 @@ To see unreleased changes, please see the [CHANGELOG on the main branch guide](h ### Added - `module` argument to `pyclass` macro. [#499](https://github.com/PyO3/pyo3/pull/499) -- `py_run!` macro [#512](https://github.com/PyO3/pyo3/pull/512) +- `py_run_bound!` macro [#512](https://github.com/PyO3/pyo3/pull/512) - Use existing fields and methods before calling custom **getattr**. [#505](https://github.com/PyO3/pyo3/pull/505) - `PyBytes` can now be indexed just like `Vec` - Implement `IntoPy` for `PyRef` and `PyRefMut`. diff --git a/README.md b/README.md index 1b163d75056..8dd3356de8f 100644 --- a/README.md +++ b/README.md @@ -152,9 +152,9 @@ 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_bound(py); let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; - let user: String = py.eval(code, None, Some(&locals))?.extract()?; + let user: String = py.eval_bound(code, None, Some(&locals))?.extract()?; println!("Hello {}, I'm Python {}", user, version); Ok(()) diff --git a/guide/src/class.md b/guide/src/class.md index e3f3502780b..a11cea740f3 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -186,7 +186,7 @@ Python::with_gil(|py| { } // You can convert `&PyCell` to a Python object - pyo3::py_run!(py, obj, "assert obj.num == 5"); + pyo3::py_run_bound!(py, obj, "assert obj.num == 5"); }); ``` @@ -352,12 +352,12 @@ impl SubSubClass { } # Python::with_gil(|py| { # let subsub = pyo3::PyCell::new(py, SubSubClass::new()).unwrap(); -# pyo3::py_run!(py, subsub, "assert subsub.method3() == 3000"); +# pyo3::py_run_bound!(py, subsub, "assert subsub.method3() == 3000"); # let subsub = SubSubClass::factory_method(py, 2).unwrap(); # let subsubsub = SubSubClass::factory_method(py, 3).unwrap(); # let cls = py.get_type::(); -# pyo3::py_run!(py, subsub cls, "assert not isinstance(subsub, cls)"); -# pyo3::py_run!(py, subsubsub cls, "assert isinstance(subsubsub, cls)"); +# pyo3::py_run_bound!(py, subsub cls, "assert not isinstance(subsub, cls)"); +# pyo3::py_run_bound!(py, subsubsub cls, "assert isinstance(subsubsub, cls)"); # }); ``` @@ -396,7 +396,7 @@ impl DictWithCounter { } # Python::with_gil(|py| { # let cnt = pyo3::PyCell::new(py, DictWithCounter::new()).unwrap(); -# pyo3::py_run!(py, cnt, "cnt.set('abc', 10); assert cnt['abc'] == 10") +# pyo3::py_run_bound!(py, cnt, "cnt.set('abc', 10); assert cnt['abc'] == 10") # }); # } ``` @@ -452,7 +452,7 @@ impl MyDict { } # Python::with_gil(|py| { # let cls = py.get_type::(); -# pyo3::py_run!(py, cls, "cls(a=1, b=2)") +# pyo3::py_run_bound!(py, cls, "cls(a=1, b=2)") # }); # } ``` @@ -721,7 +721,7 @@ impl MyClass { Python::with_gil(|py| { let my_class = py.get_type::(); - pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'") + pyo3::py_run_bound!(py, my_class, "assert my_class.my_attribute == 'hello'") }); ``` @@ -974,7 +974,7 @@ Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let y = Py::new(py, MyEnum::OtherVariant).unwrap(); let cls = py.get_type::(); - pyo3::py_run!(py, x y cls, r#" + pyo3::py_run_bound!(py, x y cls, r#" assert x == cls.Variant assert y == cls.OtherVariant assert x != y @@ -995,7 +995,7 @@ enum MyEnum { Python::with_gil(|py| { let cls = py.get_type::(); let x = MyEnum::Variant as i32; // The exact value is assigned by the compiler. - pyo3::py_run!(py, cls x, r#" + pyo3::py_run_bound!(py, cls x, r#" assert int(cls.Variant) == x assert int(cls.OtherVariant) == 10 assert cls.OtherVariant == 10 # You can also compare against int. @@ -1017,7 +1017,7 @@ enum MyEnum{ Python::with_gil(|py| { let cls = py.get_type::(); let x = Py::new(py, MyEnum::Variant).unwrap(); - pyo3::py_run!(py, cls x, r#" + pyo3::py_run_bound!(py, cls x, r#" assert repr(x) == 'MyEnum.Variant' assert repr(cls.OtherVariant) == 'MyEnum.OtherVariant' "#) @@ -1042,7 +1042,7 @@ impl MyEnum { Python::with_gil(|py| { let cls = py.get_type::(); - pyo3::py_run!(py, cls, "assert repr(cls.Answer) == '42'") + pyo3::py_run_bound!(py, cls, "assert repr(cls.Answer) == '42'") }) ``` @@ -1059,7 +1059,7 @@ enum MyEnum { Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let cls = py.get_type::(); - pyo3::py_run!(py, x cls, r#" + pyo3::py_run_bound!(py, x cls, r#" assert repr(x) == 'RenamedEnum.UPPERCASE' assert x == cls.UPPERCASE "#) @@ -1187,7 +1187,7 @@ impl pyo3::impl_::pyclass::PyClassImpl for MyClass { # Python::with_gil(|py| { # let cls = py.get_type::(); -# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'") +# pyo3::py_run_bound!(py, cls, "assert cls.__name__ == 'MyClass'") # }); # } ``` diff --git a/guide/src/class/numeric.md b/guide/src/class/numeric.md index 10a06e7c02c..f1567b171f0 100644 --- a/guide/src/class/numeric.md +++ b/guide/src/class/numeric.md @@ -390,7 +390,7 @@ fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { # let globals = PyModule::import(py, "__main__")?.dict(); # globals.set_item("Number", Number::type_object(py))?; # -# py.run(SCRIPT, Some(globals), None)?; +# py.run_bound(SCRIPT, Some(&globals.as_borrowed()), None)?; # Ok(()) # }) # } diff --git a/guide/src/class/protocols.md b/guide/src/class/protocols.md index 4577a5102b6..0e4e37f5eb5 100644 --- a/guide/src/class/protocols.md +++ b/guide/src/class/protocols.md @@ -208,8 +208,8 @@ impl Container { # Python::with_gil(|py| { # let container = Container { iter: vec![1, 2, 3, 4] }; # let inst = pyo3::PyCell::new(py, container).unwrap(); -# pyo3::py_run!(py, inst, "assert list(inst) == [1, 2, 3, 4]"); -# pyo3::py_run!(py, inst, "assert list(iter(iter(inst))) == [1, 2, 3, 4]"); +# pyo3::py_run_bound!(py, inst, "assert list(inst) == [1, 2, 3, 4]"); +# pyo3::py_run_bound!(py, inst, "assert list(iter(iter(inst))) == [1, 2, 3, 4]"); # }); ``` diff --git a/guide/src/conversions/traits.md b/guide/src/conversions/traits.md index 68304753b05..eb3244183a9 100644 --- a/guide/src/conversions/traits.md +++ b/guide/src/conversions/traits.md @@ -86,7 +86,7 @@ struct RustyStruct { # use pyo3::types::PyDict; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { -# let dict = PyDict::new(py); +# let dict = PyDict::new_bound(py); # dict.set_item("my_string", "test")?; # # let rustystruct: RustyStruct = dict.extract()?; @@ -155,7 +155,7 @@ struct RustyStruct { # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { -# let py_dict = py.eval("{'foo': 'foo', 'bar': 'bar', 'foobar': 'foobar'}", None, None)?; +# let py_dict = py.eval_bound("{'foo': 'foo', 'bar': 'bar', 'foobar': 'foobar'}", None, None)?; # let rustystruct: RustyStruct = py_dict.extract()?; # assert_eq!(rustystruct.foo, "foo"); # assert_eq!(rustystruct.bar, "bar"); diff --git a/guide/src/ecosystem/logging.md b/guide/src/ecosystem/logging.md index 2e7d4a087c6..caed60e9974 100644 --- a/guide/src/ecosystem/logging.md +++ b/guide/src/ecosystem/logging.md @@ -79,7 +79,7 @@ fn main() -> PyResult<()> { // Log some messages from Python Python::with_gil(|py| { - py.run( + py.run_bound( " import logging logging.error('Something bad happened') diff --git a/guide/src/exception.md b/guide/src/exception.md index 756477957b8..97153eab0ac 100644 --- a/guide/src/exception.md +++ b/guide/src/exception.md @@ -24,13 +24,13 @@ use pyo3::exceptions::PyException; create_exception!(mymodule, CustomError, PyException); Python::with_gil(|py| { - let ctx = [("CustomError", py.get_type::())].into_py_dict(py); - pyo3::py_run!( + let ctx = [("CustomError", py.get_type::())].into_py_dict_bound(py); + pyo3::py_run_bound!( py, *ctx, "assert str(CustomError) == \"\"" ); - pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)"); + pyo3::py_run_bound!(py, *ctx, "assert CustomError('oops').args == ('oops',)"); }); ``` diff --git a/guide/src/features.md b/guide/src/features.md index edcf3772b26..9b03eeb381f 100644 --- a/guide/src/features.md +++ b/guide/src/features.md @@ -73,7 +73,7 @@ This feature enables a dependency on the `pyo3-macros` crate, which provides the - `#[pymethods]` - `#[derive(FromPyObject)]` -It also provides the `py_run!` macro. +It also provides the `py_run_bound!` macro. These macros require a number of dependencies which may not be needed by users who just need PyO3 for Python FFI. Disabling this feature enables faster builds for those users, as these dependencies will not be built if this feature is disabled. diff --git a/guide/src/memory.md b/guide/src/memory.md index f9201e3f003..d089be4e152 100644 --- a/guide/src/memory.md +++ b/guide/src/memory.md @@ -27,7 +27,7 @@ very simple and easy-to-understand programs like this: # use pyo3::types::PyString; # fn main() -> PyResult<()> { Python::with_gil(|py| -> PyResult<()> { - let hello: &PyString = py.eval("\"Hello World!\"", None, None)?.extract()?; + let hello: Bound<'_, PyString> = py.eval_bound("\"Hello World!\"", None, None)?.downcast_into()?; println!("Python says: {}", hello); Ok(()) })?; @@ -48,7 +48,7 @@ of the time we don't have to think about this, but consider the following: # fn main() -> PyResult<()> { Python::with_gil(|py| -> PyResult<()> { for _ in 0..10 { - let hello: &PyString = py.eval("\"Hello World!\"", None, None)?.extract()?; + let hello: Bound<'_, PyString> = py.eval_bound("\"Hello World!\"", None, None)?.downcast_into()?; println!("Python says: {}", hello); } // There are 10 copies of `hello` on Python's heap here. @@ -76,7 +76,7 @@ is to acquire and release the GIL with each iteration of the loop. # fn main() -> PyResult<()> { for _ in 0..10 { Python::with_gil(|py| -> PyResult<()> { - let hello: &PyString = py.eval("\"Hello World!\"", None, None)?.extract()?; + let hello: Bound<'_, PyString> = py.eval_bound("\"Hello World!\"", None, None)?.downcast_into()?; println!("Python says: {}", hello); Ok(()) })?; // only one copy of `hello` at a time @@ -97,7 +97,7 @@ Python::with_gil(|py| -> PyResult<()> { for _ in 0..10 { let pool = unsafe { py.new_pool() }; let py = pool.python(); - let hello: &PyString = py.eval("\"Hello World!\"", None, None)?.extract()?; + let hello: Bound<'_, PyString> = py.eval_bound("\"Hello World!\"", None, None)?.downcast_into()?; println!("Python says: {}", hello); } Ok(()) @@ -144,7 +144,7 @@ reference count reaches zero? It depends whether or not we are holding the GIL. # use pyo3::types::PyString; # fn main() -> PyResult<()> { Python::with_gil(|py| -> PyResult<()> { - let hello: Py = py.eval("\"Hello World!\"", None, None)?.extract()?; + let hello: Py = py.eval_bound("\"Hello World!\"", None, None)?.extract()?; println!("Python says: {}", hello.as_ref(py)); Ok(()) })?; @@ -166,7 +166,7 @@ we are *not* holding the GIL? # use pyo3::types::PyString; # fn main() -> PyResult<()> { let hello: Py = Python::with_gil(|py| { - py.eval("\"Hello World!\"", None, None)?.extract() + py.eval_bound("\"Hello World!\"", None, None)?.extract() })?; // Do some stuff... // Now sometime later in the program we want to access `hello`. @@ -197,7 +197,7 @@ We can avoid the delay in releasing memory if we are careful to drop the # use pyo3::types::PyString; # fn main() -> PyResult<()> { let hello: Py = - Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?; + Python::with_gil(|py| py.eval_bound("\"Hello World!\"", None, None)?.extract())?; // Do some stuff... // Now sometime later in the program: Python::with_gil(|py| { @@ -219,7 +219,7 @@ until the GIL is dropped. # use pyo3::types::PyString; # fn main() -> PyResult<()> { let hello: Py = - Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?; + Python::with_gil(|py| py.eval_bound("\"Hello World!\"", None, None)?.extract())?; // Do some stuff... // Now sometime later in the program: Python::with_gil(|py| { diff --git a/guide/src/migration.md b/guide/src/migration.md index ec195ad1bc3..083acf4ceb8 100644 --- a/guide/src/migration.md +++ b/guide/src/migration.md @@ -271,7 +271,7 @@ Python::with_gil(|py| { After: -```rust +```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; @@ -394,7 +394,7 @@ fn raise_err() -> anyhow::Result<()> { # fn main() { Python::with_gil(|py| { let rs_func = wrap_pyfunction!(raise_err, py).unwrap(); - pyo3::py_run!( + pyo3::py_run_bound!( py, rs_func, r" @@ -1191,7 +1191,7 @@ all you need to do is remove `ObjectProtocol` from your code. Or if you use `ObjectProtocol` by `use pyo3::prelude::*`, you have to do nothing. Before: -```rust,compile_fail +```rust,ignore use pyo3::ObjectProtocol; # pyo3::Python::with_gil(|py| { @@ -1202,7 +1202,7 @@ assert_eq!(hi.len().unwrap(), 5); ``` After: -```rust +```rust,ignore # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); @@ -1283,7 +1283,7 @@ impl Names { } # Python::with_gil(|py| { # let names = PyCell::new(py, Names::new()).unwrap(); -# pyo3::py_run!(py, names, r" +# pyo3::py_run_bound!(py, names, r" # try: # names.merge(names) # assert False, 'Unreachable' @@ -1348,8 +1348,8 @@ After: # #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }} # Python::with_gil(|py| { # let typeobj = py.get_type::(); -# let d = [("c", typeobj)].into_py_dict(py); -# let create_obj = || py.eval("c()", None, Some(d)).unwrap(); +# let d = [("c", typeobj)].into_py_dict_bound(py); +# let create_obj = || py.eval_bound("c()", None, Some(&d)).unwrap().into_gil_ref(); let obj: &PyAny = create_obj(); let obj_cell: &PyCell = obj.extract().unwrap(); let obj_cloned: MyClass = obj.extract().unwrap(); // extracted by cloning the object diff --git a/guide/src/module.md b/guide/src/module.md index 9e52ab93e2b..3d984f60d39 100644 --- a/guide/src/module.md +++ b/guide/src/module.md @@ -93,9 +93,9 @@ fn func() -> String { # use pyo3::wrap_pymodule; # use pyo3::types::IntoPyDict; # 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_bound(py); # -# py.run("assert parent_module.child_module.func() == 'func'", None, Some(&ctx)).unwrap(); +# py.run_bound("assert parent_module.child_module.func() == 'func'", None, Some(&ctx)).unwrap(); # }) ``` diff --git a/guide/src/python_from_rust.md b/guide/src/python_from_rust.md index b0e40c035b5..0aa96500297 100644 --- a/guide/src/python_from_rust.md +++ b/guide/src/python_from_rust.md @@ -94,17 +94,17 @@ fn main() -> PyResult<()> { .into(); // call object with PyDict - let kwargs = [(key1, val1)].into_py_dict(py); - fun.call_bound(py, (), Some(&kwargs.as_borrowed()))?; + let kwargs = [(key1, val1)].into_py_dict_bound(py); + fun.call_bound(py, (), Some(&kwargs))?; // pass arguments as Vec let kwargs = vec![(key1, val1), (key2, val2)]; - fun.call_bound(py, (), Some(&kwargs.into_py_dict(py).as_borrowed()))?; + fun.call_bound(py, (), Some(&kwargs.into_py_dict_bound(py)))?; // pass arguments as HashMap let mut kwargs = HashMap::<&str, i32>::new(); kwargs.insert(key1, 1); - fun.call_bound(py, (), Some(&kwargs.into_py_dict(py).as_borrowed()))?; + fun.call_bound(py, (), Some(&kwargs.into_py_dict_bound(py)))?; Ok(()) }) @@ -155,7 +155,7 @@ use pyo3::prelude::*; # fn main() -> Result<(), ()> { Python::with_gil(|py| { let result = py - .eval("[i * 10 for i in range(5)]", None, None) + .eval_bound("[i * 10 for i in range(5)]", None, None) .map_err(|e| { e.print_and_set_sys_last_vars(py); })?; @@ -173,13 +173,13 @@ Python::with_gil(|py| { This method returns nothing (like any Python statement), but you can get access to manipulated objects via the `locals` dict. -You can also use the [`py_run!`] macro, which is a shorthand for [`Python::run`]. -Since [`py_run!`] panics on exceptions, we recommend you use this macro only for +You can also use the [`py_run_bound!`] macro, which is a shorthand for [`Python::run`]. +Since [`py_run_bound!`] panics on exceptions, we recommend you use this macro only for quickly testing your Python extensions. ```rust use pyo3::prelude::*; -use pyo3::{PyCell, py_run}; +use pyo3::{PyCell, py_run_bound}; # fn main() { #[pyclass] @@ -206,7 +206,7 @@ Python::with_gil(|py| { }; let userdata = PyCell::new(py, userdata).unwrap(); let userdata_as_tuple = (34, "Yu"); - py_run!(py, userdata userdata_as_tuple, r#" + py_run_bound!(py, userdata userdata_as_tuple, r#" assert repr(userdata) == "User Yu(id: 34)" assert userdata.as_tuple() == userdata_as_tuple "#); @@ -248,10 +248,10 @@ 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_bound(py); let lrelu_result: f64 = activators .getattr("leaky_relu")? - .call((-1.0,), Some(kwargs))? + .call((-1.0,), Some(kwargs.as_gil_ref()))? .extract()?; assert_eq!(lrelu_result, -0.2); # Ok(()) @@ -288,7 +288,7 @@ fn foo(_py: Python<'_>, foo_module: &PyModule) -> PyResult<()> { fn main() -> PyResult<()> { pyo3::append_to_inittab!(foo); - Python::with_gil(|py| Python::run(py, "import foo; foo.add_one(6)", None, None)) + Python::with_gil(|py| py.run_bound("import foo; foo.add_one(6)", None, None)) } ``` @@ -319,7 +319,7 @@ fn main() -> PyResult<()> { py_modules.set_item("foo", foo_module)?; // Now we can import + run our python code - Python::run(py, "import foo; foo.add_one(6)", None, None) + py.run_bound("import foo; foo.add_one(6)", None, None) }) } ``` @@ -427,7 +427,7 @@ fn main() -> PyResult<()> { [`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.run -[`py_run!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html +[`py_run_bound!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html ## Need to use a context manager from Rust? @@ -464,7 +464,7 @@ class House(object): house.call_method0("__enter__").unwrap(); - let result = py.eval("undefined_variable + 1", None, None); + let result = py.eval_bound("undefined_variable + 1", None, None); // If the eval threw an exception we'll pass it through to the context manager. // Otherwise, __exit__ is called with empty arguments (Python "None"). diff --git a/pyo3-benches/benches/bench_any.rs b/pyo3-benches/benches/bench_any.rs index bfd010efd19..e3c919e55f7 100644 --- a/pyo3-benches/benches/bench_any.rs +++ b/pyo3-benches/benches/bench_any.rs @@ -1,6 +1,7 @@ use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion}; use pyo3::{ + prelude::*, types::{ PyBool, PyByteArray, PyBytes, PyDict, PyFloat, PyFrozenSet, PyInt, PyList, PyMapping, PySequence, PySet, PyString, PyTuple, @@ -27,7 +28,7 @@ enum ObjectType { Unknown, } -fn find_object_type(obj: &PyAny) -> ObjectType { +fn find_object_type(obj: &Bound<'_, PyAny>) -> ObjectType { if obj.is_none() { ObjectType::None } else if obj.is_instance_of::() { @@ -63,17 +64,17 @@ fn find_object_type(obj: &PyAny) -> ObjectType { fn bench_identify_object_type(b: &mut Bencher<'_>) { Python::with_gil(|py| { - let obj = py.eval("object()", None, None).unwrap(); + let obj = py.eval_bound("object()", None, None).unwrap(); - b.iter(|| find_object_type(obj)); + b.iter(|| find_object_type(&obj)); - assert_eq!(find_object_type(obj), ObjectType::Unknown); + assert_eq!(find_object_type(&obj), ObjectType::Unknown); }); } fn bench_collect_generic_iterator(b: &mut Bencher<'_>) { Python::with_gil(|py| { - let collection = py.eval("list(range(1 << 20))", None, None).unwrap(); + let collection = py.eval_bound("list(range(1 << 20))", None, None).unwrap(); b.iter(|| { collection diff --git a/pyo3-benches/benches/bench_bigint.rs b/pyo3-benches/benches/bench_bigint.rs index d3c71629ba4..7eff183e457 100644 --- a/pyo3-benches/benches/bench_bigint.rs +++ b/pyo3-benches/benches/bench_bigint.rs @@ -1,14 +1,15 @@ use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion}; -use pyo3::{types::PyDict, PyAny, Python}; +use pyo3::prelude::*; +use pyo3::{types::PyDict, Python}; use num_bigint::BigInt; fn extract_bigint_extract_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).extract::() { + bench.iter(|| match black_box(&d).extract::() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); @@ -17,10 +18,10 @@ fn extract_bigint_extract_fail(bench: &mut Bencher<'_>) { fn extract_bigint_small(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let int = py.eval("-42", None, None).unwrap(); + let int = py.eval_bound("-42", None, None).unwrap(); bench.iter(|| { - let v = black_box(int).extract::().unwrap(); + let v = black_box(&int).extract::().unwrap(); black_box(v); }); }); @@ -28,10 +29,10 @@ fn extract_bigint_small(bench: &mut Bencher<'_>) { fn extract_bigint_big_negative(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let int = py.eval("-10**300", None, None).unwrap(); + let int = py.eval_bound("-10**300", None, None).unwrap(); bench.iter(|| { - let v = black_box(int).extract::().unwrap(); + let v = black_box(&int).extract::().unwrap(); black_box(v); }); }); @@ -39,10 +40,10 @@ fn extract_bigint_big_negative(bench: &mut Bencher<'_>) { fn extract_bigint_big_positive(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let int = py.eval("10**300", None, None).unwrap(); + let int = py.eval_bound("10**300", None, None).unwrap(); bench.iter(|| { - let v = black_box(int).extract::().unwrap(); + let v = black_box(&int).extract::().unwrap(); black_box(v); }); }); @@ -50,10 +51,10 @@ fn extract_bigint_big_positive(bench: &mut Bencher<'_>) { fn extract_bigint_huge_negative(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let int = py.eval("-10**3000", None, None).unwrap(); + let int = py.eval_bound("-10**3000", None, None).unwrap(); bench.iter(|| { - let v = black_box(int).extract::().unwrap(); + let v = black_box(&int).extract::().unwrap(); black_box(v); }); }); @@ -61,10 +62,10 @@ fn extract_bigint_huge_negative(bench: &mut Bencher<'_>) { fn extract_bigint_huge_positive(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let int = py.eval("10**3000", None, None).unwrap(); + let int = py.eval_bound("10**3000", None, None).unwrap(); bench.iter(|| { - let v = black_box(int).extract::().unwrap(); + let v = black_box(&int).extract::().unwrap(); black_box(v); }); }); diff --git a/pyo3-benches/benches/bench_decimal.rs b/pyo3-benches/benches/bench_decimal.rs index 203756b54cc..6db6704bf8e 100644 --- a/pyo3-benches/benches/bench_decimal.rs +++ b/pyo3-benches/benches/bench_decimal.rs @@ -6,20 +6,20 @@ use rust_decimal::Decimal; fn decimal_via_extract(b: &mut Bencher<'_>) { Python::with_gil(|py| { - let locals = PyDict::new(py); - py.run( + let locals = PyDict::new_bound(py); + py.run_bound( r#" import decimal py_dec = decimal.Decimal("0.0") "#, None, - Some(locals), + Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); b.iter(|| { - let _: Decimal = black_box(py_dec).extract().unwrap(); + let _: Decimal = black_box(&py_dec).extract().unwrap(); }); }) } diff --git a/pyo3-benches/benches/bench_dict.rs b/pyo3-benches/benches/bench_dict.rs index d1c23466a39..921aef9ef3a 100644 --- a/pyo3-benches/benches/bench_dict.rs +++ b/pyo3-benches/benches/bench_dict.rs @@ -7,10 +7,10 @@ use std::collections::{BTreeMap, HashMap}; fn iter_dict(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 100_000; - let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); + let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); let mut sum = 0; b.iter(|| { - for (k, _v) in dict { + for (k, _v) in dict.iter() { let i: u64 = k.extract().unwrap(); sum += i; } @@ -21,14 +21,14 @@ fn iter_dict(b: &mut Bencher<'_>) { fn dict_new(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py)); + b.iter_with_large_drop(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py)); }); } fn dict_get_item(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); + let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); let mut sum = 0; b.iter(|| { for i in 0..LEN { @@ -46,16 +46,16 @@ fn dict_get_item(b: &mut Bencher<'_>) { fn extract_hashmap(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 100_000; - let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); - b.iter(|| HashMap::::extract(dict)); + let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); + b.iter(|| HashMap::::extract(dict.as_gil_ref())); }); } fn extract_btreemap(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 100_000; - let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); - b.iter(|| BTreeMap::::extract(dict)); + let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); + b.iter(|| BTreeMap::::extract(dict.as_gil_ref())); }); } @@ -63,8 +63,8 @@ fn extract_btreemap(b: &mut Bencher<'_>) { fn extract_hashbrown_map(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 100_000; - let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); - b.iter(|| hashbrown::HashMap::::extract(dict)); + let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); + b.iter(|| hashbrown::HashMap::::extract(dict.as_gil_ref())); }); } @@ -73,7 +73,7 @@ fn mapping_from_dict(b: &mut Bencher<'_>) { const LEN: usize = 100_000; let dict = (0..LEN as u64) .map(|i| (i, i * 2)) - .into_py_dict(py) + .into_py_dict_bound(py) .to_object(py); b.iter(|| { let _: &PyMapping = dict.extract(py).unwrap(); diff --git a/pyo3-benches/benches/bench_extract.rs b/pyo3-benches/benches/bench_extract.rs index 6ff22d3834d..7312e4f8a08 100644 --- a/pyo3-benches/benches/bench_extract.rs +++ b/pyo3-benches/benches/bench_extract.rs @@ -1,16 +1,17 @@ use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion}; use pyo3::{ + prelude::*, types::{PyDict, PyFloat, PyInt, PyString}, - IntoPy, PyAny, PyObject, Python, + IntoPy, PyObject, Python, }; fn extract_str_extract_success(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let s = PyString::new(py, "Hello, World!") as &PyAny; + let s = PyString::new(py, "Hello, World!"); bench.iter(|| { - let v = black_box(s).extract::<&str>().unwrap(); + let v = black_box(&s).extract::<&str>().unwrap(); black_box(v); }); }); @@ -18,9 +19,9 @@ fn extract_str_extract_success(bench: &mut Bencher<'_>) { fn extract_str_extract_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).extract::<&str>() { + bench.iter(|| match black_box(&d).extract::<&str>() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); @@ -29,10 +30,10 @@ fn extract_str_extract_fail(bench: &mut Bencher<'_>) { fn extract_str_downcast_success(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let s = PyString::new(py, "Hello, World!") as &PyAny; + let s = PyString::new(py, "Hello, World!"); bench.iter(|| { - let py_str = black_box(s).downcast::().unwrap(); + let py_str = black_box(&s).downcast::().unwrap(); let v = py_str.to_str().unwrap(); black_box(v); }); @@ -41,9 +42,9 @@ fn extract_str_downcast_success(bench: &mut Bencher<'_>) { fn extract_str_downcast_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).downcast::() { + bench.iter(|| match black_box(&d).downcast::() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); @@ -64,9 +65,9 @@ fn extract_int_extract_success(bench: &mut Bencher<'_>) { fn extract_int_extract_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).extract::() { + bench.iter(|| match black_box(&d).extract::() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); @@ -88,9 +89,9 @@ fn extract_int_downcast_success(bench: &mut Bencher<'_>) { fn extract_int_downcast_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).downcast::() { + bench.iter(|| match black_box(&d).downcast::() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); @@ -111,9 +112,9 @@ fn extract_float_extract_success(bench: &mut Bencher<'_>) { fn extract_float_extract_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).extract::() { + bench.iter(|| match black_box(&d).extract::() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); @@ -135,9 +136,9 @@ fn extract_float_downcast_success(bench: &mut Bencher<'_>) { fn extract_float_downcast_fail(bench: &mut Bencher<'_>) { Python::with_gil(|py| { - let d = PyDict::new(py) as &PyAny; + let d = PyDict::new_bound(py); - bench.iter(|| match black_box(d).downcast::() { + bench.iter(|| match black_box(&d).downcast::() { Ok(v) => panic!("should err {}", v), Err(e) => black_box(e), }); diff --git a/pyo3-benches/benches/bench_tuple.rs b/pyo3-benches/benches/bench_tuple.rs index f224ee1bc4d..da3576db66d 100644 --- a/pyo3-benches/benches/bench_tuple.rs +++ b/pyo3-benches/benches/bench_tuple.rs @@ -6,10 +6,10 @@ use pyo3::types::{PyList, PySequence, PyTuple}; fn iter_tuple(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 100_000; - let tuple = PyTuple::new(py, 0..LEN); + let tuple = PyTuple::new_bound(py, 0..LEN); let mut sum = 0; b.iter(|| { - for x in tuple { + for x in tuple.iter_borrowed() { let i: u64 = x.extract().unwrap(); sum += i; } @@ -20,14 +20,14 @@ fn iter_tuple(b: &mut Bencher<'_>) { fn tuple_new(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - b.iter(|| PyTuple::new(py, 0..LEN)); + b.iter_with_large_drop(|| PyTuple::new_bound(py, 0..LEN)); }); } fn tuple_get_item(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - let tuple = PyTuple::new(py, 0..LEN); + let tuple = PyTuple::new_bound(py, 0..LEN); let mut sum = 0; b.iter(|| { for i in 0..LEN { @@ -41,7 +41,7 @@ fn tuple_get_item(b: &mut Bencher<'_>) { fn tuple_get_item_unchecked(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - let tuple = PyTuple::new(py, 0..LEN); + let tuple = PyTuple::new_bound(py, 0..LEN); let mut sum = 0; b.iter(|| { for i in 0..LEN { @@ -56,7 +56,7 @@ fn tuple_get_item_unchecked(b: &mut Bencher<'_>) { fn sequence_from_tuple(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - let tuple = PyTuple::new(py, 0..LEN).to_object(py); + let tuple = PyTuple::new_bound(py, 0..LEN).to_object(py); b.iter(|| tuple.extract::<&PySequence>(py).unwrap()); }); } @@ -64,10 +64,10 @@ fn sequence_from_tuple(b: &mut Bencher<'_>) { fn tuple_new_list(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - let tuple = PyTuple::new(py, 0..LEN); + let tuple = PyTuple::new_bound(py, 0..LEN); b.iter(|| { let _pool = unsafe { py.new_pool() }; - let _ = PyList::new(py, tuple); + let _ = PyList::new(py, tuple.iter_borrowed()); }); }); } @@ -75,7 +75,7 @@ fn tuple_new_list(b: &mut Bencher<'_>) { fn tuple_to_list(b: &mut Bencher<'_>) { Python::with_gil(|py| { const LEN: usize = 50_000; - let tuple = PyTuple::new(py, 0..LEN); + let tuple = PyTuple::new_bound(py, 0..LEN); b.iter(|| { let _pool = unsafe { py.new_pool() }; let _ = tuple.to_list(); diff --git a/src/buffer.rs b/src/buffer.rs index 4ff2c1d97eb..66a796470ee 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -685,6 +685,7 @@ impl_element!(f32, Float); impl_element!(f64, Float); #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::PyBuffer; use crate::ffi; diff --git a/src/conversions/anyhow.rs b/src/conversions/anyhow.rs index b362faf479f..4b3ec7d9595 100644 --- a/src/conversions/anyhow.rs +++ b/src/conversions/anyhow.rs @@ -147,8 +147,8 @@ mod test_anyhow { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); - let pyerr = py.run("raise err", None, Some(locals)).unwrap_err(); + let locals = [("err", pyerr)].into_py_dict_bound(py); + let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } @@ -164,8 +164,8 @@ mod test_anyhow { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); - let pyerr = py.run("raise err", None, Some(locals)).unwrap_err(); + let locals = [("err", pyerr)].into_py_dict_bound(py); + let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } diff --git a/src/conversions/chrono.rs b/src/conversions/chrono.rs index cc0eb73a8ef..0467a6a8166 100644 --- a/src/conversions/chrono.rs +++ b/src/conversions/chrono.rs @@ -567,8 +567,13 @@ fn timezone_utc(py: Python<'_>) -> &PyAny { #[cfg(test)] mod tests { - use super::*; - use crate::{types::PyTuple, Py}; + use super::timezone_utc; + #[cfg(all(Py_3_9, not(target_os = "windows")))] + use crate::types::{any::PyAnyMethods, dict::PyDictMethods}; + use crate::{ + exceptions::PyUserWarning, types::PyTuple, IntoPy, Py, PyAny, PyResult, Python, ToPyObject, + }; + use chrono::{DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc}; use std::{cmp::Ordering, panic}; #[test] @@ -578,11 +583,11 @@ mod tests { #[cfg(all(Py_3_9, not(target_os = "windows")))] fn test_zoneinfo_is_not_fixed_offset() { Python::with_gil(|py| { - let locals = crate::types::PyDict::new(py); - py.run( + let locals = crate::types::PyDict::new_bound(py); + py.run_bound( "import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')", None, - Some(locals), + Some(&locals), ) .unwrap(); let result: PyResult = locals.get_item("zi").unwrap().unwrap().extract(); @@ -1098,6 +1103,7 @@ mod tests { mod proptests { use super::*; use crate::tests::common::CatchWarnings; + use crate::types::any::PyAnyMethods; use crate::types::IntoPyDict; use proptest::prelude::*; @@ -1108,9 +1114,9 @@ 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_bound(py); let code = format!("datetime.datetime.fromtimestamp({}).replace(tzinfo=datetime.timezone(datetime.timedelta(seconds={})))", timestamp, timedelta); - let t = py.eval(&code, Some(globals), None).unwrap(); + let t = py.eval_bound(&code, Some(&globals), None).unwrap(); // Get ISO 8601 string from python let py_iso_str = t.call_method0("isoformat").unwrap(); diff --git a/src/conversions/eyre.rs b/src/conversions/eyre.rs index f881599e2c3..3ff0a42e3af 100644 --- a/src/conversions/eyre.rs +++ b/src/conversions/eyre.rs @@ -152,8 +152,8 @@ mod tests { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); - let pyerr = py.run("raise err", None, Some(locals)).unwrap_err(); + let locals = [("err", pyerr)].into_py_dict_bound(py); + let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } @@ -169,8 +169,8 @@ mod tests { let pyerr = PyErr::from(err); Python::with_gil(|py| { - let locals = [("err", pyerr)].into_py_dict(py); - let pyerr = py.run("raise err", None, Some(locals)).unwrap_err(); + let locals = [("err", pyerr)].into_py_dict_bound(py); + let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } diff --git a/src/conversions/hashbrown.rs b/src/conversions/hashbrown.rs index 62a7e87b804..27dc2341fb9 100644 --- a/src/conversions/hashbrown.rs +++ b/src/conversions/hashbrown.rs @@ -30,7 +30,7 @@ where H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + IntoPyDict::into_py_dict_bound(self, py).into() } } @@ -44,7 +44,7 @@ where let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + IntoPyDict::into_py_dict_bound(iter, py).into() } } @@ -108,6 +108,8 @@ where #[cfg(test)] mod tests { + use crate::types::{any::PyAnyMethods, dict::PyDictMethods}; + use super::*; #[test] @@ -160,7 +162,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_bound(py); assert_eq!(py_map.len(), 1); assert_eq!( diff --git a/src/conversions/indexmap.rs b/src/conversions/indexmap.rs index 7c7303e6d83..d439a9e4809 100644 --- a/src/conversions/indexmap.rs +++ b/src/conversions/indexmap.rs @@ -98,7 +98,7 @@ where H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + IntoPyDict::into_py_dict_bound(self, py).into() } } @@ -112,7 +112,7 @@ where let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + IntoPyDict::into_py_dict_bound(iter, py).into() } } @@ -136,6 +136,7 @@ where mod test_indexmap { use crate::types::*; + use crate::types::{any::PyAnyMethods, dict::PyDictMethods}; use crate::{IntoPy, PyObject, Python, ToPyObject}; #[test] @@ -192,7 +193,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_bound(py); assert_eq!(py_map.len(), 1); assert_eq!( @@ -221,7 +222,7 @@ mod test_indexmap { } } - let py_map = map.clone().into_py_dict(py); + let py_map = map.clone().into_py_dict_bound(py); let trip_map = py_map.extract::>().unwrap(); diff --git a/src/conversions/num_bigint.rs b/src/conversions/num_bigint.rs index 5cc2157d446..882887b1c53 100644 --- a/src/conversions/num_bigint.rs +++ b/src/conversions/num_bigint.rs @@ -50,6 +50,8 @@ use crate::{ ffi, types::*, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; +#[cfg(Py_LIMITED_API)] +use crate::{types::dict::PyDictMethods, Bound}; use num_bigint::{BigInt, BigUint}; @@ -80,14 +82,18 @@ macro_rules! bigint_conversion { let bytes = $to_bytes(self); let bytes_obj = PyBytes::new(py, &bytes); let kwargs = if $is_signed > 0 { - let kwargs = PyDict::new(py); + let kwargs = PyDict::new_bound(py); kwargs.set_item(crate::intern!(py, "signed"), true).unwrap(); Some(kwargs) } else { None }; py.get_type::() - .call_method("from_bytes", (bytes_obj, "little"), kwargs) + .call_method( + "from_bytes", + (bytes_obj, "little"), + kwargs.as_ref().map(Bound::as_gil_ref), + ) .expect("int.from_bytes() failed during to_object()") // FIXME: #1813 or similar .into() } @@ -211,7 +217,7 @@ fn int_to_py_bytes(long: &PyLong, n_bytes: usize, is_signed: bool) -> PyResult<& use crate::intern; let py = long.py(); let kwargs = if is_signed { - let kwargs = PyDict::new(py); + let kwargs = PyDict::new_bound(py); kwargs.set_item(intern!(py, "signed"), true)?; Some(kwargs) } else { @@ -220,7 +226,7 @@ fn int_to_py_bytes(long: &PyLong, n_bytes: usize, is_signed: bool) -> PyResult<& let bytes = long.call_method( intern!(py, "to_bytes"), (n_bytes, intern!(py, "little")), - kwargs, + kwargs.as_ref().map(Bound::as_gil_ref), )?; Ok(bytes.downcast()?) } @@ -249,7 +255,7 @@ fn int_n_bits(long: &PyLong) -> PyResult { #[cfg(test)] mod tests { use super::*; - use crate::types::{PyDict, PyModule}; + use crate::types::{dict::PyDictMethods, PyDict, PyModule}; use indoc::indoc; fn rust_fib() -> impl Iterator @@ -327,10 +333,10 @@ mod tests { fn convert_index_class() { Python::with_gil(|py| { let index = python_index_class(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("index", index).unwrap(); - let ob = py.eval("index.C(10)", None, Some(locals)).unwrap(); - let _: BigInt = FromPyObject::extract(ob).unwrap(); + let ob = py.eval_bound("index.C(10)", None, Some(&locals)).unwrap(); + let _: BigInt = FromPyObject::extract(ob.into_gil_ref()).unwrap(); }); } diff --git a/src/conversions/rust_decimal.rs b/src/conversions/rust_decimal.rs index 173e57851c9..0cf518fd652 100644 --- a/src/conversions/rust_decimal.rs +++ b/src/conversions/rust_decimal.rs @@ -104,7 +104,7 @@ impl IntoPy for Decimal { mod test_rust_decimal { use super::*; use crate::err::PyErr; - use crate::types::PyDict; + use crate::types::{dict::PyDictMethods, PyDict}; use rust_decimal::Decimal; #[cfg(not(target_arch = "wasm32"))] @@ -117,21 +117,21 @@ mod test_rust_decimal { Python::with_gil(|py| { let rs_orig = $rs; let rs_dec = rs_orig.into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("rs_dec", &rs_dec).unwrap(); // Checks if Rust Decimal -> Python Decimal conversion is correct - py.run( + py.run_bound( &format!( "import decimal\npy_dec = decimal.Decimal({})\nassert py_dec == rs_dec", $py ), None, - Some(locals), + Some(&locals), ) .unwrap(); // Checks if Python Decimal -> Rust Decimal conversion is correct let py_dec = locals.get_item("py_dec").unwrap().unwrap(); - let py_result: Decimal = FromPyObject::extract(py_dec).unwrap(); + let py_result: Decimal = FromPyObject::extract(py_dec.into_gil_ref()).unwrap(); assert_eq!(rs_orig, py_result); }) } @@ -159,13 +159,13 @@ mod test_rust_decimal { let num = Decimal::from_parts(lo, mid, high, negative, scale); Python::with_gil(|py| { let rs_dec = num.into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("rs_dec", &rs_dec).unwrap(); - py.run( + py.run_bound( &format!( "import decimal\npy_dec = decimal.Decimal(\"{}\")\nassert py_dec == rs_dec", num), - None, Some(locals)).unwrap(); + None, Some(&locals)).unwrap(); let roundtripped: Decimal = rs_dec.extract(py).unwrap(); assert_eq!(num, roundtripped); }) @@ -185,15 +185,15 @@ mod test_rust_decimal { #[test] fn test_nan() { Python::with_gil(|py| { - let locals = PyDict::new(py); - py.run( + let locals = PyDict::new_bound(py); + py.run_bound( "import decimal\npy_dec = decimal.Decimal(\"NaN\")", None, - Some(locals), + Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); - let roundtripped: Result = FromPyObject::extract(py_dec); + let roundtripped: Result = FromPyObject::extract(py_dec.into_gil_ref()); assert!(roundtripped.is_err()); }) } @@ -201,15 +201,15 @@ mod test_rust_decimal { #[test] fn test_infinity() { Python::with_gil(|py| { - let locals = PyDict::new(py); - py.run( + let locals = PyDict::new_bound(py); + py.run_bound( "import decimal\npy_dec = decimal.Decimal(\"Infinity\")", None, - Some(locals), + Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); - let roundtripped: Result = FromPyObject::extract(py_dec); + let roundtripped: Result = FromPyObject::extract(py_dec.into_gil_ref()); assert!(roundtripped.is_err()); }) } diff --git a/src/conversions/smallvec.rs b/src/conversions/smallvec.rs index d2e84421da3..36d811e43f8 100644 --- a/src/conversions/smallvec.rs +++ b/src/conversions/smallvec.rs @@ -95,7 +95,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::types::{PyDict, PyList}; + use crate::types::{any::PyAnyMethods, PyDict, PyList}; #[test] fn test_smallvec_into_py() { @@ -119,7 +119,7 @@ mod tests { #[test] fn test_smallvec_from_py_object_fails() { Python::with_gil(|py| { - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); let sv: PyResult> = dict.extract(); assert_eq!( sv.unwrap_err().to_string(), diff --git a/src/conversions/std/array.rs b/src/conversions/std/array.rs index 167f8070632..51520c1047f 100644 --- a/src/conversions/std/array.rs +++ b/src/conversions/std/array.rs @@ -127,7 +127,7 @@ mod tests { sync::atomic::{AtomicUsize, Ordering}, }; - use crate::{types::PyList, IntoPy, PyResult, Python, ToPyObject}; + use crate::{types::any::PyAnyMethods, types::PyList, IntoPy, PyResult, Python, ToPyObject}; #[test] fn array_try_from_fn() { @@ -154,7 +154,7 @@ mod tests { fn test_extract_bytearray_to_array() { Python::with_gil(|py| { let v: [u8; 33] = py - .eval( + .eval_bound( "bytearray(b'abcabcabcabcabcabcabcabcabcabcabc')", None, None, @@ -170,7 +170,7 @@ mod tests { fn test_extract_small_bytearray_to_array() { Python::with_gil(|py| { let v: [u8; 3] = py - .eval("bytearray(b'abc')", None, None) + .eval_bound("bytearray(b'abc')", None, None) .unwrap() .extract() .unwrap(); @@ -194,7 +194,7 @@ mod tests { fn test_extract_invalid_sequence_length() { Python::with_gil(|py| { let v: PyResult<[u8; 3]> = py - .eval("bytearray(b'abcdefg')", None, None) + .eval_bound("bytearray(b'abcdefg')", None, None) .unwrap() .extract(); assert_eq!( @@ -220,7 +220,7 @@ mod tests { #[test] fn test_extract_non_iterable_to_array() { Python::with_gil(|py| { - let v = py.eval("42", None, None).unwrap(); + let v = py.eval_bound("42", None, None).unwrap(); v.extract::().unwrap(); v.extract::<[i32; 1]>().unwrap_err(); }); diff --git a/src/conversions/std/map.rs b/src/conversions/std/map.rs index a53b0ce9222..bb82ac5f33f 100644 --- a/src/conversions/std/map.rs +++ b/src/conversions/std/map.rs @@ -14,7 +14,7 @@ where H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + IntoPyDict::into_py_dict_bound(self, py).into() } } @@ -24,7 +24,7 @@ where V: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { - IntoPyDict::into_py_dict(self, py).into() + IntoPyDict::into_py_dict_bound(self, py).into() } } @@ -38,7 +38,7 @@ where let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + IntoPyDict::into_py_dict_bound(iter, py).into() } #[cfg(feature = "experimental-inspect")] @@ -56,7 +56,7 @@ where let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); - IntoPyDict::into_py_dict(iter, py).into() + IntoPyDict::into_py_dict_bound(iter, py).into() } #[cfg(feature = "experimental-inspect")] diff --git a/src/conversions/std/num.rs b/src/conversions/std/num.rs index 1f3bf673a48..b545c935db8 100644 --- a/src/conversions/std/num.rs +++ b/src/conversions/std/num.rs @@ -357,6 +357,8 @@ nonzero_int_impl!(NonZeroUsize, usize); #[cfg(test)] mod test_128bit_integers { use super::*; + use crate::types::any::PyAnyMethods; + #[cfg(not(target_arch = "wasm32"))] use crate::types::PyDict; @@ -369,9 +371,9 @@ mod test_128bit_integers { fn test_i128_roundtrip(x: i128) { Python::with_gil(|py| { let x_py = x.into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); - py.run(&format!("assert x_py == {}", x), None, Some(locals)).unwrap(); + py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: i128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) @@ -385,9 +387,9 @@ mod test_128bit_integers { ) { Python::with_gil(|py| { let x_py = x.into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); - py.run(&format!("assert x_py == {}", x), None, Some(locals)).unwrap(); + py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: NonZeroI128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) @@ -400,9 +402,9 @@ mod test_128bit_integers { fn test_u128_roundtrip(x: u128) { Python::with_gil(|py| { let x_py = x.into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); - py.run(&format!("assert x_py == {}", x), None, Some(locals)).unwrap(); + py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: u128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) @@ -416,9 +418,9 @@ mod test_128bit_integers { ) { Python::with_gil(|py| { let x_py = x.into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); - py.run(&format!("assert x_py == {}", x), None, Some(locals)).unwrap(); + py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: NonZeroU128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) @@ -460,7 +462,7 @@ mod test_128bit_integers { #[test] fn test_i128_overflow() { Python::with_gil(|py| { - let obj = py.eval("(1 << 130) * -1", None, None).unwrap(); + let obj = py.eval_bound("(1 << 130) * -1", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) @@ -469,7 +471,7 @@ mod test_128bit_integers { #[test] fn test_u128_overflow() { Python::with_gil(|py| { - let obj = py.eval("1 << 130", None, None).unwrap(); + let obj = py.eval_bound("1 << 130", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) @@ -513,7 +515,7 @@ mod test_128bit_integers { #[test] fn test_nonzero_i128_overflow() { Python::with_gil(|py| { - let obj = py.eval("(1 << 130) * -1", None, None).unwrap(); + let obj = py.eval_bound("(1 << 130) * -1", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) @@ -522,7 +524,7 @@ mod test_128bit_integers { #[test] fn test_nonzero_u128_overflow() { Python::with_gil(|py| { - let obj = py.eval("1 << 130", None, None).unwrap(); + let obj = py.eval_bound("1 << 130", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) @@ -531,7 +533,7 @@ mod test_128bit_integers { #[test] fn test_nonzero_i128_zero_value() { Python::with_gil(|py| { - let obj = py.eval("0", None, None).unwrap(); + let obj = py.eval_bound("0", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) @@ -540,7 +542,7 @@ mod test_128bit_integers { #[test] fn test_nonzero_u128_zero_value() { Python::with_gil(|py| { - let obj = py.eval("0", None, None).unwrap(); + let obj = py.eval_bound("0", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) diff --git a/src/conversions/std/slice.rs b/src/conversions/std/slice.rs index fbe2d19e1ac..256e69b6d96 100644 --- a/src/conversions/std/slice.rs +++ b/src/conversions/std/slice.rs @@ -32,8 +32,8 @@ mod tests { #[test] fn test_extract_bytes() { Python::with_gil(|py| { - let py_bytes = py.eval("b'Hello Python'", None, None).unwrap(); - let bytes: &[u8] = FromPyObject::extract(py_bytes).unwrap(); + let py_bytes = py.eval_bound("b'Hello Python'", None, None).unwrap(); + let bytes: &[u8] = FromPyObject::extract(py_bytes.into_gil_ref()).unwrap(); assert_eq!(bytes, b"Hello Python"); }); } diff --git a/src/err/mod.rs b/src/err/mod.rs index 39975183f07..06ac3ea66c3 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -1012,7 +1012,7 @@ mod tests { Python::with_gil(|py| { let err = py - .run("raise Exception('banana')", None, None) + .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error"); let debug_str = format!("{:?}", err); @@ -1037,7 +1037,7 @@ mod tests { fn err_display() { Python::with_gil(|py| { let err = py - .run("raise Exception('banana')", None, None) + .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error"); assert_eq!(err.to_string(), "Exception: banana"); }); @@ -1078,12 +1078,12 @@ mod tests { fn test_pyerr_cause() { Python::with_gil(|py| { let err = py - .run("raise Exception('banana')", None, None) + .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error"); assert!(err.cause(py).is_none()); let err = py - .run( + .run_bound( "raise Exception('banana') from Exception('apple')", None, None, diff --git a/src/exceptions.rs b/src/exceptions.rs index 6ff662b4ae4..e6cb906a90f 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -71,8 +71,8 @@ macro_rules! impl_exception_boilerplate { /// import_exception!(socket, gaierror); /// /// Python::with_gil(|py| { -/// let ctx = [("gaierror", py.get_type::())].into_py_dict(py); -/// pyo3::py_run!(py, *ctx, "import socket; assert gaierror is socket.gaierror"); +/// let ctx = [("gaierror", py.get_type::())].into_py_dict_bound(py); +/// pyo3::py_run_bound!(py, *ctx, "import socket; assert gaierror is socket.gaierror"); /// }); /// /// ``` @@ -164,18 +164,18 @@ macro_rules! import_exception { /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction!(raise_myerror, py)?; -/// # let locals = pyo3::types::PyDict::new(py); +/// # let locals = pyo3::types::PyDict::new_bound(py); /// # locals.set_item("MyError", py.get_type::())?; /// # locals.set_item("raise_myerror", fun)?; /// # -/// # py.run( +/// # py.run_bound( /// # "try: /// # raise_myerror() /// # except MyError as e: /// # assert e.__doc__ == 'Some description.' /// # assert str(e) == 'Some error happened.'", /// # None, -/// # Some(locals), +/// # Some(&locals), /// # )?; /// # /// # Ok(()) @@ -337,7 +337,7 @@ use pyo3::prelude::*; use pyo3::exceptions::Py", $name, "; Python::with_gil(|py| { - let result: PyResult<()> = py.run(\"raise ", $name, "\", None, None); + let result: PyResult<()> = py.run_bound(\"raise ", $name, "\", None, None); let error_type = match result { Ok(_) => \"Not an error\", @@ -799,6 +799,8 @@ pub mod socket { #[cfg(test)] mod tests { use super::*; + use crate::types::any::PyAnyMethods; + use crate::types::dict::PyDictMethods; use crate::types::{IntoPyDict, PyDict}; use crate::{PyErr, Python}; @@ -814,7 +816,7 @@ mod tests { .map_err(|e| e.display(py)) .expect("could not import socket"); - let d = PyDict::new(py); + let d = PyDict::new_bound(py); d.set_item("socket", socket) .map_err(|e| e.display(py)) .expect("could not setitem"); @@ -823,7 +825,7 @@ mod tests { .map_err(|e| e.display(py)) .expect("could not setitem"); - py.run("assert isinstance(exc, socket.gaierror)", None, Some(d)) + py.run_bound("assert isinstance(exc, socket.gaierror)", None, Some(&d)) .map_err(|e| e.display(py)) .expect("assertion failed"); }); @@ -838,7 +840,7 @@ mod tests { .map_err(|e| e.display(py)) .expect("could not import email"); - let d = PyDict::new(py); + let d = PyDict::new_bound(py); d.set_item("email", email) .map_err(|e| e.display(py)) .expect("could not setitem"); @@ -846,10 +848,10 @@ mod tests { .map_err(|e| e.display(py)) .expect("could not setitem"); - py.run( + py.run_bound( "assert isinstance(exc, email.errors.MessageError)", None, - Some(d), + Some(&d), ) .map_err(|e| e.display(py)) .expect("assertion failed"); @@ -862,20 +864,20 @@ 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_bound(py); let type_description: String = py - .eval("str(CustomError)", None, Some(ctx)) + .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); - py.run( + py.run_bound( "assert CustomError('oops').args == ('oops',)", None, - Some(ctx), + Some(&ctx), ) .unwrap(); - py.run("assert CustomError.__doc__ is None", None, Some(ctx)) + py.run_bound("assert CustomError.__doc__ is None", None, Some(&ctx)) .unwrap(); }); } @@ -885,9 +887,9 @@ 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_bound(py); let type_description: String = py - .eval("str(CustomError)", None, Some(ctx)) + .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); @@ -904,21 +906,25 @@ 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_bound(py); let type_description: String = py - .eval("str(CustomError)", None, Some(ctx)) + .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); - py.run( + py.run_bound( "assert CustomError('oops').args == ('oops',)", None, - Some(ctx), + Some(&ctx), + ) + .unwrap(); + py.run_bound( + "assert CustomError.__doc__ == 'Some docs'", + None, + Some(&ctx), ) .unwrap(); - py.run("assert CustomError.__doc__ == 'Some docs'", None, Some(ctx)) - .unwrap(); }); } @@ -933,23 +939,23 @@ 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_bound(py); let type_description: String = py - .eval("str(CustomError)", None, Some(ctx)) + .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); - py.run( + py.run_bound( "assert CustomError('oops').args == ('oops',)", None, - Some(ctx), + Some(&ctx), ) .unwrap(); - py.run( + py.run_bound( "assert CustomError.__doc__ == 'Some more docs'", None, - Some(ctx), + Some(&ctx), ) .unwrap(); }); @@ -959,7 +965,7 @@ mod tests { fn native_exception_debug() { Python::with_gil(|py| { let exc = py - .run("raise Exception('banana')", None, None) + .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error") .into_value(py) .into_ref(py); @@ -974,7 +980,7 @@ mod tests { fn native_exception_display() { Python::with_gil(|py| { let exc = py - .run("raise Exception('banana')", None, None) + .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error") .into_value(py) .into_ref(py); @@ -991,7 +997,7 @@ mod tests { Python::with_gil(|py| { let exc = py - .run( + .run_bound( "raise Exception('banana') from TypeError('peach')", None, None, @@ -1076,7 +1082,7 @@ mod tests { PyErr::from_value(PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err).unwrap()) }); test_exception!(PyUnicodeEncodeError, |py| py - .eval("chr(40960).encode('ascii')", None, None) + .eval_bound("chr(40960).encode('ascii')", None, None) .unwrap_err()); test_exception!(PyUnicodeTranslateError, |_| { PyUnicodeTranslateError::new_err(("\u{3042}", 0, 1, "ouch")) diff --git a/src/ffi/tests.rs b/src/ffi/tests.rs index 2cbd84dc6db..984fd536e43 100644 --- a/src/ffi/tests.rs +++ b/src/ffi/tests.rs @@ -1,9 +1,10 @@ use crate::ffi::*; use crate::Python; +use crate::types::any::PyAnyMethods; #[cfg(not(Py_LIMITED_API))] use crate::{ - types::{PyDict, PyString}, + types::{dict::PyDictMethods, PyDict, PyString}, IntoPy, Py, PyAny, }; #[cfg(not(any(Py_3_12, Py_LIMITED_API)))] @@ -19,12 +20,12 @@ fn test_datetime_fromtimestamp() { PyDateTime_IMPORT(); py.from_owned_ptr(PyDateTime_FromTimestamp(args.as_ptr())) }; - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("dt", dt).unwrap(); - py.run( + py.run_bound( "import datetime; assert dt == datetime.datetime.fromtimestamp(100)", None, - Some(locals), + Some(&locals), ) .unwrap(); }) @@ -40,12 +41,12 @@ fn test_date_fromtimestamp() { PyDateTime_IMPORT(); py.from_owned_ptr(PyDate_FromTimestamp(args.as_ptr())) }; - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("dt", dt).unwrap(); - py.run( + py.run_bound( "import datetime; assert dt == datetime.date.fromtimestamp(100)", None, - Some(locals), + Some(&locals), ) .unwrap(); }) @@ -60,12 +61,12 @@ fn test_utc_timezone() { PyDateTime_IMPORT(); py.from_borrowed_ptr(PyDateTime_TimeZone_UTC()) }; - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("utc_timezone", utc_timezone).unwrap(); - py.run( + py.run_bound( "import datetime; assert utc_timezone is datetime.timezone.utc", None, - Some(locals), + Some(&locals), ) .unwrap(); }) @@ -81,7 +82,7 @@ fn test_timezone_from_offset() { Python::with_gil(|py| { let delta = PyDelta::new(py, 0, 100, 0, false).unwrap(); let tz: &PyAny = unsafe { py.from_borrowed_ptr(PyTimeZone_FromOffset(delta.as_ptr())) }; - crate::py_run!( + crate::py_run_bound!( py, tz, "import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100))" @@ -105,7 +106,7 @@ fn test_timezone_from_offset_and_name() { tzname.as_ptr(), )) }; - crate::py_run!( + crate::py_run_bound!( py, tz, "import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100), 'testtz')" @@ -293,7 +294,7 @@ fn test_get_tzinfo() { #[test] fn test_inc_dec_ref() { Python::with_gil(|py| { - let obj = py.eval("object()", None, None).unwrap(); + let obj = py.eval_bound("object()", None, None).unwrap(); let ref_count = obj.get_refcnt(); let ptr = obj.as_ptr(); diff --git a/src/gil.rs b/src/gil.rs index d346ad95ea9..f2bf3e404a0 100644 --- a/src/gil.rs +++ b/src/gil.rs @@ -75,7 +75,7 @@ fn gil_is_acquired() -> bool { /// /// # fn main() -> PyResult<()> { /// pyo3::prepare_freethreaded_python(); -/// Python::with_gil(|py| py.run("print('Hello World')", None, None)) +/// Python::with_gil(|py| py.run_bound("print('Hello World')", None, None)) /// # } /// ``` #[cfg(not(PyPy))] @@ -118,7 +118,7 @@ pub fn prepare_freethreaded_python() { /// ```rust /// unsafe { /// pyo3::with_embedded_python_interpreter(|py| { -/// if let Err(e) = py.run("print('Hello World')", None, None) { +/// if let Err(e) = py.run_bound("print('Hello World')", None, None) { /// // We must make sure to not return a `PyErr`! /// e.print(py); /// } @@ -507,7 +507,7 @@ fn decrement_gil_count() { #[cfg(test)] mod tests { use super::{gil_is_acquired, GILPool, GIL_COUNT, OWNED_OBJECTS, POOL}; - use crate::{ffi, gil, PyObject, Python, ToPyObject}; + use crate::{ffi, gil, types::any::PyAnyMethods, PyObject, Python, ToPyObject}; #[cfg(not(target_arch = "wasm32"))] use parking_lot::{const_mutex, Condvar, Mutex}; use std::ptr::NonNull; @@ -518,7 +518,7 @@ mod tests { let pool = unsafe { py.new_pool() }; let py = pool.python(); - let obj = py.eval("object()", None, None).unwrap(); + let obj = py.eval_bound("object()", None, None).unwrap(); obj.to_object(py) } @@ -735,7 +735,7 @@ mod tests { fn dropping_gil_does_not_invalidate_references() { // Acquiring GIL for the second time should be safe - see #864 Python::with_gil(|py| { - let obj = Python::with_gil(|_| py.eval("object()", None, None).unwrap()); + let obj = Python::with_gil(|_| py.eval_bound("object()", None, None).unwrap()); // After gil2 drops, obj should still have a reference count of one assert_eq!(obj.get_refcnt(), 1); diff --git a/src/impl_/extract_argument.rs b/src/impl_/extract_argument.rs index a18c8d4bc30..71aea0c8446 100644 --- a/src/impl_/extract_argument.rs +++ b/src/impl_/extract_argument.rs @@ -668,7 +668,7 @@ impl<'py> VarkeywordsHandler<'py> for DictVarkeywords { _function_description: &FunctionDescription, ) -> PyResult<()> { varkeywords - .get_or_insert_with(|| PyDict::new(name.py())) + .get_or_insert_with(|| PyDict::new_bound(name.py()).into_gil_ref()) .set_item(name, value) } } @@ -715,7 +715,7 @@ mod tests { Python::with_gil(|py| { let args = PyTuple::new_bound(py, Vec::<&PyAny>::new()); - let kwargs = [("foo", 0u8)].into_py_dict(py); + let kwargs = [("foo", 0u8)].into_py_dict_bound(py); let err = unsafe { function_description .extract_arguments_tuple_dict::( @@ -746,7 +746,7 @@ mod tests { Python::with_gil(|py| { let args = PyTuple::new_bound(py, Vec::<&PyAny>::new()); - let kwargs = [(1u8, 1u8)].into_py_dict(py); + let kwargs = [(1u8, 1u8)].into_py_dict_bound(py); let err = unsafe { function_description .extract_arguments_tuple_dict::( diff --git a/src/instance.rs b/src/instance.rs index 5779e9ada6f..4ca58c89626 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -389,7 +389,7 @@ impl Copy for Borrowed<'_, '_, T> {} /// /// // `&PyDict` derives its lifetime from `py` and /// // so won't be able to outlive this closure. -/// let dict: &PyDict = PyDict::new(py); +/// let dict: &PyDict = PyDict::new_bound(py); /// /// // because `Foo` contains `dict` its lifetime /// // is now also tied to `py`. @@ -418,7 +418,7 @@ impl Copy for Borrowed<'_, '_, T> {} /// #[new] /// fn __new__() -> Foo { /// Python::with_gil(|py| { -/// let dict: Py = PyDict::new(py).into(); +/// let dict: Py = PyDict::new_bound(py).into(); /// Foo { inner: dict } /// }) /// } @@ -490,7 +490,7 @@ impl Copy for Borrowed<'_, '_, T> {} /// /// # fn main() { /// Python::with_gil(|py| { -/// let first: Py = PyDict::new(py).into(); +/// let first: Py = PyDict::new_bound(py).into(); /// /// // All of these are valid syntax /// let second = Py::clone_ref(&first, py); @@ -899,7 +899,7 @@ impl Py { /// /// # fn main() { /// Python::with_gil(|py| { - /// let first: Py = PyDict::new(py).into(); + /// let first: Py = PyDict::new_bound(py).into(); /// let second = Py::clone_ref(&first, py); /// /// // Both point to the same object @@ -1471,7 +1471,7 @@ impl PyObject { /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { - /// let any: PyObject = PyDict::new(py).into(); + /// let any: PyObject = PyDict::new_bound(py).into(); /// /// assert!(any.downcast::(py).is_ok()); /// assert!(any.downcast::(py).is_err()); diff --git a/src/lib.rs b/src/lib.rs index 4802cbc2712..5a40f67a0ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -220,9 +220,9 @@ //! 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_bound(py); //! let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; -//! let user: String = py.eval(code, None, Some(&locals))?.extract()?; +//! let user: String = py.eval_bound(code, None, Some(&locals))?.extract()?; //! //! println!("Hello {}, I'm Python {}", user, version); //! Ok(()) diff --git a/src/macros.rs b/src/macros.rs index 560d43da1ca..00d90c0c4d0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,3 +1,27 @@ +/// Deprecated form of [`py_run_bound`][crate::py_run_bound]. +#[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`py_run` will be replaced by `py_run_bound` in a future PyO3 version" + ) +)] +#[macro_export] +macro_rules! py_run { + ($py:expr, $($val:ident)+, $code:literal) => {{ + $crate::py_run_impl!($py, $($val)+, $crate::indoc::indoc!($code)) + }}; + ($py:expr, $($val:ident)+, $code:expr) => {{ + $crate::py_run_impl!($py, $($val)+, &$crate::unindent::unindent($code)) + }}; + ($py:expr, *$dict:expr, $code:literal) => {{ + $crate::py_run_impl!($py, *$dict.as_borrowed(), $crate::indoc::indoc!($code)) + }}; + ($py:expr, *$dict:expr, $code:expr) => {{ + $crate::py_run_impl!($py, *$dict.as_borrowed(), &$crate::unindent::unindent($code)) + }}; +} + /// A convenient macro to execute a Python code snippet, with some local variables set. /// /// # Panics @@ -9,18 +33,18 @@ /// /// # Examples /// ``` -/// use pyo3::{prelude::*, py_run, types::PyList}; +/// use pyo3::{prelude::*, py_run_bound, types::PyList}; /// /// Python::with_gil(|py| { /// let list = PyList::new(py, &[1, 2, 3]); -/// py_run!(py, list, "assert list == [1, 2, 3]"); +/// py_run_bound!(py, list, "assert list == [1, 2, 3]"); /// }); /// ``` /// /// You can use this macro to test pyfunctions or pyclasses quickly. /// /// ``` -/// use pyo3::{prelude::*, py_run}; +/// use pyo3::{prelude::*, py_run_bound}; /// /// #[pyclass] /// #[derive(Debug)] @@ -47,7 +71,7 @@ /// Python::with_gil(|py| { /// let time = PyCell::new(py, Time {hour: 8, minute: 43, second: 16}).unwrap(); /// let time_as_tuple = (8, 43, 16); -/// py_run!(py, time time_as_tuple, r#" +/// py_run_bound!(py, time time_as_tuple, r#" /// assert time.hour == 8 /// assert time.repl_japanese() == "8時43分16秒" /// assert time.as_tuple() == time_as_tuple @@ -73,12 +97,12 @@ /// } /// /// Python::with_gil(|py| { -/// let locals = [("C", py.get_type::())].into_py_dict(py); -/// pyo3::py_run!(py, *locals, "c = C()"); +/// let locals = [("C", py.get_type::())].into_py_dict_bound(py); +/// pyo3::py_run_bound!(py, *locals, "c = C()"); /// }); /// ``` #[macro_export] -macro_rules! py_run { +macro_rules! py_run_bound { ($py:expr, $($val:ident)+, $code:literal) => {{ $crate::py_run_impl!($py, $($val)+, $crate::indoc::indoc!($code)) }}; @@ -99,17 +123,17 @@ 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_bound($py); $crate::py_run_impl!($py, *d, $code) }}; ($py:expr, *$dict:expr, $code:expr) => {{ use ::std::option::Option::*; - if let ::std::result::Result::Err(e) = $py.run($code, None, Some($dict)) { + if let ::std::result::Result::Err(e) = $py.run_bound($code, None, Some(&$dict)) { e.print($py); // So when this c api function the last line called printed the error to stderr, // the output is only written into a buffer which is never flushed because we // panic before flushing. This is where this hack comes into place - $py.run("import sys; sys.stderr.flush()", None, None) + $py.run_bound("import sys; sys.stderr.flush()", None, None) .unwrap(); ::std::panic!("{}", $code) } diff --git a/src/marker.rs b/src/marker.rs index 97f826e571f..a40440ec413 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -116,14 +116,18 @@ //! [`Rc`]: std::rc::Rc //! [`Py`]: crate::Py use crate::err::{self, PyDowncastError, PyErr, PyResult}; +use crate::ffi_ptr_ext::FfiPtrExt; use crate::gil::{GILGuard, GILPool, SuspendGIL}; use crate::impl_::not_send::NotSend; use crate::type_object::HasPyGilRef; +use crate::types::any::PyAnyMethods; use crate::types::{ PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType, }; use crate::version::PythonVersionInfo; -use crate::{ffi, FromPyPointer, IntoPy, Py, PyObject, PyTypeCheck, PyTypeInfo}; +use crate::{ + ffi, Bound, FromPyPointer, IntoPy, Py, PyNativeType, PyObject, PyTypeCheck, PyTypeInfo, +}; use std::ffi::{CStr, CString}; use std::marker::PhantomData; use std::os::raw::c_int; @@ -357,8 +361,8 @@ pub use nightly::Ungil; /// # fn main () -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// for _ in 0..10 { -/// let hello: &PyString = py.eval("\"Hello World!\"", None, None)?.extract()?; -/// println!("Python says: {}", hello.to_str()?); +/// let hello: Bound<'_, PyString> = py.eval_bound("\"Hello World!\"", None, None)?.downcast_into()?; +/// println!("Python says: {}", hello.to_cow()?); /// // Normally variables in a loop scope are dropped here, but `hello` is a reference to /// // something owned by the Python interpreter. Dropping this reference does nothing. /// } @@ -416,7 +420,7 @@ impl Python<'_> { /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { - /// let x: i32 = py.eval("5", None, None)?.extract()?; + /// let x: i32 = py.eval_bound("5", None, None)?.extract()?; /// assert_eq!(x, 5); /// Ok(()) /// }) @@ -545,6 +549,29 @@ impl<'py> Python<'py> { f() } + /// Deprecated form of [`eval_bound`][Python::eval_bound]. + #[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`eval` will be replaced by `eval_bound` in a future PyO3 version" + ) + )] + #[inline] + pub fn eval( + self, + code: &str, + globals: Option<&PyDict>, + locals: Option<&PyDict>, + ) -> PyResult<&'py PyAny> { + self.eval_bound( + code, + globals.map(PyDict::as_borrowed).as_deref(), + locals.map(PyDict::as_borrowed).as_deref(), + ) + .map(Bound::into_gil_ref) + } + /// Evaluates a Python expression in the given context and returns the result. /// /// If `globals` is `None`, it defaults to Python module `__main__`. @@ -558,18 +585,40 @@ impl<'py> Python<'py> { /// ``` /// # use pyo3::prelude::*; /// # Python::with_gil(|py| { - /// let result = py.eval("[i * 10 for i in range(5)]", None, None).unwrap(); + /// let result = py.eval_bound("[i * 10 for i in range(5)]", None, None).unwrap(); /// let res: Vec = result.extract().unwrap(); /// assert_eq!(res, vec![0, 10, 20, 30, 40]) /// # }); /// ``` - pub fn eval( + pub fn eval_bound( + self, + code: &str, + globals: Option<&Bound<'_, PyDict>>, + locals: Option<&Bound<'_, PyDict>>, + ) -> PyResult> { + self.run_code(code, ffi::Py_eval_input, globals, locals) + } + + /// Deprecated form of [`run_bound`][Python::run_bound]. + #[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`run` will be replaced by `run_bound` in a future PyO3 version" + ) + )] + #[inline] + pub fn run( self, code: &str, globals: Option<&PyDict>, locals: Option<&PyDict>, - ) -> PyResult<&'py PyAny> { - self.run_code(code, ffi::Py_eval_input, globals, locals) + ) -> PyResult<()> { + self.run_bound( + code, + globals.map(PyDict::as_borrowed).as_deref(), + locals.map(PyDict::as_borrowed).as_deref(), + ) } /// Executes one or more Python statements in the given context. @@ -587,30 +636,30 @@ impl<'py> Python<'py> { /// types::{PyBytes, PyDict}, /// }; /// Python::with_gil(|py| { - /// let locals = PyDict::new(py); - /// py.run( + /// let locals = PyDict::new_bound(py); + /// py.run_bound( /// r#" /// import base64 /// s = 'Hello Rust!' /// ret = base64.b64encode(s.encode('utf-8')) /// "#, /// None, - /// Some(locals), + /// Some(&locals), /// ) /// .unwrap(); /// let ret = locals.get_item("ret").unwrap().unwrap(); - /// let b64: &PyBytes = ret.downcast().unwrap(); + /// let b64: &Bound<'_, PyBytes> = ret.downcast().unwrap(); /// assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE="); /// }); /// ``` /// - /// You can use [`py_run!`](macro.py_run.html) for a handy alternative of `run` + /// You can use [`py_run_bound!`](macro.py_run_bound.html) for a handy alternative of `run` /// if you don't need `globals` and unwrapping is OK. - pub fn run( + pub fn run_bound( self, code: &str, - globals: Option<&PyDict>, - locals: Option<&PyDict>, + globals: Option<&Bound<'_, PyDict>>, + locals: Option<&Bound<'_, PyDict>>, ) -> PyResult<()> { let res = self.run_code(code, ffi::Py_file_input, globals, locals); res.map(|obj| { @@ -629,9 +678,9 @@ impl<'py> Python<'py> { self, code: &str, start: c_int, - globals: Option<&PyDict>, - locals: Option<&PyDict>, - ) -> PyResult<&'py PyAny> { + globals: Option<&Bound<'_, PyDict>>, + locals: Option<&Bound<'_, PyDict>>, + ) -> PyResult> { let code = CString::new(code)?; unsafe { let mptr = ffi::PyImport_AddModule("__main__\0".as_ptr() as *const _); @@ -640,9 +689,9 @@ impl<'py> Python<'py> { } let globals = globals - .map(|dict| dict.as_ptr()) + .map(Bound::as_ptr) .unwrap_or_else(|| ffi::PyModule_GetDict(mptr)); - let locals = locals.map(|dict| dict.as_ptr()).unwrap_or(globals); + let locals = locals.map(Bound::as_ptr).unwrap_or(globals); // If `globals` don't provide `__builtins__`, most of the code will fail if Python // version is <3.10. That's probably not what user intended, so insert `__builtins__` @@ -667,14 +716,10 @@ impl<'py> Python<'py> { } } - let code_obj = ffi::Py_CompileString(code.as_ptr(), "\0".as_ptr() as _, start); - if code_obj.is_null() { - return Err(PyErr::fetch(self)); - } - let res_ptr = ffi::PyEval_EvalCode(code_obj, globals, locals); - ffi::Py_DECREF(code_obj); + let code_obj = ffi::Py_CompileString(code.as_ptr(), "\0".as_ptr() as _, start) + .assume_owned_or_err(self)?; - self.from_owned_ptr_or_err(res_ptr) + ffi::PyEval_EvalCode(code_obj.as_ptr(), globals, locals).assume_owned_or_err(self) } } @@ -1065,6 +1110,7 @@ impl<'unbound> Python<'unbound> { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::*; use crate::types::{IntoPyDict, PyDict, PyList}; diff --git a/src/marshal.rs b/src/marshal.rs index 343b861deff..a52d57125f6 100644 --- a/src/marshal.rs +++ b/src/marshal.rs @@ -20,14 +20,14 @@ pub const VERSION: i32 = 4; /// /// # Examples /// ``` -/// # use pyo3::{marshal, types::PyDict}; +/// # use pyo3::{prelude::*, marshal, types::PyDict}; /// # pyo3::Python::with_gil(|py| { -/// let dict = PyDict::new(py); +/// let dict = PyDict::new_bound(py); /// dict.set_item("aap", "noot").unwrap(); /// dict.set_item("mies", "wim").unwrap(); /// dict.set_item("zus", "jet").unwrap(); /// -/// let bytes = marshal::dumps(py, dict, marshal::VERSION); +/// let bytes = marshal::dumps(py, &dict, marshal::VERSION); /// # }); /// ``` pub fn dumps<'a>(py: Python<'a>, object: &impl AsPyPointer, version: i32) -> PyResult<&'a PyBytes> { @@ -51,6 +51,7 @@ where } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::*; use crate::types::PyDict; diff --git a/src/pycell.rs b/src/pycell.rs index bde95ad8313..508f7d65c85 100644 --- a/src/pycell.rs +++ b/src/pycell.rs @@ -641,7 +641,7 @@ impl fmt::Debug for PyCell { /// } /// # Python::with_gil(|py| { /// # let sub = PyCell::new(py, Child::new()).unwrap(); -/// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 3)'"); +/// # pyo3::py_run_bound!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 3)'"); /// # }); /// ``` /// @@ -740,7 +740,7 @@ where /// } /// # Python::with_gil(|py| { /// # let sub = PyCell::new(py, Sub::new()).unwrap(); - /// # pyo3::py_run!(py, sub, "assert sub.name() == 'base1 base2 sub'") + /// # pyo3::py_run_bound!(py, sub, "assert sub.name() == 'base1 base2 sub'") /// # }); /// ``` pub fn into_super(self) -> PyRef<'p, U> { diff --git a/src/pyclass_init.rs b/src/pyclass_init.rs index 63761f435bb..2a18e093b25 100644 --- a/src/pyclass_init.rs +++ b/src/pyclass_init.rs @@ -93,7 +93,7 @@ impl PyObjectInit for PyNativeTypeInitializer { /// /// ``` /// # use pyo3::prelude::*; -/// # use pyo3::py_run; +/// # use pyo3::py_run_bound; /// #[pyclass(subclass)] /// struct BaseClass { /// #[pyo3(get)] @@ -124,7 +124,7 @@ impl PyObjectInit for PyNativeTypeInitializer { /// Python::with_gil(|py| { /// let typeobj = py.get_type::(); /// let sub_sub_class = typeobj.call((), None).unwrap(); -/// py_run!( +/// py_run_bound!( /// py, /// sub_sub_class, /// r#" diff --git a/src/sync.rs b/src/sync.rs index 62843113a8e..49c1ecaedf1 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -209,12 +209,11 @@ impl GILOnceCell> { /// # Example: Using `intern!` to avoid needlessly recreating the same Python string /// /// ``` -/// use pyo3::intern; -/// # use pyo3::{pyfunction, types::PyDict, wrap_pyfunction, PyResult, Python}; +/// use pyo3::{prelude::*, intern, types::PyDict }; /// /// #[pyfunction] -/// fn create_dict(py: Python<'_>) -> PyResult<&PyDict> { -/// let dict = PyDict::new(py); +/// fn create_dict(py: Python<'_>) -> PyResult> { +/// let dict = PyDict::new_bound(py); /// // 👇 A new `PyString` is created /// // for every call of this function. /// dict.set_item("foo", 42)?; @@ -222,8 +221,8 @@ impl GILOnceCell> { /// } /// /// #[pyfunction] -/// fn create_dict_faster(py: Python<'_>) -> PyResult<&PyDict> { -/// let dict = PyDict::new(py); +/// fn create_dict_faster(py: Python<'_>) -> PyResult> { +/// let dict = PyDict::new_bound(py); /// // 👇 A `PyString` is created once and reused /// // for the lifetime of the program. /// dict.set_item(intern!(py, "foo"), 42)?; @@ -270,7 +269,7 @@ impl Interned { mod tests { use super::*; - use crate::types::PyDict; + use crate::types::{any::PyAnyMethods, dict::PyDictMethods, PyDict}; #[test] fn test_intern() { @@ -279,7 +278,7 @@ mod tests { let foo2 = intern!(py, "foo"); let foo3 = intern!(py, stringify!(foo)); - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item(foo1, 42_usize).unwrap(); assert!(dict.contains(foo2).unwrap()); assert_eq!( diff --git a/src/tests/common.rs b/src/tests/common.rs index f2082437693..bae884f8596 100644 --- a/src/tests/common.rs +++ b/src/tests/common.rs @@ -16,10 +16,10 @@ mod inner { #[macro_export] macro_rules! py_assert { ($py:expr, $($val:ident)+, $assertion:literal) => { - pyo3::py_run!($py, $($val)+, concat!("assert ", $assertion)) + pyo3::py_run_bound!($py, $($val)+, concat!("assert ", $assertion)) }; ($py:expr, *$dict:expr, $assertion:literal) => { - pyo3::py_run!($py, *$dict, concat!("assert ", $assertion)) + pyo3::py_run_bound!($py, *$dict, concat!("assert ", $assertion)) }; } @@ -35,12 +35,12 @@ 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_bound($py); py_expect_exception!($py, *d, $code, $err) }}; // Case2: dict & no err_msg ($py:expr, *$dict:expr, $code:expr, $err:ident) => {{ - let res = $py.run($code, None, Some($dict)); + let res = $py.run_bound($code, None, Some(&$dict)); let err = res.expect_err(&format!("Did not raise {}", stringify!($err))); if !err.matches($py, $py.get_type::()) { panic!("Expected {} but got {:?}", stringify!($err), err) @@ -116,8 +116,10 @@ mod inner { impl<'py> CatchWarnings<'py> { pub fn enter(py: Python<'py>, f: impl FnOnce(&PyList) -> PyResult) -> PyResult { let warnings = py.import("warnings")?; - let kwargs = [("record", true)].into_py_dict(py); - let catch_warnings = warnings.getattr("catch_warnings")?.call((), Some(kwargs))?; + let kwargs = [("record", true)].into_py_dict_bound(py); + let catch_warnings = warnings + .getattr("catch_warnings")? + .call((), Some(kwargs.as_gil_ref()))?; let list = catch_warnings.call_method0("__enter__")?.extract()?; let _guard = Self { catch_warnings }; f(list) diff --git a/src/tests/hygiene/pyfunction.rs b/src/tests/hygiene/pyfunction.rs index 19fe2739407..196f5ecca8e 100644 --- a/src/tests/hygiene/pyfunction.rs +++ b/src/tests/hygiene/pyfunction.rs @@ -11,6 +11,6 @@ fn do_something(x: i32) -> crate::PyResult { fn invoke_wrap_pyfunction() { crate::Python::with_gil(|py| { let func = crate::wrap_pyfunction!(do_something)(py).unwrap(); - crate::py_run!(py, func, r#"func(5)"#); + crate::py_run_bound!(py, func, r#"func(5)"#); }); } diff --git a/src/types/any.rs b/src/types/any.rs index 7d36bf45b82..1aa3aecd8da 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -433,9 +433,9 @@ impl PyAny { /// let module = PyModule::from_code(py, CODE, "", "")?; /// let fun = module.getattr("function")?; /// let args = ("hello",); - /// let kwargs = PyDict::new(py); + /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; - /// let result = fun.call(args, Some(kwargs))?; + /// let result = fun.call(args, Some(kwargs.as_gil_ref()))?; /// assert_eq!(result.extract::<&str>()?, "called with args and kwargs"); /// Ok(()) /// }) @@ -533,9 +533,9 @@ impl PyAny { /// let module = PyModule::from_code(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let args = ("hello",); - /// let kwargs = PyDict::new(py); + /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; - /// let result = instance.call_method("method", args, Some(kwargs))?; + /// let result = instance.call_method("method", args, Some(kwargs.as_gil_ref()))?; /// assert_eq!(result.extract::<&str>()?, "called with args and kwargs"); /// Ok(()) /// }) @@ -736,7 +736,7 @@ impl PyAny { /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { - /// let dict = PyDict::new(py); + /// let dict = PyDict::new_bound(py).into_gil_ref(); /// assert!(dict.is_instance_of::()); /// let any: &PyAny = dict.as_ref(); /// @@ -1311,9 +1311,9 @@ pub trait PyAnyMethods<'py> { /// let module = PyModule::from_code(py, CODE, "", "")?; /// let fun = module.getattr("function")?; /// let args = ("hello",); - /// let kwargs = PyDict::new(py); + /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; - /// let result = fun.call(args, Some(kwargs))?; + /// let result = fun.call(args, Some(kwargs.as_gil_ref()))?; /// assert_eq!(result.extract::<&str>()?, "called with args and kwargs"); /// Ok(()) /// }) @@ -1403,9 +1403,9 @@ pub trait PyAnyMethods<'py> { /// let module = PyModule::from_code(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let args = ("hello",); - /// let kwargs = PyDict::new(py); + /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; - /// let result = instance.call_method("method", args, Some(kwargs))?; + /// let result = instance.call_method("method", args, Some(kwargs.as_gil_ref()))?; /// assert_eq!(result.extract::<&str>()?, "called with args and kwargs"); /// Ok(()) /// }) @@ -1562,9 +1562,9 @@ pub trait PyAnyMethods<'py> { /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { - /// let dict = PyDict::new(py); + /// let dict = PyDict::new_bound(py); /// assert!(dict.is_instance_of::()); - /// let any: &PyAny = dict.as_ref(); + /// let any: &Bound<'_, PyAny> = &dict; /// /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast::().is_err()); diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index 2514e987d4d..649529e263c 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -141,10 +141,10 @@ impl PyByteArray { /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction!(a_valid_function, py)?; - /// # let locals = pyo3::types::PyDict::new(py); + /// # let locals = pyo3::types::PyDict::new_bound(py); /// # locals.set_item("a_valid_function", fun)?; /// # - /// # py.run( + /// # py.run_bound( /// # r#"b = bytearray(b"hello world") /// # a_valid_function(b) /// # @@ -153,7 +153,7 @@ impl PyByteArray { /// # except RuntimeError as e: /// # assert str(e) == 'input is not long enough'"#, /// # None, - /// # Some(locals), + /// # Some(&locals), /// # )?; /// # /// # Ok(()) @@ -218,7 +218,7 @@ impl PyByteArray { /// copied_message[11] = b'!'; /// assert_eq!(b"Hello World!", copied_message.as_slice()); /// - /// pyo3::py_run!(py, bytearray, "assert bytearray == b'Hello World.'"); + /// pyo3::py_run_bound!(py, bytearray, "assert bytearray == b'Hello World.'"); /// # }); /// ``` pub fn to_vec(&self) -> Vec { @@ -303,10 +303,10 @@ pub trait PyByteArrayMethods<'py> { /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction!(a_valid_function, py)?; - /// # let locals = pyo3::types::PyDict::new(py); + /// # let locals = pyo3::types::PyDict::new_bound(py); /// # locals.set_item("a_valid_function", fun)?; /// # - /// # py.run( + /// # py.run_bound( /// # r#"b = bytearray(b"hello world") /// # a_valid_function(b) /// # @@ -315,7 +315,7 @@ pub trait PyByteArrayMethods<'py> { /// # except RuntimeError as e: /// # assert str(e) == 'input is not long enough'"#, /// # None, - /// # Some(locals), + /// # Some(&locals), /// # )?; /// # /// # Ok(()) @@ -376,7 +376,7 @@ pub trait PyByteArrayMethods<'py> { /// copied_message[11] = b'!'; /// assert_eq!(b"Hello World!", copied_message.as_slice()); /// - /// pyo3::py_run!(py, bytearray, "assert bytearray == b'Hello World.'"); + /// pyo3::py_run_bound!(py, bytearray, "assert bytearray == b'Hello World.'"); /// # }); /// ``` fn to_vec(&self) -> Vec; diff --git a/src/types/bytes.rs b/src/types/bytes.rs index d9d22dbb173..07065355858 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -171,6 +171,7 @@ impl IntoPy> for Cow<'_, [u8]> { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::*; diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 354414b8b4c..6c6d726565b 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -686,7 +686,7 @@ fn opt_to_pyobj(opt: Option<&PyTzInfo>) -> *mut ffi::PyObject { mod tests { use super::*; #[cfg(feature = "macros")] - use crate::py_run; + use crate::py_run_bound; #[test] #[cfg(feature = "macros")] @@ -694,14 +694,14 @@ mod tests { fn test_datetime_fromtimestamp() { Python::with_gil(|py| { let dt = PyDateTime::from_timestamp(py, 100.0, None).unwrap(); - py_run!( + py_run_bound!( py, dt, "import datetime; assert dt == datetime.datetime.fromtimestamp(100)" ); let dt = PyDateTime::from_timestamp(py, 100.0, Some(timezone_utc(py))).unwrap(); - py_run!( + py_run_bound!( py, dt, "import datetime; assert dt == datetime.datetime.fromtimestamp(100, datetime.timezone.utc)" @@ -715,7 +715,7 @@ mod tests { fn test_date_fromtimestamp() { Python::with_gil(|py| { let dt = PyDate::from_timestamp(py, 100).unwrap(); - py_run!( + py_run_bound!( py, dt, "import datetime; assert dt == datetime.date.fromtimestamp(100)" diff --git a/src/types/dict.rs b/src/types/dict.rs index 0fe48662780..c6faea70dce 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -56,9 +56,36 @@ pyobject_native_type_core!( ); impl PyDict { - /// Creates a new empty dictionary. + /// Deprecated form of [`new_bound`][PyDict::new_bound]. + #[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`PyDict::new` will be replaced by `PyDict::new_bound` in a future PyO3 version" + ) + )] + #[inline] pub fn new(py: Python<'_>) -> &PyDict { - unsafe { py.from_owned_ptr(ffi::PyDict_New()) } + Self::new_bound(py).into_gil_ref() + } + + /// Creates a new empty dictionary. + pub fn new_bound(py: Python<'_>) -> Bound<'_, PyDict> { + unsafe { ffi::PyDict_New().assume_owned(py).downcast_into_unchecked() } + } + + /// Deprecated form of [`from_sequence_bound`][PyDict::from_sequence_bound]. + #[inline] + #[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`PyDict::from_sequence` will be replaced by `PyDict::from_sequence_bound` in a future PyO3 version" + ) + )] + #[cfg(not(PyPy))] + pub fn from_sequence(seq: &PyAny) -> PyResult<&PyDict> { + Self::from_sequence_bound(&seq.as_borrowed()).map(Bound::into_gil_ref) } /// Creates a new dictionary from the sequence given. @@ -69,11 +96,11 @@ impl PyDict { /// Returns an error on invalid input. In the case of key collisions, /// this keeps the last entry seen. #[cfg(not(PyPy))] - pub fn from_sequence(seq: &PyAny) -> PyResult<&PyDict> { + pub fn from_sequence_bound<'py>(seq: &Bound<'py, PyAny>) -> PyResult> { let py = seq.py(); - let dict = Self::new(py); + let dict = Self::new_bound(py); err::error_on_minusone(py, unsafe { - ffi::PyDict_MergeFromSeq2(dict.into_ptr(), seq.into_ptr(), 1) + ffi::PyDict_MergeFromSeq2(dict.as_ptr(), seq.as_ptr(), 1) })?; Ok(dict) } @@ -139,16 +166,16 @@ impl PyDict { /// # fn main() { /// # let _ = /// Python::with_gil(|py| -> PyResult<()> { - /// let dict: &PyDict = [("a", 1)].into_py_dict(py); + /// let dict: Bound<'_, PyDict> = [("a", 1)].into_py_dict_bound(py); /// // `a` is in the dictionary, with value 1 /// assert!(dict.get_item("a")?.map_or(Ok(false), |x| x.eq(1))?); /// // `b` is not in the dictionary /// assert!(dict.get_item("b")?.is_none()); /// // `dict` is not hashable, so this returns an error - /// assert!(dict.get_item(dict).unwrap_err().is_instance_of::(py)); + /// assert!(dict.get_item(&dict).unwrap_err().is_instance_of::(py)); /// /// // `PyAny::get_item("b")` will raise a `KeyError` instead of returning `None` - /// let any: &PyAny = dict.as_ref(); + /// let any: &Bound<'_, PyAny> = &dict; /// assert!(any.get_item("b").unwrap_err().is_instance_of::(py)); /// Ok(()) /// }); @@ -640,7 +667,23 @@ impl<'py> IntoIterator for Bound<'py, PyDict> { pub trait IntoPyDict { /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed /// depends on implementation. - fn into_py_dict(self, py: Python<'_>) -> &PyDict; + #[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`into_py_dict` will be replaced by `into_py_dict_bound` in a future PyO3 version" + ) + )] + fn into_py_dict(self, py: Python<'_>) -> &PyDict + where + Self: Sized, + { + self.into_py_dict_bound(py).into_gil_ref() + } + + /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed + /// depends on implementation. + fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict>; } impl IntoPyDict for I @@ -648,8 +691,8 @@ where T: PyDictItem, I: IntoIterator, { - fn into_py_dict(self, py: Python<'_>) -> &PyDict { - let dict = PyDict::new(py); + fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { + let dict = PyDict::new_bound(py); for item in self { dict.set_item(item.key(), item.value()) .expect("Failed to set_item on dict"); @@ -697,6 +740,7 @@ where } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::*; #[cfg(not(PyPy))] diff --git a/src/types/ellipsis.rs b/src/types/ellipsis.rs index e31f9d4183b..afe285c74c0 100644 --- a/src/types/ellipsis.rs +++ b/src/types/ellipsis.rs @@ -38,6 +38,7 @@ unsafe impl PyTypeInfo for PyEllipsis { #[cfg(test)] mod tests { + use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyEllipsis}; use crate::{PyTypeInfo, Python}; @@ -61,7 +62,7 @@ mod tests { #[test] fn test_dict_is_not_ellipsis() { Python::with_gil(|py| { - assert!(PyDict::new(py).downcast::().is_err()); + assert!(PyDict::new_bound(py).downcast::().is_err()); }) } } diff --git a/src/types/function.rs b/src/types/function.rs index b4492b58c65..02c7b01ac43 100644 --- a/src/types/function.rs +++ b/src/types/function.rs @@ -52,7 +52,7 @@ impl PyCFunction { /// /// ``` /// # use pyo3::prelude::*; - /// # use pyo3::{py_run, types::{PyCFunction, PyDict, PyTuple}}; + /// # use pyo3::{py_run_bound, types::{PyCFunction, PyDict, PyTuple}}; /// /// Python::with_gil(|py| { /// let add_one = |args: &PyTuple, _kwargs: Option<&PyDict>| -> PyResult<_> { @@ -60,7 +60,7 @@ impl PyCFunction { /// Ok(i+1) /// }; /// let add_one = PyCFunction::new_closure(py, None, None, add_one).unwrap(); - /// py_run!(py, add_one, "assert add_one(42) == 43"); + /// py_run_bound!(py, add_one, "assert add_one(42) == 43"); /// }); /// ``` pub fn new_closure<'a, F, R>( diff --git a/src/types/iterator.rs b/src/types/iterator.rs index 67866348f8c..51f49ef1417 100644 --- a/src/types/iterator.rs +++ b/src/types/iterator.rs @@ -14,10 +14,10 @@ use crate::{ /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { -/// let list = py.eval("iter([1, 2, 3, 4])", None, None)?; +/// let list = py.eval_bound("iter([1, 2, 3, 4])", None, None)?; /// let numbers: PyResult> = list /// .iter()? -/// .map(|i| i.and_then(PyAny::extract::)) +/// .map(|i| i.and_then(|any| any.extract::())) /// .collect(); /// let sum: usize = numbers?.iter().sum(); /// assert_eq!(sum, 10); @@ -135,6 +135,7 @@ impl<'v> crate::PyTryFrom<'v> for PyIterator { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::PyIterator; use crate::exceptions::PyTypeError; @@ -276,7 +277,7 @@ def fibonacci(target): // Regression test for 2913 Python::with_gil(|py| { let downcaster = Py::new(py, Downcaster { failed: None }).unwrap(); - crate::py_run!( + crate::py_run_bound!( py, downcaster, r#" @@ -314,7 +315,7 @@ def fibonacci(target): // Regression test for 2913 Python::with_gil(|py| { let assert_iterator = crate::wrap_pyfunction!(assert_iterator, py).unwrap(); - crate::py_run!( + crate::py_run_bound!( py, assert_iterator, r#" diff --git a/src/types/list.rs b/src/types/list.rs index f8db0e62ee6..858e6879948 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -667,6 +667,7 @@ impl<'py> IntoIterator for Bound<'py, PyList> { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use crate::types::{PyList, PyTuple}; use crate::Python; diff --git a/src/types/mod.rs b/src/types/mod.rs index 00fe81cf37e..ce6c1bc8d57 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -59,7 +59,7 @@ pub use self::typeobject::PyType; /// /// # pub fn main() -> PyResult<()> { /// Python::with_gil(|py| { -/// let dict: &PyDict = py.eval("{'a':'b', 'c':'d'}", None, None)?.downcast()?; +/// let dict: Bound<'_, PyDict> = py.eval_bound("{'a':'b', 'c':'d'}", None, None)?.downcast_into::()?; /// /// for (key, value) in dict { /// println!("key: {}, value: {}", key, value); diff --git a/src/types/none.rs b/src/types/none.rs index 19ee80ede57..6d03e3763d6 100644 --- a/src/types/none.rs +++ b/src/types/none.rs @@ -52,6 +52,7 @@ impl IntoPy for () { #[cfg(test)] mod tests { + use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyNone}; use crate::{IntoPy, PyObject, PyTypeInfo, Python, ToPyObject}; @@ -95,7 +96,7 @@ mod tests { #[test] fn test_dict_is_not_none() { Python::with_gil(|py| { - assert!(PyDict::new(py).downcast::().is_err()); + assert!(PyDict::new_bound(py).downcast::().is_err()); }) } } diff --git a/src/types/notimplemented.rs b/src/types/notimplemented.rs index 0c61fd79bee..646968b9879 100644 --- a/src/types/notimplemented.rs +++ b/src/types/notimplemented.rs @@ -37,6 +37,7 @@ unsafe impl PyTypeInfo for PyNotImplemented { #[cfg(test)] mod tests { + use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyNotImplemented}; use crate::{PyTypeInfo, Python}; @@ -60,7 +61,9 @@ mod tests { #[test] fn test_dict_is_not_notimplemented() { Python::with_gil(|py| { - assert!(PyDict::new(py).downcast::().is_err()); + assert!(PyDict::new_bound(py) + .downcast::() + .is_err()); }) } } diff --git a/src/types/sequence.rs b/src/types/sequence.rs index fa15fe06858..64e8f316c74 100644 --- a/src/types/sequence.rs +++ b/src/types/sequence.rs @@ -566,6 +566,7 @@ impl<'v> crate::PyTryFrom<'v> for PySequence { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use crate::types::{PyList, PySequence, PyTuple}; use crate::{PyObject, Python, ToPyObject}; diff --git a/src/types/set.rs b/src/types/set.rs index be65500b4fe..efbc220d3cf 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -399,6 +399,7 @@ pub(crate) fn new_from_iter( } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::PySet; use crate::{Python, ToPyObject}; diff --git a/src/types/string.rs b/src/types/string.rs index 0ee64be53f9..f9544541191 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -452,6 +452,7 @@ impl IntoPy> for &'_ Py { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::*; use crate::Python; diff --git a/src/types/traceback.rs b/src/types/traceback.rs index b9909435976..30430496b05 100644 --- a/src/types/traceback.rs +++ b/src/types/traceback.rs @@ -28,7 +28,7 @@ impl PyTraceback { /// # let result: PyResult<()> = /// Python::with_gil(|py| { /// let err = py - /// .run("raise Exception('banana')", None, None) + /// .run_bound("raise Exception('banana')", None, None) /// .expect_err("raise will create a Python error"); /// /// let traceback = err.traceback(py).expect("raised exception will have a traceback"); @@ -64,6 +64,7 @@ impl PyTraceback { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use crate::{prelude::*, types::PyDict}; diff --git a/tests/test_anyhow.rs b/tests/test_anyhow.rs index f0df4dcc1a4..57b0db1a598 100644 --- a/tests/test_anyhow.rs +++ b/tests/test_anyhow.rs @@ -1,8 +1,10 @@ #![cfg(feature = "anyhow")] +use pyo3::prelude::PyDictMethods; + #[test] fn test_anyhow_py_function_ok_result() { - use pyo3::{py_run, pyfunction, wrap_pyfunction, Python}; + use pyo3::{py_run_bound, pyfunction, wrap_pyfunction, Python}; #[pyfunction] #[allow(clippy::unnecessary_wraps)] @@ -13,7 +15,7 @@ fn test_anyhow_py_function_ok_result() { Python::with_gil(|py| { let func = wrap_pyfunction!(produce_ok_result)(py).unwrap(); - py_run!( + py_run_bound!( py, func, r#" @@ -34,15 +36,15 @@ fn test_anyhow_py_function_err_result() { Python::with_gil(|py| { let func = wrap_pyfunction!(produce_err_result)(py).unwrap(); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("func", func).unwrap(); - py.run( + py.run_bound( r#" func() "#, None, - Some(locals), + Some(&locals), ) .unwrap_err(); }); diff --git a/tests/test_append_to_inittab.rs b/tests/test_append_to_inittab.rs index e0a57da1b5c..00cccdbb49e 100644 --- a/tests/test_append_to_inittab.rs +++ b/tests/test_append_to_inittab.rs @@ -18,7 +18,7 @@ fn test_module_append_to_inittab() { use pyo3::append_to_inittab; append_to_inittab!(module_with_functions); Python::with_gil(|py| { - py.run( + py.run_bound( r#" import module_with_functions assert module_with_functions.foo() == 123 diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index 456d21a3b62..885831ef3be 100644 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -2,7 +2,7 @@ use pyo3::class::basic::CompareOp; use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; #[path = "../src/tests/common.rs"] mod common; @@ -44,11 +44,11 @@ impl UnaryArithmetic { fn unary_arithmetic() { Python::with_gil(|py| { let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap(); - py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'"); - py_run!(py, c, "assert repr(+c) == 'UA(2.7)'"); - py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'"); - py_run!(py, c, "assert repr(round(c)) == 'UA(3)'"); - py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'"); + py_run_bound!(py, c, "assert repr(-c) == 'UA(-2.7)'"); + py_run_bound!(py, c, "assert repr(+c) == 'UA(2.7)'"); + py_run_bound!(py, c, "assert repr(abs(c)) == 'UA(2.7)'"); + py_run_bound!(py, c, "assert repr(round(c)) == 'UA(3)'"); + py_run_bound!(py, c, "assert repr(round(c, 1)) == 'UA(3)'"); }); } @@ -78,10 +78,10 @@ impl Indexable { fn indexable() { Python::with_gil(|py| { let i = PyCell::new(py, Indexable(5)).unwrap(); - py_run!(py, i, "assert int(i) == 5"); - py_run!(py, i, "assert [0, 1, 2, 3, 4, 5][i] == 5"); - py_run!(py, i, "assert float(i) == 5.0"); - py_run!(py, i, "assert int(~i) == -6"); + py_run_bound!(py, i, "assert int(i) == 5"); + py_run_bound!(py, i, "assert [0, 1, 2, 3, 4, 5][i] == 5"); + py_run_bound!(py, i, "assert float(i) == 5.0"); + py_run_bound!(py, i, "assert int(~i) == -6"); }) } @@ -138,7 +138,7 @@ fn inplace_operations() { Python::with_gil(|py| { let init = |value, code| { let c = PyCell::new(py, InPlaceOperations { value }).unwrap(); - py_run!(py, c, code); + py_run_bound!(py, c, code); }; init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'"); @@ -211,17 +211,17 @@ impl BinaryArithmetic { fn binary_arithmetic() { Python::with_gil(|py| { let c = PyCell::new(py, BinaryArithmetic {}).unwrap(); - py_run!(py, c, "assert c + c == 'BA + BA'"); - py_run!(py, c, "assert c.__add__(c) == 'BA + BA'"); - py_run!(py, c, "assert c + 1 == 'BA + 1'"); - py_run!(py, c, "assert c - 1 == 'BA - 1'"); - py_run!(py, c, "assert c * 1 == 'BA * 1'"); - py_run!(py, c, "assert c << 1 == 'BA << 1'"); - py_run!(py, c, "assert c >> 1 == 'BA >> 1'"); - py_run!(py, c, "assert c & 1 == 'BA & 1'"); - py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'"); - py_run!(py, c, "assert c | 1 == 'BA | 1'"); - py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'"); + py_run_bound!(py, c, "assert c + c == 'BA + BA'"); + py_run_bound!(py, c, "assert c.__add__(c) == 'BA + BA'"); + py_run_bound!(py, c, "assert c + 1 == 'BA + 1'"); + py_run_bound!(py, c, "assert c - 1 == 'BA - 1'"); + py_run_bound!(py, c, "assert c * 1 == 'BA * 1'"); + py_run_bound!(py, c, "assert c << 1 == 'BA << 1'"); + py_run_bound!(py, c, "assert c >> 1 == 'BA >> 1'"); + py_run_bound!(py, c, "assert c & 1 == 'BA & 1'"); + py_run_bound!(py, c, "assert c ^ 1 == 'BA ^ 1'"); + py_run_bound!(py, c, "assert c | 1 == 'BA | 1'"); + py_run_bound!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'"); // Class with __add__ only should not allow the reverse op; // this is consistent with Python classes. @@ -236,7 +236,7 @@ fn binary_arithmetic() { py_expect_exception!(py, c, "1 | c", PyTypeError); py_expect_exception!(py, c, "1 ** c", PyTypeError); - py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'"); + py_run_bound!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'"); let c: Bound<'_, PyAny> = c.extract().unwrap(); assert_py_eq!(c.add(&c).unwrap(), "BA + BA"); @@ -298,24 +298,24 @@ impl RhsArithmetic { fn rhs_arithmetic() { Python::with_gil(|py| { let c = PyCell::new(py, RhsArithmetic {}).unwrap(); - py_run!(py, c, "assert c.__radd__(1) == '1 + RA'"); - py_run!(py, c, "assert 1 + c == '1 + RA'"); - py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'"); - py_run!(py, c, "assert 1 - c == '1 - RA'"); - py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'"); - py_run!(py, c, "assert 1 * c == '1 * RA'"); - py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'"); - py_run!(py, c, "assert 1 << c == '1 << RA'"); - py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'"); - py_run!(py, c, "assert 1 >> c == '1 >> RA'"); - py_run!(py, c, "assert c.__rand__(1) == '1 & RA'"); - py_run!(py, c, "assert 1 & c == '1 & RA'"); - py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'"); - py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); - py_run!(py, c, "assert c.__ror__(1) == '1 | RA'"); - py_run!(py, c, "assert 1 | c == '1 | RA'"); - py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'"); - py_run!(py, c, "assert 1 ** c == '1 ** RA'"); + py_run_bound!(py, c, "assert c.__radd__(1) == '1 + RA'"); + py_run_bound!(py, c, "assert 1 + c == '1 + RA'"); + py_run_bound!(py, c, "assert c.__rsub__(1) == '1 - RA'"); + py_run_bound!(py, c, "assert 1 - c == '1 - RA'"); + py_run_bound!(py, c, "assert c.__rmul__(1) == '1 * RA'"); + py_run_bound!(py, c, "assert 1 * c == '1 * RA'"); + py_run_bound!(py, c, "assert c.__rlshift__(1) == '1 << RA'"); + py_run_bound!(py, c, "assert 1 << c == '1 << RA'"); + py_run_bound!(py, c, "assert c.__rrshift__(1) == '1 >> RA'"); + py_run_bound!(py, c, "assert 1 >> c == '1 >> RA'"); + py_run_bound!(py, c, "assert c.__rand__(1) == '1 & RA'"); + py_run_bound!(py, c, "assert 1 & c == '1 & RA'"); + py_run_bound!(py, c, "assert c.__rxor__(1) == '1 ^ RA'"); + py_run_bound!(py, c, "assert 1 ^ c == '1 ^ RA'"); + py_run_bound!(py, c, "assert c.__ror__(1) == '1 | RA'"); + py_run_bound!(py, c, "assert 1 | c == '1 | RA'"); + py_run_bound!(py, c, "assert c.__rpow__(1) == '1 ** RA'"); + py_run_bound!(py, c, "assert 1 ** c == '1 ** RA'"); }); } @@ -428,27 +428,27 @@ fn lhs_fellback_to_rhs() { Python::with_gil(|py| { let c = PyCell::new(py, LhsAndRhs {}).unwrap(); // If the light hand value is `LhsAndRhs`, LHS is used. - py_run!(py, c, "assert c + 1 == 'LR + 1'"); - py_run!(py, c, "assert c - 1 == 'LR - 1'"); - py_run!(py, c, "assert c * 1 == 'LR * 1'"); - py_run!(py, c, "assert c << 1 == 'LR << 1'"); - py_run!(py, c, "assert c >> 1 == 'LR >> 1'"); - py_run!(py, c, "assert c & 1 == 'LR & 1'"); - py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'"); - py_run!(py, c, "assert c | 1 == 'LR | 1'"); - py_run!(py, c, "assert c ** 1 == 'LR ** 1'"); - py_run!(py, c, "assert c @ 1 == 'LR @ 1'"); + py_run_bound!(py, c, "assert c + 1 == 'LR + 1'"); + py_run_bound!(py, c, "assert c - 1 == 'LR - 1'"); + py_run_bound!(py, c, "assert c * 1 == 'LR * 1'"); + py_run_bound!(py, c, "assert c << 1 == 'LR << 1'"); + py_run_bound!(py, c, "assert c >> 1 == 'LR >> 1'"); + py_run_bound!(py, c, "assert c & 1 == 'LR & 1'"); + py_run_bound!(py, c, "assert c ^ 1 == 'LR ^ 1'"); + py_run_bound!(py, c, "assert c | 1 == 'LR | 1'"); + py_run_bound!(py, c, "assert c ** 1 == 'LR ** 1'"); + py_run_bound!(py, c, "assert c @ 1 == 'LR @ 1'"); // Fellback to RHS because of type mismatching - py_run!(py, c, "assert 1 + c == '1 + RA'"); - py_run!(py, c, "assert 1 - c == '1 - RA'"); - py_run!(py, c, "assert 1 * c == '1 * RA'"); - py_run!(py, c, "assert 1 << c == '1 << RA'"); - py_run!(py, c, "assert 1 >> c == '1 >> RA'"); - py_run!(py, c, "assert 1 & c == '1 & RA'"); - py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); - py_run!(py, c, "assert 1 | c == '1 | RA'"); - py_run!(py, c, "assert 1 ** c == '1 ** RA'"); - py_run!(py, c, "assert 1 @ c == '1 @ RA'"); + py_run_bound!(py, c, "assert 1 + c == '1 + RA'"); + py_run_bound!(py, c, "assert 1 - c == '1 - RA'"); + py_run_bound!(py, c, "assert 1 * c == '1 * RA'"); + py_run_bound!(py, c, "assert 1 << c == '1 << RA'"); + py_run_bound!(py, c, "assert 1 >> c == '1 >> RA'"); + py_run_bound!(py, c, "assert 1 & c == '1 & RA'"); + py_run_bound!(py, c, "assert 1 ^ c == '1 ^ RA'"); + py_run_bound!(py, c, "assert 1 | c == '1 | RA'"); + py_run_bound!(py, c, "assert 1 ** c == '1 ** RA'"); + py_run_bound!(py, c, "assert 1 @ c == '1 @ RA'"); }); } @@ -495,24 +495,24 @@ impl RichComparisons2 { fn rich_comparisons() { Python::with_gil(|py| { let c = PyCell::new(py, RichComparisons {}).unwrap(); - py_run!(py, c, "assert (c < c) == 'RC < RC'"); - py_run!(py, c, "assert (c < 1) == 'RC < 1'"); - py_run!(py, c, "assert (1 < c) == 'RC > 1'"); - py_run!(py, c, "assert (c <= c) == 'RC <= RC'"); - py_run!(py, c, "assert (c <= 1) == 'RC <= 1'"); - py_run!(py, c, "assert (1 <= c) == 'RC >= 1'"); - py_run!(py, c, "assert (c == c) == 'RC == RC'"); - py_run!(py, c, "assert (c == 1) == 'RC == 1'"); - py_run!(py, c, "assert (1 == c) == 'RC == 1'"); - py_run!(py, c, "assert (c != c) == 'RC != RC'"); - py_run!(py, c, "assert (c != 1) == 'RC != 1'"); - py_run!(py, c, "assert (1 != c) == 'RC != 1'"); - py_run!(py, c, "assert (c > c) == 'RC > RC'"); - py_run!(py, c, "assert (c > 1) == 'RC > 1'"); - py_run!(py, c, "assert (1 > c) == 'RC < 1'"); - py_run!(py, c, "assert (c >= c) == 'RC >= RC'"); - py_run!(py, c, "assert (c >= 1) == 'RC >= 1'"); - py_run!(py, c, "assert (1 >= c) == 'RC <= 1'"); + py_run_bound!(py, c, "assert (c < c) == 'RC < RC'"); + py_run_bound!(py, c, "assert (c < 1) == 'RC < 1'"); + py_run_bound!(py, c, "assert (1 < c) == 'RC > 1'"); + py_run_bound!(py, c, "assert (c <= c) == 'RC <= RC'"); + py_run_bound!(py, c, "assert (c <= 1) == 'RC <= 1'"); + py_run_bound!(py, c, "assert (1 <= c) == 'RC >= 1'"); + py_run_bound!(py, c, "assert (c == c) == 'RC == RC'"); + py_run_bound!(py, c, "assert (c == 1) == 'RC == 1'"); + py_run_bound!(py, c, "assert (1 == c) == 'RC == 1'"); + py_run_bound!(py, c, "assert (c != c) == 'RC != RC'"); + py_run_bound!(py, c, "assert (c != 1) == 'RC != 1'"); + py_run_bound!(py, c, "assert (1 != c) == 'RC != 1'"); + py_run_bound!(py, c, "assert (c > c) == 'RC > RC'"); + py_run_bound!(py, c, "assert (c > 1) == 'RC > 1'"); + py_run_bound!(py, c, "assert (1 > c) == 'RC < 1'"); + py_run_bound!(py, c, "assert (c >= c) == 'RC >= RC'"); + py_run_bound!(py, c, "assert (c >= 1) == 'RC >= 1'"); + py_run_bound!(py, c, "assert (1 >= c) == 'RC <= 1'"); }); } @@ -526,12 +526,12 @@ fn rich_comparisons_python_3_type_error() { py_expect_exception!(py, c2, "c2 <= c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= 1", PyTypeError); py_expect_exception!(py, c2, "1 <= c2", PyTypeError); - py_run!(py, c2, "assert (c2 == c2) == True"); - py_run!(py, c2, "assert (c2 == 1) == True"); - py_run!(py, c2, "assert (1 == c2) == True"); - py_run!(py, c2, "assert (c2 != c2) == False"); - py_run!(py, c2, "assert (c2 != 1) == False"); - py_run!(py, c2, "assert (1 != c2) == False"); + py_run_bound!(py, c2, "assert (c2 == c2) == True"); + py_run_bound!(py, c2, "assert (c2 == 1) == True"); + py_run_bound!(py, c2, "assert (1 == c2) == True"); + py_run_bound!(py, c2, "assert (c2 != c2) == False"); + py_run_bound!(py, c2, "assert (c2 != 1) == False"); + py_run_bound!(py, c2, "assert (1 != c2) == False"); py_expect_exception!(py, c2, "c2 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 > 1", PyTypeError); py_expect_exception!(py, c2, "1 > c2", PyTypeError); @@ -621,7 +621,7 @@ mod return_not_implemented { fn _test_binary_dunder(dunder: &str) { Python::with_gil(|py| { let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap(); - py_run!( + py_run_bound!( py, c2, &format!( diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index 4d5dc69f942..876a1219e14 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_bound(py); 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())].into_py_dict(py); + let env = [("ob", instance.clone())].into_py_dict_bound(py); assert!(capture.borrow(py).capture.is_none()); diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs index bbf37a2d66b..af8fe16de7d 100644 --- a/tests/test_class_basics.rs +++ b/tests/test_class_basics.rs @@ -2,7 +2,7 @@ use pyo3::prelude::*; use pyo3::types::PyType; -use pyo3::{py_run, PyClass}; +use pyo3::{py_run_bound, PyClass}; #[path = "../src/tests/common.rs"] mod common; @@ -59,22 +59,22 @@ struct ClassWithDocs { fn class_with_docstr() { Python::with_gil(|py| { let typeobj = py.get_type::(); - py_run!( + py_run_bound!( py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'" ); - py_run!( + py_run_bound!( py, typeobj, "assert typeobj.value.__doc__ == 'Property field'" ); - py_run!( + py_run_bound!( py, typeobj, "assert typeobj.readonly.__doc__ == 'Read-only property field'" ); - py_run!( + py_run_bound!( py, typeobj, "assert typeobj.writeonly.__doc__ == 'Write-only property field'" @@ -314,7 +314,7 @@ fn test_pymethods_from_py_with() { Python::with_gil(|py| { let instance = Py::new(py, ClassWithFromPyWithMethods {}).unwrap(); - py_run!( + py_run_bound!( py, instance, r#" @@ -340,7 +340,7 @@ fn test_tuple_struct_class() { py_assert!(py, typeobj, "typeobj.__name__ == 'TupleClass'"); let instance = Py::new(py, TupleClass(5)).unwrap(); - py_run!( + py_run_bound!( py, instance, r#" @@ -371,7 +371,7 @@ fn dunder_dict_support() { }, ) .unwrap(); - py_run!( + py_run_bound!( py, inst, r#" @@ -394,7 +394,7 @@ fn access_dunder_dict() { }, ) .unwrap(); - py_run!( + py_run_bound!( py, inst, r#" @@ -425,7 +425,7 @@ fn inherited_dict() { ), ) .unwrap(); - py_run!( + py_run_bound!( py, inst, r#" @@ -453,7 +453,7 @@ fn weakref_dunder_dict_support() { }, ) .unwrap(); - py_run!( + py_run_bound!( py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" @@ -477,7 +477,7 @@ fn weakref_support() { }, ) .unwrap(); - py_run!( + py_run_bound!( py, inst, "import weakref; assert weakref.ref(inst)() is inst" @@ -505,7 +505,7 @@ fn inherited_weakref() { ), ) .unwrap(); - py_run!( + py_run_bound!( py, inst, "import weakref; assert weakref.ref(inst)() is inst" diff --git a/tests/test_class_new.rs b/tests/test_class_new.rs index 8cb426861db..9cff7e8368e 100644 --- a/tests/test_class_new.rs +++ b/tests/test_class_new.rs @@ -29,7 +29,10 @@ 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_bound(py).as_gil_ref()) + ) .is_err()); }); } @@ -169,9 +172,12 @@ c = Class() assert c.from_rust is False "# ); - let globals = PyModule::import(py, "__main__").unwrap().dict(); + let globals = PyModule::import(py, "__main__") + .unwrap() + .as_borrowed() + .dict(); globals.set_item("SuperClass", super_cls).unwrap(); - py.run(source, Some(globals), None) + py.run_bound(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); diff --git a/tests/test_coroutine.rs b/tests/test_coroutine.rs index 206c35da93c..d06f40ca025 100644 --- a/tests/test_coroutine.rs +++ b/tests/test_coroutine.rs @@ -6,7 +6,7 @@ use futures::{channel::oneshot, future::poll_fn, FutureExt}; use pyo3::{ coroutine::CancelHandle, prelude::*, - py_run, + py_run_bound, types::{IntoPyDict, PyType}, }; @@ -31,7 +31,7 @@ fn noop_coroutine() { Python::with_gil(|gil| { let noop = wrap_pyfunction!(noop, gil).unwrap(); let test = "import asyncio; assert asyncio.run(noop()) == 42"; - py_run!(gil, noop, &handle_windows(test)); + py_run_bound!(gil, noop, &handle_windows(test)); }) } @@ -68,8 +68,8 @@ fn test_coroutine_qualname() { ("my_fn", wrap_pyfunction!(my_fn, gil).unwrap().deref()), ("MyClass", gil.get_type::()), ] - .into_py_dict(gil); - py_run!(gil, *locals, &handle_windows(test)); + .into_py_dict_bound(gil); + py_run_bound!(gil, *&locals, &handle_windows(test)); }) } @@ -91,7 +91,7 @@ fn sleep_0_like_coroutine() { Python::with_gil(|gil| { let sleep_0 = wrap_pyfunction!(sleep_0, gil).unwrap(); let test = "import asyncio; assert asyncio.run(sleep_0()) == 42"; - py_run!(gil, sleep_0, &handle_windows(test)); + py_run_bound!(gil, sleep_0, &handle_windows(test)); }) } @@ -110,7 +110,7 @@ fn sleep_coroutine() { Python::with_gil(|gil| { let sleep = wrap_pyfunction!(sleep, gil).unwrap(); let test = r#"import asyncio; assert asyncio.run(sleep(0.1)) == 42"#; - py_run!(gil, sleep, &handle_windows(test)); + py_run_bound!(gil, sleep, &handle_windows(test)); }) } @@ -130,9 +130,9 @@ fn cancelled_coroutine() { let globals = gil.import("__main__").unwrap().dict(); globals.set_item("sleep", sleep).unwrap(); let err = gil - .run( + .run_bound( &pyo3::unindent::unindent(&handle_windows(test)), - Some(globals), + Some(&globals.as_borrowed()), None, ) .unwrap_err(); @@ -170,9 +170,9 @@ fn coroutine_cancel_handle() { globals .set_item("cancellable_sleep", cancellable_sleep) .unwrap(); - gil.run( + gil.run_bound( &pyo3::unindent::unindent(&handle_windows(test)), - Some(globals), + Some(&globals.as_borrowed()), None, ) .unwrap(); @@ -200,9 +200,9 @@ fn coroutine_is_cancelled() { "#; let globals = gil.import("__main__").unwrap().dict(); globals.set_item("sleep_loop", sleep_loop).unwrap(); - gil.run( + gil.run_bound( &pyo3::unindent::unindent(&handle_windows(test)), - Some(globals), + Some(&globals.as_borrowed()), None, ) .unwrap(); @@ -234,7 +234,7 @@ fn coroutine_panic() { else: assert False; "#; - py_run!(gil, panic, &handle_windows(test)); + py_run_bound!(gil, panic, &handle_windows(test)); }) } @@ -259,7 +259,7 @@ fn test_async_method_receiver() { Python::with_gil(|gil| { let test = r#" import asyncio - + obj = Counter() coro1 = obj.get() coro2 = obj.get() @@ -286,7 +286,7 @@ fn test_async_method_receiver() { assert False assert asyncio.run(coro3) == 1 "#; - let locals = [("Counter", gil.get_type::())].into_py_dict(gil); - py_run!(gil, *locals, test); + let locals = [("Counter", gil.get_type::())].into_py_dict_bound(gil); + py_run_bound!(gil, *locals, test); }) } diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index 32163abe1e0..5d7b1485260 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -4,31 +4,31 @@ use pyo3::prelude::*; use pyo3::types::{timezone_utc, IntoPyDict, PyDate, PyDateTime, PyTime}; use pyo3_ffi::PyDateTime_IMPORT; -fn _get_subclasses<'p>( - py: Python<'p>, +fn _get_subclasses<'py>( + py: Python<'py>, py_type: &str, args: &str, -) -> PyResult<(&'p PyAny, &'p PyAny, &'p PyAny)> { +) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>, Bound<'py, PyAny>)> { // 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_bound(py); let make_subclass_py = format!("class Subklass({}):\n pass", py_type); let make_sub_subclass_py = "class SubSubklass(Subklass):\n pass"; - py.run(&make_subclass_py, None, Some(locals))?; - py.run(make_sub_subclass_py, None, Some(locals))?; + py.run_bound(&make_subclass_py, None, Some(&locals))?; + py.run_bound(make_sub_subclass_py, None, Some(&locals))?; // Construct an instance of the base class - let obj = py.eval(&format!("{}({})", py_type, args), None, Some(locals))?; + let obj = py.eval_bound(&format!("{}({})", py_type, args), None, Some(&locals))?; // Construct an instance of the subclass - let sub_obj = py.eval(&format!("Subklass({})", args), None, Some(locals))?; + let sub_obj = py.eval_bound(&format!("Subklass({})", args), None, Some(&locals))?; // Construct an instance of the sub-subclass - let sub_sub_obj = py.eval(&format!("SubSubklass({})", args), None, Some(locals))?; + let sub_sub_obj = py.eval_bound(&format!("SubSubklass({})", args), None, Some(&locals))?; Ok((obj, sub_obj, sub_sub_obj)) } @@ -122,10 +122,10 @@ 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_bound(py); let offset: f32 = py - .eval("dt.utcoffset().total_seconds()", None, Some(locals)) + .eval_bound("dt.utcoffset().total_seconds()", None, Some(&locals)) .unwrap() .extract() .unwrap(); diff --git a/tests/test_dict_iter.rs b/tests/test_dict_iter.rs index dc32eb61fd7..e502a4ca2b6 100644 --- a/tests/test_dict_iter.rs +++ b/tests/test_dict_iter.rs @@ -6,7 +6,7 @@ use pyo3::types::IntoPyDict; fn iter_dict_nosegv() { Python::with_gil(|py| { const LEN: usize = 10_000_000; - let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); + let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); let mut sum = 0; for (k, _v) in dict { let i: u64 = k.extract().unwrap(); diff --git a/tests/test_enum.rs b/tests/test_enum.rs index 33e94c241c7..83f2170bf96 100644 --- a/tests/test_enum.rs +++ b/tests/test_enum.rs @@ -1,7 +1,7 @@ #![cfg(feature = "macros")] use pyo3::prelude::*; -use pyo3::{py_run, wrap_pyfunction}; +use pyo3::{py_run_bound, wrap_pyfunction}; #[path = "../src/tests/common.rs"] mod common; @@ -33,7 +33,7 @@ fn test_return_enum() { let f = wrap_pyfunction!(return_enum)(py).unwrap(); let mynum = py.get_type::(); - py_run!(py, f mynum, "assert f() == mynum.Variant") + py_run_bound!(py, f mynum, "assert f() == mynum.Variant") }); } @@ -48,7 +48,7 @@ fn test_enum_arg() { let f = wrap_pyfunction!(enum_arg)(py).unwrap(); let mynum = py.get_type::(); - py_run!(py, f mynum, "f(mynum.OtherVariant)") + py_run_bound!(py, f mynum, "f(mynum.OtherVariant)") }) } @@ -86,7 +86,7 @@ fn test_custom_discriminant() { let CustomDiscriminant = py.get_type::(); let one = Py::new(py, CustomDiscriminant::One).unwrap(); let two = Py::new(py, CustomDiscriminant::Two).unwrap(); - py_run!(py, CustomDiscriminant one two, r#" + py_run_bound!(py, CustomDiscriminant one two, r#" assert CustomDiscriminant.One == one assert CustomDiscriminant.Two == two assert one != two @@ -101,7 +101,7 @@ fn test_enum_to_int() { py_assert!(py, one, "int(one) == 1"); let v = Py::new(py, MyEnum::Variant).unwrap(); let v_value = MyEnum::Variant as isize; - py_run!(py, v v_value, "int(v) == v_value"); + py_run_bound!(py, v v_value, "int(v) == v_value"); }) } @@ -109,7 +109,7 @@ fn test_enum_to_int() { fn test_enum_compare_int() { Python::with_gil(|py| { let one = Py::new(py, CustomDiscriminant::One).unwrap(); - py_run!( + py_run_bound!( py, one, r#" diff --git a/tests/test_exceptions.rs b/tests/test_exceptions.rs index b783e887dcd..fb0b22998be 100644 --- a/tests/test_exceptions.rs +++ b/tests/test_exceptions.rs @@ -1,7 +1,7 @@ #![cfg(feature = "macros")] use pyo3::prelude::*; -use pyo3::{exceptions, py_run, PyErr, PyResult}; +use pyo3::{exceptions, py_run_bound, PyErr, PyResult}; use std::error::Error; use std::fmt; #[cfg(not(target_os = "windows"))] @@ -24,7 +24,7 @@ fn test_filenotfounderror() { Python::with_gil(|py| { let fail_to_open_file = wrap_pyfunction!(fail_to_open_file)(py).unwrap(); - py_run!( + py_run_bound!( py, fail_to_open_file, r#" @@ -70,7 +70,7 @@ fn test_custom_error() { let call_fail_with_custom_error = wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap(); - py_run!( + py_run_bound!( py, call_fail_with_custom_error, r#" diff --git a/tests/test_frompyobject.rs b/tests/test_frompyobject.rs index 30edf6f7836..4c12899f867 100644 --- a/tests/test_frompyobject.rs +++ b/tests/test_frompyobject.rs @@ -365,17 +365,17 @@ fn test_enum() { _ => panic!("Expected extracting Foo::StructVarGetAttrArg, got {:?}", f), } - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item("a", "test").expect("Failed to set item"); - let f = Foo::extract(dict.as_ref()).expect("Failed to extract Foo from dict"); + let f = Foo::extract(dict.into_gil_ref()).expect("Failed to extract Foo from dict"); match f { Foo::StructWithGetItem { a } => assert_eq!(a, "test"), _ => panic!("Expected extracting Foo::StructWithGetItem, got {:?}", f), } - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item("foo", "test").expect("Failed to set item"); - let f = Foo::extract(dict.as_ref()).expect("Failed to extract Foo from dict"); + let f = Foo::extract(dict.into_gil_ref()).expect("Failed to extract Foo from dict"); match f { Foo::StructWithGetItemArg { a } => assert_eq!(a, "test"), _ => panic!("Expected extracting Foo::StructWithGetItemArg, got {:?}", f), @@ -386,8 +386,8 @@ fn test_enum() { #[test] fn test_enum_error() { Python::with_gil(|py| { - let dict = PyDict::new(py); - let err = Foo::extract(dict.as_ref()).unwrap_err(); + let dict = PyDict::new_bound(py); + let err = Foo::extract(dict.into_gil_ref()).unwrap_err(); assert_eq!( err.to_string(), "\ @@ -429,8 +429,8 @@ enum EnumWithCatchAll<'a> { #[test] fn test_enum_catch_all() { Python::with_gil(|py| { - let dict = PyDict::new(py); - let f = EnumWithCatchAll::extract(dict.as_ref()) + let dict = PyDict::new_bound(py); + let f = EnumWithCatchAll::extract(dict.into_gil_ref()) .expect("Failed to extract EnumWithCatchAll from dict"); match f { EnumWithCatchAll::CatchAll(any) => { @@ -458,8 +458,8 @@ pub enum Bar { #[test] fn test_err_rename() { Python::with_gil(|py| { - let dict = PyDict::new(py); - let f = Bar::extract(dict.as_ref()); + let dict = PyDict::new_bound(py); + let f = Bar::extract(dict.into_gil_ref()); assert!(f.is_err()); assert_eq!( f.unwrap_err().to_string(), @@ -485,14 +485,14 @@ pub struct Zap { fn test_from_py_with() { Python::with_gil(|py| { let py_zap = py - .eval( + .eval_bound( r#"{"name": "whatever", "my_object": [1, 2, 3]}"#, None, None, ) .expect("failed to create dict"); - let zap = Zap::extract(py_zap).unwrap(); + let zap = Zap::extract(py_zap.into_gil_ref()).unwrap(); assert_eq!(zap.name, "whatever"); assert_eq!(zap.some_object_length, 3usize); @@ -506,10 +506,10 @@ pub struct ZapTuple(String, #[pyo3(from_py_with = "PyAny::len")] usize); fn test_from_py_with_tuple_struct() { Python::with_gil(|py| { let py_zap = py - .eval(r#"("whatever", [1, 2, 3])"#, None, None) + .eval_bound(r#"("whatever", [1, 2, 3])"#, None, None) .expect("failed to create tuple"); - let zap = ZapTuple::extract(py_zap).unwrap(); + let zap = ZapTuple::extract(py_zap.into_gil_ref()).unwrap(); assert_eq!(zap.0, "whatever"); assert_eq!(zap.1, 3usize); @@ -520,10 +520,10 @@ fn test_from_py_with_tuple_struct() { fn test_from_py_with_tuple_struct_error() { Python::with_gil(|py| { let py_zap = py - .eval(r#"("whatever", [1, 2, 3], "third")"#, None, None) + .eval_bound(r#"("whatever", [1, 2, 3], "third")"#, None, None) .expect("failed to create tuple"); - let f = ZapTuple::extract(py_zap); + let f = ZapTuple::extract(py_zap.into_gil_ref()); assert!(f.is_err()); assert_eq!( @@ -543,10 +543,10 @@ pub enum ZapEnum { fn test_from_py_with_enum() { Python::with_gil(|py| { let py_zap = py - .eval(r#"("whatever", [1, 2, 3])"#, None, None) + .eval_bound(r#"("whatever", [1, 2, 3])"#, None, None) .expect("failed to create tuple"); - let zap = ZapEnum::extract(py_zap).unwrap(); + let zap = ZapEnum::extract(py_zap.into_gil_ref()).unwrap(); let expected_zap = ZapEnum::Zip(2); assert_eq!(zap, expected_zap); diff --git a/tests/test_gc.rs b/tests/test_gc.rs index 54c3e1a100c..252d3009a49 100644 --- a/tests/test_gc.rs +++ b/tests/test_gc.rs @@ -3,7 +3,7 @@ use pyo3::class::PyTraverseError; use pyo3::class::PyVisit; use pyo3::prelude::*; -use pyo3::{py_run, PyCell}; +use pyo3::{py_run_bound, PyCell}; use std::cell::Cell; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -113,11 +113,11 @@ fn gc_integration() { let mut borrow = inst.borrow_mut(); borrow.self_ref = inst.to_object(py); - py_run!(py, inst, "import gc; assert inst in gc.get_objects()"); + py_run_bound!(py, inst, "import gc; assert inst in gc.get_objects()"); }); Python::with_gil(|py| { - py.run("import gc; gc.collect()", None, None).unwrap(); + py.run_bound("import gc; gc.collect()", None, None).unwrap(); assert!(drop_called.load(Ordering::Relaxed)); }); } @@ -156,7 +156,7 @@ fn gc_null_traversal() { obj.borrow_mut(py).cycle = Some(obj.clone_ref(py)); // the object doesn't have to be cleaned up, it just needs to be traversed. - py.run("import gc; gc.collect()", None, None).unwrap(); + py.run_bound("import gc; gc.collect()", None, None).unwrap(); }); } @@ -473,7 +473,7 @@ fn drop_during_traversal_with_gil() { // (but not too many) collections to get `inst` actually dropped. for _ in 0..10 { Python::with_gil(|py| { - py.run("import gc; gc.collect()", None, None).unwrap(); + py.run_bound("import gc; gc.collect()", None, None).unwrap(); }); } assert!(drop_called.load(Ordering::Relaxed)); @@ -506,7 +506,7 @@ fn drop_during_traversal_without_gil() { // (but not too many) collections to get `inst` actually dropped. for _ in 0..10 { Python::with_gil(|py| { - py.run("import gc; gc.collect()", None, None).unwrap(); + py.run_bound("import gc; gc.collect()", None, None).unwrap(); }); } assert!(drop_called.load(Ordering::Relaxed)); diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rs index f16ce61166a..c7cc0051908 100644 --- a/tests/test_getter_setter.rs +++ b/tests/test_getter_setter.rs @@ -3,7 +3,7 @@ use std::cell::Cell; use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; use pyo3::types::{IntoPyDict, PyList}; #[path = "../src/tests/common.rs"] @@ -52,19 +52,19 @@ fn class_with_properties() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap(); - py_run!(py, inst, "assert inst.get_num() == 10"); - py_run!(py, inst, "assert inst.get_num() == inst.DATA"); - py_run!(py, inst, "inst.DATA = 20"); - py_run!(py, inst, "assert inst.get_num() == 20 == inst.DATA"); + py_run_bound!(py, inst, "assert inst.get_num() == 10"); + py_run_bound!(py, inst, "assert inst.get_num() == inst.DATA"); + py_run_bound!(py, inst, "inst.DATA = 20"); + py_run_bound!(py, inst, "assert inst.get_num() == 20 == inst.DATA"); py_expect_exception!(py, inst, "del inst.DATA", PyAttributeError); - py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 20"); - py_run!(py, inst, "inst.unwrapped = 42"); - py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 42"); - py_run!(py, inst, "assert inst.data_list == [42]"); + py_run_bound!(py, inst, "assert inst.get_num() == inst.unwrapped == 20"); + py_run_bound!(py, inst, "inst.unwrapped = 42"); + py_run_bound!(py, inst, "assert inst.get_num() == inst.unwrapped == 42"); + py_run_bound!(py, inst, "assert inst.data_list == [42]"); - let d = [("C", py.get_type::())].into_py_dict(py); + let d = [("C", py.get_type::())].into_py_dict_bound(py); py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'"); }); } @@ -96,9 +96,9 @@ fn getter_setter_autogen() { ) .unwrap(); - py_run!(py, inst, "assert inst.num == 10"); - py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); - py_run!( + py_run_bound!(py, inst, "assert inst.num == 10"); + py_run_bound!(py, inst, "inst.num = 20; assert inst.num == 20"); + py_run_bound!( py, inst, "assert inst.text == 'Hello'; inst.text = 'There'; assert inst.text == 'There'" @@ -130,8 +130,8 @@ fn ref_getter_setter() { Python::with_gil(|py| { let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap(); - py_run!(py, inst, "assert inst.num == 10"); - py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); + py_run_bound!(py, inst, "assert inst.num == 10"); + py_run_bound!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } @@ -157,7 +157,7 @@ fn tuple_struct_getter_setter() { let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap(); py_assert!(py, inst, "inst.num == 10"); - py_run!(py, inst, "inst.num = 20"); + py_run_bound!(py, inst, "inst.num = 20"); py_assert!(py, inst, "inst.num == 20"); }); } @@ -172,8 +172,8 @@ fn get_set_all() { Python::with_gil(|py| { let inst = Py::new(py, All { num: 10 }).unwrap(); - py_run!(py, inst, "assert inst.num == 10"); - py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); + py_run_bound!(py, inst, "assert inst.num == 10"); + py_run_bound!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } @@ -188,8 +188,8 @@ fn get_all_and_set() { Python::with_gil(|py| { let inst = Py::new(py, All2 { num: 10 }).unwrap(); - py_run!(py, inst, "assert inst.num == 10"); - py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); + py_run_bound!(py, inst, "assert inst.num == 10"); + py_run_bound!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } @@ -208,9 +208,9 @@ fn cell_getter_setter() { let inst = Py::new(py, c).unwrap().to_object(py); let cell = Cell::new(20).to_object(py); - py_run!(py, cell, "assert cell == 20"); - py_run!(py, inst, "assert inst.cell_inner == 10"); - py_run!( + py_run_bound!(py, cell, "assert cell == 20"); + py_run_bound!(py, inst, "assert inst.cell_inner == 10"); + py_run_bound!( py, inst, "inst.cell_inner = 20; assert inst.cell_inner == 20" @@ -234,6 +234,6 @@ fn borrowed_value_with_lifetime_of_self() { Python::with_gil(|py| { let inst = Py::new(py, BorrowedValue {}).unwrap().to_object(py); - py_run!(py, inst, "assert inst.value == 'value'"); + py_run_bound!(py, inst, "assert inst.value == 'value'"); }); } diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index d1cfe628ef6..a8aaadb1c90 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -1,7 +1,7 @@ #![cfg(feature = "macros")] use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; use pyo3::types::IntoPyDict; @@ -20,12 +20,12 @@ 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_bound(py); - py.run( + py.run_bound( "class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)", None, - Some(d), + Some(&d), ) .map_err(|e| e.display(py)) .unwrap(); @@ -74,7 +74,7 @@ fn inheritance_with_new_methods() { Python::with_gil(|py| { let typeobj = py.get_type::(); let inst = typeobj.call((), None).unwrap(); - py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5"); + py_run_bound!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5"); }); } @@ -82,7 +82,7 @@ fn inheritance_with_new_methods() { fn call_base_and_sub_methods() { Python::with_gil(|py| { let obj = PyCell::new(py, SubClass::new()).unwrap(); - py_run!( + py_run_bound!( py, obj, r#" @@ -97,9 +97,13 @@ fn call_base_and_sub_methods() { fn mutation_fails() { Python::with_gil(|py| { let obj = PyCell::new(py, SubClass::new()).unwrap(); - let global = Some([("obj", obj)].into_py_dict(py)); + let global = Some([("obj", obj)].into_py_dict_bound(py)); let e = py - .run("obj.base_set(lambda: obj.sub_set_and_ret(1))", global, None) + .run_bound( + "obj.base_set(lambda: obj.sub_set_and_ret(1))", + global.as_ref(), + None, + ) .unwrap_err(); assert_eq!(&e.to_string(), "RuntimeError: Already borrowed"); }); @@ -152,7 +156,7 @@ impl SubClass2 { fn handle_result_in_new() { Python::with_gil(|py| { let subclass = py.get_type::(); - py_run!( + py_run_bound!( py, subclass, r#" @@ -199,7 +203,7 @@ mod inheriting_native_type { Python::with_gil(|py| { let set_sub = pyo3::PyCell::new(py, SetWithName::new()).unwrap(); - py_run!( + py_run_bound!( py, set_sub, r#"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == "Hello :)""# @@ -226,7 +230,7 @@ mod inheriting_native_type { fn inherit_dict() { Python::with_gil(|py| { let dict_sub = pyo3::PyCell::new(py, DictWithName::new()).unwrap(); - py_run!( + py_run_bound!( py, dict_sub, r#"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == "Hello :)""# @@ -240,10 +244,10 @@ mod inheriting_native_type { let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap(); assert_eq!(dict_sub.get_refcnt(py), 1); - let item = py.eval("object()", None, None).unwrap(); + let item = py.eval_bound("object()", None, None).unwrap(); assert_eq!(item.get_refcnt(), 1); - dict_sub.as_ref(py).set_item("foo", item).unwrap(); + dict_sub.as_ref(py).set_item("foo", &item).unwrap(); assert_eq!(item.get_refcnt(), 2); drop(dict_sub); @@ -271,17 +275,17 @@ 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 res = py.run( + let dict = [("cls", cls)].into_py_dict_bound(py); + let res = py.run_bound( "e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e", None, - Some(dict) + Some(&dict) ); let err = res.unwrap_err(); assert!(err.matches(py, cls), "{}", err); // catching the exception in Python also works: - py_run!( + py_run_bound!( py, cls, r#" @@ -312,7 +316,7 @@ fn test_subclass_ref_counts() { Python::with_gil(|py| { #[allow(non_snake_case)] let SimpleClass = py.get_type::(); - py_run!( + py_run_bound!( py, SimpleClass, r#" diff --git a/tests/test_macro_docs.rs b/tests/test_macro_docs.rs index 964e762886d..5e240816cd2 100644 --- a/tests/test_macro_docs.rs +++ b/tests/test_macro_docs.rs @@ -23,7 +23,7 @@ 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_bound(py); py_assert!( py, *d, diff --git a/tests/test_mapping.rs b/tests/test_mapping.rs index c029ce27c50..c5e00fb2981 100644 --- a/tests/test_mapping.rs +++ b/tests/test_mapping.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use pyo3::exceptions::PyKeyError; use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; use pyo3::types::IntoPyDict; use pyo3::types::PyList; use pyo3::types::PyMapping; @@ -68,9 +68,9 @@ impl Mapping { } /// Return a dict with `m = Mapping(['1', '2', '3'])`. -fn map_dict(py: Python<'_>) -> &pyo3::types::PyDict { - let d = [("Mapping", py.get_type::())].into_py_dict(py); - py_run!(py, *d, "m = Mapping(['1', '2', '3'])"); +fn map_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { + let d = [("Mapping", py.get_type::())].into_py_dict_bound(py); + py_run_bound!(py, *d, "m = Mapping(['1', '2', '3'])"); d } @@ -91,8 +91,8 @@ fn test_setitem() { Python::with_gil(|py| { let d = map_dict(py); - py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4"); - py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0"); + py_run_bound!(py, *d, "m['1'] = 4; assert m['1'] == 4"); + py_run_bound!(py, *d, "m['0'] = 0; assert m['0'] == 0"); py_assert!(py, *d, "len(m) == 4"); py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError); py_expect_exception!(py, *d, "m[0] = -1", PyTypeError); @@ -103,7 +103,7 @@ fn test_setitem() { fn test_delitem() { Python::with_gil(|py| { let d = map_dict(py); - py_run!( + py_run_bound!( py, *d, "del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2" diff --git a/tests/test_methods.rs b/tests/test_methods.rs index 6e42ad66960..a9e85df1188 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -1,7 +1,7 @@ #![cfg(feature = "macros")] use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType}; use pyo3::PyCell; @@ -89,7 +89,7 @@ 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_bound(py); py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'"); py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'"); py_assert!( @@ -116,7 +116,7 @@ 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_bound(py); py_assert!( py, *d, @@ -147,7 +147,7 @@ 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_bound(py); 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.'"); @@ -171,7 +171,7 @@ 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_bound(py); py_assert!(py, *d, "C.method(1337) == '0x539'"); }); } @@ -324,56 +324,56 @@ fn meth_signature() { Python::with_gil(|py| { let inst = Py::new(py, MethSignature {}).unwrap(); - py_run!(py, inst, "assert inst.get_optional() == 10"); - py_run!(py, inst, "assert inst.get_optional(100) == 100"); - py_run!(py, inst, "assert inst.get_optional2() == None"); - py_run!(py, inst, "assert inst.get_optional2(100) == 100"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_optional() == 10"); + py_run_bound!(py, inst, "assert inst.get_optional(100) == 100"); + py_run_bound!(py, inst, "assert inst.get_optional2() == None"); + py_run_bound!(py, inst, "assert inst.get_optional2(100) == 100"); + py_run_bound!( py, inst, "assert inst.get_optional_positional(1, 2, 3) == 2" ); - py_run!(py, inst, "assert inst.get_optional_positional(1) == None"); - py_run!(py, inst, "assert inst.get_default() == 10"); - py_run!(py, inst, "assert inst.get_default(100) == 100"); - py_run!(py, inst, "assert inst.get_kwarg() == 10"); + py_run_bound!(py, inst, "assert inst.get_optional_positional(1) == None"); + py_run_bound!(py, inst, "assert inst.get_default() == 10"); + py_run_bound!(py, inst, "assert inst.get_default(100) == 100"); + py_run_bound!(py, inst, "assert inst.get_kwarg() == 10"); py_expect_exception!(py, inst, "inst.get_kwarg(100)", PyTypeError); - py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100"); - py_run!(py, inst, "assert inst.get_kwargs() == [(), None]"); - py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_kwarg(test=100) == 100"); + py_run_bound!(py, inst, "assert inst.get_kwargs() == [(), None]"); + py_run_bound!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); + py_run_bound!( py, inst, "assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]" ); - py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]"); + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]" ); - py_run!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]"); + py_run_bound!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]"); py_expect_exception!(py, inst, "inst.get_pos_arg_kw()", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", PyTypeError); - py_run!(py, inst, "assert inst.get_pos_only(10, 11) == 21"); + py_run_bound!(py, inst, "assert inst.get_pos_only(10, 11) == 21"); py_expect_exception!(py, inst, "inst.get_pos_only(10, b = 11)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_only(a = 10, b = 11)", PyTypeError); - py_run!(py, inst, "assert inst.get_pos_only_and_pos(10, 11) == 21"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_pos_only_and_pos(10, 11) == 21"); + py_run_bound!( py, inst, "assert inst.get_pos_only_and_pos(10, b = 11) == 21" @@ -385,22 +385,22 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21" @@ -412,7 +412,7 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_kw_only(10, b = 11) == 21" @@ -430,12 +430,12 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_kw_only_with_default(10) == 13" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21" @@ -453,17 +453,17 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_all_arg_types_together(10, 10, c = 10) == 35" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40" @@ -481,13 +481,13 @@ fn meth_signature() { PyTypeError ); - py_run!(py, inst, "assert inst.get_pos_only_with_varargs(10) == 10"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_pos_only_with_varargs(10) == 10"); + py_run_bound!( py, inst, "assert inst.get_pos_only_with_varargs(10, 10) == 20" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50" @@ -499,17 +499,17 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_with_kwargs(10) == [10, None]" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_only_with_kwargs(10, b = 10, c = 10, d = 10, e = 10) == [10, {'b': 10, 'c': 10, 'd': 10, 'e': 10}]" @@ -527,58 +527,58 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_optional_pos_only_with_kwargs() == [0, None]" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_optional_pos_only_with_kwargs(10) == [10, None]" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_optional_pos_only_with_kwargs(a=10) == [0, {'a': 10}]" ); - py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5"); + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_defaults(a = 8) == 11" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_defaults(b = 8) == 10" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2" ); - py_run!(py, inst, "assert inst.get_kwargs_only(a = 1, b = 1) == 2"); - py_run!(py, inst, "assert inst.get_kwargs_only(b = 1, a = 1) == 2"); + py_run_bound!(py, inst, "assert inst.get_kwargs_only(a = 1, b = 1) == 2"); + py_run_bound!(py, inst, "assert inst.get_kwargs_only(b = 1, a = 1) == 2"); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_some_default(b = 1) == 2" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3" @@ -590,12 +590,12 @@ fn meth_signature() { PyTypeError ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_args_and_required_keyword(a=1) == ((), 1)" @@ -607,42 +607,42 @@ fn meth_signature() { PyTypeError ); - py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1) == 6"); - py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2) == 6"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_pos_arg_kw_sep1(1) == 6"); + py_run_bound!(py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2) == 6"); + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16" ); - py_run!( + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw_sep1(c=13, b=2, a=1) == 16" ); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep1(1, 2, 3)", PyTypeError); - py_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6"); - py_run!( + py_run_bound!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6"); + py_run_bound!( py, inst, "assert inst.get_pos_arg_kw_sep2(1, b=12, c=13) == 26" ); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep2(1, 2)", PyTypeError); - py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]"); + py_run_bound!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]"); py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", PyTypeError); - py_run!(py, inst, "assert inst.args_as_vec(1,2,3) == 6"); + py_run_bound!(py, inst, "assert inst.args_as_vec(1,2,3) == 6"); }); } @@ -669,7 +669,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_bound(py); py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'"); py_assert!( py, @@ -704,7 +704,7 @@ impl MethodWithLifeTime { fn method_with_lifetime() { Python::with_gil(|py| { let obj = PyCell::new(py, MethodWithLifeTime {}).unwrap(); - py_run!( + py_run_bound!( py, obj, "assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]" @@ -753,27 +753,27 @@ fn method_with_pyclassarg() { Python::with_gil(|py| { let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let obj2 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); - let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py); - 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"); - py_run!( + let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict_bound(py); + py_run_bound!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20"); + py_run_bound!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20"); + py_run_bound!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20"); + py_run_bound!( py, *d, "obj = obj1.optional_add(obj2); assert obj.value == 20" ); - py_run!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20"); - py_run!( + py_run_bound!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20"); + py_run_bound!( py, *d, "obj1.inplace_add_pyref(obj2); assert obj2.value == 30" ); - py_run!( + py_run_bound!( py, *d, "obj1.optional_inplace_add(); assert obj2.value == 30" ); - py_run!( + py_run_bound!( py, *d, "obj1.optional_inplace_add(obj2); assert obj2.value == 40" @@ -938,7 +938,7 @@ fn test_raw_idents() { Python::with_gil(|py| { let raw_idents_type = py.get_type::(); assert_eq!(raw_idents_type.qualname().unwrap(), "RawIdents"); - py_run!( + py_run_bound!( py, raw_idents_type, r#" diff --git a/tests/test_module.rs b/tests/test_module.rs index 2de23b38324..7a476b73b5a 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -2,7 +2,7 @@ use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; use pyo3::types::{IntoPyDict, PyDict, PyTuple}; #[path = "../src/tests/common.rs"] @@ -74,7 +74,7 @@ fn test_module_with_functions() { "module_with_functions", wrap_pymodule!(module_with_functions)(py), )] - .into_py_dict(py); + .into_py_dict_bound(py); py_assert!( py, @@ -127,9 +127,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_bound(py); - py_run!(py, *d, "assert different_name.__name__ == 'other_name'"); + py_run_bound!(py, *d, "assert different_name.__name__ == 'other_name'"); }); } diff --git a/tests/test_no_imports.rs b/tests/test_no_imports.rs index 4f04282702e..86b9d0f2916 100644 --- a/tests/test_no_imports.rs +++ b/tests/test_no_imports.rs @@ -90,7 +90,7 @@ fn test_basic() { pyo3::Python::with_gil(|py| { let module = pyo3::wrap_pymodule!(basic_module)(py); let cls = py.get_type::(); - let d = pyo3::types::IntoPyDict::into_py_dict( + let d = pyo3::types::IntoPyDict::into_py_dict_bound( [ ("mod", module.as_ref(py).as_ref()), ("cls", cls.as_ref()), @@ -100,25 +100,25 @@ fn test_basic() { py, ); - pyo3::py_run!(py, *d, "assert mod.answer() == 42"); - pyo3::py_run!(py, *d, "assert mod.identity() is None"); - pyo3::py_run!(py, *d, "v = object(); assert mod.identity(v) is v"); - pyo3::py_run!(py, *d, "assert cls.OKAY"); - pyo3::py_run!(py, *d, "assert (a.v, a.s) == (8, '')"); - pyo3::py_run!(py, *d, "assert (b.v, b.s) == (0, 'foo')"); - pyo3::py_run!(py, *d, "b.property = 314"); - pyo3::py_run!(py, *d, "assert b.property == 300"); - pyo3::py_run!( + pyo3::py_run_bound!(py, *d, "assert mod.answer() == 42"); + pyo3::py_run_bound!(py, *d, "assert mod.identity() is None"); + pyo3::py_run_bound!(py, *d, "v = object(); assert mod.identity(v) is v"); + pyo3::py_run_bound!(py, *d, "assert cls.OKAY"); + pyo3::py_run_bound!(py, *d, "assert (a.v, a.s) == (8, '')"); + pyo3::py_run_bound!(py, *d, "assert (b.v, b.s) == (0, 'foo')"); + pyo3::py_run_bound!(py, *d, "b.property = 314"); + pyo3::py_run_bound!(py, *d, "assert b.property == 300"); + pyo3::py_run_bound!( py, *d, "assert cls.classmethod.__doc__ == 'Some documentation here'" ); - pyo3::py_run!(py, *d, "assert cls.classmethod() is cls"); - pyo3::py_run!(py, *d, "assert cls.staticmethod(5) == '5'"); - pyo3::py_run!(py, *d, "a.s = 'bar'; assert a.s == 'bar'"); - pyo3::py_run!(py, *d, "a.mutate(); assert (a.v, a.s) == (16, 'bar!')"); - pyo3::py_run!(py, *d, "assert a + 9 == 25"); - pyo3::py_run!(py, *d, "b += a; assert (b.v, b.s) == (19, 'foobar!')"); + pyo3::py_run_bound!(py, *d, "assert cls.classmethod() is cls"); + pyo3::py_run_bound!(py, *d, "assert cls.staticmethod(5) == '5'"); + pyo3::py_run_bound!(py, *d, "a.s = 'bar'; assert a.s == 'bar'"); + pyo3::py_run_bound!(py, *d, "a.mutate(); assert (a.v, a.s) == (16, 'bar!')"); + pyo3::py_run_bound!(py, *d, "assert a + 9 == 25"); + pyo3::py_run_bound!(py, *d, "b += a; assert (b.v, b.s) == (19, 'foobar!')"); }); } @@ -141,6 +141,6 @@ impl NewClassMethod { fn test_new_class_method() { pyo3::Python::with_gil(|py| { let cls = py.get_type::(); - pyo3::py_run!(py, cls, "assert cls().cls is cls"); + pyo3::py_run_bound!(py, cls, "assert cls().cls is cls"); }); } diff --git a/tests/test_proto_methods.rs b/tests/test_proto_methods.rs index caaae751354..768abfebe28 100644 --- a/tests/test_proto_methods.rs +++ b/tests/test_proto_methods.rs @@ -2,7 +2,7 @@ use pyo3::exceptions::{PyAttributeError, PyIndexError, PyValueError}; use pyo3::types::{PyDict, PyList, PyMapping, PySequence, PySlice, PyType}; -use pyo3::{prelude::*, py_run, PyCell}; +use pyo3::{prelude::*, py_run_bound, PyCell}; use std::{isize, iter}; #[path = "../src/tests/common.rs"] @@ -216,7 +216,7 @@ fn mapping() { let inst = Py::new( py, Mapping { - values: PyDict::new(py).into(), + values: PyDict::new_bound(py).into(), }, ) .unwrap(); @@ -225,9 +225,9 @@ fn mapping() { py_assert!(py, inst, "len(inst) == 0"); - py_run!(py, inst, "inst['foo'] = 'foo'"); + py_run_bound!(py, inst, "inst['foo'] = 'foo'"); py_assert!(py, inst, "inst['foo'] == 'foo'"); - py_run!(py, inst, "del inst['foo']"); + py_run_bound!(py, inst, "del inst['foo']"); py_expect_exception!(py, inst, "inst['foo']", PyKeyError); // Default iteration will call __getitem__ with integer indices @@ -328,7 +328,7 @@ fn sequence() { py_assert!(py, inst, "len(inst) == 0"); py_expect_exception!(py, inst, "inst[0]", PyIndexError); - py_run!(py, inst, "inst.append('foo')"); + py_run_bound!(py, inst, "inst.append('foo')"); py_assert!(py, inst, "inst[0] == 'foo'"); py_assert!(py, inst, "inst[-1] == 'foo'"); @@ -338,7 +338,7 @@ fn sequence() { py_assert!(py, inst, "[*inst] == ['foo']"); - py_run!(py, inst, "del inst[0]"); + py_run_bound!(py, inst, "del inst[0]"); py_expect_exception!(py, inst, "inst['foo']", PyTypeError); @@ -352,7 +352,7 @@ fn sequence() { // however regular python len() works thanks to mp_len slot assert_eq!(inst.as_ref(py).len().unwrap(), 0); - py_run!(py, inst, "inst.append(0)"); + py_run_bound!(py, inst, "inst.append(0)"); sequence.set_item(0, 5).unwrap(); assert_eq!(inst.as_ref(py).len().unwrap(), 1); @@ -438,7 +438,7 @@ impl SetItem { fn setitem() { Python::with_gil(|py| { let c = PyCell::new(py, SetItem { key: 0, val: 0 }).unwrap(); - py_run!(py, c, "c[1] = 2"); + py_run_bound!(py, c, "c[1] = 2"); { let c = c.borrow(); assert_eq!(c.key, 1); @@ -464,7 +464,7 @@ impl DelItem { fn delitem() { Python::with_gil(|py| { let c = PyCell::new(py, DelItem { key: 0 }).unwrap(); - py_run!(py, c, "del c[1]"); + py_run_bound!(py, c, "del c[1]"); { let c = c.borrow(); assert_eq!(c.key, 1); @@ -493,12 +493,12 @@ impl SetDelItem { fn setdelitem() { Python::with_gil(|py| { let c = PyCell::new(py, SetDelItem { val: None }).unwrap(); - py_run!(py, c, "c[1] = 2"); + py_run_bound!(py, c, "c[1] = 2"); { let c = c.borrow(); assert_eq!(c.val, Some(2)); } - py_run!(py, c, "del c[1]"); + py_run_bound!(py, c, "del c[1]"); let c = c.borrow(); assert_eq!(c.val, None); }); @@ -518,8 +518,8 @@ impl Contains { fn contains() { Python::with_gil(|py| { let c = Py::new(py, Contains {}).unwrap(); - py_run!(py, c, "assert 1 in c"); - py_run!(py, c, "assert -1 not in c"); + py_run_bound!(py, c, "assert 1 in c"); + py_run_bound!(py, c, "assert -1 not in c"); py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError); }); } @@ -689,7 +689,7 @@ asyncio.run(main()) "#; let globals = PyModule::import(py, "__main__").unwrap().dict(); globals.set_item("Once", once).unwrap(); - py.run(source, Some(globals), None) + py.run_bound(source, Some(&globals.as_borrowed()), None) .map_err(|e| e.display(py)) .unwrap(); }); @@ -746,7 +746,7 @@ asyncio.run(main()) globals .set_item("AsyncIterator", py.get_type::()) .unwrap(); - py.run(source, Some(globals), None) + py.run_bound(source, Some(&globals.as_borrowed()), None) .map_err(|e| e.display(py)) .unwrap(); }); @@ -815,7 +815,7 @@ assert c.counter.count == 1 ); let globals = PyModule::import(py, "__main__").unwrap().dict(); globals.set_item("Counter", counter).unwrap(); - py.run(source, Some(globals), None) + py.run_bound(source, Some(&globals.as_borrowed()), None) .map_err(|e| e.display(py)) .unwrap(); }); diff --git a/tests/test_pyfunction.rs b/tests/test_pyfunction.rs index a2f44be6bbd..242ac500751 100644 --- a/tests/test_pyfunction.rs +++ b/tests/test_pyfunction.rs @@ -61,7 +61,7 @@ f(a, b) PyBufferError ); - pyo3::py_run!( + pyo3::py_run_bound!( py, f, r#" @@ -92,7 +92,7 @@ fn test_functions_with_function_args() { let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap(); let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap(); - pyo3::py_run!( + pyo3::py_run_bound!( py, py_cfunc_arg bool_to_string, @@ -105,7 +105,7 @@ fn test_functions_with_function_args() { { let py_func_arg = wrap_pyfunction!(function_with_pyfunction_arg)(py).unwrap(); - pyo3::py_run!( + pyo3::py_run_bound!( py, py_func_arg, r#" @@ -139,7 +139,7 @@ fn test_function_with_custom_conversion() { Python::with_gil(|py| { let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap(); - pyo3::py_run!( + pyo3::py_run_bound!( py, custom_conv_func, r#" diff --git a/tests/test_sequence.rs b/tests/test_sequence.rs index b11e4a6929d..bda4b567691 100644 --- a/tests/test_sequence.rs +++ b/tests/test_sequence.rs @@ -4,7 +4,7 @@ use pyo3::exceptions::{PyIndexError, PyValueError}; use pyo3::types::{IntoPyDict, PyList, PyMapping, PySequence}; use pyo3::{ffi, prelude::*}; -use pyo3::py_run; +use pyo3::py_run_bound; #[path = "../src/tests/common.rs"] mod common; @@ -105,10 +105,10 @@ impl ByteSequence { } /// Return a dict with `s = ByteSequence([1, 2, 3])`. -fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict { - let d = [("ByteSequence", py.get_type::())].into_py_dict(py); +fn seq_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { + let d = [("ByteSequence", py.get_type::())].into_py_dict_bound(py); // Though we can construct `s` in Rust, let's test `__new__` works. - py_run!(py, *d, "s = ByteSequence([1, 2, 3])"); + py_run_bound!(py, *d, "s = ByteSequence([1, 2, 3])"); d } @@ -130,7 +130,7 @@ fn test_setitem() { Python::with_gil(|py| { let d = seq_dict(py); - py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]"); + py_run_bound!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]"); py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError); }); } @@ -138,24 +138,24 @@ 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_bound(py); - py_run!( + py_run_bound!( py, *d, "s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]" ); - py_run!( + py_run_bound!( py, *d, "s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]" ); - py_run!( + py_run_bound!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]" ); - py_run!( + py_run_bound!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]" @@ -193,7 +193,7 @@ fn test_concat() { Python::with_gil(|py| { let d = seq_dict(py); - py_run!( + py_run_bound!( py, *d, "s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]" @@ -212,7 +212,7 @@ fn test_inplace_concat() { Python::with_gil(|py| { let d = seq_dict(py); - py_run!( + py_run_bound!( py, *d, "s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]" @@ -226,7 +226,7 @@ fn test_repeat() { Python::with_gil(|py| { let d = seq_dict(py); - py_run!(py, *d, "s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]"); + py_run_bound!(py, *d, "s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]"); py_expect_exception!(py, *d, "s2 = s * -1", PyValueError); }); } @@ -234,9 +234,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_bound(py); - py_run!( + py_run_bound!( py, *d, "s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]" @@ -270,7 +270,7 @@ fn test_generic_list_set() { Python::with_gil(|py| { let list = PyCell::new(py, GenericList { items: vec![] }).unwrap(); - py_run!(py, list, "list.items = [1, 2, 3]"); + py_run_bound!(py, list, "list.items = [1, 2, 3]"); assert!(list .borrow() .items diff --git a/tests/test_static_slots.rs b/tests/test_static_slots.rs index 402128c50df..ad6a06d6483 100644 --- a/tests/test_static_slots.rs +++ b/tests/test_static_slots.rs @@ -4,7 +4,7 @@ use pyo3::exceptions::PyIndexError; use pyo3::prelude::*; use pyo3::types::IntoPyDict; -use pyo3::py_run; +use pyo3::py_run_bound; #[path = "../src/tests/common.rs"] mod common; @@ -37,10 +37,10 @@ impl Count5 { } /// Return a dict with `s = Count5()`. -fn test_dict(py: Python<'_>) -> &pyo3::types::PyDict { - let d = [("Count5", py.get_type::())].into_py_dict(py); +fn test_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { + let d = [("Count5", py.get_type::())].into_py_dict_bound(py); // Though we can construct `s` in Rust, let's test `__new__` works. - py_run!(py, *d, "s = Count5()"); + py_run_bound!(py, *d, "s = Count5()"); d } diff --git a/tests/test_super.rs b/tests/test_super.rs index 208290df87b..21e637b22e6 100644 --- a/tests/test_super.rs +++ b/tests/test_super.rs @@ -45,7 +45,7 @@ impl SubClass { fn test_call_super_method() { Python::with_gil(|py| { let cls = py.get_type::(); - pyo3::py_run!( + pyo3::py_run_bound!( py, cls, r#" diff --git a/tests/test_unsendable_dict.rs b/tests/test_unsendable_dict.rs index a39aa1ab714..8b10742613b 100644 --- a/tests/test_unsendable_dict.rs +++ b/tests/test_unsendable_dict.rs @@ -1,7 +1,7 @@ #![cfg(feature = "macros")] use pyo3::prelude::*; -use pyo3::py_run; +use pyo3::py_run_bound; #[pyclass(dict, unsendable)] struct UnsendableDictClass {} @@ -19,7 +19,7 @@ impl UnsendableDictClass { fn test_unsendable_dict() { Python::with_gil(|py| { let inst = Py::new(py, UnsendableDictClass {}).unwrap(); - py_run!(py, inst, "assert inst.__dict__ == {}"); + py_run_bound!(py, inst, "assert inst.__dict__ == {}"); }); } @@ -39,8 +39,8 @@ impl UnsendableDictClassWithWeakRef { fn test_unsendable_dict_with_weakref() { Python::with_gil(|py| { let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap(); - py_run!(py, inst, "assert inst.__dict__ == {}"); - py_run!( + py_run_bound!(py, inst, "assert inst.__dict__ == {}"); + py_run_bound!( py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" diff --git a/tests/test_various.rs b/tests/test_various.rs index 6560610f35f..2d775280d0f 100644 --- a/tests/test_various.rs +++ b/tests/test_various.rs @@ -2,7 +2,7 @@ use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; -use pyo3::{py_run, PyCell}; +use pyo3::{py_run_bound, PyCell}; use std::fmt; @@ -30,7 +30,7 @@ fn mut_ref_arg() { let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap(); let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap(); - py_run!(py, inst1 inst2, "inst1.set_other(inst2)"); + py_run_bound!(py, inst1 inst2, "inst1.set_other(inst2)"); let inst2 = inst2.as_ref(py).borrow(); assert_eq!(inst2.n, 100); }); @@ -151,7 +151,7 @@ fn test_pickle() { module.add_class::().unwrap(); add_module(py, module).unwrap(); let inst = PyCell::new(py, PickleSupport {}).unwrap(); - py_run!( + py_run_bound!( py, inst, r#" diff --git a/tests/ui/invalid_result_conversion.stderr b/tests/ui/invalid_result_conversion.stderr index f1a429a5abd..2720c71db63 100644 --- a/tests/ui/invalid_result_conversion.stderr +++ b/tests/ui/invalid_result_conversion.stderr @@ -6,8 +6,8 @@ error[E0277]: the trait bound `PyErr: From` is not satisfied | = help: the following other types implement trait `From`: > - > > + > >> >> >> diff --git a/tests/ui/wrong_aspyref_lifetimes.rs b/tests/ui/wrong_aspyref_lifetimes.rs index 5cd8a2d3cb6..88bcbaaaaf7 100644 --- a/tests/ui/wrong_aspyref_lifetimes.rs +++ b/tests/ui/wrong_aspyref_lifetimes.rs @@ -1,7 +1,7 @@ use pyo3::{types::PyDict, Py, Python}; fn main() { - let dict: Py = Python::with_gil(|py| PyDict::new(py).into()); + let dict: Py = Python::with_gil(|py| PyDict::new_bound(py).into()); // Should not be able to get access to Py contents outside of with_gil. let dict: &PyDict = Python::with_gil(|py| dict.as_ref(py));