Merge pull request #1328 from davidhewitt/pyproto-no-inventory
pyproto: remove inventory from implementation
This commit is contained in:
commit
33b3da3337
|
@ -772,23 +772,31 @@ impl pyo3::class::methods::HasMethodsInventory for MyClass {
|
|||
}
|
||||
pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass);
|
||||
|
||||
|
||||
pub struct Pyo3ProtoInventoryForMyClass {
|
||||
def: pyo3::class::proto_methods::PyProtoMethodDef,
|
||||
}
|
||||
impl pyo3::class::proto_methods::PyProtoInventory for Pyo3ProtoInventoryForMyClass {
|
||||
fn new(def: pyo3::class::proto_methods::PyProtoMethodDef) -> Self {
|
||||
Self { def }
|
||||
impl pyo3::class::proto_methods::PyProtoMethods for MyClass {
|
||||
fn for_each_proto_slot<Visitor: FnMut(pyo3::ffi::PyType_Slot)>(visitor: Visitor) {
|
||||
// Implementation which uses dtolnay specialization to load all slots.
|
||||
use pyo3::class::proto_methods::*;
|
||||
let protocols = PyClassProtocols::<MyClass>::new();
|
||||
protocols.object_protocol_slots()
|
||||
.iter()
|
||||
.chain(protocols.number_protocol_slots())
|
||||
.chain(protocols.iter_protocol_slots())
|
||||
.chain(protocols.gc_protocol_slots())
|
||||
.chain(protocols.descr_protocol_slots())
|
||||
.chain(protocols.mapping_protocol_slots())
|
||||
.chain(protocols.sequence_protocol_slots())
|
||||
.chain(protocols.async_protocol_slots())
|
||||
.chain(protocols.buffer_protocol_slots())
|
||||
.cloned()
|
||||
.for_each(visitor);
|
||||
}
|
||||
fn get(&'static self) -> &'static pyo3::class::proto_methods::PyProtoMethodDef {
|
||||
&self.def
|
||||
|
||||
fn get_buffer() -> Option<&'static pyo3::class::proto_methods::PyBufferProcs> {
|
||||
use pyo3::class::proto_methods::*;
|
||||
let protocols = PyClassProtocols::<MyClass>::new();
|
||||
protocols.buffer_procs()
|
||||
}
|
||||
}
|
||||
impl pyo3::class::proto_methods::HasProtoInventory for MyClass {
|
||||
type ProtoMethods = Pyo3ProtoInventoryForMyClass;
|
||||
}
|
||||
pyo3::inventory::collect!(Pyo3ProtoInventoryForMyClass);
|
||||
|
||||
|
||||
impl pyo3::pyclass::PyClassSend for MyClass {
|
||||
type ThreadChecker = pyo3::pyclass::ThreadCheckerStub<MyClass>;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,9 +43,10 @@ impl MethodProto {
|
|||
pub(crate) fn impl_method_proto(
|
||||
cls: &syn::Type,
|
||||
sig: &mut syn::Signature,
|
||||
module: &syn::Path,
|
||||
meth: &MethodProto,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let p: syn::Path = syn::parse_str(meth.proto).unwrap();
|
||||
let proto: syn::Path = syn::parse_str(meth.proto).unwrap();
|
||||
|
||||
let mut impl_types = Vec::new();
|
||||
for (i, arg) in meth.args.iter().enumerate() {
|
||||
|
@ -55,8 +56,8 @@ pub(crate) fn impl_method_proto(
|
|||
|
||||
impl_types.push(quote! {type #arg_name = #arg_ty;});
|
||||
|
||||
let type1 = syn::parse_quote! { arg: <#cls as #p<'p>>::#arg_name};
|
||||
let type2 = syn::parse_quote! { arg: Option<<#cls as #p<'p>>::#arg_name>};
|
||||
let type1 = syn::parse_quote! { arg: <#cls as #module::#proto<'p>>::#arg_name};
|
||||
let type2 = syn::parse_quote! { arg: Option<<#cls as #module::#proto<'p>>::#arg_name>};
|
||||
modify_arg_ty(sig, idx, &type1, &type2)?;
|
||||
}
|
||||
|
||||
|
@ -74,14 +75,14 @@ pub(crate) fn impl_method_proto(
|
|||
}
|
||||
};
|
||||
|
||||
sig.output = syn::parse_quote! { -> <#cls as #p<'p>>::Result };
|
||||
sig.output = syn::parse_quote! { -> <#cls as #module::#proto<'p>>::Result };
|
||||
quote! { type Result = #ret_ty; }
|
||||
} else {
|
||||
proc_macro2::TokenStream::new()
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
impl<'p> #p<'p> for #cls {
|
||||
impl<'p> #module::#proto<'p> for #cls {
|
||||
#(#impl_types)*
|
||||
#res_type_def
|
||||
}
|
||||
|
|
|
@ -254,34 +254,6 @@ fn impl_methods_inventory(cls: &syn::Ident) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implement `HasProtoInventory` for the class for lazy protocol initialization.
|
||||
fn impl_proto_inventory(cls: &syn::Ident) -> TokenStream {
|
||||
// Try to build a unique type for better error messages
|
||||
let name = format!("Pyo3ProtoInventoryFor{}", cls);
|
||||
let inventory_cls = syn::Ident::new(&name, Span::call_site());
|
||||
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
pub struct #inventory_cls {
|
||||
def: pyo3::class::proto_methods::PyProtoMethodDef,
|
||||
}
|
||||
impl pyo3::class::proto_methods::PyProtoInventory for #inventory_cls {
|
||||
fn new(def: pyo3::class::proto_methods::PyProtoMethodDef) -> Self {
|
||||
Self { def }
|
||||
}
|
||||
fn get(&'static self) -> &'static pyo3::class::proto_methods::PyProtoMethodDef {
|
||||
&self.def
|
||||
}
|
||||
}
|
||||
|
||||
impl pyo3::class::proto_methods::HasProtoInventory for #cls {
|
||||
type ProtoMethods = #inventory_cls;
|
||||
}
|
||||
|
||||
pyo3::inventory::collect!(#inventory_cls);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_class_python_name<'a>(cls: &'a syn::Ident, attr: &'a PyClassArgs) -> &'a syn::Ident {
|
||||
attr.name.as_ref().unwrap_or(cls)
|
||||
}
|
||||
|
@ -383,7 +355,6 @@ fn impl_class(
|
|||
};
|
||||
|
||||
let impl_inventory = impl_methods_inventory(&cls);
|
||||
let impl_proto_inventory = impl_proto_inventory(&cls);
|
||||
|
||||
let base = &attr.base;
|
||||
let flags = &attr.flags;
|
||||
|
@ -472,7 +443,32 @@ fn impl_class(
|
|||
|
||||
#impl_inventory
|
||||
|
||||
#impl_proto_inventory
|
||||
impl pyo3::class::proto_methods::PyProtoMethods for #cls {
|
||||
fn for_each_proto_slot<Visitor: FnMut(pyo3::ffi::PyType_Slot)>(visitor: Visitor) {
|
||||
// Implementation which uses dtolnay specialization to load all slots.
|
||||
use pyo3::class::proto_methods::*;
|
||||
let protocols = PyClassProtocols::<#cls>::new();
|
||||
protocols.object_protocol_slots()
|
||||
.iter()
|
||||
.chain(protocols.number_protocol_slots())
|
||||
.chain(protocols.iter_protocol_slots())
|
||||
.chain(protocols.gc_protocol_slots())
|
||||
.chain(protocols.descr_protocol_slots())
|
||||
.chain(protocols.mapping_protocol_slots())
|
||||
.chain(protocols.sequence_protocol_slots())
|
||||
.chain(protocols.async_protocol_slots())
|
||||
.chain(protocols.buffer_protocol_slots())
|
||||
.cloned()
|
||||
.for_each(visitor);
|
||||
}
|
||||
|
||||
fn get_buffer() -> Option<&'static pyo3::class::proto_methods::PyBufferProcs> {
|
||||
use pyo3::class::proto_methods::*;
|
||||
let protocols = PyClassProtocols::<#cls>::new();
|
||||
protocols.buffer_procs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#extra
|
||||
|
||||
|
|
|
@ -62,12 +62,13 @@ fn impl_proto_impl(
|
|||
let mut trait_impls = TokenStream::new();
|
||||
let mut py_methods = Vec::new();
|
||||
let mut method_names = HashSet::new();
|
||||
let module = proto.module();
|
||||
|
||||
for iimpl in impls.iter_mut() {
|
||||
if let syn::ImplItem::Method(met) = iimpl {
|
||||
// impl Py~Protocol<'p> { type = ... }
|
||||
if let Some(m) = proto.get_proto(&met.sig.ident) {
|
||||
impl_method_proto(ty, &mut met.sig, m)?.to_tokens(&mut trait_impls);
|
||||
impl_method_proto(ty, &mut met.sig, &module, m)?.to_tokens(&mut trait_impls);
|
||||
// Insert the method to the HashSet
|
||||
method_names.insert(met.sig.ident.to_string());
|
||||
}
|
||||
|
@ -107,7 +108,7 @@ fn impl_proto_impl(
|
|||
}
|
||||
}
|
||||
let normal_methods = submit_normal_methods(py_methods, ty);
|
||||
let protocol_methods = submit_protocol_methods(method_names, ty, proto)?;
|
||||
let protocol_methods = impl_proto_methods(method_names, ty, proto);
|
||||
Ok(quote! {
|
||||
#trait_impls
|
||||
#normal_methods
|
||||
|
@ -129,49 +130,69 @@ fn submit_normal_methods(py_methods: Vec<TokenStream>, ty: &syn::Type) -> TokenS
|
|||
}
|
||||
}
|
||||
|
||||
fn submit_protocol_methods(
|
||||
fn impl_proto_methods(
|
||||
method_names: HashSet<String>,
|
||||
ty: &syn::Type,
|
||||
proto: &defs::Proto,
|
||||
) -> syn::Result<TokenStream> {
|
||||
if proto.extension_trait == "" {
|
||||
return Ok(quote! {});
|
||||
) -> TokenStream {
|
||||
if proto.slots_trait.is_empty() {
|
||||
return TokenStream::default();
|
||||
}
|
||||
let ext_trait: syn::Path = syn::parse_str(proto.extension_trait)?;
|
||||
let mut tokens = vec![];
|
||||
|
||||
let module = proto.module();
|
||||
let slots_trait = syn::Ident::new(proto.slots_trait, Span::call_site());
|
||||
let slots_trait_slots = syn::Ident::new(proto.slots_trait_slots, Span::call_site());
|
||||
|
||||
let mut maybe_buffer_methods = None;
|
||||
if proto.name == "Buffer" {
|
||||
// For buffer, we construct `PyProtoMethods` from PyBufferProcs
|
||||
tokens.push(quote! {
|
||||
let mut proto_methods = pyo3::ffi::PyBufferProcs::default();
|
||||
// On Python 3.9 we have to use PyBufferProcs to set buffer slots.
|
||||
// For now we emit this always for buffer methods, even on 3.9+.
|
||||
// Maybe in the future we can access Py_3_9 here and define it.
|
||||
maybe_buffer_methods = Some(quote! {
|
||||
impl pyo3::class::proto_methods::PyBufferProtocolProcs<#ty>
|
||||
for pyo3::class::proto_methods::PyClassProtocols<#ty>
|
||||
{
|
||||
fn buffer_procs(
|
||||
self
|
||||
) -> Option<&'static pyo3::class::proto_methods::PyBufferProcs> {
|
||||
static PROCS: pyo3::class::proto_methods::PyBufferProcs
|
||||
= pyo3::class::proto_methods::PyBufferProcs {
|
||||
bf_getbuffer: Some(pyo3::class::buffer::getbuffer::<#ty>),
|
||||
bf_releasebuffer: Some(pyo3::class::buffer::releasebuffer::<#ty>),
|
||||
};
|
||||
Some(&PROCS)
|
||||
}
|
||||
}
|
||||
});
|
||||
for getter in proto.slot_getters(method_names) {
|
||||
let get = syn::Ident::new(getter, Span::call_site());
|
||||
let field = syn::Ident::new(&format!("bf_{}", &getter[4..]), Span::call_site());
|
||||
tokens.push(quote! { proto_methods.#field = Some(<#ty as #ext_trait>::#get()); });
|
||||
}
|
||||
} else {
|
||||
// For other protocols, we construct `PyProtoMethods` from Vec<ffi::PyType_Slot>
|
||||
tokens.push(quote! { let mut proto_methods = vec![]; });
|
||||
for getter in proto.slot_getters(method_names) {
|
||||
let get = syn::Ident::new(getter, Span::call_site());
|
||||
tokens.push(quote! {
|
||||
let slot = <#ty as #ext_trait>::#get();
|
||||
proto_methods.push(pyo3::ffi::PyType_Slot { slot: slot.0, pfunc: slot.1 as _ });
|
||||
});
|
||||
}
|
||||
};
|
||||
if tokens.len() <= 1 {
|
||||
return Ok(quote! {});
|
||||
}
|
||||
Ok(quote! {
|
||||
pyo3::inventory::submit! {
|
||||
#![crate = pyo3] {
|
||||
type Inventory =
|
||||
<#ty as pyo3::class::proto_methods::HasProtoInventory>::ProtoMethods;
|
||||
<Inventory as pyo3::class::proto_methods::PyProtoInventory>::new(
|
||||
{ #(#tokens)* proto_methods.into() }
|
||||
)
|
||||
|
||||
let mut tokens = proto
|
||||
.slot_defs(method_names)
|
||||
.map(|def| {
|
||||
let slot = syn::Ident::new(def.slot, Span::call_site());
|
||||
let slot_impl = syn::Ident::new(def.slot_impl, Span::call_site());
|
||||
quote! {{
|
||||
pyo3::ffi::PyType_Slot {
|
||||
slot: pyo3::ffi::#slot,
|
||||
pfunc: #module::#slot_impl::<#ty> as _
|
||||
}
|
||||
}}
|
||||
})
|
||||
.peekable();
|
||||
|
||||
if tokens.peek().is_none() {
|
||||
return TokenStream::default();
|
||||
}
|
||||
|
||||
quote! {
|
||||
#maybe_buffer_methods
|
||||
|
||||
impl pyo3::class::proto_methods::#slots_trait<#ty>
|
||||
for pyo3::class::proto_methods::PyClassProtocols<#ty>
|
||||
{
|
||||
fn #slots_trait_slots(self) -> &'static [pyo3::ffi::PyType_Slot] {
|
||||
&[#(#tokens),*]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
//! Parts of the documentation are copied from the respective methods from the
|
||||
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::{HashCallbackOutput, IntoPyCallbackOutput};
|
||||
use crate::{exceptions, ffi, FromPyObject, PyAny, PyCell, PyClass, PyObject, PyResult};
|
||||
use crate::{exceptions, ffi, FromPyObject, PyAny, PyCell, PyClass, PyObject};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Operators for the __richcmp__ method
|
||||
|
@ -134,150 +133,73 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<PyObject>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
py_unary_func!(str, PyObjectStrProtocol, T::__str__);
|
||||
py_unary_func!(repr, PyObjectReprProtocol, T::__repr__);
|
||||
py_unary_func!(hash, PyObjectHashProtocol, T::__hash__, ffi::Py_hash_t);
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyBasicSlots {
|
||||
fn get_str() -> TypedSlot<ffi::reprfunc>
|
||||
where
|
||||
Self: for<'p> PyObjectStrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_str,
|
||||
py_unary_func!(PyObjectStrProtocol, Self::__str__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_repr() -> TypedSlot<ffi::reprfunc>
|
||||
where
|
||||
Self: for<'p> PyObjectReprProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_repr,
|
||||
py_unary_func!(PyObjectReprProtocol, Self::__repr__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_hash() -> TypedSlot<ffi::hashfunc>
|
||||
where
|
||||
Self: for<'p> PyObjectHashProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_hash,
|
||||
py_unary_func!(PyObjectHashProtocol, Self::__hash__, ffi::Py_hash_t),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_getattr() -> TypedSlot<ffi::getattrofunc>
|
||||
where
|
||||
Self: for<'p> PyObjectGetAttrProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyObjectGetAttrProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
|
||||
// for existing fields and methods first
|
||||
let existing = ffi::PyObject_GenericGetAttr(slf, arg);
|
||||
if existing.is_null() {
|
||||
// PyObject_HasAttr also tries to get an object and clears the error if it fails
|
||||
ffi::PyErr_Clear();
|
||||
} else {
|
||||
return Ok(existing);
|
||||
}
|
||||
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<PyAny>(arg);
|
||||
call_ref!(slf, __getattr__, arg).convert(py)
|
||||
})
|
||||
pub unsafe extern "C" fn getattr<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyObjectGetAttrProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
|
||||
// for existing fields and methods first
|
||||
let existing = ffi::PyObject_GenericGetAttr(slf, arg);
|
||||
if existing.is_null() {
|
||||
// PyObject_HasAttr also tries to get an object and clears the error if it fails
|
||||
ffi::PyErr_Clear();
|
||||
} else {
|
||||
return Ok(existing);
|
||||
}
|
||||
TypedSlot(ffi::Py_tp_getattro, wrap::<Self>)
|
||||
}
|
||||
|
||||
fn get_richcmp() -> TypedSlot<ffi::richcmpfunc>
|
||||
where
|
||||
Self: for<'p> PyObjectRichcmpProtocol<'p>,
|
||||
{
|
||||
fn extract_op(op: c_int) -> PyResult<CompareOp> {
|
||||
match op {
|
||||
ffi::Py_LT => Ok(CompareOp::Lt),
|
||||
ffi::Py_LE => Ok(CompareOp::Le),
|
||||
ffi::Py_EQ => Ok(CompareOp::Eq),
|
||||
ffi::Py_NE => Ok(CompareOp::Ne),
|
||||
ffi::Py_GT => Ok(CompareOp::Gt),
|
||||
ffi::Py_GE => Ok(CompareOp::Ge),
|
||||
_ => Err(exceptions::PyValueError::new_err(
|
||||
"tp_richcompare called with invalid comparison operator",
|
||||
)),
|
||||
}
|
||||
}
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
op: c_int,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyObjectRichcmpProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let arg = extract_or_return_not_implemented!(py, arg);
|
||||
let op = extract_op(op)?;
|
||||
|
||||
slf.try_borrow()?.__richcmp__(arg, op).convert(py)
|
||||
})
|
||||
}
|
||||
TypedSlot(ffi::Py_tp_richcompare, wrap::<Self>)
|
||||
}
|
||||
|
||||
fn get_setattr() -> TypedSlot<ffi::setattrofunc>
|
||||
where
|
||||
Self: for<'p> PyObjectSetAttrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_setattro,
|
||||
py_func_set!(PyObjectSetAttrProtocol, Self::__setattr__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_delattr() -> TypedSlot<ffi::setattrofunc>
|
||||
where
|
||||
Self: for<'p> PyObjectDelAttrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_setattro,
|
||||
py_func_del!(PyObjectDelAttrProtocol, Self::__delattr__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_setdelattr() -> TypedSlot<ffi::setattrofunc>
|
||||
where
|
||||
Self: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_setattro,
|
||||
py_func_set_del!(
|
||||
PyObjectSetAttrProtocol,
|
||||
PyObjectDelAttrProtocol,
|
||||
Self,
|
||||
__setattr__,
|
||||
__delattr__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_bool() -> TypedSlot<ffi::inquiry>
|
||||
where
|
||||
Self: for<'p> PyObjectBoolProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_bool,
|
||||
py_unary_func!(PyObjectBoolProtocol, Self::__bool__, c_int),
|
||||
)
|
||||
}
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<PyAny>(arg);
|
||||
call_ref!(slf, __getattr__, arg).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
impl<'p, T> PyBasicSlots for T where T: PyObjectProtocol<'p> {}
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn richcmp<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
op: c_int,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyObjectRichcmpProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let arg = extract_or_return_not_implemented!(py, arg);
|
||||
let op = match op {
|
||||
ffi::Py_LT => CompareOp::Lt,
|
||||
ffi::Py_LE => CompareOp::Le,
|
||||
ffi::Py_EQ => CompareOp::Eq,
|
||||
ffi::Py_NE => CompareOp::Ne,
|
||||
ffi::Py_GT => CompareOp::Gt,
|
||||
ffi::Py_GE => CompareOp::Ge,
|
||||
_ => {
|
||||
return Err(exceptions::PyValueError::new_err(
|
||||
"tp_richcompare called with invalid comparison operator",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
slf.try_borrow()?.__richcmp__(arg, op).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
py_func_set!(setattr, PyObjectSetAttrProtocol, T::__setattr__);
|
||||
py_func_del!(delattr, PyObjectDelAttrProtocol, T::__delattr__);
|
||||
py_func_set_del!(
|
||||
setdelattr,
|
||||
PyObjectSetAttrProtocol,
|
||||
PyObjectDelAttrProtocol,
|
||||
Self,
|
||||
__setattr__,
|
||||
__delattr__
|
||||
);
|
||||
py_unary_func!(bool, PyObjectBoolProtocol, T::__bool__, c_int);
|
||||
|
|
|
@ -11,22 +11,18 @@ use std::os::raw::c_int;
|
|||
/// Buffer protocol interface
|
||||
///
|
||||
/// For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
|
||||
/// c-api
|
||||
/// c-api.
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyBufferProtocol<'p>: PyClass {
|
||||
// No default implementations so that implementors of this trait provide both methods.
|
||||
|
||||
fn bf_getbuffer(slf: PyRefMut<Self>, view: *mut ffi::Py_buffer, flags: c_int) -> Self::Result
|
||||
where
|
||||
Self: PyBufferGetBufferProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
Self: PyBufferGetBufferProtocol<'p>;
|
||||
|
||||
fn bf_releasebuffer(slf: PyRefMut<Self>, view: *mut ffi::Py_buffer) -> Self::Result
|
||||
where
|
||||
Self: PyBufferReleaseBufferProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
Self: PyBufferReleaseBufferProtocol<'p>;
|
||||
}
|
||||
|
||||
pub trait PyBufferGetBufferProtocol<'p>: PyBufferProtocol<'p> {
|
||||
|
@ -37,46 +33,28 @@ pub trait PyBufferReleaseBufferProtocol<'p>: PyBufferProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<()>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
#[doc(hidden)]
|
||||
pub trait PyBufferSlots {
|
||||
fn get_getbuffer() -> ffi::getbufferproc
|
||||
where
|
||||
Self: for<'p> PyBufferGetBufferProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg1: *mut ffi::Py_buffer,
|
||||
arg2: c_int,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PyBufferGetBufferProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
wrap::<Self>
|
||||
}
|
||||
|
||||
fn get_releasebuffer() -> ffi::releasebufferproc
|
||||
where
|
||||
Self: for<'p> PyBufferReleaseBufferProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject, arg1: *mut ffi::Py_buffer)
|
||||
where
|
||||
T: for<'p> PyBufferReleaseBufferProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
wrap::<Self>
|
||||
}
|
||||
pub unsafe extern "C" fn getbuffer<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg1: *mut ffi::Py_buffer,
|
||||
arg2: c_int,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PyBufferGetBufferProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
impl<'p, T> PyBufferSlots for T where T: PyBufferProtocol<'p> {}
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn releasebuffer<T>(slf: *mut ffi::PyObject, arg1: *mut ffi::Py_buffer)
|
||||
where
|
||||
T: for<'p> PyBufferReleaseBufferProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).convert(py)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
//! [Python information](
|
||||
//! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors)
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, FromPyObject, PyClass, PyObject};
|
||||
use crate::{FromPyObject, PyClass, PyObject};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Descriptor interface
|
||||
|
@ -71,28 +70,5 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<()>;
|
||||
}
|
||||
|
||||
/// Extension trait for our proc-macro backend.
|
||||
#[doc(hidden)]
|
||||
pub trait PyDescrSlots {
|
||||
fn get_descr_get() -> TypedSlot<ffi::descrgetfunc>
|
||||
where
|
||||
Self: for<'p> PyDescrGetProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_descr_get,
|
||||
py_ternarys_func!(PyDescrGetProtocol, Self::__get__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_descr_set() -> TypedSlot<ffi::descrsetfunc>
|
||||
where
|
||||
Self: for<'p> PyDescrSetProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_descr_set,
|
||||
py_ternarys_func!(PyDescrSetProtocol, Self::__set__, c_int),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyDescrSlots for T where T: PyDescrProtocol<'p> {}
|
||||
py_ternarys_func!(descr_get, PyDescrGetProtocol, Self::__get__);
|
||||
py_ternarys_func!(descr_set, PyDescrSetProtocol, Self::__set__, c_int);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//! Python GC support
|
||||
//!
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::{ffi, AsPyPointer, PyCell, PyClass, Python};
|
||||
use std::os::raw::{c_int, c_void};
|
||||
|
||||
|
@ -19,64 +18,46 @@ pub trait PyGCProtocol<'p>: PyClass {
|
|||
pub trait PyGCTraverseProtocol<'p>: PyGCProtocol<'p> {}
|
||||
pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
#[doc(hidden)]
|
||||
pub trait PyGCSlots {
|
||||
fn get_traverse() -> TypedSlot<ffi::traverseproc>
|
||||
where
|
||||
Self: for<'p> PyGCTraverseProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
visit: ffi::visitproc,
|
||||
arg: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PyGCTraverseProtocol<'p>,
|
||||
{
|
||||
let pool = crate::GILPool::new();
|
||||
let py = pool.python();
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
pub unsafe extern "C" fn traverse<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
visit: ffi::visitproc,
|
||||
arg: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PyGCTraverseProtocol<'p>,
|
||||
{
|
||||
let pool = crate::GILPool::new();
|
||||
let py = pool.python();
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
let visit = PyVisit {
|
||||
visit,
|
||||
arg,
|
||||
_py: py,
|
||||
};
|
||||
let borrow = slf.try_borrow();
|
||||
if let Ok(borrow) = borrow {
|
||||
match borrow.__traverse__(visit) {
|
||||
Ok(()) => 0,
|
||||
Err(PyTraverseError(code)) => code,
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
let visit = PyVisit {
|
||||
visit,
|
||||
arg,
|
||||
_py: py,
|
||||
};
|
||||
let borrow = slf.try_borrow();
|
||||
if let Ok(borrow) = borrow {
|
||||
match borrow.__traverse__(visit) {
|
||||
Ok(()) => 0,
|
||||
Err(PyTraverseError(code)) => code,
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_tp_traverse, wrap::<Self>)
|
||||
}
|
||||
|
||||
fn get_clear() -> TypedSlot<ffi::inquiry>
|
||||
where
|
||||
Self: for<'p> PyGCClearProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject) -> c_int
|
||||
where
|
||||
T: for<'p> PyGCClearProtocol<'p>,
|
||||
{
|
||||
let pool = crate::GILPool::new();
|
||||
let slf = pool.python().from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
slf.borrow_mut().__clear__();
|
||||
0
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_tp_clear, wrap::<Self>)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyGCSlots for T where T: PyGCProtocol<'p> {}
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn clear<T>(slf: *mut ffi::PyObject) -> c_int
|
||||
where
|
||||
T: for<'p> PyGCClearProtocol<'p>,
|
||||
{
|
||||
let pool = crate::GILPool::new();
|
||||
let slf = pool.python().from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
slf.borrow_mut().__clear__();
|
||||
0
|
||||
}
|
||||
|
||||
/// Object visitor for GC.
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//! Python Iterator Interface.
|
||||
//! Trait and support implementation for implementing iterators
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::derive_utils::TryFromPyCell;
|
||||
use crate::err::PyResult;
|
||||
|
@ -72,30 +71,8 @@ pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<PyIterNextOutput>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
#[doc(hidden)]
|
||||
pub trait PyIterSlots {
|
||||
fn get_iter() -> TypedSlot<ffi::getiterfunc>
|
||||
where
|
||||
Self: for<'p> PyIterIterProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_iter,
|
||||
py_unarys_func!(PyIterIterProtocol, Self::__iter__),
|
||||
)
|
||||
}
|
||||
fn get_iternext() -> TypedSlot<ffi::iternextfunc>
|
||||
where
|
||||
Self: for<'p> PyIterNextProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_tp_iternext,
|
||||
py_unarys_func!(PyIterNextProtocol, Self::__next__),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyIterSlots for T where T: PyIterProtocol<'p> {}
|
||||
py_unarys_func!(iter, PyIterIterProtocol, Self::__iter__);
|
||||
py_unarys_func!(iternext, PyIterNextProtocol, Self::__next__);
|
||||
|
||||
/// Output of `__next__` which can either `yield` the next value in the iteration, or
|
||||
/// `return` a value to raise `StopIteration` in Python.
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
macro_rules! py_unary_func {
|
||||
($trait: ident, $class:ident :: $f:ident, $call:ident, $ret_type: ty) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident, $call:ident, $ret_type: ty) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
|
@ -11,20 +12,28 @@ macro_rules! py_unary_func {
|
|||
$call!(slf, $f).convert(py)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
// Use call_ref! by default
|
||||
($trait:ident, $class:ident :: $f:ident, $ret_type:ty) => {
|
||||
py_unary_func!($trait, $class::$f, call_ref, $ret_type);
|
||||
};
|
||||
($trait:ident, $class:ident :: $f:ident) => {
|
||||
py_unary_func!($trait, $class::$f, call_ref, *mut $crate::ffi::PyObject);
|
||||
// Use call_ref! by default
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident, $ret_type:ty) => {
|
||||
py_unary_func!($name, $trait, $class::$f, call_ref, $ret_type);
|
||||
};
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
py_unary_func!(
|
||||
$name,
|
||||
$trait,
|
||||
$class::$f,
|
||||
call_ref,
|
||||
*mut $crate::ffi::PyObject
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_unarys_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> *mut $crate::ffi::PyObject
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
|
@ -37,20 +46,23 @@ macro_rules! py_unarys_func {
|
|||
T::$f(borrow).convert(py)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_len_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {
|
||||
py_unary_func!($trait, $class::$f, $crate::ffi::Py_ssize_t)
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
py_unary_func!($name, $trait, $class::$f, $crate::ffi::Py_ssize_t);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_binary_func {
|
||||
// Use call_ref! by default
|
||||
($trait:ident, $class:ident :: $f:ident, $return:ty, $call:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject, arg: *mut ffi::PyObject) -> $return
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident, $return:ty, $call:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
) -> $return
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
|
@ -60,19 +72,19 @@ macro_rules! py_binary_func {
|
|||
$call!(slf, $f, arg).convert(py)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
($trait:ident, $class:ident :: $f:ident, $return:ty) => {
|
||||
py_binary_func!($trait, $class::$f, $return, call_ref)
|
||||
};
|
||||
($trait:ident, $class:ident :: $f:ident) => {
|
||||
py_binary_func!($trait, $class::$f, *mut $crate::ffi::PyObject)
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident, $return:ty) => {
|
||||
py_binary_func!($name, $trait, $class::$f, $return, call_ref);
|
||||
};
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
py_binary_func!($name, $trait, $class::$f, *mut $crate::ffi::PyObject);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_binary_num_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
|
@ -85,13 +97,13 @@ macro_rules! py_binary_num_func {
|
|||
T::$f(lhs.extract()?, rhs).convert(py)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_binary_reversed_num_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
|
@ -105,13 +117,13 @@ macro_rules! py_binary_reversed_num_func {
|
|||
T::$f(&*slf.try_borrow()?, arg).convert(py)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_binary_fallback_num_func {
|
||||
($class:ident, $lop_trait: ident :: $lop: ident, $rop_trait: ident :: $rop: ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $class:ident, $lop_trait: ident :: $lop: ident, $rop_trait: ident :: $rop: ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
|
@ -133,14 +145,14 @@ macro_rules! py_binary_fallback_num_func {
|
|||
}
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE(kngwyu): This macro is used only for inplace operations, so I used call_mut here.
|
||||
macro_rules! py_binary_self_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
|
@ -155,17 +167,17 @@ macro_rules! py_binary_self_func {
|
|||
Ok::<_, $crate::err::PyErr>(slf)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_ssizearg_func {
|
||||
// Use call_ref! by default
|
||||
($trait:ident, $class:ident :: $f:ident) => {
|
||||
py_ssizearg_func!($trait, $class::$f, call_ref)
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
py_ssizearg_func!($name, $trait, $class::$f, call_ref);
|
||||
};
|
||||
($trait:ident, $class:ident :: $f:ident, $call:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident, $call:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
arg: $crate::ffi::Py_ssize_t,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
|
@ -177,13 +189,13 @@ macro_rules! py_ssizearg_func {
|
|||
$call!(slf, $f; arg.into()).convert(py)
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_ternarys_func {
|
||||
($trait:ident, $class:ident :: $f:ident, $return_type:ty) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident, $return_type:ty) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject,
|
||||
|
@ -206,17 +218,16 @@ macro_rules! py_ternarys_func {
|
|||
T::$f(slf, arg1, arg2).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
wrap::<$class>
|
||||
}};
|
||||
($trait:ident, $class:ident :: $f:ident) => {
|
||||
py_ternarys_func!($trait, $class::$f, *mut $crate::ffi::PyObject);
|
||||
};
|
||||
($name:ident, $trait:ident, $class:ident :: $f:ident) => {
|
||||
py_ternarys_func!($name, $trait, $class::$f, *mut $crate::ffi::PyObject);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_func_set {
|
||||
($trait_name:ident, $class:ident :: $fn_set:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait_name:ident, $class:ident :: $fn_set:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
|
@ -239,14 +250,13 @@ macro_rules! py_func_set {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_func_del {
|
||||
($trait_name:ident, $class:ident :: $fn_del:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait_name:ident, $class:ident :: $fn_del:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
|
@ -268,14 +278,13 @@ macro_rules! py_func_del {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_func_set_del {
|
||||
($trait1:ident, $trait2:ident, $class:ident, $fn_set:ident, $fn_del:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
($name:ident, $trait1:ident, $trait2:ident, $class:ident, $fn_set:ident, $fn_del:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn $name<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
|
@ -295,8 +304,7 @@ macro_rules! py_func_set_del {
|
|||
}
|
||||
})
|
||||
}
|
||||
wrap::<$class>
|
||||
}};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! extract_or_return_not_implemented {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//! Python Mapping Interface
|
||||
//! Trait and support implementation for implementing mapping support
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::{exceptions, ffi, FromPyObject, PyClass, PyObject};
|
||||
|
||||
|
@ -73,64 +72,15 @@ pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<PyObject>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
#[doc(hidden)]
|
||||
pub trait PyMappingSlots {
|
||||
fn get_len() -> TypedSlot<ffi::lenfunc>
|
||||
where
|
||||
Self: for<'p> PyMappingLenProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_mp_length,
|
||||
py_len_func!(PyMappingLenProtocol, Self::__len__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_getitem() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyMappingGetItemProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_mp_subscript,
|
||||
py_binary_func!(PyMappingGetItemProtocol, Self::__getitem__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_setitem() -> TypedSlot<ffi::objobjargproc>
|
||||
where
|
||||
Self: for<'p> PyMappingSetItemProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_mp_ass_subscript,
|
||||
py_func_set!(PyMappingSetItemProtocol, Self::__setitem__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_delitem() -> TypedSlot<ffi::objobjargproc>
|
||||
where
|
||||
Self: for<'p> PyMappingDelItemProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_mp_ass_subscript,
|
||||
py_func_del!(PyMappingDelItemProtocol, Self::__delitem__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_setdelitem() -> TypedSlot<ffi::objobjargproc>
|
||||
where
|
||||
Self: for<'p> PyMappingSetItemProtocol<'p> + for<'p> PyMappingDelItemProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_mp_ass_subscript,
|
||||
py_func_set_del!(
|
||||
PyMappingSetItemProtocol,
|
||||
PyMappingDelItemProtocol,
|
||||
Self,
|
||||
__setitem__,
|
||||
__delitem__
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyMappingSlots for T where T: PyMappingProtocol<'p> {}
|
||||
py_len_func!(len, PyMappingLenProtocol, Self::__len__);
|
||||
py_binary_func!(getitem, PyMappingGetItemProtocol, Self::__getitem__);
|
||||
py_func_set!(setitem, PyMappingSetItemProtocol, Self::__setitem__);
|
||||
py_func_del!(delitem, PyMappingDelItemProtocol, Self::__delitem__);
|
||||
py_func_set_del!(
|
||||
setdelitem,
|
||||
PyMappingSetItemProtocol,
|
||||
PyMappingDelItemProtocol,
|
||||
Self,
|
||||
__setitem__,
|
||||
__delitem__
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ pub mod mapping;
|
|||
#[doc(hidden)]
|
||||
pub mod methods;
|
||||
pub mod number;
|
||||
#[doc(hidden)]
|
||||
pub mod proto_methods;
|
||||
pub mod pyasync;
|
||||
pub mod sequence;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
//! Python Number Interface
|
||||
//! Trait and support implementation for implementing number protocol
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::err::PyErr;
|
||||
use crate::{ffi, FromPyObject, PyClass, PyObject};
|
||||
|
@ -579,721 +578,202 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<PyObject>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
py_binary_fallback_num_func!(
|
||||
add_radd,
|
||||
T,
|
||||
PyNumberAddProtocol::__add__,
|
||||
PyNumberRAddProtocol::__radd__
|
||||
);
|
||||
py_binary_num_func!(add, PyNumberAddProtocol, T::__add__);
|
||||
py_binary_reversed_num_func!(radd, PyNumberRAddProtocol, T::__radd__);
|
||||
py_binary_fallback_num_func!(
|
||||
sub_rsub,
|
||||
T,
|
||||
PyNumberSubProtocol::__sub__,
|
||||
PyNumberRSubProtocol::__rsub__
|
||||
);
|
||||
py_binary_num_func!(sub, PyNumberSubProtocol, T::__sub__);
|
||||
py_binary_reversed_num_func!(rsub, PyNumberRSubProtocol, T::__rsub__);
|
||||
py_binary_fallback_num_func!(
|
||||
mul_rmul,
|
||||
T,
|
||||
PyNumberMulProtocol::__mul__,
|
||||
PyNumberRMulProtocol::__rmul__
|
||||
);
|
||||
py_binary_num_func!(mul, PyNumberMulProtocol, T::__mul__);
|
||||
py_binary_reversed_num_func!(rmul, PyNumberRMulProtocol, T::__rmul__);
|
||||
py_binary_num_func!(mod_, PyNumberModProtocol, T::__mod__);
|
||||
py_binary_fallback_num_func!(
|
||||
divmod_rdivmod,
|
||||
T,
|
||||
PyNumberDivmodProtocol::__divmod__,
|
||||
PyNumberRDivmodProtocol::__rdivmod__
|
||||
);
|
||||
py_binary_num_func!(divmod, PyNumberDivmodProtocol, T::__divmod__);
|
||||
py_binary_reversed_num_func!(rdivmod, PyNumberRDivmodProtocol, T::__rdivmod__);
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberSlots {
|
||||
fn get_add_radd() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberAddProtocol<'p> + for<'p> PyNumberRAddProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_add,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberAddProtocol::__add__,
|
||||
PyNumberRAddProtocol::__radd__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_add() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberAddProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_add,
|
||||
py_binary_num_func!(PyNumberAddProtocol, Self::__add__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_radd() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRAddProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_add,
|
||||
py_binary_reversed_num_func!(PyNumberRAddProtocol, Self::__radd__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_sub_rsub() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberSubProtocol<'p> + for<'p> PyNumberRSubProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_subtract,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberSubProtocol::__sub__,
|
||||
PyNumberRSubProtocol::__rsub__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_sub() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberSubProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_subtract,
|
||||
py_binary_num_func!(PyNumberSubProtocol, Self::__sub__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rsub() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRSubProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_subtract,
|
||||
py_binary_reversed_num_func!(PyNumberRSubProtocol, Self::__rsub__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_mul_rmul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberMulProtocol<'p> + for<'p> PyNumberRMulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_multiply,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberMulProtocol::__mul__,
|
||||
PyNumberRMulProtocol::__rmul__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_mul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberMulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_multiply,
|
||||
py_binary_num_func!(PyNumberMulProtocol, Self::__mul__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rmul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRMulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_multiply,
|
||||
py_binary_reversed_num_func!(PyNumberRMulProtocol, Self::__rmul__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_mod() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberModProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_remainder,
|
||||
py_binary_num_func!(PyNumberModProtocol, Self::__mod__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_divmod_rdivmod() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberDivmodProtocol<'p> + for<'p> PyNumberRDivmodProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_divmod,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberDivmodProtocol::__divmod__,
|
||||
PyNumberRDivmodProtocol::__rdivmod__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_divmod() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberDivmodProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_divmod,
|
||||
py_binary_num_func!(PyNumberDivmodProtocol, Self::__divmod__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rdivmod() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRDivmodProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_divmod,
|
||||
py_binary_reversed_num_func!(PyNumberRDivmodProtocol, Self::__rdivmod__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_pow_rpow() -> TypedSlot<ffi::ternaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberPowProtocol<'p> + for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap_pow_and_rpow<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberPowProtocol<'p> + for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let lhs = py.from_borrowed_ptr::<crate::PyAny>(lhs);
|
||||
let rhs = py.from_borrowed_ptr::<crate::PyAny>(rhs);
|
||||
let modulo = py.from_borrowed_ptr::<crate::PyAny>(modulo);
|
||||
// First, try __pow__
|
||||
match (lhs.extract(), rhs.extract(), modulo.extract()) {
|
||||
(Ok(l), Ok(r), Ok(m)) => T::__pow__(l, r, m).convert(py),
|
||||
_ => {
|
||||
// Then try __rpow__
|
||||
let slf: &crate::PyCell<T> = extract_or_return_not_implemented!(rhs);
|
||||
let arg = extract_or_return_not_implemented!(lhs);
|
||||
let modulo = extract_or_return_not_implemented!(modulo);
|
||||
slf.try_borrow()?.__rpow__(arg, modulo).convert(py)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_nb_power, wrap_pow_and_rpow::<Self>)
|
||||
}
|
||||
|
||||
fn get_pow() -> TypedSlot<ffi::ternaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberPowProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap_pow<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let lhs = extract_or_return_not_implemented!(py, lhs);
|
||||
let rhs = extract_or_return_not_implemented!(py, rhs);
|
||||
let modulo = extract_or_return_not_implemented!(py, modulo);
|
||||
T::__pow__(lhs, rhs, modulo).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_nb_power, wrap_pow::<Self>)
|
||||
}
|
||||
|
||||
fn get_rpow() -> TypedSlot<ffi::ternaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap_rpow<T>(
|
||||
arg: *mut ffi::PyObject,
|
||||
slf: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf: &crate::PyCell<T> = extract_or_return_not_implemented!(py, slf);
|
||||
let arg = extract_or_return_not_implemented!(py, arg);
|
||||
let modulo = extract_or_return_not_implemented!(py, modulo);
|
||||
pub unsafe extern "C" fn pow_rpow<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberPowProtocol<'p> + for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let lhs = py.from_borrowed_ptr::<crate::PyAny>(lhs);
|
||||
let rhs = py.from_borrowed_ptr::<crate::PyAny>(rhs);
|
||||
let modulo = py.from_borrowed_ptr::<crate::PyAny>(modulo);
|
||||
// First, try __pow__
|
||||
match (lhs.extract(), rhs.extract(), modulo.extract()) {
|
||||
(Ok(l), Ok(r), Ok(m)) => T::__pow__(l, r, m).convert(py),
|
||||
_ => {
|
||||
// Then try __rpow__
|
||||
let slf: &crate::PyCell<T> = extract_or_return_not_implemented!(rhs);
|
||||
let arg = extract_or_return_not_implemented!(lhs);
|
||||
let modulo = extract_or_return_not_implemented!(modulo);
|
||||
slf.try_borrow()?.__rpow__(arg, modulo).convert(py)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_nb_power, wrap_rpow::<Self>)
|
||||
}
|
||||
|
||||
fn get_neg() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberNegProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_negative,
|
||||
py_unary_func!(PyNumberNegProtocol, Self::__neg__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_pos() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberPosProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_positive,
|
||||
py_unary_func!(PyNumberPosProtocol, Self::__pos__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_abs() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberAbsProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_absolute,
|
||||
py_unary_func!(PyNumberAbsProtocol, Self::__abs__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_invert() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberInvertProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_invert,
|
||||
py_unary_func!(PyNumberInvertProtocol, Self::__invert__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_lshift_rlshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberLShiftProtocol<'p> + for<'p> PyNumberRLShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_lshift,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberLShiftProtocol::__lshift__,
|
||||
PyNumberRLShiftProtocol::__rlshift__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_lshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberLShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_lshift,
|
||||
py_binary_num_func!(PyNumberLShiftProtocol, Self::__lshift__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rlshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRLShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_lshift,
|
||||
py_binary_reversed_num_func!(PyNumberRLShiftProtocol, Self::__rlshift__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rshift_rrshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRShiftProtocol<'p> + for<'p> PyNumberRRShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_rshift,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberRShiftProtocol::__rshift__,
|
||||
PyNumberRRShiftProtocol::__rrshift__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_rshift,
|
||||
py_binary_num_func!(PyNumberRShiftProtocol, Self::__rshift__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rrshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRRShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_rshift,
|
||||
py_binary_reversed_num_func!(PyNumberRRShiftProtocol, Self::__rrshift__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_and_rand() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberAndProtocol<'p> + for<'p> PyNumberRAndProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_and,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberAndProtocol::__and__,
|
||||
PyNumberRAndProtocol::__rand__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_and() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberAndProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_and,
|
||||
py_binary_num_func!(PyNumberAndProtocol, Self::__and__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rand() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRAndProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_and,
|
||||
py_binary_reversed_num_func!(PyNumberRAndProtocol, Self::__rand__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_xor_rxor() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberXorProtocol<'p> + for<'p> PyNumberRXorProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_xor,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberXorProtocol::__xor__,
|
||||
PyNumberRXorProtocol::__rxor__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_xor() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberXorProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_xor,
|
||||
py_binary_num_func!(PyNumberXorProtocol, Self::__xor__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rxor() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRXorProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_xor,
|
||||
py_binary_reversed_num_func!(PyNumberRXorProtocol, Self::__rxor__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_or_ror() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberOrProtocol<'p> + for<'p> PyNumberROrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_or,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberOrProtocol::__or__,
|
||||
PyNumberROrProtocol::__ror__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_or() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberOrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_or,
|
||||
py_binary_num_func!(PyNumberOrProtocol, Self::__or__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_ror() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberROrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_or,
|
||||
py_binary_reversed_num_func!(PyNumberROrProtocol, Self::__ror__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_int() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIntProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_int,
|
||||
py_unary_func!(PyNumberIntProtocol, Self::__int__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_float() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberFloatProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_float,
|
||||
py_unary_func!(PyNumberFloatProtocol, Self::__float__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_iadd() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIAddProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_add,
|
||||
py_binary_self_func!(PyNumberIAddProtocol, Self::__iadd__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_isub() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberISubProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_subtract,
|
||||
py_binary_self_func!(PyNumberISubProtocol, Self::__isub__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_imul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIMulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_multiply,
|
||||
py_binary_self_func!(PyNumberIMulProtocol, Self::__imul__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_imod() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIModProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_remainder,
|
||||
py_binary_self_func!(PyNumberIModProtocol, Self::__imod__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_ipow() -> TypedSlot<ffi::ternaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
// NOTE: Somehow __ipow__ causes SIGSEGV in Python < 3.8 when we extract,
|
||||
// so we ignore it. It's the same as what CPython does.
|
||||
unsafe extern "C" fn wrap_ipow<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
other: *mut ffi::PyObject,
|
||||
_modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf_cell = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let other = py.from_borrowed_ptr::<crate::PyAny>(other);
|
||||
call_operator_mut!(py, slf_cell, __ipow__, other).convert(py)?;
|
||||
ffi::Py_INCREF(slf);
|
||||
Ok::<_, PyErr>(slf)
|
||||
})
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_nb_inplace_power, wrap_ipow::<Self>)
|
||||
}
|
||||
|
||||
fn get_ilshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberILShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_lshift,
|
||||
py_binary_self_func!(PyNumberILShiftProtocol, Self::__ilshift__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_irshift() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIRShiftProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_rshift,
|
||||
py_binary_self_func!(PyNumberIRShiftProtocol, Self::__irshift__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_iand() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIAndProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_and,
|
||||
py_binary_self_func!(PyNumberIAndProtocol, Self::__iand__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_ixor() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIXorProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_xor,
|
||||
py_binary_self_func!(PyNumberIXorProtocol, Self::__ixor__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_ior() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIOrProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_or,
|
||||
py_binary_self_func!(PyNumberIOrProtocol, Self::__ior__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_floordiv_rfloordiv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberFloordivProtocol<'p> + for<'p> PyNumberRFloordivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_floor_divide,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberFloordivProtocol::__floordiv__,
|
||||
PyNumberRFloordivProtocol::__rfloordiv__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_floordiv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberFloordivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_floor_divide,
|
||||
py_binary_num_func!(PyNumberFloordivProtocol, Self::__floordiv__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rfloordiv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRFloordivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_floor_divide,
|
||||
py_binary_reversed_num_func!(PyNumberRFloordivProtocol, Self::__rfloordiv__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_truediv_rtruediv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberTruedivProtocol<'p> + for<'p> PyNumberRTruedivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_true_divide,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberTruedivProtocol::__truediv__,
|
||||
PyNumberRTruedivProtocol::__rtruediv__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_truediv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberTruedivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_true_divide,
|
||||
py_binary_num_func!(PyNumberTruedivProtocol, Self::__truediv__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rtruediv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRTruedivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_true_divide,
|
||||
py_binary_reversed_num_func!(PyNumberRTruedivProtocol, Self::__rtruediv__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_ifloordiv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIFloordivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_floor_divide,
|
||||
py_binary_self_func!(PyNumberIFloordivProtocol, Self::__ifloordiv__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_itruediv() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberITruedivProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_true_divide,
|
||||
py_binary_self_func!(PyNumberITruedivProtocol, Self::__itruediv__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_index() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIndexProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_index,
|
||||
py_unary_func!(PyNumberIndexProtocol, Self::__index__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_matmul_rmatmul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberMatmulProtocol<'p> + for<'p> PyNumberRMatmulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_matrix_multiply,
|
||||
py_binary_fallback_num_func!(
|
||||
Self,
|
||||
PyNumberMatmulProtocol::__matmul__,
|
||||
PyNumberRMatmulProtocol::__rmatmul__
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_matmul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberMatmulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_matrix_multiply,
|
||||
py_binary_num_func!(PyNumberMatmulProtocol, Self::__matmul__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_rmatmul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberRMatmulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_matrix_multiply,
|
||||
py_binary_reversed_num_func!(PyNumberRMatmulProtocol, Self::__rmatmul__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_imatmul() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PyNumberIMatmulProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_nb_inplace_matrix_multiply,
|
||||
py_binary_self_func!(PyNumberIMatmulProtocol, Self::__imatmul__),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberSlots for T where T: PyNumberProtocol<'p> {}
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn pow<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let lhs = extract_or_return_not_implemented!(py, lhs);
|
||||
let rhs = extract_or_return_not_implemented!(py, rhs);
|
||||
let modulo = extract_or_return_not_implemented!(py, modulo);
|
||||
T::__pow__(lhs, rhs, modulo).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn rpow<T>(
|
||||
arg: *mut ffi::PyObject,
|
||||
slf: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf: &crate::PyCell<T> = extract_or_return_not_implemented!(py, slf);
|
||||
let arg = extract_or_return_not_implemented!(py, arg);
|
||||
let modulo = extract_or_return_not_implemented!(py, modulo);
|
||||
slf.try_borrow()?.__rpow__(arg, modulo).convert(py)
|
||||
})
|
||||
}
|
||||
|
||||
py_unary_func!(neg, PyNumberNegProtocol, T::__neg__);
|
||||
py_unary_func!(pos, PyNumberPosProtocol, T::__pos__);
|
||||
py_unary_func!(abs, PyNumberAbsProtocol, T::__abs__);
|
||||
py_unary_func!(invert, PyNumberInvertProtocol, T::__invert__);
|
||||
py_binary_fallback_num_func!(
|
||||
lshift_rlshift,
|
||||
T,
|
||||
PyNumberLShiftProtocol::__lshift__,
|
||||
PyNumberRLShiftProtocol::__rlshift__
|
||||
);
|
||||
py_binary_num_func!(lshift, PyNumberLShiftProtocol, T::__lshift__);
|
||||
py_binary_reversed_num_func!(rlshift, PyNumberRLShiftProtocol, T::__rlshift__);
|
||||
py_binary_fallback_num_func!(
|
||||
rshift_rrshift,
|
||||
T,
|
||||
PyNumberRShiftProtocol::__rshift__,
|
||||
PyNumberRRShiftProtocol::__rrshift__
|
||||
);
|
||||
py_binary_num_func!(rshift, PyNumberRShiftProtocol, T::__rshift__);
|
||||
py_binary_reversed_num_func!(rrshift, PyNumberRRShiftProtocol, T::__rrshift__);
|
||||
py_binary_fallback_num_func!(
|
||||
and_rand,
|
||||
T,
|
||||
PyNumberAndProtocol::__and__,
|
||||
PyNumberRAndProtocol::__rand__
|
||||
);
|
||||
py_binary_num_func!(and, PyNumberAndProtocol, T::__and__);
|
||||
py_binary_reversed_num_func!(rand, PyNumberRAndProtocol, T::__rand__);
|
||||
py_binary_fallback_num_func!(
|
||||
xor_rxor,
|
||||
T,
|
||||
PyNumberXorProtocol::__xor__,
|
||||
PyNumberRXorProtocol::__rxor__
|
||||
);
|
||||
py_binary_num_func!(xor, PyNumberXorProtocol, T::__xor__);
|
||||
py_binary_reversed_num_func!(rxor, PyNumberRXorProtocol, T::__rxor__);
|
||||
py_binary_fallback_num_func!(
|
||||
or_ror,
|
||||
T,
|
||||
PyNumberOrProtocol::__or__,
|
||||
PyNumberROrProtocol::__ror__
|
||||
);
|
||||
py_binary_num_func!(or, PyNumberOrProtocol, T::__or__);
|
||||
py_binary_reversed_num_func!(ror, PyNumberROrProtocol, T::__ror__);
|
||||
py_unary_func!(int, PyNumberIntProtocol, T::__int__);
|
||||
py_unary_func!(float, PyNumberFloatProtocol, T::__float__);
|
||||
py_binary_self_func!(iadd, PyNumberIAddProtocol, T::__iadd__);
|
||||
py_binary_self_func!(isub, PyNumberISubProtocol, T::__isub__);
|
||||
py_binary_self_func!(imul, PyNumberIMulProtocol, T::__imul__);
|
||||
py_binary_self_func!(imod, PyNumberIModProtocol, T::__imod__);
|
||||
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn ipow<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
other: *mut ffi::PyObject,
|
||||
_modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
// NOTE: Somehow __ipow__ causes SIGSEGV in Python < 3.8 when we extract,
|
||||
// so we ignore it. It's the same as what CPython does.
|
||||
crate::callback_body!(py, {
|
||||
let slf_cell = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let other = py.from_borrowed_ptr::<crate::PyAny>(other);
|
||||
call_operator_mut!(py, slf_cell, __ipow__, other).convert(py)?;
|
||||
ffi::Py_INCREF(slf);
|
||||
Ok::<_, PyErr>(slf)
|
||||
})
|
||||
}
|
||||
|
||||
py_binary_self_func!(ilshift, PyNumberILShiftProtocol, T::__ilshift__);
|
||||
py_binary_self_func!(irshift, PyNumberIRShiftProtocol, T::__irshift__);
|
||||
py_binary_self_func!(iand, PyNumberIAndProtocol, T::__iand__);
|
||||
py_binary_self_func!(ixor, PyNumberIXorProtocol, T::__ixor__);
|
||||
py_binary_self_func!(ior, PyNumberIOrProtocol, T::__ior__);
|
||||
py_binary_fallback_num_func!(
|
||||
floordiv_rfloordiv,
|
||||
T,
|
||||
PyNumberFloordivProtocol::__floordiv__,
|
||||
PyNumberRFloordivProtocol::__rfloordiv__
|
||||
);
|
||||
py_binary_num_func!(floordiv, PyNumberFloordivProtocol, T::__floordiv__);
|
||||
py_binary_reversed_num_func!(rfloordiv, PyNumberRFloordivProtocol, T::__rfloordiv__);
|
||||
py_binary_fallback_num_func!(
|
||||
truediv_rtruediv,
|
||||
T,
|
||||
PyNumberTruedivProtocol::__truediv__,
|
||||
PyNumberRTruedivProtocol::__rtruediv__
|
||||
);
|
||||
py_binary_num_func!(truediv, PyNumberTruedivProtocol, T::__truediv__);
|
||||
py_binary_reversed_num_func!(rtruediv, PyNumberRTruedivProtocol, T::__rtruediv__);
|
||||
py_binary_self_func!(ifloordiv, PyNumberIFloordivProtocol, T::__ifloordiv__);
|
||||
py_binary_self_func!(itruediv, PyNumberITruedivProtocol, T::__itruediv__);
|
||||
py_unary_func!(index, PyNumberIndexProtocol, T::__index__);
|
||||
py_binary_fallback_num_func!(
|
||||
matmul_rmatmul,
|
||||
T,
|
||||
PyNumberMatmulProtocol::__matmul__,
|
||||
PyNumberRMatmulProtocol::__rmatmul__
|
||||
);
|
||||
py_binary_num_func!(matmul, PyNumberMatmulProtocol, T::__matmul__);
|
||||
py_binary_reversed_num_func!(rmatmul, PyNumberRMatmulProtocol, T::__rmatmul__);
|
||||
py_binary_self_func!(imatmul, PyNumberIMatmulProtocol, T::__imatmul__);
|
||||
|
|
|
@ -1,78 +1,147 @@
|
|||
use crate::ffi;
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
use crate::ffi::PyBufferProcs;
|
||||
|
||||
/// ABI3 doesn't have buffer APIs, so here we define the empty one.
|
||||
#[cfg(Py_LIMITED_API)]
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone)]
|
||||
pub struct PyBufferProcs;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
// Note(kngwyu): default implementations are for rust-numpy. Please don't remove them.
|
||||
pub trait PyProtoMethods {
|
||||
fn get_type_slots() -> Vec<ffi::PyType_Slot> {
|
||||
vec![]
|
||||
}
|
||||
fn get_buffer() -> Option<PyBufferProcs> {
|
||||
fn for_each_proto_slot<Visitor: FnMut(ffi::PyType_Slot)>(_visitor: Visitor) {}
|
||||
fn get_buffer() -> Option<&'static PyBufferProcs> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed version of `ffi::PyType_Slot`
|
||||
#[doc(hidden)]
|
||||
pub struct TypedSlot<T: Sized>(pub std::os::raw::c_int, pub T);
|
||||
pub struct PyClassProtocols<T>(PhantomData<T>);
|
||||
|
||||
#[doc(hidden)]
|
||||
pub enum PyProtoMethodDef {
|
||||
Slots(Vec<ffi::PyType_Slot>),
|
||||
Buffer(PyBufferProcs),
|
||||
}
|
||||
|
||||
impl From<Vec<ffi::PyType_Slot>> for PyProtoMethodDef {
|
||||
fn from(slots: Vec<ffi::PyType_Slot>) -> Self {
|
||||
PyProtoMethodDef::Slots(slots)
|
||||
impl<T> PyClassProtocols<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PyBufferProcs> for PyProtoMethodDef {
|
||||
fn from(buffer_procs: PyBufferProcs) -> Self {
|
||||
PyProtoMethodDef::Buffer(buffer_procs)
|
||||
impl<T> Default for PyClassProtocols<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "macros")]
|
||||
pub trait PyProtoInventory: inventory::Collect {
|
||||
fn new(methods: PyProtoMethodDef) -> Self;
|
||||
fn get(&'static self) -> &'static PyProtoMethodDef;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "macros")]
|
||||
pub trait HasProtoInventory {
|
||||
type ProtoMethods: PyProtoInventory;
|
||||
}
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
impl<T: HasProtoInventory> PyProtoMethods for T {
|
||||
fn get_type_slots() -> Vec<ffi::PyType_Slot> {
|
||||
inventory::iter::<T::ProtoMethods>
|
||||
.into_iter()
|
||||
.filter_map(|def| match def.get() {
|
||||
PyProtoMethodDef::Slots(slots) => Some(slots),
|
||||
PyProtoMethodDef::Buffer(_) => None,
|
||||
})
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_buffer() -> Option<PyBufferProcs> {
|
||||
inventory::iter::<T::ProtoMethods>
|
||||
.into_iter()
|
||||
.find_map(|def| match def.get() {
|
||||
PyProtoMethodDef::Slots(_) => None,
|
||||
PyProtoMethodDef::Buffer(buf) => Some(buf.clone()),
|
||||
})
|
||||
impl<T> Clone for PyClassProtocols<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Copy for PyClassProtocols<T> {}
|
||||
|
||||
// All traits describing slots, as well as the fallback implementations for unimplemented protos
|
||||
//
|
||||
// Protos which are implented use dtolnay specialization to implement for PyClassProtocols<T>.
|
||||
//
|
||||
// See https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md
|
||||
|
||||
pub trait PyObjectProtocolSlots<T> {
|
||||
fn object_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyObjectProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn object_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyDescrProtocolSlots<T> {
|
||||
fn descr_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyDescrProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn descr_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyGCProtocolSlots<T> {
|
||||
fn gc_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyGCProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn gc_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyIterProtocolSlots<T> {
|
||||
fn iter_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyIterProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn iter_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyMappingProtocolSlots<T> {
|
||||
fn mapping_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyMappingProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn mapping_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyNumberProtocolSlots<T> {
|
||||
fn number_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyNumberProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn number_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyAsyncProtocolSlots<T> {
|
||||
fn async_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyAsyncProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn async_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PySequenceProtocolSlots<T> {
|
||||
fn sequence_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PySequenceProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn sequence_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyBufferProtocolSlots<T> {
|
||||
fn buffer_protocol_slots(self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
impl<T> PyBufferProtocolSlots<T> for &'_ PyClassProtocols<T> {
|
||||
fn buffer_protocol_slots(self) -> &'static [ffi::PyType_Slot] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
// On Python < 3.9 setting the buffer protocol using slots doesn't work, so these procs are used
|
||||
// on those versions to set the slots manually (on the limited API).
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub use ffi::PyBufferProcs;
|
||||
|
||||
#[cfg(Py_LIMITED_API)]
|
||||
pub struct PyBufferProcs;
|
||||
|
||||
pub trait PyBufferProtocolProcs<T> {
|
||||
fn buffer_procs(self) -> Option<&'static PyBufferProcs>;
|
||||
}
|
||||
|
||||
impl<T> PyBufferProtocolProcs<T> for &'_ PyClassProtocols<T> {
|
||||
fn buffer_procs(self) -> Option<&'static PyBufferProcs> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)
|
||||
//!
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::derive_utils::TryFromPyCell;
|
||||
use crate::err::PyResult;
|
||||
|
@ -86,41 +85,9 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
|
|||
type Result: IntoPyCallbackOutput<PyObject>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
#[doc(hidden)]
|
||||
pub trait PyAsyncSlots {
|
||||
fn get_await() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyAsyncAwaitProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_am_await,
|
||||
py_unarys_func!(PyAsyncAwaitProtocol, Self::__await__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_aiter() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyAsyncAiterProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_am_aiter,
|
||||
py_unarys_func!(PyAsyncAiterProtocol, Self::__aiter__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_anext() -> TypedSlot<ffi::unaryfunc>
|
||||
where
|
||||
Self: for<'p> PyAsyncAnextProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_am_anext,
|
||||
py_unarys_func!(PyAsyncAnextProtocol, Self::__anext__),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncSlots for T where T: PyAsyncProtocol<'p> {}
|
||||
py_unarys_func!(await_, PyAsyncAwaitProtocol, Self::__await__);
|
||||
py_unarys_func!(aiter, PyAsyncAiterProtocol, Self::__aiter__);
|
||||
py_unarys_func!(anext, PyAsyncAnextProtocol, Self::__anext__);
|
||||
|
||||
/// Output of `__anext__`.
|
||||
pub enum IterANextOutput<T, U> {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//! Python Sequence Interface
|
||||
//! Trait and support implementation for implementing sequence
|
||||
|
||||
use super::proto_methods::TypedSlot;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::conversion::{FromPyObject, IntoPy};
|
||||
use crate::err::PyErr;
|
||||
|
@ -129,177 +128,99 @@ pub trait PySequenceInplaceRepeatProtocol<'p>:
|
|||
type Result: IntoPyCallbackOutput<Self>;
|
||||
}
|
||||
|
||||
/// Extension trait for proc-macro backend.
|
||||
py_len_func!(len, PySequenceLenProtocol, Self::__len__);
|
||||
py_binary_func!(concat, PySequenceConcatProtocol, Self::__concat__);
|
||||
py_ssizearg_func!(repeat, PySequenceRepeatProtocol, Self::__repeat__);
|
||||
py_ssizearg_func!(getitem, PySequenceGetItemProtocol, Self::__getitem__);
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PySequenceSlots {
|
||||
fn get_len() -> TypedSlot<ffi::lenfunc>
|
||||
where
|
||||
Self: for<'p> PySequenceLenProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_length,
|
||||
py_len_func!(PySequenceLenProtocol, Self::__len__),
|
||||
)
|
||||
}
|
||||
pub unsafe extern "C" fn setitem<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
fn get_concat() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PySequenceConcatProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_concat,
|
||||
py_binary_func!(PySequenceConcatProtocol, Self::__concat__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_repeat() -> TypedSlot<ffi::ssizeargfunc>
|
||||
where
|
||||
Self: for<'p> PySequenceRepeatProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_repeat,
|
||||
py_ssizearg_func!(PySequenceRepeatProtocol, Self::__repeat__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_getitem() -> TypedSlot<ffi::ssizeargfunc>
|
||||
where
|
||||
Self: for<'p> PySequenceGetItemProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_item,
|
||||
py_ssizearg_func!(PySequenceGetItemProtocol, Self::__getitem__),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_setitem() -> TypedSlot<ffi::ssizeobjargproc>
|
||||
where
|
||||
Self: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
return Err(exceptions::PyNotImplementedError::new_err(format!(
|
||||
"Item deletion is not supported by {:?}",
|
||||
stringify!(T)
|
||||
)));
|
||||
}
|
||||
|
||||
let mut slf = slf.try_borrow_mut()?;
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let value = value.extract()?;
|
||||
crate::callback::convert(py, slf.__setitem__(key.into(), value))
|
||||
})
|
||||
if value.is_null() {
|
||||
return Err(exceptions::PyNotImplementedError::new_err(format!(
|
||||
"Item deletion is not supported by {:?}",
|
||||
stringify!(T)
|
||||
)));
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_sq_ass_item, wrap::<Self>)
|
||||
}
|
||||
|
||||
fn get_delitem() -> TypedSlot<ffi::ssizeobjargproc>
|
||||
where
|
||||
Self: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
crate::callback::convert(py, slf.borrow_mut().__delitem__(key.into()))
|
||||
} else {
|
||||
Err(PyErr::new::<exceptions::PyNotImplementedError, _>(format!(
|
||||
"Item assignment not supported by {:?}",
|
||||
stringify!(T)
|
||||
)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_sq_ass_item, wrap::<Self>)
|
||||
}
|
||||
|
||||
fn get_setdelitem() -> TypedSlot<ffi::ssizeobjargproc>
|
||||
where
|
||||
Self: for<'p> PySequenceDelItemProtocol<'p> + for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
call_mut!(slf, __delitem__; key.into()).convert(py)
|
||||
} else {
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let mut slf_ = slf.try_borrow_mut()?;
|
||||
let value = value.extract()?;
|
||||
slf_.__setitem__(key.into(), value).convert(py)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
TypedSlot(ffi::Py_sq_ass_item, wrap::<Self>)
|
||||
}
|
||||
|
||||
fn get_contains() -> TypedSlot<ffi::objobjproc>
|
||||
where
|
||||
Self: for<'p> PySequenceContainsProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_contains,
|
||||
py_binary_func!(PySequenceContainsProtocol, Self::__contains__, c_int),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_inplace_concat() -> TypedSlot<ffi::binaryfunc>
|
||||
where
|
||||
Self: for<'p> PySequenceInplaceConcatProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_inplace_concat,
|
||||
py_binary_func!(
|
||||
PySequenceInplaceConcatProtocol,
|
||||
Self::__inplace_concat__,
|
||||
*mut ffi::PyObject,
|
||||
call_mut
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_inplace_repeat() -> TypedSlot<ffi::ssizeargfunc>
|
||||
where
|
||||
Self: for<'p> PySequenceInplaceRepeatProtocol<'p>,
|
||||
{
|
||||
TypedSlot(
|
||||
ffi::Py_sq_inplace_repeat,
|
||||
py_ssizearg_func!(
|
||||
PySequenceInplaceRepeatProtocol,
|
||||
Self::__inplace_repeat__,
|
||||
call_mut
|
||||
),
|
||||
)
|
||||
}
|
||||
let mut slf = slf.try_borrow_mut()?;
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let value = value.extract()?;
|
||||
crate::callback::convert(py, slf.__setitem__(key.into(), value))
|
||||
})
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceSlots for T where T: PySequenceProtocol<'p> {}
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn delitem<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
crate::callback::convert(py, slf.borrow_mut().__delitem__(key.into()))
|
||||
} else {
|
||||
Err(PyErr::new::<exceptions::PyNotImplementedError, _>(format!(
|
||||
"Item assignment not supported by {:?}",
|
||||
stringify!(T)
|
||||
)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub unsafe extern "C" fn setdelitem<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
call_mut!(slf, __delitem__; key.into()).convert(py)
|
||||
} else {
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let mut slf_ = slf.try_borrow_mut()?;
|
||||
let value = value.extract()?;
|
||||
slf_.__setitem__(key.into(), value).convert(py)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
py_binary_func!(
|
||||
contains,
|
||||
PySequenceContainsProtocol,
|
||||
Self::__contains__,
|
||||
c_int
|
||||
);
|
||||
py_binary_func!(
|
||||
inplace_concat,
|
||||
PySequenceInplaceConcatProtocol,
|
||||
Self::__inplace_concat__,
|
||||
*mut ffi::PyObject,
|
||||
call_mut
|
||||
);
|
||||
py_ssizearg_func!(
|
||||
inplace_repeat,
|
||||
PySequenceInplaceRepeatProtocol,
|
||||
Self::__inplace_repeat__,
|
||||
call_mut
|
||||
);
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
use std::os::raw::c_int;
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub const Py_bf_getbuffer: c_int = 1;
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub const Py_bf_releasebuffer: c_int = 2;
|
||||
pub const Py_mp_ass_subscript: c_int = 3;
|
||||
pub const Py_mp_length: c_int = 4;
|
||||
pub const Py_mp_subscript: c_int = 5;
|
||||
|
|
19
src/lib.rs
19
src/lib.rs
|
@ -339,16 +339,15 @@ macro_rules! py_run_impl {
|
|||
use $crate::ToPyObject;
|
||||
let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict($py);
|
||||
|
||||
$py.run($code, None, Some(d))
|
||||
.map_err(|e| {
|
||||
e.print($py);
|
||||
// So when this c api function the last line called printed the error to stderr,
|
||||
// the output is only written into a buffer which is never flushed because we
|
||||
// panic before flushing. This is where this hack comes into place
|
||||
$py.run("import sys; sys.stderr.flush()", None, None)
|
||||
.unwrap();
|
||||
})
|
||||
.expect($code)
|
||||
if let Err(e) = $py.run($code, None, Some(d)) {
|
||||
e.print($py);
|
||||
// So when this c api function the last line called printed the error to stderr,
|
||||
// the output is only written into a buffer which is never flushed because we
|
||||
// panic before flushing. This is where this hack comes into place
|
||||
$py.run("import sys; sys.stderr.flush()", None, None)
|
||||
.unwrap();
|
||||
panic!($code.to_string())
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -191,11 +191,11 @@ where
|
|||
|
||||
// protocol methods
|
||||
let mut has_gc_methods = false;
|
||||
for slot in T::get_type_slots() {
|
||||
T::for_each_proto_slot(|slot| {
|
||||
has_gc_methods |= slot.slot == ffi::Py_tp_clear;
|
||||
has_gc_methods |= slot.slot == ffi::Py_tp_traverse;
|
||||
slots.0.push(slot);
|
||||
}
|
||||
});
|
||||
|
||||
slots.push(0, ptr::null_mut());
|
||||
let mut spec = ffi::PyType_Spec {
|
||||
|
@ -238,6 +238,9 @@ fn tp_init_additional<T: PyClass>(type_object: *mut ffi::PyTypeObject) {
|
|||
}
|
||||
}
|
||||
|
||||
// Setting buffer protocols via slots doesn't work until Python 3.9, so on older versions we
|
||||
// must manually fixup the type object.
|
||||
#[cfg(not(Py_3_9))]
|
||||
if let Some(buffer) = T::get_buffer() {
|
||||
unsafe {
|
||||
(*(*type_object).tp_as_buffer).bf_getbuffer = buffer.bf_getbuffer;
|
||||
|
|
Loading…
Reference in a new issue