summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/objstr.c4
-rw-r--r--tests/basics/string_format_modulo.py11
2 files changed, 11 insertions, 4 deletions
diff --git a/py/objstr.c b/py/objstr.c
index b966a7016..5dfe94ac4 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -1645,7 +1645,9 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_
}
}
- if (arg_i != n_args) {
+ if (dict == MP_OBJ_NULL && arg_i != n_args) {
+ // NOTE: if `dict` exists, then `n_args` is 1 and the dict is always consumed; either
+ // positionally, or as a map of named args, even if none were actually referenced.
mp_raise_TypeError(MP_ERROR_TEXT("format string didn't convert all arguments"));
}
diff --git a/tests/basics/string_format_modulo.py b/tests/basics/string_format_modulo.py
index 14b4a6a48..7bddd9675 100644
--- a/tests/basics/string_format_modulo.py
+++ b/tests/basics/string_format_modulo.py
@@ -51,8 +51,9 @@ print('%c' % True)
# Should be able to print dicts; in this case they aren't used
# to lookup keywords in formats like %(foo)s
-print('%s' % {})
-print('%s' % ({},))
+print('%s' % {}) # dict treated as the single (positional) arg to %
+print('%s' % ({},)) # dict is the first (and only) arg in the positional arg tuple
+print('foo' % {}) # no error, dict treated as an empty map of named args
# Cases when "*" used and there's not enough values total
try:
@@ -65,7 +66,11 @@ except TypeError:
print("TypeError")
print("%(foo)s" % {"foo": "bar", "baz": False})
-print("%s %(foo)s %(foo)s" % {"foo": 1})
+print("%s %(foo)s %(foo)s" % {"foo": 1}) # dict consumed positionally, then used as map - ok
+try:
+ print("%(foo)s %s %(foo)s" % {"foo": 1}) # used as map, then positionally - not enough args
+except TypeError:
+ print("TypeError")
try:
print("%(foo)s" % {})
except KeyError: