Skip to content

Commit 23419a2

Browse files
committed
Merge pull request adafruit#433 from pfalcon/getattr-3arg
py: Support 3-arg getattr() builtin (with default value).
2 parents 6d50866 + bfb7d6a commit 23419a2

4 files changed

Lines changed: 21 additions & 8 deletions

File tree

py/builtin.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,13 @@ STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
400400

401401
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id);
402402

403-
STATIC mp_obj_t mp_builtin_getattr(mp_obj_t o_in, mp_obj_t attr) {
404-
assert(MP_OBJ_IS_QSTR(attr));
405-
return mp_load_attr(o_in, MP_OBJ_QSTR_VALUE(attr));
403+
STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
404+
assert(MP_OBJ_IS_QSTR(args[1]));
405+
mp_obj_t defval = MP_OBJ_NULL;
406+
if (n_args > 2) {
407+
defval = args[2];
408+
}
409+
return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(args[1]), defval);
406410
}
407411

408-
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_getattr_obj, mp_builtin_getattr);
412+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);

py/runtime.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -690,12 +690,14 @@ void mp_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
690690
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
691691
}
692692

693-
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
693+
mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) {
694694
DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
695-
// use load_method
696695
mp_obj_t dest[2];
697-
mp_load_method(base, attr, dest);
698-
if (dest[1] == MP_OBJ_NULL) {
696+
// use load_method, raising or not raising exception
697+
((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest);
698+
if (dest[0] == MP_OBJ_NULL) {
699+
return defval;
700+
} else if (dest[1] == MP_OBJ_NULL) {
699701
// load_method returned just a normal attribute
700702
return dest[0];
701703
} else {
@@ -704,6 +706,10 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
704706
}
705707
}
706708

709+
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
710+
return mp_load_attr_default(base, attr, MP_OBJ_NULL);
711+
}
712+
707713
// no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
708714
// normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
709715
// method attribute found, returns: dest[0] == <method>, dest[1] == <self>

py/runtime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_
4545
void mp_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
4646
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
4747
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
48+
mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval);
4849
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
4950
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
5051
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);

tests/basics/getattr1.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ def meth(self, i):
1313
print(getattr(a, "var"))
1414
print(getattr(a, "var2"))
1515
print(getattr(a, "meth")(5))
16+
print(getattr(a, "_none_such", 123))
17+
print(getattr(list, "foo", 456))

0 commit comments

Comments
 (0)