Skip to content

Commit facabfe

Browse files
committed
Remove PropertyBuilder and add new_getset
1 parent 0aee78d commit facabfe

File tree

10 files changed

+86
-203
lines changed

10 files changed

+86
-203
lines changed

derive/src/pyclass.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,8 @@ pub fn impl_pystruct_sequence(attr: AttributeArgs, item: Item) -> Result<TokenSt
692692
let property = quote! {
693693
class.set_str_attr(
694694
#field_name_str,
695-
ctx.new_property(
695+
ctx.new_readonly_getset(
696+
#field_name_str,
696697
|zelf: &::rustpython_vm::obj::objtuple::PyTuple,
697698
_vm: &::rustpython_vm::VirtualMachine| {
698699
zelf.fast_getitem(#idx)

vm/src/exceptions.rs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -644,48 +644,44 @@ pub fn init(ctx: &PyContext) {
644644
PyBaseException::extend_class(ctx, &excs.base_exception_type);
645645

646646
extend_class!(ctx, &excs.syntax_error, {
647-
"msg" => ctx.new_property(make_arg_getter(0)),
648-
"filename" => ctx.new_property(make_arg_getter(1)),
649-
"lineno" => ctx.new_property(make_arg_getter(2)),
650-
"offset" => ctx.new_property(make_arg_getter(3)),
651-
"text" => ctx.new_property(make_arg_getter(4)),
647+
"msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)),
652648
});
653649

654650
extend_class!(ctx, &excs.import_error, {
655651
"__init__" => ctx.new_method(import_error_init),
656-
"msg" => ctx.new_property(make_arg_getter(0)),
652+
"msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)),
657653
});
658654

659655
extend_class!(ctx, &excs.stop_iteration, {
660-
"value" => ctx.new_property(make_arg_getter(0)),
656+
"value" => ctx.new_readonly_getset("value", make_arg_getter(0)),
661657
});
662658

663659
extend_class!(ctx, &excs.key_error, {
664660
"__str__" => ctx.new_method(key_error_str),
665661
});
666662

667663
extend_class!(ctx, &excs.unicode_decode_error, {
668-
"encoding" => ctx.new_property(make_arg_getter(0)),
669-
"object" => ctx.new_property(make_arg_getter(1)),
670-
"start" => ctx.new_property(make_arg_getter(2)),
671-
"end" => ctx.new_property(make_arg_getter(3)),
672-
"reason" => ctx.new_property(make_arg_getter(4)),
664+
"encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)),
665+
"object" => ctx.new_readonly_getset("object", make_arg_getter(1)),
666+
"start" => ctx.new_readonly_getset("start", make_arg_getter(2)),
667+
"end" => ctx.new_readonly_getset("end", make_arg_getter(3)),
668+
"reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)),
673669
});
674670

675671
extend_class!(ctx, &excs.unicode_encode_error, {
676-
"encoding" => ctx.new_property(make_arg_getter(0)),
677-
"object" => ctx.new_property(make_arg_getter(1)),
678-
"start" => ctx.new_property(make_arg_getter(2)),
679-
"end" => ctx.new_property(make_arg_getter(3)),
680-
"reason" => ctx.new_property(make_arg_getter(4)),
672+
"encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)),
673+
"object" => ctx.new_readonly_getset("object", make_arg_getter(1)),
674+
"start" => ctx.new_readonly_getset("start", make_arg_getter(2)),
675+
"end" => ctx.new_readonly_getset("end", make_arg_getter(3)),
676+
"reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)),
681677
});
682678

683679
extend_class!(ctx, &excs.unicode_translate_error, {
684-
"encoding" => ctx.new_property(none_getter),
685-
"object" => ctx.new_property(make_arg_getter(0)),
686-
"start" => ctx.new_property(make_arg_getter(1)),
687-
"end" => ctx.new_property(make_arg_getter(2)),
688-
"reason" => ctx.new_property(make_arg_getter(3)),
680+
"encoding" => ctx.new_readonly_getset("encoding", none_getter),
681+
"object" => ctx.new_readonly_getset("object", make_arg_getter(0)),
682+
"start" => ctx.new_readonly_getset("start", make_arg_getter(1)),
683+
"end" => ctx.new_readonly_getset("end", make_arg_getter(2)),
684+
"reason" => ctx.new_readonly_getset("reason", make_arg_getter(3)),
689685
});
690686
}
691687

vm/src/obj/objcode.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,17 @@ impl PyCodeRef {
9292
}
9393
}
9494

95-
pub fn init(context: &PyContext) {
96-
extend_class!(context, &context.types.code_type, {
95+
pub fn init(ctx: &PyContext) {
96+
extend_class!(ctx, &ctx.types.code_type, {
9797
(slot new) => PyCodeRef::new,
98-
"__repr__" => context.new_method(PyCodeRef::repr),
99-
100-
"co_argcount" => context.new_property(PyCodeRef::co_argcount),
101-
"co_consts" => context.new_property(PyCodeRef::co_consts),
102-
"co_filename" => context.new_property(PyCodeRef::co_filename),
103-
"co_firstlineno" => context.new_property(PyCodeRef::co_firstlineno),
104-
"co_kwonlyargcount" => context.new_property(PyCodeRef::co_kwonlyargcount),
105-
"co_name" => context.new_property(PyCodeRef::co_name),
106-
"co_flags" => context.new_property(PyCodeRef::co_flags),
98+
"__repr__" => ctx.new_method(PyCodeRef::repr),
99+
100+
"co_argcount" => ctx.new_readonly_getset("co_argcount", PyCodeRef::co_argcount),
101+
"co_consts" => ctx.new_readonly_getset("co_consts", PyCodeRef::co_consts),
102+
"co_filename" => ctx.new_readonly_getset("co_filename", PyCodeRef::co_filename),
103+
"co_firstlineno" => ctx.new_readonly_getset("co_firstlineno", PyCodeRef::co_firstlineno),
104+
"co_kwonlyargcount" => ctx.new_readonly_getset("co_kwonlyargcount", PyCodeRef::co_kwonlyargcount),
105+
"co_name" => ctx.new_readonly_getset("co_name", PyCodeRef::co_name),
106+
"co_flags" => ctx.new_readonly_getset("co_flags", PyCodeRef::co_flags),
107107
});
108108
}

vm/src/obj/objproperty.rs

Lines changed: 4 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,13 @@
44
use std::cell::RefCell;
55

66
use super::objtype::PyClassRef;
7-
use crate::function::{IntoPyNativeFunc, OptionalArg};
7+
use crate::function::OptionalArg;
88
use crate::pyobject::{
9-
IdProtocol, PyClassImpl, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
10-
TypeProtocol,
9+
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
1110
};
1211
use crate::slots::SlotDescriptor;
1312
use crate::vm::VirtualMachine;
1413

15-
// Read-only property, doesn't have __set__ or __delete__
16-
#[pyclass]
17-
#[derive(Debug)]
18-
pub struct PyReadOnlyProperty {
19-
getter: PyObjectRef,
20-
}
21-
22-
impl PyValue for PyReadOnlyProperty {
23-
fn class(vm: &VirtualMachine) -> PyClassRef {
24-
vm.ctx.readonly_property_type()
25-
}
26-
}
27-
28-
pub type PyReadOnlyPropertyRef = PyRef<PyReadOnlyProperty>;
29-
30-
impl SlotDescriptor for PyReadOnlyProperty {
31-
fn descr_get(
32-
vm: &VirtualMachine,
33-
zelf: PyObjectRef,
34-
obj: Option<PyObjectRef>,
35-
cls: OptionalArg<PyObjectRef>,
36-
) -> PyResult {
37-
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
38-
if vm.is_none(&obj) {
39-
if Self::_cls_is(&cls, &vm.ctx.types.type_type) {
40-
vm.invoke(&zelf.getter, cls.unwrap())
41-
} else {
42-
Ok(zelf.into_object())
43-
}
44-
} else {
45-
vm.invoke(&zelf.getter, obj)
46-
}
47-
}
48-
}
49-
50-
#[pyimpl(with(SlotDescriptor))]
51-
impl PyReadOnlyProperty {}
52-
5314
/// Property attribute.
5415
///
5516
/// fget
@@ -255,81 +216,12 @@ fn py_none_to_option(vm: &VirtualMachine, value: &PyObjectRef) -> Option<PyObjec
255216
}
256217
}
257218

258-
pub struct PropertyBuilder<'a> {
259-
ctx: &'a PyContext,
260-
getter: Option<PyObjectRef>,
261-
setter: Option<PyObjectRef>,
262-
}
263-
264-
impl<'a> PropertyBuilder<'a> {
265-
pub fn new(ctx: &'a PyContext) -> Self {
266-
Self {
267-
ctx,
268-
getter: None,
269-
setter: None,
270-
}
271-
}
272-
273-
pub fn add_getter<I, R, VM, F: IntoPyNativeFunc<I, R, VM>>(self, func: F) -> Self {
274-
let func = self.ctx.new_method(func);
275-
Self {
276-
ctx: self.ctx,
277-
getter: Some(func),
278-
setter: self.setter,
279-
}
280-
}
281-
282-
pub fn add_setter<
283-
I,
284-
V,
285-
VM,
286-
F: IntoPyNativeFunc<(I, V), impl super::objgetset::IntoPyNoResult, VM>,
287-
>(
288-
self,
289-
func: F,
290-
) -> Self {
291-
let func = self.ctx.new_method(func);
292-
Self {
293-
ctx: self.ctx,
294-
getter: self.getter,
295-
setter: Some(func),
296-
}
297-
}
298-
299-
pub fn create(self) -> PyObjectRef {
300-
if self.setter.is_some() {
301-
let payload = PyProperty {
302-
getter: self.getter.clone(),
303-
setter: self.setter.clone(),
304-
deleter: None,
305-
doc: RefCell::new(None),
306-
};
307-
308-
PyObject::new(payload, self.ctx.property_type(), None)
309-
} else {
310-
let payload = PyReadOnlyProperty {
311-
getter: self.getter.expect(
312-
"One of add_getter/add_setter must be called when constructing a property",
313-
),
314-
};
315-
316-
PyObject::new(payload, self.ctx.readonly_property_type(), None)
317-
}
318-
}
319-
}
320-
321-
pub fn init(context: &PyContext) {
322-
PyReadOnlyProperty::extend_class(context, &context.types.readonly_property_type);
323-
219+
pub(crate) fn init(context: &PyContext) {
324220
PyProperty::extend_class(context, &context.types.property_type);
325221

326222
// This is a bit unfortunate, but this instance attribute overlaps with the
327223
// class __doc__ string..
328224
extend_class!(context, &context.types.property_type, {
329-
"__doc__" =>
330-
PropertyBuilder::new(context)
331-
.add_getter(PyProperty::doc_getter)
332-
.add_setter(PyProperty::doc_setter)
333-
.create(),
225+
"__doc__" => context.new_getset("__doc__", PyProperty::doc_getter, PyProperty::doc_setter),
334226
});
335227
}

vm/src/obj/objtype.rs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::fmt;
55
use super::objdict::PyDictRef;
66
use super::objlist::PyList;
77
use super::objmappingproxy::PyMappingProxy;
8-
use super::objproperty::PropertyBuilder;
98
use super::objstr::PyStringRef;
109
use super::objtuple::PyTuple;
1110
use super::objweakref::PyWeak;
@@ -80,16 +79,13 @@ impl PyClassRef {
8079
}
8180
}
8281

83-
fn _mro(self, _vm: &VirtualMachine) -> PyTuple {
82+
#[pyproperty(name = "__mro__")]
83+
fn get_mro(self, _vm: &VirtualMachine) -> PyTuple {
8484
let elements: Vec<PyObjectRef> =
8585
_mro(&self).iter().map(|x| x.as_object().clone()).collect();
8686
PyTuple::from(elements)
8787
}
8888

89-
fn _set_mro(self, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
90-
Err(vm.new_attribute_error("read-only attribute".to_owned()))
91-
}
92-
9389
#[pyproperty(magic)]
9490
fn bases(self, vm: &VirtualMachine) -> PyObjectRef {
9591
vm.ctx
@@ -338,6 +334,18 @@ impl PyClassRef {
338334
}
339335
Ok(obj)
340336
}
337+
338+
#[pyproperty(magic)]
339+
fn dict(self) -> PyMappingProxy {
340+
PyMappingProxy::new(self)
341+
}
342+
343+
#[pyproperty(magic, setter)]
344+
fn set_dict(self, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
345+
Err(vm.new_not_implemented_error(
346+
"Setting __dict__ attribute on a type isn't yet implemented".to_owned(),
347+
))
348+
}
341349
}
342350

343351
/*
@@ -346,18 +354,6 @@ impl PyClassRef {
346354

347355
pub(crate) fn init(ctx: &PyContext) {
348356
PyClassRef::extend_class(ctx, &ctx.types.type_type);
349-
extend_class!(&ctx, &ctx.types.type_type, {
350-
"__dict__" =>
351-
PropertyBuilder::new(ctx)
352-
.add_getter(type_dict)
353-
.add_setter(type_dict_setter)
354-
.create(),
355-
"__mro__" =>
356-
PropertyBuilder::new(ctx)
357-
.add_getter(PyClassRef::_mro)
358-
.add_setter(PyClassRef::_set_mro)
359-
.create(),
360-
});
361357
}
362358

363359
fn _mro(cls: &PyClassRef) -> Vec<PyClassRef> {
@@ -409,20 +405,6 @@ pub fn type_new(
409405
new(vm, args.insert(cls.into_object()))
410406
}
411407

412-
fn type_dict(class: PyClassRef, _vm: &VirtualMachine) -> PyMappingProxy {
413-
PyMappingProxy::new(class)
414-
}
415-
416-
fn type_dict_setter(
417-
_instance: PyClassRef,
418-
_value: PyObjectRef,
419-
vm: &VirtualMachine,
420-
) -> PyResult<()> {
421-
Err(vm.new_not_implemented_error(
422-
"Setting __dict__ attribute on a type isn't yet implemented".to_owned(),
423-
))
424-
}
425-
426408
impl PyClassRef {
427409
/// This is the internal get_attr implementation for fast lookup on a class.
428410
pub fn get_attr(&self, attr_name: &str) -> Option<PyObjectRef> {

vm/src/pyobject.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ use crate::obj::objcomplex::PyComplex;
2525
use crate::obj::objdict::{PyDict, PyDictRef};
2626
use crate::obj::objfloat::PyFloat;
2727
use crate::obj::objfunction::{PyBoundMethod, PyFunction};
28+
use crate::obj::objgetset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetSet};
2829
use crate::obj::objint::{PyInt, PyIntRef};
2930
use crate::obj::objiter;
3031
use crate::obj::objlist::PyList;
3132
use crate::obj::objnamespace::PyNamespace;
3233
use crate::obj::objnone::{PyNone, PyNoneRef};
3334
use crate::obj::objobject;
34-
use crate::obj::objproperty::PropertyBuilder;
3535
use crate::obj::objset::PySet;
3636
use crate::obj::objstr;
3737
use crate::obj::objtuple::{PyTuple, PyTupleRef};
@@ -503,11 +503,23 @@ impl PyContext {
503503
)
504504
}
505505

506-
pub fn new_property<F, I, V, VM>(&self, f: F) -> PyObjectRef
506+
pub fn new_readonly_getset<F, T>(&self, name: impl Into<String>, f: F) -> PyObjectRef
507507
where
508-
F: IntoPyNativeFunc<I, V, VM>,
508+
F: IntoPyGetterFunc<T>,
509509
{
510-
PropertyBuilder::new(self).add_getter(f).create()
510+
PyObject::new(PyGetSet::with_get(name.into(), f), self.getset_type(), None)
511+
}
512+
513+
pub fn new_getset<G, S, T, U>(&self, name: impl Into<String>, g: G, s: S) -> PyObjectRef
514+
where
515+
G: IntoPyGetterFunc<T>,
516+
S: IntoPySetterFunc<U>,
517+
{
518+
PyObject::new(
519+
PyGetSet::with_get_set(name.into(), g, s),
520+
self.getset_type(),
521+
None,
522+
)
511523
}
512524

513525
pub fn new_code_object(&self, code: bytecode::CodeObject) -> PyCodeRef {

0 commit comments

Comments
 (0)