Introduce PyInternalCaster
This commit is contained in:
parent
4d7dfafe2b
commit
a6639076b9
|
@ -65,7 +65,7 @@ impl<'a> FnSpec<'a> {
|
||||||
ref pat, ref ty, ..
|
ref pat, ref ty, ..
|
||||||
}) => {
|
}) => {
|
||||||
// skip first argument (cls)
|
// skip first argument (cls)
|
||||||
if (fn_type == FnType::FnClass || fn_type == FnType::FnNew) && !has_self {
|
if fn_type == FnType::FnClass && !has_self {
|
||||||
has_self = true;
|
has_self = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,10 @@ macro_rules! py_unary_pyref_func {
|
||||||
where
|
where
|
||||||
T: for<'p> $trait<'p>,
|
T: for<'p> $trait<'p>,
|
||||||
{
|
{
|
||||||
use $crate::{pyclass::PyClassShell, FromPyPointer};
|
use $crate::pyclass::PyClassShell;
|
||||||
let py = $crate::Python::assume_gil_acquired();
|
let py = $crate::Python::assume_gil_acquired();
|
||||||
let _pool = $crate::GILPool::new(py);
|
let _pool = $crate::GILPool::new(py);
|
||||||
let slf: &mut PyClassShell<T> = FromPyPointer::from_borrowed_ptr_or_panic(py, slf);
|
let slf: &mut PyClassShell<T> = &mut *(slf as *mut PyClassShell<T>);
|
||||||
let res = $class::$f(slf).into();
|
let res = $class::$f(slf).into();
|
||||||
$crate::callback::cb_convert($conv, py, res)
|
$crate::callback::cb_convert($conv, py, res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! Conversions between various states of rust and python types and their wrappers.
|
//! Conversions between various states of rust and python types and their wrappers.
|
||||||
use crate::err::{self, PyDowncastError, PyResult};
|
use crate::err::{self, PyDowncastError, PyResult};
|
||||||
use crate::object::PyObject;
|
use crate::object::PyObject;
|
||||||
use crate::type_object::PyTypeInfo;
|
use crate::type_object::{PyConcreteObject, PyTypeInfo};
|
||||||
use crate::types::PyAny;
|
use crate::types::PyAny;
|
||||||
use crate::types::PyTuple;
|
use crate::types::PyTuple;
|
||||||
use crate::{ffi, gil, Py, Python};
|
use crate::{ffi, gil, Py, Python};
|
||||||
|
@ -393,15 +393,13 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v T {
|
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v T {
|
||||||
let value = value.into();
|
let value = value.into();
|
||||||
let ptr = value as *const _ as *const u8 as *const T;
|
T::ConcreteLayout::internal_ref_cast(value)
|
||||||
&*ptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v mut T {
|
unsafe fn try_from_mut_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v mut T {
|
||||||
let value = value.into();
|
let value = value.into();
|
||||||
let ptr = value as *const _ as *mut u8 as *mut T;
|
T::ConcreteLayout::internal_mut_cast(value)
|
||||||
&mut *ptr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,10 +451,11 @@ where
|
||||||
T: PyTypeInfo,
|
T: PyTypeInfo,
|
||||||
{
|
{
|
||||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||||
NonNull::new(ptr).map(|p| py.unchecked_downcast(gil::register_owned(py, p)))
|
NonNull::new(ptr).map(|p| T::ConcreteLayout::internal_ref_cast(gil::register_owned(py, p)))
|
||||||
}
|
}
|
||||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||||
NonNull::new(ptr).map(|p| py.unchecked_downcast(gil::register_borrowed(py, p)))
|
NonNull::new(ptr)
|
||||||
|
.map(|p| T::ConcreteLayout::internal_ref_cast(gil::register_borrowed(py, p)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,10 +464,11 @@ where
|
||||||
T: PyTypeInfo,
|
T: PyTypeInfo,
|
||||||
{
|
{
|
||||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||||
NonNull::new(ptr).map(|p| py.unchecked_mut_downcast(gil::register_owned(py, p)))
|
NonNull::new(ptr).map(|p| T::ConcreteLayout::internal_mut_cast(gil::register_owned(py, p)))
|
||||||
}
|
}
|
||||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||||
NonNull::new(ptr).map(|p| py.unchecked_mut_downcast(gil::register_borrowed(py, p)))
|
NonNull::new(ptr)
|
||||||
|
.map(|p| T::ConcreteLayout::internal_mut_cast(gil::register_borrowed(py, p)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||||
use crate::err::{PyErr, PyResult};
|
use crate::err::{PyErr, PyResult};
|
||||||
use crate::gil;
|
use crate::gil;
|
||||||
use crate::instance;
|
|
||||||
use crate::object::PyObject;
|
use crate::object::PyObject;
|
||||||
use crate::objectprotocol::ObjectProtocol;
|
use crate::objectprotocol::ObjectProtocol;
|
||||||
use crate::pyclass::{PyClass, PyClassShell};
|
use crate::pyclass::{PyClass, PyClassShell};
|
||||||
use crate::type_object::PyTypeInfo;
|
use crate::type_object::{PyConcreteObject, PyTypeInfo};
|
||||||
use crate::types::PyAny;
|
use crate::types::PyAny;
|
||||||
use crate::{ffi, IntoPy};
|
use crate::{ffi, IntoPy};
|
||||||
use crate::{AsPyPointer, FromPyObject, IntoPyPointer, Python, ToPyObject};
|
use crate::{AsPyPointer, FromPyObject, IntoPyPointer, Python, ToPyObject};
|
||||||
|
@ -36,11 +35,6 @@ unsafe impl<T> Sync for Py<T> {}
|
||||||
|
|
||||||
impl<T> Py<T> {
|
impl<T> Py<T> {
|
||||||
/// Create new instance of T and move it under python management
|
/// Create new instance of T and move it under python management
|
||||||
///
|
|
||||||
/// **NOTE**
|
|
||||||
/// This method's `where` bound is actually the same as `PyClass`.
|
|
||||||
/// However, since Rust still doesn't have higher order generics, we cannot represent
|
|
||||||
/// this bound by `PyClass`.
|
|
||||||
pub fn new(py: Python, value: T) -> PyResult<Py<T>>
|
pub fn new(py: Python, value: T) -> PyResult<Py<T>>
|
||||||
where
|
where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
|
@ -128,7 +122,8 @@ pub trait AsPyRef<T: PyTypeInfo>: Sized {
|
||||||
|
|
||||||
impl<T: PyTypeInfo> AsPyRef<T> for Py<T> {
|
impl<T: PyTypeInfo> AsPyRef<T> for Py<T> {
|
||||||
fn as_ref(&self, _py: Python) -> &T {
|
fn as_ref(&self, _py: Python) -> &T {
|
||||||
unsafe { &*(self as *const instance::Py<T> as *const T) }
|
let any = self as *const Py<T> as *const PyAny;
|
||||||
|
unsafe { T::ConcreteLayout::internal_ref_cast(&*any) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,8 +138,8 @@ impl<T> IntoPy<PyObject> for Py<T> {
|
||||||
/// Converts `Py` instance -> PyObject.
|
/// Converts `Py` instance -> PyObject.
|
||||||
/// Consumes `self` without calling `Py_DECREF()`
|
/// Consumes `self` without calling `Py_DECREF()`
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_py(self, py: Python) -> PyObject {
|
fn into_py(self, _py: Python) -> PyObject {
|
||||||
unsafe { PyObject::from_owned_ptr(py, self.into_ptr()) }
|
unsafe { PyObject::from_not_null(self.into_non_null()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,9 +156,25 @@ impl<T> IntoPyPointer for Py<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||||
let ptr = self.0.as_ptr();
|
self.into_non_null().as_ptr()
|
||||||
std::mem::forget(self);
|
}
|
||||||
ptr
|
}
|
||||||
|
|
||||||
|
impl<'a, T> std::convert::From<&PyClassShell<T>> for Py<T>
|
||||||
|
where
|
||||||
|
T: PyClass,
|
||||||
|
{
|
||||||
|
fn from(shell: &PyClassShell<T>) -> Self {
|
||||||
|
unsafe { Py::from_borrowed_ptr(shell.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> std::convert::From<&mut PyClassShell<T>> for Py<T>
|
||||||
|
where
|
||||||
|
T: PyClass,
|
||||||
|
{
|
||||||
|
fn from(shell: &mut PyClassShell<T>) -> Self {
|
||||||
|
unsafe { Py::from_borrowed_ptr(shell.as_ptr()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::class::methods::{PyMethodDefType, PyMethodsProtocol};
|
||||||
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
|
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
|
||||||
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||||
use crate::type_object::{type_flags, PyConcreteObject, PyTypeObject};
|
use crate::type_object::{type_flags, PyConcreteObject, PyTypeObject};
|
||||||
|
use crate::types::PyAny;
|
||||||
use crate::{class, ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
use crate::{class, ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
|
@ -112,7 +113,15 @@ impl<T: PyClass> PyClassShell<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PyClass> PyConcreteObject for PyClassShell<T> {
|
impl<T: PyClass> PyConcreteObject<T> for PyClassShell<T> {
|
||||||
|
unsafe fn internal_ref_cast(obj: &PyAny) -> &T {
|
||||||
|
let shell = obj.as_ptr() as *const PyClassShell<T>;
|
||||||
|
&*(*shell).pyclass
|
||||||
|
}
|
||||||
|
unsafe fn internal_mut_cast(obj: &PyAny) -> &mut T {
|
||||||
|
let shell = obj.as_ptr() as *const PyClassShell<T> as *mut PyClassShell<T>;
|
||||||
|
&mut *(*shell).pyclass
|
||||||
|
}
|
||||||
unsafe fn py_drop(&mut self, py: Python) {
|
unsafe fn py_drop(&mut self, py: Python) {
|
||||||
ManuallyDrop::drop(&mut self.pyclass);
|
ManuallyDrop::drop(&mut self.pyclass);
|
||||||
self.dict.clear_dict(py);
|
self.dict.clear_dict(py);
|
||||||
|
@ -121,6 +130,12 @@ impl<T: PyClass> PyConcreteObject 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> {
|
impl<T: PyClass> std::ops::Deref for PyClassShell<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
|
@ -134,7 +149,13 @@ impl<T: PyClass> std::ops::DerefMut for PyClassShell<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PyClass> ToPyObject for PyClassShell<T> {
|
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 {
|
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
@ -145,10 +166,11 @@ where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
{
|
{
|
||||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
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 *const _ as *const 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> {
|
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 *const _ as *const Self))
|
NonNull::new(ptr)
|
||||||
|
.map(|p| &*(gil::register_borrowed(py, p).as_ptr() as *const PyClassShell<T>))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,10 +179,14 @@ where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
{
|
{
|
||||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
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 *const _ as *mut Self))
|
NonNull::new(ptr).map(|p| {
|
||||||
|
&mut *(gil::register_owned(py, p).as_ptr() as *const PyClassShell<T> as *mut _)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
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 *const _ as *mut Self))
|
NonNull::new(ptr).map(|p| {
|
||||||
|
&mut *(gil::register_borrowed(py, p).as_ptr() as *const PyClassShell<T> as *mut _)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::ffi;
|
||||||
use crate::gil::{self, GILGuard};
|
use crate::gil::{self, GILGuard};
|
||||||
use crate::instance::AsPyRef;
|
use crate::instance::AsPyRef;
|
||||||
use crate::object::PyObject;
|
use crate::object::PyObject;
|
||||||
use crate::type_object::{PyTypeInfo, PyTypeObject};
|
use crate::type_object::{PyConcreteObject, PyTypeInfo, PyTypeObject};
|
||||||
use crate::types::{PyAny, PyDict, PyModule, PyType};
|
use crate::types::{PyAny, PyDict, PyModule, PyType};
|
||||||
use crate::AsPyPointer;
|
use crate::AsPyPointer;
|
||||||
use crate::{FromPyPointer, IntoPyPointer, PyTryFrom};
|
use crate::{FromPyPointer, IntoPyPointer, PyTryFrom};
|
||||||
|
@ -272,16 +272,6 @@ impl<'p> Python<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Python<'p> {
|
impl<'p> Python<'p> {
|
||||||
// TODO(kngwyu): Now offset dies, so what should this functions do
|
|
||||||
pub(crate) unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyAny) -> &'p T {
|
|
||||||
&*(ob as *const _ as *const T)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::cast_ref_to_mut)] // FIXME
|
|
||||||
pub(crate) unsafe fn unchecked_mut_downcast<T: PyTypeInfo>(self, ob: &PyAny) -> &'p mut T {
|
|
||||||
&mut *(ob as *const _ as *mut T)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register object in release pool, and try to downcast to specific type.
|
/// Register object in release pool, and try to downcast to specific type.
|
||||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
|
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
|
||||||
where
|
where
|
||||||
|
@ -297,7 +287,7 @@ impl<'p> Python<'p> {
|
||||||
T: PyTypeInfo,
|
T: PyTypeInfo,
|
||||||
{
|
{
|
||||||
let p = gil::register_owned(self, obj.into_nonnull());
|
let p = gil::register_owned(self, obj.into_nonnull());
|
||||||
self.unchecked_downcast(p)
|
T::ConcreteLayout::internal_ref_cast(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register `ffi::PyObject` pointer in release pool
|
/// Register `ffi::PyObject` pointer in release pool
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
use crate::instance::Py;
|
use crate::instance::Py;
|
||||||
|
use crate::instance::PyNativeType;
|
||||||
use crate::types::PyAny;
|
use crate::types::PyAny;
|
||||||
use crate::types::PyType;
|
use crate::types::PyType;
|
||||||
use crate::AsPyPointer;
|
use crate::AsPyPointer;
|
||||||
|
@ -11,17 +12,17 @@ use crate::Python;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
/// TODO: write document
|
/// TODO: write document
|
||||||
pub trait PyConcreteObject: Sized {
|
pub trait PyConcreteObject<T>: Sized {
|
||||||
|
unsafe fn internal_ref_cast(obj: &PyAny) -> &T {
|
||||||
|
&*(obj as *const _ as *const T)
|
||||||
|
}
|
||||||
|
unsafe fn internal_mut_cast(obj: &PyAny) -> &mut T {
|
||||||
|
&mut *(obj as *const _ as *const T as *mut T)
|
||||||
|
}
|
||||||
unsafe fn py_drop(&mut self, _py: Python) {}
|
unsafe fn py_drop(&mut self, _py: Python) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PyConcreteObject> AsPyPointer for T {
|
impl<T: PyNativeType> PyConcreteObject<T> for ffi::PyObject {}
|
||||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
|
||||||
(self as *const _) as _
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PyConcreteObject for ffi::PyObject {}
|
|
||||||
|
|
||||||
/// Our custom type flags
|
/// Our custom type flags
|
||||||
pub mod type_flags {
|
pub mod type_flags {
|
||||||
|
@ -39,7 +40,7 @@ pub mod type_flags {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Python type information.
|
/// Python type information.
|
||||||
pub trait PyTypeInfo {
|
pub trait PyTypeInfo: Sized {
|
||||||
/// Type of objects to store in PyObject struct
|
/// Type of objects to store in PyObject struct
|
||||||
type Type;
|
type Type;
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ pub trait PyTypeInfo {
|
||||||
type BaseType: PyTypeInfo;
|
type BaseType: PyTypeInfo;
|
||||||
|
|
||||||
/// Layout
|
/// Layout
|
||||||
type ConcreteLayout: PyConcreteObject;
|
type ConcreteLayout: PyConcreteObject<Self>;
|
||||||
|
|
||||||
/// PyTypeObject instance for this type, which might still need to
|
/// PyTypeObject instance for this type, which might still need to
|
||||||
/// be initialized
|
/// be initialized
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py_run;
|
use pyo3::py_run;
|
||||||
use pyo3::type_object::initialize_type;
|
use pyo3::pyclass::initialize_type;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::PyRawObject;
|
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
struct EmptyClassWithNew {}
|
struct EmptyClassWithNew {}
|
||||||
|
@ -7,8 +6,8 @@ struct EmptyClassWithNew {}
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl EmptyClassWithNew {
|
impl EmptyClassWithNew {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> EmptyClassWithNew {
|
||||||
obj.init(EmptyClassWithNew {});
|
EmptyClassWithNew {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +24,7 @@ fn empty_class_with_new() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
#[derive(Debug)]
|
||||||
struct NewWithOneArg {
|
struct NewWithOneArg {
|
||||||
_data: i32,
|
_data: i32,
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ struct NewWithOneArg {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl NewWithOneArg {
|
impl NewWithOneArg {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject, arg: i32) {
|
fn new(arg: i32) -> NewWithOneArg {
|
||||||
obj.init(NewWithOneArg { _data: arg })
|
NewWithOneArg { _data: arg }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,11 +56,11 @@ struct NewWithTwoArgs {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl NewWithTwoArgs {
|
impl NewWithTwoArgs {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject, arg1: i32, arg2: i32) {
|
fn new(arg1: i32, arg2: i32) -> Self {
|
||||||
obj.init(NewWithTwoArgs {
|
NewWithTwoArgs {
|
||||||
_data1: arg1,
|
_data1: arg1,
|
||||||
_data2: arg2,
|
_data2: arg2,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
tests/test_datetime.rs
Normal file → Executable file
0
tests/test_datetime.rs
Normal file → Executable file
|
@ -4,11 +4,9 @@ use pyo3::class::{
|
||||||
PyContextProtocol, PyIterProtocol, PyMappingProtocol, PyObjectProtocol, PySequenceProtocol,
|
PyContextProtocol, PyIterProtocol, PyMappingProtocol, PyObjectProtocol, PySequenceProtocol,
|
||||||
};
|
};
|
||||||
use pyo3::exceptions::{IndexError, ValueError};
|
use pyo3::exceptions::{IndexError, ValueError};
|
||||||
use pyo3::ffi;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py_run;
|
|
||||||
use pyo3::types::{IntoPyDict, PyAny, PyBytes, PySlice, PyType};
|
use pyo3::types::{IntoPyDict, PyAny, PyBytes, PySlice, PyType};
|
||||||
use pyo3::AsPyPointer;
|
use pyo3::{ffi, py_run, AsPyPointer, PyClassShell};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::{isize, iter};
|
use std::{isize, iter};
|
||||||
|
|
||||||
|
@ -55,11 +53,11 @@ struct Iterator {
|
||||||
|
|
||||||
#[pyproto]
|
#[pyproto]
|
||||||
impl<'p> PyIterProtocol for Iterator {
|
impl<'p> PyIterProtocol for Iterator {
|
||||||
fn __iter__(slf: PyRefMut<Self>) -> PyResult<Py<Iterator>> {
|
fn __iter__(slf: &mut PyClassShell<Self>) -> PyResult<Py<Iterator>> {
|
||||||
Ok(slf.into())
|
Ok(slf.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<i32>> {
|
fn __next__(mut slf: &mut PyClassShell<Self>) -> PyResult<Option<i32>> {
|
||||||
Ok(slf.iter.next())
|
Ok(slf.iter.next())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +250,7 @@ fn setitem() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let c = PyRef::new(py, SetItem { key: 0, val: 0 }).unwrap();
|
let c = PyClassShell::new_ref(py, SetItem { key: 0, val: 0 }).unwrap();
|
||||||
py_run!(py, c, "c[1] = 2");
|
py_run!(py, c, "c[1] = 2");
|
||||||
assert_eq!(c.key, 1);
|
assert_eq!(c.key, 1);
|
||||||
assert_eq!(c.val, 2);
|
assert_eq!(c.val, 2);
|
||||||
|
@ -277,7 +275,7 @@ fn delitem() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let c = PyRef::new(py, DelItem { key: 0 }).unwrap();
|
let c = PyClassShell::new_ref(py, DelItem { key: 0 }).unwrap();
|
||||||
py_run!(py, c, "del c[1]");
|
py_run!(py, c, "del c[1]");
|
||||||
assert_eq!(c.key, 1);
|
assert_eq!(c.key, 1);
|
||||||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||||
|
@ -306,7 +304,7 @@ fn setdelitem() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let c = PyRef::new(py, SetDelItem { val: None }).unwrap();
|
let c = PyClassShell::new_ref(py, SetDelItem { val: None }).unwrap();
|
||||||
py_run!(py, c, "c[1] = 2");
|
py_run!(py, c, "c[1] = 2");
|
||||||
assert_eq!(c.val, Some(2));
|
assert_eq!(c.val, Some(2));
|
||||||
py_run!(py, c, "del c[1]");
|
py_run!(py, c, "del c[1]");
|
||||||
|
@ -385,7 +383,7 @@ fn context_manager() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let mut c = PyRefMut::new(py, ContextManager { exit_called: false }).unwrap();
|
let c = PyClassShell::new_mut(py, ContextManager { exit_called: false }).unwrap();
|
||||||
py_run!(py, c, "with c as x: assert x == 42");
|
py_run!(py, c, "with c as x: assert x == 42");
|
||||||
assert!(c.exit_called);
|
assert!(c.exit_called);
|
||||||
|
|
||||||
|
@ -457,7 +455,7 @@ struct DunderDictSupport {}
|
||||||
fn dunder_dict_support() {
|
fn dunder_dict_support() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(py, DunderDictSupport {}).unwrap();
|
let inst = PyClassShell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||||
py_run!(
|
py_run!(
|
||||||
py,
|
py,
|
||||||
inst,
|
inst,
|
||||||
|
@ -472,7 +470,7 @@ fn dunder_dict_support() {
|
||||||
fn access_dunder_dict() {
|
fn access_dunder_dict() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(py, DunderDictSupport {}).unwrap();
|
let inst = PyClassShell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||||
py_run!(
|
py_run!(
|
||||||
py,
|
py,
|
||||||
inst,
|
inst,
|
||||||
|
@ -490,7 +488,7 @@ struct WeakRefDunderDictSupport {}
|
||||||
fn weakref_dunder_dict_support() {
|
fn weakref_dunder_dict_support() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(py, WeakRefDunderDictSupport {}).unwrap();
|
let inst = PyClassShell::new_ref(py, WeakRefDunderDictSupport {}).unwrap();
|
||||||
py_run!(
|
py_run!(
|
||||||
py,
|
py,
|
||||||
inst,
|
inst,
|
||||||
|
@ -515,7 +513,7 @@ impl PyObjectProtocol for ClassWithGetAttr {
|
||||||
fn getattr_doesnt_override_member() {
|
fn getattr_doesnt_override_member() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(py, ClassWithGetAttr { data: 4 }).unwrap();
|
let inst = PyClassShell::new_ref(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||||
py_assert!(py, inst, "inst.data == 4");
|
py_assert!(py, inst, "inst.data == 4");
|
||||||
py_assert!(py, inst, "inst.a == 8");
|
py_assert!(py, inst, "inst.a == 8");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
use pyo3::class::PyGCProtocol;
|
use pyo3::class::PyGCProtocol;
|
||||||
use pyo3::class::PyTraverseError;
|
use pyo3::class::PyTraverseError;
|
||||||
use pyo3::class::PyVisit;
|
use pyo3::class::PyVisit;
|
||||||
use pyo3::ffi;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py_run;
|
use pyo3::types::{PyAny, PyTuple};
|
||||||
use pyo3::types::PyAny;
|
use pyo3::{ffi, py_run, AsPyPointer, PyClassShell};
|
||||||
use pyo3::types::PyTuple;
|
|
||||||
use pyo3::AsPyPointer;
|
|
||||||
use pyo3::PyRawObject;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -157,7 +153,7 @@ fn gc_integration() {
|
||||||
{
|
{
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(
|
let inst = PyClassShell::new_mut(
|
||||||
py,
|
py,
|
||||||
GCIntegration {
|
GCIntegration {
|
||||||
self_ref: RefCell::new(py.None()),
|
self_ref: RefCell::new(py.None()),
|
||||||
|
@ -192,7 +188,7 @@ impl PyGCProtocol for GCIntegration2 {
|
||||||
fn gc_integration2() {
|
fn gc_integration2() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(py, GCIntegration2 {}).unwrap();
|
let inst = PyClassShell::new_ref(py, GCIntegration2 {}).unwrap();
|
||||||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +199,7 @@ struct WeakRefSupport {}
|
||||||
fn weakref_support() {
|
fn weakref_support() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let inst = PyRef::new(py, WeakRefSupport {}).unwrap();
|
let inst = PyClassShell::new_ref(py, WeakRefSupport {}).unwrap();
|
||||||
py_run!(
|
py_run!(
|
||||||
py,
|
py,
|
||||||
inst,
|
inst,
|
||||||
|
@ -219,8 +215,8 @@ struct BaseClassWithDrop {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl BaseClassWithDrop {
|
impl BaseClassWithDrop {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> BaseClassWithDrop {
|
||||||
obj.init(BaseClassWithDrop { data: None })
|
BaseClassWithDrop { data: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,10 +235,10 @@ struct SubClassWithDrop {
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl SubClassWithDrop {
|
impl SubClassWithDrop {
|
||||||
|
// TODO(kngwyu): Implement baseclass initialization
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> SubClassWithDrop {
|
||||||
obj.init(SubClassWithDrop { data: None });
|
SubClassWithDrop { data: None }
|
||||||
BaseClassWithDrop::new(obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use pyo3::prelude::*;
|
||||||
use pyo3::py_run;
|
use pyo3::py_run;
|
||||||
#[cfg(feature = "unsound-subclass")]
|
#[cfg(feature = "unsound-subclass")]
|
||||||
use pyo3::types::IntoPyDict;
|
use pyo3::types::IntoPyDict;
|
||||||
use std::isize;
|
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
@ -35,8 +34,8 @@ fn subclass() {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl BaseClass {
|
impl BaseClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> Self {
|
||||||
obj.init(BaseClass { val1: 10 })
|
BaseClass { val1: 10 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,13 +48,14 @@ struct SubClass {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl SubClass {
|
impl SubClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> Self {
|
||||||
obj.init(SubClass { val2: 5 });
|
SubClass { val2: 5 }
|
||||||
BaseClass::new(obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(kngwyu): disable untill super().__init__ fixed
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn inheritance_with_new_methods() {
|
fn inheritance_with_new_methods() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
9
tests/test_mapping.rs
Normal file → Executable file
9
tests/test_mapping.rs
Normal file → Executable file
|
@ -15,20 +15,19 @@ struct Mapping {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Mapping {
|
impl Mapping {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject, elements: Option<&PyList>) -> PyResult<()> {
|
fn new(elements: Option<&PyList>) -> PyResult<Self> {
|
||||||
if let Some(pylist) = elements {
|
if let Some(pylist) = elements {
|
||||||
let mut elems = HashMap::with_capacity(pylist.len());
|
let mut elems = HashMap::with_capacity(pylist.len());
|
||||||
for (i, pyelem) in pylist.into_iter().enumerate() {
|
for (i, pyelem) in pylist.into_iter().enumerate() {
|
||||||
let elem = String::extract(pyelem)?;
|
let elem = String::extract(pyelem)?;
|
||||||
elems.insert(elem, i);
|
elems.insert(elem, i);
|
||||||
}
|
}
|
||||||
obj.init(Self { index: elems });
|
Ok(Self { index: elems })
|
||||||
} else {
|
} else {
|
||||||
obj.init(Self {
|
Ok(Self {
|
||||||
index: HashMap::new(),
|
index: HashMap::new(),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py_run;
|
use pyo3::py_run;
|
||||||
use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType};
|
use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType};
|
||||||
use pyo3::PyRawObject;
|
use pyo3::PyClassShell;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ fn instance_method() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let obj = PyRefMut::new(py, InstanceMethod { member: 42 }).unwrap();
|
let obj = PyClassShell::new_mut(py, InstanceMethod { member: 42 }).unwrap();
|
||||||
assert_eq!(obj.method().unwrap(), 42);
|
assert_eq!(obj.method().unwrap(), 42);
|
||||||
let d = [("obj", obj)].into_py_dict(py);
|
let d = [("obj", obj)].into_py_dict(py);
|
||||||
py.run("assert obj.method() == 42", None, Some(d)).unwrap();
|
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 gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let obj = PyRefMut::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
let obj = PyClassShell::new_mut(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
||||||
assert_eq!(obj.method(6).unwrap(), 42);
|
assert_eq!(obj.method(6).unwrap(), 42);
|
||||||
let d = [("obj", obj)].into_py_dict(py);
|
let d = [("obj", obj)].into_py_dict(py);
|
||||||
py.run("assert obj.method(3) == 21", None, Some(d)).unwrap();
|
py.run("assert obj.method(3) == 21", None, Some(d)).unwrap();
|
||||||
|
@ -63,8 +63,8 @@ struct ClassMethod {}
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl ClassMethod {
|
impl ClassMethod {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> Self {
|
||||||
obj.init(ClassMethod {})
|
ClassMethod {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[classmethod]
|
#[classmethod]
|
||||||
|
@ -137,8 +137,8 @@ struct StaticMethod {}
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl StaticMethod {
|
impl StaticMethod {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> Self {
|
||||||
obj.init(StaticMethod {})
|
StaticMethod {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
|
@ -395,7 +395,7 @@ impl MethodWithLifeTime {
|
||||||
fn method_with_lifetime() {
|
fn method_with_lifetime() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let obj = PyRef::new(py, MethodWithLifeTime {}).unwrap();
|
let obj = PyClassShell::new_ref(py, MethodWithLifeTime {}).unwrap();
|
||||||
py_run!(
|
py_run!(
|
||||||
py,
|
py,
|
||||||
obj,
|
obj,
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
use pyo3::prelude::*;
|
|
||||||
use pyo3::py_run;
|
|
||||||
use pyo3::pyclass::PyClassShell;
|
|
||||||
use pyo3::types::PyAny;
|
|
||||||
use pyo3::FromPyPointer;
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
struct Class {
|
|
||||||
member: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
impl Class {
|
|
||||||
fn hello(&self) -> i32 {
|
|
||||||
self.member
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_shell() {
|
|
||||||
let class = Class { member: 128 };
|
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
// let obj: &PyAny = unsafe { FromPyPointer::from_owned_ptr(py, PyClassShell::new(py, class)) };
|
|
||||||
// py_run!(py, obj, "assert obj.hello() == 128");
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
use pyo3;
|
use pyo3;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::{PyBytes, PyString};
|
use pyo3::types::{PyBytes, PyString};
|
||||||
use pyo3::PyIterProtocol;
|
use pyo3::{AsPyRef, PyClassShell, PyIterProtocol};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
@ -10,20 +10,23 @@ mod common;
|
||||||
/// Assumes it's a file reader or so.
|
/// Assumes it's a file reader or so.
|
||||||
/// Inspired by https://github.com/jothan/cordoba, thanks.
|
/// Inspired by https://github.com/jothan/cordoba, thanks.
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
struct Reader {
|
struct Reader {
|
||||||
inner: HashMap<u8, String>,
|
inner: HashMap<u8, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Reader {
|
impl Reader {
|
||||||
fn clone_ref(slf: PyRef<Self>) -> PyRef<Self> {
|
fn clone_ref(slf: &PyClassShell<Self>) -> &PyClassShell<Self> {
|
||||||
slf
|
slf
|
||||||
}
|
}
|
||||||
fn clone_ref_with_py<'py>(slf: PyRef<'py, Self>, _py: Python<'py>) -> PyRef<'py, Self> {
|
fn clone_ref_with_py<'py>(
|
||||||
|
slf: &'py PyClassShell<Self>,
|
||||||
|
_py: Python<'py>,
|
||||||
|
) -> &'py PyClassShell<Self> {
|
||||||
slf
|
slf
|
||||||
}
|
}
|
||||||
fn get_iter(slf: PyRef<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
fn get_iter(slf: &PyClassShell<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||||
Ok(Iter {
|
Ok(Iter {
|
||||||
reader: slf.into(),
|
reader: slf.into(),
|
||||||
keys,
|
keys,
|
||||||
|
@ -31,7 +34,7 @@ impl Reader {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn get_iter_and_reset(
|
fn get_iter_and_reset(
|
||||||
mut slf: PyRefMut<Self>,
|
slf: &mut PyClassShell<Self>,
|
||||||
keys: Py<PyBytes>,
|
keys: Py<PyBytes>,
|
||||||
py: Python,
|
py: Python,
|
||||||
) -> PyResult<Iter> {
|
) -> PyResult<Iter> {
|
||||||
|
@ -54,13 +57,15 @@ struct Iter {
|
||||||
|
|
||||||
#[pyproto]
|
#[pyproto]
|
||||||
impl PyIterProtocol for Iter {
|
impl PyIterProtocol for Iter {
|
||||||
fn __iter__(slf: PyRefMut<Self>) -> PyResult<PyObject> {
|
fn __iter__(slf: &mut PyClassShell<Self>) -> PyResult<PyObject> {
|
||||||
let py = unsafe { Python::assume_gil_acquired() };
|
let py = unsafe { Python::assume_gil_acquired() };
|
||||||
Ok(slf.to_object(py))
|
Ok(slf.to_object(py))
|
||||||
}
|
}
|
||||||
fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<PyObject>> {
|
|
||||||
|
fn __next__(slf: &mut PyClassShell<Self>) -> PyResult<Option<PyObject>> {
|
||||||
let py = unsafe { Python::assume_gil_acquired() };
|
let py = unsafe { Python::assume_gil_acquired() };
|
||||||
match slf.keys.as_ref(py).as_bytes().get(slf.idx) {
|
let bytes = slf.keys.as_ref(py).as_bytes();
|
||||||
|
match bytes.get(slf.idx) {
|
||||||
Some(&b) => {
|
Some(&b) => {
|
||||||
let res = slf
|
let res = slf
|
||||||
.reader
|
.reader
|
||||||
|
@ -84,7 +89,7 @@ fn reader() -> Reader {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nested_iter() {
|
fn test_nested_iter1() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let reader: PyObject = reader().into_py(py);
|
let reader: PyObject = reader().into_py(py);
|
||||||
|
@ -108,7 +113,7 @@ fn test_clone_ref() {
|
||||||
fn test_nested_iter_reset() {
|
fn test_nested_iter_reset() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let reader = PyRef::new(py, reader()).unwrap();
|
let reader = PyClassShell::new_ref(py, reader()).unwrap();
|
||||||
py_assert!(
|
py_assert!(
|
||||||
py,
|
py,
|
||||||
reader,
|
reader,
|
||||||
|
|
|
@ -14,20 +14,19 @@ struct ByteSequence {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl ByteSequence {
|
impl ByteSequence {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject, elements: Option<&PyList>) -> PyResult<()> {
|
fn new(elements: Option<&PyList>) -> PyResult<Self> {
|
||||||
if let Some(pylist) = elements {
|
if let Some(pylist) = elements {
|
||||||
let mut elems = Vec::with_capacity(pylist.len());
|
let mut elems = Vec::with_capacity(pylist.len());
|
||||||
for pyelem in pylist.into_iter() {
|
for pyelem in pylist.into_iter() {
|
||||||
let elem = u8::extract(pyelem)?;
|
let elem = u8::extract(pyelem)?;
|
||||||
elems.push(elem);
|
elems.push(elem);
|
||||||
}
|
}
|
||||||
obj.init(Self { elements: elems });
|
Ok(Self { elements: elems })
|
||||||
} else {
|
} else {
|
||||||
obj.init(Self {
|
Ok(Self {
|
||||||
elements: Vec::new(),
|
elements: Vec::new(),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::{types::PyType, wrap_pyfunction, wrap_pymodule};
|
use pyo3::{types::PyType, wrap_pyfunction, wrap_pymodule, PyClassShell};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@ fn class_with_docs_and_signature() {
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[new]
|
#[new]
|
||||||
#[args(a, b = "None", "*", c = 42)]
|
#[args(a, b = "None", "*", c = 42)]
|
||||||
fn __new__(obj: &PyRawObject, a: i32, b: Option<i32>, c: i32) {
|
fn __new__(a: i32, b: Option<i32>, c: i32) -> Self {
|
||||||
let _ = (a, b, c);
|
let _ = (a, b, c);
|
||||||
obj.init(Self {});
|
Self {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ fn class_with_signature() {
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[new]
|
#[new]
|
||||||
#[args(a, b = "None", "*", c = 42)]
|
#[args(a, b = "None", "*", c = 42)]
|
||||||
fn __new__(obj: &PyRawObject, a: i32, b: Option<i32>, c: i32) {
|
fn __new__(a: i32, b: Option<i32>, c: i32) -> Self {
|
||||||
let _ = (a, b, c);
|
let _ = (a, b, c);
|
||||||
obj.init(Self {});
|
Self {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ fn test_methods() {
|
||||||
let _ = a;
|
let _ = a;
|
||||||
}
|
}
|
||||||
#[text_signature = "($self, b)"]
|
#[text_signature = "($self, b)"]
|
||||||
fn pyself_method(_this: PyRef<Self>, b: i32) {
|
fn pyself_method(_this: &PyClassShell<Self>, b: i32) {
|
||||||
let _ = b;
|
let _ = b;
|
||||||
}
|
}
|
||||||
#[classmethod]
|
#[classmethod]
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::type_object::initialize_type;
|
use pyo3::pyclass::initialize_type;
|
||||||
use pyo3::types::IntoPyDict;
|
use pyo3::types::IntoPyDict;
|
||||||
use pyo3::types::{PyDict, PyTuple};
|
use pyo3::types::{PyDict, PyTuple};
|
||||||
use pyo3::{py_run, wrap_pyfunction};
|
use pyo3::{py_run, wrap_pyfunction, AsPyRef, PyClassShell};
|
||||||
use std::isize;
|
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
@ -83,8 +82,8 @@ fn intopytuple_pyclass() {
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
let tup = (
|
let tup = (
|
||||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||||
);
|
);
|
||||||
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
|
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
|
||||||
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[1]).__name__");
|
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[1]).__name__");
|
||||||
|
@ -108,8 +107,8 @@ fn pytuple_pyclass_iter() {
|
||||||
let tup = PyTuple::new(
|
let tup = PyTuple::new(
|
||||||
py,
|
py,
|
||||||
[
|
[
|
||||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||||
]
|
]
|
||||||
.iter(),
|
.iter(),
|
||||||
);
|
);
|
||||||
|
@ -124,12 +123,12 @@ struct PickleSupport {}
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl PickleSupport {
|
impl PickleSupport {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(obj: &PyRawObject) {
|
fn new() -> PickleSupport {
|
||||||
obj.init({ PickleSupport {} });
|
PickleSupport {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __reduce__<'py>(
|
pub fn __reduce__<'py>(
|
||||||
slf: PyRef<Self>,
|
slf: &'py PyClassShell<Self>,
|
||||||
py: Python<'py>,
|
py: Python<'py>,
|
||||||
) -> PyResult<(PyObject, &'py PyTuple, PyObject)> {
|
) -> PyResult<(PyObject, &'py PyTuple, PyObject)> {
|
||||||
let cls = slf.to_object(py).getattr(py, "__class__")?;
|
let cls = slf.to_object(py).getattr(py, "__class__")?;
|
||||||
|
@ -155,7 +154,7 @@ fn test_pickle() {
|
||||||
module.add_class::<PickleSupport>().unwrap();
|
module.add_class::<PickleSupport>().unwrap();
|
||||||
add_module(py, module).unwrap();
|
add_module(py, module).unwrap();
|
||||||
initialize_type::<PickleSupport>(py, Some("test_module")).unwrap();
|
initialize_type::<PickleSupport>(py, Some("test_module")).unwrap();
|
||||||
let inst = PyRef::new(py, PickleSupport {}).unwrap();
|
let inst = PyClassShell::new_ref(py, PickleSupport {}).unwrap();
|
||||||
py_run!(
|
py_run!(
|
||||||
py,
|
py,
|
||||||
inst,
|
inst,
|
||||||
|
|
Loading…
Reference in a new issue