Rename PyClassShell with PyCell
This commit is contained in:
parent
6069ee1239
commit
a2408cacbb
|
@ -34,7 +34,7 @@ impl pyo3::pyclass::PyClassAlloc for MyClass {}
|
|||
unsafe impl pyo3::PyTypeInfo for MyClass {
|
||||
type Type = MyClass;
|
||||
type BaseType = pyo3::types::PyAny;
|
||||
type ConcreteLayout = pyo3::PyClassShell<Self>;
|
||||
type ConcreteLayout = pyo3::PyCell<Self>;
|
||||
type Initializer = pyo3::PyClassInitializer<Self>;
|
||||
|
||||
const NAME: &'static str = "MyClass";
|
||||
|
@ -109,19 +109,19 @@ fn mymodule(_py: Python, m: &PyModule) -> PyResult<()> {
|
|||
You sometimes need to convert your `pyclass` into a Python object in Rust code (e.g., for testing it).
|
||||
|
||||
For getting *GIL-bounded* (i.e., with `'py` lifetime) references of `pyclass`,
|
||||
you can use `PyClassShell<T>`.
|
||||
you can use `PyCell<T>`.
|
||||
Or you can use `Py<T>` directly, for *not-GIL-bounded* references.
|
||||
|
||||
### `PyClassShell`
|
||||
`PyClassShell` represents the actual layout of `pyclass` on the Python heap.
|
||||
### `PyCell`
|
||||
`PyCell` represents the actual layout of `pyclass` on the Python heap.
|
||||
|
||||
If you want to instantiate `pyclass` in Python and get the reference,
|
||||
you can use `PyClassShell::new_ref` or `PyClassShell::new_mut`.
|
||||
you can use `PyCell::new_ref` or `PyCell::new_mut`.
|
||||
|
||||
```rust
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::types::PyDict;
|
||||
# use pyo3::PyClassShell;
|
||||
# use pyo3::PyCell;
|
||||
#[pyclass]
|
||||
struct MyClass {
|
||||
num: i32,
|
||||
|
@ -129,15 +129,15 @@ struct MyClass {
|
|||
}
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj = PyClassShell::new_ref(py, MyClass { num: 3, debug: true }).unwrap();
|
||||
let obj = PyCell::new_ref(py, MyClass { num: 3, debug: true }).unwrap();
|
||||
// You can use deref
|
||||
assert_eq!(obj.num, 3);
|
||||
let dict = PyDict::new(py);
|
||||
// You can treat a `&PyClassShell` as a normal Python object
|
||||
// You can treat a `&PyCell` as a normal Python object
|
||||
dict.set_item("obj", obj).unwrap();
|
||||
|
||||
// return &mut PyClassShell<MyClass>
|
||||
let obj = PyClassShell::new_mut(py, MyClass { num: 3, debug: true }).unwrap();
|
||||
// return &mut PyCell<MyClass>
|
||||
let obj = PyCell::new_mut(py, MyClass { num: 3, debug: true }).unwrap();
|
||||
obj.num = 5;
|
||||
```
|
||||
|
||||
|
@ -230,7 +230,7 @@ explicitly.
|
|||
|
||||
```rust
|
||||
# use pyo3::prelude::*;
|
||||
use pyo3::PyClassShell;
|
||||
use pyo3::PyCell;
|
||||
|
||||
#[pyclass]
|
||||
struct BaseClass {
|
||||
|
@ -261,7 +261,7 @@ impl SubClass {
|
|||
(SubClass{ val2: 15}, BaseClass::new())
|
||||
}
|
||||
|
||||
fn method2(self_: &PyClassShell<Self>) -> PyResult<usize> {
|
||||
fn method2(self_: &PyCell<Self>) -> PyResult<usize> {
|
||||
self_.get_super().method().map(|x| x * self_.val2)
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ impl SubSubClass {
|
|||
.add_subclass(SubSubClass{val3: 20})
|
||||
}
|
||||
|
||||
fn method3(self_: &PyClassShell<Self>) -> PyResult<usize> {
|
||||
fn method3(self_: &PyCell<Self>) -> PyResult<usize> {
|
||||
let super_ = self_.get_super();
|
||||
SubClass::method2(super_).map(|x| x * self_.val3)
|
||||
}
|
||||
|
@ -288,20 +288,20 @@ impl SubSubClass {
|
|||
|
||||
# let gil = Python::acquire_gil();
|
||||
# let py = gil.python();
|
||||
# let subsub = pyo3::PyClassShell::new_ref(py, SubSubClass::new()).unwrap();
|
||||
# let subsub = pyo3::PyCell::new_ref(py, SubSubClass::new()).unwrap();
|
||||
# pyo3::py_run!(py, subsub, "assert subsub.method3() == 3000")
|
||||
```
|
||||
|
||||
To access the super class, you can use either of these two ways:
|
||||
- Use `self_: &PyClassShell<Self>` instead of `self`, and call `get_super()`
|
||||
- Use `self_: &PyCell<Self>` instead of `self`, and call `get_super()`
|
||||
- `ObjectProtocol::get_base`
|
||||
We recommend `PyClassShell` here, since it makes the context much clearer.
|
||||
We recommend `PyCell` here, since it makes the context much clearer.
|
||||
|
||||
|
||||
If `SubClass` does not provide a baseclass initialization, the compilation fails.
|
||||
```compile_fail
|
||||
# use pyo3::prelude::*;
|
||||
use pyo3::PyClassShell;
|
||||
use pyo3::PyCell;
|
||||
|
||||
#[pyclass]
|
||||
struct BaseClass {
|
||||
|
@ -761,8 +761,8 @@ struct GCTracked {} // Fails because it does not implement PyGCProtocol
|
|||
Iterators can be defined using the
|
||||
[`PyIterProtocol`](https://docs.rs/pyo3/latest/pyo3/class/iter/trait.PyIterProtocol.html) trait.
|
||||
It includes two methods `__iter__` and `__next__`:
|
||||
* `fn __iter__(slf: &mut PyClassShell<Self>) -> PyResult<impl IntoPy<PyObject>>`
|
||||
* `fn __next__(slf: &mut PyClassShell<Self>) -> PyResult<Option<impl IntoPy<PyObject>>>`
|
||||
* `fn __iter__(slf: &mut PyCell<Self>) -> PyResult<impl IntoPy<PyObject>>`
|
||||
* `fn __next__(slf: &mut PyCell<Self>) -> PyResult<Option<impl IntoPy<PyObject>>>`
|
||||
|
||||
Returning `Ok(None)` from `__next__` indicates that that there are no further items.
|
||||
|
||||
|
@ -770,7 +770,7 @@ Example:
|
|||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::{PyIterProtocol, PyClassShell};
|
||||
use pyo3::{PyIterProtocol, PyCell};
|
||||
|
||||
#[pyclass]
|
||||
struct MyIterator {
|
||||
|
@ -779,10 +779,10 @@ struct MyIterator {
|
|||
|
||||
#[pyproto]
|
||||
impl PyIterProtocol for MyIterator {
|
||||
fn __iter__(slf: &mut PyClassShell<Self>) -> PyResult<Py<MyIterator>> {
|
||||
fn __iter__(slf: &mut PyCell<Self>) -> PyResult<Py<MyIterator>> {
|
||||
Ok(slf.into())
|
||||
}
|
||||
fn __next__(slf: &mut PyClassShell<Self>) -> PyResult<Option<PyObject>> {
|
||||
fn __next__(slf: &mut PyCell<Self>) -> PyResult<Option<PyObject>> {
|
||||
Ok(slf.iter.next())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ your Python extensions quickly.
|
|||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::{PyClassShell, PyObjectProtocol, py_run};
|
||||
use pyo3::{PyCell, PyObjectProtocol, py_run};
|
||||
# fn main() {
|
||||
#[pyclass]
|
||||
struct UserData {
|
||||
|
@ -61,7 +61,7 @@ let userdata = UserData {
|
|||
id: 34,
|
||||
name: "Yu".to_string(),
|
||||
};
|
||||
let userdata = PyClassShell::new_ref(py, userdata).unwrap();
|
||||
let userdata = PyCell::new_ref(py, userdata).unwrap();
|
||||
let userdata_as_tuple = (34, "Yu");
|
||||
py_run!(py, userdata userdata_as_tuple, r#"
|
||||
assert repr(userdata) == "User Yu(id: 34)"
|
||||
|
|
|
@ -373,7 +373,7 @@ fn impl_class(
|
|||
unsafe impl pyo3::type_object::PyTypeInfo for #cls {
|
||||
type Type = #cls;
|
||||
type BaseType = #base;
|
||||
type ConcreteLayout = pyo3::pyclass::PyClassShell<Self>;
|
||||
type ConcreteLayout = pyo3::pyclass::PyCell<Self>;
|
||||
type Initializer = pyo3::pyclass_init::PyClassInitializer<Self>;
|
||||
|
||||
const NAME: &'static str = #cls_name;
|
||||
|
|
|
@ -175,7 +175,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
|
|||
|
||||
#body
|
||||
|
||||
match _result.and_then(|init| pyo3::PyClassInitializer::from(init).create_shell(_py)) {
|
||||
match _result.and_then(|init| pyo3::PyClassInitializer::from(init).create_cell(_py)) {
|
||||
Ok(slf) => slf as _,
|
||||
Err(e) => e.restore_and_null(_py),
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
use crate::callback::{CallbackConverter, PyObjectCallbackConverter};
|
||||
use crate::err::PyResult;
|
||||
use crate::{ffi, pyclass::PyClassShell, IntoPy, PyClass, PyObject};
|
||||
use crate::{IntoPyPointer, Python};
|
||||
use crate::{ffi, IntoPy, IntoPyPointer, PyCell, PyClass, PyObject, Python};
|
||||
use std::ptr;
|
||||
|
||||
/// Python Iterator Interface.
|
||||
|
@ -14,14 +13,14 @@ use std::ptr;
|
|||
/// `https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter`
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyIterProtocol<'p>: PyClass {
|
||||
fn __iter__(slf: &mut PyClassShell<Self>) -> Self::Result
|
||||
fn __iter__(slf: &mut PyCell<Self>) -> Self::Result
|
||||
where
|
||||
Self: PyIterIterProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn __next__(slf: &mut PyClassShell<Self>) -> Self::Result
|
||||
fn __next__(slf: &mut PyCell<Self>) -> Self::Result
|
||||
where
|
||||
Self: PyIterNextProtocol<'p>,
|
||||
{
|
||||
|
|
|
@ -35,10 +35,10 @@ macro_rules! py_unary_pyref_func {
|
|||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
use $crate::pyclass::PyClassShell;
|
||||
use $crate::PyCell;
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf: &mut PyClassShell<T> = &mut *(slf as *mut PyClassShell<T>);
|
||||
let slf: &mut PyCell<T> = &mut *(slf as *mut PyCell<T>);
|
||||
let res = $class::$f(slf).into();
|
||||
$crate::callback::cb_convert($conv, py, res)
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ use crate::err::{PyErr, PyResult};
|
|||
use crate::gil;
|
||||
use crate::object::PyObject;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::pyclass::{PyClass, PyClassShell};
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::type_object::{PyObjectLayout, PyTypeInfo};
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, IntoPy};
|
||||
use crate::{AsPyPointer, FromPyObject, IntoPyPointer, Python, ToPyObject};
|
||||
use crate::{
|
||||
ffi, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, PyCell, PyClass, PyClassInitializer,
|
||||
Python, ToPyObject,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
|
@ -43,7 +43,7 @@ impl<T> Py<T> {
|
|||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
let initializer = value.into();
|
||||
let obj = unsafe { initializer.create_shell(py)? };
|
||||
let obj = unsafe { initializer.create_cell(py)? };
|
||||
let ob = unsafe { Py::from_owned_ptr(obj as _) };
|
||||
Ok(ob)
|
||||
}
|
||||
|
@ -174,22 +174,22 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// `&PyClassShell<T>` can be converted to `Py<T>`
|
||||
impl<'a, T> std::convert::From<&PyClassShell<T>> for Py<T>
|
||||
// `&PyCell<T>` can be converted to `Py<T>`
|
||||
impl<'a, T> std::convert::From<&PyCell<T>> for Py<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
fn from(shell: &PyClassShell<T>) -> Self {
|
||||
unsafe { Py::from_borrowed_ptr(shell.as_ptr()) }
|
||||
fn from(cell: &PyCell<T>) -> Self {
|
||||
unsafe { Py::from_borrowed_ptr(cell.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> std::convert::From<&mut PyClassShell<T>> for Py<T>
|
||||
impl<'a, T> std::convert::From<&mut PyCell<T>> for Py<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
fn from(shell: &mut PyClassShell<T>) -> Self {
|
||||
unsafe { Py::from_borrowed_ptr(shell.as_ptr()) }
|
||||
fn from(cell: &mut PyCell<T>) -> Self {
|
||||
unsafe { Py::from_borrowed_ptr(cell.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ pub use crate::gil::{init_once, GILGuard, GILPool};
|
|||
pub use crate::instance::{AsPyRef, ManagedPyRef, Py, PyNativeType};
|
||||
pub use crate::object::PyObject;
|
||||
pub use crate::objectprotocol::ObjectProtocol;
|
||||
pub use crate::pyclass::{PyClass, PyClassShell};
|
||||
pub use crate::pycell::PyCell;
|
||||
pub use crate::pyclass::PyClass;
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::python::{prepare_freethreaded_python, Python};
|
||||
pub use crate::type_object::{type_flags, PyTypeInfo};
|
||||
|
@ -170,6 +171,7 @@ pub mod marshal;
|
|||
mod object;
|
||||
mod objectprotocol;
|
||||
pub mod prelude;
|
||||
mod pycell;
|
||||
pub mod pyclass;
|
||||
pub mod pyclass_init;
|
||||
pub mod pyclass_slots;
|
||||
|
@ -221,7 +223,7 @@ macro_rules! wrap_pymodule {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use pyo3::{prelude::*, py_run, PyClassShell};
|
||||
/// use pyo3::{prelude::*, py_run, PyCell};
|
||||
/// #[pyclass]
|
||||
/// #[derive(Debug)]
|
||||
/// struct Time {
|
||||
|
@ -244,7 +246,7 @@ macro_rules! wrap_pymodule {
|
|||
/// }
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let time = PyClassShell::new_ref(py, Time {hour: 8, minute: 43, second: 16}).unwrap();
|
||||
/// let time = PyCell::new_ref(py, Time {hour: 8, minute: 43, second: 16}).unwrap();
|
||||
/// let time_as_tuple = (8, 43, 16);
|
||||
/// py_run!(py, time time_as_tuple, r#"
|
||||
/// assert time.hour == 8
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
//! Traits and structs for `#[pyclass]`.
|
||||
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
|
||||
use crate::pyclass::PyClass;
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||
use crate::type_object::{PyObjectLayout, PyObjectSizedLayout};
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// `PyCell` represents the concrete layout of `T: PyClass` when it is converted
|
||||
/// to a Python class.
|
||||
///
|
||||
/// You can use it to test your `#[pyclass]` correctly works.
|
||||
///
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// # use pyo3::{py_run, PyCell};
|
||||
/// #[pyclass]
|
||||
/// struct Book {
|
||||
/// #[pyo3(get)]
|
||||
/// name: &'static str,
|
||||
/// author: &'static str,
|
||||
/// }
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let book = Book {
|
||||
/// name: "The Man in the High Castle",
|
||||
/// author: "Philip Kindred Dick",
|
||||
/// };
|
||||
/// let book_cell = PyCell::new_ref(py, book).unwrap();
|
||||
/// py_run!(py, book_cell, "assert book_cell.name[-6:] == 'Castle'");
|
||||
/// ```
|
||||
#[repr(C)]
|
||||
pub struct PyCell<T: PyClass> {
|
||||
ob_base: <T::BaseType as PyTypeInfo>::ConcreteLayout,
|
||||
pyclass: ManuallyDrop<T>,
|
||||
dict: T::Dict,
|
||||
weakref: T::WeakRef,
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyCell<T> {
|
||||
/// Make new `PyCell` on the Python heap and returns the reference of it.
|
||||
pub fn new_ref(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_cell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Make new `PyCell` on the Python heap and returns the mutable reference of it.
|
||||
pub fn new_mut(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&mut Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_cell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the reference of base object.
|
||||
pub fn get_super(&self) -> &<T::BaseType as PyTypeInfo>::ConcreteLayout {
|
||||
&self.ob_base
|
||||
}
|
||||
|
||||
/// Get the mutable reference of base object.
|
||||
pub fn get_super_mut(&mut self) -> &mut <T::BaseType as PyTypeInfo>::ConcreteLayout {
|
||||
&mut self.ob_base
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn internal_new(py: Python) -> PyResult<*mut Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
let base = T::alloc(py);
|
||||
if base.is_null() {
|
||||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
let self_ = base as *mut Self;
|
||||
(*self_).dict = T::Dict::new();
|
||||
(*self_).weakref = T::WeakRef::new();
|
||||
Ok(self_)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyObjectLayout<T> for PyCell<T> {
|
||||
const IS_NATIVE_TYPE: bool = false;
|
||||
fn get_super_or(&mut self) -> Option<&mut <T::BaseType as PyTypeInfo>::ConcreteLayout> {
|
||||
Some(&mut self.ob_base)
|
||||
}
|
||||
unsafe fn internal_ref_cast(obj: &PyAny) -> &T {
|
||||
let cell = obj.as_ptr() as *const Self;
|
||||
&(*cell).pyclass
|
||||
}
|
||||
unsafe fn internal_mut_cast(obj: &PyAny) -> &mut T {
|
||||
let cell = obj.as_ptr() as *const _ as *mut Self;
|
||||
&mut (*cell).pyclass
|
||||
}
|
||||
unsafe fn py_drop(&mut self, py: Python) {
|
||||
ManuallyDrop::drop(&mut self.pyclass);
|
||||
self.dict.clear_dict(py);
|
||||
self.weakref.clear_weakrefs(self.as_ptr(), py);
|
||||
self.ob_base.py_drop(py);
|
||||
}
|
||||
unsafe fn py_init(&mut self, value: T) {
|
||||
self.pyclass = ManuallyDrop::new(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyObjectSizedLayout<T> for PyCell<T> {}
|
||||
|
||||
impl<T: PyClass> AsPyPointer for PyCell<T> {
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
(self as *const _) as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> std::ops::Deref for PyCell<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
self.pyclass.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> std::ops::DerefMut for PyCell<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.pyclass.deref_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> ToPyObject for &PyCell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> ToPyObject for &mut PyCell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p PyCell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| &*(gil::register_owned(py, p).as_ptr() as *const PyCell<T>))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| &*(gil::register_borrowed(py, p).as_ptr() as *const PyCell<T>))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p mut PyCell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| &mut *(gil::register_owned(py, p).as_ptr() as *const _ as *mut PyCell<T>))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| &mut *(gil::register_borrowed(py, p).as_ptr() as *const _ as *mut PyCell<T>))
|
||||
}
|
||||
}
|
186
src/pyclass.rs
186
src/pyclass.rs
|
@ -1,15 +1,11 @@
|
|||
//! Traits and structs for `#[pyclass]`.
|
||||
//! `PyClass` trait
|
||||
use crate::class::methods::{PyMethodDefType, PyMethodsProtocol};
|
||||
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||
use crate::type_object::{type_flags, PyObjectLayout, PyObjectSizedLayout};
|
||||
use crate::types::PyAny;
|
||||
use crate::{class, ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
||||
use crate::type_object::{type_flags, PyObjectLayout};
|
||||
use crate::{class, ffi, gil, PyCell, PyErr, PyResult, PyTypeInfo, Python};
|
||||
use std::ffi::CString;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::ptr;
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn default_alloc<T: PyTypeInfo>() -> *mut ffi::PyObject {
|
||||
|
@ -71,187 +67,17 @@ pub unsafe fn tp_free_fallback(obj: *mut ffi::PyObject) {
|
|||
}
|
||||
|
||||
/// If `PyClass` is implemented for `T`, then we can use `T` in the Python world,
|
||||
/// via `PyClassShell`.
|
||||
/// via `PyCell`.
|
||||
///
|
||||
/// The `#[pyclass]` attribute automatically implements this trait for your Rust struct,
|
||||
/// so you don't have to use this trait directly.
|
||||
pub trait PyClass:
|
||||
PyTypeInfo<ConcreteLayout = PyClassShell<Self>> + Sized + PyClassAlloc + PyMethodsProtocol
|
||||
PyTypeInfo<ConcreteLayout = PyCell<Self>> + Sized + PyClassAlloc + PyMethodsProtocol
|
||||
{
|
||||
type Dict: PyClassDict;
|
||||
type WeakRef: PyClassWeakRef;
|
||||
}
|
||||
|
||||
/// `PyClassShell` represents the concrete layout of `T: PyClass` when it is converted
|
||||
/// to a Python class.
|
||||
///
|
||||
/// You can use it to test your `#[pyclass]` correctly works.
|
||||
///
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// # use pyo3::{py_run, PyClassShell};
|
||||
/// #[pyclass]
|
||||
/// struct Book {
|
||||
/// #[pyo3(get)]
|
||||
/// name: &'static str,
|
||||
/// author: &'static str,
|
||||
/// }
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let book = Book {
|
||||
/// name: "The Man in the High Castle",
|
||||
/// author: "Philip Kindred Dick",
|
||||
/// };
|
||||
/// let book_shell = PyClassShell::new_ref(py, book).unwrap();
|
||||
/// py_run!(py, book_shell, "assert book_shell.name[-6:] == 'Castle'");
|
||||
/// ```
|
||||
#[repr(C)]
|
||||
pub struct PyClassShell<T: PyClass> {
|
||||
ob_base: <T::BaseType as PyTypeInfo>::ConcreteLayout,
|
||||
pyclass: ManuallyDrop<T>,
|
||||
dict: T::Dict,
|
||||
weakref: T::WeakRef,
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyClassShell<T> {
|
||||
/// Make new `PyClassShell` on the Python heap and returns the reference of it.
|
||||
pub fn new_ref(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_shell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Make new `PyClassShell` on the Python heap and returns the mutable reference of it.
|
||||
pub fn new_mut(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&mut Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_shell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the reference of base object.
|
||||
pub fn get_super(&self) -> &<T::BaseType as PyTypeInfo>::ConcreteLayout {
|
||||
&self.ob_base
|
||||
}
|
||||
|
||||
/// Get the mutable reference of base object.
|
||||
pub fn get_super_mut(&mut self) -> &mut <T::BaseType as PyTypeInfo>::ConcreteLayout {
|
||||
&mut self.ob_base
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn new(py: Python) -> PyResult<*mut Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
let base = T::alloc(py);
|
||||
if base.is_null() {
|
||||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
let self_ = base as *mut Self;
|
||||
(*self_).dict = T::Dict::new();
|
||||
(*self_).weakref = T::WeakRef::new();
|
||||
Ok(self_)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyObjectLayout<T> for PyClassShell<T> {
|
||||
const IS_NATIVE_TYPE: bool = false;
|
||||
fn get_super_or(&mut self) -> Option<&mut <T::BaseType as PyTypeInfo>::ConcreteLayout> {
|
||||
Some(&mut self.ob_base)
|
||||
}
|
||||
unsafe fn internal_ref_cast(obj: &PyAny) -> &T {
|
||||
let shell = obj.as_ptr() as *const Self;
|
||||
&(*shell).pyclass
|
||||
}
|
||||
unsafe fn internal_mut_cast(obj: &PyAny) -> &mut T {
|
||||
let shell = obj.as_ptr() as *const _ as *mut Self;
|
||||
&mut (*shell).pyclass
|
||||
}
|
||||
unsafe fn py_drop(&mut self, py: Python) {
|
||||
ManuallyDrop::drop(&mut self.pyclass);
|
||||
self.dict.clear_dict(py);
|
||||
self.weakref.clear_weakrefs(self.as_ptr(), py);
|
||||
self.ob_base.py_drop(py);
|
||||
}
|
||||
unsafe fn py_init(&mut self, value: T) {
|
||||
self.pyclass = ManuallyDrop::new(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyObjectSizedLayout<T> for PyClassShell<T> {}
|
||||
|
||||
impl<T: PyClass> AsPyPointer for PyClassShell<T> {
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
(self as *const _) as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> std::ops::Deref for PyClassShell<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
self.pyclass.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> std::ops::DerefMut for PyClassShell<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.pyclass.deref_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> ToPyObject for &PyClassShell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> ToPyObject for &mut PyClassShell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p PyClassShell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| &*(gil::register_owned(py, p).as_ptr() as *const PyClassShell<T>))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| &*(gil::register_borrowed(py, p).as_ptr() as *const PyClassShell<T>))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p mut PyClassShell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| {
|
||||
&mut *(gil::register_owned(py, p).as_ptr() as *const _ as *mut PyClassShell<T>)
|
||||
})
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| {
|
||||
&mut *(gil::register_borrowed(py, p).as_ptr() as *const _ as *mut PyClassShell<T>)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub(crate) fn initialize_type_object<T>(
|
||||
py: Python,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Initialization utilities for `#[pyclass]`.
|
||||
use crate::pyclass::{PyClass, PyClassShell};
|
||||
use crate::type_object::{PyObjectLayout, PyObjectSizedLayout, PyTypeInfo};
|
||||
use crate::{PyResult, Python};
|
||||
use crate::{PyCell, PyClass, PyResult, Python};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Initializer for Python types.
|
||||
|
@ -9,7 +8,7 @@ use std::marker::PhantomData;
|
|||
/// This trait is intended to use internally for distinguishing `#[pyclass]` and
|
||||
/// Python native types.
|
||||
pub trait PyObjectInit<T: PyTypeInfo>: Sized {
|
||||
fn init_class(self, shell: &mut T::ConcreteLayout);
|
||||
fn init_class(self, layout: &mut T::ConcreteLayout);
|
||||
private_decl! {}
|
||||
}
|
||||
|
||||
|
@ -17,7 +16,7 @@ pub trait PyObjectInit<T: PyTypeInfo>: Sized {
|
|||
pub struct PyNativeTypeInitializer<T: PyTypeInfo>(PhantomData<T>);
|
||||
|
||||
impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
|
||||
fn init_class(self, _shell: &mut T::ConcreteLayout) {}
|
||||
fn init_class(self, _layout: &mut T::ConcreteLayout) {}
|
||||
private_impl! {}
|
||||
}
|
||||
|
||||
|
@ -115,14 +114,14 @@ impl<T: PyClass> PyClassInitializer<T> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub unsafe fn create_shell(self, py: Python) -> PyResult<*mut PyClassShell<T>>
|
||||
pub unsafe fn create_cell(self, py: Python) -> PyResult<*mut PyCell<T>>
|
||||
where
|
||||
T: PyClass,
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout: PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
let shell = PyClassShell::new(py)?;
|
||||
self.init_class(&mut *shell);
|
||||
Ok(shell)
|
||||
let cell = PyCell::internal_new(py)?;
|
||||
self.init_class(&mut *cell);
|
||||
Ok(cell)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::ptr::NonNull;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// `T: PyObjectLayout<U>` represents that `T` is a concrete representaion of `U` in Python heap.
|
||||
/// E.g., `PyClassShell` is a concrete representaion of all `pyclass`es, and `ffi::PyObject`
|
||||
/// E.g., `PyCell` is a concrete representaion of all `pyclass`es, and `ffi::PyObject`
|
||||
/// is of `PyAny`.
|
||||
///
|
||||
/// This trait is intended to be used internally.
|
||||
|
|
|
@ -6,7 +6,7 @@ use pyo3::class::{
|
|||
use pyo3::exceptions::{IndexError, ValueError};
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{IntoPyDict, PyAny, PyBytes, PySlice, PyType};
|
||||
use pyo3::{ffi, py_run, AsPyPointer, PyClassShell};
|
||||
use pyo3::{ffi, py_run, AsPyPointer, PyCell};
|
||||
use std::convert::TryFrom;
|
||||
use std::{isize, iter};
|
||||
|
||||
|
@ -53,11 +53,11 @@ struct Iterator {
|
|||
|
||||
#[pyproto]
|
||||
impl<'p> PyIterProtocol for Iterator {
|
||||
fn __iter__(slf: &mut PyClassShell<Self>) -> PyResult<Py<Iterator>> {
|
||||
fn __iter__(slf: &mut PyCell<Self>) -> PyResult<Py<Iterator>> {
|
||||
Ok(slf.into())
|
||||
}
|
||||
|
||||
fn __next__(slf: &mut PyClassShell<Self>) -> PyResult<Option<i32>> {
|
||||
fn __next__(slf: &mut PyCell<Self>) -> PyResult<Option<i32>> {
|
||||
Ok(slf.iter.next())
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ fn setitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyClassShell::new_ref(py, SetItem { key: 0, val: 0 }).unwrap();
|
||||
let c = PyCell::new_ref(py, SetItem { key: 0, val: 0 }).unwrap();
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
assert_eq!(c.key, 1);
|
||||
assert_eq!(c.val, 2);
|
||||
|
@ -275,7 +275,7 @@ fn delitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyClassShell::new_ref(py, DelItem { key: 0 }).unwrap();
|
||||
let c = PyCell::new_ref(py, DelItem { key: 0 }).unwrap();
|
||||
py_run!(py, c, "del c[1]");
|
||||
assert_eq!(c.key, 1);
|
||||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||
|
@ -304,7 +304,7 @@ fn setdelitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyClassShell::new_ref(py, SetDelItem { val: None }).unwrap();
|
||||
let c = PyCell::new_ref(py, SetDelItem { val: None }).unwrap();
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
assert_eq!(c.val, Some(2));
|
||||
py_run!(py, c, "del c[1]");
|
||||
|
@ -383,7 +383,7 @@ fn context_manager() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyClassShell::new_mut(py, ContextManager { exit_called: false }).unwrap();
|
||||
let c = PyCell::new_mut(py, ContextManager { exit_called: false }).unwrap();
|
||||
py_run!(py, c, "with c as x: assert x == 42");
|
||||
assert!(c.exit_called);
|
||||
|
||||
|
@ -455,7 +455,7 @@ struct DunderDictSupport {}
|
|||
fn dunder_dict_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||
let inst = PyCell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -470,7 +470,7 @@ fn dunder_dict_support() {
|
|||
fn access_dunder_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||
let inst = PyCell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -488,7 +488,7 @@ struct WeakRefDunderDictSupport {}
|
|||
fn weakref_dunder_dict_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_ref(py, WeakRefDunderDictSupport {}).unwrap();
|
||||
let inst = PyCell::new_ref(py, WeakRefDunderDictSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -513,7 +513,7 @@ impl PyObjectProtocol for ClassWithGetAttr {
|
|||
fn getattr_doesnt_override_member() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_ref(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||
let inst = PyCell::new_ref(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 4");
|
||||
py_assert!(py, inst, "inst.a == 8");
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use pyo3::class::PyTraverseError;
|
|||
use pyo3::class::PyVisit;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyAny, PyTuple};
|
||||
use pyo3::{ffi, py_run, AsPyPointer, PyClassShell};
|
||||
use pyo3::{ffi, py_run, AsPyPointer, PyCell};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
@ -153,7 +153,7 @@ fn gc_integration() {
|
|||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_mut(
|
||||
let inst = PyCell::new_mut(
|
||||
py,
|
||||
GCIntegration {
|
||||
self_ref: RefCell::new(py.None()),
|
||||
|
@ -188,7 +188,7 @@ impl PyGCProtocol for GCIntegration2 {
|
|||
fn gc_integration2() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_ref(py, GCIntegration2 {}).unwrap();
|
||||
let inst = PyCell::new_ref(py, GCIntegration2 {}).unwrap();
|
||||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ struct WeakRefSupport {}
|
|||
fn weakref_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyClassShell::new_ref(py, WeakRefSupport {}).unwrap();
|
||||
let inst = PyCell::new_ref(py, WeakRefSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
|
|
@ -126,7 +126,7 @@ impl SetWithName {
|
|||
fn inherit_set() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set_sub = pyo3::pyclass::PyClassShell::new_ref(py, SetWithName::new()).unwrap();
|
||||
let set_sub = pyo3::pyclass::PyCell::new_ref(py, SetWithName::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
set_sub,
|
||||
|
@ -152,7 +152,7 @@ impl DictWithName {
|
|||
fn inherit_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let dict_sub = pyo3::pyclass::PyClassShell::new_ref(py, DictWithName::new()).unwrap();
|
||||
let dict_sub = pyo3::pyclass::PyCell::new_ref(py, DictWithName::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
dict_sub,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::py_run;
|
||||
use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType};
|
||||
use pyo3::PyClassShell;
|
||||
use pyo3::PyCell;
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -23,7 +23,7 @@ fn instance_method() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = PyClassShell::new_mut(py, InstanceMethod { member: 42 }).unwrap();
|
||||
let obj = PyCell::new_mut(py, InstanceMethod { member: 42 }).unwrap();
|
||||
assert_eq!(obj.method().unwrap(), 42);
|
||||
let d = [("obj", obj)].into_py_dict(py);
|
||||
py.run("assert obj.method() == 42", None, Some(d)).unwrap();
|
||||
|
@ -49,7 +49,7 @@ fn instance_method_with_args() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = PyClassShell::new_mut(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
||||
let obj = PyCell::new_mut(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
||||
assert_eq!(obj.method(6).unwrap(), 42);
|
||||
let d = [("obj", obj)].into_py_dict(py);
|
||||
py.run("assert obj.method(3) == 21", None, Some(d)).unwrap();
|
||||
|
@ -395,7 +395,7 @@ impl MethodWithLifeTime {
|
|||
fn method_with_lifetime() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj = PyClassShell::new_ref(py, MethodWithLifeTime {}).unwrap();
|
||||
let obj = PyCell::new_ref(py, MethodWithLifeTime {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
obj,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use pyo3;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyBytes, PyString};
|
||||
use pyo3::{AsPyRef, PyClassShell, PyIterProtocol};
|
||||
use pyo3::{AsPyRef, PyCell, PyIterProtocol};
|
||||
use std::collections::HashMap;
|
||||
|
||||
mod common;
|
||||
|
@ -17,27 +17,20 @@ struct Reader {
|
|||
|
||||
#[pymethods]
|
||||
impl Reader {
|
||||
fn clone_ref(slf: &PyClassShell<Self>) -> &PyClassShell<Self> {
|
||||
fn clone_ref(slf: &PyCell<Self>) -> &PyCell<Self> {
|
||||
slf
|
||||
}
|
||||
fn clone_ref_with_py<'py>(
|
||||
slf: &'py PyClassShell<Self>,
|
||||
_py: Python<'py>,
|
||||
) -> &'py PyClassShell<Self> {
|
||||
fn clone_ref_with_py<'py>(slf: &'py PyCell<Self>, _py: Python<'py>) -> &'py PyCell<Self> {
|
||||
slf
|
||||
}
|
||||
fn get_iter(slf: &PyClassShell<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||
fn get_iter(slf: &PyCell<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||
Ok(Iter {
|
||||
reader: slf.into(),
|
||||
keys,
|
||||
idx: 0,
|
||||
})
|
||||
}
|
||||
fn get_iter_and_reset(
|
||||
slf: &mut PyClassShell<Self>,
|
||||
keys: Py<PyBytes>,
|
||||
py: Python,
|
||||
) -> PyResult<Iter> {
|
||||
fn get_iter_and_reset(slf: &mut PyCell<Self>, keys: Py<PyBytes>, py: Python) -> PyResult<Iter> {
|
||||
let reader = Py::new(py, slf.clone())?;
|
||||
slf.inner.clear();
|
||||
Ok(Iter {
|
||||
|
@ -57,12 +50,12 @@ struct Iter {
|
|||
|
||||
#[pyproto]
|
||||
impl PyIterProtocol for Iter {
|
||||
fn __iter__(slf: &mut PyClassShell<Self>) -> PyResult<PyObject> {
|
||||
fn __iter__(slf: &mut PyCell<Self>) -> PyResult<PyObject> {
|
||||
let py = unsafe { Python::assume_gil_acquired() };
|
||||
Ok(slf.to_object(py))
|
||||
}
|
||||
|
||||
fn __next__(slf: &mut PyClassShell<Self>) -> PyResult<Option<PyObject>> {
|
||||
fn __next__(slf: &mut PyCell<Self>) -> PyResult<Option<PyObject>> {
|
||||
let py = unsafe { Python::assume_gil_acquired() };
|
||||
let bytes = slf.keys.as_ref(py).as_bytes();
|
||||
match bytes.get(slf.idx) {
|
||||
|
@ -113,7 +106,7 @@ fn test_clone_ref() {
|
|||
fn test_nested_iter_reset() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let reader = PyClassShell::new_ref(py, reader()).unwrap();
|
||||
let reader = PyCell::new_ref(py, reader()).unwrap();
|
||||
py_assert!(
|
||||
py,
|
||||
reader,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::{types::PyType, wrap_pyfunction, wrap_pymodule, PyClassShell};
|
||||
use pyo3::{types::PyType, wrap_pyfunction, wrap_pymodule, PyCell};
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -144,7 +144,7 @@ fn test_methods() {
|
|||
let _ = a;
|
||||
}
|
||||
#[text_signature = "($self, b)"]
|
||||
fn pyself_method(_this: &PyClassShell<Self>, b: i32) {
|
||||
fn pyself_method(_this: &PyCell<Self>, b: i32) {
|
||||
let _ = b;
|
||||
}
|
||||
#[classmethod]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::types::IntoPyDict;
|
||||
use pyo3::types::{PyDict, PyTuple};
|
||||
use pyo3::{py_run, wrap_pyfunction, AsPyRef, PyClassShell};
|
||||
use pyo3::{py_run, wrap_pyfunction, AsPyRef, PyCell};
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -81,8 +81,8 @@ fn intopytuple_pyclass() {
|
|||
let py = gil.python();
|
||||
|
||||
let tup = (
|
||||
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyCell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyCell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
);
|
||||
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
|
||||
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[1]).__name__");
|
||||
|
@ -106,8 +106,8 @@ fn pytuple_pyclass_iter() {
|
|||
let tup = PyTuple::new(
|
||||
py,
|
||||
[
|
||||
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyCell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyCell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
]
|
||||
.iter(),
|
||||
);
|
||||
|
@ -127,7 +127,7 @@ impl PickleSupport {
|
|||
}
|
||||
|
||||
pub fn __reduce__<'py>(
|
||||
slf: &'py PyClassShell<Self>,
|
||||
slf: &'py PyCell<Self>,
|
||||
py: Python<'py>,
|
||||
) -> PyResult<(PyObject, &'py PyTuple, PyObject)> {
|
||||
let cls = slf.to_object(py).getattr(py, "__class__")?;
|
||||
|
@ -152,7 +152,7 @@ fn test_pickle() {
|
|||
let module = PyModule::new(py, "test_module").unwrap();
|
||||
module.add_class::<PickleSupport>().unwrap();
|
||||
add_module(py, module).unwrap();
|
||||
let inst = PyClassShell::new_ref(py, PickleSupport {}).unwrap();
|
||||
let inst = PyCell::new_ref(py, PickleSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
|
Loading…
Reference in New Issue