8000 py: Support instance __call__ method. · lurch/micropython@755565d · GitHub
[go: up one dir, main page]

Skip to content

Commit 755565d

Browse files
committed
py: Support instance __call__ method.
1 parent 410f307 commit 755565d

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

py/objtype.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,16 @@ STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
338338
}
339339
}
340340

341+
STATIC mp_obj_t class_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
342+
mp_obj_class_t *self = self_in;
343+
mp_obj_t member = mp_obj_class_lookup(self->base.type, MP_QSTR___call__);
344+
if (member == MP_OBJ_NULL) {
345+
return member;
346+
}
347+
mp_obj_t meth = mp_obj_new_bound_meth(member, self);
348+
return mp_call_function_n_kw(meth, n_args, n_kw, args);
349+
}
350+
341351
/******************************************************************************/
342352
// type object
343353
// - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
@@ -474,6 +484,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
474484
o->load_attr = class_load_attr;
475485
o->store_attr = class_store_attr;
476486
o->subscr = class_subscr;
487+
o->call = class_call;
477488
o->bases_tuple = bases_tuple;
478489
o->locals_dict = locals_dict;
479490
return o;

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Q(__repr__)
3131
Q(__str__)
3232
Q(__getattr__)
3333
Q(__del__)
34+
Q(__call__)
3435

3536
Q(micropython)
3637
Q(byte_code)

py/runtime.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,13 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, uint n_args, uint n_kw, const mp
481481

482482
// do the call
483483
if (type->call != NULL) {
484-
return type->call(fun_in, n_args, n_kw, args);
485-
} else {
486-
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
484+
mp_obj_t res = type->call(fun_in, n_args, n_kw, args);
485+
if (res != NULL) {
486+
return res;
487+
}
487488
}
489+
490+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
488491
}
489492

490493
// args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)

tests/basics/class_call.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class C1:
2+
def __call__(self, val):
3+
print('call', val)
4+
return 'item'
5+
6+
class C2:
7+
8+
def __getattr__(self, k):
9+
pass
10+
11+
c1 = C1()
12+
print(c1(1))
13+
14+
c2 = C2()
15+
try:
16+
print(c2(1))
17+
except TypeError:
18+
print("TypeError")

0 commit comments

Comments
 (0)
0