fix #[prop] impl

This commit is contained in:
Nikolay Kim 2017-08-07 23:52:24 -07:00
parent 59d9f9e453
commit 3b00145040
5 changed files with 33 additions and 9 deletions

View File

@ -348,7 +348,7 @@ fn impl_descriptors(cls: &syn::Ty, descriptors: Vec<(syn::Field, Vec<FnType>)>)
let tokens = quote! { let tokens = quote! {
#(#methods)* #(#methods)*
impl _pyo3::class::methods::PyMethodsProtocolImpl for #cls { impl _pyo3::class::methods::PyPropMethodsProtocolImpl for #cls {
fn py_methods() -> &'static [_pyo3::class::PyMethodDefType] { fn py_methods() -> &'static [_pyo3::class::PyMethodDefType] {
static METHODS: &'static [_pyo3::class::PyMethodDefType] = &[ static METHODS: &'static [_pyo3::class::PyMethodDefType] = &[
#(#py_methods),* #(#py_methods),*

View File

@ -9,6 +9,7 @@ static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
/// `PyMethodDefType` represents different types of python callable objects. /// `PyMethodDefType` represents different types of python callable objects.
/// It is used by `#[py::methods]` and `#[py::proto]` annotations. /// It is used by `#[py::methods]` and `#[py::proto]` annotations.
#[derive(Debug)]
pub enum PyMethodDefType { pub enum PyMethodDefType {
/// Represents class `__new__` method /// Represents class `__new__` method
New(PyMethodDef), New(PyMethodDef),
@ -28,7 +29,7 @@ pub enum PyMethodDefType {
Setter(PySetterDef), Setter(PySetterDef),
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub enum PyMethodType { pub enum PyMethodType {
PyCFunction(ffi::PyCFunction), PyCFunction(ffi::PyCFunction),
PyCFunctionWithKeywords(ffi::PyCFunctionWithKeywords), PyCFunctionWithKeywords(ffi::PyCFunctionWithKeywords),
@ -37,7 +38,7 @@ pub enum PyMethodType {
PyInitFunc(ffi::initproc), PyInitFunc(ffi::initproc),
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub struct PyMethodDef { pub struct PyMethodDef {
pub ml_name: &'static str, pub ml_name: &'static str,
pub ml_meth: PyMethodType, pub ml_meth: PyMethodType,
@ -45,14 +46,14 @@ pub struct PyMethodDef {
pub ml_doc: &'static str, pub ml_doc: &'static str,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub struct PyGetterDef { pub struct PyGetterDef {
pub name: &'static str, pub name: &'static str,
pub meth: ffi::getter, pub meth: ffi::getter,
pub doc: &'static str, pub doc: &'static str,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub struct PySetterDef { pub struct PySetterDef {
pub name: &'static str, pub name: &'static str,
pub meth: ffi::setter, pub meth: ffi::setter,
@ -133,3 +134,14 @@ impl<T> PyMethodsProtocolImpl for T {
NO_PY_METHODS NO_PY_METHODS
} }
} }
#[doc(hidden)]
pub trait PyPropMethodsProtocolImpl {
fn py_methods() -> &'static [PyMethodDefType];
}
impl<T> PyPropMethodsProtocolImpl for T {
default fn py_methods() -> &'static [PyMethodDefType] {
NO_PY_METHODS
}
}

View File

@ -291,6 +291,8 @@ mod test {
#[test] #[test]
fn test_owned_nested() { fn test_owned_nested() {
pythonrun::prepare_pyo3_library(); pythonrun::prepare_pyo3_library();
let gil = Python::acquire_gil();
let py = gil.python();
unsafe { unsafe {
let p: &'static mut ReleasePool = &mut *POOL; let p: &'static mut ReleasePool = &mut *POOL;
@ -298,8 +300,7 @@ mod test {
let cnt; let cnt;
let empty; let empty;
{ {
let gil = Python::acquire_gil(); let _pool = GILPool::new();
let py = gil.python();
assert_eq!(p.owned.len(), 0); assert_eq!(p.owned.len(), 0);
// empty tuple is singleton // empty tuple is singleton
@ -318,7 +319,6 @@ mod test {
assert_eq!(p.owned.len(), 1); assert_eq!(p.owned.len(), 1);
} }
{ {
let _gil = Python::acquire_gil();
assert_eq!(p.owned.len(), 0); assert_eq!(p.owned.len(), 0);
assert_eq!(cnt, ffi::Py_REFCNT(empty)); assert_eq!(cnt, ffi::Py_REFCNT(empty));
} }

View File

@ -390,6 +390,8 @@ fn py_class_method_defs<T>() -> PyResult<(Option<ffi::newfunc>,
let mut new = None; let mut new = None;
let mut init = None; let mut init = None;
//<T as class::methods::PyPropMethodsProtocolImpl>::py_methods()
for def in <T as class::methods::PyMethodsProtocolImpl>::py_methods() { for def in <T as class::methods::PyMethodsProtocolImpl>::py_methods() {
match *def { match *def {
PyMethodDefType::New(ref def) => { PyMethodDefType::New(ref def) => {
@ -458,7 +460,9 @@ fn py_class_async_methods<T>(_defs: &mut Vec<ffi::PyMethodDef>) {}
fn py_class_properties<T>() -> Vec<ffi::PyGetSetDef> { fn py_class_properties<T>() -> Vec<ffi::PyGetSetDef> {
let mut defs = HashMap::new(); let mut defs = HashMap::new();
for def in <T as class::methods::PyMethodsProtocolImpl>::py_methods() { for def in <T as class::methods::PyMethodsProtocolImpl>::py_methods()
.iter().chain(<T as class::methods::PyPropMethodsProtocolImpl>::py_methods().iter())
{
match *def { match *def {
PyMethodDefType::Getter(ref getter) => { PyMethodDefType::Getter(ref getter) => {
let name = getter.name.to_string(); let name = getter.name.to_string();

View File

@ -1288,6 +1288,14 @@ struct GetterSetter {
token: PyToken token: PyToken
} }
#[py::methods]
impl GetterSetter {
fn get_num2(&self) -> PyResult<i32> {
Ok(self.num)
}
}
#[test] #[test]
fn getter_setter_autogen() { fn getter_setter_autogen() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();