new impl for sequence protocol
This commit is contained in:
parent
452a4e8d7f
commit
629f53ac52
|
@ -7,7 +7,10 @@ use quote::Tokens;
|
|||
pub enum MethodProto {
|
||||
Unary{name: &'static str, pyres: bool, proto: &'static str, },
|
||||
Binary{name: &'static str, arg: &'static str, pyres: bool, proto: &'static str},
|
||||
Ternary{name: &'static str, arg1: &'static str, arg2: &'static str, proto: &'static str},
|
||||
Ternary{name: &'static str,
|
||||
arg1: &'static str,
|
||||
arg2: &'static str,
|
||||
pyres: bool, proto: &'static str},
|
||||
Quaternary{name: &'static str,
|
||||
arg1: &'static str,
|
||||
arg2: &'static str,
|
||||
|
@ -20,7 +23,7 @@ impl MethodProto {
|
|||
match *self {
|
||||
MethodProto::Unary{name: n, pyres: _, proto: _} => n == name,
|
||||
MethodProto::Binary{name: n, arg: _, pyres: _, proto: _} => n == name,
|
||||
MethodProto::Ternary{name: n, arg1: _, arg2: _, proto: _} => n == name,
|
||||
MethodProto::Ternary{name: n, arg1: _, arg2: _, pyres: _, proto: _} => n == name,
|
||||
MethodProto::Quaternary{name: n, arg1: _, arg2: _, arg3: _, proto: _} => n == name,
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +78,7 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
}
|
||||
}
|
||||
},
|
||||
MethodProto::Ternary{name: _, arg1, arg2, proto} => {
|
||||
MethodProto::Ternary{name: _, arg1, arg2, pyres, proto} => {
|
||||
let p = syn::Ident::from(proto);
|
||||
let arg1_name = syn::Ident::from(arg1);
|
||||
let arg1_ty = get_arg_ty(sig, 2);
|
||||
|
@ -83,12 +86,22 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
let arg2_ty = get_arg_ty(sig, 3);
|
||||
let succ = get_res_success(ty);
|
||||
|
||||
quote! {
|
||||
impl #p for #cls {
|
||||
type #arg1_name = #arg1_ty;
|
||||
type #arg2_name = #arg2_ty;
|
||||
type Success = #succ;
|
||||
type Result = #ty;
|
||||
if pyres {
|
||||
quote! {
|
||||
impl #p for #cls {
|
||||
type #arg1_name = #arg1_ty;
|
||||
type #arg2_name = #arg2_ty;
|
||||
type Success = #succ;
|
||||
type Result = #ty;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
impl #p for #cls {
|
||||
type #arg1_name = #arg1_ty;
|
||||
type #arg2_name = #arg2_ty;
|
||||
type Result = #ty;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -132,11 +132,12 @@ static MAPPING: Proto = Proto {
|
|||
name: "__setitem__",
|
||||
arg1: "Key",
|
||||
arg2: "Value",
|
||||
pyres: false,
|
||||
proto: "_pyo3::class::mapping::PyMappingSetItemProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__delitem__",
|
||||
arg: "Key",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "_pyo3::class::mapping::PyMappingDelItemProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__contains__",
|
||||
|
@ -166,7 +167,54 @@ static MAPPING: Proto = Proto {
|
|||
proto: "_pyo3::class::mapping::PyMappingReversedProtocolImpl",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
static SEQ: Proto = Proto {
|
||||
name: "Sequence",
|
||||
methods: &[
|
||||
MethodProto::Unary{
|
||||
name: "__len__",
|
||||
pyres: false,
|
||||
proto: "_pyo3::class::sequence::PySequenceLenProtocol"},
|
||||
MethodProto::Unary{
|
||||
name: "__getitem__",
|
||||
pyres: true,
|
||||
proto: "_pyo3::class::sequence::PySequenceGetItemProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__setitem__",
|
||||
arg: "Value",
|
||||
pyres: false,
|
||||
proto: "_pyo3::class::sequence::PyMappingSetItemProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__delitem__",
|
||||
arg: "Key",
|
||||
pyres: false,
|
||||
proto: "_pyo3::class::mapping::PyMappingDelItemProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__contains__",
|
||||
arg: "Item",
|
||||
pyres: false,
|
||||
proto: "_pyo3::class::sequence::PySequenceContainsProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__concat__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
proto: "_pyo3::class::sequence::PySequenceConcatProtocol"},
|
||||
MethodProto::Unary{
|
||||
name: "__repeat__",
|
||||
pyres: true,
|
||||
proto: "_pyo3::class::sequence::PySequenceRepeatProtocol"},
|
||||
MethodProto::Binary{
|
||||
name: "__inplace_concat__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
proto: "_pyo3::class::sequence::PySequenceInplaceConcatProtocol"},
|
||||
MethodProto::Unary{
|
||||
name: "__inplace_repeat__",
|
||||
pyres: true,
|
||||
proto: "_pyo3::class::sequence::PySequenceInplaceRepeatProtocol"},
|
||||
],
|
||||
py_methods: &[],
|
||||
};
|
||||
|
||||
|
||||
|
@ -187,6 +235,8 @@ pub fn build_py_proto(ast: &mut syn::Item) -> Tokens {
|
|||
impl_proto_impl(ty, impl_items, &ITER),
|
||||
"PyContextProtocol" =>
|
||||
impl_proto_impl(ty, impl_items, &CONTEXT),
|
||||
"PySequenceProtocol" =>
|
||||
impl_proto_impl(ty, impl_items, &SEQ),
|
||||
"PyBufferProtocol" =>
|
||||
impl_protocol("_pyo3::class::buffer::PyBufferProtocolImpl",
|
||||
path.clone(), ty, impl_items, &DEFAULT_METHODS),
|
||||
|
@ -196,9 +246,6 @@ pub fn build_py_proto(ast: &mut syn::Item) -> Tokens {
|
|||
"PyGCProtocol" =>
|
||||
impl_protocol("_pyo3::class::gc::PyGCProtocolImpl",
|
||||
path.clone(), ty, impl_items, &DEFAULT_METHODS),
|
||||
"PySequenceProtocol" =>
|
||||
impl_protocol("_pyo3::class::sequence::PySequenceProtocolImpl",
|
||||
path.clone(), ty, impl_items, &DEFAULT_METHODS),
|
||||
"PyNumberProtocol" =>
|
||||
impl_protocol("_pyo3::class::number::PyNumberProtocolImpl",
|
||||
path.clone(), ty, impl_items, &NUM_METHODS),
|
||||
|
|
|
@ -162,23 +162,24 @@ macro_rules! py_ternary_func {
|
|||
#[doc(hidden)]
|
||||
macro_rules! py_ssizearg_func {
|
||||
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
arg: $crate::Py_ssize_t) -> *mut $crate::ffi::PyObject
|
||||
where T: $trait + PythonObject
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut $crate::ffi::PyObject,
|
||||
arg: $crate::Py_ssize_t,
|
||||
) -> *mut $crate::ffi::PyObject
|
||||
where T: $trait
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::callback::handle_callback(LOCATION, $conv, |py| {
|
||||
let slf = $crate::PyObject::from_borrowed_ptr(py, slf).unchecked_cast_into::<T>();
|
||||
let slf = $crate::PyObject::from_borrowed_ptr(py,slf).unchecked_cast_into::<T>();
|
||||
let ret = slf.$f(py, arg as isize);
|
||||
$crate::PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
ret.into()
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
Some(wrap::<$class>)
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_objobj_proc {
|
||||
|
@ -201,6 +202,32 @@ macro_rules! py_objobj_proc {
|
|||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_objobj_proc_ {
|
||||
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
arg: *mut $crate::ffi::PyObject,
|
||||
) -> $crate::c_int
|
||||
where T: $trait + PythonObject
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::callback::handle_callback(LOCATION, $conv, |py| {
|
||||
let slf = $crate::PyObject::from_borrowed_ptr(py,slf).unchecked_cast_into::<T>();
|
||||
let arg = PyObject::from_borrowed_ptr(py, arg);
|
||||
let ret = match arg.extract(py) {
|
||||
Ok(arg) => slf.$f(py, arg).into(),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
$crate::PyDrop::release_ref(arg, py);
|
||||
$crate::PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_ternary_slot {
|
||||
|
|
|
@ -58,13 +58,11 @@ pub trait PyMappingGetItemProtocol: PyMappingProtocol {
|
|||
pub trait PyMappingSetItemProtocol: PyMappingProtocol {
|
||||
type Key: for<'a> FromPyObject<'a>;
|
||||
type Value: for<'a> FromPyObject<'a>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
|
||||
pub trait PyMappingDelItemProtocol: PyMappingProtocol {
|
||||
type Key: for<'a> FromPyObject<'a>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
|
||||
|
@ -103,11 +101,11 @@ impl<T> PyMappingProtocolImpl for T {
|
|||
impl<T> PyMappingProtocolImpl for T where T: PyMappingProtocol {
|
||||
#[inline]
|
||||
fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
|
||||
let mut f = Self::mp_ass_subscript();
|
||||
|
||||
if let Some(df) = Self::mp_del_subscript() {
|
||||
f = Some(df)
|
||||
}
|
||||
let f = if let Some(df) = Self::mp_del_subscript() {
|
||||
Some(df)
|
||||
} else {
|
||||
Self::mp_ass_subscript()
|
||||
};
|
||||
|
||||
Some(ffi::PyMappingMethods {
|
||||
mp_length: Self::mp_length(),
|
||||
|
|
|
@ -9,160 +9,207 @@ use ffi;
|
|||
use err::{PyErr, PyResult};
|
||||
use python::{Python, PythonObject, PyDrop};
|
||||
use objects::{exc, PyObject};
|
||||
use callback::{handle_callback, PyObjectCallbackConverter,
|
||||
use callback::{PyObjectCallbackConverter,
|
||||
LenResultConverter, UnitCallbackConverter, BoolConverter};
|
||||
use class::NO_METHODS;
|
||||
use ::{ToPyObject, FromPyObject};
|
||||
|
||||
|
||||
/// Sequece interface
|
||||
pub trait PySequenceProtocol {
|
||||
fn __len__(&self, py: Python) -> PyResult<usize>;
|
||||
#[allow(unused_variables)]
|
||||
pub trait PySequenceProtocol: PythonObject {
|
||||
fn __len__(&self, py: Python) -> Self::Result
|
||||
where Self: PySequenceLenProtocol { unimplemented!() }
|
||||
|
||||
fn __getitem__(&self, py: Python, key: isize) -> PyResult<PyObject>;
|
||||
fn __getitem__(&self, py: Python, key: isize) -> Self::Result
|
||||
where Self: PySequenceGetItemProtocol { unimplemented!() }
|
||||
|
||||
fn __setitem__(&self, py: Python, key: isize, value: &PyObject) -> PyResult<()>;
|
||||
fn __setitem__(&self, py: Python, key: isize, value: Self::Value) -> Self::Result
|
||||
where Self: PySequenceSetItemProtocol { unimplemented!() }
|
||||
|
||||
fn __delitem__(&self, py: Python, key: isize) -> PyResult<()>;
|
||||
fn __delitem__(&self, py: Python, key: isize) -> Self::Result
|
||||
where Self: PySequenceDelItemProtocol { unimplemented!() }
|
||||
|
||||
fn __contains__(&self, py: Python, value: &PyObject) -> PyResult<bool>;
|
||||
fn __contains__(&self, py: Python, item: Self::Item) -> Self::Result
|
||||
where Self: PySequenceContainsProtocol { unimplemented!() }
|
||||
|
||||
fn __concat__(&self, py: Python, other: &PyObject) -> PyResult<PyObject>;
|
||||
fn __concat__(&self, py: Python, other: Self::Other) -> Self::Result
|
||||
where Self: PySequenceConcatProtocol { unimplemented!() }
|
||||
|
||||
fn __repeat__(&self, py: Python, count: isize) -> PyResult<PyObject>;
|
||||
fn __repeat__(&self, py: Python, count: isize) -> Self::Result
|
||||
where Self: PySequenceRepeatProtocol { unimplemented!() }
|
||||
|
||||
fn __inplace_concat__(&self, py: Python, other: &PyObject) -> PyResult<PyObject>;
|
||||
|
||||
fn __inplace_repeat__(&self, py: Python, count: isize) -> PyResult<PyObject>;
|
||||
fn __inplace_concat__(&self, py: Python, other: Self::Other) -> Self::Result
|
||||
where Self: PySequenceInplaceConcatProtocol { unimplemented!() }
|
||||
|
||||
fn __inplace_repeat__(&self, py: Python, count: isize) -> Self::Result
|
||||
where Self: PySequenceInplaceRepeatProtocol { unimplemented!() }
|
||||
}
|
||||
|
||||
impl<T> PySequenceProtocol for T where T: PythonObject {
|
||||
default fn __len__(&self, py: Python) -> PyResult<usize> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
// The following are a bunch of marker traits used to detect
|
||||
// the existance of a slotted method.
|
||||
|
||||
default fn __getitem__(&self, py: Python, _: isize) -> PyResult<PyObject> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
pub trait PySequenceLenProtocol: PySequenceProtocol {
|
||||
type Result: Into<PyResult<usize>>;
|
||||
}
|
||||
|
||||
default fn __setitem__(&self, py: Python, _: isize, _: &PyObject) -> PyResult<()> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(
|
||||
py, format!("Subscript assignment not supported by {:?}", self.as_object())))
|
||||
}
|
||||
pub trait PySequenceGetItemProtocol: PySequenceProtocol {
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
||||
default fn __delitem__(&self, py: Python, _: isize) -> PyResult<()> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(
|
||||
py, format!("Subscript deletion not supported by {:?}", self.as_object())))
|
||||
}
|
||||
pub trait PySequenceSetItemProtocol: PySequenceProtocol {
|
||||
type Value: for<'a> FromPyObject<'a>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
|
||||
default fn __contains__(&self, py: Python, _: &PyObject) -> PyResult<bool> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
pub trait PySequenceDelItemProtocol: PySequenceProtocol {
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
|
||||
default fn __concat__(&self, py: Python, _: &PyObject) -> PyResult<PyObject> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
pub trait PySequenceContainsProtocol: PySequenceProtocol {
|
||||
type Item: for<'a> FromPyObject<'a>;
|
||||
type Result: Into<PyResult<bool>>;
|
||||
}
|
||||
|
||||
default fn __repeat__(&self, py: Python, _: isize) -> PyResult<PyObject> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
pub trait PySequenceConcatProtocol: PySequenceProtocol {
|
||||
type Other: for<'a> FromPyObject<'a>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
||||
default fn __inplace_concat__(&self, py: Python, _: &PyObject) -> PyResult<PyObject> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
pub trait PySequenceRepeatProtocol: PySequenceProtocol {
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
||||
default fn __inplace_repeat__(&self, py: Python, _: isize) -> PyResult<PyObject> {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(py, "Not implemented"))
|
||||
}
|
||||
pub trait PySequenceInplaceConcatProtocol: PySequenceProtocol + ToPyObject {
|
||||
type Other: for<'a> FromPyObject<'a>;
|
||||
type Result: Into<PyResult<Self>>;
|
||||
}
|
||||
|
||||
pub trait PySequenceInplaceRepeatProtocol: PySequenceProtocol + ToPyObject {
|
||||
type Result: Into<PyResult<Self>>;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PySequenceProtocolImpl {
|
||||
fn methods() -> &'static [&'static str];
|
||||
fn tp_as_sequence() -> Option<ffi::PySequenceMethods>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceProtocolImpl for T {
|
||||
default fn methods() -> &'static [&'static str] {
|
||||
NO_METHODS
|
||||
#[inline]
|
||||
default fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl ffi::PySequenceMethods {
|
||||
impl<T> PySequenceProtocolImpl for T where T: PySequenceProtocol {
|
||||
#[inline]
|
||||
fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
|
||||
let f = if let Some(df) = Self::sq_del_item() {
|
||||
Some(df)
|
||||
} else {
|
||||
Self::sq_ass_item()
|
||||
};
|
||||
|
||||
/// Construct PySequenceMethods struct for PyTypeObject.tp_as_sequence
|
||||
pub fn new<T>() -> Option<ffi::PySequenceMethods>
|
||||
where T: PySequenceProtocol + PySequenceProtocolImpl + PythonObject
|
||||
{
|
||||
let methods = T::methods();
|
||||
if methods.is_empty() {
|
||||
return None
|
||||
}
|
||||
|
||||
let mut meth: ffi::PySequenceMethods = ffi::PySequenceMethods_INIT;
|
||||
|
||||
for name in methods {
|
||||
match name {
|
||||
&"__len__" => {
|
||||
meth.sq_length = py_len_func!(
|
||||
PySequenceProtocol, T::__len__, LenResultConverter);
|
||||
},
|
||||
&"__getitem__" => {
|
||||
meth.sq_item = py_ssizearg_func!(
|
||||
PySequenceProtocol, T::__getitem__, PyObjectCallbackConverter);
|
||||
},
|
||||
&"__repeat__" => {
|
||||
meth.sq_repeat = py_ssizearg_func!(
|
||||
PySequenceProtocol, T::__repeat__, PyObjectCallbackConverter);
|
||||
},
|
||||
&"__contains__" => {
|
||||
meth.sq_contains = py_objobj_proc!(
|
||||
PySequenceProtocol, T::__contains__, BoolConverter);
|
||||
},
|
||||
&"__concat__" => {
|
||||
meth.sq_concat = py_binary_func!(
|
||||
PySequenceProtocol, T::__concat__, PyObjectCallbackConverter);
|
||||
},
|
||||
&"__inplace_concat__" => {
|
||||
meth.sq_inplace_concat = py_binary_func!(
|
||||
PySequenceProtocol, T::__inplace_concat__, PyObjectCallbackConverter);
|
||||
},
|
||||
&"__inplace_repeat__" => {
|
||||
meth.sq_inplace_repeat = py_ssizearg_func!(
|
||||
PySequenceProtocol, T::__inplace_repeat__, PyObjectCallbackConverter);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// always set
|
||||
meth.sq_ass_item = Some(sq_ass_subscript::<T>());
|
||||
|
||||
Some(meth)
|
||||
Some(ffi::PySequenceMethods {
|
||||
sq_length: Self::sq_length(),
|
||||
sq_concat: Self::sq_concat(),
|
||||
sq_repeat: Self::sq_repeat(),
|
||||
sq_item: Self::sq_item(),
|
||||
was_sq_slice: 0 as *mut _,
|
||||
sq_ass_item: f,
|
||||
was_sq_ass_slice: 0 as *mut _,
|
||||
sq_contains: Self::sq_contains(),
|
||||
sq_inplace_concat: Self::sq_inplace_concat(),
|
||||
sq_inplace_repeat: Self::sq_inplace_repeat(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceLenProtocolImpl {
|
||||
fn sq_length() -> Option<ffi::lenfunc>;
|
||||
}
|
||||
|
||||
fn sq_ass_subscript<T>() -> ffi::ssizeobjargproc
|
||||
where T: PySequenceProtocol + PythonObject
|
||||
impl<T> PySequenceLenProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject) -> c_int
|
||||
where T: PySequenceProtocol + PythonObject
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".__setitem__()");
|
||||
#[inline]
|
||||
default fn sq_length() -> Option<ffi::lenfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
handle_callback(
|
||||
LOCATION, UnitCallbackConverter, |py|
|
||||
{
|
||||
impl<T> PySequenceLenProtocolImpl for T
|
||||
where T: PySequenceLenProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_length() -> Option<ffi::lenfunc> {
|
||||
py_len_func_!(PySequenceLenProtocol, T::__len__, LenResultConverter)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceGetItemProtocolImpl {
|
||||
fn sq_item() -> Option<ffi::ssizeargfunc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceGetItemProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_item() -> Option<ffi::ssizeargfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceGetItemProtocolImpl for T
|
||||
where T: PySequenceGetItemProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_item() -> Option<ffi::ssizeargfunc> {
|
||||
py_ssizearg_func!(PySequenceGetItemProtocol, T::__getitem__, PyObjectCallbackConverter)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceSetItemProtocolImpl {
|
||||
fn sq_ass_item() -> Option<ffi::ssizeobjargproc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceSetItemProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceSetItemProtocolImpl for T
|
||||
where T: PySequenceSetItemProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where T: PySequenceSetItemProtocol
|
||||
{
|
||||
const LOCATION: &'static str = "foo.__setitem__()";
|
||||
::callback::handle_callback(LOCATION, UnitCallbackConverter, |py| {
|
||||
let slf = PyObject::from_borrowed_ptr(py, slf).unchecked_cast_into::<T>();
|
||||
|
||||
// if value is none, then __delitem__
|
||||
let ret = if value.is_null() {
|
||||
slf.__delitem__(py, key as isize)
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(
|
||||
py, format!("Item deletion not supported by {:?}",
|
||||
stringify!(T))))
|
||||
} else {
|
||||
let value = PyObject::from_borrowed_ptr(py, value);
|
||||
let ret = slf.__setitem__(py, key as isize, &value);
|
||||
let ret = match value.extract(py) {
|
||||
Ok(value) => slf.__setitem__(py, key as isize, value).into(),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
PyDrop::release_ref(value, py);
|
||||
ret
|
||||
};
|
||||
|
@ -170,6 +217,195 @@ fn sq_ass_subscript<T>() -> ffi::ssizeobjargproc
|
|||
PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceDelItemProtocolImpl {
|
||||
fn sq_del_item() -> Option<ffi::ssizeobjargproc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceDelItemProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceDelItemProtocolImpl for T
|
||||
where T: PySequenceDelItemProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject) -> c_int
|
||||
where T: PySequenceDelItemProtocol
|
||||
{
|
||||
const LOCATION: &'static str = "T.__detitem__()";
|
||||
::callback::handle_callback(LOCATION, UnitCallbackConverter, |py| {
|
||||
let slf = PyObject::from_borrowed_ptr(py, slf).unchecked_cast_into::<T>();
|
||||
|
||||
let ret = if value.is_null() {
|
||||
slf.__delitem__(py, key as isize).into()
|
||||
} else {
|
||||
Err(PyErr::new::<exc::NotImplementedError, _>(
|
||||
py, format!("Item assignment not supported by {:?}",
|
||||
stringify!(T))))
|
||||
};
|
||||
|
||||
PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceDelItemProtocolImpl for T
|
||||
where T: PySequenceSetItemProtocol + PySequenceDelItemProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject) -> c_int
|
||||
where T: PySequenceSetItemProtocol + PySequenceDelItemProtocol
|
||||
{
|
||||
const LOCATION: &'static str = "T.__set/del_item__()";
|
||||
::callback::handle_callback(LOCATION, UnitCallbackConverter, |py| {
|
||||
let slf = PyObject::from_borrowed_ptr(py, slf).unchecked_cast_into::<T>();
|
||||
|
||||
let ret = if value.is_null() {
|
||||
slf.__delitem__(py, key).into()
|
||||
} else {
|
||||
let value = PyObject::from_borrowed_ptr(py, value);
|
||||
let ret = match value.extract(py) {
|
||||
Ok(value) => slf.__setitem__(py, key, value).into(),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
PyDrop::release_ref(value, py);
|
||||
ret
|
||||
};
|
||||
|
||||
PyDrop::release_ref(slf, py);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
trait PySequenceContainsProtocolImpl {
|
||||
fn sq_contains() -> Option<ffi::objobjproc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceContainsProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_contains() -> Option<ffi::objobjproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceContainsProtocolImpl for T
|
||||
where T: PySequenceContainsProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_contains() -> Option<ffi::objobjproc> {
|
||||
py_objobj_proc_!(PySequenceContainsProtocol, T::__contains__, BoolConverter)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceConcatProtocolImpl {
|
||||
fn sq_concat() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceConcatProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_concat() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceConcatProtocolImpl for T
|
||||
where T: PySequenceConcatProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_concat() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func_!(PySequenceConcatProtocol, T::__concat__, PyObjectCallbackConverter)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceRepeatProtocolImpl {
|
||||
fn sq_repeat() -> Option<ffi::ssizeargfunc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceRepeatProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceRepeatProtocolImpl for T
|
||||
where T: PySequenceRepeatProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
py_ssizearg_func!(PySequenceRepeatProtocol, T::__repeat__, PyObjectCallbackConverter)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceInplaceConcatProtocolImpl {
|
||||
fn sq_inplace_concat() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceInplaceConcatProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceInplaceConcatProtocolImpl for T
|
||||
where T: PySequenceInplaceConcatProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func_!(PySequenceInplaceConcatProtocol, T::__inplace_concat__, PyObjectCallbackConverter)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceInplaceRepeatProtocolImpl {
|
||||
fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceInplaceRepeatProtocolImpl for T
|
||||
where T: PySequenceProtocol
|
||||
{
|
||||
#[inline]
|
||||
default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceInplaceRepeatProtocolImpl for T
|
||||
where T: PySequenceInplaceRepeatProtocol
|
||||
{
|
||||
#[inline]
|
||||
fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
py_ssizearg_func!(PySequenceInplaceRepeatProtocol, T::__inplace_repeat__, PyObjectCallbackConverter)
|
||||
}
|
||||
wrap::<T>
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ pub fn initialize_type<T>(py: Python, module_name: Option<&str>, type_name: &str
|
|||
}
|
||||
|
||||
// sequence methods
|
||||
if let Some(meth) = ffi::PySequenceMethods::new::<T>() {
|
||||
if let Some(meth) = <T as class::sequence::PySequenceProtocolImpl>::tp_as_sequence() {
|
||||
static mut SQ_METHODS: ffi::PySequenceMethods = ffi::PySequenceMethods_INIT;
|
||||
*(unsafe { &mut SQ_METHODS }) = meth;
|
||||
type_object.tp_as_sequence = unsafe { &mut SQ_METHODS };
|
||||
|
@ -214,6 +214,9 @@ fn py_class_method_defs<T>() -> (Option<ffi::newfunc>,
|
|||
for def in <T as class::context::PyContextProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::mapping::PyMappingProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
|
||||
(new, call, defs)
|
||||
}
|
||||
|
|
|
@ -468,7 +468,7 @@ fn comparisons() {
|
|||
}
|
||||
|
||||
|
||||
/*#[py::class]
|
||||
#[py::class]
|
||||
struct Sequence {}
|
||||
|
||||
#[py::proto]
|
||||
|
@ -477,7 +477,7 @@ impl PySequenceProtocol for Sequence {
|
|||
Ok(5)
|
||||
}
|
||||
|
||||
fn __getitem__(&self, py: Python, key: isize) -> PyResult<PyObject> {
|
||||
fn __getitem__(&self, py: Python, key: isize) -> PyResult<isize> {
|
||||
if key == 5 {
|
||||
return Err(PyErr::new::<exc::IndexError, NoArgs>(py, NoArgs));
|
||||
}
|
||||
|
@ -492,8 +492,8 @@ fn sequence() {
|
|||
|
||||
let c = Sequence::create_instance(py).unwrap();
|
||||
py_assert!(py, c, "list(c) == [0, 1, 2, 3, 4]");
|
||||
py_assert!(py, c, "c['abc'] == 'abc'");
|
||||
}*/
|
||||
py_expect_exception!(py, c, "c['abc']", TypeError);
|
||||
}
|
||||
|
||||
|
||||
#[py::class]
|
||||
|
@ -622,11 +622,11 @@ fn reversed() {
|
|||
py_run!(py, c, "assert reversed(c) == 'I am reversed'");
|
||||
}
|
||||
|
||||
/*#[py::class]
|
||||
#[py::class]
|
||||
struct Contains {}
|
||||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol for Contains {
|
||||
impl PySequenceProtocol for Contains {
|
||||
fn __contains__(&self, py: Python, item: i32) -> PyResult<bool> {
|
||||
Ok(item >= 0)
|
||||
}
|
||||
|
@ -640,8 +640,8 @@ fn contains() {
|
|||
let c = Contains::create_instance(py).unwrap();
|
||||
py_run!(py, c, "assert 1 in c");
|
||||
py_run!(py, c, "assert -1 not in c");
|
||||
py_run!(py, c, "assert 'wrong type' not in c");
|
||||
}*/
|
||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", TypeError);
|
||||
}
|
||||
|
||||
/*
|
||||
py_class!(class UnaryArithmetic |py| {
|
||||
|
|
Loading…
Reference in New Issue