summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/objtype.c7
-rw-r--r--tests/basics/class_descriptor.py27
2 files changed, 34 insertions, 0 deletions
diff --git a/py/objtype.c b/py/objtype.c
index 847216982a..b9af100899 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -660,6 +660,13 @@ static void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
// try __getattr__
if (attr != MP_QSTR___getattr__) {
+ #if MICROPY_PY_DESCRIPTORS
+ // With descriptors enabled, don't delegate lookups of __get__/__set__/__delete__.
+ if (attr == MP_QSTR___get__ || attr == MP_QSTR___set__ || attr == MP_QSTR___delete__) {
+ return;
+ }
+ #endif
+
#if MICROPY_PY_DELATTR_SETATTR
// If the requested attr is __setattr__/__delattr__ then don't delegate the lookup
// to __getattr__. If we followed CPython's behaviour then __setattr__/__delattr__
diff --git a/tests/basics/class_descriptor.py b/tests/basics/class_descriptor.py
index 54f386230f..83d3167430 100644
--- a/tests/basics/class_descriptor.py
+++ b/tests/basics/class_descriptor.py
@@ -21,14 +21,41 @@ m = Main()
try:
m.__class__
except AttributeError:
+ # Target doesn't support __class__.
print("SKIP")
raise SystemExit
r = m.Forward
if 'Descriptor' in repr(r.__class__):
+ # Target doesn't support descriptors.
print('SKIP')
raise SystemExit
+# Test assignment and deletion.
+
print(r)
m.Forward = 'a'
del m.Forward
+
+# Test that lookup of descriptors like __get__ are not passed into __getattr__.
+
+
+class NonDescriptor:
+ def __getattr__(self, attr):
+ print("getattr", attr)
+
+
+class TestClass:
+ non_descriptor = NonDescriptor()
+
+
+print(isinstance(TestClass().non_descriptor, NonDescriptor))
+
+t = TestClass()
+t.non_descriptor = 123
+print(t.non_descriptor)
+
+try:
+ del TestClass().non_descriptor
+except AttributeError:
+ print("AttributeError")