py_class!: __add__, __sub__, __mul__, __neg__, __pos__, __abs__, __invert__
This commit is contained in:
parent
04081bc8de
commit
4535827f8e
|
@ -324,6 +324,24 @@ TODO: implement support for `__cmp__`, `__lt__`, `__le__`, `__gt__`, `__ge__`, `
|
|||
If extraction of the `item` parameter fails with `TypeError`,
|
||||
`__contains__` will return `Ok(false)`.
|
||||
|
||||
## Arithmetic methods
|
||||
|
||||
* `def __add__(lhs, rhs) -> PyResult<impl ToPyObject>`
|
||||
* `def __sub__(lhs, rhs) -> PyResult<impl ToPyObject>`
|
||||
* `def __mul__(lhs, rhs) -> PyResult<impl ToPyObject>`
|
||||
|
||||
The parameters `lhs` and `rhs` must not be given an explicit type.
|
||||
Within the method bodies, both parameters will implicitly have type `&PyObject`.
|
||||
|
||||
There are no separate "reversed" versions of these methods (`__radd__()`, etc.)
|
||||
Instead, if the first operand cannot perform the operation,
|
||||
the same method of the second operand is called, with the operands in the same order.
|
||||
|
||||
This means that you can't rely on the first parameter of these methods being `self`
|
||||
or being the right type, and you should test the types of both operands before deciding what to do.
|
||||
If you can't handle the combination of types you've been given,
|
||||
you should return `Ok(py.NotImplemented())`.
|
||||
|
||||
## Other Special Methods
|
||||
|
||||
* `def __bool__(&self) -> PyResult<bool>`
|
||||
|
|
|
@ -505,11 +505,9 @@ def normal_method(special_name):
|
|||
def special_class_method(special_name, *args, **kwargs):
|
||||
generate_class_method(special_name=special_name, *args, **kwargs)
|
||||
|
||||
Argument = namedtuple('Argument', ['name', 'default_type'])
|
||||
class Argument(object):
|
||||
def __init__(self, name, extract_err='passthrough'):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.extract_err = 'py_class_extract_error_%s' % extract_err
|
||||
|
||||
@special_method
|
||||
def operator(special_name, slot,
|
||||
|
@ -535,12 +533,14 @@ def operator(special_name, slot,
|
|||
for arg in args:
|
||||
arg_pattern += ', ${0}:ident : ${0}_type:ty'.format(arg.name)
|
||||
param_list.append('{{ ${0} : ${0}_type = {{}} }}'.format(arg.name))
|
||||
if len(args) == 0:
|
||||
if slot == 'sq_contains':
|
||||
new_slots = [(slot, 'py_class_contains_slot!($class::%s, $%s_type)' % (special_name, args[0].name))]
|
||||
elif len(args) == 0:
|
||||
new_slots = [(slot, 'py_class_unary_slot!($class::%s, %s, %s)'
|
||||
% (special_name, res_ffi_type, res_conv))]
|
||||
elif len(args) == 1:
|
||||
new_slots = [(slot, 'py_class_binary_slot!($class::%s, $%s_type, %s, %s, %s)'
|
||||
% (special_name, args[0].name, args[0].extract_err, res_ffi_type, res_conv))]
|
||||
new_slots = [(slot, 'py_class_binary_slot!($class::%s, $%s_type, %s, %s)'
|
||||
% (special_name, args[0].name, res_ffi_type, res_conv))]
|
||||
elif len(args) == 2:
|
||||
new_slots = [(slot, 'py_class_ternary_slot!($class::%s, $%s_type, $%s_type, %s, %s)'
|
||||
% (special_name, args[0].name, args[1].name, res_ffi_type, res_conv))]
|
||||
|
@ -564,6 +564,22 @@ def call_operator(special_name, slot):
|
|||
value_macro='py_class_call_slot',
|
||||
value_args='$class::%s' % special_name)
|
||||
|
||||
@special_method
|
||||
def binary_numeric_operator(special_name, slot):
|
||||
generate_case(
|
||||
pattern='def %s($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* }'
|
||||
% special_name,
|
||||
new_impl='py_class_impl_item! { $class, $py, %s() $res_type; { $($body)* } ' % special_name
|
||||
+'[ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }',
|
||||
new_slots=[(slot, 'py_class_binary_numeric_slot!($class::%s)' % special_name)]
|
||||
)
|
||||
error('Invalid signature for binary numeric operator %s' % special_name)(special_name)
|
||||
|
||||
@special_method
|
||||
def reflected_numeric_operator(special_name):
|
||||
error('Reflected numeric operator %s is not supported by py_class! Use __%s__ instead!'
|
||||
% (special_name, special_name[3:-2]))(special_name)
|
||||
|
||||
special_names = {
|
||||
'__init__': error('__init__ is not supported by py_class!; use __new__ instead.'),
|
||||
'__new__': special_class_method(
|
||||
|
@ -634,14 +650,12 @@ special_names = {
|
|||
'__next__': operator('tp_iternext',
|
||||
res_conv='$crate::py_class::slots::IterNextResultConverter'),
|
||||
'__reversed__': normal_method(),
|
||||
'__contains__': operator('sq_contains',
|
||||
args=[Argument('item', extract_err='false')],
|
||||
res_type='bool'),
|
||||
'__contains__': operator('sq_contains', args=[Argument('item')]),
|
||||
|
||||
# Emulating numeric types
|
||||
'__add__': unimplemented(),
|
||||
'__sub__': unimplemented(),
|
||||
'__mul__': unimplemented(),
|
||||
'__add__': binary_numeric_operator('nb_add'),
|
||||
'__sub__': binary_numeric_operator('nb_subtract'),
|
||||
'__mul__': binary_numeric_operator('nb_multiply'),
|
||||
'__matmul__': unimplemented(),
|
||||
'__div__': unimplemented(),
|
||||
'__truediv__': unimplemented(),
|
||||
|
@ -656,21 +670,21 @@ special_names = {
|
|||
'__or__': unimplemented(),
|
||||
|
||||
# Emulating numeric types - reflected
|
||||
'__radd__': unimplemented(),
|
||||
'__rsub__': unimplemented(),
|
||||
'__rmul__': unimplemented(),
|
||||
'__rmatmul__': unimplemented(),
|
||||
'__rdiv__': unimplemented(),
|
||||
'__rtruediv__': unimplemented(),
|
||||
'__rfloordiv__': unimplemented(),
|
||||
'__rmod__': unimplemented(),
|
||||
'__rdivmod__': unimplemented(),
|
||||
'__rpow__': unimplemented(),
|
||||
'__rlshift__': unimplemented(),
|
||||
'__rrshift__': unimplemented(),
|
||||
'__rand__': unimplemented(),
|
||||
'__rxor__': unimplemented(),
|
||||
'__ror__': unimplemented(),
|
||||
'__radd__': reflected_numeric_operator(),
|
||||
'__rsub__': reflected_numeric_operator(),
|
||||
'__rmul__': reflected_numeric_operator(),
|
||||
'__rmatmul__': reflected_numeric_operator(),
|
||||
'__rdiv__': reflected_numeric_operator(),
|
||||
'__rtruediv__': reflected_numeric_operator(),
|
||||
'__rfloordiv__': reflected_numeric_operator(),
|
||||
'__rmod__': reflected_numeric_operator(),
|
||||
'__rdivmod__': reflected_numeric_operator(),
|
||||
'__rpow__': reflected_numeric_operator(),
|
||||
'__rlshift__': reflected_numeric_operator(),
|
||||
'__rrshift__': reflected_numeric_operator(),
|
||||
'__rand__': reflected_numeric_operator(),
|
||||
'__rxor__': reflected_numeric_operator(),
|
||||
'__ror__': reflected_numeric_operator(),
|
||||
|
||||
# Emulating numeric types - in-place
|
||||
'__iadd__': unimplemented(),
|
||||
|
@ -690,10 +704,10 @@ special_names = {
|
|||
'__ior__': unimplemented(),
|
||||
|
||||
# Unary arithmetic
|
||||
'__neg__': unimplemented(),
|
||||
'__pos__': unimplemented(),
|
||||
'__abs__': unimplemented(),
|
||||
'__invert__': unimplemented(),
|
||||
'__neg__': operator('nb_negative'),
|
||||
'__pos__': operator('nb_positive'),
|
||||
'__abs__': operator('nb_absolute'),
|
||||
'__invert__': operator('nb_invert'),
|
||||
'__complex__': unimplemented(),
|
||||
'__int__': unimplemented(),
|
||||
'__long__': unimplemented(),
|
||||
|
|
|
@ -293,13 +293,65 @@ macro_rules! py_class_impl {
|
|||
}
|
||||
$members
|
||||
}};
|
||||
{ { def __abs__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_absolute: py_class_unary_slot!($class::__abs__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __abs__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __abs__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__abs__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __abs__" }
|
||||
};
|
||||
{ { def __add__($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_add: py_class_binary_numeric_slot!($class::__add__),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __add__() $res_type; { $($body)* } [ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __add__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__add__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for binary numeric operator __add__" }
|
||||
};
|
||||
|
||||
{ { def __aenter__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -430,7 +482,7 @@ macro_rules! py_class_impl {
|
|||
$type_slots $as_number
|
||||
/* as_sequence */ [
|
||||
$( $sq_slot_name : $sq_slot_value, )*
|
||||
sq_contains: py_class_binary_slot!($class::__contains__, $item_type, py_class_extract_error_false, $crate::_detail::libc::c_int, $crate::py_class::slots::BoolConverter),
|
||||
sq_contains: py_class_contains_slot!($class::__contains__, $item_type),
|
||||
]
|
||||
$as_mapping $setdelitem
|
||||
}
|
||||
|
@ -474,7 +526,7 @@ macro_rules! py_class_impl {
|
|||
$type_slots $as_number $as_sequence $as_mapping
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: $sdi_setitem_slot_value,
|
||||
sdi_delitem: { py_class_binary_slot!($class::__delitem__, $key_type, py_class_extract_error_passthrough, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
sdi_delitem: { py_class_binary_slot!($class::__delitem__, $key_type, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
|
@ -556,7 +608,7 @@ macro_rules! py_class_impl {
|
|||
]
|
||||
/* as_mapping */ [
|
||||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_subscript: py_class_binary_slot!($class::__getitem__, $key_type, py_class_extract_error_passthrough, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
mp_subscript: py_class_binary_slot!($class::__getitem__, $key_type, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$setdelitem
|
||||
}
|
||||
|
@ -654,9 +706,35 @@ macro_rules! py_class_impl {
|
|||
{ { def __int__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__int__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __invert__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_invert: py_class_unary_slot!($class::__invert__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __invert__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __invert__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__invert__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __invert__" }
|
||||
};
|
||||
|
||||
{ { def __ior__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -769,17 +847,69 @@ macro_rules! py_class_impl {
|
|||
{ { def __mod__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__mod__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __mul__($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_multiply: py_class_binary_numeric_slot!($class::__mul__),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __mul__() $res_type; { $($body)* } [ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __mul__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__mul__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for binary numeric operator __mul__" }
|
||||
};
|
||||
|
||||
{ { def __ne__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__ne__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __neg__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_negative: py_class_unary_slot!($class::__neg__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __neg__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __neg__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__neg__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __neg__" }
|
||||
};
|
||||
{ { def __new__ ($cls:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
|
@ -868,9 +998,35 @@ macro_rules! py_class_impl {
|
|||
{ { def __or__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__or__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __pos__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_positive: py_class_unary_slot!($class::__pos__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __pos__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __pos__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__pos__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __pos__" }
|
||||
};
|
||||
|
||||
{ { def __pow__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -878,19 +1034,19 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __radd__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__radd__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __radd__ is not supported by py_class! Use __add__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rand__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rand__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rand__ is not supported by py_class! Use __and__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rdiv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rdiv__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rdiv__ is not supported by py_class! Use __div__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rdivmod__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rdivmod__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rdivmod__ is not supported by py_class! Use __divmod__ instead!" }
|
||||
};
|
||||
{ { def __repr__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
|
@ -922,27 +1078,27 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __rfloordiv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rfloordiv__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rfloordiv__ is not supported by py_class! Use __floordiv__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rlshift__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rlshift__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rlshift__ is not supported by py_class! Use __lshift__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rmatmul__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rmatmul__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rmatmul__ is not supported by py_class! Use __matmul__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rmod__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rmod__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rmod__ is not supported by py_class! Use __mod__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rmul__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rmul__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rmul__ is not supported by py_class! Use __mul__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __ror__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__ror__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __ror__ is not supported by py_class! Use __or__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __round__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -950,11 +1106,11 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __rpow__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rpow__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rpow__ is not supported by py_class! Use __pow__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rrshift__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rrshift__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rrshift__ is not supported by py_class! Use __rshift__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rshift__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -962,15 +1118,15 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __rsub__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rsub__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rsub__ is not supported by py_class! Use __sub__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rtruediv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rtruediv__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rtruediv__ is not supported by py_class! Use __truediv__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rxor__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rxor__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rxor__ is not supported by py_class! Use __xor__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __set__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -1039,9 +1195,35 @@ macro_rules! py_class_impl {
|
|||
{ { def __str__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for operator __str__" }
|
||||
};
|
||||
{ { def __sub__($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_subtract: py_class_binary_numeric_slot!($class::__sub__),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __sub__() $res_type; { $($body)* } [ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __sub__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__sub__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for binary numeric operator __sub__" }
|
||||
};
|
||||
|
||||
{ { def __subclasscheck__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
|
|
@ -293,13 +293,65 @@ macro_rules! py_class_impl {
|
|||
}
|
||||
$members
|
||||
}};
|
||||
{ { def __abs__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_absolute: py_class_unary_slot!($class::__abs__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __abs__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __abs__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__abs__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __abs__" }
|
||||
};
|
||||
{ { def __add__($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_add: py_class_binary_numeric_slot!($class::__add__),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __add__() $res_type; { $($body)* } [ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __add__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__add__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for binary numeric operator __add__" }
|
||||
};
|
||||
|
||||
{ { def __aenter__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -430,7 +482,7 @@ macro_rules! py_class_impl {
|
|||
$type_slots $as_number
|
||||
/* as_sequence */ [
|
||||
$( $sq_slot_name : $sq_slot_value, )*
|
||||
sq_contains: py_class_binary_slot!($class::__contains__, $item_type, py_class_extract_error_false, $crate::_detail::libc::c_int, $crate::py_class::slots::BoolConverter),
|
||||
sq_contains: py_class_contains_slot!($class::__contains__, $item_type),
|
||||
]
|
||||
$as_mapping $setdelitem
|
||||
}
|
||||
|
@ -474,7 +526,7 @@ macro_rules! py_class_impl {
|
|||
$type_slots $as_number $as_sequence $as_mapping
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: $sdi_setitem_slot_value,
|
||||
sdi_delitem: { py_class_binary_slot!($class::__delitem__, $key_type, py_class_extract_error_passthrough, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
sdi_delitem: { py_class_binary_slot!($class::__delitem__, $key_type, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
|
@ -556,7 +608,7 @@ macro_rules! py_class_impl {
|
|||
]
|
||||
/* as_mapping */ [
|
||||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_subscript: py_class_binary_slot!($class::__getitem__, $key_type, py_class_extract_error_passthrough, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
mp_subscript: py_class_binary_slot!($class::__getitem__, $key_type, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$setdelitem
|
||||
}
|
||||
|
@ -654,9 +706,35 @@ macro_rules! py_class_impl {
|
|||
{ { def __int__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__int__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __invert__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_invert: py_class_unary_slot!($class::__invert__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __invert__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __invert__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__invert__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __invert__" }
|
||||
};
|
||||
|
||||
{ { def __ior__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -769,17 +847,69 @@ macro_rules! py_class_impl {
|
|||
{ { def __mod__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__mod__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __mul__($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_multiply: py_class_binary_numeric_slot!($class::__mul__),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __mul__() $res_type; { $($body)* } [ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __mul__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__mul__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for binary numeric operator __mul__" }
|
||||
};
|
||||
|
||||
{ { def __ne__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__ne__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __neg__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_negative: py_class_unary_slot!($class::__neg__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __neg__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __neg__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__neg__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __neg__" }
|
||||
};
|
||||
{ { def __new__ ($cls:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
|
@ -868,9 +998,35 @@ macro_rules! py_class_impl {
|
|||
{ { def __or__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__or__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __pos__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_positive: py_class_unary_slot!($class::__pos__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __pos__(&$slf,) $res_type; { $($body)* } [] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __pos__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__pos__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __pos__" }
|
||||
};
|
||||
|
||||
{ { def __pow__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -878,19 +1034,19 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __radd__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__radd__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __radd__ is not supported by py_class! Use __add__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rand__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rand__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rand__ is not supported by py_class! Use __and__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rdiv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rdiv__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rdiv__ is not supported by py_class! Use __div__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rdivmod__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rdivmod__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rdivmod__ is not supported by py_class! Use __divmod__ instead!" }
|
||||
};
|
||||
{ { def __repr__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
|
@ -922,27 +1078,27 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __rfloordiv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rfloordiv__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rfloordiv__ is not supported by py_class! Use __floordiv__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rlshift__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rlshift__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rlshift__ is not supported by py_class! Use __lshift__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rmatmul__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rmatmul__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rmatmul__ is not supported by py_class! Use __matmul__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rmod__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rmod__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rmod__ is not supported by py_class! Use __mod__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rmul__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rmul__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rmul__ is not supported by py_class! Use __mul__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __ror__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__ror__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __ror__ is not supported by py_class! Use __or__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __round__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -950,11 +1106,11 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __rpow__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rpow__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rpow__ is not supported by py_class! Use __pow__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rrshift__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rrshift__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rrshift__ is not supported by py_class! Use __rshift__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rshift__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -962,15 +1118,15 @@ macro_rules! py_class_impl {
|
|||
};
|
||||
|
||||
{ { def __rsub__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rsub__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rsub__ is not supported by py_class! Use __sub__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rtruediv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rtruediv__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rtruediv__ is not supported by py_class! Use __truediv__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __rxor__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__rxor__ is not supported by py_class! yet." }
|
||||
py_error! { "Reflected numeric operator __rxor__ is not supported by py_class! Use __xor__ instead!" }
|
||||
};
|
||||
|
||||
{ { def __set__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -1039,9 +1195,35 @@ macro_rules! py_class_impl {
|
|||
{ { def __str__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for operator __str__" }
|
||||
};
|
||||
{ { def __sub__($left:ident, $right:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots
|
||||
/* as_number */ [
|
||||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_subtract: py_class_binary_numeric_slot!($class::__sub__),
|
||||
]
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __sub__() $res_type; { $($body)* } [ { $left : &$crate::PyObject = {} } { $right : &$crate::PyObject = {} } ] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __sub__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__sub__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for binary numeric operator __sub__" }
|
||||
};
|
||||
|
||||
{ { def __subclasscheck__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
|
||||
use ffi;
|
||||
use std::{mem, isize, ptr};
|
||||
use libc::{c_char, c_int};
|
||||
use libc::{c_char, c_int, c_long};
|
||||
use python::{Python, PythonObject};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyObject;
|
||||
use function::CallbackConverter;
|
||||
use err::{PyErr};
|
||||
use err::{PyErr, PyResult};
|
||||
use exc;
|
||||
use Py_hash_t;
|
||||
|
||||
|
@ -56,17 +57,24 @@ macro_rules! py_class_type_object_flags {
|
|||
/* traverse_proc: */ None,
|
||||
/* traverse_data: */ [ /*name*/ ]
|
||||
}) => {
|
||||
$crate::_detail::ffi::Py_TPFLAGS_DEFAULT
|
||||
$crate::py_class::slots::TPFLAGS_DEFAULT
|
||||
};
|
||||
(/* gc: */ {
|
||||
$traverse_proc: expr,
|
||||
$traverse_data: tt
|
||||
}) => {
|
||||
$crate::_detail::ffi::Py_TPFLAGS_DEFAULT
|
||||
$crate::py_class::slots::TPFLAGS_DEFAULT
|
||||
| $crate::_detail::ffi::Py_TPFLAGS_HAVE_GC
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub const TPFLAGS_DEFAULT : c_long = ffi::Py_TPFLAGS_DEFAULT
|
||||
| ffi::Py_TPFLAGS_CHECKTYPES;
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
pub const TPFLAGS_DEFAULT : c_long = ffi::Py_TPFLAGS_DEFAULT;
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_type_object_dynamic_init {
|
||||
|
@ -253,7 +261,7 @@ macro_rules! py_class_unary_slot {
|
|||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_binary_slot {
|
||||
($class:ident :: $f:ident, $arg_type:ty, $extract_err:ident, $res_type:ty, $conv:expr) => {{
|
||||
($class:ident :: $f:ident, $arg_type:ty, $res_type:ty, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap_binary<DUMMY>(
|
||||
slf: *mut $crate::_detail::ffi::PyObject,
|
||||
arg: *mut $crate::_detail::ffi::PyObject)
|
||||
|
@ -269,10 +277,10 @@ macro_rules! py_class_binary_slot {
|
|||
Ok(prepared) => {
|
||||
match <$arg_type as $crate::ExtractPyObject>::extract(py, &prepared) {
|
||||
Ok(arg) => slf.$f(py, arg),
|
||||
Err(e) => $extract_err!(py, e)
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
},
|
||||
Err(e) => $extract_err!(py, e)
|
||||
Err(e) => Err(e)
|
||||
};
|
||||
$crate::PyDrop::release_ref(arg, py);
|
||||
$crate::PyDrop::release_ref(slf, py);
|
||||
|
@ -329,22 +337,79 @@ macro_rules! py_class_ternary_slot {
|
|||
}}
|
||||
}
|
||||
|
||||
// sq_contains is special-cased slot because it converts type errors to Ok(false)
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_extract_error_passthrough {
|
||||
($py: ident, $e:ident) => (Err($e));
|
||||
macro_rules! py_class_contains_slot {
|
||||
($class:ident :: $f:ident, $arg_type:ty) => {{
|
||||
unsafe extern "C" fn sq_contains(
|
||||
slf: *mut $crate::_detail::ffi::PyObject,
|
||||
arg: *mut $crate::_detail::ffi::PyObject)
|
||||
-> $crate::_detail::libc::c_int
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::_detail::handle_callback(
|
||||
LOCATION, $crate::py_class::slots::BoolConverter,
|
||||
|py| {
|
||||
let slf = $crate::PyObject::from_borrowed_ptr(py, slf).unchecked_cast_into::<$class>();
|
||||
let arg = $crate::PyObject::from_borrowed_ptr(py, arg);
|
||||
let ret = match <$arg_type as $crate::ExtractPyObject>::prepare_extract(py, &arg) {
|
||||
Ok(prepared) => {
|
||||
match <$arg_type as $crate::ExtractPyObject>::extract(py, &prepared) {
|
||||
Ok(arg) => slf.$f(py, arg),
|
||||
Err(e) => $crate::py_class::slots::type_error_to_false(py, e)
|
||||
}
|
||||
},
|
||||
Err(e) => $crate::py_class::slots::type_error_to_false(py, e)
|
||||
};
|
||||
$crate::PyDrop::release_ref(arg, py);
|
||||
$crate::PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(sq_contains)
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn type_error_to_false(py: Python, e: PyErr) -> PyResult<bool> {
|
||||
if e.matches(py, py.get_type::<exc::TypeError>()) {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_extract_error_false {
|
||||
($py: ident, $e:ident) => {
|
||||
if $e.matches($py, $py.get_type::<$crate::exc::TypeError>()) {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err($e)
|
||||
macro_rules! py_class_binary_numeric_slot {
|
||||
($class:ident :: $f:ident) => {{
|
||||
unsafe extern "C" fn binary_numeric<DUMMY>(
|
||||
lhs: *mut $crate::_detail::ffi::PyObject,
|
||||
rhs: *mut $crate::_detail::ffi::PyObject)
|
||||
-> *mut $crate::_detail::ffi::PyObject
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::_detail::handle_callback(
|
||||
LOCATION, $crate::_detail::PyObjectCallbackConverter,
|
||||
|py| {
|
||||
let lhs = $crate::PyObject::from_borrowed_ptr(py, lhs);
|
||||
let rhs = $crate::PyObject::from_borrowed_ptr(py, rhs);
|
||||
let ret = $class::$f(py, &lhs, &rhs);
|
||||
$crate::PyDrop::release_ref(lhs, py);
|
||||
$crate::PyDrop::release_ref(rhs, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
};
|
||||
Some(binary_numeric::<()>)
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn type_error_to_not_implemented(py: Python, e: PyErr) -> PyResult<PyObject> {
|
||||
if e.matches(py, py.get_type::<exc::TypeError>()) {
|
||||
Ok(py.NotImplemented())
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnitCallbackConverter;
|
||||
|
|
|
@ -285,6 +285,13 @@ impl<'p> Python<'p> {
|
|||
unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_False()).unchecked_cast_into::<PyBool>() }
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `NotImplemented`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn NotImplemented(self) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_NotImplemented()) }
|
||||
}
|
||||
|
||||
/// Gets the Python type object for type T.
|
||||
pub fn get_type<T>(self) -> PyType where T: PythonObjectWithTypeObject {
|
||||
T::type_object(self)
|
||||
|
|
|
@ -572,3 +572,66 @@ fn contains() {
|
|||
py_run!(py, c, "assert 'wrong type' not in c");
|
||||
}
|
||||
|
||||
py_class!(class UnaryArithmetic |py| {
|
||||
def __neg__(&self) -> PyResult<&'static str> {
|
||||
Ok("neg")
|
||||
}
|
||||
|
||||
def __pos__(&self) -> PyResult<&'static str> {
|
||||
Ok("pos")
|
||||
}
|
||||
|
||||
def __abs__(&self) -> PyResult<&'static str> {
|
||||
Ok("abs")
|
||||
}
|
||||
|
||||
def __invert__(&self) -> PyResult<&'static str> {
|
||||
Ok("invert")
|
||||
}
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn unary_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = UnaryArithmetic::create_instance(py).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'");
|
||||
}
|
||||
|
||||
py_class!(class BinaryArithmetic |py| {
|
||||
def __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("BA")
|
||||
}
|
||||
|
||||
def __add__(lhs, rhs) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", lhs, rhs))
|
||||
}
|
||||
|
||||
def __sub__(lhs, rhs) -> PyResult<String> {
|
||||
Ok(format!("{:?} - {:?}", lhs, rhs))
|
||||
}
|
||||
|
||||
def __mul__(lhs, rhs) -> PyResult<String> {
|
||||
Ok(format!("{:?} * {:?}", lhs, rhs))
|
||||
}
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn binary_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = BinaryArithmetic::create_instance(py).unwrap();
|
||||
py_run!(py, c, "assert c + 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'");
|
||||
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'");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue