Merge pull request #839 from kngwyu/radd-fix
Make __r*__ methods work with operators
This commit is contained in:
commit
85de698a0d
|
@ -7,9 +7,44 @@ pub struct Proto {
|
|||
pub py_methods: &'static [PyMethod],
|
||||
}
|
||||
|
||||
impl Proto {
|
||||
pub(crate) fn get_proto<Q>(&self, query: Q) -> Option<&'static MethodProto>
|
||||
where
|
||||
Q: PartialEq<&'static str>,
|
||||
{
|
||||
self.methods.iter().find(|m| query == m.name())
|
||||
}
|
||||
pub(crate) fn get_method<Q>(&self, query: Q) -> Option<&'static PyMethod>
|
||||
where
|
||||
Q: PartialEq<&'static str>,
|
||||
{
|
||||
self.py_methods.iter().find(|m| query == m.name)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(kngwyu): Currently only __radd__-like methods use METH_COEXIST to prevent
|
||||
// __add__-like methods from overriding them.
|
||||
pub struct PyMethod {
|
||||
pub name: &'static str,
|
||||
pub proto: &'static str,
|
||||
pub can_coexist: bool,
|
||||
}
|
||||
|
||||
impl PyMethod {
|
||||
const fn coexist(name: &'static str, proto: &'static str) -> Self {
|
||||
PyMethod {
|
||||
name,
|
||||
proto,
|
||||
can_coexist: true,
|
||||
}
|
||||
}
|
||||
const fn new(name: &'static str, proto: &'static str) -> Self {
|
||||
PyMethod {
|
||||
name,
|
||||
proto,
|
||||
can_coexist: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const OBJECT: Proto = Proto {
|
||||
|
@ -73,18 +108,9 @@ pub const OBJECT: Proto = Proto {
|
|||
},
|
||||
],
|
||||
py_methods: &[
|
||||
PyMethod {
|
||||
name: "__format__",
|
||||
proto: "pyo3::class::basic::FormatProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__bytes__",
|
||||
proto: "pyo3::class::basic::BytesProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__unicode__",
|
||||
proto: "pyo3::class::basic::UnicodeProtocolImpl",
|
||||
},
|
||||
PyMethod::new("__format__", "pyo3::class::basic::FormatProtocolImpl"),
|
||||
PyMethod::new("__bytes__", "pyo3::class::basic::BytesProtocolImpl"),
|
||||
PyMethod::new("__unicode__", "pyo3::class::basic::UnicodeProtocolImpl"),
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -120,14 +146,14 @@ pub const ASYNC: Proto = Proto {
|
|||
},
|
||||
],
|
||||
py_methods: &[
|
||||
PyMethod {
|
||||
name: "__aenter__",
|
||||
proto: "pyo3::class::pyasync::PyAsyncAenterProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__aexit__",
|
||||
proto: "pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
|
||||
},
|
||||
PyMethod::new(
|
||||
"__aenter__",
|
||||
"pyo3::class::pyasync::PyAsyncAenterProtocolImpl",
|
||||
),
|
||||
PyMethod::new(
|
||||
"__aexit__",
|
||||
"pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -165,14 +191,14 @@ pub const CONTEXT: Proto = Proto {
|
|||
},
|
||||
],
|
||||
py_methods: &[
|
||||
PyMethod {
|
||||
name: "__enter__",
|
||||
proto: "pyo3::class::context::PyContextEnterProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__exit__",
|
||||
proto: "pyo3::class::context::PyContextExitProtocolImpl",
|
||||
},
|
||||
PyMethod::new(
|
||||
"__enter__",
|
||||
"pyo3::class::context::PyContextEnterProtocolImpl",
|
||||
),
|
||||
PyMethod::new(
|
||||
"__exit__",
|
||||
"pyo3::class::context::PyContextExitProtocolImpl",
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -222,14 +248,11 @@ pub const DESCR: Proto = Proto {
|
|||
},
|
||||
],
|
||||
py_methods: &[
|
||||
PyMethod {
|
||||
name: "__del__",
|
||||
proto: "pyo3::class::context::PyDescrDelProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__set_name__",
|
||||
proto: "pyo3::class::context::PyDescrNameProtocolImpl",
|
||||
},
|
||||
PyMethod::new("__del__", "pyo3::class::context::PyDescrDelProtocolImpl"),
|
||||
PyMethod::new(
|
||||
"__set_name__",
|
||||
"pyo3::class::context::PyDescrNameProtocolImpl",
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -283,10 +306,10 @@ pub const MAPPING: Proto = Proto {
|
|||
proto: "pyo3::class::mapping::PyMappingReversedProtocol",
|
||||
},
|
||||
],
|
||||
py_methods: &[PyMethod {
|
||||
name: "__reversed__",
|
||||
proto: "pyo3::class::mapping::PyMappingReversedProtocolImpl",
|
||||
}],
|
||||
py_methods: &[PyMethod::new(
|
||||
"__reversed__",
|
||||
"pyo3::class::mapping::PyMappingReversedProtocolImpl",
|
||||
)],
|
||||
};
|
||||
|
||||
pub const SEQ: Proto = Proto {
|
||||
|
@ -579,10 +602,9 @@ pub const NUM: Proto = Proto {
|
|||
pyres: false,
|
||||
proto: "pyo3::class::number::PyNumberIModProtocol",
|
||||
},
|
||||
MethodProto::Ternary {
|
||||
MethodProto::Binary {
|
||||
name: "__ipow__",
|
||||
arg1: "Other",
|
||||
arg2: "Modulo",
|
||||
arg: "Other",
|
||||
pyres: false,
|
||||
proto: "pyo3::class::number::PyNumberIPowProtocol",
|
||||
},
|
||||
|
@ -651,81 +673,58 @@ pub const NUM: Proto = Proto {
|
|||
pyres: true,
|
||||
proto: "pyo3::class::number::PyNumberFloatProtocol",
|
||||
},
|
||||
MethodProto::Unary {
|
||||
name: "__round__",
|
||||
pyres: true,
|
||||
proto: "pyo3::class::number::PyNumberRoundProtocol",
|
||||
},
|
||||
MethodProto::Unary {
|
||||
name: "__index__",
|
||||
pyres: true,
|
||||
proto: "pyo3::class::number::PyNumberIndexProtocol",
|
||||
},
|
||||
MethodProto::Binary {
|
||||
name: "__round__",
|
||||
arg: "NDigits",
|
||||
pyres: true,
|
||||
proto: "pyo3::class::number::PyNumberRoundProtocol",
|
||||
},
|
||||
],
|
||||
py_methods: &[
|
||||
PyMethod {
|
||||
name: "__radd__",
|
||||
proto: "pyo3::class::number::PyNumberRAddProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rsub__",
|
||||
proto: "pyo3::class::number::PyNumberRSubProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rmul__",
|
||||
proto: "pyo3::class::number::PyNumberRMulProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rmatmul__",
|
||||
proto: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rtruediv__",
|
||||
proto: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rfloordiv__",
|
||||
proto: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rmod__",
|
||||
proto: "pyo3::class::number::PyNumberRModProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rdivmod__",
|
||||
proto: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rpow__",
|
||||
proto: "pyo3::class::number::PyNumberRPowProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rlshift__",
|
||||
proto: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rrshift__",
|
||||
proto: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rand__",
|
||||
proto: "pyo3::class::number::PyNumberRAndProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__rxor__",
|
||||
proto: "pyo3::class::number::PyNumberRXorProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__ror__",
|
||||
proto: "pyo3::class::number::PyNumberROrProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__complex__",
|
||||
proto: "pyo3::class::number::PyNumberComplexProtocolImpl",
|
||||
},
|
||||
PyMethod {
|
||||
name: "__round__",
|
||||
proto: "pyo3::class::number::PyNumberRoundProtocolImpl",
|
||||
},
|
||||
PyMethod::coexist("__radd__", "pyo3::class::number::PyNumberRAddProtocolImpl"),
|
||||
PyMethod::coexist("__rsub__", "pyo3::class::number::PyNumberRSubProtocolImpl"),
|
||||
PyMethod::coexist("__rmul__", "pyo3::class::number::PyNumberRMulProtocolImpl"),
|
||||
PyMethod::coexist(
|
||||
"__rmatmul__",
|
||||
"pyo3::class::number::PyNumberRMatmulProtocolImpl",
|
||||
),
|
||||
PyMethod::coexist(
|
||||
"__rtruediv__",
|
||||
"pyo3::class::number::PyNumberRTruedivProtocolImpl",
|
||||
),
|
||||
PyMethod::coexist(
|
||||
"__rfloordiv__",
|
||||
"pyo3::class::number::PyNumberRFloordivProtocolImpl",
|
||||
),
|
||||
PyMethod::coexist("__rmod__", "pyo3::class::number::PyNumberRModProtocolImpl"),
|
||||
PyMethod::coexist(
|
||||
"__rdivmod__",
|
||||
"pyo3::class::number::PyNumberRDivmodProtocolImpl",
|
||||
),
|
||||
PyMethod::coexist("__rpow__", "pyo3::class::number::PyNumberRPowProtocolImpl"),
|
||||
PyMethod::coexist(
|
||||
"__rlshift__",
|
||||
"pyo3::class::number::PyNumberRLShiftProtocolImpl",
|
||||
),
|
||||
PyMethod::coexist(
|
||||
"__rrshift__",
|
||||
"pyo3::class::number::PyNumberRRShiftProtocolImpl",
|
||||
),
|
||||
PyMethod::coexist("__rand__", "pyo3::class::number::PyNumberRAndProtocolImpl"),
|
||||
PyMethod::coexist("__rxor__", "pyo3::class::number::PyNumberRXorProtocolImpl"),
|
||||
PyMethod::coexist("__ror__", "pyo3::class::number::PyNumberROrProtocolImpl"),
|
||||
PyMethod::new(
|
||||
"__complex__",
|
||||
"pyo3::class::number::PyNumberComplexProtocolImpl",
|
||||
),
|
||||
PyMethod::new(
|
||||
"__round__",
|
||||
"pyo3::class::number::PyNumberRoundProtocolImpl",
|
||||
),
|
||||
],
|
||||
};
|
||||
|
|
|
@ -69,7 +69,7 @@ impl MethodProto {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn impl_method_proto(
|
||||
pub(crate) fn impl_method_proto(
|
||||
cls: &syn::Type,
|
||||
sig: &mut syn::Signature,
|
||||
meth: &MethodProto,
|
||||
|
|
|
@ -459,7 +459,6 @@ fn impl_descriptors(
|
|||
.collect::<syn::Result<_>>()?;
|
||||
|
||||
Ok(quote! {
|
||||
|
||||
pyo3::inventory::submit! {
|
||||
#![crate = pyo3] {
|
||||
type ClsInventory = <#cls as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;
|
||||
|
|
|
@ -63,39 +63,40 @@ fn impl_proto_impl(
|
|||
|
||||
for iimpl in impls.iter_mut() {
|
||||
if let syn::ImplItem::Method(ref mut met) = iimpl {
|
||||
for m in proto.methods {
|
||||
if met.sig.ident == m.name() {
|
||||
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
|
||||
}
|
||||
if let Some(m) = proto.get_proto(&met.sig.ident) {
|
||||
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
|
||||
}
|
||||
for m in proto.py_methods {
|
||||
if met.sig.ident == m.name {
|
||||
let name = &met.sig.ident;
|
||||
let proto: syn::Path = syn::parse_str(m.proto).unwrap();
|
||||
if let Some(m) = proto.get_method(&met.sig.ident) {
|
||||
let name = &met.sig.ident;
|
||||
let proto: syn::Path = syn::parse_str(m.proto).unwrap();
|
||||
|
||||
let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) {
|
||||
Ok(fn_spec) => fn_spec,
|
||||
Err(err) => return err.to_compile_error(),
|
||||
};
|
||||
let meth = pymethod::impl_proto_wrap(ty, &fn_spec);
|
||||
let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) {
|
||||
Ok(fn_spec) => fn_spec,
|
||||
Err(err) => return err.to_compile_error(),
|
||||
};
|
||||
let meth = pymethod::impl_proto_wrap(ty, &fn_spec);
|
||||
let coexist = if m.can_coexist {
|
||||
quote!(pyo3::ffi::METH_COEXIST)
|
||||
} else {
|
||||
quote!(0)
|
||||
};
|
||||
py_methods.push(quote! {
|
||||
impl #proto for #ty
|
||||
{
|
||||
#[inline]
|
||||
fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
|
||||
#meth
|
||||
|
||||
py_methods.push(quote! {
|
||||
impl #proto for #ty
|
||||
{
|
||||
#[inline]
|
||||
fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
|
||||
#meth
|
||||
|
||||
Some(pyo3::class::PyMethodDef {
|
||||
ml_name: stringify!(#name),
|
||||
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
|
||||
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
|
||||
ml_doc: ""
|
||||
})
|
||||
}
|
||||
Some(pyo3::class::PyMethodDef {
|
||||
ml_name: stringify!(#name),
|
||||
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
|
||||
// We need METH_COEXIST here to prevent __add__ from overriding __radd__
|
||||
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist,
|
||||
ml_doc: ""
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,29 @@ macro_rules! py_binary_num_func {
|
|||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_binary_reverse_num_func {
|
||||
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
// Swap lhs <-> rhs
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(rhs);
|
||||
let arg = py.from_borrowed_ptr::<$crate::PyAny>(lhs);
|
||||
call_ref_with_converter!(slf, $conv, py, $f, arg)
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
}};
|
||||
}
|
||||
|
||||
// NOTE(kngwyu): This macro is used only for inplace operations, so I used call_mut here.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
|
@ -256,12 +279,39 @@ macro_rules! py_ternary_num_func {
|
|||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_ternary_self_func {
|
||||
macro_rules! py_ternary_reverse_num_func {
|
||||
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject,
|
||||
arg3: *mut $crate::ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
// Swap lhs <-> rhs
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(arg2);
|
||||
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
|
||||
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg3);
|
||||
call_ref_with_converter!(slf, $conv, py, $f, arg1, arg2)
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
}};
|
||||
}
|
||||
|
||||
// NOTE(kngwyu): Somehow __ipow__ causes SIGSEGV in Python < 3.8 when we extract arg2,
|
||||
// so we ignore it. It's the same as what CPython does.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_dummy_ternary_self_func {
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject,
|
||||
_arg2: *mut $crate::ffi::PyObject,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
where
|
||||
T: for<'p> $trait<'p>,
|
||||
|
@ -270,16 +320,18 @@ macro_rules! py_ternary_self_func {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
|
||||
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2);
|
||||
let result = call_mut!(slf_cell, $f, arg1, arg2);
|
||||
let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
|
||||
let result = call_mut!(slf_, $f, arg);
|
||||
match result {
|
||||
Ok(_) => slf,
|
||||
Ok(_) => {
|
||||
ffi::Py_INCREF(slf);
|
||||
slf
|
||||
}
|
||||
Err(e) => e.restore_and_null(py),
|
||||
}
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
Some(wrap::<$class>)
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
|
|||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn __pow__(lhs: Self::Left, rhs: Self::Right, modulo: Self::Modulo) -> Self::Result
|
||||
fn __pow__(lhs: Self::Left, rhs: Self::Right, modulo: Option<Self::Modulo>) -> Self::Result
|
||||
where
|
||||
Self: PyNumberPowProtocol<'p>,
|
||||
{
|
||||
|
@ -145,7 +145,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
|
|||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn __rpow__(&'p self, other: Self::Other) -> Self::Result
|
||||
fn __rpow__(&'p self, other: Self::Other, modulo: Option<Self::Modulo>) -> Self::Result
|
||||
where
|
||||
Self: PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
|
@ -224,7 +224,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
|
|||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn __ipow__(&'p mut self, other: Self::Other, modulo: Self::Modulo) -> Self::Result
|
||||
fn __ipow__(&'p mut self, other: Self::Other) -> Self::Result
|
||||
where
|
||||
Self: PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
|
@ -304,18 +304,18 @@ pub trait PyNumberProtocol<'p>: PyClass {
|
|||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn __round__(&'p self) -> Self::Result
|
||||
where
|
||||
Self: PyNumberRoundProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn __index__(&'p self) -> Self::Result
|
||||
where
|
||||
Self: PyNumberIndexProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn __round__(&'p self, ndigits: Option<Self::NDigits>) -> Self::Result
|
||||
where
|
||||
Self: PyNumberRoundProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> {
|
||||
|
@ -544,7 +544,6 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
|
|||
|
||||
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Modulo: FromPyObject<'p>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
|
||||
|
@ -610,6 +609,7 @@ pub trait PyNumberFloatProtocol<'p>: PyNumberProtocol<'p> {
|
|||
|
||||
pub trait PyNumberRoundProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Success: IntoPy<PyObject>;
|
||||
type NDigits: FromPyObject<'p>;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
||||
|
@ -647,22 +647,22 @@ where
|
|||
{
|
||||
fn tp_as_number() -> Option<ffi::PyNumberMethods> {
|
||||
Some(ffi::PyNumberMethods {
|
||||
nb_add: Self::nb_add(),
|
||||
nb_subtract: Self::nb_subtract(),
|
||||
nb_multiply: Self::nb_multiply(),
|
||||
nb_add: Self::nb_add().or_else(Self::nb_add_fallback),
|
||||
nb_subtract: Self::nb_subtract().or_else(Self::nb_sub_fallback),
|
||||
nb_multiply: Self::nb_multiply().or_else(Self::nb_mul_fallback),
|
||||
nb_remainder: Self::nb_remainder(),
|
||||
nb_divmod: Self::nb_divmod(),
|
||||
nb_power: Self::nb_power(),
|
||||
nb_divmod: Self::nb_divmod().or_else(Self::nb_divmod_fallback),
|
||||
nb_power: Self::nb_power().or_else(Self::nb_pow_fallback),
|
||||
nb_negative: Self::nb_negative(),
|
||||
nb_positive: Self::nb_positive(),
|
||||
nb_absolute: Self::nb_absolute(),
|
||||
nb_bool: <Self as PyObjectProtocolImpl>::nb_bool_fn(),
|
||||
nb_invert: Self::nb_invert(),
|
||||
nb_lshift: Self::nb_lshift(),
|
||||
nb_rshift: Self::nb_rshift(),
|
||||
nb_and: Self::nb_and(),
|
||||
nb_xor: Self::nb_xor(),
|
||||
nb_or: Self::nb_or(),
|
||||
nb_lshift: Self::nb_lshift().or_else(Self::nb_lshift_fallback),
|
||||
nb_rshift: Self::nb_rshift().or_else(Self::nb_rshift_fallback),
|
||||
nb_and: Self::nb_and().or_else(Self::nb_and_fallback),
|
||||
nb_xor: Self::nb_xor().or_else(Self::nb_xor_fallback),
|
||||
nb_or: Self::nb_or().or_else(Self::nb_or_fallback),
|
||||
nb_int: Self::nb_int(),
|
||||
nb_reserved: ::std::ptr::null_mut(),
|
||||
nb_float: Self::nb_float(),
|
||||
|
@ -676,12 +676,12 @@ where
|
|||
nb_inplace_and: Self::nb_inplace_and(),
|
||||
nb_inplace_xor: Self::nb_inplace_xor(),
|
||||
nb_inplace_or: Self::nb_inplace_or(),
|
||||
nb_floor_divide: Self::nb_floor_divide(),
|
||||
nb_true_divide: Self::nb_true_divide(),
|
||||
nb_floor_divide: Self::nb_floor_divide().or_else(Self::nb_floordiv_fallback),
|
||||
nb_true_divide: Self::nb_true_divide().or_else(Self::nb_truediv_fallback),
|
||||
nb_inplace_floor_divide: Self::nb_inplace_floor_divide(),
|
||||
nb_inplace_true_divide: Self::nb_inplace_true_divide(),
|
||||
nb_index: Self::nb_index(),
|
||||
nb_matrix_multiply: Self::nb_matrix_multiply(),
|
||||
nb_matrix_multiply: Self::nb_matrix_multiply().or_else(Self::nb_matmul_fallback),
|
||||
nb_inplace_matrix_multiply: Self::nb_inplace_matrix_multiply(),
|
||||
})
|
||||
}
|
||||
|
@ -1279,7 +1279,7 @@ where
|
|||
T: for<'p> PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
|
||||
py_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__)
|
||||
py_dummy_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1407,14 +1407,72 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRSubProtocolImpl {
|
||||
fn __rsub__() -> Option<PyMethodDef> {
|
||||
// Fallback trait for nb_add
|
||||
trait PyNumberAddFallback {
|
||||
fn nb_add_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberAddFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_add_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
|
||||
impl<T> PyNumberAddFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRAddProtocol<'p>,
|
||||
{
|
||||
fn nb_add_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRAddProtocol,
|
||||
T::__radd__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRSubProtocolImpl {
|
||||
fn __rsub__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRSubProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rsub__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberSubFallback {
|
||||
fn nb_sub_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberSubFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_sub_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberSubFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRSubProtocol<'p>,
|
||||
{
|
||||
fn nb_sub_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRSubProtocol,
|
||||
T::__rsub__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRMulProtocolImpl {
|
||||
|
@ -1430,6 +1488,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberMulFallback {
|
||||
fn nb_mul_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberMulFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_mul_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberMulFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRMulProtocol<'p>,
|
||||
{
|
||||
fn nb_mul_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRMulProtocol,
|
||||
T::__rmul__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRMatmulProtocolImpl {
|
||||
fn __rmatmul__() -> Option<PyMethodDef>;
|
||||
|
@ -1444,6 +1528,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberMatmulFallback {
|
||||
fn nb_matmul_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberMatmulFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_matmul_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberMatmulFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRMatmulProtocol<'p>,
|
||||
{
|
||||
fn nb_matmul_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRMatmulProtocol,
|
||||
T::__rmatmul__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRTruedivProtocolImpl {
|
||||
fn __rtruediv__() -> Option<PyMethodDef>;
|
||||
|
@ -1458,6 +1568,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberTruedivFallback {
|
||||
fn nb_truediv_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberTruedivFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_truediv_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberTruedivFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRTruedivProtocol<'p>,
|
||||
{
|
||||
fn nb_truediv_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRTruedivProtocol,
|
||||
T::__rtruediv__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRFloordivProtocolImpl {
|
||||
fn __rfloordiv__() -> Option<PyMethodDef>;
|
||||
|
@ -1472,6 +1608,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberFloordivFallback {
|
||||
fn nb_floordiv_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberFloordivFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_floordiv_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberFloordivFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRFloordivProtocol<'p>,
|
||||
{
|
||||
fn nb_floordiv_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRFloordivProtocol,
|
||||
T::__rfloordiv__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRModProtocolImpl {
|
||||
fn __rmod__() -> Option<PyMethodDef>;
|
||||
|
@ -1486,6 +1648,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberModFallback {
|
||||
fn nb_mod_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberModFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_mod_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberModFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRModProtocol<'p>,
|
||||
{
|
||||
fn nb_mod_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRModProtocol,
|
||||
T::__rmod__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRDivmodProtocolImpl {
|
||||
fn __rdivmod__() -> Option<PyMethodDef>;
|
||||
|
@ -1500,6 +1688,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberDivmodFallback {
|
||||
fn nb_divmod_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberDivmodFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_divmod_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberDivmodFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRDivmodProtocol<'p>,
|
||||
{
|
||||
fn nb_divmod_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRDivmodProtocol,
|
||||
T::__rdivmod__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRPowProtocolImpl {
|
||||
fn __rpow__() -> Option<PyMethodDef>;
|
||||
|
@ -1514,6 +1728,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberPowFallback {
|
||||
fn nb_pow_fallback() -> Option<ffi::ternaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberPowFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_pow_fallback() -> Option<ffi::ternaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberPowFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRPowProtocol<'p>,
|
||||
{
|
||||
fn nb_pow_fallback() -> Option<ffi::ternaryfunc> {
|
||||
py_ternary_reverse_num_func!(
|
||||
PyNumberRPowProtocol,
|
||||
T::__rpow__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRLShiftProtocolImpl {
|
||||
fn __rlshift__() -> Option<PyMethodDef>;
|
||||
|
@ -1528,6 +1768,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberLShiftFallback {
|
||||
fn nb_lshift_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberLShiftFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_lshift_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberLShiftFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRLShiftProtocol<'p>,
|
||||
{
|
||||
fn nb_lshift_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRLShiftProtocol,
|
||||
T::__rlshift__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRRShiftProtocolImpl {
|
||||
fn __rrshift__() -> Option<PyMethodDef>;
|
||||
|
@ -1542,6 +1808,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberRRshiftFallback {
|
||||
fn nb_rshift_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRRshiftFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_rshift_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberRRshiftFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRRShiftProtocol<'p>,
|
||||
{
|
||||
fn nb_rshift_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRRShiftProtocol,
|
||||
T::__rrshift__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRAndProtocolImpl {
|
||||
fn __rand__() -> Option<PyMethodDef>;
|
||||
|
@ -1556,6 +1848,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberAndFallback {
|
||||
fn nb_and_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberAndFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_and_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberAndFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRAndProtocol<'p>,
|
||||
{
|
||||
fn nb_and_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRAndProtocol,
|
||||
T::__rand__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRXorProtocolImpl {
|
||||
fn __rxor__() -> Option<PyMethodDef>;
|
||||
|
@ -1570,6 +1888,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberXorFallback {
|
||||
fn nb_xor_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberXorFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_xor_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberXorFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberRXorProtocol<'p>,
|
||||
{
|
||||
fn nb_xor_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberRXorProtocol,
|
||||
T::__rxor__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberROrProtocolImpl {
|
||||
fn __ror__() -> Option<PyMethodDef>;
|
||||
|
@ -1584,6 +1928,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberOrFallback {
|
||||
fn nb_or_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberOrFallback for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn nb_or_fallback() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyNumberOrFallback for T
|
||||
where
|
||||
T: for<'p> PyNumberROrProtocol<'p>,
|
||||
{
|
||||
fn nb_or_fallback() -> Option<ffi::binaryfunc> {
|
||||
py_binary_reverse_num_func!(
|
||||
PyNumberROrProtocol,
|
||||
T::__ror__,
|
||||
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberNegProtocolImpl {
|
||||
fn nb_negative() -> Option<ffi::unaryfunc>;
|
||||
}
|
||||
|
@ -1767,7 +2137,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberComplexProtocolImpl {
|
||||
pub trait PyNumberComplexProtocolImpl {
|
||||
fn __complex__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
|
@ -1780,7 +2150,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait PyNumberRoundProtocolImpl {
|
||||
pub trait PyNumberRoundProtocolImpl {
|
||||
fn __round__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,6 @@ impl Drop for GILGuard {
|
|||
unsafe {
|
||||
let pool: &'static mut ReleasePool = &mut *POOL;
|
||||
pool.drain(self.python(), self.owned, self.borrowed);
|
||||
|
||||
ffi::PyGILState_Release(self.gstate);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,24 +8,39 @@ use pyo3::py_run;
|
|||
mod common;
|
||||
|
||||
#[pyclass]
|
||||
struct UnaryArithmetic {}
|
||||
struct UnaryArithmetic {
|
||||
inner: f64,
|
||||
}
|
||||
|
||||
impl UnaryArithmetic {
|
||||
fn new(value: f64) -> Self {
|
||||
UnaryArithmetic { inner: value }
|
||||
}
|
||||
}
|
||||
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for UnaryArithmetic {
|
||||
fn __repr__(&self) -> PyResult<String> {
|
||||
Ok(format!("UA({})", self.inner))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for UnaryArithmetic {
|
||||
fn __neg__(&self) -> PyResult<&'static str> {
|
||||
Ok("neg")
|
||||
fn __neg__(&self) -> PyResult<Self> {
|
||||
Ok(Self::new(-self.inner))
|
||||
}
|
||||
|
||||
fn __pos__(&self) -> PyResult<&'static str> {
|
||||
Ok("pos")
|
||||
fn __pos__(&self) -> PyResult<Self> {
|
||||
Ok(Self::new(self.inner))
|
||||
}
|
||||
|
||||
fn __abs__(&self) -> PyResult<&'static str> {
|
||||
Ok("abs")
|
||||
fn __abs__(&self) -> PyResult<Self> {
|
||||
Ok(Self::new(self.inner.abs()))
|
||||
}
|
||||
|
||||
fn __invert__(&self) -> PyResult<&'static str> {
|
||||
Ok("invert")
|
||||
fn __round__(&self, _ndigits: Option<u32>) -> PyResult<Self> {
|
||||
Ok(Self::new(self.inner.round()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,11 +49,12 @@ fn unary_arithmetic() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Py::new(py, UnaryArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert -c == 'neg'");
|
||||
py_run!(py, c, "assert +c == 'pos'");
|
||||
py_run!(py, c, "assert abs(c) == 'abs'");
|
||||
py_run!(py, c, "assert ~c == 'invert'");
|
||||
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
|
||||
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
|
||||
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
|
||||
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -104,15 +120,19 @@ impl PyNumberProtocol for InPlaceOperations {
|
|||
self.value |= other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ipow__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value.pow(other);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inplace_operations() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let init = |value, code| {
|
||||
let c = Py::new(py, InPlaceOperations { value }).unwrap();
|
||||
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
|
||||
py_run!(py, c, code);
|
||||
};
|
||||
|
||||
|
@ -124,6 +144,11 @@ fn inplace_operations() {
|
|||
init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'");
|
||||
init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
|
||||
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||
init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'");
|
||||
init(
|
||||
3,
|
||||
"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
|
||||
);
|
||||
}
|
||||
|
||||
#[pyproto]
|
||||
|
@ -159,6 +184,10 @@ impl PyNumberProtocol for BinaryArithmetic {
|
|||
fn __or__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} | {:?}", lhs, rhs))
|
||||
}
|
||||
|
||||
fn __pow__(lhs: &PyAny, rhs: &PyAny, mod_: Option<u32>) -> PyResult<String> {
|
||||
Ok(format!("{:?} ** {:?} (mod: {:?})", lhs, rhs, mod_))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -166,8 +195,9 @@ fn binary_arithmetic() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Py::new(py, BinaryArithmetic {}).unwrap();
|
||||
let c = PyCell::new(py, BinaryArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c + c == 'BA + BA'");
|
||||
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
|
||||
py_run!(py, c, "assert c + 1 == 'BA + 1'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + BA'");
|
||||
py_run!(py, c, "assert c - 1 == 'BA - 1'");
|
||||
|
@ -185,6 +215,10 @@ fn binary_arithmetic() {
|
|||
py_run!(py, c, "assert 1 ^ c == '1 ^ BA'");
|
||||
py_run!(py, c, "assert c | 1 == 'BA | 1'");
|
||||
py_run!(py, c, "assert 1 | c == '1 | BA'");
|
||||
py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'");
|
||||
py_run!(py, c, "assert 1 ** c == '1 ** BA (mod: None)'");
|
||||
|
||||
py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -195,6 +229,38 @@ impl PyNumberProtocol for RhsArithmetic {
|
|||
fn __radd__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} + RA", other))
|
||||
}
|
||||
|
||||
fn __rsub__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} - RA", other))
|
||||
}
|
||||
|
||||
fn __rmul__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} * RA", other))
|
||||
}
|
||||
|
||||
fn __rlshift__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} << RA", other))
|
||||
}
|
||||
|
||||
fn __rrshift__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} >> RA", other))
|
||||
}
|
||||
|
||||
fn __rand__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} & RA", other))
|
||||
}
|
||||
|
||||
fn __rxor__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} ^ RA", other))
|
||||
}
|
||||
|
||||
fn __ror__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} | RA", other))
|
||||
}
|
||||
|
||||
fn __rpow__(&self, other: &PyAny, _mod: Option<&'p PyAny>) -> PyResult<String> {
|
||||
Ok(format!("{:?} ** RA", other))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -202,11 +268,78 @@ fn rhs_arithmetic() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Py::new(py, RhsArithmetic {}).unwrap();
|
||||
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
|
||||
// TODO: commented out for now until reflected arithemtics gets fixed.
|
||||
// see discussion here: https://github.com/PyO3/pyo3/pull/550
|
||||
// py_run!(py, c, "assert 1 + c == '1 + RA'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + RA'");
|
||||
py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
|
||||
py_run!(py, c, "assert 1 - c == '1 - RA'");
|
||||
py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'");
|
||||
py_run!(py, c, "assert 1 * c == '1 * RA'");
|
||||
py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'");
|
||||
py_run!(py, c, "assert 1 << c == '1 << RA'");
|
||||
py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'");
|
||||
py_run!(py, c, "assert 1 >> c == '1 >> RA'");
|
||||
py_run!(py, c, "assert c.__rand__(1) == '1 & RA'");
|
||||
py_run!(py, c, "assert 1 & c == '1 & RA'");
|
||||
py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'");
|
||||
py_run!(py, c, "assert 1 ^ c == '1 ^ RA'");
|
||||
py_run!(py, c, "assert c.__ror__(1) == '1 | RA'");
|
||||
py_run!(py, c, "assert 1 | c == '1 | RA'");
|
||||
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
|
||||
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
struct LhsAndRhsArithmetic {}
|
||||
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for LhsAndRhsArithmetic {
|
||||
fn __radd__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} + RA", other))
|
||||
}
|
||||
|
||||
fn __rsub__(&self, other: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} - RA", other))
|
||||
}
|
||||
|
||||
fn __rpow__(&self, other: &PyAny, _mod: Option<&'p PyAny>) -> PyResult<String> {
|
||||
Ok(format!("{:?} ** RA", other))
|
||||
}
|
||||
|
||||
fn __add__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", lhs, rhs))
|
||||
}
|
||||
|
||||
fn __sub__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
|
||||
Ok(format!("{:?} - {:?}", lhs, rhs))
|
||||
}
|
||||
|
||||
fn __pow__(lhs: &PyAny, rhs: &PyAny, _mod: Option<u32>) -> PyResult<String> {
|
||||
Ok(format!("{:?} ** {:?}", lhs, rhs))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for LhsAndRhsArithmetic {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("BA")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lhs_override_rhs() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, LhsAndRhsArithmetic {}).unwrap();
|
||||
// Not overrided
|
||||
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
|
||||
py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
|
||||
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
|
||||
// Overrided
|
||||
py_run!(py, c, "assert 1 + c == '1 + BA'");
|
||||
py_run!(py, c, "assert 1 - c == '1 - BA'");
|
||||
py_run!(py, c, "assert 1 ** c == '1 ** BA'");
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -254,7 +387,7 @@ fn rich_comparisons() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Py::new(py, RichComparisons {}).unwrap();
|
||||
let c = PyCell::new(py, RichComparisons {}).unwrap();
|
||||
py_run!(py, c, "assert (c < c) == 'RC < RC'");
|
||||
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
|
||||
|
@ -280,7 +413,7 @@ fn rich_comparisons_python_3_type_error() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c2 = Py::new(py, RichComparisons2 {}).unwrap();
|
||||
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
|
||||
py_expect_exception!(py, c2, "c2 < c2", TypeError);
|
||||
py_expect_exception!(py, c2, "c2 < 1", TypeError);
|
||||
py_expect_exception!(py, c2, "1 < c2", TypeError);
|
||||
|
|
Loading…
Reference in New Issue