Skip to content

Commit 6b84401

Browse files
committed
Make it enable to safely inherit native types
1 parent 8175d6f commit 6b84401

36 files changed

+264
-104
lines changed

pyo3-derive-backend/src/pyclass.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub struct PyClassArgs {
1616
pub name: Option<syn::Expr>,
1717
pub flags: Vec<syn::Expr>,
1818
pub base: syn::TypePath,
19+
pub has_extends: bool,
1920
pub module: Option<syn::LitStr>,
2021
}
2122

@@ -39,8 +40,9 @@ impl Default for PyClassArgs {
3940
module: None,
4041
// We need the 0 as value for the constant we're later building using quote for when there
4142
// are no other flags
42-
flags: vec![parse_quote! {0}],
43-
base: parse_quote! {pyo3::types::PyAny},
43+
flags: vec![parse_quote! { 0 }],
44+
base: parse_quote! { pyo3::types::PyAny },
45+
has_extends: false,
4446
}
4547
}
4648
}
@@ -89,6 +91,7 @@ impl PyClassArgs {
8991
path: exp.path.clone(),
9092
qself: None,
9193
};
94+
self.has_extends = true;
9295
}
9396
_ => {
9497
return Err(syn::Error::new_spanned(
@@ -318,7 +321,7 @@ fn impl_class(
318321
}
319322
}
320323
}
321-
// TODO: implement dict and weakref
324+
322325
let weakref = if has_weakref {
323326
quote! { type WeakRef = pyo3::pyclass_slots::PyClassWeakRefSlot; }
324327
} else {
@@ -355,6 +358,11 @@ fn impl_class(
355358

356359
let base = &attr.base;
357360
let flags = &attr.flags;
361+
let extended = if attr.has_extends {
362+
quote! { pyo3::type_flags::EXTENDED }
363+
} else {
364+
quote! { 0 }
365+
};
358366

359367
Ok(quote! {
360368
impl pyo3::type_object::PyTypeInfo for #cls {
@@ -365,7 +373,7 @@ fn impl_class(
365373
const NAME: &'static str = #cls_name;
366374
const MODULE: Option<&'static str> = #module;
367375
const DESCRIPTION: &'static str = #doc;
368-
const FLAGS: usize = #(#flags)|*;
376+
const FLAGS: usize = #(#flags)|* | #extended;
369377

370378
#[inline]
371379
unsafe fn type_object() -> &'static mut pyo3::ffi::PyTypeObject {

src/conversion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! Conversions between various states of rust and python types and their wrappers.
44
use crate::err::{self, PyDowncastError, PyResult};
55
use crate::object::PyObject;
6-
use crate::type_object::{PyConcreteObject, PyTypeInfo};
6+
use crate::type_object::{PyObjectLayout, PyTypeInfo};
77
use crate::types::PyAny;
88
use crate::types::PyTuple;
99
use crate::{ffi, gil, Py, Python};

src/ffi/code.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ pub struct PyCodeObject {
3131
pub co_extra: *mut c_void,
3232
}
3333

34-
impl Default for PyCodeObject {
35-
#[inline]
36-
fn default() -> Self {
37-
unsafe { ::std::mem::zeroed() }
38-
}
39-
}
40-
4134
/* Masks for co_flags */
4235
pub const CO_OPTIMIZED: c_int = 0x0001;
4336
pub const CO_NEWLOCALS: c_int = 0x0002;

src/ffi/complexobject.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,17 @@ extern "C" {
2727
pub fn PyComplex_ImagAsDouble(op: *mut PyObject) -> c_double;
2828
}
2929

30-
#[cfg(not(Py_LIMITED_API))]
3130
#[repr(C)]
3231
#[derive(Copy, Clone)]
3332
pub struct Py_complex {
3433
pub real: c_double,
3534
pub imag: c_double,
3635
}
3736

38-
#[cfg(not(Py_LIMITED_API))]
3937
#[repr(C)]
4038
#[derive(Copy, Clone)]
4139
pub struct PyComplexObject {
42-
_ob_base: PyObject,
40+
pub ob_base: PyObject,
4341
pub cval: Py_complex,
4442
}
4543

src/ffi/datetime.rs

100644100755
File mode changed.

src/ffi/dictobject.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ extern "C" {
1313
pub static mut PyDictValues_Type: PyTypeObject;
1414
}
1515

16+
#[repr(C)]
17+
pub struct PyDictKeysObject {
18+
_unused: [u8; 0],
19+
}
20+
21+
#[repr(C)]
22+
#[derive(Debug)]
23+
pub struct PyDictObject {
24+
pub ob_base: PyObject,
25+
pub ma_used: Py_ssize_t,
26+
#[cfg(Py_3_6)]
27+
pub ma_version_tag: u64,
28+
pub ma_keys: *mut PyDictKeysObject,
29+
pub ma_values: *mut *mut PyObject,
30+
}
31+
1632
#[inline]
1733
pub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int {
1834
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS)

src/ffi/floatobject.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::ffi::object::*;
22
use std::os::raw::{c_double, c_int};
33

4-
#[cfg(not(Py_LIMITED_API))]
54
#[repr(C)]
65
pub struct PyFloatObject {
76
pub ob_base: PyObject,

src/ffi/listobject.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@ use std::os::raw::c_int;
55
#[repr(C)]
66
#[derive(Copy, Clone)]
77
pub struct PyListObject {
8-
#[cfg(py_sys_config = "Py_TRACE_REFS")]
9-
pub _ob_next: *mut PyObject,
10-
#[cfg(py_sys_config = "Py_TRACE_REFS")]
11-
pub _ob_prev: *mut PyObject,
12-
pub ob_refcnt: Py_ssize_t,
13-
pub ob_type: *mut PyTypeObject,
14-
pub ob_size: Py_ssize_t,
8+
pub ob_base: PyVarObject,
159
pub ob_item: *mut *mut PyObject,
1610
pub allocated: Py_ssize_t,
1711
}

src/ffi/longobject.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ use std::os::raw::{
66
};
77

88
/// This is an opaque type in the python c api
9-
#[repr(transparent)]
10-
pub struct PyLongObject(*mut c_void);
9+
#[repr(C)]
10+
pub struct PyLongObject {
11+
_unused: [u8; 0],
12+
}
1113

1214
#[cfg_attr(windows, link(name = "pythonXY"))]
1315
extern "C" {

src/ffi/setobject.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::ffi::object::*;
2-
use crate::ffi::pyport::Py_ssize_t;
2+
use crate::ffi::pyport::{Py_hash_t, Py_ssize_t};
33
use std::os::raw::c_int;
44

55
#[cfg_attr(windows, link(name = "pythonXY"))]
@@ -11,6 +11,28 @@ extern "C" {
1111
pub static mut PySetIter_Type: PyTypeObject;
1212
}
1313

14+
pub const PySet_MINSIZE: usize = 8;
15+
16+
#[repr(C)]
17+
#[derive(Debug)]
18+
pub struct setentry {
19+
pub key: *mut PyObject,
20+
pub hash: Py_hash_t,
21+
}
22+
23+
#[repr(C)]
24+
pub struct PySetObject {
25+
pub ob_base: PyObject,
26+
pub fill: Py_ssize_t,
27+
pub used: Py_ssize_t,
28+
pub mask: Py_ssize_t,
29+
pub table: *mut setentry,
30+
pub hash: Py_hash_t,
31+
pub finger: Py_ssize_t,
32+
pub smalltable: [setentry; PySet_MINSIZE],
33+
pub weakreflist: *mut PyObject,
34+
}
35+
1436
#[inline]
1537
#[cfg_attr(PyPy, link_name = "PyPyFrozenSet_CheckExact")]
1638
pub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int {

0 commit comments

Comments
 (0)