Introduce PyInternalCaster
This commit is contained in:
parent
4d7dfafe2b
commit
a6639076b9
|
@ -65,7 +65,7 @@ impl<'a> FnSpec<'a> {
|
|||
ref pat, ref ty, ..
|
||||
}) => {
|
||||
// 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;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@ macro_rules! py_unary_pyref_func {
|
|||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
use $crate::{pyclass::PyClassShell, FromPyPointer};
|
||||
use $crate::pyclass::PyClassShell;
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
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();
|
||||
$crate::callback::cb_convert($conv, py, res)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! Conversions between various states of rust and python types and their wrappers.
|
||||
use crate::err::{self, PyDowncastError, PyResult};
|
||||
use crate::object::PyObject;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::type_object::{PyConcreteObject, PyTypeInfo};
|
||||
use crate::types::PyAny;
|
||||
use crate::types::PyTuple;
|
||||
use crate::{ffi, gil, Py, Python};
|
||||
|
@ -393,15 +393,13 @@ where
|
|||
#[inline]
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v T {
|
||||
let value = value.into();
|
||||
let ptr = value as *const _ as *const u8 as *const T;
|
||||
&*ptr
|
||||
T::ConcreteLayout::internal_ref_cast(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v mut T {
|
||||
let value = value.into();
|
||||
let ptr = value as *const _ as *mut u8 as *mut T;
|
||||
&mut *ptr
|
||||
T::ConcreteLayout::internal_mut_cast(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,10 +451,11 @@ where
|
|||
T: PyTypeInfo,
|
||||
{
|
||||
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> {
|
||||
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,
|
||||
{
|
||||
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> {
|
||||
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
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::gil;
|
||||
use crate::instance;
|
||||
use crate::object::PyObject;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::pyclass::{PyClass, PyClassShell};
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::type_object::{PyConcreteObject, PyTypeInfo};
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, IntoPy};
|
||||
use crate::{AsPyPointer, FromPyObject, IntoPyPointer, Python, ToPyObject};
|
||||
|
@ -36,11 +35,6 @@ unsafe impl<T> Sync for Py<T> {}
|
|||
|
||||
impl<T> Py<T> {
|
||||
/// 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>>
|
||||
where
|
||||
T: PyClass,
|
||||
|
@ -128,7 +122,8 @@ pub trait AsPyRef<T: PyTypeInfo>: Sized {
|
|||
|
||||
impl<T: PyTypeInfo> AsPyRef<T> for Py<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.
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
fn into_py(self, py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_owned_ptr(py, self.into_ptr()) }
|
||||
fn into_py(self, _py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_not_null(self.into_non_null()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,9 +156,25 @@ impl<T> IntoPyPointer for Py<T> {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
let ptr = self.0.as_ptr();
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
self.into_non_null().as_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::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||
use crate::type_object::{type_flags, PyConcreteObject, PyTypeObject};
|
||||
use crate::types::PyAny;
|
||||
use crate::{class, ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
||||
use std::ffi::CString;
|
||||
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) {
|
||||
ManuallyDrop::drop(&mut self.pyclass);
|
||||
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> {
|
||||
type Target = 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 {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
|
@ -145,10 +166,11 @@ 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 *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> {
|
||||
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,
|
||||
{
|
||||
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> {
|
||||
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::instance::AsPyRef;
|
||||
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::AsPyPointer;
|
||||
use crate::{FromPyPointer, IntoPyPointer, PyTryFrom};
|
||||
|
@ -272,16 +272,6 @@ 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.
|
||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
|
||||
where
|
||||
|
@ -297,7 +287,7 @@ impl<'p> Python<'p> {
|
|||
T: PyTypeInfo,
|
||||
{
|
||||
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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use crate::ffi;
|
||||
use crate::instance::Py;
|
||||
use crate::instance::PyNativeType;
|
||||
use crate::types::PyAny;
|
||||
use crate::types::PyType;
|
||||
use crate::AsPyPointer;
|
||||
|
@ -11,17 +12,17 @@ use crate::Python;
|
|||
use std::ptr::NonNull;
|
||||
|
||||
/// 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) {}
|
||||
}
|
||||
|
||||
impl<T: PyConcreteObject> AsPyPointer for T {
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
(self as *const _) as _
|
||||
}
|
||||
}
|
||||
|
||||
impl PyConcreteObject for ffi::PyObject {}
|
||||
impl<T: PyNativeType> PyConcreteObject<T> for ffi::PyObject {}
|
||||
|
||||
/// Our custom type flags
|
||||
pub mod type_flags {
|
||||
|
@ -39,7 +40,7 @@ pub mod type_flags {
|
|||
}
|
||||
|
||||
/// Python type information.
|
||||
pub trait PyTypeInfo {
|
||||
pub trait PyTypeInfo: Sized {
|
||||
/// Type of objects to store in PyObject struct
|
||||
type Type;
|
||||
|
||||
|
@ -59,7 +60,7 @@ pub trait PyTypeInfo {
|
|||
type BaseType: PyTypeInfo;
|
||||
|
||||
/// Layout
|
||||
type ConcreteLayout: PyConcreteObject;
|
||||
type ConcreteLayout: PyConcreteObject<Self>;
|
||||
|
||||
/// PyTypeObject instance for this type, which might still need to
|
||||
/// be initialized
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::py_run;
|
||||
use pyo3::type_object::initialize_type;
|
||||
use pyo3::pyclass::initialize_type;
|
||||
|
||||
mod common;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::PyRawObject;
|
||||
|
||||
#[pyclass]
|
||||
struct EmptyClassWithNew {}
|
||||
|
@ -7,8 +6,8 @@ struct EmptyClassWithNew {}
|
|||
#[pymethods]
|
||||
impl EmptyClassWithNew {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(EmptyClassWithNew {});
|
||||
fn new() -> EmptyClassWithNew {
|
||||
EmptyClassWithNew {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +24,7 @@ fn empty_class_with_new() {
|
|||
}
|
||||
|
||||
#[pyclass]
|
||||
#[derive(Debug)]
|
||||
struct NewWithOneArg {
|
||||
_data: i32,
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ struct NewWithOneArg {
|
|||
#[pymethods]
|
||||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject, arg: i32) {
|
||||
obj.init(NewWithOneArg { _data: arg })
|
||||
fn new(arg: i32) -> NewWithOneArg {
|
||||
NewWithOneArg { _data: arg }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +56,11 @@ struct NewWithTwoArgs {
|
|||
#[pymethods]
|
||||
impl NewWithTwoArgs {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject, arg1: i32, arg2: i32) {
|
||||
obj.init(NewWithTwoArgs {
|
||||
fn new(arg1: i32, arg2: i32) -> Self {
|
||||
NewWithTwoArgs {
|
||||
_data1: arg1,
|
||||
_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,
|
||||
};
|
||||
use pyo3::exceptions::{IndexError, ValueError};
|
||||
use pyo3::ffi;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py_run;
|
||||
use pyo3::types::{IntoPyDict, PyAny, PyBytes, PySlice, PyType};
|
||||
use pyo3::AsPyPointer;
|
||||
use pyo3::{ffi, py_run, AsPyPointer, PyClassShell};
|
||||
use std::convert::TryFrom;
|
||||
use std::{isize, iter};
|
||||
|
||||
|
@ -55,11 +53,11 @@ struct Iterator {
|
|||
|
||||
#[pyproto]
|
||||
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())
|
||||
}
|
||||
|
||||
fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<i32>> {
|
||||
fn __next__(mut slf: &mut PyClassShell<Self>) -> PyResult<Option<i32>> {
|
||||
Ok(slf.iter.next())
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +250,7 @@ fn setitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
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");
|
||||
assert_eq!(c.key, 1);
|
||||
assert_eq!(c.val, 2);
|
||||
|
@ -277,7 +275,7 @@ fn delitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
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]");
|
||||
assert_eq!(c.key, 1);
|
||||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||
|
@ -306,7 +304,7 @@ fn setdelitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
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");
|
||||
assert_eq!(c.val, Some(2));
|
||||
py_run!(py, c, "del c[1]");
|
||||
|
@ -385,7 +383,7 @@ fn context_manager() {
|
|||
let gil = Python::acquire_gil();
|
||||
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");
|
||||
assert!(c.exit_called);
|
||||
|
||||
|
@ -457,7 +455,7 @@ struct DunderDictSupport {}
|
|||
fn dunder_dict_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyRef::new(py, DunderDictSupport {}).unwrap();
|
||||
let inst = PyClassShell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -472,7 +470,7 @@ fn dunder_dict_support() {
|
|||
fn access_dunder_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyRef::new(py, DunderDictSupport {}).unwrap();
|
||||
let inst = PyClassShell::new_ref(py, DunderDictSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -490,7 +488,7 @@ struct WeakRefDunderDictSupport {}
|
|||
fn weakref_dunder_dict_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyRef::new(py, WeakRefDunderDictSupport {}).unwrap();
|
||||
let inst = PyClassShell::new_ref(py, WeakRefDunderDictSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -515,7 +513,7 @@ impl PyObjectProtocol for ClassWithGetAttr {
|
|||
fn getattr_doesnt_override_member() {
|
||||
let gil = Python::acquire_gil();
|
||||
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.a == 8");
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
use pyo3::class::PyGCProtocol;
|
||||
use pyo3::class::PyTraverseError;
|
||||
use pyo3::class::PyVisit;
|
||||
use pyo3::ffi;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py_run;
|
||||
use pyo3::types::PyAny;
|
||||
use pyo3::types::PyTuple;
|
||||
use pyo3::AsPyPointer;
|
||||
use pyo3::PyRawObject;
|
||||
use pyo3::types::{PyAny, PyTuple};
|
||||
use pyo3::{ffi, py_run, AsPyPointer, PyClassShell};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
@ -157,7 +153,7 @@ fn gc_integration() {
|
|||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyRef::new(
|
||||
let inst = PyClassShell::new_mut(
|
||||
py,
|
||||
GCIntegration {
|
||||
self_ref: RefCell::new(py.None()),
|
||||
|
@ -192,7 +188,7 @@ impl PyGCProtocol for GCIntegration2 {
|
|||
fn gc_integration2() {
|
||||
let gil = Python::acquire_gil();
|
||||
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()");
|
||||
}
|
||||
|
||||
|
@ -203,7 +199,7 @@ struct WeakRefSupport {}
|
|||
fn weakref_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyRef::new(py, WeakRefSupport {}).unwrap();
|
||||
let inst = PyClassShell::new_ref(py, WeakRefSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
|
@ -219,8 +215,8 @@ struct BaseClassWithDrop {
|
|||
#[pymethods]
|
||||
impl BaseClassWithDrop {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(BaseClassWithDrop { data: None })
|
||||
fn new() -> BaseClassWithDrop {
|
||||
BaseClassWithDrop { data: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,10 +235,10 @@ struct SubClassWithDrop {
|
|||
|
||||
#[pymethods]
|
||||
impl SubClassWithDrop {
|
||||
// TODO(kngwyu): Implement baseclass initialization
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(SubClassWithDrop { data: None });
|
||||
BaseClassWithDrop::new(obj);
|
||||
fn new() -> SubClassWithDrop {
|
||||
SubClassWithDrop { data: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ use pyo3::prelude::*;
|
|||
use pyo3::py_run;
|
||||
#[cfg(feature = "unsound-subclass")]
|
||||
use pyo3::types::IntoPyDict;
|
||||
use std::isize;
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -35,8 +34,8 @@ fn subclass() {
|
|||
#[pymethods]
|
||||
impl BaseClass {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(BaseClass { val1: 10 })
|
||||
fn new() -> Self {
|
||||
BaseClass { val1: 10 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,13 +48,14 @@ struct SubClass {
|
|||
#[pymethods]
|
||||
impl SubClass {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(SubClass { val2: 5 });
|
||||
BaseClass::new(obj);
|
||||
fn new() -> Self {
|
||||
SubClass { val2: 5 }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(kngwyu): disable untill super().__init__ fixed
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn inheritance_with_new_methods() {
|
||||
let gil = Python::acquire_gil();
|
||||
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]
|
||||
impl Mapping {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject, elements: Option<&PyList>) -> PyResult<()> {
|
||||
fn new(elements: Option<&PyList>) -> PyResult<Self> {
|
||||
if let Some(pylist) = elements {
|
||||
let mut elems = HashMap::with_capacity(pylist.len());
|
||||
for (i, pyelem) in pylist.into_iter().enumerate() {
|
||||
let elem = String::extract(pyelem)?;
|
||||
elems.insert(elem, i);
|
||||
}
|
||||
obj.init(Self { index: elems });
|
||||
Ok(Self { index: elems })
|
||||
} else {
|
||||
obj.init(Self {
|
||||
Ok(Self {
|
||||
index: HashMap::new(),
|
||||
});
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::py_run;
|
||||
use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType};
|
||||
use pyo3::PyRawObject;
|
||||
use pyo3::PyClassShell;
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -23,7 +23,7 @@ fn instance_method() {
|
|||
let gil = Python::acquire_gil();
|
||||
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);
|
||||
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 = PyRefMut::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
||||
let obj = PyClassShell::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();
|
||||
|
@ -63,8 +63,8 @@ struct ClassMethod {}
|
|||
#[pymethods]
|
||||
impl ClassMethod {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(ClassMethod {})
|
||||
fn new() -> Self {
|
||||
ClassMethod {}
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
|
@ -137,8 +137,8 @@ struct StaticMethod {}
|
|||
#[pymethods]
|
||||
impl StaticMethod {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init(StaticMethod {})
|
||||
fn new() -> Self {
|
||||
StaticMethod {}
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
|
@ -395,7 +395,7 @@ impl MethodWithLifeTime {
|
|||
fn method_with_lifetime() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj = PyRef::new(py, MethodWithLifeTime {}).unwrap();
|
||||
let obj = PyClassShell::new_ref(py, MethodWithLifeTime {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
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::prelude::*;
|
||||
use pyo3::types::{PyBytes, PyString};
|
||||
use pyo3::PyIterProtocol;
|
||||
use pyo3::{AsPyRef, PyClassShell, PyIterProtocol};
|
||||
use std::collections::HashMap;
|
||||
|
||||
mod common;
|
||||
|
@ -10,20 +10,23 @@ mod common;
|
|||
/// Assumes it's a file reader or so.
|
||||
/// Inspired by https://github.com/jothan/cordoba, thanks.
|
||||
#[pyclass]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
struct Reader {
|
||||
inner: HashMap<u8, String>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Reader {
|
||||
fn clone_ref(slf: PyRef<Self>) -> PyRef<Self> {
|
||||
fn clone_ref(slf: &PyClassShell<Self>) -> &PyClassShell<Self> {
|
||||
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
|
||||
}
|
||||
fn get_iter(slf: PyRef<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||
fn get_iter(slf: &PyClassShell<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||
Ok(Iter {
|
||||
reader: slf.into(),
|
||||
keys,
|
||||
|
@ -31,7 +34,7 @@ impl Reader {
|
|||
})
|
||||
}
|
||||
fn get_iter_and_reset(
|
||||
mut slf: PyRefMut<Self>,
|
||||
slf: &mut PyClassShell<Self>,
|
||||
keys: Py<PyBytes>,
|
||||
py: Python,
|
||||
) -> PyResult<Iter> {
|
||||
|
@ -54,13 +57,15 @@ struct Iter {
|
|||
|
||||
#[pyproto]
|
||||
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() };
|
||||
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() };
|
||||
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) => {
|
||||
let res = slf
|
||||
.reader
|
||||
|
@ -84,7 +89,7 @@ fn reader() -> Reader {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_iter() {
|
||||
fn test_nested_iter1() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let reader: PyObject = reader().into_py(py);
|
||||
|
@ -108,7 +113,7 @@ fn test_clone_ref() {
|
|||
fn test_nested_iter_reset() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let reader = PyRef::new(py, reader()).unwrap();
|
||||
let reader = PyClassShell::new_ref(py, reader()).unwrap();
|
||||
py_assert!(
|
||||
py,
|
||||
reader,
|
||||
|
|
|
@ -14,20 +14,19 @@ struct ByteSequence {
|
|||
#[pymethods]
|
||||
impl ByteSequence {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject, elements: Option<&PyList>) -> PyResult<()> {
|
||||
fn new(elements: Option<&PyList>) -> PyResult<Self> {
|
||||
if let Some(pylist) = elements {
|
||||
let mut elems = Vec::with_capacity(pylist.len());
|
||||
for pyelem in pylist.into_iter() {
|
||||
let elem = u8::extract(pyelem)?;
|
||||
elems.push(elem);
|
||||
}
|
||||
obj.init(Self { elements: elems });
|
||||
Ok(Self { elements: elems })
|
||||
} else {
|
||||
obj.init(Self {
|
||||
Ok(Self {
|
||||
elements: Vec::new(),
|
||||
});
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::{types::PyType, wrap_pyfunction, wrap_pymodule};
|
||||
use pyo3::{types::PyType, wrap_pyfunction, wrap_pymodule, PyClassShell};
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -44,9 +44,9 @@ fn class_with_docs_and_signature() {
|
|||
impl MyClass {
|
||||
#[new]
|
||||
#[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);
|
||||
obj.init(Self {});
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,9 +76,9 @@ fn class_with_signature() {
|
|||
impl MyClass {
|
||||
#[new]
|
||||
#[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);
|
||||
obj.init(Self {});
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ fn test_methods() {
|
|||
let _ = a;
|
||||
}
|
||||
#[text_signature = "($self, b)"]
|
||||
fn pyself_method(_this: PyRef<Self>, b: i32) {
|
||||
fn pyself_method(_this: &PyClassShell<Self>, b: i32) {
|
||||
let _ = b;
|
||||
}
|
||||
#[classmethod]
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::type_object::initialize_type;
|
||||
use pyo3::pyclass::initialize_type;
|
||||
use pyo3::types::IntoPyDict;
|
||||
use pyo3::types::{PyDict, PyTuple};
|
||||
use pyo3::{py_run, wrap_pyfunction};
|
||||
use std::isize;
|
||||
use pyo3::{py_run, wrap_pyfunction, AsPyRef, PyClassShell};
|
||||
|
||||
mod common;
|
||||
|
||||
|
@ -83,8 +82,8 @@ fn intopytuple_pyclass() {
|
|||
let py = gil.python();
|
||||
|
||||
let tup = (
|
||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
||||
PyClassShell::new_ref(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__ == type(tup[1]).__name__");
|
||||
|
@ -108,8 +107,8 @@ fn pytuple_pyclass_iter() {
|
|||
let tup = PyTuple::new(
|
||||
py,
|
||||
[
|
||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
||||
PyRef::new(py, SimplePyClass {}).unwrap(),
|
||||
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
PyClassShell::new_ref(py, SimplePyClass {}).unwrap(),
|
||||
]
|
||||
.iter(),
|
||||
);
|
||||
|
@ -124,12 +123,12 @@ struct PickleSupport {}
|
|||
#[pymethods]
|
||||
impl PickleSupport {
|
||||
#[new]
|
||||
fn new(obj: &PyRawObject) {
|
||||
obj.init({ PickleSupport {} });
|
||||
fn new() -> PickleSupport {
|
||||
PickleSupport {}
|
||||
}
|
||||
|
||||
pub fn __reduce__<'py>(
|
||||
slf: PyRef<Self>,
|
||||
slf: &'py PyClassShell<Self>,
|
||||
py: Python<'py>,
|
||||
) -> PyResult<(PyObject, &'py PyTuple, PyObject)> {
|
||||
let cls = slf.to_object(py).getattr(py, "__class__")?;
|
||||
|
@ -155,7 +154,7 @@ fn test_pickle() {
|
|||
module.add_class::<PickleSupport>().unwrap();
|
||||
add_module(py, 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,
|
||||
inst,
|
||||
|
|
Loading…
Reference in a new issue