From 3678a6bdc6a925f2bce6423c41f911229836f946 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 May 2018 23:10:46 +1000 Subject: [PATCH] py/modbuiltins: Make built-in dir support the __dir__ special method. If MICROPY_PY_ALL_SPECIAL_METHODS is enabled then dir() will now delegate to the special method __dir__ if the object it is listing has this method. --- py/makeqstrdata.py | 3 +++ py/modbuiltins.c | 7 +++++++ tests/basics/special_methods2.py | 9 +++++++++ 3 files changed, 19 insertions(+) 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