Skip to content

Commit a7e985d

Browse files
Fix some pyo3 testcase against the c-api
1 parent dd9bce5 commit a7e985d

5 files changed

Lines changed: 71 additions & 4 deletions

File tree

‎crates/capi/src/import.rs‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@ use rustpython_vm::import::import_code_obj;
88
pub unsafe extern "C" fn PyImport_Import(name: *mut PyObject) -> *mut PyObject {
99
with_vm(|vm| {
1010
let name = unsafe { (&*name).try_downcast_ref::<PyStr>(vm)? };
11-
vm.import(name, 0)
11+
vm.import(name, 0)?;
12+
13+
let sys_modules = vm
14+
.sys_module
15+
.get_attr(rustpython_vm::identifier!(vm, modules), vm)?;
16+
let sys_modules = sys_modules.try_downcast_ref::<PyDict>(vm)?;
17+
18+
if let Some(module) = sys_modules.get_item_opt(name, vm)? {
19+
Ok(module)
20+
} else {
21+
vm.import(name, 0)
22+
}
1223
})
1324
}
1425

@@ -74,4 +85,12 @@ mod tests {
7485
let _module = py.import("types").unwrap();
7586
})
7687
}
88+
89+
#[test]
90+
fn import_sub_module() {
91+
Python::attach(|py| {
92+
let module = py.import("collections.abc").unwrap();
93+
module.getattr("Sequence").unwrap();
94+
})
95+
}
7796
}

‎crates/capi/src/methodobject.rs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub(crate) fn build_method_def(
5353

5454
let flags = PyMethodFlags::from_bits(ml.ml_flags as u32)
5555
.ok_or_else(|| vm.new_system_error("PyMethodDef contains unknown flags"))?;
56+
let has_self = has_self && !flags.contains(PyMethodFlags::STATIC);
5657

5758
let method = ml.ml_meth;
5859

@@ -359,4 +360,17 @@ mod tests {
359360
);
360361
})
361362
}
363+
364+
#[test]
365+
fn test_wrap_static_no_args_function() {
366+
#[pyfunction()]
367+
fn f() {}
368+
369+
Python::attach(|py| {
370+
let module = PyModule::new(py, "test_wrap_pyfunction_forms").unwrap();
371+
372+
let func = wrap_pyfunction!(f, &module).unwrap();
373+
func.call0().unwrap();
374+
});
375+
}
362376
}

‎crates/capi/src/object.rs‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub unsafe extern "C" fn PyObject_HasAttrWithError(
217217
with_vm(|vm| {
218218
let obj = unsafe { &*obj };
219219
let name = unsafe { &*attr_name }.try_downcast_ref::<PyStr>(vm)?;
220-
obj.has_attr(name, vm)
220+
Ok(vm.get_attribute_opt(obj.to_owned(), name)?.is_some())
221221
})
222222
}
223223

@@ -272,7 +272,7 @@ pub unsafe extern "C" fn PyObject_HasAttrStringWithError(
272272
with_vm(|vm| {
273273
let obj = unsafe { &*obj };
274274
let name = unsafe { attr_name.try_as_str(vm) }?;
275-
obj.has_attr(name, vm)
275+
Ok(vm.get_attribute_opt(obj.to_owned(), name)?.is_some())
276276
})
277277
}
278278

@@ -591,4 +591,15 @@ mod tests {
591591
assert!(dict.get_item("foo").is_ok());
592592
})
593593
}
594+
595+
#[test]
596+
fn test_hasattr() {
597+
Python::attach(|py| {
598+
let x = 5i32.into_pyobject(py).unwrap();
599+
assert!(x.is_instance_of::<PyInt>());
600+
601+
assert!(x.hasattr("to_bytes").unwrap());
602+
assert!(!x.hasattr("bbbbbbytes").unwrap());
603+
})
604+
}
594605
}

‎crates/capi/src/pycapsule.rs‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ pub unsafe extern "C" fn PyCapsule_GetContext(capsule: *mut PyObject) -> *mut c_
4848
let capsule = unsafe { &*capsule }
4949
.downcast_ref_if_exact::<PyCapsule>(vm)
5050
.ok_or_else(|| vm.new_value_error("Invalid capsule"))?;
51+
52+
if capsule.pointer().is_null() {
53+
return Err(vm.new_value_error("Capsule has null pointer"));
54+
}
55+
5156
Ok(capsule.context())
5257
})
5358
}
@@ -143,6 +148,7 @@ fn checked_capsule<'a>(
143148

144149
#[cfg(test)]
145150
mod tests {
151+
use pyo3::ffi;
146152
use pyo3::prelude::*;
147153
use pyo3::types::PyCapsule;
148154

@@ -156,4 +162,21 @@ mod tests {
156162
assert_eq!(unsafe { ptr.cast::<String>().as_ref() }, "Some data");
157163
})
158164
}
165+
166+
#[test]
167+
fn capsule_context_on_invalid_capsule() {
168+
Python::attach(|py| {
169+
let cap = PyCapsule::new_with_value(py, 123u32, c"name").unwrap();
170+
171+
// Invalidate the capsule
172+
// SAFETY: intentionally breaking the capsule for testing
173+
unsafe {
174+
ffi::PyCapsule_SetPointer(cap.as_ptr(), core::ptr::null_mut());
175+
}
176+
177+
// context() on invalid capsule should fail
178+
let result = cap.context();
179+
assert!(result.is_err());
180+
});
181+
}
159182
}

‎crates/vm/src/builtins/capsule.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl Representable for PyCapsule {
7676

7777
impl Destructor for PyCapsule {
7878
fn del(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
79-
if let Some(destructor) = zelf.destructor() {
79+
if !zelf.pointer().is_null() && let Some(destructor) = zelf.destructor() {
8080
unsafe { destructor(zelf.as_object().as_raw().cast_mut()) };
8181
}
8282
Ok(())

0 commit comments

Comments
 (0)