Use with_gil instead of acquire_gil in examples
This commit is contained in:
parent
3fa10a38d3
commit
aedd6352e3
|
@ -85,25 +85,25 @@ struct MyClass {
|
||||||
num: i32,
|
num: i32,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
}
|
}
|
||||||
let gil = Python::acquire_gil();
|
Python::with_gil(|py| {
|
||||||
let py = gil.python();
|
let obj = PyCell::new(py, MyClass { num: 3, debug: true }).unwrap();
|
||||||
let obj = PyCell::new(py, MyClass { num: 3, debug: true }).unwrap();
|
{
|
||||||
{
|
let obj_ref = obj.borrow(); // Get PyRef
|
||||||
let obj_ref = obj.borrow(); // Get PyRef
|
assert_eq!(obj_ref.num, 3);
|
||||||
assert_eq!(obj_ref.num, 3);
|
// You cannot get PyRefMut unless all PyRefs are dropped
|
||||||
// You cannot get PyRefMut unless all PyRefs are dropped
|
assert!(obj.try_borrow_mut().is_err());
|
||||||
assert!(obj.try_borrow_mut().is_err());
|
}
|
||||||
}
|
{
|
||||||
{
|
let mut obj_mut = obj.borrow_mut(); // Get PyRefMut
|
||||||
let mut obj_mut = obj.borrow_mut(); // Get PyRefMut
|
obj_mut.num = 5;
|
||||||
obj_mut.num = 5;
|
// You cannot get any other refs until the PyRefMut is dropped
|
||||||
// You cannot get any other refs until the PyRefMut is dropped
|
assert!(obj.try_borrow().is_err());
|
||||||
assert!(obj.try_borrow().is_err());
|
assert!(obj.try_borrow_mut().is_err());
|
||||||
assert!(obj.try_borrow_mut().is_err());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// You can convert `&PyCell` to a Python object
|
// You can convert `&PyCell` to a Python object
|
||||||
pyo3::py_run!(py, obj, "assert obj.num == 5")
|
pyo3::py_run!(py, obj, "assert obj.num == 5");
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
`&PyCell<T>` is bounded by the same lifetime as a [`GILGuard`].
|
`&PyCell<T>` is bounded by the same lifetime as a [`GILGuard`].
|
||||||
|
@ -118,15 +118,14 @@ struct MyClass {
|
||||||
num: i32,
|
num: i32,
|
||||||
}
|
}
|
||||||
fn return_myclass() -> Py<MyClass> {
|
fn return_myclass() -> Py<MyClass> {
|
||||||
let gil = Python::acquire_gil();
|
Python::with_gil(|py| Py::new(py, MyClass { num: 1 }).unwrap())
|
||||||
let py = gil.python();
|
|
||||||
Py::new(py, MyClass { num: 1 }).unwrap()
|
|
||||||
}
|
}
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let obj = return_myclass();
|
let obj = return_myclass();
|
||||||
let cell = obj.as_ref(gil.python()); // Py<MyClass>::as_ref returns &PyCell<MyClass>
|
Python::with_gil(|py|{
|
||||||
let obj_ref = cell.borrow(); // Get PyRef<T>
|
let cell = obj.as_ref(py); // Py<MyClass>::as_ref returns &PyCell<MyClass>
|
||||||
assert_eq!(obj_ref.num, 1);
|
let obj_ref = cell.borrow(); // Get PyRef<T>
|
||||||
|
assert_eq!(obj_ref.num, 1);
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## Customizing the class
|
## Customizing the class
|
||||||
|
@ -261,10 +260,10 @@ impl SubSubClass {
|
||||||
SubClass::method2(super_).map(|x| x * v)
|
SubClass::method2(super_).map(|x| x * v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
# let subsub = pyo3::PyCell::new(py, SubSubClass::new()).unwrap();
|
||||||
# let subsub = pyo3::PyCell::new(py, SubSubClass::new()).unwrap();
|
# pyo3::py_run!(py, subsub, "assert subsub.method3() == 3000")
|
||||||
# pyo3::py_run!(py, subsub, "assert subsub.method3() == 3000")
|
# });
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also inherit native types such as `PyDict`, if they implement
|
You can also inherit native types such as `PyDict`, if they implement
|
||||||
|
@ -274,8 +273,7 @@ However, because of some technical problems, we don't currently provide safe upc
|
||||||
that inherit native types. Even in such cases, you can unsafely get a base class by raw pointer conversion.
|
that inherit native types. Even in such cases, you can unsafely get a base class by raw pointer conversion.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #[cfg(Py_LIMITED_API)] fn main() {}
|
# #[cfg(not(Py_LIMITED_API))] {
|
||||||
# #[cfg(not(Py_LIMITED_API))] fn main() {
|
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
use pyo3::types::PyDict;
|
use pyo3::types::PyDict;
|
||||||
use pyo3::{AsPyPointer, PyNativeType};
|
use pyo3::{AsPyPointer, PyNativeType};
|
||||||
|
@ -300,10 +298,10 @@ impl DictWithCounter {
|
||||||
dict.set_item(key, value)
|
dict.set_item(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
# let cnt = pyo3::PyCell::new(py, DictWithCounter::new()).unwrap();
|
||||||
# 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!(py, cnt, "cnt.set('abc', 10); assert cnt['abc'] == 10")
|
# });
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -563,10 +561,10 @@ impl MyClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let gil = Python::acquire_gil();
|
Python::with_gil(|py| {
|
||||||
let py = gil.python();
|
let my_class = py.get_type::<MyClass>();
|
||||||
let my_class = py.get_type::<MyClass>();
|
pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'")
|
||||||
pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'")
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that unlike class variables defined in Python code, class attributes defined in Rust cannot
|
Note that unlike class variables defined in Python code, class attributes defined in Rust cannot
|
||||||
|
@ -712,8 +710,7 @@ This simple technique works for the case when there is zero or one implementatio
|
||||||
The `#[pyclass]` macro expands to roughly the code seen below. The `PyClassImplCollector` is the type used internally by PyO3 for dtolnay specialization:
|
The `#[pyclass]` macro expands to roughly the code seen below. The `PyClassImplCollector` is the type used internally by PyO3 for dtolnay specialization:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #[cfg(not(feature = "multiple-pymethods"))]
|
# #[cfg(not(feature = "multiple-pymethods"))] {
|
||||||
# {
|
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
// Note: the implementation differs slightly with the `multiple-pymethods` feature enabled.
|
// Note: the implementation differs slightly with the `multiple-pymethods` feature enabled.
|
||||||
|
|
||||||
|
@ -808,10 +805,10 @@ impl pyo3::class::impl_::PyClassImpl for MyClass {
|
||||||
collector.buffer_procs()
|
collector.buffer_procs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
# let cls = py.get_type::<MyClass>();
|
||||||
# let cls = py.get_type::<MyClass>();
|
# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'")
|
||||||
# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'")
|
# });
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -275,17 +275,12 @@ impl PyIterProtocol for Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
# let container = Container { iter: vec![1, 2, 3, 4] };
|
||||||
# let inst = pyo3::PyCell::new(
|
# let inst = pyo3::PyCell::new(py, container).unwrap();
|
||||||
# py,
|
# pyo3::py_run!(py, inst, "assert list(inst) == [1, 2, 3, 4]");
|
||||||
# Container {
|
# pyo3::py_run!(py, inst, "assert list(iter(iter(inst))) == [1, 2, 3, 4]");
|
||||||
# iter: vec![1, 2, 3, 4],
|
# });
|
||||||
# },
|
|
||||||
# )
|
|
||||||
# .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]");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For more details on Python's iteration protocols, check out [the "Iterator Types" section of the library
|
For more details on Python's iteration protocols, check out [the "Iterator Types" section of the library
|
||||||
|
|
|
@ -23,14 +23,11 @@ use pyo3::exceptions::PyException;
|
||||||
|
|
||||||
create_exception!(mymodule, CustomError, PyException);
|
create_exception!(mymodule, CustomError, PyException);
|
||||||
|
|
||||||
fn main() {
|
Python::with_gil(|py| {
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
let ctx = [("CustomError", py.get_type::<CustomError>())].into_py_dict(py);
|
let ctx = [("CustomError", py.get_type::<CustomError>())].into_py_dict(py);
|
||||||
|
pyo3::py_run!(py, *ctx, "assert str(CustomError) == \"<class 'mymodule.CustomError'>\"");
|
||||||
py.run("assert str(CustomError) == \"<class 'mymodule.CustomError'>\"", None, Some(&ctx)).unwrap();
|
pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)");
|
||||||
py.run("assert CustomError('oops').args == ('oops',)", None, Some(&ctx)).unwrap();
|
});
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When using PyO3 to create an extension module, you can add the new exception to
|
When using PyO3 to create an extension module, you can add the new exception to
|
||||||
|
@ -58,13 +55,11 @@ To raise an exception, first you need to obtain an exception type and construct
|
||||||
use pyo3::{Python, PyErr};
|
use pyo3::{Python, PyErr};
|
||||||
use pyo3::exceptions::PyTypeError;
|
use pyo3::exceptions::PyTypeError;
|
||||||
|
|
||||||
fn main() {
|
Python::with_gil(|py| {
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
PyTypeError::new_err("Error").restore(py);
|
PyTypeError::new_err("Error").restore(py);
|
||||||
assert!(PyErr::occurred(py));
|
assert!(PyErr::occurred(py));
|
||||||
drop(PyErr::fetch(py));
|
drop(PyErr::fetch(py));
|
||||||
}
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
From `pyfunction`s and `pyclass` methods, returning an `Err(PyErr)` is enough;
|
From `pyfunction`s and `pyclass` methods, returning an `Err(PyErr)` is enough;
|
||||||
|
@ -103,14 +98,12 @@ In PyO3 every native type has access to the [`PyAny::is_instance`] method which
|
||||||
use pyo3::Python;
|
use pyo3::Python;
|
||||||
use pyo3::types::{PyBool, PyList};
|
use pyo3::types::{PyBool, PyList};
|
||||||
|
|
||||||
fn main() {
|
Python::with_gil(|py| {
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
assert!(PyBool::new(py, true).is_instance::<PyBool>().unwrap());
|
assert!(PyBool::new(py, true).is_instance::<PyBool>().unwrap());
|
||||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||||
assert!(!list.is_instance::<PyBool>().unwrap());
|
assert!(!list.is_instance::<PyBool>().unwrap());
|
||||||
assert!(list.is_instance::<PyList>().unwrap());
|
assert!(list.is_instance::<PyList>().unwrap());
|
||||||
}
|
});
|
||||||
```
|
```
|
||||||
[`PyAny::is_instance`] calls the underlying [`PyType::is_instance`](https://docs.rs/pyo3/latest/pyo3/types/struct.PyType.html#method.is_instance)
|
[`PyAny::is_instance`] calls the underlying [`PyType::is_instance`](https://docs.rs/pyo3/latest/pyo3/types/struct.PyType.html#method.is_instance)
|
||||||
method to do the actual work.
|
method to do the actual work.
|
||||||
|
@ -120,10 +113,10 @@ To check the type of an exception, you can similarly do:
|
||||||
```rust
|
```rust
|
||||||
# use pyo3::exceptions::PyTypeError;
|
# use pyo3::exceptions::PyTypeError;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
|
||||||
# let err = PyTypeError::new_err(());
|
# let err = PyTypeError::new_err(());
|
||||||
err.is_instance::<PyTypeError>(py);
|
err.is_instance::<PyTypeError>(py);
|
||||||
|
# });
|
||||||
```
|
```
|
||||||
|
|
||||||
## Handling Rust errors
|
## Handling Rust errors
|
||||||
|
|
|
@ -266,22 +266,16 @@ To migrate, just pass a `py` argument to any calls to these methods.
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
```rust,compile_fail
|
```rust,compile_fail
|
||||||
use pyo3::prelude::*;
|
# pyo3::Python::with_gil(|py| {
|
||||||
|
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
|
|
||||||
py.None().get_refcnt();
|
py.None().get_refcnt();
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
```rust
|
```rust
|
||||||
use pyo3::prelude::*;
|
# pyo3::Python::with_gil(|py| {
|
||||||
|
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
|
|
||||||
py.None().get_refcnt(py);
|
py.None().get_refcnt(py);
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
## from 0.9.* to 0.10
|
## from 0.9.* to 0.10
|
||||||
|
@ -296,18 +290,20 @@ Before:
|
||||||
```rust,compile_fail
|
```rust,compile_fail
|
||||||
use pyo3::ObjectProtocol;
|
use pyo3::ObjectProtocol;
|
||||||
|
|
||||||
let gil = pyo3::Python::acquire_gil();
|
# pyo3::Python::with_gil(|py| {
|
||||||
let obj = gil.python().eval("lambda: 'Hi :)'", None, None).unwrap();
|
let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap();
|
||||||
let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap();
|
let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap();
|
||||||
assert_eq!(hi.len().unwrap(), 5);
|
assert_eq!(hi.len().unwrap(), 5);
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
```rust
|
```rust
|
||||||
let gil = pyo3::Python::acquire_gil();
|
# pyo3::Python::with_gil(|py| {
|
||||||
let obj = gil.python().eval("lambda: 'Hi :)'", None, None).unwrap();
|
let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap();
|
||||||
let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap();
|
let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap();
|
||||||
assert_eq!(hi.len().unwrap(), 5);
|
assert_eq!(hi.len().unwrap(), 5);
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
### No `#![feature(specialization)]` in user code
|
### No `#![feature(specialization)]` in user code
|
||||||
|
@ -380,16 +376,16 @@ impl Names {
|
||||||
self.names.append(&mut other.names)
|
self.names.append(&mut other.names)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
# let names = PyCell::new(py, Names::new()).unwrap();
|
||||||
# let names = PyCell::new(py, Names::new()).unwrap();
|
# pyo3::py_run!(py, names, r"
|
||||||
# pyo3::py_run!(py, names, r"
|
# try:
|
||||||
# try:
|
# names.merge(names)
|
||||||
# names.merge(names)
|
# assert False, 'Unreachable'
|
||||||
# assert False, 'Unreachable'
|
# except RuntimeError as e:
|
||||||
# except RuntimeError as e:
|
# assert str(e) == 'Already borrowed'
|
||||||
# assert str(e) == 'Already borrowed'
|
# ");
|
||||||
# ");
|
# })
|
||||||
```
|
```
|
||||||
`Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`.
|
`Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`.
|
||||||
Given this `#[pyclass]`, calling `names.merge(names)` in Python raises
|
Given this `#[pyclass]`, calling `names.merge(names)` in Python raises
|
||||||
|
@ -410,9 +406,9 @@ Before:
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# #[pyclass]
|
# #[pyclass]
|
||||||
# struct MyClass {}
|
# struct MyClass {}
|
||||||
let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
let py = gil.python();
|
|
||||||
let obj_ref = PyRef::new(py, MyClass {}).unwrap();
|
let obj_ref = PyRef::new(py, MyClass {}).unwrap();
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
|
@ -420,10 +416,10 @@ After:
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# #[pyclass]
|
# #[pyclass]
|
||||||
# struct MyClass {}
|
# struct MyClass {}
|
||||||
let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
let py = gil.python();
|
|
||||||
let obj = PyCell::new(py, MyClass {}).unwrap();
|
let obj = PyCell::new(py, MyClass {}).unwrap();
|
||||||
let obj_ref = obj.borrow();
|
let obj_ref = obj.borrow();
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Object extraction
|
#### Object extraction
|
||||||
|
@ -445,8 +441,7 @@ After:
|
||||||
# use pyo3::types::IntoPyDict;
|
# use pyo3::types::IntoPyDict;
|
||||||
# #[pyclass] #[derive(Clone)] struct MyClass {}
|
# #[pyclass] #[derive(Clone)] struct MyClass {}
|
||||||
# #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }}
|
# #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }}
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
|
||||||
# let typeobj = py.get_type::<MyClass>();
|
# let typeobj = py.get_type::<MyClass>();
|
||||||
# let d = [("c", typeobj)].into_py_dict(py);
|
# let d = [("c", typeobj)].into_py_dict(py);
|
||||||
# let create_obj = || py.eval("c()", None, Some(d)).unwrap();
|
# let create_obj = || py.eval("c()", None, Some(d)).unwrap();
|
||||||
|
@ -458,6 +453,7 @@ let obj_cloned: MyClass = obj.extract().unwrap(); // extracted by cloning the ob
|
||||||
// we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references
|
// we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references
|
||||||
}
|
}
|
||||||
let obj_ref_mut: PyRefMut<MyClass> = obj.extract().unwrap();
|
let obj_ref_mut: PyRefMut<MyClass> = obj.extract().unwrap();
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,21 +38,20 @@ fn main() {
|
||||||
let arg2 = "arg2";
|
let arg2 = "arg2";
|
||||||
let arg3 = "arg3";
|
let arg3 = "arg3";
|
||||||
|
|
||||||
let gil = Python::acquire_gil();
|
Python::with_gil(|py| {
|
||||||
let py = gil.python();
|
let obj = SomeObject::new(py);
|
||||||
|
|
||||||
let obj = SomeObject::new(py);
|
// call object without empty arguments
|
||||||
|
obj.call0(py);
|
||||||
|
|
||||||
// call object without empty arguments
|
// call object with PyTuple
|
||||||
obj.call0(py);
|
let args = PyTuple::new(py, &[arg1, arg2, arg3]);
|
||||||
|
obj.call1(py, args);
|
||||||
|
|
||||||
// call object with PyTuple
|
// pass arguments as rust tuple
|
||||||
let args = PyTuple::new(py, &[arg1, arg2, arg3]);
|
let args = (arg1, arg2, arg3);
|
||||||
obj.call1(py, args);
|
obj.call1(py, args);
|
||||||
|
});
|
||||||
// pass arguments as rust tuple
|
|
||||||
let args = (arg1, arg2, arg3);
|
|
||||||
obj.call1(py, args);
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -79,23 +78,22 @@ fn main() {
|
||||||
let key2 = "key2";
|
let key2 = "key2";
|
||||||
let val2 = 2;
|
let val2 = 2;
|
||||||
|
|
||||||
let gil = Python::acquire_gil();
|
Python::with_gil(|py| {
|
||||||
let py = gil.python();
|
let obj = SomeObject::new(py);
|
||||||
|
|
||||||
let obj = SomeObject::new(py);
|
// call object with PyDict
|
||||||
|
let kwargs = [(key1, val1)].into_py_dict(py);
|
||||||
|
obj.call(py, (), Some(kwargs));
|
||||||
|
|
||||||
// call object with PyDict
|
// pass arguments as Vec
|
||||||
let kwargs = [(key1, val1)].into_py_dict(py);
|
let kwargs = vec![(key1, val1), (key2, val2)];
|
||||||
obj.call(py, (), Some(kwargs));
|
obj.call(py, (), Some(kwargs.into_py_dict(py)));
|
||||||
|
|
||||||
// pass arguments as Vec
|
// pass arguments as HashMap
|
||||||
let kwargs = vec![(key1, val1), (key2, val2)];
|
let mut kwargs = HashMap::<&str, i32>::new();
|
||||||
obj.call(py, (), Some(kwargs.into_py_dict(py)));
|
kwargs.insert(key1, 1);
|
||||||
|
obj.call(py, (), Some(kwargs.into_py_dict(py)));
|
||||||
// pass arguments as HashMap
|
});
|
||||||
let mut kwargs = HashMap::<&str, i32>::new();
|
|
||||||
kwargs.insert(key1, 1);
|
|
||||||
obj.call(py, (), Some(kwargs.into_py_dict(py)));
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -170,8 +170,7 @@ For a `Py<PyList>`, the conversions are as below:
|
||||||
```rust
|
```rust
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyList;
|
# use pyo3::types::PyList;
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
|
||||||
let list: Py<PyList> = PyList::empty(py).into();
|
let list: Py<PyList> = PyList::empty(py).into();
|
||||||
|
|
||||||
// To &PyList with Py::as_ref() (borrows from the Py)
|
// To &PyList with Py::as_ref() (borrows from the Py)
|
||||||
|
@ -184,14 +183,14 @@ let _: &PyList = list.into_ref(py);
|
||||||
# let list = list_clone;
|
# let list = list_clone;
|
||||||
// To Py<PyAny> (aka PyObject) with .into()
|
// To Py<PyAny> (aka PyObject) with .into()
|
||||||
let _: Py<PyAny> = list.into();
|
let _: Py<PyAny> = list.into();
|
||||||
|
# })
|
||||||
```
|
```
|
||||||
|
|
||||||
For a `#[pyclass] struct MyClass`, the conversions for `Py<MyClass>` are below:
|
For a `#[pyclass] struct MyClass`, the conversions for `Py<MyClass>` are below:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# let gil = Python::acquire_gil();
|
# Python::with_gil(|py| {
|
||||||
# let py = gil.python();
|
|
||||||
# #[pyclass] struct MyClass { }
|
# #[pyclass] struct MyClass { }
|
||||||
# Python::with_gil(|py| -> PyResult<()> {
|
# Python::with_gil(|py| -> PyResult<()> {
|
||||||
let my_class: Py<MyClass> = Py::new(py, MyClass { })?;
|
let my_class: Py<MyClass> = Py::new(py, MyClass { })?;
|
||||||
|
@ -215,6 +214,7 @@ let _: PyRef<MyClass> = my_class.try_borrow(py)?;
|
||||||
let _: PyRefMut<MyClass> = my_class.try_borrow_mut(py)?;
|
let _: PyRefMut<MyClass> = my_class.try_borrow_mut(py)?;
|
||||||
# Ok(())
|
# Ok(())
|
||||||
# }).unwrap();
|
# }).unwrap();
|
||||||
|
# });
|
||||||
```
|
```
|
||||||
|
|
||||||
### `PyCell<SomeType>`
|
### `PyCell<SomeType>`
|
||||||
|
|
|
@ -38,11 +38,10 @@ use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, Python};
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # let gil = Python::acquire_gil();
|
/// # Python::with_gil(|py| {
|
||||||
/// # let py = gil.python();
|
/// # let inst = Py::new(py, Iter { count: 0 }).unwrap();
|
||||||
/// # let inst = Py::new(py, Iter { count: 0 }).unwrap();
|
/// # pyo3::py_run!(py, inst, "assert next(inst) == 1");
|
||||||
/// # pyo3::py_run!(py, inst, "assert next(inst) == 1");
|
/// # }); // test of StopIteration is done in examples/rustapi_module/pyclass_iter.rs
|
||||||
/// # // test of StopIteration is done in examples/rustapi_module/pyclass_iter.rs
|
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub trait PyIterProtocol<'p>: PyClass {
|
pub trait PyIterProtocol<'p>: PyClass {
|
||||||
|
|
|
@ -18,10 +18,11 @@ use std::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{AsPyPointer, prelude::*};
|
/// use pyo3::{AsPyPointer, prelude::*};
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let dict = pyo3::types::PyDict::new(gil.python());
|
/// let dict = pyo3::types::PyDict::new(py);
|
||||||
/// // All native object wrappers implement AsPyPointer!!!
|
/// // All native object wrappers implement AsPyPointer!!!
|
||||||
/// assert_ne!(dict.as_ptr(), std::ptr::null_mut());
|
/// assert_ne!(dict.as_ptr(), std::ptr::null_mut());
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub trait AsPyPointer {
|
pub trait AsPyPointer {
|
||||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||||
|
|
|
@ -60,16 +60,10 @@ macro_rules! impl_exception_boilerplate {
|
||||||
/// import_exception!(socket, gaierror);
|
/// import_exception!(socket, gaierror);
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let ctx = [("gaierror", py.get_type::<gaierror>())].into_py_dict(py);
|
||||||
///
|
/// pyo3::py_run!(py, *ctx, "import socket; assert gaierror is socket.gaierror");
|
||||||
/// let ctx = [("gaierror", py.get_type::<gaierror>())].into_py_dict(py);
|
/// });
|
||||||
/// py.run(
|
|
||||||
/// "import socket; assert gaierror is socket.gaierror",
|
|
||||||
/// None,
|
|
||||||
/// Some(ctx),
|
|
||||||
/// )
|
|
||||||
/// .unwrap();
|
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -137,22 +131,17 @@ macro_rules! import_exception {
|
||||||
/// create_exception!(mymodule, CustomError, PyException);
|
/// create_exception!(mymodule, CustomError, PyException);
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let error_type = py.get_type::<CustomError>();
|
||||||
/// let error_type = py.get_type::<CustomError>();
|
/// let ctx = [("CustomError", error_type)].into_py_dict(py);
|
||||||
/// let ctx = [("CustomError", error_type)].into_py_dict(py);
|
/// let type_description: String = py
|
||||||
/// let type_description: String = py
|
/// .eval("str(CustomError)", None, Some(&ctx))
|
||||||
/// .eval("str(CustomError)", None, Some(&ctx))
|
/// .unwrap()
|
||||||
/// .unwrap()
|
/// .extract()
|
||||||
/// .extract()
|
/// .unwrap();
|
||||||
/// .unwrap();
|
/// assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
||||||
/// assert_eq!(type_description, "<class 'mymodule.CustomError'>");
|
/// pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)");
|
||||||
/// py.run(
|
/// });
|
||||||
/// "assert CustomError('oops').args == ('oops',)",
|
|
||||||
/// None,
|
|
||||||
/// Some(ctx),
|
|
||||||
/// )
|
|
||||||
/// .unwrap();
|
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
@ -178,8 +178,11 @@ where
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RAII type that represents the Global Interpreter Lock acquisition. To get hold of a value of
|
/// RAII type that represents the Global Interpreter Lock acquisition.
|
||||||
/// this type, see [`Python::acquire_gil`](struct.Python.html#method.acquire_gil).
|
///
|
||||||
|
/// Users are strongly encouraged to [`Python::with_gil`](struct.Python.html#method.with_gil)
|
||||||
|
/// instead of directly constructing this type.
|
||||||
|
/// See [`Python::acquire_gil`](struct.Python.html#method.acquire_gil) for more.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -286,6 +286,10 @@ macro_rules! wrap_pymodule {
|
||||||
|
|
||||||
/// A convenient macro to execute a Python code snippet, with some local variables set.
|
/// A convenient macro to execute a Python code snippet, with some local variables set.
|
||||||
///
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// This macro internally calls [`Python::run`](struct.Python.html#method.run) and panics
|
||||||
|
/// if it returns `Err`, after printing the error to stdout.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{prelude::*, py_run, types::PyList};
|
/// use pyo3::{prelude::*, py_run, types::PyList};
|
||||||
|
@ -297,7 +301,6 @@ macro_rules! wrap_pymodule {
|
||||||
///
|
///
|
||||||
/// You can use this macro to test pyfunctions or pyclasses quickly.
|
/// You can use this macro to test pyfunctions or pyclasses quickly.
|
||||||
///
|
///
|
||||||
/// # Examples
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{prelude::*, py_run, PyCell};
|
/// use pyo3::{prelude::*, py_run, PyCell};
|
||||||
/// #[pyclass]
|
/// #[pyclass]
|
||||||
|
|
5
src/marshal.rs
Normal file → Executable file
5
src/marshal.rs
Normal file → Executable file
|
@ -21,15 +21,14 @@ pub const VERSION: i32 = 4;
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use pyo3::{marshal, types::PyDict};
|
/// # use pyo3::{marshal, types::PyDict};
|
||||||
/// # let gil = pyo3::Python::acquire_gil();
|
/// # pyo3::Python::with_gil(|py| {
|
||||||
/// # let py = gil.python();
|
|
||||||
/// #
|
|
||||||
/// let dict = PyDict::new(py);
|
/// let dict = PyDict::new(py);
|
||||||
/// dict.set_item("aap", "noot").unwrap();
|
/// dict.set_item("aap", "noot").unwrap();
|
||||||
/// dict.set_item("mies", "wim").unwrap();
|
/// dict.set_item("mies", "wim").unwrap();
|
||||||
/// dict.set_item("zus", "jet").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> {
|
pub fn dumps<'a>(py: Python<'a>, object: &impl AsPyPointer, version: i32) -> PyResult<&'a PyBytes> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -25,9 +25,7 @@ use std::cell::UnsafeCell;
|
||||||
/// .get_or_init(py, || PyList::empty(py).into())
|
/// .get_or_init(py, || PyList::empty(py).into())
|
||||||
/// .as_ref(py)
|
/// .as_ref(py)
|
||||||
/// }
|
/// }
|
||||||
/// # let gil = Python::acquire_gil();
|
/// # Python::with_gil(|py| assert_eq!(get_shared_list(py).len(), 0));
|
||||||
/// # let py = gil.python();
|
|
||||||
/// # assert_eq!(get_shared_list(py).len(), 0 );
|
|
||||||
/// ```
|
/// ```
|
||||||
pub struct GILOnceCell<T>(UnsafeCell<Option<T>>);
|
pub struct GILOnceCell<T>(UnsafeCell<Option<T>>);
|
||||||
|
|
||||||
|
|
|
@ -121,15 +121,15 @@ impl<T: PyClass> PyCellInner<T> {
|
||||||
/// name: &'static str,
|
/// name: &'static str,
|
||||||
/// author: &'static str,
|
/// author: &'static str,
|
||||||
/// }
|
/// }
|
||||||
/// let gil = Python::acquire_gil();
|
|
||||||
/// let py = gil.python();
|
|
||||||
/// let book = Book {
|
/// let book = Book {
|
||||||
/// name: "The Man in the High Castle",
|
/// name: "The Man in the High Castle",
|
||||||
/// author: "Philip Kindred Dick",
|
/// author: "Philip Kindred Dick",
|
||||||
/// };
|
/// };
|
||||||
/// let book_cell = PyCell::new(py, book).unwrap();
|
/// Python::with_gil(|py| {
|
||||||
/// // you can expose PyCell to Python snippets
|
/// let book_cell = PyCell::new(py, book).unwrap();
|
||||||
/// pyo3::py_run!(py, book_cell, "assert book_cell.name[-6:] == 'Castle'");
|
/// // `&PyCell` implements `ToPyObject`, so you can use it in a Python snippet
|
||||||
|
/// pyo3::py_run!(py, book_cell, "assert book_cell.name[-6:] == 'Castle'");
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
/// You can use `slf: &PyCell<Self>` as an alternative `self` receiver of `#[pymethod]`,
|
/// You can use `slf: &PyCell<Self>` as an alternative `self` receiver of `#[pymethod]`,
|
||||||
/// though you rarely need it.
|
/// though you rarely need it.
|
||||||
|
@ -154,10 +154,10 @@ impl<T: PyClass> PyCellInner<T> {
|
||||||
/// Ok(*counter)
|
/// Ok(*counter)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// # let gil = Python::acquire_gil();
|
/// # Python::with_gil(|py| {
|
||||||
/// # let py = gil.python();
|
/// # let counter = PyCell::new(py, Counter::default()).unwrap();
|
||||||
/// # let counter = PyCell::new(py, Counter::default()).unwrap();
|
/// # pyo3::py_run!(py, counter, "assert counter.increment('cat') == 1");
|
||||||
/// # pyo3::py_run!(py, counter, "assert counter.increment('cat') == 1");
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PyCell<T: PyClass> {
|
pub struct PyCell<T: PyClass> {
|
||||||
|
@ -245,18 +245,18 @@ impl<T: PyClass> PyCell<T> {
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// #[pyclass]
|
/// #[pyclass]
|
||||||
/// struct Class {}
|
/// struct Class {}
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let c = PyCell::new(py, Class {}).unwrap();
|
||||||
/// let c = PyCell::new(py, Class {}).unwrap();
|
/// {
|
||||||
/// {
|
/// let m = c.borrow_mut();
|
||||||
/// let m = c.borrow_mut();
|
/// assert!(c.try_borrow().is_err());
|
||||||
/// assert!(c.try_borrow().is_err());
|
/// }
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// {
|
/// {
|
||||||
/// let m = c.borrow();
|
/// let m = c.borrow();
|
||||||
/// assert!(c.try_borrow().is_ok());
|
/// assert!(c.try_borrow().is_ok());
|
||||||
/// }
|
/// }
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_borrow(&self) -> Result<PyRef<'_, T>, PyBorrowError> {
|
pub fn try_borrow(&self) -> Result<PyRef<'_, T>, PyBorrowError> {
|
||||||
self.thread_checker.ensure();
|
self.thread_checker.ensure();
|
||||||
|
@ -280,15 +280,15 @@ impl<T: PyClass> PyCell<T> {
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// #[pyclass]
|
/// #[pyclass]
|
||||||
/// struct Class {}
|
/// struct Class {}
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let c = PyCell::new(py, Class {}).unwrap();
|
||||||
/// let c = PyCell::new(py, Class {}).unwrap();
|
/// {
|
||||||
/// {
|
/// let m = c.borrow();
|
||||||
/// let m = c.borrow();
|
/// assert!(c.try_borrow_mut().is_err());
|
||||||
/// assert!(c.try_borrow_mut().is_err());
|
/// }
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// assert!(c.try_borrow_mut().is_ok());
|
/// assert!(c.try_borrow_mut().is_ok());
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_borrow_mut(&self) -> Result<PyRefMut<'_, T>, PyBorrowMutError> {
|
pub fn try_borrow_mut(&self) -> Result<PyRefMut<'_, T>, PyBorrowMutError> {
|
||||||
self.thread_checker.ensure();
|
self.thread_checker.ensure();
|
||||||
|
@ -315,19 +315,19 @@ impl<T: PyClass> PyCell<T> {
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// #[pyclass]
|
/// #[pyclass]
|
||||||
/// struct Class {}
|
/// struct Class {}
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let c = PyCell::new(py, Class {}).unwrap();
|
||||||
/// let c = PyCell::new(py, Class {}).unwrap();
|
|
||||||
///
|
///
|
||||||
/// {
|
/// {
|
||||||
/// let m = c.borrow_mut();
|
/// let m = c.borrow_mut();
|
||||||
/// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
|
/// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// {
|
/// {
|
||||||
/// let m = c.borrow();
|
/// let m = c.borrow();
|
||||||
/// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
|
/// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
|
||||||
/// }
|
/// }
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, PyBorrowError> {
|
pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, PyBorrowError> {
|
||||||
self.thread_checker.ensure();
|
self.thread_checker.ensure();
|
||||||
|
@ -485,10 +485,10 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
|
||||||
/// format!("{}(base: {}, cnt: {})", slf.name, basename, refcnt)
|
/// format!("{}(base: {}, cnt: {})", slf.name, basename, refcnt)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// # let gil = Python::acquire_gil();
|
/// # Python::with_gil(|py| {
|
||||||
/// # let py = gil.python();
|
/// # let sub = PyCell::new(py, Child::new()).unwrap();
|
||||||
/// # let sub = PyCell::new(py, Child::new()).unwrap();
|
/// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 3)'");
|
||||||
/// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 3)'");
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub struct PyRef<'p, T: PyClass> {
|
pub struct PyRef<'p, T: PyClass> {
|
||||||
inner: &'p PyCellInner<T>,
|
inner: &'p PyCellInner<T>,
|
||||||
|
@ -549,10 +549,10 @@ where
|
||||||
/// format!("{} {} {}", super_.as_ref().name1, super_.name2, subname)
|
/// format!("{} {} {}", super_.as_ref().name1, super_.name2, subname)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// # let gil = Python::acquire_gil();
|
/// # Python::with_gil(|py| {
|
||||||
/// # let py = gil.python();
|
/// # let sub = PyCell::new(py, Sub::new()).unwrap();
|
||||||
/// # let sub = PyCell::new(py, Sub::new()).unwrap();
|
/// # pyo3::py_run!(py, sub, "assert sub.name() == 'base1 base2 sub'")
|
||||||
/// # pyo3::py_run!(py, sub, "assert sub.name() == 'base1 base2 sub'")
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn into_super(self) -> PyRef<'p, U> {
|
pub fn into_super(self) -> PyRef<'p, U> {
|
||||||
let PyRef { inner } = self;
|
let PyRef { inner } = self;
|
||||||
|
|
|
@ -30,6 +30,7 @@ impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// # use pyo3::py_run;
|
/// # use pyo3::py_run;
|
||||||
|
/// # use pyo3::types::IntoPyDict;
|
||||||
/// #[pyclass(subclass)]
|
/// #[pyclass(subclass)]
|
||||||
/// struct BaseClass {
|
/// struct BaseClass {
|
||||||
/// #[pyo3(get)]
|
/// #[pyo3(get)]
|
||||||
|
@ -55,14 +56,18 @@ impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
|
||||||
/// .add_subclass(SubSubClass { subsubname: "subsub" })
|
/// .add_subclass(SubSubClass { subsubname: "subsub" })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let typeobj = py.get_type::<SubSubClass>();
|
||||||
/// let typeobj = py.get_type::<SubSubClass>();
|
/// let sub_sub_class = typeobj.call((), None).unwrap();
|
||||||
/// let inst = typeobj.call((), None).unwrap();
|
/// py_run!(
|
||||||
/// py_run!(py, inst, r#"
|
/// py,
|
||||||
/// assert inst.basename == 'base'
|
/// sub_sub_class,
|
||||||
/// assert inst.subname == 'sub'
|
/// r#"
|
||||||
/// assert inst.subsubname == 'subsub'"#);
|
/// assert sub_sub_class.basename == 'base'
|
||||||
|
/// assert sub_sub_class.subname == 'sub'
|
||||||
|
/// assert sub_sub_class.subsubname == 'subsub'"#
|
||||||
|
/// );
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub struct PyClassInitializer<T: PyClass> {
|
pub struct PyClassInitializer<T: PyClass> {
|
||||||
init: T,
|
init: T,
|
||||||
|
|
|
@ -208,15 +208,16 @@ impl<'p> Python<'p> {
|
||||||
/// Ok(sum)
|
/// Ok(sum)
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// let gil = Python::acquire_gil();
|
///
|
||||||
/// let py = gil.python();
|
/// Python::with_gil(|py| {
|
||||||
/// let m = PyModule::new(py, "pcount").unwrap();
|
/// let m = PyModule::new(py, "pcount").unwrap();
|
||||||
/// m.add_function(wrap_pyfunction!(parallel_count, m).unwrap()).unwrap();
|
/// m.add_function(wrap_pyfunction!(parallel_count, m).unwrap()).unwrap();
|
||||||
/// let locals = [("pcount", m)].into_py_dict(py);
|
/// let locals = [("pcount", m)].into_py_dict(py);
|
||||||
/// py.run(r#"
|
/// pyo3::py_run!(py, *locals, r#"
|
||||||
/// s = ["Flow", "my", "tears", "the", "Policeman", "Said"]
|
/// s = ["Flow", "my", "tears", "the", "Policeman", "Said"]
|
||||||
/// assert pcount.parallel_count(s, "a") == 3
|
/// assert pcount.parallel_count(s, "a") == 3
|
||||||
/// "#, None, Some(locals));
|
/// "#);
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// **Note:**
|
/// **Note:**
|
||||||
|
@ -280,11 +281,11 @@ impl<'p> Python<'p> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use pyo3::{types::{PyBytes, PyDict}, prelude::*};
|
/// # use pyo3::{types::{PyBytes, PyDict}, prelude::*};
|
||||||
/// # let gil = pyo3::Python::acquire_gil();
|
/// # Python::with_gil(|py| {
|
||||||
/// # let py = gil.python();
|
|
||||||
/// let result = py.eval("[i * 10 for i in range(5)]", None, None).unwrap();
|
/// let result = py.eval("[i * 10 for i in range(5)]", None, None).unwrap();
|
||||||
/// let res: Vec<i64> = result.extract().unwrap();
|
/// let res: Vec<i64> = result.extract().unwrap();
|
||||||
/// assert_eq!(res, vec![0, 10, 20, 30, 40])
|
/// assert_eq!(res, vec![0, 10, 20, 30, 40])
|
||||||
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval(
|
pub fn eval(
|
||||||
self,
|
self,
|
||||||
|
@ -303,22 +304,26 @@ impl<'p> Python<'p> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{types::{PyBytes, PyDict}, prelude::*};
|
/// use pyo3::{types::{PyBytes, PyDict}, prelude::*};
|
||||||
/// let gil = pyo3::Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let locals = PyDict::new(py);
|
||||||
/// let locals = PyDict::new(py);
|
/// py.run(
|
||||||
/// py.run(
|
/// 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();
|
/// )
|
||||||
/// let ret = locals.get_item("ret").unwrap();
|
/// .unwrap();
|
||||||
/// let b64: &PyBytes = ret.downcast().unwrap();
|
/// let ret = locals.get_item("ret").unwrap();
|
||||||
/// assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE=");
|
/// let b64: &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`
|
||||||
|
/// if you don't need `globals` and unwrapping is OK.
|
||||||
pub fn run(
|
pub fn run(
|
||||||
self,
|
self,
|
||||||
code: &str,
|
code: &str,
|
||||||
|
@ -602,21 +607,20 @@ impl<'p> Python<'p> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// // Some long-running process like a webserver, which never releases the GIL.
|
||||||
|
/// loop {
|
||||||
|
/// // Create a new pool, so that PyO3 can clear memory at the end of the loop.
|
||||||
|
/// let pool = unsafe { py.new_pool() };
|
||||||
///
|
///
|
||||||
/// // Some long-running process like a webserver, which never releases the GIL.
|
/// // It is recommended to *always* immediately set py to the pool's Python, to help
|
||||||
/// loop {
|
/// // avoid creating references with invalid lifetimes.
|
||||||
/// // Create a new pool, so that PyO3 can clear memory at the end of the loop.
|
/// let py = unsafe { pool.python() };
|
||||||
/// let pool = unsafe { py.new_pool() };
|
|
||||||
///
|
///
|
||||||
/// // It is recommended to *always* immediately set py to the pool's Python, to help
|
/// // do stuff...
|
||||||
/// // avoid creating references with invalid lifetimes.
|
/// # break; // Exit the loop so that doctest terminates!
|
||||||
/// let py = unsafe { pool.python() };
|
/// }
|
||||||
///
|
/// });
|
||||||
/// // do stuff...
|
|
||||||
/// # break; // Exit the loop so that doctest terminates!
|
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
|
|
@ -28,12 +28,13 @@ use std::os::raw::c_int;
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::prelude::*;
|
/// use pyo3::prelude::*;
|
||||||
/// use pyo3::types::{PyAny, PyDict, PyList};
|
/// use pyo3::types::{PyAny, PyDict, PyList};
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let dict = PyDict::new(gil.python());
|
/// let dict = PyDict::new(py);
|
||||||
/// assert!(dict.is_instance::<PyAny>().unwrap());
|
/// assert!(dict.is_instance::<PyAny>().unwrap());
|
||||||
/// let any: &PyAny = dict.as_ref();
|
/// let any: &PyAny = dict.as_ref();
|
||||||
/// assert!(any.downcast::<PyDict>().is_ok());
|
/// assert!(any.downcast::<PyDict>().is_ok());
|
||||||
/// assert!(any.downcast::<PyList>().is_err());
|
/// assert!(any.downcast::<PyList>().is_err());
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct PyAny(UnsafeCell<ffi::PyObject>);
|
pub struct PyAny(UnsafeCell<ffi::PyObject>);
|
||||||
|
@ -255,16 +256,16 @@ impl PyAny {
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// use pyo3::types::IntoPyDict;
|
/// use pyo3::types::IntoPyDict;
|
||||||
///
|
///
|
||||||
/// let gil = Python::acquire_gil();
|
/// Python::with_gil(|py| {
|
||||||
/// let py = gil.python();
|
/// let list = vec![3, 6, 5, 4, 7].to_object(py);
|
||||||
/// let list = vec![3, 6, 5, 4, 7].to_object(py);
|
/// let dict = vec![("reverse", true)].into_py_dict(py);
|
||||||
/// let dict = vec![("reverse", true)].into_py_dict(py);
|
/// list.call_method(py, "sort", (), Some(dict)).unwrap();
|
||||||
/// list.call_method(py, "sort", (), Some(dict)).unwrap();
|
/// assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3]);
|
||||||
/// assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3]);
|
|
||||||
///
|
///
|
||||||
/// let new_element = 1.to_object(py);
|
/// let new_element = 1.to_object(py);
|
||||||
/// list.call_method(py, "append", (new_element,), None).unwrap();
|
/// list.call_method(py, "append", (new_element,), None).unwrap();
|
||||||
/// assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3, 1]);
|
/// assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3, 1]);
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn call_method(
|
pub fn call_method(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -133,10 +133,7 @@ impl PyByteArray {
|
||||||
/// ```
|
/// ```
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// # use pyo3::types::PyByteArray;
|
/// # use pyo3::types::PyByteArray;
|
||||||
/// # use pyo3::types::IntoPyDict;
|
/// # Python::with_gil(|py| {
|
||||||
/// # let gil = Python::acquire_gil();
|
|
||||||
/// # let py = gil.python();
|
|
||||||
/// #
|
|
||||||
/// let bytearray = PyByteArray::new(py, b"Hello World.");
|
/// let bytearray = PyByteArray::new(py, b"Hello World.");
|
||||||
/// let mut copied_message = bytearray.to_vec();
|
/// let mut copied_message = bytearray.to_vec();
|
||||||
/// assert_eq!(b"Hello World.", copied_message.as_slice());
|
/// assert_eq!(b"Hello World.", copied_message.as_slice());
|
||||||
|
@ -144,8 +141,8 @@ impl PyByteArray {
|
||||||
/// copied_message[11] = b'!';
|
/// copied_message[11] = b'!';
|
||||||
/// assert_eq!(b"Hello World!", copied_message.as_slice());
|
/// assert_eq!(b"Hello World!", copied_message.as_slice());
|
||||||
///
|
///
|
||||||
/// let locals = [("bytearray", bytearray)].into_py_dict(py);
|
/// pyo3::py_run!(py, bytearray, "assert bytearray == b'Hello World.'");
|
||||||
/// py.run("assert bytearray == b'Hello World.'", None, Some(locals)).unwrap();
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn to_vec(&self) -> Vec<u8> {
|
pub fn to_vec(&self) -> Vec<u8> {
|
||||||
unsafe { self.as_bytes() }.to_vec()
|
unsafe { self.as_bytes() }.to_vec()
|
||||||
|
|
Loading…
Reference in a new issue