diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 38fde1a9c6..3c0a609092 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -114,6 +114,9 @@ def parse_input_headers(infiles): if ident == "": # Sort empty qstr above all still order = -200000 + elif ident == "__dir__": + # Put __dir__ after empty qstr for builtin dir() to work + order = -190000 elif ident.startswith("__"): order -= 100000 qstrs[ident] = (order, ident, qstr) diff --git a/py/modbuiltins.c b/py/modbuiltins.c index bc99f82610..0d511338b0 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -190,6 +190,13 @@ STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { mp_obj_t dest[2]; mp_load_method_protected(args[0], i, dest, false); if (dest[0] != MP_OBJ_NULL) { + #if MICROPY_PY_ALL_SPECIAL_METHODS + // Support for __dir__: see if we can dispatch to this special method + // This relies on MP_QSTR__dir__ being first after MP_QSTR_ + if (i == MP_QSTR___dir__ && dest[1] != MP_OBJ_NULL) { + return mp_call_method_n_kw(0, 0, dest); + } + #endif mp_obj_list_append(dir, MP_OBJ_NEW_QSTR(i)); } } diff --git a/tests/basics/special_methods2.py b/tests/basics/special_methods2.py index ba7cf27cda..1a38a250c0 100644 --- a/tests/basics/special_methods2.py +++ b/tests/basics/special_methods2.py @@ -94,6 +94,9 @@ class Cud(): print("__isub__ called") return self + def __dir__(self): + return ['a', 'b', 'c'] + cud1 = Cud() cud2 = Cud() @@ -113,6 +116,12 @@ cud2 // cud1 cud1 += cud2 cud1 -= cud2 +# test that dir() delegates to __dir__ special method +print(dir(cud1)) + +# test that dir() does not delegate to __dir__ for the type +print('a' in dir(Cud)) + # TODO: the following operations are not supported on every ports # # ne is not supported, !(eq) is called instead