2017-05-16 05:24:06 +00:00
|
|
|
// Copyright (c) 2017-present PyO3 Project and Contributors
|
|
|
|
|
|
|
|
use syn;
|
2017-05-18 07:05:49 +00:00
|
|
|
use quote::{Tokens, ToTokens};
|
2017-05-20 06:14:59 +00:00
|
|
|
use method::{FnArg, FnSpec, FnType};
|
2017-05-18 07:05:49 +00:00
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
|
|
|
|
pub fn gen_py_method<'a>(cls: &Box<syn::Ty>, name: &syn::Ident,
|
2017-05-20 06:14:59 +00:00
|
|
|
sig: &mut syn::MethodSig, meth_attrs: &mut Vec<syn::Attribute>) -> Tokens
|
2017-05-16 07:07:36 +00:00
|
|
|
{
|
2017-05-16 05:24:06 +00:00
|
|
|
check_generic(name, sig);
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
let spec = FnSpec::parse(name, sig, meth_attrs);
|
2017-05-16 05:24:06 +00:00
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
match spec.tp {
|
2017-05-16 18:58:18 +00:00
|
|
|
FnType::Fn =>
|
2017-06-07 04:57:03 +00:00
|
|
|
impl_py_method_def(name, &spec, &impl_wrap(cls, name, &spec, true)),
|
2017-05-20 06:14:59 +00:00
|
|
|
FnType::FnNew =>
|
|
|
|
impl_py_method_def_new(name, &impl_wrap_new(cls, name, &spec)),
|
|
|
|
FnType::FnCall =>
|
2017-06-07 04:57:03 +00:00
|
|
|
impl_py_method_def_call(name, &impl_wrap(cls, name, &spec, false)),
|
2017-05-20 06:14:59 +00:00
|
|
|
FnType::Getter(ref getter) =>
|
|
|
|
impl_py_getter_def(name, getter, &impl_wrap_getter(cls, name, &spec)),
|
|
|
|
FnType::Setter(ref setter) =>
|
|
|
|
impl_py_setter_def(name, setter, &impl_wrap_setter(cls, name, &spec)),
|
2017-05-18 07:05:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
|
2017-05-16 18:58:18 +00:00
|
|
|
fn check_generic(name: &syn::Ident, sig: &syn::MethodSig) {
|
2017-05-16 05:24:06 +00:00
|
|
|
if !sig.generics.ty_params.is_empty() {
|
|
|
|
panic!("python method can not be generic: {:?}", name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
/// Generate function wrapper (PyCFunction, PyCFunctionWithKeywords)
|
2017-06-07 04:57:03 +00:00
|
|
|
pub fn impl_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec, noargs: bool) -> Tokens {
|
2017-05-20 06:14:59 +00:00
|
|
|
let cb = impl_call(cls, name, &spec);
|
2017-05-26 23:51:33 +00:00
|
|
|
let output = &spec.output;
|
2017-05-20 06:14:59 +00:00
|
|
|
|
2017-06-07 04:57:03 +00:00
|
|
|
if spec.args.is_empty() && noargs {
|
|
|
|
quote! {
|
|
|
|
unsafe extern "C" fn wrap(slf: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
|
|
|
{
|
|
|
|
const LOCATION: &'static str = concat!(
|
|
|
|
stringify!(#cls), ".", stringify!(#name), "()");
|
|
|
|
_pyo3::callback::cb_meth(LOCATION, |py| {
|
|
|
|
//println!("METH {:?} =====: {:?} {:?} {:?}", LOCATION, slf, args, kwargs);
|
|
|
|
let slf = #cls::from_borrowed_ptr(slf);
|
|
|
|
|
|
|
|
let result = {
|
|
|
|
let result: #output = {
|
|
|
|
#cb
|
|
|
|
};
|
|
|
|
_pyo3::callback::cb_convert(
|
|
|
|
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
|
|
|
};
|
|
|
|
py.release(slf);
|
|
|
|
//println!("METH {:?} =====", LOCATION);
|
|
|
|
result
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let body = impl_arg_params(&spec, cb);
|
2017-05-20 06:14:59 +00:00
|
|
|
|
2017-06-07 04:57:03 +00:00
|
|
|
quote! {
|
|
|
|
unsafe extern "C" fn wrap(
|
|
|
|
slf: *mut _pyo3::ffi::PyObject,
|
|
|
|
args: *mut _pyo3::ffi::PyObject,
|
|
|
|
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
|
|
|
{
|
|
|
|
const LOCATION: &'static str = concat!(
|
|
|
|
stringify!(#cls), ".", stringify!(#name), "()");
|
|
|
|
_pyo3::callback::cb_meth(LOCATION, |py| {
|
|
|
|
//println!("METH {:?} =====: {:?} {:?} {:?}", LOCATION, slf, args, kwargs);
|
|
|
|
let slf = #cls::from_borrowed_ptr(slf);
|
|
|
|
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
|
|
|
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
|
|
|
|
|
|
|
let result = {
|
|
|
|
let result: #output = {
|
|
|
|
#body
|
|
|
|
};
|
|
|
|
_pyo3::callback::cb_convert(
|
|
|
|
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
2017-06-07 02:26:59 +00:00
|
|
|
};
|
2017-06-07 04:57:03 +00:00
|
|
|
py.release(kwargs);
|
|
|
|
py.release(args);
|
|
|
|
py.release(slf);
|
|
|
|
//println!("METH {:?} =====", LOCATION);
|
|
|
|
result
|
|
|
|
})
|
|
|
|
}
|
2017-05-20 06:14:59 +00:00
|
|
|
}
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-25 05:43:07 +00:00
|
|
|
/// Generate function wrapper for protocol method (PyCFunction, PyCFunctionWithKeywords)
|
|
|
|
pub fn impl_proto_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
|
|
|
let cb = impl_call(cls, name, &spec);
|
|
|
|
let body = impl_arg_params(&spec, cb);
|
|
|
|
|
|
|
|
quote! {
|
2017-05-27 17:49:38 +00:00
|
|
|
#[allow(unused_mut)]
|
|
|
|
unsafe extern "C" fn wrap(slf: *mut _pyo3::ffi::PyObject,
|
|
|
|
args: *mut _pyo3::ffi::PyObject,
|
|
|
|
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
2017-05-25 05:43:07 +00:00
|
|
|
{
|
|
|
|
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
|
2017-05-27 17:49:38 +00:00
|
|
|
_pyo3::callback::cb_meth(LOCATION, |py| {
|
2017-06-04 00:27:26 +00:00
|
|
|
let slf = #cls::from_borrowed_ptr(slf);
|
2017-05-29 09:47:27 +00:00
|
|
|
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
|
|
|
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
2017-05-25 05:43:07 +00:00
|
|
|
|
2017-05-27 17:49:38 +00:00
|
|
|
let result = {
|
|
|
|
#body
|
|
|
|
};
|
2017-06-04 00:27:26 +00:00
|
|
|
py.release(slf);
|
2017-05-27 17:49:38 +00:00
|
|
|
_pyo3::callback::cb_convert(
|
|
|
|
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
2017-05-25 05:43:07 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-20 06:14:59 +00:00
|
|
|
|
|
|
|
/// Generate function wrapper (PyCFunction, PyCFunctionWithKeywords)
|
|
|
|
pub fn impl_wrap_new(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
|
|
|
let cb = impl_class_new(cls, name, spec);
|
|
|
|
let body = impl_arg_params(spec, cb);
|
2017-05-27 17:49:38 +00:00
|
|
|
let output = &spec.output;
|
2017-05-16 05:24:06 +00:00
|
|
|
|
|
|
|
quote! {
|
2017-05-27 17:49:38 +00:00
|
|
|
#[allow(unused_mut)]
|
2017-05-20 06:14:59 +00:00
|
|
|
unsafe extern "C" fn wrap(cls: *mut _pyo3::ffi::PyTypeObject,
|
|
|
|
args: *mut _pyo3::ffi::PyObject,
|
|
|
|
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
2017-05-16 05:24:06 +00:00
|
|
|
{
|
2017-05-27 17:49:38 +00:00
|
|
|
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name), "()");
|
|
|
|
|
|
|
|
_pyo3::callback::cb_meth(LOCATION, |py| {
|
2017-05-29 09:47:27 +00:00
|
|
|
let cls = _pyo3::PyType::from_type_ptr(py, cls);
|
|
|
|
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
|
|
|
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
2017-05-16 05:24:06 +00:00
|
|
|
|
2017-05-27 17:49:38 +00:00
|
|
|
let result: #output = {
|
|
|
|
#body
|
|
|
|
};
|
|
|
|
_pyo3::callback::cb_convert(
|
|
|
|
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
2017-05-25 05:43:07 +00:00
|
|
|
})
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 18:58:18 +00:00
|
|
|
|
|
|
|
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords)
|
2017-05-20 06:14:59 +00:00
|
|
|
fn impl_wrap_getter(cls: &Box<syn::Ty>, name: &syn::Ident, _spec: &FnSpec) -> Tokens {
|
2017-05-16 18:58:18 +00:00
|
|
|
quote! {
|
2017-05-25 05:43:07 +00:00
|
|
|
unsafe extern "C" fn wrap(slf: *mut _pyo3::ffi::PyObject,
|
|
|
|
_: *mut _pyo3::c_void)
|
|
|
|
-> *mut _pyo3::ffi::PyObject
|
2017-05-16 18:58:18 +00:00
|
|
|
{
|
|
|
|
const LOCATION: &'static str = concat!(
|
|
|
|
stringify!(#cls), ".getter_", stringify!(#name), "()");
|
2017-05-27 17:49:38 +00:00
|
|
|
_pyo3::callback::cb_unary::<#cls, _, _, _>(
|
|
|
|
LOCATION, slf, _pyo3::callback::PyObjectCallbackConverter, |py, slf| {
|
2017-05-25 05:43:07 +00:00
|
|
|
slf.#name(py)
|
|
|
|
})
|
2017-05-16 18:58:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords)
|
2017-05-20 06:14:59 +00:00
|
|
|
fn impl_wrap_setter(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
2017-05-27 17:49:38 +00:00
|
|
|
if spec.args.len() < 1 {
|
|
|
|
println!("Not enough arguments for setter {}::{}", quote!{#cls}, name);
|
|
|
|
}
|
2017-05-20 06:14:59 +00:00
|
|
|
let val_ty = spec.args[0].ty;
|
2017-05-18 21:46:29 +00:00
|
|
|
|
2017-05-16 18:58:18 +00:00
|
|
|
quote! {
|
2017-05-27 17:49:38 +00:00
|
|
|
#[allow(unused_mut)]
|
2017-05-18 18:15:06 +00:00
|
|
|
unsafe extern "C" fn wrap(slf: *mut _pyo3::ffi::PyObject,
|
|
|
|
value: *mut _pyo3::ffi::PyObject,
|
|
|
|
_: *mut _pyo3::c_void) -> _pyo3::c_int
|
2017-05-16 18:58:18 +00:00
|
|
|
{
|
|
|
|
const LOCATION: &'static str = concat!(
|
|
|
|
stringify!(#cls), ".setter", stringify!(#name), "()");
|
2017-05-27 17:49:38 +00:00
|
|
|
_pyo3::callback::cb_setter(LOCATION, |py| {
|
2017-06-04 00:27:26 +00:00
|
|
|
let slf = #cls::from_borrowed_ptr(slf);
|
2017-05-28 15:57:34 +00:00
|
|
|
let value = _pyo3::PyObject::from_borrowed_ptr(py, value);
|
2017-05-25 05:43:07 +00:00
|
|
|
|
2017-06-03 01:58:16 +00:00
|
|
|
let result = match <#val_ty as _pyo3::FromPyObject>::extract(py, &value) {
|
2017-06-04 00:27:26 +00:00
|
|
|
Ok(val) => slf.as_mut(py).#name(py, val),
|
2017-05-25 05:43:07 +00:00
|
|
|
Err(e) => Err(e)
|
2017-05-27 17:49:38 +00:00
|
|
|
};
|
2017-06-04 00:27:26 +00:00
|
|
|
py.release(slf);
|
2017-05-27 17:49:38 +00:00
|
|
|
match result {
|
|
|
|
Ok(_) => 0,
|
|
|
|
Err(e) => {
|
|
|
|
e.restore(py);
|
|
|
|
-1
|
|
|
|
}
|
2017-05-25 05:43:07 +00:00
|
|
|
}
|
|
|
|
})
|
2017-05-16 18:58:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-27 17:49:38 +00:00
|
|
|
fn impl_call(_cls: &Box<syn::Ty>, fname: &syn::Ident, spec: &FnSpec) -> Tokens {
|
2017-05-20 06:14:59 +00:00
|
|
|
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
2017-05-25 05:43:07 +00:00
|
|
|
quote! {{
|
2017-06-04 00:27:26 +00:00
|
|
|
slf.as_mut(py).#fname(py, #(#names),*)
|
2017-05-25 05:43:07 +00:00
|
|
|
}}
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
fn impl_class_new(cls: &Box<syn::Ty>, fname: &syn::Ident, spec: &FnSpec) -> Tokens {
|
|
|
|
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
2017-05-25 05:43:07 +00:00
|
|
|
quote! {{
|
2017-05-27 17:49:38 +00:00
|
|
|
#cls::#fname(&cls, py, #(#names),*)
|
2017-05-25 05:43:07 +00:00
|
|
|
}}
|
2017-05-20 06:14:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn impl_arg_params(spec: &FnSpec, body: Tokens) -> Tokens {
|
2017-05-25 05:43:07 +00:00
|
|
|
if spec.args.is_empty() {
|
|
|
|
return body
|
|
|
|
}
|
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
let mut params = Vec::new();
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
for arg in spec.args.iter() {
|
|
|
|
if ! (spec.is_args(&arg.name) || spec.is_kwargs(&arg.name)) {
|
2017-05-18 07:05:49 +00:00
|
|
|
let name = arg.name.as_ref();
|
|
|
|
let opt = if let Some(_) = arg.optional {
|
|
|
|
syn::Ident::from("true")
|
|
|
|
} else {
|
2017-05-20 06:14:59 +00:00
|
|
|
if let Some(_) = spec.default_value(&arg.name) {
|
2017-05-18 07:05:49 +00:00
|
|
|
syn::Ident::from("true")
|
|
|
|
} else {
|
|
|
|
syn::Ident::from("false")
|
|
|
|
}
|
|
|
|
};
|
|
|
|
params.push(
|
|
|
|
quote! {
|
2017-05-18 18:15:06 +00:00
|
|
|
_pyo3::argparse::ParamDescription{name: #name, is_optional: #opt,}
|
2017-05-18 07:05:49 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
let placeholders: Vec<syn::Ident> = params.iter().map(
|
|
|
|
|_| syn::Ident::from("None")).collect();
|
|
|
|
|
|
|
|
// generate extrat args
|
2017-05-20 06:14:59 +00:00
|
|
|
let mut rargs = spec.args.clone();
|
|
|
|
rargs.reverse();
|
2017-05-16 05:24:06 +00:00
|
|
|
let mut body = body;
|
2017-05-20 17:40:33 +00:00
|
|
|
for arg in rargs.iter() {
|
2017-05-18 07:05:49 +00:00
|
|
|
body = impl_arg_param(&arg, &spec, &body);
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 07:05:49 +00:00
|
|
|
let accept_args = syn::Ident::from(
|
2017-05-20 06:14:59 +00:00
|
|
|
if spec.accept_args() { "true" } else { "false" });
|
2017-05-18 07:05:49 +00:00
|
|
|
let accept_kwargs = syn::Ident::from(
|
2017-05-20 06:14:59 +00:00
|
|
|
if spec.accept_kwargs() { "true" } else { "false" });
|
2017-05-18 07:05:49 +00:00
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
// create array of arguments, and then parse
|
|
|
|
quote! {
|
2017-05-18 18:15:06 +00:00
|
|
|
const PARAMS: &'static [_pyo3::argparse::ParamDescription<'static>] = &[
|
2017-05-16 05:24:06 +00:00
|
|
|
#(#params),*
|
|
|
|
];
|
|
|
|
|
|
|
|
let mut output = [#(#placeholders),*];
|
2017-06-07 02:26:59 +00:00
|
|
|
let result = match _pyo3::argparse::parse_args(
|
|
|
|
py, Some(LOCATION), PARAMS, &args,
|
|
|
|
kwargs.as_ref(), #accept_args, #accept_kwargs, &mut output)
|
|
|
|
{
|
2017-05-16 05:24:06 +00:00
|
|
|
Ok(_) => {
|
|
|
|
let mut _iter = output.iter();
|
|
|
|
|
|
|
|
#body
|
|
|
|
},
|
|
|
|
Err(err) => Err(err)
|
2017-06-07 02:26:59 +00:00
|
|
|
};
|
|
|
|
for p in output.iter_mut() {
|
|
|
|
if let Some(ob) = p.take() {
|
|
|
|
py.release(ob);
|
|
|
|
}
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
2017-06-07 02:26:59 +00:00
|
|
|
|
|
|
|
result
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
2017-05-16 05:24:06 +00:00
|
|
|
let ty = arg.ty;
|
|
|
|
let name = arg.name;
|
|
|
|
|
|
|
|
// First unwrap() asserts the iterated sequence is long enough (which should be guaranteed);
|
|
|
|
// second unwrap() asserts the parameter was not missing (which fn
|
|
|
|
// parse_args already checked for).
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
if spec.is_args(&name) {
|
2017-05-16 05:24:06 +00:00
|
|
|
quote! {
|
2017-06-07 02:26:59 +00:00
|
|
|
match <#ty as _pyo3::FromPyObject>::extract(py, args.as_ref())
|
2017-05-16 05:24:06 +00:00
|
|
|
{
|
|
|
|
Ok(#name) => {
|
|
|
|
#body
|
|
|
|
}
|
|
|
|
Err(e) => Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-20 06:14:59 +00:00
|
|
|
else if spec.is_kwargs(&name) {
|
2017-05-18 07:05:49 +00:00
|
|
|
quote! {
|
|
|
|
let #name = kwargs.as_ref();
|
|
|
|
#body
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-05-25 05:43:07 +00:00
|
|
|
if let Some(_) = arg.optional {
|
2017-05-18 07:05:49 +00:00
|
|
|
// default value
|
|
|
|
let mut default = Tokens::new();
|
2017-05-20 06:14:59 +00:00
|
|
|
if let Some(d) = spec.default_value(name) {
|
2017-05-18 18:15:06 +00:00
|
|
|
let dt = quote!{ Some(#d) };
|
|
|
|
dt.to_tokens(&mut default);
|
2017-05-18 07:05:49 +00:00
|
|
|
} else {
|
|
|
|
syn::Ident::from("None").to_tokens(&mut default);
|
|
|
|
}
|
|
|
|
|
|
|
|
quote! {
|
2017-05-25 05:43:07 +00:00
|
|
|
match
|
|
|
|
match _iter.next().unwrap().as_ref() {
|
|
|
|
Some(obj) => {
|
2017-06-03 01:58:16 +00:00
|
|
|
if obj.is_none(py) {
|
2017-05-25 05:43:07 +00:00
|
|
|
Ok(#default)
|
|
|
|
} else {
|
2017-06-03 01:58:16 +00:00
|
|
|
match obj.extract(py) {
|
2017-05-25 05:43:07 +00:00
|
|
|
Ok(obj) => Ok(Some(obj)),
|
|
|
|
Err(e) => Err(e)
|
|
|
|
}
|
2017-05-19 04:35:08 +00:00
|
|
|
}
|
2017-05-25 05:43:07 +00:00
|
|
|
},
|
|
|
|
None => Ok(#default)
|
|
|
|
}
|
|
|
|
{
|
2017-05-18 07:05:49 +00:00
|
|
|
Ok(#name) => #body,
|
|
|
|
Err(e) => Err(e)
|
|
|
|
}
|
|
|
|
}
|
2017-05-20 06:14:59 +00:00
|
|
|
} else if let Some(default) = spec.default_value(name) {
|
2017-05-18 07:05:49 +00:00
|
|
|
quote! {
|
|
|
|
match match _iter.next().unwrap().as_ref() {
|
|
|
|
Some(obj) => {
|
2017-06-06 03:25:00 +00:00
|
|
|
if obj.is_none(py) {
|
2017-05-19 04:35:08 +00:00
|
|
|
Ok(#default)
|
|
|
|
} else {
|
2017-06-03 01:58:16 +00:00
|
|
|
match obj.extract(py) {
|
2017-05-19 04:35:08 +00:00
|
|
|
Ok(obj) => Ok(obj),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
2017-05-18 07:05:49 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
None => Ok(#default)
|
|
|
|
} {
|
|
|
|
Ok(#name) => #body,
|
|
|
|
Err(e) => Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
quote! {
|
2017-06-03 01:58:16 +00:00
|
|
|
match _iter.next().unwrap().as_ref().unwrap().extract(py)
|
2017-05-18 07:05:49 +00:00
|
|
|
{
|
|
|
|
Ok(#name) => {
|
|
|
|
#body
|
|
|
|
}
|
|
|
|
Err(e) => Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-07 04:57:03 +00:00
|
|
|
pub fn impl_py_method_def(name: &syn::Ident, spec: &FnSpec, wrapper: &Tokens) -> Tokens {
|
|
|
|
if spec.args.is_empty() {
|
|
|
|
quote! {
|
|
|
|
_pyo3::class::PyMethodDefType::Method({
|
|
|
|
#wrapper
|
|
|
|
|
|
|
|
_pyo3::class::PyMethodDef {
|
|
|
|
ml_name: stringify!(#name),
|
|
|
|
ml_meth: _pyo3::class::PyMethodType::PyNoArgsFunction(wrap),
|
|
|
|
ml_flags: _pyo3::ffi::METH_NOARGS,
|
|
|
|
ml_doc: "",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
quote! {
|
|
|
|
_pyo3::class::PyMethodDefType::Method({
|
|
|
|
#wrapper
|
|
|
|
|
|
|
|
_pyo3::class::PyMethodDef {
|
|
|
|
ml_name: stringify!(#name),
|
|
|
|
ml_meth: _pyo3::class::PyMethodType::PyCFunctionWithKeywords(wrap),
|
|
|
|
ml_flags: _pyo3::ffi::METH_VARARGS | _pyo3::ffi::METH_KEYWORDS,
|
|
|
|
ml_doc: "",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-05-18 07:05:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
pub fn impl_py_method_def_new(name: &syn::Ident, wrapper: &Tokens) -> Tokens {
|
|
|
|
quote! {
|
|
|
|
_pyo3::class::PyMethodDefType::New({
|
|
|
|
#wrapper
|
2017-05-18 07:05:49 +00:00
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
_pyo3::class::PyMethodDef {
|
|
|
|
ml_name: stringify!(#name),
|
|
|
|
ml_meth: _pyo3::class::PyMethodType::PyNewFunc(wrap),
|
|
|
|
ml_flags: _pyo3::ffi::METH_VARARGS | _pyo3::ffi::METH_KEYWORDS,
|
|
|
|
ml_doc: "",
|
|
|
|
}
|
|
|
|
})
|
2017-05-18 07:05:49 +00:00
|
|
|
}
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
pub fn impl_py_method_def_call(name: &syn::Ident, wrapper: &Tokens) -> Tokens {
|
2017-05-16 18:58:18 +00:00
|
|
|
quote! {
|
2017-05-20 06:14:59 +00:00
|
|
|
_pyo3::class::PyMethodDefType::Call({
|
2017-05-16 18:58:18 +00:00
|
|
|
#wrapper
|
|
|
|
|
2017-05-18 18:15:06 +00:00
|
|
|
_pyo3::class::PyMethodDef {
|
2017-05-16 18:58:18 +00:00
|
|
|
ml_name: stringify!(#name),
|
2017-05-18 18:15:06 +00:00
|
|
|
ml_meth: _pyo3::class::PyMethodType::PyCFunctionWithKeywords(wrap),
|
|
|
|
ml_flags: _pyo3::ffi::METH_VARARGS | _pyo3::ffi::METH_KEYWORDS,
|
2017-05-16 18:58:18 +00:00
|
|
|
ml_doc: "",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
fn impl_py_setter_def(name: &syn::Ident, setter: &Option<String>, wrapper: &Tokens) -> Tokens {
|
|
|
|
let n = if let &Some(ref name) = setter {
|
2017-05-16 18:58:18 +00:00
|
|
|
name.to_string()
|
|
|
|
} else {
|
|
|
|
let n = String::from(name.as_ref());
|
|
|
|
if n.starts_with("set_") {
|
|
|
|
n[4..].to_string()
|
|
|
|
} else {
|
|
|
|
n
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
quote! {
|
2017-05-18 18:15:06 +00:00
|
|
|
_pyo3::class::PyMethodDefType::Setter({
|
2017-05-16 18:58:18 +00:00
|
|
|
#wrapper
|
|
|
|
|
2017-05-18 18:15:06 +00:00
|
|
|
_pyo3::class::PySetterDef {
|
2017-05-16 18:58:18 +00:00
|
|
|
name: #n,
|
|
|
|
meth: wrap,
|
|
|
|
doc: "",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 06:14:59 +00:00
|
|
|
fn impl_py_getter_def(name: &syn::Ident, getter: &Option<String>, wrapper: &Tokens) -> Tokens {
|
|
|
|
let n = if let &Some(ref name) = getter {
|
2017-05-16 18:58:18 +00:00
|
|
|
name.to_string()
|
|
|
|
} else {
|
|
|
|
let n = String::from(name.as_ref());
|
|
|
|
if n.starts_with("get_") {
|
|
|
|
n[4..].to_string()
|
|
|
|
} else {
|
|
|
|
n
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
2017-05-16 18:58:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
quote! {
|
2017-05-18 18:15:06 +00:00
|
|
|
_pyo3::class::PyMethodDefType::Getter({
|
2017-05-16 18:58:18 +00:00
|
|
|
#wrapper
|
|
|
|
|
2017-05-18 18:15:06 +00:00
|
|
|
_pyo3::class::PyGetterDef {
|
2017-05-16 18:58:18 +00:00
|
|
|
name: #n,
|
|
|
|
meth: wrap,
|
|
|
|
doc: "",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|