From b4efac14cde7dca4b3fd5ded9b29e11f97621d14 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 8 Jun 2014 01:13:35 +0300 Subject: [PATCH] py: Make sure getattr() works with non-interned strings (by interning them). --- py/builtin.c | 9 +++++++-- py/obj.h | 1 + py/objstr.c | 5 +++++ tests/basics/getattr1.py | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/py/builtin.c b/py/builtin.c index 8621b0b003..834108f1b5 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -452,12 +452,17 @@ STATIC inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t d } 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 attr = args[1]; + if (MP_OBJ_IS_TYPE(attr, &mp_type_str)) { + attr = mp_obj_str_intern(attr); + } else if (!MP_OBJ_IS_QSTR(attr)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "string required")); + } 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); + return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(attr), defval); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr); diff --git a/py/obj.h b/py/obj.h index c7f0a9879e..d5ea40901c 100644 --- a/py/obj.h +++ b/py/obj.h @@ -468,6 +468,7 @@ uint mp_obj_str_get_len(mp_obj_t self_in); qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len); +mp_obj_t mp_obj_str_intern(mp_obj_t str); void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len); #if MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objstr.c b/py/objstr.c index 4e70b00812..6656090c84 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1751,6 +1751,11 @@ mp_obj_t mp_obj_new_str(const char* data, uint len, bool make_qstr_if_not_alread } } +mp_obj_t mp_obj_str_intern(mp_obj_t str) { + GET_STR_DATA_LEN(str, data, len); + return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len)); +} + mp_obj_t mp_obj_new_bytes(const byte* data, uint len) { return mp_obj_new_str_of_type(&mp_type_bytes, data, len); } diff --git a/tests/basics/getattr1.py b/tests/basics/getattr1.py index 9a96154ca5..59cb7e7f7a 100644 --- a/tests/basics/getattr1.py +++ b/tests/basics/getattr1.py @@ -15,3 +15,4 @@ print(getattr(a, "var2")) print(getattr(a, "meth")(5)) print(getattr(a, "_none_such", 123)) print(getattr(list, "foo", 456)) +print(getattr(a, "va" + "r2"))