Skip to content

Commit b4efac1

Browse files
committed
py: Make sure getattr() works with non-interned strings (by interning them).
1 parent d31a093 commit b4efac1

4 files changed

Lines changed: 14 additions & 2 deletions

File tree

py/builtin.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,12 +452,17 @@ STATIC inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t d
452452
}
453453

454454
STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
455-
assert(MP_OBJ_IS_QSTR(args[1]));
455+
mp_obj_t attr = args[1];
456+
if (MP_OBJ_IS_TYPE(attr, &mp_type_str)) {
457+
attr = mp_obj_str_intern(attr);
458+
} else if (!MP_OBJ_IS_QSTR(attr)) {
459+
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "string required"));
460+
}
456461
mp_obj_t defval = MP_OBJ_NULL;
457462
if (n_args > 2) {
458463
defval = args[2];
459464
}
460-
return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(args[1]), defval);
465+
return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(attr), defval);
461466
}
462467

463468
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);

py/obj.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ uint mp_obj_str_get_len(mp_obj_t self_in);
468468
qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr
469469
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
470470
const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len);
471+
mp_obj_t mp_obj_str_intern(mp_obj_t str);
471472
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len);
472473

473474
#if MICROPY_PY_BUILTINS_FLOAT

py/objstr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,11 @@ mp_obj_t mp_obj_new_str(const char* data, uint len, bool make_qstr_if_not_alread
17511751
}
17521752
}
17531753

1754+
mp_obj_t mp_obj_str_intern(mp_obj_t str) {
1755+
GET_STR_DATA_LEN(str, data, len);
1756+
return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len));
1757+
}
1758+
17541759
mp_obj_t mp_obj_new_bytes(const byte* data, uint len) {
17551760
return mp_obj_new_str_of_type(&mp_type_bytes, data, len);
17561761
}

tests/basics/getattr1.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ def meth(self, i):
1515
print(getattr(a, "meth")(5))
1616
print(getattr(a, "_none_such", 123))
1717
print(getattr(list, "foo", 456))
18+
print(getattr(a, "va" + "r2"))

0 commit comments

Comments
 (0)