summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/obj.h4
-rw-r--r--py/objtype.c43
-rw-r--r--py/runtime.c2
3 files changed, 33 insertions, 16 deletions
diff --git a/py/obj.h b/py/obj.h
index 855b151506..2ccda66ee7 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -255,9 +255,7 @@ mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_type_t *mp_obj_get_type(mp_obj_t o_in);
const char *mp_obj_get_type_str(mp_obj_t o_in);
-bool mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo);
-// Without supefluous arg checking
-bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo);
+bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo); // arguments should be type objects
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
diff --git a/py/objtype.c b/py/objtype.c
index c814e9c75e..9eb228ce3f 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -454,6 +454,8 @@ mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) {
/******************************************************************************/
// subclassing and built-ins specific to types
+// object and classinfo should be type objects
+// (but the function will fail gracefully if they are not)
bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo) {
for (;;) {
if (object == classinfo) {
@@ -462,7 +464,11 @@ bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo) {
// not equivalent classes, keep searching base classes
- assert(MP_OBJ_IS_TYPE(object, &mp_type_type));
+ // object should always be a type object, but just return false if it's not
+ if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
+ return false;
+ }
+
mp_obj_type_t *self = object;
// for a const struct, this entry might be NULL
@@ -470,14 +476,17 @@ bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo) {
return false;
}
+ // get the base objects (they should be type objects)
uint len;
mp_obj_t *items;
mp_obj_tuple_get(self->bases_tuple, &len, &items);
if (len == 0) {
return false;
}
+
+ // iterate through the base objects
for (uint i = 0; i < len - 1; i++) {
- if (mp_obj_is_subclass(items[i], classinfo)) {
+ if (mp_obj_is_subclass_fast(items[i], classinfo)) {
return true;
}
}
@@ -487,27 +496,37 @@ bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo) {
}
}
-bool mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
- if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"));
+STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
+ uint len;
+ mp_obj_t *items;
+ if (MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) {
+ len = 1;
+ items = &classinfo;
+ } else if (MP_OBJ_IS_TYPE(classinfo, &tuple_type)) {
+ mp_obj_tuple_get(classinfo, &len, &items);
+ } else {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"));
}
- // TODO support a tuple of classes for second argument
- if (!MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class"));
+ for (uint i = 0; i < len; i++) {
+ if (mp_obj_is_subclass_fast(object, items[i])) {
+ return mp_const_true;
+ }
}
-
- return mp_obj_is_subclass_fast(object, classinfo);
+ return mp_const_false;
}
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
- return MP_BOOL(mp_obj_is_subclass(object, classinfo));
+ if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"));
+ }
+ return mp_obj_is_subclass(object, classinfo);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);
STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
- return MP_BOOL(mp_obj_is_subclass(mp_obj_get_type(object), classinfo));
+ return mp_obj_is_subclass(mp_obj_get_type(object), classinfo);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
diff --git a/py/runtime.c b/py/runtime.c
index 0de161b08b..9d41f059f5 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -518,7 +518,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
if (mp_obj_is_exception_instance(lhs)) {
lhs = mp_obj_get_type(lhs);
}
- if (mp_obj_is_subclass(lhs, rhs)) {
+ if (mp_obj_is_subclass_fast(lhs, rhs)) {
return mp_const_true;
} else {
return mp_const_false;