py_class!: add __length_hint__, and map __len__ to both sq_length and mp_length.
This commit is contained in:
parent
318d9a9ef3
commit
713a5c53d3
|
@ -285,6 +285,19 @@ TODO: implement support for `__cmp__`, `__lt__`, `__le__`, `__gt__`, `__ge__`, `
|
|||
Objects that compare equal must have the same hash value.
|
||||
The return type must be `PyResult<T>` where `T` is one of Rust's primitive integer types.
|
||||
|
||||
## Emulating Container Types
|
||||
|
||||
* `def __len__(&self) -> PyResult<usize>`
|
||||
|
||||
Called by the built-in Python function `len()`.
|
||||
|
||||
* `def __length_hint__(&self) -> PyResult<usize>`
|
||||
|
||||
Should return an estimated length for the object.
|
||||
This method is purely an optimization and is never required for correctness.
|
||||
|
||||
`__length_hint__` is new in Python 3.4; older versions will ignore the method.
|
||||
|
||||
## Other Special Methods
|
||||
|
||||
* `def __bool__(&self) -> PyResult<bool>`
|
||||
|
@ -320,6 +333,7 @@ macro_rules! py_class {
|
|||
/* type_slots */ [ /* slot: expr, */ ]
|
||||
/* as_number */ [ /* slot: expr, */ ]
|
||||
/* as_sequence */ [ /* slot: expr, */ ]
|
||||
/* as_mapping */ [ /* slot: expr, */ ]
|
||||
}
|
||||
/* impls: */ { /* impl body */ }
|
||||
/* members: */ { /* ident = expr; */ };
|
||||
|
|
|
@ -275,6 +275,7 @@ slot_groups = (
|
|||
('tp', 'type_slots'),
|
||||
('nb', 'as_number'),
|
||||
('sq', 'as_sequence'),
|
||||
('mp', 'as_mapping'),
|
||||
)
|
||||
|
||||
def generate_case(pattern, new_impl=None, new_slots=None, new_members=None):
|
||||
|
@ -413,7 +414,7 @@ def traverse_and_clear():
|
|||
{ $class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $slot_name:ident : $slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* } $members:tt;
|
||||
def __clear__ (&$slf:ident) $body:block $($tail:tt)*
|
||||
|
@ -424,7 +425,7 @@ def traverse_and_clear():
|
|||
$( $slot_name : $slot_value, )*
|
||||
tp_clear: py_class_tp_clear!($class),
|
||||
]
|
||||
$as_number $as_sequence
|
||||
$as_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -552,12 +553,17 @@ def unary_operator(special_name, slot,
|
|||
res_conv = '$crate::_detail::PyObjectCallbackConverter'
|
||||
else:
|
||||
res_conv = '$crate::_detail::PythonObjectCallbackConverter::<$crate::%s>(::std::marker::PhantomData)' % res_type
|
||||
new_slots = [(slot, 'py_class_unary_slot!($class::%s, %s, %s)'
|
||||
% (special_name, res_ffi_type, res_conv))]
|
||||
if slot == 'sq_length':
|
||||
# __len__ must be saved to two slots
|
||||
# Use PySequence_Size to forward mp_length calls to sq_length.
|
||||
new_slots.append(('mp_length', 'Some($crate::_detail::ffi::PySequence_Size)'))
|
||||
generate_case(
|
||||
pattern='def %s(&$slf:ident) -> $res_type:ty { $($body:tt)* }' % special_name,
|
||||
new_impl='py_class_impl_item! { $class, $py, %s(&$slf,) $res_type; { $($body)* } [] }'
|
||||
% special_name,
|
||||
new_slots=[(slot, 'py_class_unary_slot!($class::%s, %s, %s)'
|
||||
% (special_name, res_ffi_type, res_conv))]
|
||||
new_slots=new_slots
|
||||
)
|
||||
# Generate fall-back matcher that produces an error
|
||||
# when using the wrong method signature
|
||||
|
@ -621,7 +627,7 @@ special_names = {
|
|||
'__len__': unary_operator('sq_length',
|
||||
res_ffi_type='$crate::_detail::ffi::Py_ssize_t',
|
||||
res_conv='$crate::py_class::slots::LenResultConverter'),
|
||||
'__length_hint__': unimplemented(),
|
||||
'__length_hint__': normal_method(),
|
||||
'__getitem__': unimplemented(),
|
||||
'__missing__': unimplemented(),
|
||||
'__setitem__': unimplemented(),
|
||||
|
|
|
@ -268,7 +268,7 @@ macro_rules! py_class_impl {
|
|||
{ $class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $slot_name:ident : $slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* } $members:tt;
|
||||
def __clear__ (&$slf:ident) $body:block $($tail:tt)*
|
||||
|
@ -279,7 +279,7 @@ macro_rules! py_class_impl {
|
|||
$( $slot_name : $slot_value, )*
|
||||
tp_clear: py_class_tp_clear!($class),
|
||||
]
|
||||
$as_number $as_sequence
|
||||
$as_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -338,7 +338,7 @@ macro_rules! py_class_impl {
|
|||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt
|
||||
$as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -351,7 +351,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_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -368,7 +368,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -380,7 +380,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -391,7 +391,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -403,7 +403,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -549,7 +549,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -561,7 +561,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -686,7 +686,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -698,7 +698,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -734,6 +734,7 @@ macro_rules! py_class_impl {
|
|||
/* 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, )* ]
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -746,6 +747,10 @@ macro_rules! py_class_impl {
|
|||
$( $sq_slot_name : $sq_slot_value, )*
|
||||
sq_length: py_class_unary_slot!($class::__len__, $crate::_detail::ffi::Py_ssize_t, $crate::py_class::slots::LenResultConverter),
|
||||
]
|
||||
/* as_mapping */ [
|
||||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_length: Some($crate::_detail::ffi::PySequence_Size),
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -759,12 +764,6 @@ macro_rules! py_class_impl {
|
|||
} => {
|
||||
py_error! { "Invalid signature for unary operator __len__" }
|
||||
};
|
||||
// def __length_hint__()
|
||||
{ $class:ident $py:ident $info:tt $slots:tt $impls:tt $members:tt;
|
||||
def __length_hint__ $($tail:tt)*
|
||||
} => {
|
||||
py_error! { "__length_hint__ is not supported by py_class! yet." }
|
||||
};
|
||||
// def __long__()
|
||||
{ $class:ident $py:ident $info:tt $slots:tt $impls:tt $members:tt;
|
||||
def __long__ $($tail:tt)*
|
||||
|
@ -822,7 +821,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -834,7 +833,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -845,7 +844,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -857,7 +856,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -871,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -883,7 +882,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -948,7 +947,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -960,7 +959,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -1079,7 +1078,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -1091,7 +1090,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
|
|
@ -268,7 +268,7 @@ macro_rules! py_class_impl {
|
|||
{ $class:ident $py:ident $info:tt
|
||||
/* slots: */ {
|
||||
/* type_slots */ [ $( $slot_name:ident : $slot_value:expr, )* ]
|
||||
$as_number:tt $as_sequence:tt
|
||||
$as_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* } $members:tt;
|
||||
def __clear__ (&$slf:ident) $body:block $($tail:tt)*
|
||||
|
@ -279,7 +279,7 @@ macro_rules! py_class_impl {
|
|||
$( $slot_name : $slot_value, )*
|
||||
tp_clear: py_class_tp_clear!($class),
|
||||
]
|
||||
$as_number $as_sequence
|
||||
$as_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -338,7 +338,7 @@ macro_rules! py_class_impl {
|
|||
/* slots: */ {
|
||||
$type_slots:tt
|
||||
/* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ]
|
||||
$as_sequence:tt
|
||||
$as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -351,7 +351,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_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -368,7 +368,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -380,7 +380,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -391,7 +391,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -403,7 +403,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -549,7 +549,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -561,7 +561,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -686,7 +686,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -698,7 +698,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -734,6 +734,7 @@ macro_rules! py_class_impl {
|
|||
/* 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, )* ]
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -746,6 +747,10 @@ macro_rules! py_class_impl {
|
|||
$( $sq_slot_name : $sq_slot_value, )*
|
||||
sq_length: py_class_unary_slot!($class::__len__, $crate::_detail::ffi::Py_ssize_t, $crate::py_class::slots::LenResultConverter),
|
||||
]
|
||||
/* as_mapping */ [
|
||||
$( $mp_slot_name : $mp_slot_value, )*
|
||||
mp_length: Some($crate::_detail::ffi::PySequence_Size),
|
||||
]
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -759,12 +764,6 @@ macro_rules! py_class_impl {
|
|||
} => {
|
||||
py_error! { "Invalid signature for unary operator __len__" }
|
||||
};
|
||||
// def __length_hint__()
|
||||
{ $class:ident $py:ident $info:tt $slots:tt $impls:tt $members:tt;
|
||||
def __length_hint__ $($tail:tt)*
|
||||
} => {
|
||||
py_error! { "__length_hint__ is not supported by py_class! yet." }
|
||||
};
|
||||
// def __long__()
|
||||
{ $class:ident $py:ident $info:tt $slots:tt $impls:tt $members:tt;
|
||||
def __long__ $($tail:tt)*
|
||||
|
@ -822,7 +821,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -834,7 +833,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -845,7 +844,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -857,7 +856,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -871,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -883,7 +882,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -948,7 +947,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -960,7 +959,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
@ -1079,7 +1078,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_number:tt $as_sequence:tt $as_mapping:tt
|
||||
}
|
||||
{ $( $imp:item )* }
|
||||
$members:tt;
|
||||
|
@ -1091,7 +1090,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_number $as_sequence $as_mapping
|
||||
}
|
||||
/* impl: */ {
|
||||
$($imp)*
|
||||
|
|
|
@ -35,6 +35,7 @@ macro_rules! py_class_type_object_static_init {
|
|||
/* type_slots */ [ $( $slot_name:ident : $slot_value:expr, )* ]
|
||||
$as_number:tt
|
||||
$as_sequence:tt
|
||||
$as_mapping:tt
|
||||
}) => (
|
||||
$crate::_detail::ffi::PyTypeObject {
|
||||
$( $slot_name : $slot_value, )*
|
||||
|
@ -74,6 +75,7 @@ macro_rules! py_class_type_object_dynamic_init {
|
|||
$type_slots:tt
|
||||
$as_number:tt
|
||||
$as_sequence:tt
|
||||
$as_mapping:tt
|
||||
}
|
||||
) => {
|
||||
unsafe {
|
||||
|
@ -84,6 +86,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,6 +159,21 @@ 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 ,)+]) => {{
|
||||
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 }
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{mem, isize, iter};
|
|||
use std::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) => {{
|
||||
|
@ -304,6 +304,10 @@ fn len() {
|
|||
|
||||
let inst = Len::create_instance(py, 10).unwrap();
|
||||
py_assert!(py, inst, "len(inst) == 10");
|
||||
unsafe {
|
||||
assert_eq!(ffi::PyObject_Size(inst.as_object().as_ptr()), 10);
|
||||
assert_eq!(ffi::PyMapping_Size(inst.as_object().as_ptr()), 10);
|
||||
}
|
||||
|
||||
let inst = Len::create_instance(py, (isize::MAX as usize) + 1).unwrap();
|
||||
py_expect_exception!(py, inst, "len(inst)", OverflowError);
|
||||
|
|
Loading…
Reference in New Issue