Skip to content

Commit

Permalink
Merge pull request #658 from kngwyu/remove-init
Browse files Browse the repository at this point in the history
[NEED DISCUSSION] Remove #[init] attribute
  • Loading branch information
kngwyu committed Nov 9, 2019
2 parents 72debed + 3eff3ca commit 99f9b36
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 85 deletions.
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ print(json.dumps({
serde_json::from_str(&json).map_err(|e| format!("Deserializing failed: {}", e))
}

fn configure(interpreter_config: &InterpreterConfig) -> Result<(String), String> {
fn configure(interpreter_config: &InterpreterConfig) -> Result<String, String> {
if let Some(minor) = interpreter_config.version.minor {
if minor < PY3_MIN_MINOR {
return Err(format!(
Expand Down
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 disabled from PyO3 0.9.0",
));
} 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 disabled 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

0 comments on commit 99f9b36

Please sign in to comment.