[formatter] implement 'M' format specifier

Map a list of objects to a list of values

[
    {"name": "John Doe"      , "age": 42},
    {"name": "Jane Smith"    , "age": 24},
    {"name": "Max Mustermann", "age": null}
]

== :Mname =>

["John Doe", "Jane Smith", "Max Mustermann"]
This commit is contained in:
Mike Fährmann
2025-06-22 15:09:28 +02:00
parent 71461ceaba
commit 2bcc2f2a17
3 changed files with 60 additions and 11 deletions

View File

@@ -221,7 +221,7 @@ class FStringFormatter():
"""Generate text by evaluating an f-string literal"""
def __init__(self, fstring, default=NONE, fmt=None):
self.format_map = util.compile_expression('f"""' + fstring + '"""')
self.format_map = util.compile_expression(f'f"""{fstring}"""')
class TemplateFormatter(StringFormatter):
@@ -302,7 +302,7 @@ def _parse_optional(format_spec, default):
fmt = _build_format_func(format_spec, default)
def optional(obj):
return before + fmt(obj) + after if obj else ""
return f"{before}{fmt(obj)}{after}" if obj else ""
return optional
@@ -385,6 +385,27 @@ def _parse_join(format_spec, default):
return apply_join
def _parse_map(format_spec, default):
key, _, format_spec = format_spec.partition(_SEPARATOR)
key = key[1:]
fmt = _build_format_func(format_spec, default)
def map_(obj):
if not obj or isinstance(obj, str):
return fmt(obj)
results = []
for item in obj:
if isinstance(item, dict):
value = item.get(key, ...)
results.append(default if value is ... else value)
else:
results.append(item)
return fmt(results)
return map_
def _parse_replace(format_spec, default):
old, new, format_spec = format_spec.split(_SEPARATOR, 2)
old = old[1:]
@@ -507,6 +528,7 @@ _FORMAT_SPECIFIERS = {
"D": _parse_datetime,
"J": _parse_join,
"L": _parse_maxlen,
"M": _parse_map,
"O": _parse_offset,
"R": _parse_replace,
"S": _parse_sort,