[formatter] implement 'X' format specifier (#5770)
This commit is contained in:
@@ -180,6 +180,16 @@ Format specifiers can be used for advanced formatting by using the options provi
|
|||||||
<td><code>{foo:L3/long/}</code></td>
|
<td><code>{foo:L3/long/}</code></td>
|
||||||
<td><code>long</code></td>
|
<td><code>long</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td rowspan="2"><code>X<maxlen>/<ext>/</code></td>
|
||||||
|
<td rowspan="2">Limit output to <code><maxlen></code> characters. Cut output and add <code><ext></code> to its end if its length exceeds <code><maxlen></code></td>
|
||||||
|
<td><code>{foo:X15/ .../}</code></td>
|
||||||
|
<td><code>Foo Bar</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>{foo:L6/ .../}</code></td>
|
||||||
|
<td><code>Fo ...</code></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>J<separator>/</code></td>
|
<td><code>J<separator>/</code></td>
|
||||||
<td>Concatenates elements of a list with <code><separator></code> using <a href="https://docs.python.org/3/library/stdtypes.html#str.join" rel="nofollow"><code>str.join()</code></a></td>
|
<td>Concatenates elements of a list with <code><separator></code> using <a href="https://docs.python.org/3/library/stdtypes.html#str.join" rel="nofollow"><code>str.join()</code></a></td>
|
||||||
|
|||||||
@@ -423,6 +423,19 @@ def _parse_sort(format_spec, default):
|
|||||||
return sort_asc
|
return sort_asc
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_limit(format_spec, default):
|
||||||
|
limit, hint, format_spec = format_spec.split(_SEPARATOR, 2)
|
||||||
|
limit = int(limit[1:])
|
||||||
|
limit_hint = limit - len(hint)
|
||||||
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
|
def apply_limit(obj):
|
||||||
|
if len(obj) > limit:
|
||||||
|
obj = obj[:limit_hint] + hint
|
||||||
|
return fmt(obj)
|
||||||
|
return apply_limit
|
||||||
|
|
||||||
|
|
||||||
def _default_format(format_spec, default):
|
def _default_format(format_spec, default):
|
||||||
def wrap(obj):
|
def wrap(obj):
|
||||||
return format(obj, format_spec)
|
return format(obj, format_spec)
|
||||||
@@ -469,9 +482,10 @@ _FORMAT_SPECIFIERS = {
|
|||||||
"[": _parse_slice,
|
"[": _parse_slice,
|
||||||
"C": _parse_conversion,
|
"C": _parse_conversion,
|
||||||
"D": _parse_datetime,
|
"D": _parse_datetime,
|
||||||
"L": _parse_maxlen,
|
|
||||||
"J": _parse_join,
|
"J": _parse_join,
|
||||||
|
"L": _parse_maxlen,
|
||||||
"O": _parse_offset,
|
"O": _parse_offset,
|
||||||
"R": _parse_replace,
|
"R": _parse_replace,
|
||||||
"S": _parse_sort,
|
"S": _parse_sort,
|
||||||
|
"X": _parse_limit,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,6 +272,13 @@ class TestFormatter(unittest.TestCase):
|
|||||||
self._run_test("{h:CHC}" , "Foo & Bar")
|
self._run_test("{h:CHC}" , "Foo & Bar")
|
||||||
self._run_test("{l:CSulc}", "A, b, c")
|
self._run_test("{l:CSulc}", "A, b, c")
|
||||||
|
|
||||||
|
def test_specifier_limit(self):
|
||||||
|
self._run_test("{a:X20/ */}", "hElLo wOrLd")
|
||||||
|
self._run_test("{a:X10/ */}", "hElLo wO *")
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
self._run_test("{a:Xfoo/ */}", "hello wo *")
|
||||||
|
|
||||||
def test_chain_special(self):
|
def test_chain_special(self):
|
||||||
# multiple replacements
|
# multiple replacements
|
||||||
self._run_test("{a:Rh/C/RE/e/RL/l/}", "Cello wOrld")
|
self._run_test("{a:Rh/C/RE/e/RL/l/}", "Cello wOrld")
|
||||||
|
|||||||
Reference in New Issue
Block a user