Skip to content

Commit c0b235e

Browse files
committed
cleanup property and get descriptor codes
1 parent 58744df commit c0b235e

File tree

4 files changed

+30
-25
lines changed

4 files changed

+30
-25
lines changed

vm/src/obj/objproperty.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,22 @@ struct PropertyArgs {
7373
}
7474

7575
impl SlotDescriptor for PyProperty {
76+
#[allow(clippy::collapsible_if)]
7677
fn descr_get(
7778
vm: &VirtualMachine,
7879
zelf: PyObjectRef,
7980
obj: Option<PyObjectRef>,
8081
_cls: OptionalArg<PyObjectRef>,
8182
) -> PyResult {
8283
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 {
84+
if vm.is_none(&obj) {
85+
Ok(zelf.into_object())
86+
} else {
87+
if let Some(getter) = zelf.getter.as_ref() {
8788
vm.invoke(&getter, obj)
89+
} else {
90+
Err(vm.new_attribute_error("unreadable attribute".to_string()))
8891
}
89-
} else {
90-
Err(vm.new_attribute_error("unreadable attribute".to_owned()))
9192
}
9293
}
9394
}

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: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -618,23 +618,28 @@ 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)
642+
.unwrap_or(Ok(attr))
638643
}
639644

640645
pub fn call_method<T>(&self, obj: &PyObjectRef, method_name: &str, args: T) -> PyResult
@@ -654,7 +659,7 @@ impl VirtualMachine {
654659
method_name,
655660
func
656661
);
657-
let wrapped = self.call_get_descriptor(func, obj.clone())?;
662+
let wrapped = self.call_if_get_descriptor(func, obj.clone())?;
658663
self.invoke(&wrapped, args)
659664
}
660665
None => Err(self.new_type_error(format!("Unsupported method: {}", method_name))),
@@ -787,7 +792,7 @@ impl VirtualMachine {
787792
{
788793
let cls = obj.class();
789794
match cls.get_attr(method_name) {
790-
Some(method) => self.call_get_descriptor(method, obj.clone()),
795+
Some(method) => self.call_if_get_descriptor(method, obj.clone()),
791796
None => Err(self.new_type_error(err_msg())),
792797
}
793798
}
@@ -796,7 +801,7 @@ impl VirtualMachine {
796801
pub fn get_method(&self, obj: PyObjectRef, method_name: &str) -> Option<PyResult> {
797802
let cls = obj.class();
798803
let method = cls.get_attr(method_name)?;
799-
Some(self.call_get_descriptor(method, obj.clone()))
804+
Some(self.call_if_get_descriptor(method, obj.clone()))
800805
}
801806

802807
/// Calls a method on `obj` passing `arg`, if the method exists.
@@ -848,6 +853,7 @@ impl VirtualMachine {
848853
})
849854
}
850855

856+
/// CPython _PyObject_GenericGetAttrWithDict
851857
pub fn generic_getattribute(
852858
&self,
853859
obj: PyObjectRef,
@@ -859,10 +865,8 @@ impl VirtualMachine {
859865
if let Some(attr) = cls.get_attr(&name) {
860866
let attr_class = attr.class();
861867
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);
868+
if let Some(r) = self.call_get_descriptor(attr, obj.clone()) {
869+
return r.map(Some);
866870
}
867871
}
868872
}
@@ -876,7 +880,7 @@ impl VirtualMachine {
876880
if let Some(obj_attr) = attr {
877881
Ok(Some(obj_attr))
878882
} else if let Some(attr) = cls.get_attr(&name) {
879-
self.call_get_descriptor(attr, obj).map(Some)
883+
self.call_if_get_descriptor(attr, obj).map(Some)
880884
} else if let Some(getter) = cls.get_attr("__getattr__") {
881885
self.invoke(&getter, vec![obj, name_str.into_object()])
882886
.map(Some)

0 commit comments

Comments
 (0)