summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorstijn <stijn@ignitron.net>2024-08-21 16:22:01 +0200
committerDamien George <damien@micropython.org>2024-10-07 11:37:52 +1100
commit338df1ae357eefe987df4429b88d3094f9c7b8c2 (patch)
treef2d3d9197a8d14c2be602a820a38126e77781c32 /py
parent548f88d2bd254f1328014a303f8bf602a0646421 (diff)
py/objtype: Allow passing keyword arguments to native base __init__.
Allowing passing keyword arguments to a native base's __init__, i.e. `make_new` in the C code. Previously only positional arguments were allowed. The main trade-off in this commit is that every call to the native base's `make_new` is now going to be preceded by a call to `mp_map_init_fixed_table` even though most of what that does is unused and instead it merely serves as a way to pass the number of keyword arguments. Fixes issue #15465. Signed-off-by: stijn <stijn@ignitron.net>
Diffstat (limited to 'py')
-rw-r--r--py/obj.h3
-rw-r--r--py/objfun.c4
-rw-r--r--py/objtype.c6
3 files changed, 9 insertions, 4 deletions
diff --git a/py/obj.h b/py/obj.h
index eac2b89ea..d942e1bbf 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -516,6 +516,9 @@ typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t);
typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *);
// mp_fun_kw_t takes mp_map_t* (and not const mp_map_t*) to ease passing
// this arg to mp_map_lookup().
+// Note that the mp_obj_t* array will contain all arguments, positional and keyword, with the keyword
+// ones starting at offset n, like: arg0 arg1 ... arg<n> key0 value0 key1 value1 ..., and the mp_map_t*
+// gets those same keyword arguments but as a map for convenience; see fun_builtin_var_call.
typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *);
// Flags for type behaviour (mp_obj_type_t.flags)
diff --git a/py/objfun.c b/py/objfun.c
index 8279605e9..0b1b8c115 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -107,7 +107,9 @@ static mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_k
if (self->sig & 1) {
// function allows keywords
- // we create a map directly from the given args array
+ // we create a map directly from the given args array; self->fun.kw does still
+ // expect args to have both positional and keyword arguments, ordered as:
+ // arg0 arg1 ... arg<n_args> key0 value0 key1 value1 ... key<n_kw> value<n_kw>
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
diff --git a/py/objtype.c b/py/objtype.c
index 16ff5310d..847216982 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -85,14 +85,14 @@ static int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
// This wrapper function allows a subclass of a native type to call the
// __init__() method (corresponding to type->make_new) of the native type.
-static mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) {
+static mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]);
const mp_obj_type_t *native_base = NULL;
instance_count_native_bases(self->base.type, &native_base);
- self->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args - 1, 0, args + 1);
+ self->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args - 1, kw_args->used, args + 1);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper);
+static MP_DEFINE_CONST_FUN_OBJ_KW(native_base_init_wrapper_obj, 1, native_base_init_wrapper);
#if !MICROPY_CPYTHON_COMPAT
static