From 317a37a851afe04d485351b07d10b3e3b749be39 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 16 Aug 2024 16:52:04 +0800 Subject: [PATCH] support `__getattr__` --- include/pocketpy/xmacros/magics.h | 1 + src/public/py_ops.c | 8 ++++++++ tests/50_reflection.py | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/include/pocketpy/xmacros/magics.h b/include/pocketpy/xmacros/magics.h index 7e8730c1..2fc26836 100644 --- a/include/pocketpy/xmacros/magics.h +++ b/include/pocketpy/xmacros/magics.h @@ -59,6 +59,7 @@ MAGIC_METHOD(__package__) MAGIC_METHOD(__path__) MAGIC_METHOD(__class__) MAGIC_METHOD(__abs__) +MAGIC_METHOD(__getattr__) MAGIC_METHOD(__missing__) #endif \ No newline at end of file diff --git a/src/public/py_ops.c b/src/public/py_ops.c index ccb86686..cd41aff4 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -151,6 +151,14 @@ bool py_getattr(py_Ref self, py_Name name) { } } + py_Ref fallback = py_tpfindmagic(type, __getattr__); + if(fallback){ + py_push(fallback); + py_push(self); + py_newstr(py_pushtmp(), py_name2str(name)); + return py_vectorcall(1, 0); + } + if(self->type == tp_module) { py_Ref path = py_getdict(self, __path__); c11_sbuf buf; diff --git a/tests/50_reflection.py b/tests/50_reflection.py index 50433fc7..c4118174 100644 --- a/tests/50_reflection.py +++ b/tests/50_reflection.py @@ -26,3 +26,27 @@ except AttributeError: pass assert getattr(a, 'xxx', 1) == 1 + +class A: + def __init__(self, x): + self.x = x + + def __getattr__(self, name): + if not name: + raise AttributeError + return name, None + +a = A(1) +assert a.x == 1 +assert a.y == ('y', None) +assert a.zzz == ('zzz', None) + +assert getattr(a, 'x') == 1 +assert getattr(a, 'zzz') == ('zzz', None) + +assert hasattr(a, 'x') +assert hasattr(a, 'y') +assert hasattr(a, 'zzz') + +assert not hasattr(a, '') +