new impl for sequence protocol

This commit is contained in:
Nikolay Kim 2017-05-20 12:15:28 -07:00
parent 452a4e8d7f
commit 629f53ac52
7 changed files with 470 additions and 146 deletions

View File

@ -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;
}
}
}
},

View File

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

View File

@ -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 {

View File

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

View File

@ -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>
}

View File

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

View File

@ -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| {