summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/objnamedtuple.c34
-rw-r--r--tests/basics/namedtuple1.py30
2 files changed, 52 insertions, 12 deletions
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 0fe2f774af..313eeac5e4 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -89,9 +89,39 @@ STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
// Counts include implicit "self"
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"__new__() takes %d positional arguments but %d were given",
- num_fields + 1, n_args + 1));
+ num_fields + 1, n_args + n_kw + 1));
}
- mp_obj_tuple_t *tuple = mp_obj_new_tuple(n_args, args);
+
+ mp_obj_t *arg_objects;
+ if (n_args == num_fields) {
+ arg_objects = (mp_obj_t*)args;
+ } else {
+ size_t alloc_size = sizeof(mp_obj_t) * num_fields;
+ arg_objects = alloca(alloc_size);
+ memset(arg_objects, 0, alloc_size);
+
+ for (mp_uint_t i = 0; i < n_args; i++) {
+ arg_objects[i] = args[i];
+ }
+
+ for (mp_uint_t i = n_args; i < n_args + 2 * n_kw; i += 2) {
+ qstr kw = MP_OBJ_QSTR_VALUE(args[i]);
+ int id = namedtuple_find_field(type, kw);
+ if (id == -1) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "__new__() got an unexpected keyword argument '%s'",
+ qstr_str(kw)));
+ }
+ if (arg_objects[id] != NULL) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "__new__() got multiple values for argument '%s'",
+ qstr_str(kw)));
+ }
+ arg_objects[id] = args[i + 1];
+ }
+ }
+
+ mp_obj_tuple_t *tuple = mp_obj_new_tuple(num_fields, arg_objects);
tuple->base.type = type_in;
return tuple;
}
diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py
index a94b7e7ab0..9afeed9408 100644
--- a/tests/basics/namedtuple1.py
+++ b/tests/basics/namedtuple1.py
@@ -6,19 +6,19 @@ except ImportError:
T = namedtuple("Tup", ["foo", "bar"])
# CPython prints fully qualified name, what we don't bother to do so far
#print(T)
-t = T(1, 2)
-print(t)
-print(t[0], t[1])
-print(t.foo, t.bar)
+for t in T(1, 2), T(bar=1, foo=2):
+ print(t)
+ print(t[0], t[1])
+ print(t.foo, t.bar)
-print(len(t))
-print(bool(t))
-print(t + t)
-print(t * 3)
+ print(len(t))
+ print(bool(t))
+ print(t + t)
+ print(t * 3)
-print([f for f in t])
+ print([f for f in t])
-print(isinstance(t, tuple))
+ print(isinstance(t, tuple))
try:
t[0] = 200
@@ -39,6 +39,16 @@ try:
except TypeError:
print("TypeError")
+try:
+ t = T(foo=1)
+except TypeError:
+ print("TypeError")
+
+try:
+ t = T(1, foo=1)
+except TypeError:
+ print("TypeError")
+
# Try single string
# Not implemented so far
#T3 = namedtuple("TupComma", "foo bar")