pymethods: faster compilation for protos, tidy ups
This commit is contained in:
parent
43eb762346
commit
c2d78ca76e
|
@ -93,11 +93,17 @@ pub enum FnType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnType {
|
impl FnType {
|
||||||
pub fn self_conversion(&self, cls: Option<&syn::Type>, error_mode: ExtractErrorMode) -> TokenStream {
|
pub fn self_conversion(
|
||||||
|
&self,
|
||||||
|
cls: Option<&syn::Type>,
|
||||||
|
error_mode: ExtractErrorMode,
|
||||||
|
) -> TokenStream {
|
||||||
match self {
|
match self {
|
||||||
FnType::Getter(st) | FnType::Setter(st) | FnType::Fn(st) | FnType::FnCall(st) => {
|
FnType::Getter(st) | FnType::Setter(st) | FnType::Fn(st) | FnType::FnCall(st) => st
|
||||||
st.receiver(cls.expect("no class given for Fn with a \"self\" receiver"), error_mode)
|
.receiver(
|
||||||
}
|
cls.expect("no class given for Fn with a \"self\" receiver"),
|
||||||
|
error_mode,
|
||||||
|
),
|
||||||
FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => {
|
FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => {
|
||||||
quote!()
|
quote!()
|
||||||
}
|
}
|
||||||
|
@ -128,6 +134,7 @@ pub enum SelfType {
|
||||||
TryFromPyCell(Span),
|
TryFromPyCell(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub enum ExtractErrorMode {
|
pub enum ExtractErrorMode {
|
||||||
NotImplemented,
|
NotImplemented,
|
||||||
Raise,
|
Raise,
|
||||||
|
@ -138,7 +145,7 @@ impl SelfType {
|
||||||
let cell = match error_mode {
|
let cell = match error_mode {
|
||||||
ExtractErrorMode::Raise => {
|
ExtractErrorMode::Raise => {
|
||||||
quote! { _py.from_borrowed_ptr::<::pyo3::PyAny>(_slf).downcast::<::pyo3::PyCell<#cls>>()? }
|
quote! { _py.from_borrowed_ptr::<::pyo3::PyAny>(_slf).downcast::<::pyo3::PyCell<#cls>>()? }
|
||||||
},
|
}
|
||||||
ExtractErrorMode::NotImplemented => {
|
ExtractErrorMode::NotImplemented => {
|
||||||
quote! {
|
quote! {
|
||||||
match _py.from_borrowed_ptr::<::pyo3::PyAny>(_slf).downcast::<::pyo3::PyCell<#cls>>() {
|
match _py.from_borrowed_ptr::<::pyo3::PyAny>(_slf).downcast::<::pyo3::PyCell<#cls>>() {
|
||||||
|
@ -146,7 +153,7 @@ impl SelfType {
|
||||||
::std::result::Result::Err(_) => return ::pyo3::callback::convert(_py, _py.NotImplemented()),
|
::std::result::Result::Err(_) => return ::pyo3::callback::convert(_py, _py.NotImplemented()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
match self {
|
match self {
|
||||||
SelfType::Receiver { mutable: false } => {
|
SelfType::Receiver { mutable: false } => {
|
||||||
|
|
|
@ -592,50 +592,6 @@ fn impl_class(
|
||||||
visitor(collector.async_protocol_slots());
|
visitor(collector.async_protocol_slots());
|
||||||
visitor(collector.buffer_protocol_slots());
|
visitor(collector.buffer_protocol_slots());
|
||||||
visitor(collector.methods_protocol_slots());
|
visitor(collector.methods_protocol_slots());
|
||||||
let mut generated_slots = ::std::vec::Vec::new();
|
|
||||||
if let ::std::option::Option::Some(setattr) = ::pyo3::generate_pyclass_setattr_slot!(#cls) {
|
|
||||||
generated_slots.push(setattr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_setdescr_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_setitem_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_add_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_sub_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_mul_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_mod_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_divmod_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_lshift_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_rshift_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_and_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_or_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_xor_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
if let ::std::option::Option::Some(setdescr) = ::pyo3::generate_pyclass_matmul_slot!(#cls) {
|
|
||||||
generated_slots.push(setdescr);
|
|
||||||
}
|
|
||||||
visitor(&generated_slots);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_buffer() -> ::std::option::Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
|
fn get_buffer() -> ::std::option::Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
konst::{ConstAttributes, ConstSpec},
|
konst::{ConstAttributes, ConstSpec},
|
||||||
pyfunction::PyFunctionOptions,
|
pyfunction::PyFunctionOptions,
|
||||||
|
@ -40,6 +42,9 @@ pub fn impl_methods(
|
||||||
let mut trait_impls = Vec::new();
|
let mut trait_impls = Vec::new();
|
||||||
let mut proto_impls = Vec::new();
|
let mut proto_impls = Vec::new();
|
||||||
let mut methods = Vec::new();
|
let mut methods = Vec::new();
|
||||||
|
|
||||||
|
let mut implemented_proto_fragments = HashSet::new();
|
||||||
|
|
||||||
for iimpl in impls.iter_mut() {
|
for iimpl in impls.iter_mut() {
|
||||||
match iimpl {
|
match iimpl {
|
||||||
syn::ImplItem::Method(meth) => {
|
syn::ImplItem::Method(meth) => {
|
||||||
|
@ -53,6 +58,11 @@ pub fn impl_methods(
|
||||||
let attrs = get_cfg_attributes(&meth.attrs);
|
let attrs = get_cfg_attributes(&meth.attrs);
|
||||||
trait_impls.push(quote!(#(#attrs)* #token_stream));
|
trait_impls.push(quote!(#(#attrs)* #token_stream));
|
||||||
}
|
}
|
||||||
|
GeneratedPyMethod::SlotTraitImpl(method_name, token_stream) => {
|
||||||
|
implemented_proto_fragments.insert(method_name);
|
||||||
|
let attrs = get_cfg_attributes(&meth.attrs);
|
||||||
|
trait_impls.push(quote!(#(#attrs)* #token_stream));
|
||||||
|
}
|
||||||
GeneratedPyMethod::Proto(token_stream) => {
|
GeneratedPyMethod::Proto(token_stream) => {
|
||||||
let attrs = get_cfg_attributes(&meth.attrs);
|
let attrs = get_cfg_attributes(&meth.attrs);
|
||||||
proto_impls.push(quote!(#(#attrs)* #token_stream))
|
proto_impls.push(quote!(#(#attrs)* #token_stream))
|
||||||
|
@ -81,7 +91,9 @@ pub fn impl_methods(
|
||||||
};
|
};
|
||||||
|
|
||||||
let protos_registration = match methods_type {
|
let protos_registration = match methods_type {
|
||||||
PyClassMethodsType::Specialization => Some(impl_protos(ty, proto_impls)),
|
PyClassMethodsType::Specialization => {
|
||||||
|
Some(impl_protos(ty, proto_impls, implemented_proto_fragments))
|
||||||
|
}
|
||||||
PyClassMethodsType::Inventory => {
|
PyClassMethodsType::Inventory => {
|
||||||
if proto_impls.is_empty() {
|
if proto_impls.is_empty() {
|
||||||
None
|
None
|
||||||
|
@ -135,7 +147,36 @@ fn impl_py_methods(ty: &syn::Type, methods: Vec<TokenStream>) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_protos(ty: &syn::Type, proto_impls: Vec<TokenStream>) -> TokenStream {
|
fn impl_protos(
|
||||||
|
ty: &syn::Type,
|
||||||
|
mut proto_impls: Vec<TokenStream>,
|
||||||
|
mut implemented_proto_fragments: HashSet<String>,
|
||||||
|
) -> TokenStream {
|
||||||
|
macro_rules! try_add_shared_slot {
|
||||||
|
($first:literal, $second:literal, $slot:ident) => {{
|
||||||
|
let first_implemented = implemented_proto_fragments.remove($first);
|
||||||
|
let second_implemented = implemented_proto_fragments.remove($second);
|
||||||
|
if first_implemented || second_implemented {
|
||||||
|
proto_impls.push(quote! { ::pyo3::$slot!(#ty) })
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
try_add_shared_slot!("__setattr__", "__delattr__", generate_pyclass_setattr_slot);
|
||||||
|
try_add_shared_slot!("__set__", "__delete__", generate_pyclass_setdescr_slot);
|
||||||
|
try_add_shared_slot!("__setitem__", "__delitem__", generate_pyclass_setitem_slot);
|
||||||
|
try_add_shared_slot!("__add__", "__radd__", generate_pyclass_add_slot);
|
||||||
|
try_add_shared_slot!("__sub__", "__rsub__", generate_pyclass_sub_slot);
|
||||||
|
try_add_shared_slot!("__mul__", "__rmul__", generate_pyclass_mul_slot);
|
||||||
|
try_add_shared_slot!("__mod__", "__rmod__", generate_pyclass_mod_slot);
|
||||||
|
try_add_shared_slot!("__divmod__", "__rdivmod__", generate_pyclass_divmod_slot);
|
||||||
|
try_add_shared_slot!("__lshift__", "__rlshift__", generate_pyclass_lshift_slot);
|
||||||
|
try_add_shared_slot!("__rshift__", "__rrshift__", generate_pyclass_rshift_slot);
|
||||||
|
try_add_shared_slot!("__and__", "__rand__", generate_pyclass_and_slot);
|
||||||
|
try_add_shared_slot!("__or__", "__ror__", generate_pyclass_or_slot);
|
||||||
|
try_add_shared_slot!("__xor__", "__rxor__", generate_pyclass_xor_slot);
|
||||||
|
try_add_shared_slot!("__matmul__", "__rmatmul__", generate_pyclass_matmul_slot);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl ::pyo3::class::impl_::PyMethodsProtocolSlots<#ty>
|
impl ::pyo3::class::impl_::PyMethodsProtocolSlots<#ty>
|
||||||
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
|
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub enum GeneratedPyMethod {
|
||||||
Method(TokenStream),
|
Method(TokenStream),
|
||||||
Proto(TokenStream),
|
Proto(TokenStream),
|
||||||
TraitImpl(TokenStream),
|
TraitImpl(TokenStream),
|
||||||
|
SlotTraitImpl(String, TokenStream),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_py_method(
|
pub fn gen_py_method(
|
||||||
|
@ -41,7 +42,7 @@ pub fn gen_py_method(
|
||||||
|
|
||||||
if let Some(slot_fragment_def) = pyproto_fragment(&method_name) {
|
if let Some(slot_fragment_def) = pyproto_fragment(&method_name) {
|
||||||
let proto = slot_fragment_def.generate_pyproto_fragment(cls, &spec)?;
|
let proto = slot_fragment_def.generate_pyproto_fragment(cls, &spec)?;
|
||||||
return Ok(GeneratedPyMethod::TraitImpl(proto));
|
return Ok(GeneratedPyMethod::SlotTraitImpl(method_name, proto));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match &spec.tp {
|
Ok(match &spec.tp {
|
||||||
|
@ -216,8 +217,12 @@ pub fn impl_py_setter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
|
||||||
};
|
};
|
||||||
|
|
||||||
let slf = match property_type {
|
let slf = match property_type {
|
||||||
PropertyType::Descriptor { .. } => SelfType::Receiver { mutable: true }.receiver(cls, ExtractErrorMode::Raise),
|
PropertyType::Descriptor { .. } => {
|
||||||
PropertyType::Function { self_type, .. } => self_type.receiver(cls, ExtractErrorMode::Raise),
|
SelfType::Receiver { mutable: true }.receiver(cls, ExtractErrorMode::Raise)
|
||||||
|
}
|
||||||
|
PropertyType::Function { self_type, .. } => {
|
||||||
|
self_type.receiver(cls, ExtractErrorMode::Raise)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
::pyo3::class::PyMethodDefType::Setter({
|
::pyo3::class::PyMethodDefType::Setter({
|
||||||
|
@ -292,8 +297,12 @@ pub fn impl_py_getter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
|
||||||
};
|
};
|
||||||
|
|
||||||
let slf = match property_type {
|
let slf = match property_type {
|
||||||
PropertyType::Descriptor { .. } => SelfType::Receiver { mutable: false }.receiver(cls, ExtractErrorMode::Raise),
|
PropertyType::Descriptor { .. } => {
|
||||||
PropertyType::Function { self_type, .. } => self_type.receiver(cls, ExtractErrorMode::Raise),
|
SelfType::Receiver { mutable: false }.receiver(cls, ExtractErrorMode::Raise)
|
||||||
|
}
|
||||||
|
PropertyType::Function { self_type, .. } => {
|
||||||
|
self_type.receiver(cls, ExtractErrorMode::Raise)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
::pyo3::class::PyMethodDefType::Getter({
|
::pyo3::class::PyMethodDefType::Getter({
|
||||||
|
@ -401,8 +410,9 @@ const __HASH__: SlotDef = SlotDef::new("Py_tp_hash", "hashfunc")
|
||||||
.return_conversion(TokenGenerator(
|
.return_conversion(TokenGenerator(
|
||||||
|| quote! { ::pyo3::callback::HashCallbackOutput },
|
|| quote! { ::pyo3::callback::HashCallbackOutput },
|
||||||
));
|
));
|
||||||
const __RICHCMP__: SlotDef =
|
const __RICHCMP__: SlotDef = SlotDef::new("Py_tp_richcompare", "richcmpfunc")
|
||||||
SlotDef::new("Py_tp_richcompare", "richcmpfunc").arguments(&[Ty::Object, Ty::CompareOp]);
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
|
.arguments(&[Ty::ObjectOrNotImplemented, Ty::CompareOp]);
|
||||||
const __GET__: SlotDef =
|
const __GET__: SlotDef =
|
||||||
SlotDef::new("Py_tp_descr_get", "descrgetfunc").arguments(&[Ty::Object, Ty::Object]);
|
SlotDef::new("Py_tp_descr_get", "descrgetfunc").arguments(&[Ty::Object, Ty::Object]);
|
||||||
const __ITER__: SlotDef = SlotDef::new("Py_tp_iter", "getiterfunc");
|
const __ITER__: SlotDef = SlotDef::new("Py_tp_iter", "getiterfunc");
|
||||||
|
@ -431,42 +441,55 @@ const __BOOL__: SlotDef = SlotDef::new("Py_nb_bool", "inquiry").ret_ty(Ty::Int);
|
||||||
|
|
||||||
const __IADD__: SlotDef = SlotDef::new("Py_nb_inplace_add", "binaryfunc")
|
const __IADD__: SlotDef = SlotDef::new("Py_nb_inplace_add", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __ISUB__: SlotDef = SlotDef::new("Py_nb_inplace_subtract", "binaryfunc")
|
const __ISUB__: SlotDef = SlotDef::new("Py_nb_inplace_subtract", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IMUL__: SlotDef = SlotDef::new("Py_nb_inplace_multiply", "binaryfunc")
|
const __IMUL__: SlotDef = SlotDef::new("Py_nb_inplace_multiply", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IMATMUL__: SlotDef = SlotDef::new("Py_nb_inplace_matrix_multiply", "binaryfunc")
|
const __IMATMUL__: SlotDef = SlotDef::new("Py_nb_inplace_matrix_multiply", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __ITRUEDIV__: SlotDef = SlotDef::new("Py_nb_inplace_true_divide", "binaryfunc")
|
const __ITRUEDIV__: SlotDef = SlotDef::new("Py_nb_inplace_true_divide", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IFLOORDIV__: SlotDef = SlotDef::new("Py_nb_inplace_floor_divide", "binaryfunc")
|
const __IFLOORDIV__: SlotDef = SlotDef::new("Py_nb_inplace_floor_divide", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IMOD__: SlotDef = SlotDef::new("Py_nb_inplace_remainder", "binaryfunc")
|
const __IMOD__: SlotDef = SlotDef::new("Py_nb_inplace_remainder", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "ternaryfunc")
|
const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "ternaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented, Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented, Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __ILSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_lshift", "binaryfunc")
|
const __ILSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_lshift", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IRSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_rshift", "binaryfunc")
|
const __IRSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_rshift", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IAND__: SlotDef = SlotDef::new("Py_nb_inplace_and", "binaryfunc")
|
const __IAND__: SlotDef = SlotDef::new("Py_nb_inplace_and", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IXOR__: SlotDef = SlotDef::new("Py_nb_inplace_xor", "binaryfunc")
|
const __IXOR__: SlotDef = SlotDef::new("Py_nb_inplace_xor", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IOR__: SlotDef = SlotDef::new("Py_nb_inplace_or", "binaryfunc")
|
const __IOR__: SlotDef = SlotDef::new("Py_nb_inplace_or", "binaryfunc")
|
||||||
.arguments(&[Ty::ObjectOrNotImplemented])
|
.arguments(&[Ty::ObjectOrNotImplemented])
|
||||||
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
|
|
||||||
fn pyproto(method_name: &str) -> Option<&'static SlotDef> {
|
fn pyproto(method_name: &str) -> Option<&'static SlotDef> {
|
||||||
|
@ -659,6 +682,7 @@ struct SlotDef {
|
||||||
arguments: &'static [Ty],
|
arguments: &'static [Ty],
|
||||||
ret_ty: Ty,
|
ret_ty: Ty,
|
||||||
before_call_method: Option<TokenGenerator>,
|
before_call_method: Option<TokenGenerator>,
|
||||||
|
extract_error_mode: ExtractErrorMode,
|
||||||
return_mode: Option<ReturnMode>,
|
return_mode: Option<ReturnMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,6 +694,7 @@ impl SlotDef {
|
||||||
arguments: &[],
|
arguments: &[],
|
||||||
ret_ty: Ty::Object,
|
ret_ty: Ty::Object,
|
||||||
before_call_method: None,
|
before_call_method: None,
|
||||||
|
extract_error_mode: ExtractErrorMode::Raise,
|
||||||
return_mode: None,
|
return_mode: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,6 +719,11 @@ impl SlotDef {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn extract_error_mode(mut self, extract_error_mode: ExtractErrorMode) -> Self {
|
||||||
|
self.extract_error_mode = extract_error_mode;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
const fn return_self(mut self) -> Self {
|
const fn return_self(mut self) -> Self {
|
||||||
self.return_mode = Some(ReturnMode::ReturnSelf);
|
self.return_mode = Some(ReturnMode::ReturnSelf);
|
||||||
self
|
self
|
||||||
|
@ -705,13 +735,21 @@ impl SlotDef {
|
||||||
func_ty,
|
func_ty,
|
||||||
before_call_method,
|
before_call_method,
|
||||||
arguments,
|
arguments,
|
||||||
|
extract_error_mode,
|
||||||
ret_ty,
|
ret_ty,
|
||||||
return_mode,
|
return_mode,
|
||||||
} = self;
|
} = self;
|
||||||
let py = syn::Ident::new("_py", Span::call_site());
|
let py = syn::Ident::new("_py", Span::call_site());
|
||||||
let method_arguments = generate_method_arguments(arguments);
|
let method_arguments = generate_method_arguments(arguments);
|
||||||
let ret_ty = ret_ty.ffi_type();
|
let ret_ty = ret_ty.ffi_type();
|
||||||
let body = generate_method_body(cls, spec, &py, arguments, ExtractErrorMode::Raise, return_mode.as_ref())?;
|
let body = generate_method_body(
|
||||||
|
cls,
|
||||||
|
spec,
|
||||||
|
&py,
|
||||||
|
arguments,
|
||||||
|
*extract_error_mode,
|
||||||
|
return_mode.as_ref(),
|
||||||
|
)?;
|
||||||
Ok(quote!({
|
Ok(quote!({
|
||||||
unsafe extern "C" fn __wrap(_raw_slf: *mut ::pyo3::ffi::PyObject, #(#method_arguments),*) -> #ret_ty {
|
unsafe extern "C" fn __wrap(_raw_slf: *mut ::pyo3::ffi::PyObject, #(#method_arguments),*) -> #ret_ty {
|
||||||
let _slf = _raw_slf;
|
let _slf = _raw_slf;
|
||||||
|
@ -765,6 +803,7 @@ fn generate_method_body(
|
||||||
struct SlotFragmentDef {
|
struct SlotFragmentDef {
|
||||||
fragment: &'static str,
|
fragment: &'static str,
|
||||||
arguments: &'static [Ty],
|
arguments: &'static [Ty],
|
||||||
|
extract_error_mode: ExtractErrorMode,
|
||||||
ret_ty: Ty,
|
ret_ty: Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,10 +812,16 @@ impl SlotFragmentDef {
|
||||||
SlotFragmentDef {
|
SlotFragmentDef {
|
||||||
fragment,
|
fragment,
|
||||||
arguments,
|
arguments,
|
||||||
|
extract_error_mode: ExtractErrorMode::Raise,
|
||||||
ret_ty: Ty::Void,
|
ret_ty: Ty::Void,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn extract_error_mode(mut self, extract_error_mode: ExtractErrorMode) -> Self {
|
||||||
|
self.extract_error_mode = extract_error_mode;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
const fn ret_ty(mut self, ret_ty: Ty) -> Self {
|
const fn ret_ty(mut self, ret_ty: Ty) -> Self {
|
||||||
self.ret_ty = ret_ty;
|
self.ret_ty = ret_ty;
|
||||||
self
|
self
|
||||||
|
@ -786,19 +831,17 @@ impl SlotFragmentDef {
|
||||||
let SlotFragmentDef {
|
let SlotFragmentDef {
|
||||||
fragment,
|
fragment,
|
||||||
arguments,
|
arguments,
|
||||||
|
extract_error_mode,
|
||||||
ret_ty,
|
ret_ty,
|
||||||
} = self;
|
} = self;
|
||||||
let fragment_trait = format_ident!("PyClass{}SlotFragment", fragment);
|
let fragment_trait = format_ident!("PyClass{}SlotFragment", fragment);
|
||||||
let implemented = format_ident!("{}implemented", fragment);
|
|
||||||
let method = syn::Ident::new(fragment, Span::call_site());
|
let method = syn::Ident::new(fragment, Span::call_site());
|
||||||
let py = syn::Ident::new("_py", Span::call_site());
|
let py = syn::Ident::new("_py", Span::call_site());
|
||||||
let method_arguments = generate_method_arguments(arguments);
|
let method_arguments = generate_method_arguments(arguments);
|
||||||
let body = generate_method_body(cls, spec, &py, arguments, ExtractErrorMode::NotImplemented, None)?;
|
let body = generate_method_body(cls, spec, &py, arguments, *extract_error_mode, None)?;
|
||||||
let ret_ty = ret_ty.ffi_type();
|
let ret_ty = ret_ty.ffi_type();
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
impl ::pyo3::class::impl_::#fragment_trait<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
|
impl ::pyo3::class::impl_::#fragment_trait<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||||
#[inline]
|
|
||||||
fn #implemented(self) -> bool { true }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn #method(
|
unsafe fn #method(
|
||||||
|
@ -817,21 +860,43 @@ impl SlotFragmentDef {
|
||||||
|
|
||||||
const __SETATTR__: SlotFragmentDef =
|
const __SETATTR__: SlotFragmentDef =
|
||||||
SlotFragmentDef::new("__setattr__", &[Ty::Object, Ty::NonNullObject]);
|
SlotFragmentDef::new("__setattr__", &[Ty::Object, Ty::NonNullObject]);
|
||||||
const __DELATTR__: SlotFragmentDef =
|
const __DELATTR__: SlotFragmentDef = SlotFragmentDef::new("__delattr__", &[Ty::Object]);
|
||||||
SlotFragmentDef::new("__delattr__", &[Ty::Object]);
|
const __SET__: SlotFragmentDef = SlotFragmentDef::new("__set__", &[Ty::Object, Ty::NonNullObject]);
|
||||||
const __SET__: SlotFragmentDef =
|
const __DELETE__: SlotFragmentDef = SlotFragmentDef::new("__delete__", &[Ty::Object]);
|
||||||
SlotFragmentDef::new("__set__", &[Ty::Object, Ty::NonNullObject]);
|
|
||||||
const __DELETE__: SlotFragmentDef =
|
|
||||||
SlotFragmentDef::new("__delete__", &[Ty::Object]);
|
|
||||||
const __SETITEM__: SlotFragmentDef =
|
const __SETITEM__: SlotFragmentDef =
|
||||||
SlotFragmentDef::new("__setitem__", &[Ty::Object, Ty::NonNullObject]);
|
SlotFragmentDef::new("__setitem__", &[Ty::Object, Ty::NonNullObject]);
|
||||||
const __DELITEM__: SlotFragmentDef =
|
const __DELITEM__: SlotFragmentDef = SlotFragmentDef::new("__delitem__", &[Ty::Object]);
|
||||||
SlotFragmentDef::new("__delitem__", &[Ty::Object]);
|
|
||||||
|
|
||||||
const __ADD__: SlotFragmentDef =
|
macro_rules! binary_num_slot_fragment_def {
|
||||||
SlotFragmentDef::new("__add__", &[Ty::ObjectOrNotImplemented]).ret_ty(Ty::Object);
|
($ident:ident, $name:literal) => {
|
||||||
const __RADD__: SlotFragmentDef =
|
const $ident: SlotFragmentDef = SlotFragmentDef::new($name, &[Ty::ObjectOrNotImplemented])
|
||||||
SlotFragmentDef::new("__radd__", &[Ty::ObjectOrNotImplemented]).ret_ty(Ty::Object);
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
|
.ret_ty(Ty::Object);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_num_slot_fragment_def!(__ADD__, "__add__");
|
||||||
|
binary_num_slot_fragment_def!(__RADD__, "__radd__");
|
||||||
|
binary_num_slot_fragment_def!(__SUB__, "__sub__");
|
||||||
|
binary_num_slot_fragment_def!(__RSUB__, "__rsub__");
|
||||||
|
binary_num_slot_fragment_def!(__MUL__, "__mul__");
|
||||||
|
binary_num_slot_fragment_def!(__RMUL__, "__rmul__");
|
||||||
|
binary_num_slot_fragment_def!(__MATMUL__, "__matmul__");
|
||||||
|
binary_num_slot_fragment_def!(__RMATMUL__, "__rmatmul__");
|
||||||
|
binary_num_slot_fragment_def!(__DIVMOD__, "__divmod__");
|
||||||
|
binary_num_slot_fragment_def!(__RDIVMOD__, "__rdivmod__");
|
||||||
|
binary_num_slot_fragment_def!(__MOD__, "__mod__");
|
||||||
|
binary_num_slot_fragment_def!(__RMOD__, "__rmod__");
|
||||||
|
binary_num_slot_fragment_def!(__LSHIFT__, "__lshift__");
|
||||||
|
binary_num_slot_fragment_def!(__RLSHIFT__, "__rlshift__");
|
||||||
|
binary_num_slot_fragment_def!(__RSHIFT__, "__rshift__");
|
||||||
|
binary_num_slot_fragment_def!(__RRSHIFT__, "__rrshift__");
|
||||||
|
binary_num_slot_fragment_def!(__AND__, "__and__");
|
||||||
|
binary_num_slot_fragment_def!(__RAND__, "__rand__");
|
||||||
|
binary_num_slot_fragment_def!(__XOR__, "__xor__");
|
||||||
|
binary_num_slot_fragment_def!(__RXOR__, "__rxor__");
|
||||||
|
binary_num_slot_fragment_def!(__OR__, "__or__");
|
||||||
|
binary_num_slot_fragment_def!(__ROR__, "__ror__");
|
||||||
|
|
||||||
fn pyproto_fragment(method_name: &str) -> Option<&'static SlotFragmentDef> {
|
fn pyproto_fragment(method_name: &str) -> Option<&'static SlotFragmentDef> {
|
||||||
match method_name {
|
match method_name {
|
||||||
|
@ -843,6 +908,26 @@ fn pyproto_fragment(method_name: &str) -> Option<&'static SlotFragmentDef> {
|
||||||
"__delitem__" => Some(&__DELITEM__),
|
"__delitem__" => Some(&__DELITEM__),
|
||||||
"__add__" => Some(&__ADD__),
|
"__add__" => Some(&__ADD__),
|
||||||
"__radd__" => Some(&__RADD__),
|
"__radd__" => Some(&__RADD__),
|
||||||
|
"__sub__" => Some(&__SUB__),
|
||||||
|
"__rsub__" => Some(&__RSUB__),
|
||||||
|
"__mul__" => Some(&__MUL__),
|
||||||
|
"__rmul__" => Some(&__RMUL__),
|
||||||
|
"__matmul__" => Some(&__MATMUL__),
|
||||||
|
"__rmatmul__" => Some(&__RMATMUL__),
|
||||||
|
"__divmod__" => Some(&__DIVMOD__),
|
||||||
|
"__rdivmod__" => Some(&__RDIVMOD__),
|
||||||
|
"__mod__" => Some(&__MOD__),
|
||||||
|
"__rmod__" => Some(&__RMOD__),
|
||||||
|
"__lshift__" => Some(&__LSHIFT__),
|
||||||
|
"__rlshift__" => Some(&__RLSHIFT__),
|
||||||
|
"__rshift__" => Some(&__RSHIFT__),
|
||||||
|
"__rrshift__" => Some(&__RRSHIFT__),
|
||||||
|
"__and__" => Some(&__AND__),
|
||||||
|
"__rand__" => Some(&__RAND__),
|
||||||
|
"__xor__" => Some(&__XOR__),
|
||||||
|
"__rxor__" => Some(&__RXOR__),
|
||||||
|
"__or__" => Some(&__OR__),
|
||||||
|
"__ror__" => Some(&__ROR__),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,15 +109,9 @@ impl<T> PyClassCallImpl<T> for &'_ PyClassImplCollector<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! slot_fragment_trait {
|
macro_rules! slot_fragment_trait {
|
||||||
($trait_name:ident, $implemented_name:ident, $($default_method:tt)*) => {
|
($trait_name:ident, $($default_method:tt)*) => {
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub trait $trait_name<T>: Sized {
|
pub trait $trait_name<T>: Sized {
|
||||||
#[inline]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $implemented_name(self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
$($default_method)*
|
$($default_method)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,8 +127,6 @@ macro_rules! define_pyclass_setattr_slot {
|
||||||
(
|
(
|
||||||
$set_trait:ident,
|
$set_trait:ident,
|
||||||
$del_trait:ident,
|
$del_trait:ident,
|
||||||
$set_implemented:ident,
|
|
||||||
$del_implemented:ident,
|
|
||||||
$set:ident,
|
$set:ident,
|
||||||
$del:ident,
|
$del:ident,
|
||||||
$set_error:expr,
|
$set_error:expr,
|
||||||
|
@ -145,7 +137,6 @@ macro_rules! define_pyclass_setattr_slot {
|
||||||
) => {
|
) => {
|
||||||
slot_fragment_trait! {
|
slot_fragment_trait! {
|
||||||
$set_trait,
|
$set_trait,
|
||||||
$set_implemented,
|
|
||||||
|
|
||||||
/// # Safety: _slf and _attr must be valid non-null Python objects
|
/// # Safety: _slf and _attr must be valid non-null Python objects
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -162,7 +153,6 @@ macro_rules! define_pyclass_setattr_slot {
|
||||||
|
|
||||||
slot_fragment_trait! {
|
slot_fragment_trait! {
|
||||||
$del_trait,
|
$del_trait,
|
||||||
$del_implemented,
|
|
||||||
|
|
||||||
/// # Safety: _slf and _attr must be valid non-null Python objects
|
/// # Safety: _slf and _attr must be valid non-null Python objects
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -180,31 +170,26 @@ macro_rules! define_pyclass_setattr_slot {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! $generate_macro {
|
macro_rules! $generate_macro {
|
||||||
($cls:ty) => {{
|
($cls:ty) => {{
|
||||||
use ::std::option::Option::*;
|
unsafe extern "C" fn __wrap(
|
||||||
use $crate::class::impl_::*;
|
_slf: *mut $crate::ffi::PyObject,
|
||||||
let collector = PyClassImplCollector::<$cls>::new();
|
attr: *mut $crate::ffi::PyObject,
|
||||||
if collector.$set_implemented() || collector.$del_implemented() {
|
value: *mut $crate::ffi::PyObject,
|
||||||
unsafe extern "C" fn __wrap(
|
) -> ::std::os::raw::c_int {
|
||||||
_slf: *mut $crate::ffi::PyObject,
|
use ::std::option::Option::*;
|
||||||
attr: *mut $crate::ffi::PyObject,
|
use $crate::callback::IntoPyCallbackOutput;
|
||||||
value: *mut $crate::ffi::PyObject,
|
use $crate::class::impl_::*;
|
||||||
) -> ::std::os::raw::c_int {
|
$crate::callback::handle_panic(|py| {
|
||||||
use $crate::callback::IntoPyCallbackOutput;
|
let collector = PyClassImplCollector::<$cls>::new();
|
||||||
$crate::callback::handle_panic(|py| {
|
if let Some(value) = ::std::ptr::NonNull::new(value) {
|
||||||
let collector = PyClassImplCollector::<$cls>::new();
|
collector.$set(py, _slf, attr, value).convert(py)
|
||||||
if let Some(value) = ::std::ptr::NonNull::new(value) {
|
} else {
|
||||||
collector.$set(py, _slf, attr, value).convert(py)
|
collector.$del(py, _slf, attr).convert(py)
|
||||||
} else {
|
}
|
||||||
collector.$del(py, _slf, attr).convert(py)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some($crate::ffi::PyType_Slot {
|
|
||||||
slot: $crate::ffi::$slot,
|
|
||||||
pfunc: __wrap as $crate::ffi::$func_ty as _,
|
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
None
|
$crate::ffi::PyType_Slot {
|
||||||
|
slot: $crate::ffi::$slot,
|
||||||
|
pfunc: __wrap as $crate::ffi::$func_ty as _,
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -214,8 +199,6 @@ macro_rules! define_pyclass_setattr_slot {
|
||||||
define_pyclass_setattr_slot! {
|
define_pyclass_setattr_slot! {
|
||||||
PyClass__setattr__SlotFragment,
|
PyClass__setattr__SlotFragment,
|
||||||
PyClass__delattr__SlotFragment,
|
PyClass__delattr__SlotFragment,
|
||||||
__setattr__implemented,
|
|
||||||
__delattr__implemented,
|
|
||||||
__setattr__,
|
__setattr__,
|
||||||
__delattr__,
|
__delattr__,
|
||||||
Err(PyAttributeError::new_err("can't set attribute")),
|
Err(PyAttributeError::new_err("can't set attribute")),
|
||||||
|
@ -228,8 +211,6 @@ define_pyclass_setattr_slot! {
|
||||||
define_pyclass_setattr_slot! {
|
define_pyclass_setattr_slot! {
|
||||||
PyClass__set__SlotFragment,
|
PyClass__set__SlotFragment,
|
||||||
PyClass__delete__SlotFragment,
|
PyClass__delete__SlotFragment,
|
||||||
__set__implemented,
|
|
||||||
__delete__implemented,
|
|
||||||
__set__,
|
__set__,
|
||||||
__delete__,
|
__delete__,
|
||||||
Err(PyNotImplementedError::new_err("can't set descriptor")),
|
Err(PyNotImplementedError::new_err("can't set descriptor")),
|
||||||
|
@ -242,8 +223,6 @@ define_pyclass_setattr_slot! {
|
||||||
define_pyclass_setattr_slot! {
|
define_pyclass_setattr_slot! {
|
||||||
PyClass__setitem__SlotFragment,
|
PyClass__setitem__SlotFragment,
|
||||||
PyClass__delitem__SlotFragment,
|
PyClass__delitem__SlotFragment,
|
||||||
__setitem__implemented,
|
|
||||||
__delitem__implemented,
|
|
||||||
__setitem__,
|
__setitem__,
|
||||||
__delitem__,
|
__delitem__,
|
||||||
Err(PyNotImplementedError::new_err("can't set item")),
|
Err(PyNotImplementedError::new_err("can't set item")),
|
||||||
|
@ -261,8 +240,6 @@ macro_rules! define_pyclass_binary_operator_slot {
|
||||||
(
|
(
|
||||||
$lhs_trait:ident,
|
$lhs_trait:ident,
|
||||||
$rhs_trait:ident,
|
$rhs_trait:ident,
|
||||||
$lhs_implemented:ident,
|
|
||||||
$rhs_implemented:ident,
|
|
||||||
$lhs:ident,
|
$lhs:ident,
|
||||||
$rhs:ident,
|
$rhs:ident,
|
||||||
$generate_macro:ident,
|
$generate_macro:ident,
|
||||||
|
@ -271,7 +248,6 @@ macro_rules! define_pyclass_binary_operator_slot {
|
||||||
) => {
|
) => {
|
||||||
slot_fragment_trait! {
|
slot_fragment_trait! {
|
||||||
$lhs_trait,
|
$lhs_trait,
|
||||||
$lhs_implemented,
|
|
||||||
|
|
||||||
/// # Safety: _slf and _attr must be valid non-null Python objects
|
/// # Safety: _slf and _attr must be valid non-null Python objects
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -288,7 +264,6 @@ macro_rules! define_pyclass_binary_operator_slot {
|
||||||
|
|
||||||
slot_fragment_trait! {
|
slot_fragment_trait! {
|
||||||
$rhs_trait,
|
$rhs_trait,
|
||||||
$rhs_implemented,
|
|
||||||
|
|
||||||
/// # Safety: _slf and _attr must be valid non-null Python objects
|
/// # Safety: _slf and _attr must be valid non-null Python objects
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -307,31 +282,25 @@ macro_rules! define_pyclass_binary_operator_slot {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! $generate_macro {
|
macro_rules! $generate_macro {
|
||||||
($cls:ty) => {{
|
($cls:ty) => {{
|
||||||
use ::std::option::Option::*;
|
unsafe extern "C" fn __wrap(
|
||||||
use $crate::class::impl_::*;
|
_slf: *mut $crate::ffi::PyObject,
|
||||||
let collector = PyClassImplCollector::<$cls>::new();
|
_other: *mut $crate::ffi::PyObject,
|
||||||
if collector.$lhs_implemented() || collector.$rhs_implemented() {
|
) -> *mut $crate::ffi::PyObject {
|
||||||
unsafe extern "C" fn __wrap(
|
$crate::callback::handle_panic(|py| {
|
||||||
_slf: *mut $crate::ffi::PyObject,
|
use ::pyo3::class::impl_::*;
|
||||||
_other: *mut $crate::ffi::PyObject,
|
let collector = PyClassImplCollector::<$cls>::new();
|
||||||
) -> *mut $crate::ffi::PyObject {
|
let lhs_result = collector.$lhs(py, _slf, _other)?;
|
||||||
$crate::callback::handle_panic(|py| {
|
if lhs_result == $crate::ffi::Py_NotImplemented() {
|
||||||
let collector = PyClassImplCollector::<$cls>::new();
|
$crate::ffi::Py_DECREF(lhs_result);
|
||||||
let lhs_result = collector.$lhs(py, _slf, _other)?;
|
collector.$rhs(py, _other, _slf)
|
||||||
if lhs_result == $crate::ffi::Py_NotImplemented() {
|
} else {
|
||||||
$crate::ffi::Py_DECREF(lhs_result);
|
::std::result::Result::Ok(lhs_result)
|
||||||
collector.$rhs(py, _other, _slf)
|
}
|
||||||
} else {
|
|
||||||
::std::result::Result::Ok(lhs_result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some($crate::ffi::PyType_Slot {
|
|
||||||
slot: $crate::ffi::$slot,
|
|
||||||
pfunc: __wrap as $crate::ffi::$func_ty as _,
|
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
None
|
$crate::ffi::PyType_Slot {
|
||||||
|
slot: $crate::ffi::$slot,
|
||||||
|
pfunc: __wrap as $crate::ffi::$func_ty as _,
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -341,8 +310,6 @@ macro_rules! define_pyclass_binary_operator_slot {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__add__SlotFragment,
|
PyClass__add__SlotFragment,
|
||||||
PyClass__radd__SlotFragment,
|
PyClass__radd__SlotFragment,
|
||||||
__add__implemented,
|
|
||||||
__radd__implemented,
|
|
||||||
__add__,
|
__add__,
|
||||||
__radd__,
|
__radd__,
|
||||||
generate_pyclass_add_slot,
|
generate_pyclass_add_slot,
|
||||||
|
@ -353,8 +320,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__sub__SlotFragment,
|
PyClass__sub__SlotFragment,
|
||||||
PyClass__rsub__SlotFragment,
|
PyClass__rsub__SlotFragment,
|
||||||
__sub__implemented,
|
|
||||||
__rsub__implemented,
|
|
||||||
__sub__,
|
__sub__,
|
||||||
__rsub__,
|
__rsub__,
|
||||||
generate_pyclass_sub_slot,
|
generate_pyclass_sub_slot,
|
||||||
|
@ -365,8 +330,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__mul__SlotFragment,
|
PyClass__mul__SlotFragment,
|
||||||
PyClass__rmul__SlotFragment,
|
PyClass__rmul__SlotFragment,
|
||||||
__mul__implemented,
|
|
||||||
__rmul__implemented,
|
|
||||||
__mul__,
|
__mul__,
|
||||||
__rmul__,
|
__rmul__,
|
||||||
generate_pyclass_mul_slot,
|
generate_pyclass_mul_slot,
|
||||||
|
@ -377,8 +340,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__mod__SlotFragment,
|
PyClass__mod__SlotFragment,
|
||||||
PyClass__rmod__SlotFragment,
|
PyClass__rmod__SlotFragment,
|
||||||
__mod__implemented,
|
|
||||||
__rmod__implemented,
|
|
||||||
__mod__,
|
__mod__,
|
||||||
__rmod__,
|
__rmod__,
|
||||||
generate_pyclass_mod_slot,
|
generate_pyclass_mod_slot,
|
||||||
|
@ -389,8 +350,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__divmod__SlotFragment,
|
PyClass__divmod__SlotFragment,
|
||||||
PyClass__rdivmod__SlotFragment,
|
PyClass__rdivmod__SlotFragment,
|
||||||
__divmod__implemented,
|
|
||||||
__rdivmod__implemented,
|
|
||||||
__divmod__,
|
__divmod__,
|
||||||
__rdivmod__,
|
__rdivmod__,
|
||||||
generate_pyclass_divmod_slot,
|
generate_pyclass_divmod_slot,
|
||||||
|
@ -401,8 +360,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__lshift__SlotFragment,
|
PyClass__lshift__SlotFragment,
|
||||||
PyClass__rlshift__SlotFragment,
|
PyClass__rlshift__SlotFragment,
|
||||||
__lshift__implemented,
|
|
||||||
__rlshift__implemented,
|
|
||||||
__lshift__,
|
__lshift__,
|
||||||
__rlshift__,
|
__rlshift__,
|
||||||
generate_pyclass_lshift_slot,
|
generate_pyclass_lshift_slot,
|
||||||
|
@ -413,8 +370,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__rshift__SlotFragment,
|
PyClass__rshift__SlotFragment,
|
||||||
PyClass__rrshift__SlotFragment,
|
PyClass__rrshift__SlotFragment,
|
||||||
__rshift__implemented,
|
|
||||||
__rrshift__implemented,
|
|
||||||
__rshift__,
|
__rshift__,
|
||||||
__rrshift__,
|
__rrshift__,
|
||||||
generate_pyclass_rshift_slot,
|
generate_pyclass_rshift_slot,
|
||||||
|
@ -425,8 +380,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__and__SlotFragment,
|
PyClass__and__SlotFragment,
|
||||||
PyClass__rand__SlotFragment,
|
PyClass__rand__SlotFragment,
|
||||||
__and__implemented,
|
|
||||||
__rand__implemented,
|
|
||||||
__and__,
|
__and__,
|
||||||
__rand__,
|
__rand__,
|
||||||
generate_pyclass_and_slot,
|
generate_pyclass_and_slot,
|
||||||
|
@ -437,8 +390,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__or__SlotFragment,
|
PyClass__or__SlotFragment,
|
||||||
PyClass__ror__SlotFragment,
|
PyClass__ror__SlotFragment,
|
||||||
__or__implemented,
|
|
||||||
__ror__implemented,
|
|
||||||
__or__,
|
__or__,
|
||||||
__ror__,
|
__ror__,
|
||||||
generate_pyclass_or_slot,
|
generate_pyclass_or_slot,
|
||||||
|
@ -449,8 +400,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__xor__SlotFragment,
|
PyClass__xor__SlotFragment,
|
||||||
PyClass__rxor__SlotFragment,
|
PyClass__rxor__SlotFragment,
|
||||||
__xor__implemented,
|
|
||||||
__rxor__implemented,
|
|
||||||
__xor__,
|
__xor__,
|
||||||
__rxor__,
|
__rxor__,
|
||||||
generate_pyclass_xor_slot,
|
generate_pyclass_xor_slot,
|
||||||
|
@ -461,8 +410,6 @@ define_pyclass_binary_operator_slot! {
|
||||||
define_pyclass_binary_operator_slot! {
|
define_pyclass_binary_operator_slot! {
|
||||||
PyClass__matmul__SlotFragment,
|
PyClass__matmul__SlotFragment,
|
||||||
PyClass__rmatmul__SlotFragment,
|
PyClass__rmatmul__SlotFragment,
|
||||||
__matmul__implemented,
|
|
||||||
__rmatmul__implemented,
|
|
||||||
__matmul__,
|
__matmul__,
|
||||||
__rmatmul__,
|
__rmatmul__,
|
||||||
generate_pyclass_matmul_slot,
|
generate_pyclass_matmul_slot,
|
||||||
|
|
|
@ -9,7 +9,9 @@ struct UnaryArithmetic {
|
||||||
inner: f64,
|
inner: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
impl UnaryArithmetic {
|
impl UnaryArithmetic {
|
||||||
|
#[new]
|
||||||
fn new(value: f64) -> Self {
|
fn new(value: f64) -> Self {
|
||||||
UnaryArithmetic { inner: value }
|
UnaryArithmetic { inner: value }
|
||||||
}
|
}
|
||||||
|
@ -521,7 +523,7 @@ mod return_not_implemented {
|
||||||
fn __mod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
fn __mod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||||
slf
|
slf
|
||||||
}
|
}
|
||||||
fn __pow__<'p>(slf: PyRef<'p, Self>, _other: u8, _modulo: Option<u8>) -> PyRef<'p, Self> {
|
fn __pow__(slf: PyRef<Self>, _other: u8, _modulo: Option<u8>) -> PyRef<Self> {
|
||||||
slf
|
slf
|
||||||
}
|
}
|
||||||
fn __lshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
fn __lshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||||
|
|
|
@ -158,14 +158,11 @@ fn test_hash() {
|
||||||
fn test_richcmp() {
|
fn test_richcmp() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let example_py = make_example(py);
|
let example_py = make_example(py);
|
||||||
assert_eq!(
|
assert!(example_py
|
||||||
example_py
|
.rich_compare(example_py, CompareOp::Eq)
|
||||||
.rich_compare(example_py, CompareOp::Eq)
|
.unwrap()
|
||||||
.unwrap()
|
.is_true()
|
||||||
.is_true()
|
.unwrap());
|
||||||
.unwrap(),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,4 +549,5 @@ assert c.counter.count == 3
|
||||||
// TODO: test __anext__, __aiter__
|
// TODO: test __anext__, __aiter__
|
||||||
// TODO: test __index__, __int__, __float__, __invert__
|
// TODO: test __index__, __int__, __float__, __invert__
|
||||||
// TODO: __floordiv__, __truediv__
|
// TODO: __floordiv__, __truediv__
|
||||||
|
// TODO: __pow__, __rpow__
|
||||||
// TODO: better argument casting errors
|
// TODO: better argument casting errors
|
||||||
|
|
Loading…
Reference in a new issue