py_class!: add __setitem__ and __delitem__
This commit is contained in:
parent
806f212dc4
commit
5886720c90
|
@ -302,6 +302,14 @@ TODO: implement support for `__cmp__`, `__lt__`, `__le__`, `__gt__`, `__ge__`, `
|
|||
|
||||
Called by the Python subscript operator `self[key]`.
|
||||
|
||||
* `def __setitem__(&self, key: impl ExtractPyObject, value: impl ExtractPyObject) -> PyResult<()>`
|
||||
|
||||
Called by Python `self[key] = value`.
|
||||
|
||||
* `def __delitem__(&self, key: impl ExtractPyObject) -> PyResult<()>`
|
||||
|
||||
Called by Python `del self[key]`.
|
||||
|
||||
## Other Special Methods
|
||||
|
||||
* `def __bool__(&self) -> PyResult<bool>`
|
||||
|
@ -339,6 +347,10 @@ macro_rules! py_class {
|
|||
/* as_number */ [ /* slot: expr, */ ]
|
||||
/* as_sequence */ [ /* slot: expr, */ ]
|
||||
/* as_mapping */ [ /* slot: expr, */ ]
|
||||
/* setitem_delitem */ [
|
||||
sdi_setitem: {},
|
||||
sdi_delitem: {},
|
||||
]
|
||||
}
|
||||
/* impls: */ { /* impl body */ }
|
||||
/* members: */ { /* ident = expr; */ }
|
||||
|
|
|
@ -226,10 +226,11 @@ def write(text):
|
|||
last_char = line[-1]
|
||||
|
||||
slot_groups = (
|
||||
('tp', 'type_slots'),
|
||||
('nb', 'as_number'),
|
||||
('sq', 'as_sequence'),
|
||||
('mp', 'as_mapping'),
|
||||
('tp', 'type_slots', None),
|
||||
('nb', 'as_number', None),
|
||||
('sq', 'as_sequence', None),
|
||||
('mp', 'as_mapping', None),
|
||||
('sdi', 'setdelitem', ['sdi_setitem', 'sdi_delitem'])
|
||||
)
|
||||
|
||||
def generate_case(pattern, old_info=None, new_info=None, new_impl=None, new_slots=None, new_members=None):
|
||||
|
@ -248,10 +249,19 @@ def generate_case(pattern, old_info=None, new_info=None, new_impl=None, new_slot
|
|||
write('$info:tt')
|
||||
if new_slots:
|
||||
write('\n/* slots: */ {\n')
|
||||
for prefix, group_name in slot_groups:
|
||||
for prefix, group_name, explicit_slots in slot_groups:
|
||||
if any(s.startswith(prefix) for s, v in new_slots):
|
||||
write('\n/* %s */ [ $( $%s_slot_name:ident : $%s_slot_value:expr, )* ]\n'
|
||||
% (group_name, prefix, prefix))
|
||||
if explicit_slots is None:
|
||||
write('\n/* %s */ [ $( $%s_slot_name:ident : $%s_slot_value:expr, )* ]\n'
|
||||
% (group_name, prefix, prefix))
|
||||
else:
|
||||
write('\n/* %s */ [\n' % group_name)
|
||||
for slot in explicit_slots:
|
||||
if any(s == slot for s, v in new_slots):
|
||||
write('%s: {},\n' % slot)
|
||||
else:
|
||||
write('%s: $%s_slot_value:tt,\n' % (slot, slot))
|
||||
write(']\n')
|
||||
else:
|
||||
write('$%s:tt' % group_name)
|
||||
write('\n}\n')
|
||||
|
@ -271,13 +281,21 @@ def generate_case(pattern, old_info=None, new_info=None, new_impl=None, new_slot
|
|||
write(new_info or '$info')
|
||||
if new_slots:
|
||||
write('\n/* slots: */ {\n')
|
||||
for prefix, group_name in slot_groups:
|
||||
for prefix, group_name, explicit_slots in slot_groups:
|
||||
if any(s.startswith(prefix) for s, v in new_slots):
|
||||
write('\n/* %s */ [\n' % group_name)
|
||||
write('$( $%s_slot_name : $%s_slot_value, )*\n' % (prefix, prefix))
|
||||
for s, v in new_slots:
|
||||
if s.startswith(prefix):
|
||||
write('%s: %s,\n' % (s, v))
|
||||
if explicit_slots is None:
|
||||
write('$( $%s_slot_name : $%s_slot_value, )*\n' % (prefix, prefix))
|
||||
for s, v in new_slots:
|
||||
if s.startswith(prefix):
|
||||
write('%s: %s,\n' % (s, v))
|
||||
else:
|
||||
for slot in explicit_slots:
|
||||
slot_value = next((v for s, v in new_slots if s == slot), None)
|
||||
if slot_value is None:
|
||||
write('%s: $%s_slot_value,\n' % (slot, slot))
|
||||
else:
|
||||
write('%s: { %s },\n' % (slot, slot_value))
|
||||
write(']\n')
|
||||
else:
|
||||
write('$%s' % group_name)
|
||||
|
@ -498,7 +516,10 @@ def operator(special_name, slot,
|
|||
additional_slots=()
|
||||
):
|
||||
if res_conv is None:
|
||||
if res_type == 'PyObject':
|
||||
if res_type == '()':
|
||||
res_conv = '$crate::py_class::slots::UnitCallbackConverter'
|
||||
res_ffi_type = '$crate::_detail::libc::c_int'
|
||||
elif res_type == 'PyObject':
|
||||
res_conv = '$crate::_detail::PyObjectCallbackConverter'
|
||||
else:
|
||||
res_conv = '$crate::_detail::PythonObjectCallbackConverter::<$crate::%s>(::std::marker::PhantomData)' % res_type
|
||||
|
@ -512,7 +533,10 @@ def operator(special_name, slot,
|
|||
% (special_name, res_ffi_type, res_conv))]
|
||||
elif len(args) == 1:
|
||||
new_slots = [(slot, 'py_class_binary_slot!($class::%s, $%s_type, %s, %s)'
|
||||
% (special_name, arg.name, res_ffi_type, res_conv))]
|
||||
% (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))]
|
||||
else:
|
||||
raise ValueError('Unsupported argument count')
|
||||
generate_case(
|
||||
|
@ -523,7 +547,7 @@ def operator(special_name, slot,
|
|||
)
|
||||
# Generate fall-back matcher that produces an error
|
||||
# when using the wrong method signature
|
||||
error('Invalid signature for unary operator %s' % special_name)(special_name)
|
||||
error('Invalid signature for operator %s' % special_name)(special_name)
|
||||
|
||||
@special_method
|
||||
def call_operator(special_name, slot):
|
||||
|
@ -588,13 +612,18 @@ special_names = {
|
|||
('mp_length', 'Some($crate::_detail::ffi::PySequence_Size)')
|
||||
]),
|
||||
'__length_hint__': normal_method(),
|
||||
'__getitem__': operator('mp_subscript', args=[Argument('x', '&PyObject')],
|
||||
'__getitem__': operator('mp_subscript',
|
||||
args=[Argument('key', '&PyObject')],
|
||||
additional_slots=[
|
||||
('sq_item', 'Some($crate::py_class::slots::sq_item)')
|
||||
]),
|
||||
'__missing__': normal_method(),
|
||||
'__setitem__': unimplemented(),
|
||||
'__delitem__': unimplemented(),
|
||||
'__setitem__': operator('sdi_setitem',
|
||||
args=[Argument('key', '&PyObject'), Argument('value', '&PyObject')],
|
||||
res_type='()'),
|
||||
'__delitem__': operator('sdi_delitem',
|
||||
args=[Argument('key', '&PyObject')],
|
||||
res_type='()'),
|
||||
'__iter__': operator('tp_iter'),
|
||||
'__next__': operator('tp_iternext',
|
||||
res_conv='$crate::py_class::slots::IterNextResultConverter'),
|
||||
|
@ -677,6 +706,12 @@ special_names = {
|
|||
}
|
||||
|
||||
def main():
|
||||
if sys.argv[1:] == ['--format']:
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
return
|
||||
write(line)
|
||||
print(header)
|
||||
print('')
|
||||
print('// !!!!!!!!!!!!!!!!!!!!!!!!!!!')
|
||||
|
|
|
@ -269,7 +269,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -281,7 +281,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_clear: py_class_tp_clear!($class),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -326,7 +326,7 @@ macro_rules! py_class_impl {
|
|||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -339,7 +339,7 @@ macro_rules! py_class_impl {
|
|||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_nonzero: py_class_unary_slot!($class::__bool__, $crate::_detail::libc::c_int, $crate::py_class::slots::BoolConverter),
|
||||
]
|
||||
$as_sequence $as_mapping
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -349,13 +349,13 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __bool__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __bool__" }
|
||||
py_error! { "Invalid signature for operator __bool__" }
|
||||
};
|
||||
{ { def __call__ (&$slf:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -367,7 +367,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_call: py_class_call_slot!{$class::__call__ []},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -379,7 +379,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -391,7 +391,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_call: py_argparse_parse_plist_impl!{py_class_call_slot {$class::__call__} [] ($($p)+,)},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -430,9 +430,36 @@ macro_rules! py_class_impl {
|
|||
{ { def __delete__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__delete__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __delitem__(&$slf:ident, $key:ident : $key_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: $sdi_setitem_slot_value:tt,
|
||||
sdi_delitem: {},
|
||||
]
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$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, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __delitem__(&$slf,) $res_type; { $($body)* } [{ $key : $key_type = {} }] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __delitem__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__delitem__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __delitem__" }
|
||||
};
|
||||
|
||||
{ { def __dir__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -482,12 +509,13 @@ macro_rules! py_class_impl {
|
|||
{ { def __getattribute__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__getattribute__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __getitem__(&$slf:ident, $x:ident : $x_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
{ { def __getitem__(&$slf:ident, $key:ident : $key_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt $as_number:tt
|
||||
/* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ]
|
||||
/* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ]
|
||||
$setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -502,18 +530,19 @@ macro_rules! py_class_impl {
|
|||
]
|
||||
/* as_mapping */ [
|
||||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_subscript: py_class_binary_slot!($class::__getitem__, $x_type, *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
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __getitem__(&$slf,) $res_type; { $($body)* } [{ $x : $x_type = {} }] }
|
||||
py_class_impl_item! { $class, $py, __getitem__(&$slf,) $res_type; { $($body)* } [{ $key : $key_type = {} }] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __getitem__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __getitem__" }
|
||||
py_error! { "Invalid signature for operator __getitem__" }
|
||||
};
|
||||
|
||||
{ { def __gt__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -523,7 +552,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -535,7 +564,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_hash: py_class_unary_slot!($class::__hash__, $crate::Py_hash_t, $crate::py_class::slots::HashConverter),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -545,7 +574,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __hash__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __hash__" }
|
||||
py_error! { "Invalid signature for operator __hash__" }
|
||||
};
|
||||
|
||||
{ { def __iadd__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -623,7 +652,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -635,7 +664,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_iter: py_class_unary_slot!($class::__iter__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -645,7 +674,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __iter__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __iter__" }
|
||||
py_error! { "Invalid signature for operator __iter__" }
|
||||
};
|
||||
|
||||
{ { def __itruediv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -665,6 +694,7 @@ macro_rules! py_class_impl {
|
|||
$type_slots:tt $as_number:tt
|
||||
/* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ]
|
||||
/* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ]
|
||||
$setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -681,6 +711,7 @@ macro_rules! py_class_impl {
|
|||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_length: Some($crate::_detail::ffi::PySequence_Size),
|
||||
]
|
||||
$setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -690,7 +721,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __len__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __len__" }
|
||||
py_error! { "Invalid signature for operator __len__" }
|
||||
};
|
||||
|
||||
{ { def __long__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -728,7 +759,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -740,7 +771,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_new: py_class_wrap_newfunc!{$class::__new__ []},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -752,7 +783,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -764,7 +795,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_new: py_argparse_parse_plist_impl!{py_class_wrap_newfunc {$class::__new__} [] ($($p)+,)},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -779,7 +810,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -791,7 +822,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_iternext: py_class_unary_slot!($class::__next__, *mut $crate::_detail::ffi::PyObject, $crate::py_class::slots::IterNextResultConverter),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -801,7 +832,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __next__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __next__" }
|
||||
py_error! { "Invalid signature for operator __next__" }
|
||||
};
|
||||
|
||||
{ { def __nonzero__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -839,7 +870,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -851,7 +882,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_repr: py_class_unary_slot!($class::__repr__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(::std::marker::PhantomData)),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -861,7 +892,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __repr__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __repr__" }
|
||||
py_error! { "Invalid signature for operator __repr__" }
|
||||
};
|
||||
|
||||
{ { def __reversed__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -927,15 +958,42 @@ macro_rules! py_class_impl {
|
|||
{ { def __setattr__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__setattr__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __setitem__(&$slf:ident, $key:ident : $key_type:ty, $value:ident : $value_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: {},
|
||||
sdi_delitem: $sdi_delitem_slot_value:tt,
|
||||
]
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots $as_number $as_sequence $as_mapping
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: { py_class_ternary_slot!($class::__setitem__, $key_type, $value_type, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
sdi_delitem: $sdi_delitem_slot_value,
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __setitem__(&$slf,) $res_type; { $($body)* } [{ $key : $key_type = {} } { $value : $value_type = {} }] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __setitem__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__setitem__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __setitem__" }
|
||||
};
|
||||
{ { def __str__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -947,7 +1005,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_str: py_class_unary_slot!($class::__str__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(::std::marker::PhantomData)),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -957,7 +1015,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __str__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __str__" }
|
||||
py_error! { "Invalid signature for operator __str__" }
|
||||
};
|
||||
|
||||
{ { def __sub__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
|
|
@ -269,7 +269,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -281,7 +281,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_clear: py_class_tp_clear!($class),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -326,7 +326,7 @@ macro_rules! py_class_impl {
|
|||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt $as_mapping:tt
|
||||
$as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -339,7 +339,7 @@ macro_rules! py_class_impl {
|
|||
$( $nb_slot_name : $nb_slot_value, )*
|
||||
nb_bool: py_class_unary_slot!($class::__bool__, $crate::_detail::libc::c_int, $crate::py_class::slots::BoolConverter),
|
||||
]
|
||||
$as_sequence $as_mapping
|
||||
$as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -349,13 +349,13 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __bool__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __bool__" }
|
||||
py_error! { "Invalid signature for operator __bool__" }
|
||||
};
|
||||
{ { def __call__ (&$slf:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -367,7 +367,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_call: py_class_call_slot!{$class::__call__ []},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -379,7 +379,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -391,7 +391,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_call: py_argparse_parse_plist_impl!{py_class_call_slot {$class::__call__} [] ($($p)+,)},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -430,9 +430,36 @@ macro_rules! py_class_impl {
|
|||
{ { def __delete__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__delete__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __delitem__(&$slf:ident, $key:ident : $key_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: $sdi_setitem_slot_value:tt,
|
||||
sdi_delitem: {},
|
||||
]
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$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, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __delitem__(&$slf,) $res_type; { $($body)* } [{ $key : $key_type = {} }] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __delitem__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__delitem__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __delitem__" }
|
||||
};
|
||||
|
||||
{ { def __dir__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -482,12 +509,13 @@ macro_rules! py_class_impl {
|
|||
{ { def __getattribute__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__getattribute__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __getitem__(&$slf:ident, $x:ident : $x_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
{ { def __getitem__(&$slf:ident, $key:ident : $key_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt $as_number:tt
|
||||
/* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ]
|
||||
/* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ]
|
||||
$setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -502,18 +530,19 @@ macro_rules! py_class_impl {
|
|||
]
|
||||
/* as_mapping */ [
|
||||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_subscript: py_class_binary_slot!($class::__getitem__, $x_type, *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
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __getitem__(&$slf,) $res_type; { $($body)* } [{ $x : $x_type = {} }] }
|
||||
py_class_impl_item! { $class, $py, __getitem__(&$slf,) $res_type; { $($body)* } [{ $key : $key_type = {} }] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __getitem__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __getitem__" }
|
||||
py_error! { "Invalid signature for operator __getitem__" }
|
||||
};
|
||||
|
||||
{ { def __gt__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -523,7 +552,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -535,7 +564,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_hash: py_class_unary_slot!($class::__hash__, $crate::Py_hash_t, $crate::py_class::slots::HashConverter),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -545,7 +574,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __hash__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __hash__" }
|
||||
py_error! { "Invalid signature for operator __hash__" }
|
||||
};
|
||||
|
||||
{ { def __iadd__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -623,7 +652,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -635,7 +664,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_iter: py_class_unary_slot!($class::__iter__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -645,7 +674,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __iter__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __iter__" }
|
||||
py_error! { "Invalid signature for operator __iter__" }
|
||||
};
|
||||
|
||||
{ { def __itruediv__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -665,6 +694,7 @@ macro_rules! py_class_impl {
|
|||
$type_slots:tt $as_number:tt
|
||||
/* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ]
|
||||
/* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ]
|
||||
$setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -681,6 +711,7 @@ macro_rules! py_class_impl {
|
|||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_length: Some($crate::_detail::ffi::PySequence_Size),
|
||||
]
|
||||
$setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -690,7 +721,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __len__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __len__" }
|
||||
py_error! { "Invalid signature for operator __len__" }
|
||||
};
|
||||
|
||||
{ { def __long__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -728,7 +759,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -740,7 +771,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_new: py_class_wrap_newfunc!{$class::__new__ []},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -752,7 +783,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -764,7 +795,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_new: py_argparse_parse_plist_impl!{py_class_wrap_newfunc {$class::__new__} [] ($($p)+,)},
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -779,7 +810,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -791,7 +822,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_iternext: py_class_unary_slot!($class::__next__, *mut $crate::_detail::ffi::PyObject, $crate::py_class::slots::IterNextResultConverter),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -801,7 +832,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __next__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __next__" }
|
||||
py_error! { "Invalid signature for operator __next__" }
|
||||
};
|
||||
|
||||
{ { def __nonzero__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -839,7 +870,7 @@ macro_rules! py_class_impl {
|
|||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -851,7 +882,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_repr: py_class_unary_slot!($class::__repr__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(::std::marker::PhantomData)),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -861,7 +892,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __repr__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __repr__" }
|
||||
py_error! { "Invalid signature for operator __repr__" }
|
||||
};
|
||||
|
||||
{ { def __reversed__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
@ -927,15 +958,42 @@ macro_rules! py_class_impl {
|
|||
{ { def __setattr__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__setattr__ is not supported by py_class! yet." }
|
||||
};
|
||||
{ { def __setitem__(&$slf:ident, $key:ident : $key_type:ty, $value:ident : $value_type:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
$type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: {},
|
||||
sdi_delitem: $sdi_delitem_slot_value:tt,
|
||||
]
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
} => { py_class_impl! {
|
||||
{ $($tail)* }
|
||||
$class $py $info
|
||||
/* slots: */ {
|
||||
$type_slots $as_number $as_sequence $as_mapping
|
||||
/* setdelitem */ [
|
||||
sdi_setitem: { py_class_ternary_slot!($class::__setitem__, $key_type, $value_type, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) },
|
||||
sdi_delitem: $sdi_delitem_slot_value,
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
py_class_impl_item! { $class, $py, __setitem__(&$slf,) $res_type; { $($body)* } [{ $key : $key_type = {} } { $value : $value_type = {} }] }
|
||||
}
|
||||
$members
|
||||
}};
|
||||
|
||||
{ { def __setitem__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "__setitem__ is not supported by py_class! yet." }
|
||||
py_error! { "Invalid signature for operator __setitem__" }
|
||||
};
|
||||
{ { def __str__(&$slf:ident) -> $res_type:ty { $($body:tt)* } $($tail:tt)* }
|
||||
$class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt
|
||||
|
@ -947,7 +1005,7 @@ macro_rules! py_class_impl {
|
|||
$( $tp_slot_name : $tp_slot_value, )*
|
||||
tp_str: py_class_unary_slot!($class::__str__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(::std::marker::PhantomData)),
|
||||
]
|
||||
$as_number $as_sequence $as_mapping
|
||||
$as_number $as_sequence $as_mapping $setdelitem
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -957,7 +1015,7 @@ macro_rules! py_class_impl {
|
|||
}};
|
||||
|
||||
{ { def __str__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
py_error! { "Invalid signature for unary operator __str__" }
|
||||
py_error! { "Invalid signature for operator __str__" }
|
||||
};
|
||||
|
||||
{ { def __sub__ $($tail:tt)* } $( $stuff:tt )* } => {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
use ffi;
|
||||
use std::{mem, isize, ptr};
|
||||
use libc::c_int;
|
||||
use libc::{c_char, c_int};
|
||||
use python::{Python, PythonObject};
|
||||
use conversion::ToPyObject;
|
||||
use function::CallbackConverter;
|
||||
|
@ -36,6 +36,7 @@ macro_rules! py_class_type_object_static_init {
|
|||
$as_number:tt
|
||||
$as_sequence:tt
|
||||
$as_mapping:tt
|
||||
$setdelitem:tt
|
||||
}) => (
|
||||
$crate::_detail::ffi::PyTypeObject {
|
||||
$( $slot_name : $slot_value, )*
|
||||
|
@ -76,6 +77,7 @@ macro_rules! py_class_type_object_dynamic_init {
|
|||
$as_number:tt
|
||||
$as_sequence:tt
|
||||
$as_mapping:tt
|
||||
$setdelitem:tt
|
||||
}
|
||||
) => {
|
||||
unsafe {
|
||||
|
@ -86,7 +88,7 @@ macro_rules! py_class_type_object_dynamic_init {
|
|||
// call slot macros outside of unsafe block
|
||||
*(unsafe { &mut $type_object.tp_as_sequence }) = py_class_as_sequence!($as_sequence);
|
||||
*(unsafe { &mut $type_object.tp_as_number }) = py_class_as_number!($as_number);
|
||||
*(unsafe { &mut $type_object.tp_as_mapping }) = py_class_as_mapping!($as_mapping);
|
||||
py_class_as_mapping!($type_object, $as_mapping, $setdelitem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,18 +164,69 @@ macro_rules! py_class_as_number {
|
|||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_as_mapping {
|
||||
([]) => (0 as *mut $crate::_detail::ffi::PyMappingMethods);
|
||||
([$( $slot_name:ident : $slot_value:expr ,)+]) => {{
|
||||
( $type_object:ident, [], [
|
||||
sdi_setitem: {},
|
||||
sdi_delitem: {},
|
||||
]) => {};
|
||||
( $type_object:ident, [ $( $slot_name:ident : $slot_value:expr ,)+ ], [
|
||||
sdi_setitem: {},
|
||||
sdi_delitem: {},
|
||||
]) => {
|
||||
static mut MAPPING_METHODS : $crate::_detail::ffi::PyMappingMethods
|
||||
= $crate::_detail::ffi::PyMappingMethods {
|
||||
$( $slot_name : $slot_value, )*
|
||||
..
|
||||
$crate::_detail::ffi::PyMappingMethods_INIT
|
||||
};
|
||||
unsafe { &mut MAPPING_METHODS }
|
||||
}}
|
||||
unsafe { $type_object.tp_as_mapping = &mut MAPPING_METHODS; }
|
||||
};
|
||||
( $type_object:ident, [ $( $slot_name:ident : $slot_value:expr ,)* ], [
|
||||
sdi_setitem: $setitem:tt,
|
||||
sdi_delitem: $delitem:tt,
|
||||
]) => {{
|
||||
unsafe extern "C" fn mp_ass_subscript(
|
||||
slf: *mut $crate::_detail::ffi::PyObject,
|
||||
key: *mut $crate::_detail::ffi::PyObject,
|
||||
val: *mut $crate::_detail::ffi::PyObject
|
||||
) -> $crate::_detail::libc::c_int {
|
||||
if val.is_null() {
|
||||
py_class_mp_ass_subscript!($delitem, slf,
|
||||
b"Subscript assignment not supported by %.200s\0",
|
||||
key)
|
||||
} else {
|
||||
py_class_mp_ass_subscript!($setitem, slf,
|
||||
b"Subscript deletion not supported by %.200s\0",
|
||||
key, val)
|
||||
}
|
||||
}
|
||||
static mut MAPPING_METHODS : $crate::_detail::ffi::PyMappingMethods
|
||||
= $crate::_detail::ffi::PyMappingMethods {
|
||||
$( $slot_name : $slot_value, )*
|
||||
mp_ass_subscript: Some(mp_ass_subscript),
|
||||
..
|
||||
$crate::_detail::ffi::PyMappingMethods_INIT
|
||||
};
|
||||
unsafe { $type_object.tp_as_mapping = &mut MAPPING_METHODS; }
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_mp_ass_subscript {
|
||||
({}, $slf:ident, $error:expr, $( $arg:expr ),+) => {
|
||||
$crate::py_class::slots::mp_ass_subscript_error($slf, $error)
|
||||
};
|
||||
({$slot:expr}, $slf:ident, $error:expr, $( $arg:expr ),+) => {
|
||||
$slot.unwrap()($slf, $( $arg ),+)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn mp_ass_subscript_error(o: *mut ffi::PyObject, err: &[u8]) -> c_int {
|
||||
ffi::PyErr_Format(ffi::PyExc_NotImplementedError,
|
||||
err.as_ptr() as *const c_char,
|
||||
(*ffi::Py_TYPE(o)).tp_name);
|
||||
-1
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
|
@ -201,7 +254,7 @@ macro_rules! py_class_unary_slot {
|
|||
#[doc(hidden)]
|
||||
macro_rules! py_class_binary_slot {
|
||||
($class:ident :: $f:ident, $arg_type:ty, $res_type:ty, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap_unary<DUMMY>(
|
||||
unsafe extern "C" fn wrap_binary<DUMMY>(
|
||||
slf: *mut $crate::_detail::ffi::PyObject,
|
||||
arg: *mut $crate::_detail::ffi::PyObject)
|
||||
-> $res_type
|
||||
|
@ -226,10 +279,72 @@ macro_rules! py_class_binary_slot {
|
|||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap_unary::<()>)
|
||||
Some(wrap_binary::<()>)
|
||||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_class_ternary_slot {
|
||||
($class:ident :: $f:ident, $arg1_type:ty, $arg2_type:ty, $res_type:ty, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap_binary<DUMMY>(
|
||||
slf: *mut $crate::_detail::ffi::PyObject,
|
||||
arg1: *mut $crate::_detail::ffi::PyObject,
|
||||
arg2: *mut $crate::_detail::ffi::PyObject)
|
||||
-> $res_type
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::_detail::handle_callback(
|
||||
LOCATION, $conv,
|
||||
|py| {
|
||||
let slf = $crate::PyObject::from_borrowed_ptr(py, slf).unchecked_cast_into::<$class>();
|
||||
let arg1 = $crate::PyObject::from_borrowed_ptr(py, arg1);
|
||||
let arg2 = $crate::PyObject::from_borrowed_ptr(py, arg2);
|
||||
let ret = match <$arg1_type as $crate::ExtractPyObject>::prepare_extract(py, &arg1) {
|
||||
Ok(prepared1) => {
|
||||
match <$arg1_type as $crate::ExtractPyObject>::extract(py, &prepared1) {
|
||||
Ok(arg1) => {
|
||||
match <$arg2_type as $crate::ExtractPyObject>::prepare_extract(py, &arg2) {
|
||||
Ok(prepared2) => {
|
||||
match <$arg2_type as $crate::ExtractPyObject>::extract(py, &prepared2) {
|
||||
Ok(arg2) => slf.$f(py, arg1, arg2),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
};
|
||||
$crate::PyDrop::release_ref(arg1, py);
|
||||
$crate::PyDrop::release_ref(arg2, py);
|
||||
$crate::PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap_binary::<()>)
|
||||
}}
|
||||
}
|
||||
|
||||
pub struct UnitCallbackConverter;
|
||||
|
||||
impl CallbackConverter<()> for UnitCallbackConverter {
|
||||
type R = c_int;
|
||||
|
||||
#[inline]
|
||||
fn convert(_: (), _: Python) -> c_int {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn error_value() -> c_int {
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LenResultConverter;
|
||||
|
||||
impl CallbackConverter<usize> for LenResultConverter {
|
||||
|
@ -244,6 +359,7 @@ impl CallbackConverter<usize> for LenResultConverter {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn error_value() -> isize {
|
||||
-1
|
||||
}
|
||||
|
@ -267,6 +383,7 @@ impl <T> CallbackConverter<Option<T>>
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn error_value() -> *mut ffi::PyObject {
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
|
|
@ -5,26 +5,32 @@
|
|||
use cpython::{PyObject, PythonObject, PyDrop, PyClone, PyResult, Python, NoArgs, ObjectProtocol,
|
||||
PyDict, PyBytes, PyUnicode, PyErr, exc};
|
||||
use std::{mem, isize, iter};
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use cpython::_detail::ffi;
|
||||
|
||||
macro_rules! py_assert {
|
||||
($py:expr, $val:ident, $assertion:expr) => {{
|
||||
macro_rules! py_run {
|
||||
($py:expr, $val:ident, $code:expr) => {{
|
||||
let d = PyDict::new($py);
|
||||
d.set_item($py, stringify!($val), &$val).unwrap();
|
||||
$py.run(concat!("assert ", $assertion), None, Some(&d)).expect(concat!("assert ", $assertion));
|
||||
$py.run($code, None, Some(&d)).expect($code);
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! py_assert {
|
||||
($py:expr, $val:ident, $assertion:expr) => { py_run!($py, $val, concat!("assert ", $assertion)) };
|
||||
}
|
||||
|
||||
macro_rules! py_expect_exception {
|
||||
($py:expr, $val:ident, $code:expr, $err:ident) => {{
|
||||
let d = PyDict::new($py);
|
||||
d.set_item($py, stringify!($val), $val).unwrap();
|
||||
let res = $py.eval($code, None, Some(&d));
|
||||
let res = $py.run($code, None, Some(&d));
|
||||
let err = res.unwrap_err();
|
||||
assert!(err.matches($py, $py.get_type::<exc::$err>()));
|
||||
if !err.matches($py, $py.get_type::<exc::$err>()) {
|
||||
panic!(format!("Expected {} but got {:?}", stringify!($err), err))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -465,3 +471,72 @@ fn callable() {
|
|||
py_assert!(py, nc, "not callable(nc)");
|
||||
}
|
||||
|
||||
py_class!(class SetItem |py| {
|
||||
data key: Cell<i32>;
|
||||
data val: Cell<i32>;
|
||||
|
||||
def __setitem__(&self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.key(py).set(key);
|
||||
self.val(py).set(val);
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = SetItem::create_instance(py, Cell::new(0), Cell::new(0)).unwrap();
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
assert_eq!(c.key(py).get(), 1);
|
||||
assert_eq!(c.val(py).get(), 2);
|
||||
py_expect_exception!(py, c, "del c[1]", NotImplementedError);
|
||||
}
|
||||
|
||||
py_class!(class DelItem |py| {
|
||||
data key: Cell<i32>;
|
||||
|
||||
def __delitem__(&self, key: i32) -> PyResult<()> {
|
||||
self.key(py).set(key);
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = DelItem::create_instance(py, Cell::new(0)).unwrap();
|
||||
py_run!(py, c, "del c[1]");
|
||||
assert_eq!(c.key(py).get(), 1);
|
||||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||
}
|
||||
|
||||
py_class!(class SetDelItem |py| {
|
||||
data val: Cell<Option<i32>>;
|
||||
|
||||
def __setitem__(&self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.val(py).set(Some(val));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
def __delitem__(&self, key: i32) -> PyResult<()> {
|
||||
self.val(py).set(None);
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn setdelitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = SetDelItem::create_instance(py, Cell::new(None)).unwrap();
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
assert_eq!(c.val(py).get(), Some(2));
|
||||
py_run!(py, c, "del c[1]");
|
||||
assert_eq!(c.val(py).get(), None);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue