Commit bfb7d6a2 authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

py: Support 3-arg getattr() builtin (with default value).

parent 438d504e
......@@ -400,9 +400,13 @@ STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id);
STATIC mp_obj_t mp_builtin_getattr(mp_obj_t o_in, mp_obj_t attr) {
assert(MP_OBJ_IS_QSTR(attr));
return mp_load_attr(o_in, MP_OBJ_QSTR_VALUE(attr));
STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_QSTR(args[1]));
mp_obj_t defval = MP_OBJ_NULL;
if (n_args > 2) {
defval = args[2];
}
return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(args[1]), defval);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_getattr_obj, mp_builtin_getattr);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);
......@@ -689,12 +689,14 @@ too_long:
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
}
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) {
DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
// use load_method
mp_obj_t dest[2];
mp_load_method(base, attr, dest);
if (dest[1] == MP_OBJ_NULL) {
// use load_method, raising or not raising exception
((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest);
if (dest[0] == MP_OBJ_NULL) {
return defval;
} else if (dest[1] == MP_OBJ_NULL) {
// load_method returned just a normal attribute
return dest[0];
} else {
......@@ -703,6 +705,10 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
}
}
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
return mp_load_attr_default(base, attr, MP_OBJ_NULL);
}
// no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
// normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
// method attribute found, returns: dest[0] == <method>, dest[1] == <self>
......
......@@ -45,6 +45,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_
void mp_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
......
......@@ -13,3 +13,5 @@ a = A()
print(getattr(a, "var"))
print(getattr(a, "var2"))
print(getattr(a, "meth")(5))
print(getattr(a, "_none_such", 123))
print(getattr(list, "foo", 456))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment