[formatter] implement 'A' format specifier (#6036)
This commit is contained in:
@@ -202,6 +202,12 @@ Format specifiers can be used for advanced formatting by using the options provi
|
|||||||
<td><code>{foo:Ro/()/}</code></td>
|
<td><code>{foo:Ro/()/}</code></td>
|
||||||
<td><code>F()() Bar</code></td>
|
<td><code>F()() Bar</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>A<op><value>/</code></td>
|
||||||
|
<td>Apply arithmetic operation <code><op></code> (<code>+</code>, <code>-</code>, <code>*</code>) to the current value</td>
|
||||||
|
<td><code>{num:A+1/}</code></td>
|
||||||
|
<td><code>"2"</code></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>C<conversion(s)>/</code></td>
|
<td><code>C<conversion(s)>/</code></td>
|
||||||
<td>Apply <a href="#conversions">Conversions</a> to the current value</td>
|
<td>Apply <a href="#conversions">Conversions</a> to the current value</td>
|
||||||
|
|||||||
@@ -325,6 +325,23 @@ def _parse_slice(format_spec, default):
|
|||||||
return apply_slice
|
return apply_slice
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_arithmetic(format_spec, default):
|
||||||
|
op, _, format_spec = format_spec.partition(_SEPARATOR)
|
||||||
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
|
value = int(op[2:])
|
||||||
|
op = op[1]
|
||||||
|
|
||||||
|
if op == "+":
|
||||||
|
return lambda obj: fmt(obj + value)
|
||||||
|
if op == "-":
|
||||||
|
return lambda obj: fmt(obj - value)
|
||||||
|
if op == "*":
|
||||||
|
return lambda obj: fmt(obj * value)
|
||||||
|
|
||||||
|
return fmt
|
||||||
|
|
||||||
|
|
||||||
def _parse_conversion(format_spec, default):
|
def _parse_conversion(format_spec, default):
|
||||||
conversions, _, format_spec = format_spec.partition(_SEPARATOR)
|
conversions, _, format_spec = format_spec.partition(_SEPARATOR)
|
||||||
convs = [_CONVERSIONS[c] for c in conversions[1:]]
|
convs = [_CONVERSIONS[c] for c in conversions[1:]]
|
||||||
@@ -480,6 +497,7 @@ _CONVERSIONS = {
|
|||||||
_FORMAT_SPECIFIERS = {
|
_FORMAT_SPECIFIERS = {
|
||||||
"?": _parse_optional,
|
"?": _parse_optional,
|
||||||
"[": _parse_slice,
|
"[": _parse_slice,
|
||||||
|
"A": _parse_arithmetic,
|
||||||
"C": _parse_conversion,
|
"C": _parse_conversion,
|
||||||
"D": _parse_datetime,
|
"D": _parse_datetime,
|
||||||
"J": _parse_join,
|
"J": _parse_join,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class TestFormatter(unittest.TestCase):
|
|||||||
"b": "äöü",
|
"b": "äöü",
|
||||||
"j": "げんそうきょう",
|
"j": "げんそうきょう",
|
||||||
"d": {"a": "foo", "b": 0, "c": None},
|
"d": {"a": "foo", "b": 0, "c": None},
|
||||||
|
"i": 2,
|
||||||
"l": ["a", "b", "c"],
|
"l": ["a", "b", "c"],
|
||||||
"n": None,
|
"n": None,
|
||||||
"s": " \n\r\tSPACE ",
|
"s": " \n\r\tSPACE ",
|
||||||
@@ -267,6 +268,11 @@ class TestFormatter(unittest.TestCase):
|
|||||||
"{a:Sort-reverse}", # starts with 'S', contains 'r'
|
"{a:Sort-reverse}", # starts with 'S', contains 'r'
|
||||||
"['w', 'r', 'o', 'l', 'h', 'd', 'O', 'L', 'L', 'E', ' ']")
|
"['w', 'r', 'o', 'l', 'h', 'd', 'O', 'L', 'L', 'E', ' ']")
|
||||||
|
|
||||||
|
def test_specifier_arithmetic(self):
|
||||||
|
self._run_test("{i:A+1}", "3")
|
||||||
|
self._run_test("{i:A-1}", "1")
|
||||||
|
self._run_test("{i:A*3}", "6")
|
||||||
|
|
||||||
def test_specifier_conversions(self):
|
def test_specifier_conversions(self):
|
||||||
self._run_test("{a:Cl}" , "hello world")
|
self._run_test("{a:Cl}" , "hello world")
|
||||||
self._run_test("{h:CHC}" , "Foo & Bar")
|
self._run_test("{h:CHC}" , "Foo & Bar")
|
||||||
|
|||||||
Reference in New Issue
Block a user