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.
This commit is contained in:
Damien George 2018-05-10 23:10:46 +10:00
parent 29d28c2574
commit 3678a6bdc6
3 changed files with 19 additions and 0 deletions

View File

@ -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)

View File

@ -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));
}
}

View File

@ -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