1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#[macro_export]
macro_rules! import_exception {
($module: ident, $name: ident) => {
#[allow(non_camel_case_types)]
pub struct $name;
impl ::std::convert::From<$name> for $crate::PyErr {
fn from(_err: $name) -> $crate::PyErr {
$crate::PyErr::new::<$name, _>(())
}
}
impl<T> ::std::convert::Into<$crate::PyResult<T>> for $name {
fn into(self) -> $crate::PyResult<T> {
$crate::PyErr::new::<$name, _>(()).into()
}
}
impl $name {
pub fn new<T: $crate::ToPyObject + 'static>(args: T) -> $crate::PyErr
where Self: $crate::typeob::PyTypeObject + Sized
{
$crate::PyErr::new::<Self, T>(args)
}
pub fn into<R, T: $crate::ToPyObject + 'static>(args: T) -> $crate::PyResult<R>
where Self: $crate::typeob::PyTypeObject + Sized
{
$crate::PyErr::new::<Self, T>(args).into()
}
}
impl $crate::typeob::PyTypeObject for $name {
#[inline(always)]
fn init_type() {}
#[inline]
fn type_object() -> $crate::Py<$crate::PyType> {
use $crate::IntoPyPointer;
static mut TYPE_OBJECT: *mut $crate::ffi::PyTypeObject = ::std::ptr::null_mut();
unsafe {
if TYPE_OBJECT.is_null() {
let gil = $crate::Python::acquire_gil();
let py = gil.python();
let imp = py.import(stringify!($module))
.expect(concat!(
"Can not import module: ", stringify!($module)));
let cls = imp.get(stringify!($name))
.expect(concat!(
"Can not load exception class: {}.{}", stringify!($module),
".", stringify!($name)));
TYPE_OBJECT = cls.into_ptr() as *mut $crate::ffi::PyTypeObject;
}
$crate::Py::from_borrowed_ptr(
TYPE_OBJECT as *const _ as *mut $crate::ffi::PyObject)
}
}
}
};
}
#[cfg(test)]
mod test {
use {PyErr, Python};
use objects::PyDict;
import_exception!(socket, gaierror);
#[test]
fn test_check_exception() {
let gil = Python::acquire_gil();
let py = gil.python();
let err: PyErr = gaierror.into();
let d = PyDict::new(py);
d.set_item("socket", py.import("socket").map_err(|e| e.print(py)).unwrap()).unwrap();
d.set_item("exc", err).unwrap();
py.run("assert isinstance(exc, socket.gaierror)", None, Some(d)).unwrap();
}
}