From 1a7403bb743c02a37247d0c76397cc7891fc127c Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 10 May 2014 21:09:18 +0300 Subject: [PATCH] objtype: Implement ->getiter() method for instances. Includes support for native bases. --- py/objtype.c | 23 +++++++++++++++++++++++ tests/basics/subclass_native_specmeth.py | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/basics/subclass_native_specmeth.py diff --git a/py/objtype.c b/py/objtype.c index f43c92d350..460e0b2758 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -501,6 +501,28 @@ STATIC mp_obj_t instance_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp return mp_call_function_n_kw(meth, n_args, n_kw, args); } +STATIC mp_obj_t instance_getiter(mp_obj_t self_in) { + mp_obj_instance_t *self = self_in; + mp_obj_t member[2] = {MP_OBJ_NULL}; + mp_obj_class_lookup(self, self->base.type, MP_QSTR___iter__, offsetof(mp_obj_type_t, getiter), member); + if (member[0] == MP_OBJ_NULL) { + // This kinda duplicates code in mp_getiter() + mp_obj_class_lookup(self, self->base.type, MP_QSTR___getitem__, 0, member); + if (member[0] != MP_OBJ_NULL) { + // __getitem__ exists, create an iterator + instance_convert_return_attr(self_in, member[0], member); + return mp_obj_new_getitem_iter(member); + } + return MP_OBJ_NULL; + } + if (member[0] == MP_OBJ_SENTINEL) { + mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); + return type->getiter(self->subobj[0]); + } + mp_obj_t meth = mp_obj_new_bound_meth(member[0], self); + return mp_call_function_n_kw(meth, 0, 0, NULL); +} + /******************************************************************************/ // type object // - the struct is mp_obj_type_t and is defined in obj.h so const types can be made @@ -655,6 +677,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) o->store_attr = instance_store_attr; o->subscr = instance_subscr; o->call = instance_call; + o->getiter = instance_getiter; o->bases_tuple = bases_tuple; o->locals_dict = locals_dict; diff --git a/tests/basics/subclass_native_specmeth.py b/tests/basics/subclass_native_specmeth.py new file mode 100644 index 0000000000..91ffc9624b --- /dev/null +++ b/tests/basics/subclass_native_specmeth.py @@ -0,0 +1,18 @@ +# Test calling non-special method inherited from native type + +class mylist(list): + pass + +l = mylist([1, 2, 3]) +print(l) +print([e for e in l]) + + +class mylist2(list): + + def __iter__(self): + return iter([10, 20, 30]) + +l = mylist2([1, 2, 3]) +print(l) +print([e for e in l])