Skip to content

Commit

Permalink
Merge pull request #1132 from alex/abi3-class-creation
Browse files Browse the repository at this point in the history
Use PyType_Spec for creating new types in Rust
  • Loading branch information
kngwyu committed Sep 5, 2020
2 parents 4a05f27 + 4004620 commit 62a175e
Show file tree
Hide file tree
Showing 18 changed files with 501 additions and 134 deletions.
4 changes: 3 additions & 1 deletion examples/rustapi_module/tests/test_datetime.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime as pdt
import platform
import struct
import re
import sys

import pytest
Expand Down Expand Up @@ -327,4 +328,5 @@ def test_tz_class_introspection():
tzi = rdt.TzClass()

assert tzi.__class__ == rdt.TzClass
assert repr(tzi).startswith("<TzClass object at")
# PyPy generate <importlib.bootstrap.TzClass ...> for some reason.
assert re.match(r"^<[\w\.]*TzClass object at", repr(tzi))
4 changes: 2 additions & 2 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ or by `self_.into_super()` as `PyRef<Self::BaseClass>`.
```rust
# use pyo3::prelude::*;

#[pyclass]
#[pyclass(subclass)]
struct BaseClass {
val1: usize,
}
Expand All @@ -222,7 +222,7 @@ impl BaseClass {
}
}

#[pyclass(extends=BaseClass)]
#[pyclass(extends=BaseClass, subclass)]
struct SubClass {
val2: usize,
}
Expand Down
42 changes: 34 additions & 8 deletions src/class/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)

use crate::callback::{HashCallbackOutput, IntoPyCallbackOutput};
use crate::pyclass::maybe_push_slot;
use crate::{exceptions, ffi, FromPyObject, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult};
use std::os::raw::c_int;
use std::os::raw::{c_int, c_void};

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

#[doc(hidden)]
impl PyObjectMethods {
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
type_object.tp_str = self.tp_str;
type_object.tp_repr = self.tp_repr;
type_object.tp_hash = self.tp_hash;
type_object.tp_getattro = self.tp_getattro;
type_object.tp_richcompare = self.tp_richcompare;
type_object.tp_setattro = self.tp_setattro;
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
maybe_push_slot(slots, ffi::Py_tp_str, self.tp_str.map(|v| v as *mut c_void));
maybe_push_slot(
slots,
ffi::Py_tp_repr,
self.tp_repr.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_hash,
self.tp_hash.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_getattro,
self.tp_getattro.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_richcompare,
self.tp_richcompare.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_setattro,
self.tp_setattro.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_nb_bool,
self.nb_bool.map(|v| v as *mut c_void),
);
}
// Set functions used by `#[pyproto]`.
pub fn set_str<T>(&mut self)
Expand Down
17 changes: 13 additions & 4 deletions src/class/descr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
//! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors)

use crate::callback::IntoPyCallbackOutput;
use crate::pyclass::maybe_push_slot;
use crate::types::PyAny;
use crate::{ffi, FromPyObject, PyClass, PyObject};
use std::os::raw::c_int;
use std::os::raw::{c_int, c_void};

/// Descriptor interface
#[allow(unused_variables)]
Expand Down Expand Up @@ -79,9 +80,17 @@ pub struct PyDescrMethods {

#[doc(hidden)]
impl PyDescrMethods {
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
type_object.tp_descr_get = self.tp_descr_get;
type_object.tp_descr_set = self.tp_descr_set;
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
maybe_push_slot(
slots,
ffi::Py_tp_descr_get,
self.tp_descr_get.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_descr_set,
self.tp_descr_set.map(|v| v as *mut c_void),
);
}
pub fn set_descr_get<T>(&mut self)
where
Expand Down
15 changes: 12 additions & 3 deletions src/class/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! Python GC support
//!

use crate::pyclass::maybe_push_slot;
use crate::{ffi, AsPyPointer, PyCell, PyClass, Python};
use std::os::raw::{c_int, c_void};

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

#[doc(hidden)]
impl PyGCMethods {
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
type_object.tp_traverse = self.tp_traverse;
type_object.tp_clear = self.tp_clear;
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
maybe_push_slot(
slots,
ffi::Py_tp_traverse,
self.tp_traverse.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_clear,
self.tp_clear.map(|v| v as *mut c_void),
);
}

pub fn set_traverse<T>(&mut self)
Expand Down
16 changes: 13 additions & 3 deletions src/class/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
use crate::callback::IntoPyCallbackOutput;
use crate::derive_utils::TryFromPyCell;
use crate::err::PyResult;
use crate::pyclass::maybe_push_slot;
use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, Python};
use std::os::raw::c_void;

/// Python Iterator Interface.
///
Expand Down Expand Up @@ -79,9 +81,17 @@ pub struct PyIterMethods {

#[doc(hidden)]
impl PyIterMethods {
pub(crate) fn update_typeobj(&self, type_object: &mut ffi::PyTypeObject) {
type_object.tp_iter = self.tp_iter;
type_object.tp_iternext = self.tp_iternext;
pub(crate) fn update_slots(&self, slots: &mut Vec<ffi::PyType_Slot>) {
maybe_push_slot(
slots,
ffi::Py_tp_iter,
self.tp_iter.map(|v| v as *mut c_void),
);
maybe_push_slot(
slots,
ffi::Py_tp_iternext,
self.tp_iternext.map(|v| v as *mut c_void),
);
}
pub fn set_iter<T>(&mut self)
where
Expand Down
5 changes: 0 additions & 5 deletions src/class/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,11 +581,6 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {

#[doc(hidden)]
impl ffi::PyNumberMethods {
pub(crate) fn from_nb_bool(nb_bool: ffi::inquiry) -> *mut Self {
let mut nm = ffi::PyNumberMethods_INIT;
nm.nb_bool = Some(nb_bool);
Box::into_raw(Box::new(nm))
}
pub fn set_add_radd<T>(&mut self)
where
T: for<'p> PyNumberAddProtocol<'p> + for<'p> PyNumberRAddProtocol<'p>,
Expand Down
6 changes: 3 additions & 3 deletions src/pycell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
/// - You want to get super class.
/// ```
/// # use pyo3::prelude::*;
/// #[pyclass]
/// #[pyclass(subclass)]
/// struct Parent {
/// basename: &'static str,
/// }
Expand Down Expand Up @@ -516,11 +516,11 @@ where
/// # Examples
/// ```
/// # use pyo3::prelude::*;
/// #[pyclass]
/// #[pyclass(subclass)]
/// struct Base1 {
/// name1: &'static str,
/// }
/// #[pyclass(extends=Base1)]
/// #[pyclass(extends=Base1, subclass)]
/// struct Base2 {
/// name2: &'static str,
/// }
Expand Down
Loading

0 comments on commit 62a175e

Please sign in to comment.