Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

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

### Removed

Expand Down
9 changes: 5 additions & 4 deletions guide/src/exception.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

## Define a new exception

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

```rust
#[macro_use] extern crate pyo3;

py_exception!(module, MyError, pyo3::exceptions::Exception);
create_exception!(module, MyError, pyo3::exceptions::Exception);
```

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

use pyo3::Python;
use pyo3::types::PyDict;
use pyo3::exceptions::Exception;

py_exception!(mymodule, CustomError, pyo3::exceptions::Exception);
create_exception!(mymodule, CustomError, Exception);

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

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

```rust
Expand Down
4 changes: 2 additions & 2 deletions pyo3cls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use syn::parse::Parser;
use syn::punctuated::Punctuated;

#[proc_macro_attribute]
pub fn mod2init(
pub fn pymodule2(
attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
Expand Down Expand Up @@ -46,7 +46,7 @@ pub fn mod2init(
}

#[proc_macro_attribute]
pub fn mod3init(
pub fn pymodule3(
attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
Expand Down
109 changes: 7 additions & 102 deletions src/err.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use libc;
use std;
use std::error::Error;
use std::ffi::CString;
use std::io;
use std::os::raw::c_char;

use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use crate::ffi;
Expand All @@ -13,101 +7,12 @@ use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeObject;
use crate::types::{exceptions, PyObjectRef, PyType};

/// Defines a new exception type.
///
/// # Syntax
/// `py_exception!(module, MyError, pyo3::exceptions::Exception)`
///
/// * `module` is the name of the containing module.
/// * `MyError` is the name of the new exception type.
/// * `pyo3::exceptions::Exception` is the name of the base type
///
/// # Example
/// ```
/// #[macro_use]
/// extern crate pyo3;
///
/// use pyo3::Python;
/// use pyo3::types::PyDict;
///
/// py_exception!(mymodule, CustomError, pyo3::exceptions::Exception);
///
/// fn main() {
/// let gil = Python::acquire_gil();
/// let py = gil.python();
/// let ctx = PyDict::new(py);
///
/// ctx.set_item("CustomError", py.get_type::<CustomError>()).unwrap();
///
/// py.run("assert str(CustomError) == \"<class 'mymodule.CustomError'>\"",
/// None, Some(&ctx)).unwrap();
/// py.run("assert CustomError('oops').args == ('oops',)", None, Some(ctx)).unwrap();
/// }
/// ```
#[macro_export]
macro_rules! py_exception {
($module: ident, $name: ident, $base: ty) => {
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 py_err<T: $crate::ToPyObject + 'static>(args: T) -> $crate::PyErr {
$crate::PyErr::new::<$name, T>(args)
}
pub fn into<R, T: $crate::ToPyObject + 'static>(args: T) -> $crate::PyResult<R> {
$crate::PyErr::new::<$name, T>(args).into()
}
#[inline]
fn type_object() -> *mut $crate::ffi::PyTypeObject {
static mut TYPE_OBJECT: *mut $crate::ffi::PyTypeObject =
0 as *mut $crate::ffi::PyTypeObject;

unsafe {
if TYPE_OBJECT.is_null() {
let gil = $crate::Python::acquire_gil();
let py = gil.python();

TYPE_OBJECT = $crate::PyErr::new_type(
py,
concat!(stringify!($module), ".", stringify!($name)),
Some(py.get_type::<$base>()),
None,
);
}
TYPE_OBJECT
}
}
}

impl $crate::typeob::PyTypeObject for $name {
#[inline]
fn init_type() {
let _ = $name::type_object();
}

#[inline]
fn type_object() -> $crate::Py<$crate::types::PyType> {
unsafe {
$crate::Py::from_borrowed_ptr(
$name::type_object() as *const _ as *mut $crate::ffi::PyObject
)
}
}
}
};
}
use libc::c_int;
use std;
use std::error::Error;
use std::ffi::CString;
use std::io;
use std::os::raw::c_char;

/// Represents a `PyErr` value
pub enum PyErrValue {
Expand Down Expand Up @@ -607,7 +512,7 @@ pub fn panic_after_error() -> ! {

/// Returns Ok if the error code is not -1.
#[inline]
pub fn error_on_minusone(py: Python, result: libc::c_int) -> PyResult<()> {
pub fn error_on_minusone(py: Python, result: c_int) -> PyResult<()> {
if result != -1 {
Ok(())
} else {
Expand Down
66 changes: 35 additions & 31 deletions src/ffi3/object.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::ffi3::pyport::{Py_hash_t, Py_ssize_t};
use std::mem;
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void};
use std::ptr;

Expand All @@ -24,7 +25,7 @@ pub const PyObject_HEAD_INIT: PyObject = PyObject {
#[cfg(not(py_sys_config = "Py_TRACE_REFS"))]
pub const PyObject_HEAD_INIT: PyObject = PyObject {
ob_refcnt: 1,
ob_type: ::std::ptr::null_mut(),
ob_type: ptr::null_mut(),
};

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

#[repr(C)]
Expand All @@ -108,7 +110,7 @@ mod bufferinfo {
impl Default for Py_buffer {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}

Expand Down Expand Up @@ -198,7 +200,9 @@ mod typeobject {
mod typeobject {
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi3::{self, object};
use std::mem;
use std::os::raw::{c_char, c_uint, c_ulong, c_void};
use std::ptr;

#[repr(C)]
#[derive(Copy, Clone)]
Expand Down Expand Up @@ -244,7 +248,7 @@ mod typeobject {
impl Default for PyNumberMethods {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}
macro_rules! as_expr {
Expand Down Expand Up @@ -320,17 +324,17 @@ mod typeobject {
impl Default for PySequenceMethods {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}
pub const PySequenceMethods_INIT: PySequenceMethods = PySequenceMethods {
sq_length: None,
sq_concat: None,
sq_repeat: None,
sq_item: None,
was_sq_slice: ::std::ptr::null_mut(),
was_sq_slice: ptr::null_mut(),
sq_ass_item: None,
was_sq_ass_slice: ::std::ptr::null_mut(),
was_sq_ass_slice: ptr::null_mut(),
sq_contains: None,
sq_inplace_concat: None,
sq_inplace_repeat: None,
Expand All @@ -346,7 +350,7 @@ mod typeobject {
impl Default for PyMappingMethods {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}
pub const PyMappingMethods_INIT: PyMappingMethods = PyMappingMethods {
Expand All @@ -365,7 +369,7 @@ mod typeobject {
impl Default for PyAsyncMethods {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}
pub const PyAsyncMethods_INIT: PyAsyncMethods = PyAsyncMethods {
Expand All @@ -383,7 +387,7 @@ mod typeobject {
impl Default for PyBufferProcs {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}
pub const PyBufferProcs_INIT: PyBufferProcs = PyBufferProcs {
Expand Down Expand Up @@ -462,37 +466,37 @@ mod typeobject {
ob_base: ffi3::object::PyObject_HEAD_INIT,
ob_size: 0
},
tp_name: ::std::ptr::null(),
tp_name: ptr::null(),
tp_basicsize: 0,
tp_itemsize: 0,
tp_dealloc: None,
tp_print: None,
tp_getattr: None,
tp_setattr: None,
$tp_as_async: ::std::ptr::null_mut(),
$tp_as_async: ptr::null_mut(),
tp_repr: None,
tp_as_number: ::std::ptr::null_mut(),
tp_as_sequence: ::std::ptr::null_mut(),
tp_as_mapping: ::std::ptr::null_mut(),
tp_as_number: ptr::null_mut(),
tp_as_sequence: ptr::null_mut(),
tp_as_mapping: ptr::null_mut(),
tp_hash: None,
tp_call: None,
tp_str: None,
tp_getattro: None,
tp_setattro: None,
tp_as_buffer: ::std::ptr::null_mut(),
tp_as_buffer: ptr::null_mut(),
tp_flags: ffi3::object::Py_TPFLAGS_DEFAULT,
tp_doc: ::std::ptr::null(),
tp_doc: ptr::null(),
tp_traverse: None,
tp_clear: None,
tp_richcompare: None,
tp_weaklistoffset: 0,
tp_iter: None,
tp_iternext: None,
tp_methods: ::std::ptr::null_mut(),
tp_members: ::std::ptr::null_mut(),
tp_getset: ::std::ptr::null_mut(),
tp_base: ::std::ptr::null_mut(),
tp_dict: ::std::ptr::null_mut(),
tp_methods: ptr::null_mut(),
tp_members: ptr::null_mut(),
tp_getset: ptr::null_mut(),
tp_base: ptr::null_mut(),
tp_dict: ptr::null_mut(),
tp_descr_get: None,
tp_descr_set: None,
tp_dictoffset: 0,
Expand All @@ -501,11 +505,11 @@ mod typeobject {
tp_new: None,
tp_free: None,
tp_is_gc: None,
tp_bases: ::std::ptr::null_mut(),
tp_mro: ::std::ptr::null_mut(),
tp_cache: ::std::ptr::null_mut(),
tp_subclasses: ::std::ptr::null_mut(),
tp_weaklist: ::std::ptr::null_mut(),
tp_bases: ptr::null_mut(),
tp_mro: ptr::null_mut(),
tp_cache: ptr::null_mut(),
tp_subclasses: ptr::null_mut(),
tp_weaklist: ptr::null_mut(),
tp_del: None,
tp_version_tag: 0,
$($tail)*
Expand All @@ -522,8 +526,8 @@ mod typeobject {
tp_allocs: 0,
tp_frees: 0,
tp_maxalloc: 0,
tp_prev: ::std::ptr::null_mut(),
tp_next: ::std::ptr::null_mut(),
tp_prev: ptr::null_mut(),
tp_next: ptr::null_mut(),
)
}
}
Expand Down Expand Up @@ -556,7 +560,7 @@ mod typeobject {
impl Default for PyHeapTypeObject {
#[inline]
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}

Expand All @@ -582,7 +586,7 @@ pub struct PyType_Slot {

impl Default for PyType_Slot {
fn default() -> PyType_Slot {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}

Expand All @@ -598,7 +602,7 @@ pub struct PyType_Spec {

impl Default for PyType_Spec {
fn default() -> PyType_Spec {
unsafe { ::std::mem::zeroed() }
unsafe { mem::zeroed() }
}
}

Expand Down
Loading