Fill tp_dict on types in an abi3-friendly way

I think this might technically be backwards incompatible if you had a custom metaclass with fancy behavior, but pyo3 doesn't seem to have any native support for those.
This commit is contained in:
Alex Gaynor 2020-09-08 08:18:52 -04:00
parent e8936be3ce
commit 0709a02310

View file

@ -202,10 +202,7 @@ impl LazyStaticType {
// Now we hold the GIL and we can assume it won't be released until we // Now we hold the GIL and we can assume it won't be released until we
// return from the function. // return from the function.
let result = self.tp_dict_filled.get_or_init(py, move || { let result = self.tp_dict_filled.get_or_init(py, move || {
let tp_dict = unsafe { (*type_object).tp_dict }; let result = initialize_tp_dict(py, type_object as *mut ffi::PyObject, items);
let result = initialize_tp_dict(py, tp_dict, items);
// See discussion on #982 for why we need this.
unsafe { ffi::PyType_Modified(type_object) };
// Initialization successfully complete, can clear the thread list. // Initialization successfully complete, can clear the thread list.
// (No further calls to get_or_init() will try to init, on any thread.) // (No further calls to get_or_init() will try to init, on any thread.)
@ -224,7 +221,7 @@ impl LazyStaticType {
fn initialize_tp_dict( fn initialize_tp_dict(
py: Python, py: Python,
tp_dict: *mut ffi::PyObject, type_object: *mut ffi::PyObject,
items: Vec<(&'static str, PyObject)>, items: Vec<(&'static str, PyObject)>,
) -> PyResult<()> { ) -> PyResult<()> {
use std::ffi::CString; use std::ffi::CString;
@ -233,7 +230,7 @@ fn initialize_tp_dict(
// the POV of other threads. // the POV of other threads.
for (key, val) in items { for (key, val) in items {
let ret = unsafe { let ret = unsafe {
ffi::PyDict_SetItemString(tp_dict, CString::new(key)?.as_ptr(), val.into_ptr()) ffi::PyObject_SetAttrString(type_object, CString::new(key)?.as_ptr(), val.into_ptr())
}; };
if ret < 0 { if ret < 0 {
return Err(PyErr::fetch(py)); return Err(PyErr::fetch(py));