Skip to content

Commit 1fcd08f

Browse files
committed
cleanup property and get descriptor codes
1 parent 372f3d4 commit 1fcd08f

File tree

4 files changed

+28
-25
lines changed

4 files changed

+28
-25
lines changed

vm/src/obj/objproperty.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ impl SlotDescriptor for PyProperty {
8080
_cls: OptionalArg<PyObjectRef>,
8181
) -> PyResult {
8282
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
83-
if let Some(getter) = zelf.getter.as_ref() {
84-
if obj.is(vm.ctx.none.as_object()) {
85-
Ok(zelf.into_object())
86-
} else {
83+
if vm.is_none(&obj) {
84+
Ok(zelf.into_object())
85+
} else {
86+
if let Some(getter) = zelf.getter.as_ref() {
8787
vm.invoke(&getter, obj)
88+
} else {
89+
Err(vm.new_attribute_error("unreadable attribute".to_string()))
8890
}
89-
} else {
90-
Err(vm.new_attribute_error("unreadable attribute".to_owned()))
9191
}
9292
}
9393
}

vm/src/obj/objsuper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl PySuper {
6363
// This is a classmethod
6464
return Ok(item);
6565
}
66-
return vm.call_get_descriptor(item, inst.clone());
66+
return vm.call_if_get_descriptor(item, inst.clone());
6767
}
6868
}
6969
Err(vm.new_attribute_error(format!(

vm/src/obj/objtype.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl PyClassRef {
185185
if let Some(cls_attr) = self.get_attr(&name) {
186186
Ok(cls_attr)
187187
} else if let Some(attr) = mcl.get_attr(&name) {
188-
vm.call_get_descriptor(attr, self.into_object())
188+
vm.call_if_get_descriptor(attr, self.into_object())
189189
} else if let Some(ref getter) = self.get_attr("__getattr__") {
190190
vm.invoke(getter, vec![mcl.into_object(), name_ref.into_object()])
191191
} else {

vm/src/vm.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -618,23 +618,27 @@ impl VirtualMachine {
618618
objbool::boolval(self, ret)
619619
}
620620

621-
pub fn call_get_descriptor(&self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult {
622-
let attr_class = attr.class();
623-
let slots = attr_class.slots.borrow();
624-
if let Some(descr_get) = slots.borrow().descr_get.as_ref() {
621+
pub fn call_get_descriptor(&self, descr: PyObjectRef, obj: PyObjectRef) -> Option<PyResult> {
622+
let descr_class = descr.class();
623+
let slots = descr_class.slots.borrow();
624+
Some(if let Some(descr_get) = slots.borrow().descr_get.as_ref() {
625625
let cls = obj.class();
626626
descr_get(
627627
self,
628-
attr,
628+
descr,
629629
Some(obj.clone()),
630630
OptionalArg::Present(cls.into_object()),
631631
)
632-
} else if let Some(ref descriptor) = attr_class.get_attr("__get__") {
632+
} else if let Some(ref descriptor) = descr_class.get_attr("__get__") {
633633
let cls = obj.class();
634-
self.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()])
634+
self.invoke(descriptor, vec![descr, obj.clone(), cls.into_object()])
635635
} else {
636-
Ok(attr)
637-
}
636+
return None;
637+
})
638+
}
639+
640+
pub fn call_if_get_descriptor(&self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult {
641+
self.call_get_descriptor(attr.clone(), obj).unwrap_or(Ok(attr))
638642
}
639643

640644
pub fn call_method<T>(&self, obj: &PyObjectRef, method_name: &str, args: T) -> PyResult
@@ -654,7 +658,7 @@ impl VirtualMachine {
654658
method_name,
655659
func
656660
);
657-
let wrapped = self.call_get_descriptor(func, obj.clone())?;
661+
let wrapped = self.call_if_get_descriptor(func, obj.clone())?;
658662
self.invoke(&wrapped, args)
659663
}
660664
None => Err(self.new_type_error(format!("Unsupported method: {}", method_name))),
@@ -787,7 +791,7 @@ impl VirtualMachine {
787791
{
788792
let cls = obj.class();
789793
match cls.get_attr(method_name) {
790-
Some(method) => self.call_get_descriptor(method, obj.clone()),
794+
Some(method) => self.call_if_get_descriptor(method, obj.clone()),
791795
None => Err(self.new_type_error(err_msg())),
792796
}
793797
}
@@ -796,7 +800,7 @@ impl VirtualMachine {
796800
pub fn get_method(&self, obj: PyObjectRef, method_name: &str) -> Option<PyResult> {
797801
let cls = obj.class();
798802
let method = cls.get_attr(method_name)?;
799-
Some(self.call_get_descriptor(method, obj.clone()))
803+
Some(self.call_if_get_descriptor(method, obj.clone()))
800804
}
801805

802806
/// Calls a method on `obj` passing `arg`, if the method exists.
@@ -848,6 +852,7 @@ impl VirtualMachine {
848852
})
849853
}
850854

855+
/// CPython _PyObject_GenericGetAttrWithDict
851856
pub fn generic_getattribute(
852857
&self,
853858
obj: PyObjectRef,
@@ -859,10 +864,8 @@ impl VirtualMachine {
859864
if let Some(attr) = cls.get_attr(&name) {
860865
let attr_class = attr.class();
861866
if attr_class.has_attr("__set__") {
862-
if let Some(descriptor) = attr_class.get_attr("__get__") {
863-
return self
864-
.invoke(&descriptor, vec![attr, obj, cls.into_object()])
865-
.map(Some);
867+
if let Some(r) = self.call_get_descriptor(attr, obj.clone()) {
868+
return r.map(Some);
866869
}
867870
}
868871
}
@@ -876,7 +879,7 @@ impl VirtualMachine {
876879
if let Some(obj_attr) = attr {
877880
Ok(Some(obj_attr))
878881
} else if let Some(attr) = cls.get_attr(&name) {
879-
self.call_get_descriptor(attr, obj).map(Some)
882+
self.call_if_get_descriptor(attr, obj).map(Some)
880883
} else if let Some(getter) = cls.get_attr("__getattr__") {
881884
self.invoke(&getter, vec![obj, name_str.into_object()])
882885
.map(Some)

0 commit comments

Comments
 (0)