Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ff30666

Browse files
committed
py: Add basic implementation of hasattr() function.
1 parent a086315 commit ff30666

File tree

5 files changed

+47
-0
lines changed

5 files changed

+47
-0
lines changed

py/builtin.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,21 @@ STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
462462

463463
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);
464464

465+
STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) {
466+
assert(MP_OBJ_IS_QSTR(attr_in));
467+
468+
mp_obj_t dest[2];
469+
// TODO: https://docs.python.org/3.3/library/functions.html?highlight=hasattr#hasattr
470+
// explicitly says "This is implemented by calling getattr(object, name) and seeing
471+
// whether it raises an AttributeError or not.", so we should explicitly wrap this
472+
// in nlr_push and handle exception.
473+
mp_load_method_maybe(object_in, MP_OBJ_QSTR_VALUE(attr_in), dest);
474+
475+
return MP_BOOL(dest[0] != MP_OBJ_NULL);
476+
}
477+
478+
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr);
479+
465480
// These two are defined in terms of MicroPython API functions right away
466481
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_globals_get);
467482
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_locals_get);

py/builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj);
4141
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_exec_obj);
4242
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_getattr_obj);
4343
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_globals_obj);
44+
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hasattr_obj);
4445
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj);
4546
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hex_obj);
4647
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_id_obj);

py/builtintables.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
9090
{ MP_OBJ_NEW_QSTR(MP_QSTR_exec), (mp_obj_t)&mp_builtin_exec_obj },
9191
{ MP_OBJ_NEW_QSTR(MP_QSTR_getattr), (mp_obj_t)&mp_builtin_getattr_obj },
9292
{ MP_OBJ_NEW_QSTR(MP_QSTR_globals), (mp_obj_t)&mp_builtin_globals_obj },
93+
{ MP_OBJ_NEW_QSTR(MP_QSTR_hasattr), (mp_obj_t)&mp_builtin_hasattr_obj },
9394
{ MP_OBJ_NEW_QSTR(MP_QSTR_hash), (mp_obj_t)&mp_builtin_hash_obj },
9495
{ MP_OBJ_NEW_QSTR(MP_QSTR_hex), (mp_obj_t)&mp_builtin_hex_obj },
9596
{ MP_OBJ_NEW_QSTR(MP_QSTR_id), (mp_obj_t)&mp_builtin_id_obj },

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ Q(float)
142142
Q(from_bytes)
143143
Q(getattr)
144144
Q(globals)
145+
Q(hasattr)
145146
Q(hash)
146147
Q(hex)
147148
Q(%#x)

tests/basics/hasattr1.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class A:
2+
3+
var = 132
4+
5+
def __init__(self):
6+
self.var2 = 34
7+
8+
def meth(self, i):
9+
return 42 + i
10+
11+
12+
a = A()
13+
print(hasattr(a, "var"))
14+
print(hasattr(a, "var2"))
15+
print(hasattr(a, "meth"))
16+
print(hasattr(a, "_none_such"))
17+
print(hasattr(list, "foo"))
18+
19+
class C:
20+
21+
def __getattr__(self, attr):
22+
if attr == "exists":
23+
return attr
24+
raise AttributeError
25+
26+
c = C()
27+
print(hasattr(c, "exists"))
28+
# TODO
29+
#print(hasattr(c, "doesnt_exist"))

0 commit comments

Comments
 (0)