implement string literals in replacement fields
- either {_lit[foo]} or {'foo'}
- useful as alternative for empty metadata fields: {title|'no title'}
- due to using '_string.formatter_field_name_split()' to parse format
strings, using certain characters will result in an error: [].:!
This commit is contained in:
@@ -20,6 +20,7 @@ _CACHE = {}
|
|||||||
_CONVERSIONS = None
|
_CONVERSIONS = None
|
||||||
_GLOBALS = {
|
_GLOBALS = {
|
||||||
"_env": lambda: os.environ,
|
"_env": lambda: os.environ,
|
||||||
|
"_lit": lambda: _literal,
|
||||||
"_now": datetime.datetime.now,
|
"_now": datetime.datetime.now,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +220,10 @@ 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 = []
|
||||||
|
|
||||||
|
if first[0] == "'":
|
||||||
|
funcs.append(operator.itemgetter(first[1:-1]))
|
||||||
|
first = "_lit"
|
||||||
|
|
||||||
for is_attr, key in rest:
|
for is_attr, key in rest:
|
||||||
if is_attr:
|
if is_attr:
|
||||||
func = operator.attrgetter
|
func = operator.attrgetter
|
||||||
@@ -344,3 +349,15 @@ def _default_format(format_spec):
|
|||||||
def wrap(obj):
|
def wrap(obj):
|
||||||
return format(obj, format_spec)
|
return format(obj, format_spec)
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
class Literal():
|
||||||
|
# __getattr__, __getattribute__, and __class_getitem__
|
||||||
|
# are all slower than regular __getitem__
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __getitem__(key):
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
_literal = Literal()
|
||||||
|
|||||||
@@ -208,6 +208,22 @@ class TestFormatter(unittest.TestCase):
|
|||||||
self.assertRegex(out1, r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\d(\.\d+)?$")
|
self.assertRegex(out1, r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\d(\.\d+)?$")
|
||||||
self.assertNotEqual(out1, out2)
|
self.assertNotEqual(out1, out2)
|
||||||
|
|
||||||
|
def test_literals(self):
|
||||||
|
value = "foo"
|
||||||
|
|
||||||
|
self._run_test("{'foo'}" , value)
|
||||||
|
self._run_test("{'foo'!u}" , value.upper())
|
||||||
|
self._run_test("{'f00':R0/o/}" , value)
|
||||||
|
self._run_test("{'foobar'[:3]}", value)
|
||||||
|
self._run_test("{z|'foo'}" , value)
|
||||||
|
self._run_test("{z|''|'foo'}" , value)
|
||||||
|
|
||||||
|
self._run_test("{_lit[foo]}" , value)
|
||||||
|
self._run_test("{_lit[foo]!u}" , value.upper())
|
||||||
|
self._run_test("{_lit[f00]:R0/o/}" , value)
|
||||||
|
self._run_test("{_lit[foobar][:3]}", value)
|
||||||
|
self._run_test("{z|_lit[foo]}" , value)
|
||||||
|
|
||||||
def test_template(self):
|
def test_template(self):
|
||||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||||
path1 = os.path.join(tmpdirname, "tpl1")
|
path1 = os.path.join(tmpdirname, "tpl1")
|
||||||
|
|||||||
Reference in New Issue
Block a user