Merge pull request #3816 from Icxolu/python-run
port `Python::run` to `Bound` API
This commit is contained in:
commit
45f2b0aba5
|
@ -387,10 +387,10 @@ fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
#
|
#
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
# Python::with_gil(|py| -> PyResult<()> {
|
# Python::with_gil(|py| -> PyResult<()> {
|
||||||
# let globals = PyModule::import(py, "__main__")?.dict();
|
# let globals = PyModule::import(py, "__main__")?.dict().as_borrowed();
|
||||||
# globals.set_item("Number", Number::type_object_bound(py))?;
|
# globals.set_item("Number", Number::type_object_bound(py))?;
|
||||||
#
|
#
|
||||||
# py.run(SCRIPT, Some(globals), None)?;
|
# py.run_bound(SCRIPT, Some(&globals), None)?;
|
||||||
# Ok(())
|
# Ok(())
|
||||||
# })
|
# })
|
||||||
# }
|
# }
|
||||||
|
|
|
@ -93,9 +93,9 @@ fn func() -> String {
|
||||||
# use pyo3::wrap_pymodule;
|
# use pyo3::wrap_pymodule;
|
||||||
# use pyo3::types::IntoPyDict;
|
# use pyo3::types::IntoPyDict;
|
||||||
# let parent_module = wrap_pymodule!(parent_module)(py);
|
# let parent_module = wrap_pymodule!(parent_module)(py);
|
||||||
# let ctx = [("parent_module", parent_module)].into_py_dict(py);
|
# let ctx = [("parent_module", parent_module)].into_py_dict(py).as_borrowed();
|
||||||
#
|
#
|
||||||
# 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();
|
||||||
# })
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,7 @@ fn foo(_py: Python<'_>, foo_module: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
fn main() -> PyResult<()> {
|
fn main() -> PyResult<()> {
|
||||||
pyo3::append_to_inittab!(foo);
|
pyo3::append_to_inittab!(foo);
|
||||||
Python::with_gil(|py| Python::run(py, "import foo; foo.add_one(6)", None, None))
|
Python::with_gil(|py| Python::run_bound(py, "import foo; foo.add_one(6)", None, None))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ fn main() -> PyResult<()> {
|
||||||
py_modules.set_item("foo", foo_module)?;
|
py_modules.set_item("foo", foo_module)?;
|
||||||
|
|
||||||
// Now we can import + run our python code
|
// Now we can import + run our python code
|
||||||
Python::run(py, "import foo; foo.add_one(6)", None, None)
|
Python::run_bound(py, "import foo; foo.add_one(6)", None, None)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -147,8 +147,8 @@ mod test_anyhow {
|
||||||
let pyerr = PyErr::from(err);
|
let pyerr = PyErr::from(err);
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = [("err", pyerr)].into_py_dict(py);
|
let locals = [("err", pyerr)].into_py_dict(py).as_borrowed();
|
||||||
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
|
let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err();
|
||||||
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,8 @@ mod test_anyhow {
|
||||||
let pyerr = PyErr::from(err);
|
let pyerr = PyErr::from(err);
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = [("err", pyerr)].into_py_dict(py);
|
let locals = [("err", pyerr)].into_py_dict(py).as_borrowed();
|
||||||
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
|
let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err();
|
||||||
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -574,12 +574,15 @@ mod tests {
|
||||||
// tzdata there to make this work.
|
// tzdata there to make this work.
|
||||||
#[cfg(all(Py_3_9, not(target_os = "windows")))]
|
#[cfg(all(Py_3_9, not(target_os = "windows")))]
|
||||||
fn test_zoneinfo_is_not_fixed_offset() {
|
fn test_zoneinfo_is_not_fixed_offset() {
|
||||||
|
use crate::types::any::PyAnyMethods;
|
||||||
|
use crate::types::dict::PyDictMethods;
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = crate::types::PyDict::new(py);
|
let locals = crate::types::PyDict::new_bound(py);
|
||||||
py.run(
|
py.run_bound(
|
||||||
"import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')",
|
"import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let result: PyResult<FixedOffset> = locals.get_item("zi").unwrap().unwrap().extract();
|
let result: PyResult<FixedOffset> = locals.get_item("zi").unwrap().unwrap().extract();
|
||||||
|
|
|
@ -152,8 +152,8 @@ mod tests {
|
||||||
let pyerr = PyErr::from(err);
|
let pyerr = PyErr::from(err);
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = [("err", pyerr)].into_py_dict(py);
|
let locals = [("err", pyerr)].into_py_dict(py).as_borrowed();
|
||||||
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
|
let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err();
|
||||||
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -169,8 +169,8 @@ mod tests {
|
||||||
let pyerr = PyErr::from(err);
|
let pyerr = PyErr::from(err);
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = [("err", pyerr)].into_py_dict(py);
|
let locals = [("err", pyerr)].into_py_dict(py).as_borrowed();
|
||||||
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
|
let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err();
|
||||||
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,8 @@ impl IntoPy<PyObject> for Decimal {
|
||||||
mod test_rust_decimal {
|
mod test_rust_decimal {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::err::PyErr;
|
use crate::err::PyErr;
|
||||||
|
use crate::types::any::PyAnyMethods;
|
||||||
|
use crate::types::dict::PyDictMethods;
|
||||||
use crate::types::PyDict;
|
use crate::types::PyDict;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
|
|
||||||
|
@ -121,16 +123,16 @@ mod test_rust_decimal {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let rs_orig = $rs;
|
let rs_orig = $rs;
|
||||||
let rs_dec = rs_orig.into_py(py);
|
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();
|
locals.set_item("rs_dec", &rs_dec).unwrap();
|
||||||
// Checks if Rust Decimal -> Python Decimal conversion is correct
|
// Checks if Rust Decimal -> Python Decimal conversion is correct
|
||||||
py.run(
|
py.run_bound(
|
||||||
&format!(
|
&format!(
|
||||||
"import decimal\npy_dec = decimal.Decimal({})\nassert py_dec == rs_dec",
|
"import decimal\npy_dec = decimal.Decimal({})\nassert py_dec == rs_dec",
|
||||||
$py
|
$py
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Checks if Python Decimal -> Rust Decimal conversion is correct
|
// Checks if Python Decimal -> Rust Decimal conversion is correct
|
||||||
|
@ -163,13 +165,13 @@ mod test_rust_decimal {
|
||||||
let num = Decimal::from_parts(lo, mid, high, negative, scale);
|
let num = Decimal::from_parts(lo, mid, high, negative, scale);
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let rs_dec = num.into_py(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();
|
locals.set_item("rs_dec", &rs_dec).unwrap();
|
||||||
py.run(
|
py.run_bound(
|
||||||
&format!(
|
&format!(
|
||||||
"import decimal\npy_dec = decimal.Decimal(\"{}\")\nassert py_dec == rs_dec",
|
"import decimal\npy_dec = decimal.Decimal(\"{}\")\nassert py_dec == rs_dec",
|
||||||
num),
|
num),
|
||||||
None, Some(locals)).unwrap();
|
None, Some(&locals)).unwrap();
|
||||||
let roundtripped: Decimal = rs_dec.extract(py).unwrap();
|
let roundtripped: Decimal = rs_dec.extract(py).unwrap();
|
||||||
assert_eq!(num, roundtripped);
|
assert_eq!(num, roundtripped);
|
||||||
})
|
})
|
||||||
|
@ -189,11 +191,11 @@ mod test_rust_decimal {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nan() {
|
fn test_nan() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = PyDict::new(py);
|
let locals = PyDict::new_bound(py);
|
||||||
py.run(
|
py.run_bound(
|
||||||
"import decimal\npy_dec = decimal.Decimal(\"NaN\")",
|
"import decimal\npy_dec = decimal.Decimal(\"NaN\")",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let py_dec = locals.get_item("py_dec").unwrap().unwrap();
|
let py_dec = locals.get_item("py_dec").unwrap().unwrap();
|
||||||
|
@ -205,11 +207,11 @@ mod test_rust_decimal {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_infinity() {
|
fn test_infinity() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = PyDict::new(py);
|
let locals = PyDict::new_bound(py);
|
||||||
py.run(
|
py.run_bound(
|
||||||
"import decimal\npy_dec = decimal.Decimal(\"Infinity\")",
|
"import decimal\npy_dec = decimal.Decimal(\"Infinity\")",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let py_dec = locals.get_item("py_dec").unwrap().unwrap();
|
let py_dec = locals.get_item("py_dec").unwrap().unwrap();
|
||||||
|
|
|
@ -376,6 +376,9 @@ mod test_128bit_integers {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::types::PyDict;
|
use crate::types::PyDict;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use crate::types::dict::PyDictMethods;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
|
||||||
|
@ -385,9 +388,9 @@ mod test_128bit_integers {
|
||||||
fn test_i128_roundtrip(x: i128) {
|
fn test_i128_roundtrip(x: i128) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let x_py = x.into_py(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();
|
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();
|
let roundtripped: i128 = x_py.extract(py).unwrap();
|
||||||
assert_eq!(x, roundtripped);
|
assert_eq!(x, roundtripped);
|
||||||
})
|
})
|
||||||
|
@ -401,9 +404,9 @@ mod test_128bit_integers {
|
||||||
) {
|
) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let x_py = x.into_py(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();
|
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();
|
let roundtripped: NonZeroI128 = x_py.extract(py).unwrap();
|
||||||
assert_eq!(x, roundtripped);
|
assert_eq!(x, roundtripped);
|
||||||
})
|
})
|
||||||
|
@ -416,9 +419,9 @@ mod test_128bit_integers {
|
||||||
fn test_u128_roundtrip(x: u128) {
|
fn test_u128_roundtrip(x: u128) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let x_py = x.into_py(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();
|
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();
|
let roundtripped: u128 = x_py.extract(py).unwrap();
|
||||||
assert_eq!(x, roundtripped);
|
assert_eq!(x, roundtripped);
|
||||||
})
|
})
|
||||||
|
@ -432,9 +435,9 @@ mod test_128bit_integers {
|
||||||
) {
|
) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let x_py = x.into_py(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();
|
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();
|
let roundtripped: NonZeroU128 = x_py.extract(py).unwrap();
|
||||||
assert_eq!(x, roundtripped);
|
assert_eq!(x, roundtripped);
|
||||||
})
|
})
|
||||||
|
|
|
@ -1030,7 +1030,7 @@ mod tests {
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let err = 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");
|
.expect_err("raising should have given us an error");
|
||||||
|
|
||||||
let debug_str = format!("{:?}", err);
|
let debug_str = format!("{:?}", err);
|
||||||
|
@ -1055,7 +1055,7 @@ mod tests {
|
||||||
fn err_display() {
|
fn err_display() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let err = 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");
|
.expect_err("raising should have given us an error");
|
||||||
assert_eq!(err.to_string(), "Exception: banana");
|
assert_eq!(err.to_string(), "Exception: banana");
|
||||||
});
|
});
|
||||||
|
@ -1102,12 +1102,12 @@ mod tests {
|
||||||
fn test_pyerr_cause() {
|
fn test_pyerr_cause() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let err = 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");
|
.expect_err("raising should have given us an error");
|
||||||
assert!(err.cause(py).is_none());
|
assert!(err.cause(py).is_none());
|
||||||
|
|
||||||
let err = py
|
let err = py
|
||||||
.run(
|
.run_bound(
|
||||||
"raise Exception('banana') from Exception('apple')",
|
"raise Exception('banana') from Exception('apple')",
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -165,18 +165,18 @@ macro_rules! import_exception {
|
||||||
/// # fn main() -> PyResult<()> {
|
/// # fn main() -> PyResult<()> {
|
||||||
/// # Python::with_gil(|py| -> PyResult<()> {
|
/// # Python::with_gil(|py| -> PyResult<()> {
|
||||||
/// # let fun = wrap_pyfunction!(raise_myerror, py)?;
|
/// # 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::<MyError>())?;
|
/// # locals.set_item("MyError", py.get_type::<MyError>())?;
|
||||||
/// # locals.set_item("raise_myerror", fun)?;
|
/// # locals.set_item("raise_myerror", fun)?;
|
||||||
/// #
|
/// #
|
||||||
/// # py.run(
|
/// # py.run_bound(
|
||||||
/// # "try:
|
/// # "try:
|
||||||
/// # raise_myerror()
|
/// # raise_myerror()
|
||||||
/// # except MyError as e:
|
/// # except MyError as e:
|
||||||
/// # assert e.__doc__ == 'Some description.'
|
/// # assert e.__doc__ == 'Some description.'
|
||||||
/// # assert str(e) == 'Some error happened.'",
|
/// # assert str(e) == 'Some error happened.'",
|
||||||
/// # None,
|
/// # None,
|
||||||
/// # Some(locals),
|
/// # Some(&locals),
|
||||||
/// # )?;
|
/// # )?;
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
|
@ -338,7 +338,7 @@ use pyo3::prelude::*;
|
||||||
use pyo3::exceptions::Py", $name, ";
|
use pyo3::exceptions::Py", $name, ";
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
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 {
|
let error_type = match result {
|
||||||
Ok(_) => \"Not an error\",
|
Ok(_) => \"Not an error\",
|
||||||
|
@ -816,7 +816,7 @@ mod tests {
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("could not import socket");
|
.expect("could not import socket");
|
||||||
|
|
||||||
let d = PyDict::new(py);
|
let d = PyDict::new_bound(py);
|
||||||
d.set_item("socket", socket)
|
d.set_item("socket", socket)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("could not setitem");
|
.expect("could not setitem");
|
||||||
|
@ -825,7 +825,7 @@ mod tests {
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("could not setitem");
|
.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))
|
.map_err(|e| e.display(py))
|
||||||
.expect("assertion failed");
|
.expect("assertion failed");
|
||||||
});
|
});
|
||||||
|
@ -840,7 +840,7 @@ mod tests {
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("could not import email");
|
.expect("could not import email");
|
||||||
|
|
||||||
let d = PyDict::new(py);
|
let d = PyDict::new_bound(py);
|
||||||
d.set_item("email", email)
|
d.set_item("email", email)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("could not setitem");
|
.expect("could not setitem");
|
||||||
|
@ -848,10 +848,10 @@ mod tests {
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("could not setitem");
|
.expect("could not setitem");
|
||||||
|
|
||||||
py.run(
|
py.run_bound(
|
||||||
"assert isinstance(exc, email.errors.MessageError)",
|
"assert isinstance(exc, email.errors.MessageError)",
|
||||||
None,
|
None,
|
||||||
Some(d),
|
Some(&d),
|
||||||
)
|
)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.expect("assertion failed");
|
.expect("assertion failed");
|
||||||
|
@ -871,14 +871,13 @@ mod tests {
|
||||||
.extract()
|
.extract()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
||||||
let ctx = ctx.as_gil_ref();
|
py.run_bound(
|
||||||
py.run(
|
|
||||||
"assert CustomError('oops').args == ('oops',)",
|
"assert CustomError('oops').args == ('oops',)",
|
||||||
None,
|
None,
|
||||||
Some(ctx),
|
Some(&ctx),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
py.run("assert CustomError.__doc__ is None", None, Some(ctx))
|
py.run_bound("assert CustomError.__doc__ is None", None, Some(&ctx))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -914,15 +913,18 @@ mod tests {
|
||||||
.extract()
|
.extract()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
||||||
let ctx = ctx.as_gil_ref();
|
py.run_bound(
|
||||||
py.run(
|
|
||||||
"assert CustomError('oops').args == ('oops',)",
|
"assert CustomError('oops').args == ('oops',)",
|
||||||
None,
|
None,
|
||||||
Some(ctx),
|
Some(&ctx),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
py.run_bound(
|
||||||
|
"assert CustomError.__doc__ == 'Some docs'",
|
||||||
|
None,
|
||||||
|
Some(&ctx),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
py.run("assert CustomError.__doc__ == 'Some docs'", None, Some(ctx))
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,17 +946,16 @@ mod tests {
|
||||||
.extract()
|
.extract()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
||||||
let ctx = ctx.as_gil_ref();
|
py.run_bound(
|
||||||
py.run(
|
|
||||||
"assert CustomError('oops').args == ('oops',)",
|
"assert CustomError('oops').args == ('oops',)",
|
||||||
None,
|
None,
|
||||||
Some(ctx),
|
Some(&ctx),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
py.run(
|
py.run_bound(
|
||||||
"assert CustomError.__doc__ == 'Some more docs'",
|
"assert CustomError.__doc__ == 'Some more docs'",
|
||||||
None,
|
None,
|
||||||
Some(ctx),
|
Some(&ctx),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
@ -964,7 +965,7 @@ mod tests {
|
||||||
fn native_exception_debug() {
|
fn native_exception_debug() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let exc = 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")
|
.expect_err("raising should have given us an error")
|
||||||
.into_value(py)
|
.into_value(py)
|
||||||
.into_ref(py);
|
.into_ref(py);
|
||||||
|
@ -979,7 +980,7 @@ mod tests {
|
||||||
fn native_exception_display() {
|
fn native_exception_display() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let exc = 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")
|
.expect_err("raising should have given us an error")
|
||||||
.into_value(py)
|
.into_value(py)
|
||||||
.into_ref(py);
|
.into_ref(py);
|
||||||
|
@ -996,7 +997,7 @@ mod tests {
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let exc = py
|
let exc = py
|
||||||
.run(
|
.run_bound(
|
||||||
"raise Exception('banana') from TypeError('peach')",
|
"raise Exception('banana') from TypeError('peach')",
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -20,12 +20,12 @@ fn test_datetime_fromtimestamp() {
|
||||||
PyDateTime_IMPORT();
|
PyDateTime_IMPORT();
|
||||||
py.from_owned_ptr(PyDateTime_FromTimestamp(args.as_ptr()))
|
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();
|
locals.set_item("dt", dt).unwrap();
|
||||||
py.run(
|
py.run_bound(
|
||||||
"import datetime; assert dt == datetime.datetime.fromtimestamp(100)",
|
"import datetime; assert dt == datetime.datetime.fromtimestamp(100)",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
})
|
})
|
||||||
|
@ -41,12 +41,12 @@ fn test_date_fromtimestamp() {
|
||||||
PyDateTime_IMPORT();
|
PyDateTime_IMPORT();
|
||||||
py.from_owned_ptr(PyDate_FromTimestamp(args.as_ptr()))
|
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();
|
locals.set_item("dt", dt).unwrap();
|
||||||
py.run(
|
py.run_bound(
|
||||||
"import datetime; assert dt == datetime.date.fromtimestamp(100)",
|
"import datetime; assert dt == datetime.date.fromtimestamp(100)",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
})
|
})
|
||||||
|
@ -61,12 +61,12 @@ fn test_utc_timezone() {
|
||||||
PyDateTime_IMPORT();
|
PyDateTime_IMPORT();
|
||||||
py.from_borrowed_ptr(PyDateTime_TimeZone_UTC())
|
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();
|
locals.set_item("utc_timezone", utc_timezone).unwrap();
|
||||||
py.run(
|
py.run_bound(
|
||||||
"import datetime; assert utc_timezone is datetime.timezone.utc",
|
"import datetime; assert utc_timezone is datetime.timezone.utc",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
})
|
})
|
||||||
|
|
|
@ -75,7 +75,7 @@ fn gil_is_acquired() -> bool {
|
||||||
///
|
///
|
||||||
/// # fn main() -> PyResult<()> {
|
/// # fn main() -> PyResult<()> {
|
||||||
/// pyo3::prepare_freethreaded_python();
|
/// 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))]
|
#[cfg(not(PyPy))]
|
||||||
|
@ -118,7 +118,7 @@ pub fn prepare_freethreaded_python() {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// unsafe {
|
/// unsafe {
|
||||||
/// pyo3::with_embedded_python_interpreter(|py| {
|
/// 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`!
|
/// // We must make sure to not return a `PyErr`!
|
||||||
/// e.print(py);
|
/// e.print(py);
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -104,12 +104,13 @@ macro_rules! py_run_impl {
|
||||||
}};
|
}};
|
||||||
($py:expr, *$dict:expr, $code:expr) => {{
|
($py:expr, *$dict:expr, $code:expr) => {{
|
||||||
use ::std::option::Option::*;
|
use ::std::option::Option::*;
|
||||||
if let ::std::result::Result::Err(e) = $py.run($code, None, Some($dict)) {
|
use $crate::PyNativeType;
|
||||||
|
if let ::std::result::Result::Err(e) = $py.run_bound($code, None, Some(&$dict.as_borrowed())) {
|
||||||
e.print($py);
|
e.print($py);
|
||||||
// So when this c api function the last line called printed the error to stderr,
|
// 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
|
// 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
|
// 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();
|
.unwrap();
|
||||||
::std::panic!("{}", $code)
|
::std::panic!("{}", $code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -600,6 +600,27 @@ impl<'py> Python<'py> {
|
||||||
self.run_code(code, ffi::Py_eval_input, globals, locals)
|
self.run_code(code, ffi::Py_eval_input, globals, locals)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deprecated version of [`Python::run_bound`]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "`Python::run` will be replaced by `Python::run_bound` in a future PyO3 version"
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
pub fn run(
|
||||||
|
self,
|
||||||
|
code: &str,
|
||||||
|
globals: Option<&PyDict>,
|
||||||
|
locals: Option<&PyDict>,
|
||||||
|
) -> PyResult<()> {
|
||||||
|
self.run_bound(
|
||||||
|
code,
|
||||||
|
globals.map(PyNativeType::as_borrowed).as_deref(),
|
||||||
|
locals.map(PyNativeType::as_borrowed).as_deref(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Executes one or more Python statements in the given context.
|
/// Executes one or more Python statements in the given context.
|
||||||
///
|
///
|
||||||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||||
|
@ -615,37 +636,32 @@ impl<'py> Python<'py> {
|
||||||
/// types::{PyBytes, PyDict},
|
/// types::{PyBytes, PyDict},
|
||||||
/// };
|
/// };
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let locals = PyDict::new(py);
|
/// let locals = PyDict::new_bound(py);
|
||||||
/// py.run(
|
/// py.run_bound(
|
||||||
/// r#"
|
/// r#"
|
||||||
/// import base64
|
/// import base64
|
||||||
/// s = 'Hello Rust!'
|
/// s = 'Hello Rust!'
|
||||||
/// ret = base64.b64encode(s.encode('utf-8'))
|
/// ret = base64.b64encode(s.encode('utf-8'))
|
||||||
/// "#,
|
/// "#,
|
||||||
/// None,
|
/// None,
|
||||||
/// Some(locals),
|
/// Some(&locals),
|
||||||
/// )
|
/// )
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
/// let ret = locals.get_item("ret").unwrap().unwrap();
|
/// let ret = locals.get_item("ret").unwrap().unwrap();
|
||||||
/// let b64: &PyBytes = ret.downcast().unwrap();
|
/// let b64 = ret.downcast::<PyBytes>().unwrap();
|
||||||
/// assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE=");
|
/// 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!`](macro.py_run.html) for a handy alternative of `run`
|
||||||
/// if you don't need `globals` and unwrapping is OK.
|
/// if you don't need `globals` and unwrapping is OK.
|
||||||
pub fn run(
|
pub fn run_bound(
|
||||||
self,
|
self,
|
||||||
code: &str,
|
code: &str,
|
||||||
globals: Option<&PyDict>,
|
globals: Option<&Bound<'py, PyDict>>,
|
||||||
locals: Option<&PyDict>,
|
locals: Option<&Bound<'py, PyDict>>,
|
||||||
) -> PyResult<()> {
|
) -> PyResult<()> {
|
||||||
let res = self.run_code(
|
let res = self.run_code(code, ffi::Py_file_input, globals, locals);
|
||||||
code,
|
|
||||||
ffi::Py_file_input,
|
|
||||||
globals.map(PyNativeType::as_borrowed).as_deref(),
|
|
||||||
locals.map(PyNativeType::as_borrowed).as_deref(),
|
|
||||||
);
|
|
||||||
res.map(|obj| {
|
res.map(|obj| {
|
||||||
debug_assert!(obj.is_none());
|
debug_assert!(obj.is_none());
|
||||||
})
|
})
|
||||||
|
@ -1235,9 +1251,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_py_run_inserts_globals() {
|
fn test_py_run_inserts_globals() {
|
||||||
|
use crate::types::dict::PyDictMethods;
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let namespace = PyDict::new(py);
|
let namespace = PyDict::new_bound(py);
|
||||||
py.run("class Foo: pass", Some(namespace), Some(namespace))
|
py.run_bound("class Foo: pass", Some(&namespace), Some(&namespace))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(namespace.get_item("Foo"), Ok(Some(..))));
|
assert!(matches!(namespace.get_item("Foo"), Ok(Some(..))));
|
||||||
assert!(matches!(namespace.get_item("__builtins__"), Ok(Some(..))));
|
assert!(matches!(namespace.get_item("__builtins__"), Ok(Some(..))));
|
||||||
|
|
|
@ -40,7 +40,8 @@ mod inner {
|
||||||
}};
|
}};
|
||||||
// Case2: dict & no err_msg
|
// Case2: dict & no err_msg
|
||||||
($py:expr, *$dict:expr, $code:expr, $err:ident) => {{
|
($py:expr, *$dict:expr, $code:expr, $err:ident) => {{
|
||||||
let res = $py.run($code, None, Some($dict));
|
use pyo3::PyNativeType;
|
||||||
|
let res = $py.run_bound($code, None, Some(&$dict.as_borrowed()));
|
||||||
let err = res.expect_err(&format!("Did not raise {}", stringify!($err)));
|
let err = res.expect_err(&format!("Did not raise {}", stringify!($err)));
|
||||||
if !err.matches($py, $py.get_type::<pyo3::exceptions::$err>()) {
|
if !err.matches($py, $py.get_type::<pyo3::exceptions::$err>()) {
|
||||||
panic!("Expected {} but got {:?}", stringify!($err), err)
|
panic!("Expected {} but got {:?}", stringify!($err), err)
|
||||||
|
|
|
@ -197,10 +197,10 @@ impl PyByteArray {
|
||||||
/// # fn main() -> PyResult<()> {
|
/// # fn main() -> PyResult<()> {
|
||||||
/// # Python::with_gil(|py| -> PyResult<()> {
|
/// # Python::with_gil(|py| -> PyResult<()> {
|
||||||
/// # let fun = wrap_pyfunction!(a_valid_function, py)?;
|
/// # 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)?;
|
/// # locals.set_item("a_valid_function", fun)?;
|
||||||
/// #
|
/// #
|
||||||
/// # py.run(
|
/// # py.run_bound(
|
||||||
/// # r#"b = bytearray(b"hello world")
|
/// # r#"b = bytearray(b"hello world")
|
||||||
/// # a_valid_function(b)
|
/// # a_valid_function(b)
|
||||||
/// #
|
/// #
|
||||||
|
@ -209,7 +209,7 @@ impl PyByteArray {
|
||||||
/// # except RuntimeError as e:
|
/// # except RuntimeError as e:
|
||||||
/// # assert str(e) == 'input is not long enough'"#,
|
/// # assert str(e) == 'input is not long enough'"#,
|
||||||
/// # None,
|
/// # None,
|
||||||
/// # Some(locals),
|
/// # Some(&locals),
|
||||||
/// # )?;
|
/// # )?;
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
|
@ -359,10 +359,10 @@ pub trait PyByteArrayMethods<'py> {
|
||||||
/// # fn main() -> PyResult<()> {
|
/// # fn main() -> PyResult<()> {
|
||||||
/// # Python::with_gil(|py| -> PyResult<()> {
|
/// # Python::with_gil(|py| -> PyResult<()> {
|
||||||
/// # let fun = wrap_pyfunction!(a_valid_function, py)?;
|
/// # 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)?;
|
/// # locals.set_item("a_valid_function", fun)?;
|
||||||
/// #
|
/// #
|
||||||
/// # py.run(
|
/// # py.run_bound(
|
||||||
/// # r#"b = bytearray(b"hello world")
|
/// # r#"b = bytearray(b"hello world")
|
||||||
/// # a_valid_function(b)
|
/// # a_valid_function(b)
|
||||||
/// #
|
/// #
|
||||||
|
@ -371,7 +371,7 @@ pub trait PyByteArrayMethods<'py> {
|
||||||
/// # except RuntimeError as e:
|
/// # except RuntimeError as e:
|
||||||
/// # assert str(e) == 'input is not long enough'"#,
|
/// # assert str(e) == 'input is not long enough'"#,
|
||||||
/// # None,
|
/// # None,
|
||||||
/// # Some(locals),
|
/// # Some(&locals),
|
||||||
/// # )?;
|
/// # )?;
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl PyTraceback {
|
||||||
/// # let result: PyResult<()> =
|
/// # let result: PyResult<()> =
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let err = 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");
|
/// .expect_err("raise will create a Python error");
|
||||||
///
|
///
|
||||||
/// let traceback = err.traceback_bound(py).expect("raised exception will have a traceback");
|
/// let traceback = err.traceback_bound(py).expect("raised exception will have a traceback");
|
||||||
|
@ -71,7 +71,7 @@ pub trait PyTracebackMethods<'py> {
|
||||||
/// # let result: PyResult<()> =
|
/// # let result: PyResult<()> =
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let err = 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");
|
/// .expect_err("raise will create a Python error");
|
||||||
///
|
///
|
||||||
/// let traceback = err.traceback_bound(py).expect("raised exception will have a traceback");
|
/// let traceback = err.traceback_bound(py).expect("raised exception will have a traceback");
|
||||||
|
@ -121,7 +121,7 @@ mod tests {
|
||||||
fn format_traceback() {
|
fn format_traceback() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let err = 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");
|
.expect_err("raising should have given us an error");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -134,9 +134,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_err_from_value() {
|
fn test_err_from_value() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = PyDict::new(py);
|
let locals = PyDict::new_bound(py);
|
||||||
// Produce an error from python so that it has a traceback
|
// Produce an error from python so that it has a traceback
|
||||||
py.run(
|
py.run_bound(
|
||||||
r"
|
r"
|
||||||
try:
|
try:
|
||||||
raise ValueError('raised exception')
|
raise ValueError('raised exception')
|
||||||
|
@ -144,10 +144,10 @@ except Exception as e:
|
||||||
err = e
|
err = e
|
||||||
",
|
",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = PyErr::from_value(locals.get_item("err").unwrap().unwrap());
|
let err = PyErr::from_value(locals.get_item("err").unwrap().unwrap().into_gil_ref());
|
||||||
let traceback = err.value(py).getattr("__traceback__").unwrap();
|
let traceback = err.value(py).getattr("__traceback__").unwrap();
|
||||||
assert!(err.traceback_bound(py).unwrap().is(traceback));
|
assert!(err.traceback_bound(py).unwrap().is(traceback));
|
||||||
})
|
})
|
||||||
|
@ -156,15 +156,15 @@ except Exception as e:
|
||||||
#[test]
|
#[test]
|
||||||
fn test_err_into_py() {
|
fn test_err_into_py() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = PyDict::new(py);
|
let locals = PyDict::new_bound(py);
|
||||||
// Produce an error from python so that it has a traceback
|
// Produce an error from python so that it has a traceback
|
||||||
py.run(
|
py.run_bound(
|
||||||
r"
|
r"
|
||||||
def f():
|
def f():
|
||||||
raise ValueError('raised exception')
|
raise ValueError('raised exception')
|
||||||
",
|
",
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let f = locals.get_item("f").unwrap().unwrap();
|
let f = locals.get_item("f").unwrap().unwrap();
|
||||||
|
|
|
@ -25,6 +25,7 @@ fn test_anyhow_py_function_ok_result() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_anyhow_py_function_err_result() {
|
fn test_anyhow_py_function_err_result() {
|
||||||
|
use pyo3::prelude::PyDictMethods;
|
||||||
use pyo3::{pyfunction, types::PyDict, wrap_pyfunction, Python};
|
use pyo3::{pyfunction, types::PyDict, wrap_pyfunction, Python};
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
|
@ -34,15 +35,15 @@ fn test_anyhow_py_function_err_result() {
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let func = wrap_pyfunction!(produce_err_result)(py).unwrap();
|
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();
|
locals.set_item("func", func).unwrap();
|
||||||
|
|
||||||
py.run(
|
py.run_bound(
|
||||||
r#"
|
r#"
|
||||||
func()
|
func()
|
||||||
"#,
|
"#,
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn test_module_append_to_inittab() {
|
||||||
use pyo3::append_to_inittab;
|
use pyo3::append_to_inittab;
|
||||||
append_to_inittab!(module_with_functions);
|
append_to_inittab!(module_with_functions);
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
py.run(
|
py.run_bound(
|
||||||
r#"
|
r#"
|
||||||
import module_with_functions
|
import module_with_functions
|
||||||
assert module_with_functions.foo() == 123
|
assert module_with_functions.foo() == 123
|
||||||
|
|
|
@ -169,9 +169,12 @@ c = Class()
|
||||||
assert c.from_rust is False
|
assert c.from_rust is False
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
let globals = PyModule::import(py, "__main__")
|
||||||
|
.unwrap()
|
||||||
|
.dict()
|
||||||
|
.as_borrowed();
|
||||||
globals.set_item("SuperClass", super_cls).unwrap();
|
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))
|
.map_err(|e| e.display(py))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
|
|
@ -127,12 +127,12 @@ fn cancelled_coroutine() {
|
||||||
await task
|
await task
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
"#;
|
"#;
|
||||||
let globals = gil.import("__main__").unwrap().dict();
|
let globals = gil.import("__main__").unwrap().dict().as_borrowed();
|
||||||
globals.set_item("sleep", sleep).unwrap();
|
globals.set_item("sleep", sleep).unwrap();
|
||||||
let err = gil
|
let err = gil
|
||||||
.run(
|
.run_bound(
|
||||||
&pyo3::unindent::unindent(&handle_windows(test)),
|
&pyo3::unindent::unindent(&handle_windows(test)),
|
||||||
Some(globals),
|
Some(&globals),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
@ -166,13 +166,13 @@ fn coroutine_cancel_handle() {
|
||||||
return await task
|
return await task
|
||||||
assert asyncio.run(main()) == 0
|
assert asyncio.run(main()) == 0
|
||||||
"#;
|
"#;
|
||||||
let globals = gil.import("__main__").unwrap().dict();
|
let globals = gil.import("__main__").unwrap().dict().as_borrowed();
|
||||||
globals
|
globals
|
||||||
.set_item("cancellable_sleep", cancellable_sleep)
|
.set_item("cancellable_sleep", cancellable_sleep)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
gil.run(
|
gil.run_bound(
|
||||||
&pyo3::unindent::unindent(&handle_windows(test)),
|
&pyo3::unindent::unindent(&handle_windows(test)),
|
||||||
Some(globals),
|
Some(&globals),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -198,11 +198,11 @@ fn coroutine_is_cancelled() {
|
||||||
await task
|
await task
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
"#;
|
"#;
|
||||||
let globals = gil.import("__main__").unwrap().dict();
|
let globals = gil.import("__main__").unwrap().dict().as_borrowed();
|
||||||
globals.set_item("sleep_loop", sleep_loop).unwrap();
|
globals.set_item("sleep_loop", sleep_loop).unwrap();
|
||||||
gil.run(
|
gil.run_bound(
|
||||||
&pyo3::unindent::unindent(&handle_windows(test)),
|
&pyo3::unindent::unindent(&handle_windows(test)),
|
||||||
Some(globals),
|
Some(&globals),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -12,14 +12,16 @@ fn _get_subclasses<'py>(
|
||||||
// Import the class from Python and create some subclasses
|
// Import the class from Python and create some subclasses
|
||||||
let datetime = py.import("datetime")?;
|
let datetime = py.import("datetime")?;
|
||||||
|
|
||||||
let locals = [(py_type, datetime.getattr(py_type)?)].into_py_dict(py);
|
let locals = [(py_type, datetime.getattr(py_type)?)]
|
||||||
|
.into_py_dict(py)
|
||||||
|
.as_borrowed();
|
||||||
|
|
||||||
let make_subclass_py = format!("class Subklass({}):\n pass", py_type);
|
let make_subclass_py = format!("class Subklass({}):\n pass", py_type);
|
||||||
|
|
||||||
let make_sub_subclass_py = "class SubSubklass(Subklass):\n pass";
|
let make_sub_subclass_py = "class SubSubklass(Subklass):\n pass";
|
||||||
|
|
||||||
py.run(&make_subclass_py, None, Some(locals))?;
|
py.run_bound(&make_subclass_py, None, Some(&locals))?;
|
||||||
py.run(make_sub_subclass_py, None, Some(locals))?;
|
py.run_bound(make_sub_subclass_py, None, Some(&locals))?;
|
||||||
|
|
||||||
let locals = locals.as_borrowed();
|
let locals = locals.as_borrowed();
|
||||||
// Construct an instance of the base class
|
// Construct an instance of the base class
|
||||||
|
|
|
@ -117,7 +117,7 @@ fn gc_integration() {
|
||||||
});
|
});
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
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));
|
assert!(drop_called.load(Ordering::Relaxed));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ fn gc_null_traversal() {
|
||||||
obj.borrow_mut(py).cycle = Some(obj.clone_ref(py));
|
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.
|
// 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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +469,7 @@ fn drop_during_traversal_with_gil() {
|
||||||
// (but not too many) collections to get `inst` actually dropped.
|
// (but not too many) collections to get `inst` actually dropped.
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
Python::with_gil(|py| {
|
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));
|
assert!(drop_called.load(Ordering::Relaxed));
|
||||||
|
@ -502,7 +502,7 @@ fn drop_during_traversal_without_gil() {
|
||||||
// (but not too many) collections to get `inst` actually dropped.
|
// (but not too many) collections to get `inst` actually dropped.
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
Python::with_gil(|py| {
|
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));
|
assert!(drop_called.load(Ordering::Relaxed));
|
||||||
|
|
|
@ -20,12 +20,14 @@ struct SubclassAble {}
|
||||||
#[test]
|
#[test]
|
||||||
fn subclass() {
|
fn subclass() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = [("SubclassAble", py.get_type::<SubclassAble>())].into_py_dict(py);
|
let d = [("SubclassAble", py.get_type::<SubclassAble>())]
|
||||||
|
.into_py_dict(py)
|
||||||
|
.as_borrowed();
|
||||||
|
|
||||||
py.run(
|
py.run_bound(
|
||||||
"class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)",
|
"class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)",
|
||||||
None,
|
None,
|
||||||
Some(d),
|
Some(&d),
|
||||||
)
|
)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -97,9 +99,13 @@ fn call_base_and_sub_methods() {
|
||||||
fn mutation_fails() {
|
fn mutation_fails() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let obj = PyCell::new(py, SubClass::new()).unwrap();
|
let obj = PyCell::new(py, SubClass::new()).unwrap();
|
||||||
let global = Some([("obj", obj)].into_py_dict(py));
|
let global = [("obj", obj)].into_py_dict(py).as_borrowed();
|
||||||
let e = 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))",
|
||||||
|
Some(&global),
|
||||||
|
None,
|
||||||
|
)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
assert_eq!(&e.to_string(), "RuntimeError: Already borrowed");
|
assert_eq!(&e.to_string(), "RuntimeError: Already borrowed");
|
||||||
});
|
});
|
||||||
|
@ -271,11 +277,11 @@ mod inheriting_native_type {
|
||||||
fn custom_exception() {
|
fn custom_exception() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let cls = py.get_type::<CustomException>();
|
let cls = py.get_type::<CustomException>();
|
||||||
let dict = [("cls", cls)].into_py_dict(py);
|
let dict = [("cls", cls)].into_py_dict(py).as_borrowed();
|
||||||
let res = py.run(
|
let res = py.run_bound(
|
||||||
"e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e",
|
"e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e",
|
||||||
None,
|
None,
|
||||||
Some(dict)
|
Some(&dict)
|
||||||
);
|
);
|
||||||
let err = res.unwrap_err();
|
let err = res.unwrap_err();
|
||||||
assert!(err.matches(py, cls), "{}", err);
|
assert!(err.matches(py, cls), "{}", err);
|
||||||
|
|
|
@ -687,9 +687,12 @@ if sys.platform == "win32" and sys.version_info >= (3, 8, 0):
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
"#;
|
"#;
|
||||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
let globals = PyModule::import(py, "__main__")
|
||||||
|
.unwrap()
|
||||||
|
.dict()
|
||||||
|
.as_borrowed();
|
||||||
globals.set_item("Once", once).unwrap();
|
globals.set_item("Once", once).unwrap();
|
||||||
py.run(source, Some(globals), None)
|
py.run_bound(source, Some(&globals), None)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
@ -741,12 +744,15 @@ if sys.platform == "win32" and sys.version_info >= (3, 8, 0):
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
"#;
|
"#;
|
||||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
let globals = PyModule::import(py, "__main__")
|
||||||
|
.unwrap()
|
||||||
|
.dict()
|
||||||
|
.as_borrowed();
|
||||||
globals.set_item("Once", once).unwrap();
|
globals.set_item("Once", once).unwrap();
|
||||||
globals
|
globals
|
||||||
.set_item("AsyncIterator", py.get_type::<AsyncIterator>())
|
.set_item("AsyncIterator", py.get_type::<AsyncIterator>())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
py.run(source, Some(globals), None)
|
py.run_bound(source, Some(&globals), None)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
@ -813,9 +819,12 @@ del c.counter
|
||||||
assert c.counter.count == 1
|
assert c.counter.count == 1
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
let globals = PyModule::import(py, "__main__")
|
||||||
|
.unwrap()
|
||||||
|
.dict()
|
||||||
|
.as_borrowed();
|
||||||
globals.set_item("Counter", counter).unwrap();
|
globals.set_item("Counter", counter).unwrap();
|
||||||
py.run(source, Some(globals), None)
|
py.run_bound(source, Some(&globals), None)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue