From e7f947c9878c97d78d6fa1f07319e8358b889bf2 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Tue, 16 Jan 2024 16:14:13 +0800 Subject: [PATCH] ... --- docs/features/differences.md | 15 +++++++-------- src/pocketpy.cpp | 10 ++++++++++ src/vm.cpp | 18 +++++------------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/docs/features/differences.md b/docs/features/differences.md index 9546ac94..b0aba9ab 100644 --- a/docs/features/differences.md +++ b/docs/features/differences.md @@ -20,14 +20,12 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp ## Unimplemented features -1. `__getattr__` and `__setattr__`. -2. Descriptor protocol `__get__` and `__set__`. However, `@property` is implemented. -3. `__slots__` in class definition. -4. Access the exception object in try..except. -5. `else` clause in try..except. -6. Inplace methods like `__iadd__` and `__imul__`. -7. `__del__` in class definition. -8. Multiple inheritance. +1. Descriptor protocol `__get__` and `__set__`. However, `@property` is implemented. +2. `__slots__` in class definition. +3. `else` clause in try..except. +4. Inplace methods like `__iadd__` and `__imul__`. +5. `__del__` in class definition. +6. Multiple inheritance. ## Different behaviors @@ -42,3 +40,4 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp 9. A `Tab` is equivalent to 4 spaces. You can mix `Tab` and spaces in indentation, but it is not recommended. 10. `%`, `&`, `//`, `^` and `|` for `int` behave the same as C, not python. 11. `str.split` and `str.splitlines` will remove all empty entries. +12. `__getattr__` and `__setattr__` can only be set in cpp. diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 8fbef162..28a7e958 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -1604,6 +1604,16 @@ void VM::post_init(){ return vm->None; }); + _all_types[tp_module].m__getattr__ = [](VM* vm, PyObject* obj, StrName name) -> PyObject*{ + const Str& path = CAST(Str&, obj->attr(__path__)); + PyObject* mod = vm->py_import(fmt(path, ".", name.sv()), false); + if(mod != nullptr){ + obj->attr().set(name, mod); + return mod; + } + return nullptr; + }; + bind_method<1>(tp_property, "setter", [](VM* vm, ArgsView args) { Property& self = _CAST(Property&, args[0]); // The setter's name is not necessary to be the same as the property's name diff --git a/src/vm.cpp b/src/vm.cpp index 116dc139..33264ec8 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1041,17 +1041,8 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){ const PyTypeInfo* ti = &_all_types[objtype]; if(ti->m__getattr__){ - return ti->m__getattr__(this, obj, name); - } - - if(is_non_tagged_type(obj, tp_module)){ - Str path = CAST(Str&, obj->attr(__path__)); - path = path + "." + name.sv(); - PyObject* mod = py_import(path, false); - if(mod != nullptr){ - obj->attr().set(name, mod); - return mod; - } + PyObject* ret = ti->m__getattr__(this, obj, name); + if(ret) return ret; } if(throw_err) AttributeError(obj, name); @@ -1120,8 +1111,9 @@ PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, b } const PyTypeInfo* ti = &_all_types[objtype]; - if(fallback && ti->m__getattr__){ - return ti->m__getattr__(this, obj, name); + if(ti->m__getattr__){ + PyObject* ret = ti->m__getattr__(this, obj, name); + if(ret) return ret; } if(throw_err) AttributeError(obj, name);