Skip to content

Commit 790a103

Browse files
authored
Merge pull request #291 from PyO3/exception_macros
Refactor the exception macros
2 parents 27b4c8a + 9102f2e commit 790a103

9 files changed

Lines changed: 288 additions & 250 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1414

1515
* Renamed `add_function` to `add_wrapped` as it now also supports modules.
1616
* Renamed `#[pymodinit]` to `#[pymodule]`.
17+
* Renamed `py_exception` to `create_exception` and refactored the error macros.
1718

1819
### Removed
1920

guide/src/exception.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
## Define a new exception
44

5-
You can use the `py_exception!` macro to define a new exception type:
5+
You can use the `create_exception!` macro to define a new exception type:
66

77
```rust
88
#[macro_use] extern crate pyo3;
99

10-
py_exception!(module, MyError, pyo3::exceptions::Exception);
10+
create_exception!(module, MyError, pyo3::exceptions::Exception);
1111
```
1212

1313
* `module` is the name of the containing module.
@@ -20,8 +20,9 @@ For example:
2020

2121
use pyo3::Python;
2222
use pyo3::types::PyDict;
23+
use pyo3::exceptions::Exception;
2324

24-
py_exception!(mymodule, CustomError, pyo3::exceptions::Exception);
25+
create_exception!(mymodule, CustomError, Exception);
2526

2627
fn main() {
2728
let gil = Python::acquire_gil();
@@ -61,7 +62,7 @@ PyErr::from_instance(py, err).restore(py);
6162

6263
If rust type exists for exception, then it is possible to use `new` method.
6364
For example each standard exception defined in `exc` module
64-
has corresponding rust type, exceptions defined by `py_exception!` and `import_exception!` macro
65+
has corresponding rust type, exceptions defined by `create_exception!` and `import_exception!` macro
6566
have rust type as well.
6667

6768
```rust

pyo3cls/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use syn::parse::Parser;
1818
use syn::punctuated::Punctuated;
1919

2020
#[proc_macro_attribute]
21-
pub fn mod2init(
21+
pub fn pymodule2(
2222
attr: proc_macro::TokenStream,
2323
input: proc_macro::TokenStream,
2424
) -> proc_macro::TokenStream {
@@ -46,7 +46,7 @@ pub fn mod2init(
4646
}
4747

4848
#[proc_macro_attribute]
49-
pub fn mod3init(
49+
pub fn pymodule3(
5050
attr: proc_macro::TokenStream,
5151
input: proc_macro::TokenStream,
5252
) -> proc_macro::TokenStream {

src/err.rs

Lines changed: 7 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
// Copyright (c) 2017-present PyO3 Project and Contributors
2-
use libc;
3-
use std;
4-
use std::error::Error;
5-
use std::ffi::CString;
6-
use std::io;
7-
use std::os::raw::c_char;
82

93
use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
104
use crate::ffi;
@@ -13,101 +7,12 @@ use crate::object::PyObject;
137
use crate::python::{IntoPyPointer, Python, ToPyPointer};
148
use crate::typeob::PyTypeObject;
159
use crate::types::{exceptions, PyObjectRef, PyType};
16-
17-
/// Defines a new exception type.
18-
///
19-
/// # Syntax
20-
/// `py_exception!(module, MyError, pyo3::exceptions::Exception)`
21-
///
22-
/// * `module` is the name of the containing module.
23-
/// * `MyError` is the name of the new exception type.
24-
/// * `pyo3::exceptions::Exception` is the name of the base type
25-
///
26-
/// # Example
27-
/// ```
28-
/// #[macro_use]
29-
/// extern crate pyo3;
30-
///
31-
/// use pyo3::Python;
32-
/// use pyo3::types::PyDict;
33-
///
34-
/// py_exception!(mymodule, CustomError, pyo3::exceptions::Exception);
35-
///
36-
/// fn main() {
37-
/// let gil = Python::acquire_gil();
38-
/// let py = gil.python();
39-
/// let ctx = PyDict::new(py);
40-
///
41-
/// ctx.set_item("CustomError", py.get_type::<CustomError>()).unwrap();
42-
///
43-
/// py.run("assert str(CustomError) == \"<class 'mymodule.CustomError'>\"",
44-
/// None, Some(&ctx)).unwrap();
45-
/// py.run("assert CustomError('oops').args == ('oops',)", None, Some(ctx)).unwrap();
46-
/// }
47-
/// ```
48-
#[macro_export]
49-
macro_rules! py_exception {
50-
($module: ident, $name: ident, $base: ty) => {
51-
pub struct $name;
52-
53-
impl std::convert::From<$name> for $crate::PyErr {
54-
fn from(_err: $name) -> $crate::PyErr {
55-
$crate::PyErr::new::<$name, _>(())
56-
}
57-
}
58-
59-
impl<T> std::convert::Into<$crate::PyResult<T>> for $name {
60-
fn into(self) -> $crate::PyResult<T> {
61-
$crate::PyErr::new::<$name, _>(()).into()
62-
}
63-
}
64-
65-
impl $name {
66-
pub fn py_err<T: $crate::ToPyObject + 'static>(args: T) -> $crate::PyErr {
67-
$crate::PyErr::new::<$name, T>(args)
68-
}
69-
pub fn into<R, T: $crate::ToPyObject + 'static>(args: T) -> $crate::PyResult<R> {
70-
$crate::PyErr::new::<$name, T>(args).into()
71-
}
72-
#[inline]
73-
fn type_object() -> *mut $crate::ffi::PyTypeObject {
74-
static mut TYPE_OBJECT: *mut $crate::ffi::PyTypeObject =
75-
0 as *mut $crate::ffi::PyTypeObject;
76-
77-
unsafe {
78-
if TYPE_OBJECT.is_null() {
79-
let gil = $crate::Python::acquire_gil();
80-
let py = gil.python();
81-
82-
TYPE_OBJECT = $crate::PyErr::new_type(
83-
py,
84-
concat!(stringify!($module), ".", stringify!($name)),
85-
Some(py.get_type::<$base>()),
86-
None,
87-
);
88-
}
89-
TYPE_OBJECT
90-
}
91-
}
92-
}
93-
94-
impl $crate::typeob::PyTypeObject for $name {
95-
#[inline]
96-
fn init_type() {
97-
let _ = $name::type_object();
98-
}
99-
100-
#[inline]
101-
fn type_object() -> $crate::Py<$crate::types::PyType> {
102-
unsafe {
103-
$crate::Py::from_borrowed_ptr(
104-
$name::type_object() as *const _ as *mut $crate::ffi::PyObject
105-
)
106-
}
107-
}
108-
}
109-
};
110-
}
10+
use libc::c_int;
11+
use std;
12+
use std::error::Error;
13+
use std::ffi::CString;
14+
use std::io;
15+
use std::os::raw::c_char;
11116

11217
/// Represents a `PyErr` value
11318
pub enum PyErrValue {
@@ -607,7 +512,7 @@ pub fn panic_after_error() -> ! {
607512

608513
/// Returns Ok if the error code is not -1.
609514
#[inline]
610-
pub fn error_on_minusone(py: Python, result: libc::c_int) -> PyResult<()> {
515+
pub fn error_on_minusone(py: Python, result: c_int) -> PyResult<()> {
611516
if result != -1 {
612517
Ok(())
613518
} else {

src/ffi3/object.rs

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::ffi3::pyport::{Py_hash_t, Py_ssize_t};
2+
use std::mem;
23
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void};
34
use std::ptr;
45

@@ -24,7 +25,7 @@ pub const PyObject_HEAD_INIT: PyObject = PyObject {
2425
#[cfg(not(py_sys_config = "Py_TRACE_REFS"))]
2526
pub const PyObject_HEAD_INIT: PyObject = PyObject {
2627
ob_refcnt: 1,
27-
ob_type: ::std::ptr::null_mut(),
28+
ob_type: ptr::null_mut(),
2829
};
2930

3031
#[repr(C)]
@@ -87,6 +88,7 @@ pub type objobjargproc =
8788
#[cfg(not(Py_LIMITED_API))]
8889
mod bufferinfo {
8990
use crate::ffi3::pyport::Py_ssize_t;
91+
use std::mem;
9092
use std::os::raw::{c_char, c_int, c_void};
9193

9294
#[repr(C)]
@@ -108,7 +110,7 @@ mod bufferinfo {
108110
impl Default for Py_buffer {
109111
#[inline]
110112
fn default() -> Self {
111-
unsafe { ::std::mem::zeroed() }
113+
unsafe { mem::zeroed() }
112114
}
113115
}
114116

@@ -198,7 +200,9 @@ mod typeobject {
198200
mod typeobject {
199201
use crate::ffi3::pyport::Py_ssize_t;
200202
use crate::ffi3::{self, object};
203+
use std::mem;
201204
use std::os::raw::{c_char, c_uint, c_ulong, c_void};
205+
use std::ptr;
202206

203207
#[repr(C)]
204208
#[derive(Copy, Clone)]
@@ -244,7 +248,7 @@ mod typeobject {
244248
impl Default for PyNumberMethods {
245249
#[inline]
246250
fn default() -> Self {
247-
unsafe { ::std::mem::zeroed() }
251+
unsafe { mem::zeroed() }
248252
}
249253
}
250254
macro_rules! as_expr {
@@ -320,17 +324,17 @@ mod typeobject {
320324
impl Default for PySequenceMethods {
321325
#[inline]
322326
fn default() -> Self {
323-
unsafe { ::std::mem::zeroed() }
327+
unsafe { mem::zeroed() }
324328
}
325329
}
326330
pub const PySequenceMethods_INIT: PySequenceMethods = PySequenceMethods {
327331
sq_length: None,
328332
sq_concat: None,
329333
sq_repeat: None,
330334
sq_item: None,
331-
was_sq_slice: ::std::ptr::null_mut(),
335+
was_sq_slice: ptr::null_mut(),
332336
sq_ass_item: None,
333-
was_sq_ass_slice: ::std::ptr::null_mut(),
337+
was_sq_ass_slice: ptr::null_mut(),
334338
sq_contains: None,
335339
sq_inplace_concat: None,
336340
sq_inplace_repeat: None,
@@ -346,7 +350,7 @@ mod typeobject {
346350
impl Default for PyMappingMethods {
347351
#[inline]
348352
fn default() -> Self {
349-
unsafe { ::std::mem::zeroed() }
353+
unsafe { mem::zeroed() }
350354
}
351355
}
352356
pub const PyMappingMethods_INIT: PyMappingMethods = PyMappingMethods {
@@ -365,7 +369,7 @@ mod typeobject {
365369
impl Default for PyAsyncMethods {
366370
#[inline]
367371
fn default() -> Self {
368-
unsafe { ::std::mem::zeroed() }
372+
unsafe { mem::zeroed() }
369373
}
370374
}
371375
pub const PyAsyncMethods_INIT: PyAsyncMethods = PyAsyncMethods {
@@ -383,7 +387,7 @@ mod typeobject {
383387
impl Default for PyBufferProcs {
384388
#[inline]
385389
fn default() -> Self {
386-
unsafe { ::std::mem::zeroed() }
390+
unsafe { mem::zeroed() }
387391
}
388392
}
389393
pub const PyBufferProcs_INIT: PyBufferProcs = PyBufferProcs {
@@ -462,37 +466,37 @@ mod typeobject {
462466
ob_base: ffi3::object::PyObject_HEAD_INIT,
463467
ob_size: 0
464468
},
465-
tp_name: ::std::ptr::null(),
469+
tp_name: ptr::null(),
466470
tp_basicsize: 0,
467471
tp_itemsize: 0,
468472
tp_dealloc: None,
469473
tp_print: None,
470474
tp_getattr: None,
471475
tp_setattr: None,
472-
$tp_as_async: ::std::ptr::null_mut(),
476+
$tp_as_async: ptr::null_mut(),
473477
tp_repr: None,
474-
tp_as_number: ::std::ptr::null_mut(),
475-
tp_as_sequence: ::std::ptr::null_mut(),
476-
tp_as_mapping: ::std::ptr::null_mut(),
478+
tp_as_number: ptr::null_mut(),
479+
tp_as_sequence: ptr::null_mut(),
480+
tp_as_mapping: ptr::null_mut(),
477481
tp_hash: None,
478482
tp_call: None,
479483
tp_str: None,
480484
tp_getattro: None,
481485
tp_setattro: None,
482-
tp_as_buffer: ::std::ptr::null_mut(),
486+
tp_as_buffer: ptr::null_mut(),
483487
tp_flags: ffi3::object::Py_TPFLAGS_DEFAULT,
484-
tp_doc: ::std::ptr::null(),
488+
tp_doc: ptr::null(),
485489
tp_traverse: None,
486490
tp_clear: None,
487491
tp_richcompare: None,
488492
tp_weaklistoffset: 0,
489493
tp_iter: None,
490494
tp_iternext: None,
491-
tp_methods: ::std::ptr::null_mut(),
492-
tp_members: ::std::ptr::null_mut(),
493-
tp_getset: ::std::ptr::null_mut(),
494-
tp_base: ::std::ptr::null_mut(),
495-
tp_dict: ::std::ptr::null_mut(),
495+
tp_methods: ptr::null_mut(),
496+
tp_members: ptr::null_mut(),
497+
tp_getset: ptr::null_mut(),
498+
tp_base: ptr::null_mut(),
499+
tp_dict: ptr::null_mut(),
496500
tp_descr_get: None,
497501
tp_descr_set: None,
498502
tp_dictoffset: 0,
@@ -501,11 +505,11 @@ mod typeobject {
501505
tp_new: None,
502506
tp_free: None,
503507
tp_is_gc: None,
504-
tp_bases: ::std::ptr::null_mut(),
505-
tp_mro: ::std::ptr::null_mut(),
506-
tp_cache: ::std::ptr::null_mut(),
507-
tp_subclasses: ::std::ptr::null_mut(),
508-
tp_weaklist: ::std::ptr::null_mut(),
508+
tp_bases: ptr::null_mut(),
509+
tp_mro: ptr::null_mut(),
510+
tp_cache: ptr::null_mut(),
511+
tp_subclasses: ptr::null_mut(),
512+
tp_weaklist: ptr::null_mut(),
509513
tp_del: None,
510514
tp_version_tag: 0,
511515
$($tail)*
@@ -522,8 +526,8 @@ mod typeobject {
522526
tp_allocs: 0,
523527
tp_frees: 0,
524528
tp_maxalloc: 0,
525-
tp_prev: ::std::ptr::null_mut(),
526-
tp_next: ::std::ptr::null_mut(),
529+
tp_prev: ptr::null_mut(),
530+
tp_next: ptr::null_mut(),
527531
)
528532
}
529533
}
@@ -556,7 +560,7 @@ mod typeobject {
556560
impl Default for PyHeapTypeObject {
557561
#[inline]
558562
fn default() -> Self {
559-
unsafe { ::std::mem::zeroed() }
563+
unsafe { mem::zeroed() }
560564
}
561565
}
562566

@@ -582,7 +586,7 @@ pub struct PyType_Slot {
582586

583587
impl Default for PyType_Slot {
584588
fn default() -> PyType_Slot {
585-
unsafe { ::std::mem::zeroed() }
589+
unsafe { mem::zeroed() }
586590
}
587591
}
588592

@@ -598,7 +602,7 @@ pub struct PyType_Spec {
598602

599603
impl Default for PyType_Spec {
600604
fn default() -> PyType_Spec {
601-
unsafe { ::std::mem::zeroed() }
605+
unsafe { mem::zeroed() }
602606
}
603607
}
604608

0 commit comments

Comments
 (0)