[formatter] support loading an f-string from a template file
"\fTF ~/path/to/file.txt"
This commit is contained in:
@@ -255,11 +255,6 @@ Starting a format string with '\f<Type> ' allows to set a different format strin
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
|
||||||
<td align="center"><code>T</code></td>
|
|
||||||
<td>A template file containing the actual format string</td>
|
|
||||||
<td><code>\fT ~/.templates/booru.txt</code></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><code>F</code></td>
|
<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>An <a href="https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals">f-string</a> literal</td>
|
||||||
@@ -270,6 +265,16 @@ Starting a format string with '\f<Type> ' allows to set a different format strin
|
|||||||
<td>An arbitrary Python expression</td>
|
<td>An arbitrary Python expression</td>
|
||||||
<td><code>\fE title.upper().replace(' ', '-')</code></td>
|
<td><code>\fE title.upper().replace(' ', '-')</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><code>T</code></td>
|
||||||
|
<td>Path to a template file containing a regular format string</td>
|
||||||
|
<td><code>\fT ~/.templates/booru.txt</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><code>TF</code></td>
|
||||||
|
<td>Path to a template file containing an <a href="https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals">f-string</a> literal</td>
|
||||||
|
<td><code>\fTF ~/.templates/fstr.txt</code></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><code>M</code></td>
|
<td align="center"><code>M</code></td>
|
||||||
<td>Path or name of a Python module
|
<td>Path or name of a Python module
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ def parse(format_string, default=NONE, fmt=format):
|
|||||||
|
|
||||||
if kind == "T":
|
if kind == "T":
|
||||||
cls = TemplateFormatter
|
cls = TemplateFormatter
|
||||||
|
elif kind == "TF":
|
||||||
|
cls = TemplateFStringFormatter
|
||||||
elif kind == "E":
|
elif kind == "E":
|
||||||
cls = ExpressionFormatter
|
cls = ExpressionFormatter
|
||||||
elif kind == "M":
|
elif kind == "M":
|
||||||
@@ -197,15 +199,6 @@ class StringFormatter():
|
|||||||
return lambda obj: fmt(conversion(obj))
|
return lambda obj: fmt(conversion(obj))
|
||||||
|
|
||||||
|
|
||||||
class TemplateFormatter(StringFormatter):
|
|
||||||
"""Read format_string from file"""
|
|
||||||
|
|
||||||
def __init__(self, path, default=NONE, fmt=format):
|
|
||||||
with open(util.expand_path(path)) as fp:
|
|
||||||
format_string = fp.read()
|
|
||||||
StringFormatter.__init__(self, format_string, default, fmt)
|
|
||||||
|
|
||||||
|
|
||||||
class ExpressionFormatter():
|
class ExpressionFormatter():
|
||||||
"""Generate text by evaluating a Python expression"""
|
"""Generate text by evaluating a Python expression"""
|
||||||
|
|
||||||
@@ -229,6 +222,24 @@ class FStringFormatter():
|
|||||||
self.format_map = util.compile_expression('f"""' + fstring + '"""')
|
self.format_map = util.compile_expression('f"""' + fstring + '"""')
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateFormatter(StringFormatter):
|
||||||
|
"""Read format_string from file"""
|
||||||
|
|
||||||
|
def __init__(self, path, default=NONE, fmt=format):
|
||||||
|
with open(util.expand_path(path)) as fp:
|
||||||
|
format_string = fp.read()
|
||||||
|
StringFormatter.__init__(self, format_string, default, fmt)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateFStringFormatter(FStringFormatter):
|
||||||
|
"""Read f-string from file"""
|
||||||
|
|
||||||
|
def __init__(self, path, default=NONE, fmt=format):
|
||||||
|
with open(util.expand_path(path)) as fp:
|
||||||
|
format_string = fp.read()
|
||||||
|
FStringFormatter.__init__(self, format_string, default, fmt)
|
||||||
|
|
||||||
|
|
||||||
def parse_field_name(field_name):
|
def parse_field_name(field_name):
|
||||||
first, rest = _string.formatter_field_name_split(field_name)
|
first, rest = _string.formatter_field_name_split(field_name)
|
||||||
funcs = []
|
funcs = []
|
||||||
|
|||||||
@@ -348,6 +348,27 @@ class TestFormatter(unittest.TestCase):
|
|||||||
self._run_test("\fF foo-'\"{a.upper()}\"'-bar",
|
self._run_test("\fF foo-'\"{a.upper()}\"'-bar",
|
||||||
"""foo-'"{}"'-bar""".format(self.kwdict["a"].upper()))
|
"""foo-'"{}"'-bar""".format(self.kwdict["a"].upper()))
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x3060000, "no fstring support")
|
||||||
|
def test_template_fstring(self):
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||||
|
path1 = os.path.join(tmpdirname, "tpl1")
|
||||||
|
path2 = os.path.join(tmpdirname, "tpl2")
|
||||||
|
|
||||||
|
with open(path1, "w") as fp:
|
||||||
|
fp.write("{a}")
|
||||||
|
fmt1 = formatter.parse("\fTF " + path1)
|
||||||
|
|
||||||
|
with open(path2, "w") as fp:
|
||||||
|
fp.write("foo-'\"{a.upper()}\"'-bar")
|
||||||
|
fmt2 = formatter.parse("\fTF " + path2)
|
||||||
|
|
||||||
|
self.assertEqual(fmt1.format_map(self.kwdict), self.kwdict["a"])
|
||||||
|
self.assertEqual(fmt2.format_map(self.kwdict),
|
||||||
|
"""foo-'"{}"'-bar""".format(self.kwdict["a"].upper()))
|
||||||
|
|
||||||
|
with self.assertRaises(OSError):
|
||||||
|
formatter.parse("\fTF /")
|
||||||
|
|
||||||
def test_module(self):
|
def test_module(self):
|
||||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||||
path = os.path.join(tmpdirname, "testmod.py")
|
path = os.path.join(tmpdirname, "testmod.py")
|
||||||
|
|||||||
Reference in New Issue
Block a user