[formatter] allow evaluating f-string literals

by starting a format string with '\fF'.

This was technically already possible with '\fE',
but this makes it a bit more convenient.
This commit is contained in:
Mike Fährmann
2022-03-18 13:31:01 +01:00
parent 58e0b17211
commit cf44aba333
3 changed files with 23 additions and 1 deletions

View File

@@ -197,6 +197,11 @@ Starting a format string with '\f<Type> ' allows to set a different format strin
<td>A template file containing the actual format string</td>
<td><code>\fT ~/.templates/booru.txt</code></td>
</tr>
<tr>
<td align="center"><code>F</code></td>
<td>An <a href="https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals">f-string</a> literal</td>
<td><code>\fF '{title.strip()}' by {artist.capitalize()}</code></td>
</tr>
<tr>
<td align="center"><code>E</code></td>
<td>An arbitrary Python expression</td>

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2021 Mike Fährmann
# Copyright 2021-2022 Mike Fährmann
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -43,6 +43,8 @@ def parse(format_string, default=None):
cls = ExpressionFormatter
elif kind == "M":
cls = ModuleFormatter
elif kind == "F":
cls = FStringFormatter
formatter = _CACHE[key] = cls(format_string, default)
return formatter
@@ -206,6 +208,13 @@ class ModuleFormatter():
self.format_map = getattr(module, function_name)
class FStringFormatter():
"""Generate text by evaluaring an f-string literal"""
def __init__(self, fstring, default=None):
self.format_map = util.compile_expression("f'''" + fstring + "'''")
def parse_field_name(field_name):
first, rest = _string.formatter_field_name_split(field_name)
funcs = []

View File

@@ -232,6 +232,14 @@ class TestFormatter(unittest.TestCase):
self._run_test("\fE name * 2 + ' ' + a", "{}{} {}".format(
self.kwdict["name"], self.kwdict["name"], self.kwdict["a"]))
@unittest.skipIf(sys.hexversion < 0x3060000, "no fstring support")
def test_fstring(self):
self._run_test("\fF {a}", self.kwdict["a"])
self._run_test("\fF {name}{name} {a}", "{}{} {}".format(
self.kwdict["name"], self.kwdict["name"], self.kwdict["a"]))
self._run_test("\fF foo-'\"{a.upper()}\"'-bar",
"""foo-'"{}"'-bar""".format(self.kwdict["a"].upper()))
def test_module(self):
with tempfile.TemporaryDirectory() as tmpdirname:
path = os.path.join(tmpdirname, "testmod.py")