objstr: Implement kwargs support for str.format().

This commit is contained in:
Paul Sokolovsky 2015-01-04 00:14:13 +02:00
parent ae58795c44
commit c114496641
4 changed files with 35 additions and 18 deletions

View File

@ -141,7 +141,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);
STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
return mp_obj_str_format(MP_ARRAY_SIZE(args), args);
return mp_obj_str_format(MP_ARRAY_SIZE(args), args, MP_OBJ_NULL);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);

View File

@ -832,7 +832,7 @@ STATIC NORETURN void terse_str_format_value_error(void) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad format string"));
}
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
GET_STR_DATA_LEN(args[0], str, len);
@ -932,23 +932,36 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
mp_obj_t arg = mp_const_none;
if (field_name) {
if (arg_i > 0) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
terse_str_format_value_error();
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"can't switch from automatic field numbering to manual field specification"));
}
}
int index = 0;
if (str_to_int(vstr_str(field_name), &index) != vstr_len(field_name) - 1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "attributes not supported yet"));
const char *field = vstr_str(field_name);
const char *lookup = NULL;
if (MP_LIKELY(unichar_isdigit(*field))) {
if (arg_i > 0) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
terse_str_format_value_error();
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"can't switch from automatic field numbering to manual field specification"));
}
}
lookup = str_to_int(vstr_str(field_name), &index) + field;
if (index >= n_args - 1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
}
arg = args[index + 1];
arg_i = -1;
} else {
for (lookup = field; *lookup && *lookup != '.' && *lookup != '['; lookup++);
mp_obj_t field_q = mp_obj_new_str(field, lookup - field, true/*?*/);
mp_map_elem_t *key_elem = mp_map_lookup(kwargs, field_q, MP_MAP_LOOKUP);
if (key_elem == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, field_q));
}
arg = key_elem->value;
}
if (index >= n_args - 1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
if (*lookup) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, "attributes not supported yet"));
}
arg = args[index + 1];
arg_i = -1;
vstr_free(field_name);
field_name = NULL;
} else {
@ -1775,7 +1788,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
MP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);

View File

@ -55,7 +55,7 @@ typedef struct _mp_obj_str_t {
else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len);
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args);
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len);
mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);

View File

@ -60,6 +60,10 @@ test("{:@<6d}", -123)
test("{:@=6d}", -123)
test("{:06d}", -123)
print("{foo}/foo".format(foo="bar"))
print("{}".format(123, foo="bar"))
print("{}-{foo}".format(123, foo="bar"))
def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg):
fmt = '{'
if conv: