types: refactor native_type macros
This commit is contained in:
parent
ff5e2d0856
commit
f8d408f3b5
|
@ -12,8 +12,6 @@ use std::os::raw::c_char;
|
|||
#[macro_export]
|
||||
macro_rules! impl_exception_boilerplate {
|
||||
($name: ident) => {
|
||||
$crate::pyobject_native_type_fmt!($name);
|
||||
|
||||
impl std::convert::From<&$name> for $crate::PyErr {
|
||||
fn from(err: &$name) -> $crate::PyErr {
|
||||
$crate::PyErr::from_instance(err)
|
||||
|
@ -88,22 +86,10 @@ macro_rules! import_exception {
|
|||
$name,
|
||||
$crate::ffi::PyBaseExceptionObject,
|
||||
*$name::type_object_raw($crate::Python::assume_gil_acquired()),
|
||||
Some(stringify!($module)),
|
||||
$name::check
|
||||
Some(stringify!($module))
|
||||
);
|
||||
|
||||
impl $name {
|
||||
/// Check if a python object is an instance of this exception.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a valid pointer to a Python object
|
||||
unsafe fn check(ptr: *mut $crate::ffi::PyObject) -> $crate::libc::c_int {
|
||||
$crate::ffi::PyObject_TypeCheck(
|
||||
ptr,
|
||||
Self::type_object_raw($crate::Python::assume_gil_acquired()) as *mut _,
|
||||
)
|
||||
}
|
||||
|
||||
fn type_object_raw(py: $crate::Python) -> *mut $crate::ffi::PyTypeObject {
|
||||
use $crate::once_cell::GILOnceCell;
|
||||
use $crate::AsPyPointer;
|
||||
|
@ -191,22 +177,10 @@ macro_rules! create_exception_type_object {
|
|||
$name,
|
||||
$crate::ffi::PyBaseExceptionObject,
|
||||
*$name::type_object_raw($crate::Python::assume_gil_acquired()),
|
||||
Some(stringify!($module)),
|
||||
$name::check
|
||||
Some(stringify!($module))
|
||||
);
|
||||
|
||||
impl $name {
|
||||
/// Check if a python object is an instance of this exception.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a valid pointer to a Python object
|
||||
unsafe fn check(ptr: *mut $crate::ffi::PyObject) -> $crate::libc::c_int {
|
||||
$crate::ffi::PyObject_TypeCheck(
|
||||
ptr,
|
||||
Self::type_object_raw($crate::Python::assume_gil_acquired()) as *mut _,
|
||||
)
|
||||
}
|
||||
|
||||
fn type_object_raw(py: $crate::Python) -> *mut $crate::ffi::PyTypeObject {
|
||||
use $crate::once_cell::GILOnceCell;
|
||||
use $crate::AsPyPointer;
|
||||
|
@ -240,18 +214,7 @@ macro_rules! impl_native_exception (
|
|||
pub type $legacy_name = $crate::Py<$name>;
|
||||
|
||||
$crate::impl_exception_boilerplate!($name);
|
||||
|
||||
impl $name {
|
||||
/// Check if a python object is an instance of this exception.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a valid pointer to a Python object
|
||||
unsafe fn check(ptr: *mut $crate::ffi::PyObject) -> $crate::libc::c_int {
|
||||
ffi::PyObject_TypeCheck(ptr, ffi::$exc_name as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
$crate::pyobject_native_type_core!($name, $layout, *(ffi::$exc_name as *mut ffi::PyTypeObject), Some("builtins"), $name::check);
|
||||
$crate::pyobject_native_type_core!($name, $layout, *(ffi::$exc_name as *mut ffi::PyTypeObject), Some("builtins"));
|
||||
);
|
||||
($name:ident, $legacy_name:ident, $exc_name:ident) => (
|
||||
impl_native_exception!($name, $legacy_name, $exc_name, ffi::PyBaseExceptionObject);
|
||||
|
|
|
@ -45,18 +45,10 @@ impl crate::AsPyPointer for PyAny {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PyAny {
|
||||
#[inline]
|
||||
fn eq(&self, o: &PyAny) -> bool {
|
||||
self.as_ptr() == o.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl crate::PyNativeType for PyAny {}
|
||||
unsafe impl crate::type_object::PyLayout<PyAny> for ffi::PyObject {}
|
||||
impl crate::type_object::PySizedLayout<PyAny> for ffi::PyObject {}
|
||||
|
||||
pyobject_native_type_convert!(
|
||||
pyobject_native_type_info!(
|
||||
PyAny,
|
||||
ffi::PyObject,
|
||||
ffi::PyBaseObject_Type,
|
||||
|
@ -66,7 +58,7 @@ pyobject_native_type_convert!(
|
|||
|
||||
pyobject_native_type_extract!(PyAny);
|
||||
|
||||
pyobject_native_type_fmt!(PyAny);
|
||||
pyobject_native_type_base!(PyAny);
|
||||
|
||||
impl PyAny {
|
||||
/// Convert this PyAny to a concrete Python type.
|
||||
|
|
|
@ -24,7 +24,6 @@ use crate::{PyDowncastError, PyTryFrom};
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyIterator(PyAny);
|
||||
pyobject_native_type_named!(PyIterator);
|
||||
|
|
186
src/types/mod.rs
186
src/types/mod.rs
|
@ -27,17 +27,65 @@ pub use self::string::{PyString, PyString as PyUnicode};
|
|||
pub use self::tuple::PyTuple;
|
||||
pub use self::typeobject::PyType;
|
||||
|
||||
// Implementations core to all native types
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_base(
|
||||
($name: ty $(,generics: <$($generics:ident),+>)?) => {
|
||||
unsafe impl<$($($generics),+)?> $crate::PyNativeType for $name {}
|
||||
|
||||
impl<$($($generics),+)?> ::std::fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter)
|
||||
-> Result<(), ::std::fmt::Error>
|
||||
{
|
||||
let s = self.repr().map_err(|_| ::std::fmt::Error)?;
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($($generics),+)?> ::std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter)
|
||||
-> Result<(), ::std::fmt::Error>
|
||||
{
|
||||
let s = self.str().map_err(|_| ::std::fmt::Error)?;
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($($generics),+)?> $crate::ToPyObject for $name
|
||||
{
|
||||
#[inline]
|
||||
fn to_object(&self, py: $crate::Python) -> $crate::PyObject {
|
||||
use $crate::AsPyPointer;
|
||||
unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($($generics),+)?> PartialEq for $name {
|
||||
#[inline]
|
||||
fn eq(&self, o: &$name) -> bool {
|
||||
use $crate::AsPyPointer;
|
||||
|
||||
self.as_ptr() == o.as_ptr()
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
// Implementations core to all native types except for PyAny (because they don't
|
||||
// make sense on PyAny / have different implementations).
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_named (
|
||||
($name: ty $(,$type_param: ident)*) => {
|
||||
impl<$($type_param,)*> ::std::convert::AsRef<$crate::PyAny> for $name {
|
||||
($name: ty $(,generics: <$($generics:ident),+>)?) => {
|
||||
$crate::pyobject_native_type_base!($name $(,generics: <$($generics),+>)?);
|
||||
|
||||
impl<$($($generics),+)?> ::std::convert::AsRef<$crate::PyAny> for $name {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &$crate::PyAny {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($type_param,)*> ::std::ops::Deref for $name {
|
||||
impl<$($($generics),+)?> ::std::ops::Deref for $name {
|
||||
type Target = $crate::PyAny;
|
||||
|
||||
#[inline]
|
||||
|
@ -46,9 +94,7 @@ macro_rules! pyobject_native_type_named (
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<$($type_param,)*> $crate::PyNativeType for $name {}
|
||||
|
||||
impl<$($type_param,)*> $crate::AsPyPointer for $name {
|
||||
impl<$($($generics),+)?> $crate::AsPyPointer for $name {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
|
||||
|
@ -56,43 +102,15 @@ macro_rules! pyobject_native_type_named (
|
|||
}
|
||||
}
|
||||
|
||||
impl<$($type_param,)*> PartialEq for $name {
|
||||
#[inline]
|
||||
fn eq(&self, o: &$name) -> bool {
|
||||
use $crate::AsPyPointer;
|
||||
|
||||
self.as_ptr() == o.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($type_param,)*> $crate::IntoPy<$crate::Py<$name>> for &'_ $name {
|
||||
impl<$($($generics),+)?> $crate::IntoPy<$crate::Py<$name>> for &'_ $name {
|
||||
#[inline]
|
||||
fn into_py(self, py: $crate::Python) -> $crate::Py<$name> {
|
||||
use $crate::AsPyPointer;
|
||||
unsafe { $crate::Py::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_core {
|
||||
($name: ty, $layout: path, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
unsafe impl $crate::type_object::PyLayout<$name> for $layout {}
|
||||
$crate::pyobject_native_type_named!($name $(,$type_param)*);
|
||||
$crate::pyobject_native_type_convert!($name, $layout, $typeobject, $module, $checkfunction $(,$type_param)*);
|
||||
$crate::pyobject_native_type_extract!($name $(,$type_param)*);
|
||||
|
||||
impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::PyAny {
|
||||
fn from(ob: &'a $name) -> Self {
|
||||
unsafe{&*(ob as *const $name as *const $crate::PyAny)}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Rust>=1.40 allows this impl for rust-numpy.
|
||||
// So we should move this to `named` or `convert` when we bump MSRV.
|
||||
impl<$($type_param,)*> From<&'_ $name> for $crate::Py<$name> {
|
||||
impl<$($($generics),+)?> From<&'_ $name> for $crate::Py<$name> {
|
||||
#[inline]
|
||||
fn from(other: &$name) -> Self {
|
||||
use $crate::AsPyPointer;
|
||||
|
@ -100,16 +118,32 @@ macro_rules! pyobject_native_type_core {
|
|||
unsafe { $crate::Py::from_borrowed_ptr(other.py(), other.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $($($generics),+)?> ::std::convert::From<&'a $name> for &'a $crate::PyAny {
|
||||
fn from(ob: &'a $name) -> Self {
|
||||
unsafe{&*(ob as *const $name as *const $crate::PyAny)}
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_core {
|
||||
($name: ty, $layout: path, $typeobject: expr, $module: expr $(, $checkfunction:path)? $(,generics: <$($generics:ident),+>)? ) => {
|
||||
unsafe impl $crate::type_object::PyLayout<$name> for $layout {}
|
||||
$crate::pyobject_native_type_named!($name $(,generics: <$($generics),+>)?);
|
||||
$crate::pyobject_native_type_info!($name, $layout, $typeobject, $module $(, $checkfunction)? $(,generics: <$($generics),+>)?);
|
||||
$crate::pyobject_native_type_extract!($name $(,generics: <$($generics),+>)?);
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_sized {
|
||||
($name: ty, $layout: path $(,$type_param: ident)*) => {
|
||||
($name: ty, $layout: path $(,generics: <$($generics:ident),+>)?) => {
|
||||
// To prevent inheriting native types with ABI3
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
impl $crate::type_object::PySizedLayout<$name> for $layout {}
|
||||
impl<'a, $($type_param,)*> $crate::derive_utils::PyBaseTypeUtils for $name {
|
||||
impl<'a, $($($generics),+)?> $crate::derive_utils::PyBaseTypeUtils for $name {
|
||||
type Dict = $crate::pyclass_slots::PyClassDummySlot;
|
||||
type WeakRef = $crate::pyclass_slots::PyClassDummySlot;
|
||||
type LayoutAsBase = $crate::pycell::PyCellBase<$name>;
|
||||
|
@ -121,38 +155,36 @@ macro_rules! pyobject_native_type_sized {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type {
|
||||
($name: ty, $layout: path, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
$crate::pyobject_native_type_core!($name, $layout, $typeobject, $module, $checkfunction $(,$type_param)*);
|
||||
$crate::pyobject_native_type_sized!($name, $layout $(,$type_param)*);
|
||||
$crate::pyobject_native_type_fmt!($name $(,$type_param)*);
|
||||
($name: ty, $layout: path, $typeobject: expr, $module: expr, $checkfunction:path $(,generics: <$($generics:ident),+>)?) => {
|
||||
$crate::pyobject_native_type_core!($name, $layout, $typeobject, $module, $checkfunction $(,generics: <$($generics),+>)?);
|
||||
$crate::pyobject_native_type_sized!($name, $layout $(,generics: <$($generics),+>)?);
|
||||
};
|
||||
($name: ty, $layout: path, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
($name: ty, $layout: path, $typeobject: expr, $checkfunction:path $(,generics: <$($generics:ident),+>)?) => {
|
||||
$crate::pyobject_native_type! {
|
||||
$name, $layout, $typeobject, Some("builtins"), $checkfunction $(,$type_param)*
|
||||
$name, $layout, $typeobject, Some("builtins"), $checkfunction $(,generics: <$($generics),+>)?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_var_type {
|
||||
($name: ty, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
($name: ty, $typeobject: expr, $module: expr, $checkfunction:path $(,generics: <$($generics:ident),+>)?) => {
|
||||
$crate::pyobject_native_type_core!(
|
||||
$name, $crate::ffi::PyObject, $typeobject, Some("builtins"), $checkfunction $(,$type_param)*);
|
||||
$crate::pyobject_native_type_fmt!($name $(,$type_param)*);
|
||||
$name, $crate::ffi::PyObject, $typeobject, Some("builtins"), $checkfunction $(,generics: <$($generics),+>)?);
|
||||
};
|
||||
($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
($name: ty, $typeobject: expr, $checkfunction: path $(,generics: <$($generics:ident),+>)?) => {
|
||||
$crate::pyobject_native_var_type! {
|
||||
$name, $typeobject, Some("builtins"), $checkfunction $(,$type_param)*
|
||||
$name, $typeobject, Some("builtins"), $checkfunction $(,generics: <$($generics),+>)?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: This macro is not included in pyobject_native_type_convert!
|
||||
// NOTE: This macro is not included in pyobject_native_type_base!
|
||||
// because rust-numpy has a special implementation.
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_extract {
|
||||
($name: ty $(,$type_param: ident)*) => {
|
||||
impl<'py, $($type_param,)*> $crate::FromPyObject<'py> for &'py $name {
|
||||
($name: ty $(,generics: <$($generics:ident),+>)?) => {
|
||||
impl<'py, $($($generics),+)?> $crate::FromPyObject<'py> for &'py $name {
|
||||
fn extract(obj: &'py $crate::PyAny) -> $crate::PyResult<Self> {
|
||||
$crate::PyTryFrom::try_from(obj).map_err(Into::into)
|
||||
}
|
||||
|
@ -161,10 +193,10 @@ macro_rules! pyobject_native_type_extract {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_convert(
|
||||
macro_rules! pyobject_native_type_info(
|
||||
($name: ty, $layout: path, $typeobject: expr,
|
||||
$module: expr, $checkfunction: path $(,$type_param: ident)*) => {
|
||||
unsafe impl<$($type_param,)*> $crate::type_object::PyTypeInfo for $name {
|
||||
$module: expr $(, $checkfunction:path)? $(,generics: <$($generics:ident),+>)?) => {
|
||||
unsafe impl<$($($generics),+)?> $crate::type_object::PyTypeInfo for $name {
|
||||
type Type = ();
|
||||
type BaseType = $crate::PyAny;
|
||||
type Layout = $layout;
|
||||
|
@ -183,43 +215,13 @@ macro_rules! pyobject_native_type_convert(
|
|||
unsafe { &mut $typeobject }
|
||||
}
|
||||
|
||||
#[allow(unused_unsafe)]
|
||||
fn is_type_of(ptr: &$crate::PyAny) -> bool {
|
||||
use $crate::AsPyPointer;
|
||||
unsafe { $checkfunction(ptr.as_ptr()) > 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($type_param,)*> $crate::ToPyObject for $name
|
||||
{
|
||||
#[inline]
|
||||
fn to_object(&self, py: $crate::Python) -> $crate::PyObject {
|
||||
use $crate::AsPyPointer;
|
||||
unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_fmt(
|
||||
($name: ty $(,$type_param: ident)*) => {
|
||||
impl<$($type_param,)*> ::std::fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter)
|
||||
-> Result<(), ::std::fmt::Error>
|
||||
{
|
||||
let s = self.repr().map_err(|_| ::std::fmt::Error)?;
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($type_param,)*> ::std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter)
|
||||
-> Result<(), ::std::fmt::Error>
|
||||
{
|
||||
let s = self.str().map_err(|_| ::std::fmt::Error)?;
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
$(
|
||||
fn is_type_of(ptr: &$crate::PyAny) -> bool {
|
||||
use $crate::AsPyPointer;
|
||||
#[allow(unused_unsafe)]
|
||||
unsafe { $checkfunction(ptr.as_ptr()) > 0 }
|
||||
}
|
||||
)?
|
||||
}
|
||||
};
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue