-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Update PyO3 to 0.29 & enable c-api tests
#8000
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -170,6 +170,7 @@ nvars | |
| opname | ||
| opnames | ||
| orelse | ||
| osmodule | ||
| outparam | ||
| outparm | ||
| paramfunc | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| implementation=CPython | ||
| version=3.14 | ||
| implementation=RustPython | ||
| version=3.15 | ||
| shared=true | ||
| abi3=true | ||
| target_abi=RustPython-abi3t-3.15 | ||
| suppress_build_script_link_lines=true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| use crate::PyObject; | ||
|
|
||
| #[repr(C)] | ||
| pub struct PyCriticalSection; | ||
|
|
||
| #[repr(C)] | ||
| pub struct PyCriticalSection2; | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn PyCriticalSection_Begin(c: *mut PyCriticalSection, op: *mut PyObject) { | ||
| let _ = (c, op); | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn PyCriticalSection_End(c: *mut PyCriticalSection) { | ||
| let _ = c; | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn PyCriticalSection2_Begin( | ||
| c: *mut PyCriticalSection2, | ||
| a: *mut PyObject, | ||
| b: *mut PyObject, | ||
| ) { | ||
| let _ = (c, a, b); | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn PyCriticalSection2_End(c: *mut PyCriticalSection2) { | ||
| let _ = c; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,6 +57,43 @@ pub unsafe extern "C" fn PyDict_GetItemRef( | |
| }) | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn PyDict_SetDefaultRef( | ||
| dict: *mut PyObject, | ||
| key: *mut PyObject, | ||
| default_value: *mut PyObject, | ||
| result: *mut *mut PyObject, | ||
| ) -> c_int { | ||
| with_vm(|vm| { | ||
| let result = NonNull::new(result); | ||
| if let Some(result) = result { | ||
| unsafe { | ||
| result.write(core::ptr::null_mut()); | ||
| } | ||
| } | ||
| let dict = unsafe { &*dict }.try_downcast_ref::<PyDict>(vm)?; | ||
| let key = unsafe { &*key }; | ||
|
|
||
| if let Some(value) = dict.inner_getitem_opt(key, vm)? { | ||
| if let Some(result) = result { | ||
| unsafe { | ||
| result.write(value.into_raw().as_ptr()); | ||
| } | ||
| } | ||
| Ok(true) | ||
| } else { | ||
| let value = unsafe { &*default_value }.to_owned(); | ||
| dict.inner_setitem(key, value.clone(), vm)?; | ||
|
Comment on lines
+77
to
+86
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd crates/capi/src && wc -l dictobject.rsRepository: RustPython/RustPython Length of output: 83 🏁 Script executed: cd crates/capi/src && sed -n '60,100p' dictobject.rsRepository: RustPython/RustPython Length of output: 1332 🏁 Script executed: # Search for setdefault or entry patterns in dict implementation
fd -e rs | xargs rg -l "setdefault|entry" | head -5Repository: RustPython/RustPython Length of output: 182 🏁 Script executed: # Look for the dict module and check for setdefault implementations
fd -e rs | xargs rg -A 5 "fn setdefault" | head -50Repository: RustPython/RustPython Length of output: 1597 🏁 Script executed: # Get full context of setdefault_entry
fd -e rs dict_inner.rs | xargs sed -n '1,500p' | grep -A 30 "pub(crate) fn setdefault_entry"Repository: RustPython/RustPython Length of output: 47 🏁 Script executed: # Search in dict_inner.rs for the complete setdefault_entry and setdefault implementations
rg -A 20 "pub\(crate\) fn setdefault" crates/vm/src/dict_inner.rsRepository: RustPython/RustPython Length of output: 1599 🏁 Script executed: # Check the PyDict struct and see what methods are available
rg -B 5 -A 15 "impl PyDict" crates/pyobject/src/py_dict.rs | head -100Repository: RustPython/RustPython Length of output: 136 🏁 Script executed: # Look for inner_getitem_opt and inner_setitem in PyDict to understand the current approach
rg "inner_getitem_opt|inner_setitem" crates/pyobject/src/py_dict.rs | head -20Repository: RustPython/RustPython Length of output: 136 🏁 Script executed: # Find where PyDict is defined
fd -e rs | xargs rg "struct PyDict" | head -10Repository: RustPython/RustPython Length of output: 116 🏁 Script executed: # Look at the full setdefault_entry implementation to see what it returns
rg -A 30 "pub\(crate\) fn setdefault_entry" crates/vm/src/dict_inner.rsRepository: RustPython/RustPython Length of output: 1245 🏁 Script executed: # Check what dict module/PyDict implementations look like
fd -e rs | xargs rg "impl.*PyDict" | head -20Repository: RustPython/RustPython Length of output: 1244 🏁 Script executed: # Find where inner_getitem_opt and inner_setitem are defined for PyDict
rg "fn inner_getitem_opt|fn inner_setitem" crates --type rs | head -20Repository: RustPython/RustPython Length of output: 92 🏁 Script executed: # Search in builtins/dict.rs for inner_getitem_opt and inner_setitem
rg "fn inner_getitem_opt|fn inner_setitem" crates/vm/src/builtins/dict.rsRepository: RustPython/RustPython Length of output: 163 🏁 Script executed: # Get the full view of how PyDict methods work
sed -n '1,100p' crates/vm/src/builtins/dict.rsRepository: RustPython/RustPython Length of output: 3266 🏁 Script executed: # Check what the setdefault implementation in PyDict looks like
rg -B 5 -A 20 "fn setdefault" crates/vm/src/builtins/dict.rsRepository: RustPython/RustPython Length of output: 609 🏁 Script executed: # Look for how inner_getitem_opt delegates and what it calls
rg -A 10 "inner_getitem_opt" crates/vm/src/builtins/dict.rs | head -50Repository: RustPython/RustPython Length of output: 296 🏁 Script executed: # See what inner_setitem actually does
rg -A 15 "pub fn inner_setitem" crates/vm/src/builtins/dict.rsRepository: RustPython/RustPython Length of output: 458 🏁 Script executed: # Verify that inner_getitem_opt and inner_setitem each trigger separate dict operations
rg -B 2 -A 8 "pub fn inner_getitem_opt" crates/vm/src/builtins/dict.rsRepository: RustPython/RustPython Length of output: 268 🏁 Script executed: # Check the full setdefault_entry to see if we can adapt it for the C API use case
rg -A 40 "pub\(crate\) fn setdefault_entry" crates/vm/src/dict_inner.rs | head -60Repository: RustPython/RustPython Length of output: 1439 Use dict_inner::Dict::setdefault_entry to avoid double-hashing the key. The current implementation calls 🤖 Prompt for AI Agents |
||
| if let Some(result) = result { | ||
| unsafe { | ||
| result.write(value.into_raw().as_ptr()); | ||
| } | ||
| } | ||
| Ok(false) | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn PyDict_Size(dict: *mut PyObject) -> isize { | ||
| with_vm(|vm| { | ||
|
|
@@ -187,21 +224,21 @@ pub unsafe extern "C" fn PyDict_Next( | |
| }) | ||
| } | ||
|
|
||
| #[cfg(false)] | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use pyo3::prelude::*; | ||
| use pyo3::types::{IntoPyDict, PyDict, PyDictMethods, PyInt, PyList}; | ||
|
|
||
| #[test] | ||
| fn test_create_empty_dict() { | ||
| fn create_empty_dict() { | ||
| Python::attach(|py| { | ||
| let dict = PyDict::new(py); | ||
| assert!(dict.is_instance_of::<PyDict>()); | ||
| }) | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_create_dict_with_items() { | ||
| fn create_dict_with_items() { | ||
| Python::attach(|py| { | ||
| let dict = [(1, 2), (3, 4)].into_py_dict(py)?; | ||
| let value = dict.get_item(1)?.unwrap().cast_into::<PyInt>()?; | ||
|
|
@@ -214,7 +251,7 @@ mod tests { | |
| } | ||
|
|
||
| #[test] | ||
| fn test_dict_iter() { | ||
| fn dict_iter() { | ||
| Python::attach(|py| { | ||
| let dict = [(1, 2), (3, 4)].into_py_dict(py).unwrap(); | ||
| let values = dict | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| use crate::{PyObject, pystate::with_vm}; | ||
| use rustpython_vm::PyPayload; | ||
| use rustpython_vm::builtins::PyGenericAlias; | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn Py_GenericAlias( | ||
| origin: *mut PyObject, | ||
| args: *mut PyObject, | ||
| ) -> *mut PyObject { | ||
| with_vm(|vm| { | ||
| let origin = unsafe { &*origin }.to_owned(); | ||
| let args = unsafe { &*args }.to_owned(); | ||
| PyGenericAlias::from_args(origin, args, vm).into_pyobject(vm) | ||
| }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
abi3tis only supported from 3.15 onwards. This does not require actual 3.15 runtime support.