Skip to content

Commit 7182111

Browse files
authored
Merge pull request RustPython#3748 from youknowone/getattr
Fix getattr to use `__getattribute__` correctly
2 parents c40bc62 + b9c1f31 commit 7182111

File tree

4 files changed

+20
-17
lines changed

4 files changed

+20
-17
lines changed

Lib/test/test_enum.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,6 @@ def red(self):
429429
green = 2
430430
blue = 3
431431

432-
# TODO: RUSTPYTHON
433-
@unittest.expectedFailure
434432
def test_enum_with_value_name(self):
435433
class Huh(Enum):
436434
name = 1
@@ -1668,8 +1666,6 @@ class Test(Base):
16681666
test = 1
16691667
self.assertIs(type(Test.test), Test)
16701668

1671-
# TODO: RUSTPYTHON
1672-
@unittest.expectedFailure
16731669
def test_subclass_duplicate_name_dynamic(self):
16741670
from types import DynamicClassAttribute
16751671
class Base(Enum):

vm/src/builtins/weakproxy.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{PyStrRef, PyType, PyTypeRef, PyWeak};
22
use crate::{
33
class::PyClassImpl,
44
function::OptionalArg,
5-
types::{Constructor, SetAttr},
5+
types::{Constructor, GetAttr, SetAttr},
66
Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
77
};
88

@@ -57,14 +57,8 @@ crate::common::static_cell! {
5757
static WEAK_SUBCLASS: PyTypeRef;
5858
}
5959

60-
#[pyimpl(with(SetAttr, Constructor))]
60+
#[pyimpl(with(GetAttr, SetAttr, Constructor))]
6161
impl PyWeakProxy {
62-
// TODO: callbacks
63-
#[pymethod(magic)]
64-
fn getattr(&self, attr_name: PyStrRef, vm: &VirtualMachine) -> PyResult {
65-
let obj = self.weak.upgrade().ok_or_else(|| new_reference_error(vm))?;
66-
obj.get_attr(attr_name, vm)
67-
}
6862
#[pymethod(magic)]
6963
fn str(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
7064
match self.weak.upgrade() {
@@ -81,6 +75,14 @@ fn new_reference_error(vm: &VirtualMachine) -> PyRef<super::PyBaseException> {
8175
)
8276
}
8377

78+
impl GetAttr for PyWeakProxy {
79+
// TODO: callbacks
80+
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
81+
let obj = zelf.weak.upgrade().ok_or_else(|| new_reference_error(vm))?;
82+
obj.get_attr(name, vm)
83+
}
84+
}
85+
8486
impl SetAttr for PyWeakProxy {
8587
fn setattro(
8688
zelf: &crate::Py<Self>,

vm/src/protocol/object.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,6 @@ impl PyObject {
233233
}
234234
None => Ok(Some(attr)),
235235
}
236-
} else if let Some(getter) = obj_cls.get_attr(identifier!(vm, __getattr__)) {
237-
drop(obj_cls);
238-
vm.invoke(&getter, (self.to_owned(), name_str)).map(Some)
239236
} else {
240237
Ok(None)
241238
}

vm/src/types/slot.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,15 @@ fn call_wrapper(zelf: &PyObject, args: FuncArgs, vm: &VirtualMachine) -> PyResul
414414
}
415415

416416
fn getattro_wrapper(zelf: &PyObject, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
417-
vm.call_special_method(zelf.to_owned(), identifier!(vm, __getattribute__), (name,))
417+
let __getattribute__ = identifier!(vm, __getattribute__);
418+
let __getattr__ = identifier!(vm, __getattr__);
419+
match vm.call_special_method(zelf.to_owned(), __getattribute__, (name.clone(),)) {
420+
Ok(r) => Ok(r),
421+
Err(_) if zelf.class().has_attr(__getattr__) => {
422+
vm.call_special_method(zelf.to_owned(), __getattr__, (name,))
423+
}
424+
Err(e) => Err(e),
425+
}
418426
}
419427

420428
fn setattro_wrapper(
@@ -522,7 +530,7 @@ impl PyType {
522530
"__call__" => {
523531
update_slot!(call, call_wrapper);
524532
}
525-
"__getattribute__" => {
533+
"__getattr__" | "__getattribute__" => {
526534
update_slot!(getattro, getattro_wrapper);
527535
}
528536
"__setattr__" | "__delattr__" => {

0 commit comments

Comments
 (0)