Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEED DISCUSSION] Remove #[init] attribute #658

Merged
merged 3 commits into from
Nov 9, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions pyo3-derive-backend/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub enum FnType {
Setter(Option<String>),
Fn,
FnNew,
FnInit,
FnCall,
FnClass,
FnStatic,
Expand Down Expand Up @@ -291,7 +290,10 @@ fn parse_attributes(attrs: &mut Vec<syn::Attribute>) -> syn::Result<(FnType, Vec
if name.is_ident("new") || name.is_ident("__new__") {
res = Some(FnType::FnNew)
} else if name.is_ident("init") || name.is_ident("__init__") {
res = Some(FnType::FnInit)
return Err(syn::Error::new_spanned(
name,
"#[init] is duplicated from PyO3 0.9.0!",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be #[init] is removed from PyO3 0.9.0!? Since #[init] was never working I think we don't have to return an error.

))
} else if name.is_ident("call") || name.is_ident("__call__") {
res = Some(FnType::FnCall)
} else if name.is_ident("classmethod") {
Expand Down Expand Up @@ -322,7 +324,10 @@ fn parse_attributes(attrs: &mut Vec<syn::Attribute>) -> syn::Result<(FnType, Vec
if path.is_ident("new") {
res = Some(FnType::FnNew)
} else if path.is_ident("init") {
res = Some(FnType::FnInit)
return Err(syn::Error::new_spanned(
path,
"#[init] is duplicated from PyO3 0.9.0!",
))
} else if path.is_ident("call") {
res = Some(FnType::FnCall)
} else if path.is_ident("setter") || path.is_ident("getter") {
Expand Down
59 changes: 0 additions & 59 deletions pyo3-derive-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub fn gen_py_method(
&impl_wrap_pyslf(cls, name, &spec, self_ty, true),
),
FnType::FnNew => impl_py_method_def_new(name, doc, &impl_wrap_new(cls, name, &spec)),
FnType::FnInit => impl_py_method_def_init(name, doc, &impl_wrap_init(cls, name, &spec)),
FnType::FnCall => impl_py_method_def_call(name, doc, &impl_wrap(cls, name, &spec, false)),
FnType::FnClass => impl_py_method_def_class(name, doc, &impl_wrap_class(cls, name, &spec)),
FnType::FnStatic => {
Expand Down Expand Up @@ -220,45 +219,6 @@ pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> T
}
}

/// Generate function wrapper for ffi::initproc
fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let cb = impl_call(cls, name, &spec);
let output = &spec.output;
let result_empty: syn::Type = syn::parse_quote!(PyResult<()>);
let empty: syn::Type = syn::parse_quote!(());
if output != &result_empty || output != &empty {
panic!("Constructor must return PyResult<()> or a ()");
}

let body = impl_arg_params(&spec, cb);

quote! {
#[allow(unused_mut)]
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject,
_args: *mut pyo3::ffi::PyObject,
_kwargs: *mut pyo3::ffi::PyObject) -> pyo3::libc::c_int
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#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);

#body

match _result {
Ok(_) => 0,
Err(e) => {
e.restore(_py);
-1
}
}
}
}
}

/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let names: Vec<syn::Ident> = get_arg_names(&spec);
Expand Down Expand Up @@ -612,25 +572,6 @@ pub fn impl_py_method_def_new(
}
}

pub fn impl_py_method_def_init(
name: &syn::Ident,
doc: syn::Lit,
wrapper: &TokenStream,
) -> TokenStream {
quote! {
pyo3::class::PyMethodDefType::Init({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#name),
ml_meth: pyo3::class::PyMethodType::PyInitFunc(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
ml_doc: #doc,
}
})
}
}

pub fn impl_py_method_def_class(
name: &syn::Ident,
doc: syn::Lit,
Expand Down
2 changes: 0 additions & 2 deletions src/class/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use std::ffi::CString;
pub enum PyMethodDefType {
/// Represents class `__new__` method
New(PyMethodDef),
/// Represents class `__init__` method
Init(PyMethodDef),
/// Represents class `__call__` method
Call(PyMethodDef),
/// Represents class method
Expand Down
22 changes: 2 additions & 20 deletions src/type_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,23 +372,14 @@ where
type_object.tp_as_buffer = to_ptr(<T as class::buffer::PyBufferProtocolImpl>::tp_as_buffer());

// normal methods
let (new, init, call, mut methods) = py_class_method_defs::<T>();
let (new, call, mut methods) = py_class_method_defs::<T>();
if !methods.is_empty() {
methods.push(ffi::PyMethodDef_INIT);
type_object.tp_methods = Box::into_raw(methods.into_boxed_slice()) as *mut _;
}

if let (None, Some(_)) = (new, init) {
panic!(
"{}.__new__ method is required if __init__ method defined",
T::NAME
);
}

// __new__ method
type_object.tp_new = new;
// __init__ method
type_object.tp_init = init;
// __call__ method
type_object.tp_call = call;

Expand Down Expand Up @@ -440,14 +431,12 @@ fn py_class_flags<T: PyTypeInfo>(type_object: &mut ffi::PyTypeObject) {

fn py_class_method_defs<T: PyMethodsProtocol>() -> (
Option<ffi::newfunc>,
Option<ffi::initproc>,
Option<ffi::PyCFunctionWithKeywords>,
Vec<ffi::PyMethodDef>,
) {
let mut defs = Vec::new();
let mut call = None;
let mut new = None;
let mut init = None;

for def in T::py_methods() {
match *def {
Expand All @@ -463,13 +452,6 @@ fn py_class_method_defs<T: PyMethodsProtocol>() -> (
panic!("Method type is not supoorted by tp_call slot")
}
}
PyMethodDefType::Init(ref def) => {
if let class::methods::PyMethodType::PyInitFunc(meth) = def.ml_meth {
init = Some(meth)
} else {
panic!("Method type is not supoorted by tp_init slot")
}
}
PyMethodDefType::Method(ref def)
| PyMethodDefType::Class(ref def)
| PyMethodDefType::Static(ref def) => {
Expand Down Expand Up @@ -497,7 +479,7 @@ fn py_class_method_defs<T: PyMethodsProtocol>() -> (

py_class_async_methods::<T>(&mut defs);

(new, init, call, defs)
(new, call, defs)
}

fn py_class_async_methods<T>(defs: &mut Vec<ffi::PyMethodDef>) {
Expand Down