'Formatting only named fields with str.format_map()
I'm familiar with the usual ways to avoid missing fields causing problems when formatting a string. For example:
class SafeMap(dict):
def __missing__(self, key):
return f'{{{key}}}'
s = '{a}{b}'.format_map(SafeMap({'a': 1}))
print(s)
Result:
'1{b}'
However, I have a case where I want to apply a partial map like in the example, but the string also contains positional fields, for example:
s = '{a}{}{b}'.format_map(SafeMap({'a': 1}))
print(s)
Causes a ValueError: Format string contains positional fields due to there not being a value provided to replace the positional field between {a} and {b}.
My question: without manually parsing the entire string myself, is there a reliable way to perform a partial .format_map() on a string that leaves both unmatched named fields and positional fields alone?
(either all of them, or perhaps it only fills the ones that are not provided with a value - but I'm specifically after a case where it simply does not touch positional fields)
That is when running:
s = '{a}{}{b}'.format_map(SomeMagicClass({'a': 1}))
I need the result to be:
1{}{b}
And I need the solution to work reliably for any formattable string, not just this trivial case. If you know of a reliable solution that doesn't use a class, I'd be happy with that as well, the class-based solution is only presented as an example because it is a common solution.
Solution 1:[1]
What I ended up with myself:
from string import Formatter
def partial_format_map(s, d):
return ''.join(lit + (
Formatter().convert_field(
Formatter().format_field(self.globals[key], fmt), conv) if key in self.globals else
'' if key is None else
f'{{{key}{":" + fmt if fmt else ""}{":" + conv if conv else ""}}}'
) for lit, key, fmt, conv in Formatter().parse(value))
This works fairly well, but I'd be happy to accept a better answer - especially if someone sees fault with this solution.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Grismar |
