From 0038a8c1a43eadad7f2d95dfc0856c805d5b8377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Mon, 27 Sep 2021 19:24:02 +0200 Subject: [PATCH] implement a way to specify 'extended' format strings Starting a format string with '\f ' allows to set a different format string type than the default. Available ones are - T: A template file containing the actual format string "\fT ~/.templates/booru.txt - E: An arbitrary Python expression "\fE title.upper().replace(' ', '-')" - M: Name of a Python module followed by a function name inside it. This function gets called with the current metadata dict as argument and should return a string. "\fM my_module:generate_text" '\f' was chosen since it is highly unlikely that a regular format string would start with it, but that character could be changed to for example '\\' or '/' etc. --- gallery_dl/formatter.py | 43 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/gallery_dl/formatter.py b/gallery_dl/formatter.py index b13b033d..654e5d0d 100644 --- a/gallery_dl/formatter.py +++ b/gallery_dl/formatter.py @@ -24,8 +24,22 @@ def parse(format_string, default=None): try: return _CACHE[key] except KeyError: - formatter = _CACHE[key] = StringFormatter(format_string, default) - return formatter + pass + + cls = StringFormatter + if format_string.startswith("\f"): + kind, _, format_string = format_string.partition(" ") + kind = kind[1:] + + if kind == "T": + cls = TemplateFormatter + elif kind == "E": + cls = ExpressionFormatter + elif kind == "M": + cls = ModuleFormatter + + formatter = _CACHE[key] = cls(format_string, default) + return formatter class StringFormatter(): @@ -148,6 +162,31 @@ class StringFormatter(): return wrap +class TemplateFormatter(StringFormatter): + """Read format_string from file""" + + def __init__(self, path, default=None): + with open(util.expand_path(path)) as fp: + format_string = fp.read() + StringFormatter.__init__(self, format_string, default) + + +class ExpressionFormatter(): + """Generate text by evaluating a Python expression""" + + def __init__(self, expression, default=None): + self.format_map = util.compile_expression(expression) + + +class ModuleFormatter(): + """Generate text by calling an external function""" + + def __init__(self, function_spec, default=None): + module_name, _, function_name = function_spec.partition(":") + module = __import__(module_name) + self.format_map = getattr(module, function_name) + + def parse_field_name(field_name): first, rest = _string.formatter_field_name_split(field_name) funcs = []