Skip to content

Commit 8592e01

Browse files
committed
Proof of concept of using PEP384s PyType_Spec
1 parent 4a05f27 commit 8592e01

17 files changed

+486
-333
lines changed

guide/src/class.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ or by `self_.into_super()` as `PyRef<Self::BaseClass>`.
205205
```rust
206206
# use pyo3::prelude::*;
207207

208-
#[pyclass]
208+
#[pyclass(subclass)]
209209
struct BaseClass {
210210
val1: usize,
211211
}
@@ -222,7 +222,7 @@ impl BaseClass {
222222
}
223223
}
224224

225-
#[pyclass(extends=BaseClass)]
225+
#[pyclass(extends=BaseClass, subclass)]
226226
struct SubClass {
227227
val2: usize,
228228
}

src/class/basic.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)
1010
1111
use crate::callback::{HashCallbackOutput, IntoPyCallbackOutput};
12+
use crate::pyclass::maybe_push_slot;
1213
use crate::{exceptions, ffi, FromPyObject, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult};
13-
use std::os::raw::c_int;
14+
use std::os::raw::{c_int, c_void};
1415

1516
/// Operators for the __richcmp__ method
1617
#[derive(Debug)]
@@ -147,13 +148,38 @@ pub struct PyObjectMethods {
147148

148149
#[doc(hidden)]
149150
impl PyObjectMethods {
150-
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
151-
type_object.tp_str = self.tp_str;
152-
type_object.tp_repr = self.tp_repr;
153-
type_object.tp_hash = self.tp_hash;
154-
type_object.tp_getattro = self.tp_getattro;
155-
type_object.tp_richcompare = self.tp_richcompare;
156-
type_object.tp_setattro = self.tp_setattro;
151+
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
152+
maybe_push_slot(slots, ffi::Py_tp_str, self.tp_str.map(|v| v as *mut c_void));
153+
maybe_push_slot(
154+
slots,
155+
ffi::Py_tp_repr,
156+
self.tp_repr.map(|v| v as *mut c_void),
157+
);
158+
maybe_push_slot(
159+
slots,
160+
ffi::Py_tp_hash,
161+
self.tp_hash.map(|v| v as *mut c_void),
162+
);
163+
maybe_push_slot(
164+
slots,
165+
ffi::Py_tp_getattro,
166+
self.tp_getattro.map(|v| v as *mut c_void),
167+
);
168+
maybe_push_slot(
169+
slots,
170+
ffi::Py_tp_richcompare,
171+
self.tp_richcompare.map(|v| v as *mut c_void),
172+
);
173+
maybe_push_slot(
174+
slots,
175+
ffi::Py_tp_setattro,
176+
self.tp_setattro.map(|v| v as *mut c_void),
177+
);
178+
maybe_push_slot(
179+
slots,
180+
ffi::Py_nb_bool,
181+
self.nb_bool.map(|v| v as *mut c_void),
182+
);
157183
}
158184
// Set functions used by `#[pyproto]`.
159185
pub fn set_str<T>(&mut self)

src/class/descr.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
//! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors)
77
88
use crate::callback::IntoPyCallbackOutput;
9+
use crate::pyclass::maybe_push_slot;
910
use crate::types::PyAny;
1011
use crate::{ffi, FromPyObject, PyClass, PyObject};
11-
use std::os::raw::c_int;
12+
use std::os::raw::{c_int, c_void};
1213

1314
/// Descriptor interface
1415
#[allow(unused_variables)]
@@ -79,9 +80,17 @@ pub struct PyDescrMethods {
7980

8081
#[doc(hidden)]
8182
impl PyDescrMethods {
82-
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
83-
type_object.tp_descr_get = self.tp_descr_get;
84-
type_object.tp_descr_set = self.tp_descr_set;
83+
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
84+
maybe_push_slot(
85+
slots,
86+
ffi::Py_tp_descr_get,
87+
self.tp_descr_get.map(|v| v as *mut c_void),
88+
);
89+
maybe_push_slot(
90+
slots,
91+
ffi::Py_tp_descr_set,
92+
self.tp_descr_set.map(|v| v as *mut c_void),
93+
);
8594
}
8695
pub fn set_descr_get<T>(&mut self)
8796
where

src/class/gc.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! Python GC support
44
//!
55
6+
use crate::pyclass::maybe_push_slot;
67
use crate::{ffi, AsPyPointer, PyCell, PyClass, Python};
78
use std::os::raw::{c_int, c_void};
89

@@ -27,9 +28,17 @@ pub struct PyGCMethods {
2728

2829
#[doc(hidden)]
2930
impl PyGCMethods {
30-
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
31-
type_object.tp_traverse = self.tp_traverse;
32-
type_object.tp_clear = self.tp_clear;
31+
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
32+
maybe_push_slot(
33+
slots,
34+
ffi::Py_tp_traverse,
35+
self.tp_traverse.map(|v| v as *mut c_void),
36+
);
37+
maybe_push_slot(
38+
slots,
39+
ffi::Py_tp_clear,
40+
self.tp_clear.map(|v| v as *mut c_void),
41+
);
3342
}
3443

3544
pub fn set_traverse<T>(&mut self)

src/class/iter.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
use crate::callback::IntoPyCallbackOutput;
66
use crate::derive_utils::TryFromPyCell;
77
use crate::err::PyResult;
8+
use crate::pyclass::maybe_push_slot;
89
use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, Python};
10+
use std::os::raw::c_void;
911

1012
/// Python Iterator Interface.
1113
///
@@ -79,9 +81,17 @@ pub struct PyIterMethods {
7981

8082
#[doc(hidden)]
8183
impl PyIterMethods {
82-
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
83-
type_object.tp_iter = self.tp_iter;
84-
type_object.tp_iternext = self.tp_iternext;
84+
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
85+
maybe_push_slot(
86+
slots,
87+
ffi::Py_tp_iter,
88+
self.tp_iter.map(|v| v as *mut c_void),
89+
);
90+
maybe_push_slot(
91+
slots,
92+
ffi::Py_tp_iternext,
93+
self.tp_iternext.map(|v| v as *mut c_void),
94+
);
8595
}
8696
pub fn set_iter<T>(&mut self)
8797
where

src/class/number.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -581,11 +581,6 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {
581581

582582
#[doc(hidden)]
583583
impl ffi::PyNumberMethods {
584-
pub(crate) fn from_nb_bool(nb_bool: ffi::inquiry) -> *mut Self {
585-
let mut nm = ffi::PyNumberMethods_INIT;
586-
nm.nb_bool = Some(nb_bool);
587-
Box::into_raw(Box::new(nm))
588-
}
589584
pub fn set_add_radd<T>(&mut self)
590585
where
591586
T: for<'p> PyNumberAddProtocol<'p> + for<'p> PyNumberRAddProtocol<'p>,

src/pycell.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
455455
/// - You want to get super class.
456456
/// ```
457457
/// # use pyo3::prelude::*;
458-
/// #[pyclass]
458+
/// #[pyclass(subclass)]
459459
/// struct Parent {
460460
/// basename: &'static str,
461461
/// }
@@ -516,11 +516,11 @@ where
516516
/// # Examples
517517
/// ```
518518
/// # use pyo3::prelude::*;
519-
/// #[pyclass]
519+
/// #[pyclass(subclass)]
520520
/// struct Base1 {
521521
/// name1: &'static str,
522522
/// }
523-
/// #[pyclass(extends=Base1)]
523+
/// #[pyclass(extends=Base1, subclass)]
524524
/// struct Base2 {
525525
/// name2: &'static str,
526526
/// }

0 commit comments

Comments
 (0)