py_class!: add __length_hint__, and map __len__ to both sq_length and mp_length.

This commit is contained in:
Daniel Grunwald 2016-05-06 23:16:06 +02:00
parent 318d9a9ef3
commit 713a5c53d3
6 changed files with 102 additions and 62 deletions

View File

@ -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; */ };

View File

@ -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(),

View File

@ -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)*

View File

@ -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)*

View File

@ -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)]

View File

@ -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);