Skip to content

Commit dbfcbc8

Browse files
Add more error functions to c-api
Add windows error functions Implement unicode error functions Add errno functions to c-api Spell Review Refactor windows errors Review
1 parent 1205fd2 commit dbfcbc8

5 files changed

Lines changed: 770 additions & 40 deletions

File tree

crates/capi/src/pyerrors.rs

Lines changed: 244 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@ use crate::object::define_py_check;
22
use crate::util::CStrExt;
33
use crate::{PyObject, pystate::with_vm};
44
use core::convert::Infallible;
5-
use core::ffi::{c_char, c_int};
5+
use core::ffi::{CStr, c_char, c_int};
66
use core::ptr::NonNull;
7-
use core::slice;
7+
pub use errno::*;
88
use rustpython_vm::builtins::{PyBaseException, PyTuple, PyType};
99
use rustpython_vm::convert::IntoObject;
1010
use rustpython_vm::exceptions::ExceptionZoo;
11+
use rustpython_vm::signal::set_interrupt_ex;
1112
use rustpython_vm::{AsObject, PyObjectRef, PyResult};
13+
use std::process::abort;
14+
pub use unicode::*;
15+
#[cfg(windows)]
16+
pub use windows::*;
17+
18+
mod errno;
19+
mod unicode;
20+
#[cfg(windows)]
21+
mod windows;
1222

1323
macro_rules! define_exception_statics {
1424
($( $(#[$meta:meta])* $export:ident => $exc:ident ),* $(,)?) => {
@@ -318,55 +328,249 @@ pub unsafe extern "C" fn PyException_SetContext(exc: *mut PyObject, context: *mu
318328
}
319329

320330
#[unsafe(no_mangle)]
321-
pub unsafe extern "C" fn PyUnicodeDecodeError_Create(
322-
encoding: *const c_char,
323-
object: *const c_char,
324-
length: isize,
325-
start: isize,
326-
end: isize,
327-
reason: *const c_char,
328-
) -> *mut PyObject {
331+
pub unsafe extern "C" fn PyException_SetTraceback(exc: *mut PyObject, tb: *mut PyObject) -> c_int {
329332
with_vm(|vm| {
330-
let encoding = unsafe { encoding.try_as_str(vm) }?;
331-
let reason = unsafe { reason.try_as_str(vm) }?;
332-
let length: usize = length
333-
.try_into()
334-
.map_err(|_| vm.new_system_error("length must be non-negative"))?;
335-
let start: usize = start
336-
.try_into()
337-
.map_err(|_| vm.new_system_error("start must be non-negative"))?;
338-
let end: usize = end
339-
.try_into()
340-
.map_err(|_| vm.new_system_error("end must be non-negative"))?;
341-
342-
let bytes = if object.is_null() {
343-
if length != 0 {
344-
return Err(vm.new_system_error(
345-
"PyUnicodeDecodeError_Create called with null object and non-zero length",
346-
));
347-
}
348-
Vec::new()
333+
let exc = unsafe { &*exc }.try_downcast_ref::<PyBaseException>(vm)?;
334+
let traceback = unsafe { tb.as_ref() }.map(|obj| obj.to_owned());
335+
exc.set___traceback__(vm.unwrap_or_none(traceback), vm)
336+
})
337+
}
338+
339+
#[unsafe(no_mangle)]
340+
pub extern "C" fn PyErr_Clear() {
341+
with_vm(|vm| vm.set_exception(None))
342+
}
343+
344+
#[unsafe(no_mangle)]
345+
pub unsafe extern "C" fn PyErr_ExceptionMatches(exc: *mut PyObject) -> c_int {
346+
with_vm(|vm| {
347+
if let Some(current) = vm.current_exception() {
348+
current
349+
.class()
350+
.as_object()
351+
.is_subclass(unsafe { &*exc }, vm)
349352
} else {
350-
unsafe { slice::from_raw_parts(object.cast::<u8>(), length) }.to_vec()
353+
Ok(false)
354+
}
355+
})
356+
}
357+
358+
#[unsafe(no_mangle)]
359+
pub extern "C" fn PyErr_BadArgument() -> c_int {
360+
with_vm::<PyResult<Infallible>, ()>(|vm| {
361+
Err(vm.new_type_error("bad argument type for built-in operation"))
362+
});
363+
0
364+
}
365+
366+
#[unsafe(no_mangle)]
367+
pub extern "C" fn PyErr_BadInternalCall() {
368+
with_vm::<PyResult<Infallible>, _>(|vm| {
369+
Err(vm.new_system_error("bad argument to internal function"))
370+
})
371+
}
372+
373+
#[unsafe(no_mangle)]
374+
pub extern "C" fn PyErr_CheckSignals() -> c_int {
375+
with_vm(|vm| vm.check_signals())
376+
}
377+
378+
#[unsafe(no_mangle)]
379+
pub extern "C" fn PyErr_SetInterrupt() {
380+
PyErr_SetInterruptEx(libc::SIGINT);
381+
}
382+
383+
#[unsafe(no_mangle)]
384+
pub extern "C" fn PyErr_SetInterruptEx(signum: c_int) -> c_int {
385+
let Ok(signum) = signum.try_into() else {
386+
return -1;
387+
};
388+
set_interrupt_ex(signum).map_or(-1, |_| 0)
389+
}
390+
391+
#[unsafe(no_mangle)]
392+
pub unsafe extern "C" fn Py_FatalError(message: *const c_char) -> ! {
393+
let message = if message.is_null() {
394+
c"(null)"
395+
} else {
396+
unsafe { CStr::from_ptr(message) }
397+
};
398+
eprintln!("Fatal Python error: {message:?}");
399+
abort()
400+
}
401+
402+
#[unsafe(no_mangle)]
403+
pub unsafe extern "C" fn PyErr_SetNone(exception: *mut PyObject) {
404+
with_vm::<PyResult<Infallible>, _>(|vm| {
405+
let exc_type = unsafe { (&*exception).to_owned() };
406+
let normalized = vm.normalize_exception(exc_type, vm.ctx.none(), vm.ctx.none())?;
407+
Err(normalized)
408+
})
409+
}
410+
411+
#[unsafe(no_mangle)]
412+
pub extern "C" fn PyErr_NoMemory() -> *mut PyObject {
413+
with_vm::<PyResult<*mut PyObject>, _>(|vm| Err(vm.new_memory_error("")))
414+
}
415+
416+
#[unsafe(no_mangle)]
417+
pub unsafe extern "C" fn PyErr_Fetch(
418+
ptype: *mut *mut PyObject,
419+
pvalue: *mut *mut PyObject,
420+
ptraceback: *mut *mut PyObject,
421+
) {
422+
with_vm(|vm| {
423+
let (ty, value, tb) = vm.take_raised_exception().map_or_else(
424+
|| {
425+
(
426+
core::ptr::null_mut(),
427+
core::ptr::null_mut(),
428+
core::ptr::null_mut(),
429+
)
430+
},
431+
|exc| {
432+
let (ty, value, tb) = vm.split_exception(exc);
433+
let tb = if vm.is_none(&tb) {
434+
core::ptr::null_mut()
435+
} else {
436+
tb.into_raw().as_ptr()
437+
};
438+
(ty.into_raw().as_ptr(), value.into_raw().as_ptr(), tb)
439+
},
440+
);
441+
442+
if let Some(ptype) = NonNull::new(ptype) {
443+
unsafe { ptype.write(ty) };
444+
}
445+
if let Some(pvalue) = NonNull::new(pvalue) {
446+
unsafe { pvalue.write(value) };
447+
}
448+
if let Some(ptraceback) = NonNull::new(ptraceback) {
449+
unsafe { ptraceback.write(tb) };
450+
}
451+
})
452+
}
453+
454+
#[unsafe(no_mangle)]
455+
pub unsafe extern "C" fn PyErr_Restore(
456+
exc_type: *mut PyObject,
457+
exc_val: *mut PyObject,
458+
exc_tb: *mut PyObject,
459+
) {
460+
with_vm(|vm| {
461+
let exc_type = NonNull::new(exc_type).map(|ptr| unsafe { PyObjectRef::from_raw(ptr) });
462+
let exc_val = NonNull::new(exc_val).map(|ptr| unsafe { PyObjectRef::from_raw(ptr) });
463+
let exc_tb = NonNull::new(exc_tb).map(|ptr| unsafe { PyObjectRef::from_raw(ptr) });
464+
465+
if let Some(exc_type) = exc_type {
466+
let normalized = vm.normalize_exception(
467+
exc_type,
468+
vm.unwrap_or_none(exc_val),
469+
vm.unwrap_or_none(exc_tb),
470+
)?;
471+
vm.set_exception(Some(normalized));
472+
} else {
473+
vm.set_exception(None);
351474
};
352475

353-
let exc = vm.new_unicode_decode_error_real(
354-
vm.ctx.new_str(encoding),
355-
vm.ctx.new_bytes(bytes),
356-
start,
357-
end,
358-
vm.ctx.new_str(reason),
476+
Ok(())
477+
})
478+
}
479+
480+
#[unsafe(no_mangle)]
481+
pub extern "C" fn PyErr_GetHandledException() -> *mut PyObject {
482+
with_vm(|vm| {
483+
vm.current_exception()
484+
.map(|exc| exc.into_object().into_raw().as_ptr())
485+
.unwrap_or_default()
486+
})
487+
}
488+
489+
#[unsafe(no_mangle)]
490+
pub unsafe extern "C" fn PyErr_SetHandledException(exc: *mut PyObject) {
491+
with_vm(|vm| {
492+
if let Some(exc) = NonNull::new(exc) {
493+
let exception = unsafe { PyObjectRef::from_raw(exc).downcast_unchecked() };
494+
vm.set_exception(Some(exception));
495+
} else {
496+
vm.set_exception(None);
497+
}
498+
})
499+
}
500+
501+
#[unsafe(no_mangle)]
502+
pub unsafe extern "C" fn PyErr_GetExcInfo(
503+
ptype: *mut *mut PyObject,
504+
pvalue: *mut *mut PyObject,
505+
ptraceback: *mut *mut PyObject,
506+
) {
507+
with_vm(|vm| {
508+
let (ty, value, tb) = vm.current_exception().map_or_else(
509+
|| {
510+
(
511+
core::ptr::null_mut(),
512+
core::ptr::null_mut(),
513+
core::ptr::null_mut(),
514+
)
515+
},
516+
|exc| {
517+
let (ty, value, tb) = vm.split_exception(exc);
518+
let tb = if vm.is_none(&tb) {
519+
core::ptr::null_mut()
520+
} else {
521+
tb.into_raw().as_ptr()
522+
};
523+
(ty.into_raw().as_ptr(), value.into_raw().as_ptr(), tb)
524+
},
359525
);
360-
Ok(exc)
526+
527+
if let Some(ptype) = NonNull::new(ptype) {
528+
unsafe { ptype.write(ty) };
529+
}
530+
if let Some(pvalue) = NonNull::new(pvalue) {
531+
unsafe { pvalue.write(value) };
532+
}
533+
if let Some(ptraceback) = NonNull::new(ptraceback) {
534+
unsafe { ptraceback.write(tb) };
535+
}
361536
})
362537
}
363538

364539
#[unsafe(no_mangle)]
365-
pub unsafe extern "C" fn PyException_SetTraceback(exc: *mut PyObject, tb: *mut PyObject) -> c_int {
540+
pub unsafe extern "C" fn PyErr_SetExcInfo(
541+
exc_type: *mut PyObject,
542+
exc_val: *mut PyObject,
543+
exc_tb: *mut PyObject,
544+
) {
545+
with_vm(|vm| {
546+
let _exc_type = NonNull::new(exc_type).map(|ptr| unsafe { PyObjectRef::from_raw(ptr) });
547+
let _exc_tb = NonNull::new(exc_tb).map(|ptr| unsafe { PyObjectRef::from_raw(ptr) });
548+
let exc_val = NonNull::new(exc_val).map(|ptr| unsafe { PyObjectRef::from_raw(ptr) });
549+
let exc = exc_val
550+
.map(|obj| {
551+
obj.downcast::<PyBaseException>()
552+
.map_err(|_| vm.new_type_error("exception value must be an exception instance"))
553+
})
554+
.transpose()?;
555+
vm.set_exception(exc);
556+
Ok(())
557+
})
558+
}
559+
560+
#[unsafe(no_mangle)]
561+
pub unsafe extern "C" fn PyException_GetArgs(exc: *mut PyObject) -> *mut PyObject {
366562
with_vm(|vm| {
367563
let exc = unsafe { &*exc }.try_downcast_ref::<PyBaseException>(vm)?;
368-
let traceback = unsafe { tb.as_ref() }.map(|obj| obj.to_owned());
369-
exc.set___traceback__(vm.unwrap_or_none(traceback), vm)
564+
Ok(exc.args())
565+
})
566+
}
567+
568+
#[unsafe(no_mangle)]
569+
pub unsafe extern "C" fn PyException_SetArgs(exc: *mut PyObject, args: *mut PyObject) {
570+
with_vm(|vm| {
571+
let exc = unsafe { &*exc }.try_downcast_ref::<PyBaseException>(vm)?;
572+
let args = unsafe { &*args }.to_owned();
573+
exc.as_object().set_attr("args", args, vm)
370574
})
371575
}
372576

0 commit comments

Comments
 (0)