pyo3/pyo3-derive-backend/src/pymethod.rs

653 lines
21 KiB
Rust
Raw Normal View History

2017-05-16 05:24:06 +00:00
// Copyright (c) 2017-present PyO3 Project and Contributors
use crate::method::{FnArg, FnSpec, FnType};
2019-02-01 13:01:18 +00:00
use crate::utils;
use proc_macro2::{Span, TokenStream};
use quote::quote;
2017-05-18 07:05:49 +00:00
pub fn gen_py_method(
cls: &syn::Type,
2019-08-11 12:16:02 +00:00
sig: &mut syn::Signature,
2018-07-03 20:28:40 +00:00
meth_attrs: &mut Vec<syn::Attribute>,
) -> syn::Result<TokenStream> {
check_generic(sig)?;
2017-05-16 05:24:06 +00:00
let spec = FnSpec::parse(sig, &mut *meth_attrs, true)?;
2017-05-16 05:24:06 +00:00
Ok(match spec.tp {
FnType::Fn => impl_py_method_def(&spec, &impl_wrap(cls, &spec, true)),
FnType::PySelf(ref self_ty) => {
impl_py_method_def(&spec, &impl_wrap_pyslf(cls, &spec, self_ty, true))
2018-07-03 20:28:40 +00:00
}
FnType::FnNew => impl_py_method_def_new(&spec, &impl_wrap_new(cls, &spec)),
FnType::FnCall => impl_py_method_def_call(&spec, &impl_wrap(cls, &spec, false)),
FnType::FnClass => impl_py_method_def_class(&spec, &impl_wrap_class(cls, &spec)),
FnType::FnStatic => impl_py_method_def_static(&spec, &impl_wrap_static(cls, &spec)),
FnType::Getter => impl_py_getter_def(&spec, &impl_wrap_getter(cls, &spec)?),
FnType::Setter => impl_py_setter_def(&spec, &impl_wrap_setter(cls, &spec)?),
})
2017-05-18 07:05:49 +00:00
}
fn check_generic(sig: &syn::Signature) -> syn::Result<()> {
let err_msg = |typ| format!("A Python method can't have a generic {} parameter", typ);
2019-08-11 12:16:02 +00:00
for param in &sig.generics.params {
2019-04-24 06:58:26 +00:00
match param {
syn::GenericParam::Lifetime(_) => {}
syn::GenericParam::Type(_) => {
return Err(syn::Error::new_spanned(param, err_msg("type")));
}
syn::GenericParam::Const(_) => {
return Err(syn::Error::new_spanned(param, err_msg("const")));
}
2019-04-24 06:58:26 +00:00
}
2017-05-16 05:24:06 +00:00
}
Ok(())
2017-05-16 05:24:06 +00:00
}
2017-05-20 06:14:59 +00:00
/// Generate function wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap(cls: &syn::Type, spec: &FnSpec<'_>, noargs: bool) -> TokenStream {
let body = impl_call(cls, &spec);
let slf = impl_self(&quote! { &mut #cls });
impl_wrap_common(cls, spec, noargs, slf, body)
}
pub fn impl_wrap_pyslf(
cls: &syn::Type,
spec: &FnSpec<'_>,
self_ty: &syn::TypePath,
noargs: bool,
) -> TokenStream {
let names = get_arg_names(spec);
let name = &spec.name;
let body = quote! {
#cls::#name(_slf, #(#names),*)
};
let slf = impl_self(self_ty);
impl_wrap_common(cls, spec, noargs, slf, body)
}
2017-05-20 06:14:59 +00:00
fn impl_wrap_common(
cls: &syn::Type,
spec: &FnSpec<'_>,
noargs: bool,
slf: TokenStream,
body: TokenStream,
) -> TokenStream {
let py_name = spec.py_name();
if spec.args.is_empty() && noargs {
quote! {
2017-07-23 17:07:23 +00:00
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject
) -> *mut pyo3::ffi::PyObject
{
2017-07-20 21:21:57 +00:00
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#py_name), "()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
#slf
let _result = {
pyo3::derive_utils::IntoPyResult::into_py_result(#body)
};
pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
}
}
} else {
let body = impl_arg_params(&spec, body);
2017-05-20 06:14:59 +00:00
quote! {
2017-07-23 17:07:23 +00:00
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-07-20 21:21:57 +00:00
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#py_name), "()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
2017-07-20 21:21:57 +00:00
#body
pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _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: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let py_name = spec.py_name();
let cb = impl_call(cls, &spec);
2017-05-25 05:43:07 +00:00
let body = impl_arg_params(&spec, cb);
quote! {
#[allow(unused_mut)]
2017-07-23 17:07:23 +00:00
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!(#py_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
2017-07-20 21:21:57 +00:00
#body
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
2017-06-08 18:29:40 +00:00
/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let name = &spec.name;
let py_name = spec.py_name();
let names: Vec<syn::Ident> = get_arg_names(&spec);
let cb = quote! { #cls::#name(&_obj, #(#names),*) };
2017-06-08 18:29:40 +00:00
2017-05-20 06:14:59 +00:00
let body = impl_arg_params(spec, cb);
2017-05-16 05:24:06 +00:00
quote! {
#[allow(unused_mut)]
2017-07-23 17:07:23 +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
{
use pyo3::type_object::PyTypeInfo;
2017-08-08 07:27:33 +00:00
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#py_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
match pyo3::type_object::PyRawObject::new(_py, #cls::type_object(), _cls) {
2017-08-08 07:27:33 +00:00
Ok(_obj) => {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
2017-08-08 07:27:33 +00:00
#body
2017-08-08 07:27:33 +00:00
match _result {
Ok(_) => pyo3::IntoPyPointer::into_ptr(_obj),
2017-08-08 07:27:33 +00:00
Err(e) => {
2017-08-08 07:58:12 +00:00
e.restore(_py);
2018-07-03 19:11:56 +00:00
::std::ptr::null_mut()
2017-08-08 07:27:33 +00:00
}
}
}
Err(e) => {
2017-08-08 07:58:12 +00:00
e.restore(_py);
2018-07-03 19:11:56 +00:00
::std::ptr::null_mut()
2017-08-08 07:27:33 +00:00
}
}
2017-05-16 05:24:06 +00:00
}
}
}
2017-06-08 18:29:40 +00:00
/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let name = &spec.name;
let py_name = spec.py_name();
let names: Vec<syn::Ident> = get_arg_names(&spec);
let cb = quote! { #cls::#name(&_cls, #(#names),*) };
2017-06-08 18:29:40 +00:00
let body = impl_arg_params(spec, cb);
quote! {
#[allow(unused_mut)]
2017-07-23 17:07:23 +00:00
unsafe extern "C" fn __wrap(
_cls: *mut pyo3::ffi::PyObject,
_args: *mut pyo3::ffi::PyObject,
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
2017-06-08 18:29:40 +00:00
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#py_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
2017-07-20 21:21:57 +00:00
#body
pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
2017-06-08 18:29:40 +00:00
}
}
}
/// Generate static method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let name = &spec.name;
let py_name = spec.py_name();
let names: Vec<syn::Ident> = get_arg_names(&spec);
let cb = quote! { #cls::#name(#(#names),*) };
2017-06-08 18:29:40 +00:00
let body = impl_arg_params(spec, cb);
quote! {
#[allow(unused_mut)]
2017-07-23 17:07:23 +00:00
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-06-08 18:29:40 +00:00
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#py_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
2017-06-08 18:29:40 +00:00
#body
pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
2017-06-08 18:29:40 +00:00
}
}
}
2017-05-16 18:58:18 +00:00
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords)
pub(crate) fn impl_wrap_getter(cls: &syn::Type, spec: &FnSpec) -> syn::Result<TokenStream> {
let takes_py = match &*spec.args {
[] => false,
[arg] if utils::if_type_is_python(arg.ty) => true,
_ => {
return Err(syn::Error::new_spanned(
spec.args[0].ty,
"Getter function can only have one argument of type pyo3::Python!",
));
}
};
let name = &spec.name;
let py_name = spec.py_name();
let fncall = if takes_py {
quote! { _slf.#name(_py) }
} else {
quote! { _slf.#name() }
};
Ok(quote! {
2017-07-23 17:07:23 +00:00
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> *mut pyo3::ffi::PyObject
2017-05-16 18:58:18 +00:00
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#py_name),"()");
2017-07-20 21:21:57 +00:00
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
2017-07-20 21:21:57 +00:00
let result = pyo3::derive_utils::IntoPyResult::into_py_result(#fncall);
match result {
2017-07-20 21:21:57 +00:00
Ok(val) => {
pyo3::IntoPyPointer::into_ptr(pyo3::IntoPy::<PyObject>::into_py(val, _py))
2017-07-20 21:21:57 +00:00
}
Err(e) => {
2017-07-23 17:07:23 +00:00
e.restore(_py);
2018-07-03 19:11:56 +00:00
::std::ptr::null_mut()
2017-07-20 21:21:57 +00:00
}
}
2017-05-16 18:58:18 +00:00
}
})
2017-05-16 18:58:18 +00:00
}
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords)
pub(crate) fn impl_wrap_setter(cls: &syn::Type, spec: &FnSpec<'_>) -> syn::Result<TokenStream> {
let name = &spec.name;
let py_name = spec.py_name();
let val_ty = match &*spec.args {
[] => {
return Err(syn::Error::new_spanned(
&spec.name,
"Not enough arguments for setter {}::{}",
))
}
[arg] => &arg.ty,
_ => {
return Err(syn::Error::new_spanned(
spec.args[0].ty,
"Setter function must have exactly one argument",
))
}
};
Ok(quote! {
#[allow(unused_mut)]
2017-07-23 17:07:23 +00:00
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject,
_value: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> pyo3::libc::c_int
2017-05-16 18:58:18 +00:00
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#py_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _value = _py.from_borrowed_ptr(_value);
2017-07-20 21:21:57 +00:00
let _result = match <#val_ty as pyo3::FromPyObject>::extract(_value) {
Ok(_val) => {
pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_val))
}
2017-07-20 21:21:57 +00:00
Err(e) => Err(e)
};
2017-07-23 17:07:23 +00:00
match _result {
2017-07-20 21:21:57 +00:00
Ok(_) => 0,
Err(e) => {
2017-07-23 17:07:23 +00:00
e.restore(_py);
2017-07-20 21:21:57 +00:00
-1
2017-05-25 05:43:07 +00:00
}
2017-07-20 21:21:57 +00:00
}
2017-05-16 18:58:18 +00:00
}
})
2017-05-16 18:58:18 +00:00
}
/// This function abstracts away some copied code and can propably be simplified itself
pub fn get_arg_names(spec: &FnSpec) -> Vec<syn::Ident> {
(0..spec.args.len())
.map(|pos| syn::Ident::new(&format!("arg{}", pos), Span::call_site()))
.collect()
}
fn impl_call(_cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
let fname = &spec.name;
let names = get_arg_names(spec);
quote! { _slf.#fname(#(#names),*) }
}
fn impl_self<T: quote::ToTokens>(self_ty: &T) -> TokenStream {
quote! {
let _slf: #self_ty = pyo3::FromPyPointer::from_borrowed_ptr(_py, _slf);
}
}
/// Converts a bool to "true" or "false"
fn bool_to_ident(condition: bool) -> syn::Ident {
if condition {
syn::Ident::new("true", Span::call_site())
} else {
syn::Ident::new("false", Span::call_site())
}
2017-05-16 05:24:06 +00:00
}
2019-02-01 13:01:18 +00:00
pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream {
if spec.args.is_empty() {
return quote! {
let _result = {
pyo3::derive_utils::IntoPyResult::into_py_result(#body)
};
};
2017-05-25 05:43:07 +00:00
}
2017-06-18 15:00:27 +00:00
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 arg.py || spec.is_args(&arg.name) || spec.is_kwargs(&arg.name) {
2018-07-03 20:28:40 +00:00
continue;
}
let name = arg.name;
let kwonly = bool_to_ident(spec.is_kw_only(&arg.name));
let opt = bool_to_ident(arg.optional.is_some() || spec.default_value(&arg.name).is_some());
params.push(quote! {
pyo3::derive_utils::ParamDescription {
name: stringify!(#name),
is_optional: #opt,
kw_only: #kwonly
}
});
2017-05-16 05:24:06 +00:00
}
let mut param_conversion = Vec::new();
let mut option_pos = 0;
for (idx, arg) in spec.args.iter().enumerate() {
param_conversion.push(impl_arg_param(&arg, &spec, idx, &mut option_pos));
2017-05-16 05:24:06 +00:00
}
let accept_args = bool_to_ident(spec.accept_args());
let accept_kwargs = bool_to_ident(spec.accept_kwargs());
let num_normal_params = params.len();
2017-05-16 05:24:06 +00:00
// create array of arguments, and then parse
quote! {
use pyo3::ObjectProtocol;
const PARAMS: &'static [pyo3::derive_utils::ParamDescription] = &[
2017-05-16 05:24:06 +00:00
#(#params),*
];
let mut output = [None; #num_normal_params];
let mut _args = _args;
let mut _kwargs = _kwargs;
2017-05-16 05:24:06 +00:00
// Workaround to use the question mark operator without rewriting everything
let _result = (|| {
let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args(
Some(_LOCATION),
PARAMS,
_args,
_kwargs,
#accept_args,
#accept_kwargs,
&mut output
)?;
#(#param_conversion)*
pyo3::derive_utils::IntoPyResult::into_py_result(#body)
})();
2017-05-16 05:24:06 +00:00
}
}
/// Re option_pos: The option slice doesn't contain the py: Python argument, so the argument
/// index and the index in option diverge when using py: Python
2019-02-01 13:01:18 +00:00
fn impl_arg_param(
arg: &FnArg<'_>,
spec: &FnSpec<'_>,
idx: usize,
option_pos: &mut usize,
2019-02-01 13:01:18 +00:00
) -> TokenStream {
let arg_name = syn::Ident::new(&format!("arg{}", idx), Span::call_site());
if arg.py {
return quote! {
let #arg_name = _py;
};
}
2017-05-16 05:24:06 +00:00
let ty = arg.ty;
let name = arg.name;
2017-05-20 06:14:59 +00:00
if spec.is_args(&name) {
return quote! {
let #arg_name = <#ty as pyo3::FromPyObject>::extract(_args.as_ref())?;
};
} else if spec.is_kwargs(&name) {
return quote! {
2017-07-23 17:07:23 +00:00
let #arg_name = _kwargs;
};
}
let arg_value = quote!(output[#option_pos]);
*option_pos += 1;
if arg.optional.is_some() {
let default = if let Some(d) = spec.default_value(name) {
if d.to_string() == "None" {
quote! { None }
} else {
quote! { Some(#d) }
}
} else {
quote! { None }
};
quote! {
let #arg_name = match #arg_value.as_ref() {
Some(_obj) => {
if _obj.is_none() {
#default
} else {
Some(_obj.extract()?)
2018-05-14 20:44:30 +00:00
}
},
None => #default
};
}
} else if let Some(default) = spec.default_value(name) {
quote! {
let #arg_name = match #arg_value.as_ref() {
Some(_obj) => {
if _obj.is_none() {
#default
} else {
_obj.extract()?
}
},
None => #default
};
}
} else {
quote! {
let #arg_name = #arg_value.unwrap().extract()?;
2017-05-18 07:05:49 +00:00
}
}
}
pub fn impl_py_method_def(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = spec.py_name();
let doc = &spec.doc;
if spec.args.is_empty() {
quote! {
pyo3::class::PyMethodDefType::Method({
#wrapper
pyo3::class::PyMethodDef {
ml_name: stringify!(#py_name),
ml_meth: pyo3::class::PyMethodType::PyNoArgsFunction(__wrap),
ml_flags: pyo3::ffi::METH_NOARGS,
2017-06-13 04:08:59 +00:00
ml_doc: #doc,
}
})
}
} else {
quote! {
pyo3::class::PyMethodDefType::Method({
#wrapper
pyo3::class::PyMethodDef {
ml_name: stringify!(#py_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
2017-06-13 04:08:59 +00:00
ml_doc: #doc,
}
})
}
2017-05-18 07:05:49 +00:00
}
}
pub fn impl_py_method_def_new(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = spec.py_name();
let doc = &spec.doc;
2017-05-20 06:14:59 +00:00
quote! {
pyo3::class::PyMethodDefType::New({
2017-05-20 06:14:59 +00:00
#wrapper
2017-05-18 07:05:49 +00:00
pyo3::class::PyMethodDef {
ml_name: stringify!(#py_name),
ml_meth: pyo3::class::PyMethodType::PyNewFunc(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
2017-06-13 04:08:59 +00:00
ml_doc: #doc,
2017-05-20 06:14:59 +00:00
}
})
2017-05-18 07:05:49 +00:00
}
2017-05-16 05:24:06 +00:00
}
pub fn impl_py_method_def_class(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = spec.py_name();
let doc = &spec.doc;
2017-06-08 18:29:40 +00:00
quote! {
pyo3::class::PyMethodDefType::Class({
2017-06-08 18:29:40 +00:00
#wrapper
pyo3::class::PyMethodDef {
ml_name: stringify!(#py_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS |
pyo3::ffi::METH_CLASS,
2017-06-13 04:08:59 +00:00
ml_doc: #doc,
2017-06-08 18:29:40 +00:00
}
})
}
}
pub fn impl_py_method_def_static(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = spec.py_name();
let doc = &spec.doc;
2017-06-08 18:29:40 +00:00
quote! {
pyo3::class::PyMethodDefType::Static({
2017-06-08 18:29:40 +00:00
#wrapper
pyo3::class::PyMethodDef {
ml_name: stringify!(#py_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | pyo3::ffi::METH_STATIC,
2017-06-13 04:08:59 +00:00
ml_doc: #doc,
2017-06-08 18:29:40 +00:00
}
})
}
}
pub fn impl_py_method_def_call(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = spec.py_name();
let doc = &spec.doc;
2017-05-16 18:58:18 +00:00
quote! {
pyo3::class::PyMethodDefType::Call({
2017-05-16 18:58:18 +00:00
#wrapper
pyo3::class::PyMethodDef {
ml_name: stringify!(#py_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
2017-06-13 04:08:59 +00:00
ml_doc: #doc,
2017-05-16 18:58:18 +00:00
}
})
}
}
pub(crate) fn impl_py_setter_def(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = &spec.py_name();
let doc = &spec.doc;
2017-05-16 18:58:18 +00:00
quote! {
pyo3::class::PyMethodDefType::Setter({
2017-05-16 18:58:18 +00:00
#wrapper
pyo3::class::PySetterDef {
name: stringify!(#py_name),
2017-07-23 17:07:23 +00:00
meth: __wrap,
2017-06-13 04:08:59 +00:00
doc: #doc,
2017-05-16 18:58:18 +00:00
}
})
}
}
pub(crate) fn impl_py_getter_def(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
let py_name = &spec.py_name();
let doc = &spec.doc;
2017-05-16 18:58:18 +00:00
quote! {
pyo3::class::PyMethodDefType::Getter({
2017-05-16 18:58:18 +00:00
#wrapper
pyo3::class::PyGetterDef {
name: stringify!(#py_name),
2017-07-23 17:07:23 +00:00
meth: __wrap,
2017-06-13 04:08:59 +00:00
doc: #doc,
2017-05-16 18:58:18 +00:00
}
})
}
2017-05-16 05:24:06 +00:00
}