Skip to content

Commit ced2423

Browse files
committed
IntoPyGetterFunc, IntoPySetterFunc
1 parent 9f4d0bc commit ced2423

File tree

4 files changed

+71
-33
lines changed

4 files changed

+71
-33
lines changed

derive/src/pyclass.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,16 +445,16 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
445445
return TokenStream2::new();
446446
}
447447
};
448-
let setter = match data.1 {
449-
Some(func) => quote! { Some(&Self::#func) },
450-
None => quote! { None },
448+
let (new, setter) = match data.1 {
449+
Some(func) => (quote! { with_get_set }, quote! { , &Self::#func }),
450+
None => (quote! {with_get} , quote! { }),
451451
};
452452
let str_name = name.to_string();
453453
quote! {
454454
class.set_str_attr(
455455
#name,
456456
::rustpython_vm::pyobject::PyObject::new(
457-
::rustpython_vm::obj::objgetset::PyGetSet::new(#str_name.into(), Some(&Self::#getter_func), #setter),
457+
::rustpython_vm::obj::objgetset::PyGetSet::#new(#str_name.into(), &Self::#getter_func #setter),
458458
ctx.getset_type(), None)
459459
)
460460
}

vm/src/exceptions.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,13 @@ impl PyBaseException {
6868
}
6969

7070
#[pydata(name = "args")]
71-
fn get_args(zelf: PyObjectRef, _vm: &VirtualMachine) -> PyResult {
72-
let zelf = zelf.payload::<PyBaseException>().unwrap();
73-
Ok(zelf.args.borrow().clone().into_object())
71+
fn get_args(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyTupleRef {
72+
zelf.args.borrow().clone()
7473
}
7574

7675
#[pydata(setter)]
77-
fn set_args(zelf: PyObjectRef, args: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
78-
let zelf = PyBaseExceptionRef::try_from_object(vm, zelf)?;
79-
let args = PyIterable::try_from_object(vm, args)?
80-
.iter(vm)?
81-
.collect::<PyResult<Vec<_>>>()?;
76+
fn set_args(zelf: PyRef<Self>, args: PyIterable, vm: &VirtualMachine) -> PyResult<()> {
77+
let args = args.iter(vm)?.collect::<PyResult<Vec<_>>>()?;
8278
zelf.args.replace(PyTuple::from(args).into_ref(vm));
8379
Ok(())
8480
}

vm/src/obj/objgetset.rs

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,57 @@
33
*/
44
use super::objtype::PyClassRef;
55
use crate::function::OptionalArg;
6-
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
6+
use crate::pyobject::{
7+
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
8+
};
79
use crate::slots::PyBuiltinDescriptor;
810
use crate::vm::VirtualMachine;
911

10-
pub type PyGetterFunc = dyn Fn(PyObjectRef, &VirtualMachine) -> PyResult;
11-
pub type PySetterFunc = dyn Fn(PyObjectRef, PyObjectRef, &VirtualMachine) -> PyResult<()>;
12+
pub type PyGetterFunc = Box<dyn Fn(PyObjectRef, &VirtualMachine) -> PyResult>;
13+
pub type PySetterFunc = Box<dyn Fn(PyObjectRef, PyObjectRef, &VirtualMachine) -> PyResult<()>>;
14+
15+
pub trait IntoPyGetterFunc<T, R> {
16+
fn into_getter(self) -> PyGetterFunc;
17+
}
18+
19+
impl<F, T, R> IntoPyGetterFunc<T, R> for F
20+
where
21+
F: Fn(T, &VirtualMachine) -> R + 'static,
22+
T: TryFromObject,
23+
R: IntoPyObject,
24+
{
25+
fn into_getter(self) -> PyGetterFunc {
26+
Box::new(move |obj, vm| {
27+
let obj = T::try_from_object(vm, obj)?;
28+
(self)(obj, vm).into_pyobject(vm)
29+
})
30+
}
31+
}
32+
33+
pub trait IntoPySetterFunc<T, V> {
34+
fn into_setter(self) -> PySetterFunc;
35+
}
36+
37+
impl<F, T, V> IntoPySetterFunc<T, V> for F
38+
where
39+
F: Fn(T, V, &VirtualMachine) -> PyResult<()> + 'static,
40+
T: TryFromObject,
41+
V: TryFromObject,
42+
{
43+
fn into_setter(self) -> PySetterFunc {
44+
Box::new(move |obj, value, vm| {
45+
let obj = T::try_from_object(vm, obj)?;
46+
let value = V::try_from_object(vm, value)?;
47+
(self)(obj, value, vm)
48+
})
49+
}
50+
}
1251

1352
#[pyclass]
1453
pub struct PyGetSet {
1554
name: String,
16-
getter: Option<Box<PyGetterFunc>>,
17-
setter: Option<Box<PySetterFunc>>,
55+
getter: Option<PyGetterFunc>,
56+
setter: Option<PySetterFunc>,
1857
// doc: Option<String>,
1958
}
2059

@@ -66,23 +105,26 @@ impl PyBuiltinDescriptor for PyGetSet {
66105
}
67106

68107
impl PyGetSet {
69-
pub fn new(
70-
name: String,
71-
getter: Option<&'static PyGetterFunc>,
72-
setter: Option<&'static PySetterFunc>,
73-
) -> Self {
108+
pub fn with_get<G, T, R>(name: String, getter: G) -> Self
109+
where
110+
G: IntoPyGetterFunc<T, R>,
111+
{
74112
Self {
75113
name,
76-
getter: if let Some(f) = getter {
77-
Some(Box::new(f))
78-
} else {
79-
None
80-
},
81-
setter: if let Some(f) = setter {
82-
Some(Box::new(f))
83-
} else {
84-
None
85-
},
114+
getter: Some(getter.into_getter()),
115+
setter: None,
116+
}
117+
}
118+
119+
pub fn with_get_set<G, S, GT, GR, ST, SV>(name: String, getter: G, setter: S) -> Self
120+
where
121+
G: IntoPyGetterFunc<GT, GR>,
122+
S: IntoPySetterFunc<ST, SV>,
123+
{
124+
Self {
125+
name,
126+
getter: Some(getter.into_getter()),
127+
setter: Some(setter.into_setter()),
86128
}
87129
}
88130
}

vm/src/obj/objobject.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ pub fn init(context: &PyContext) {
183183
"__new__" => context.new_classmethod(objtype::type_new),
184184
"__init__" => context.new_method(object_init),
185185
"__class__" => PyObject::new(
186-
PyGetSet::new("__class__".into(), Some(&object_class_getter), Some(&object_class_setter)),
186+
PyGetSet::with_get_set("__class__".into(), &object_class_getter, &object_class_setter),
187187
context.getset_type(), None),
188188
"__eq__" => context.new_method(object_eq),
189189
"__ne__" => context.new_method(object_ne),

0 commit comments

Comments
 (0)