[formatter/jinja] add support for options (#1390)

- custom filters
- custom tests
- policies
- Environment.__init__() arguments
This commit is contained in:
Mike Fährmann
2025-07-21 22:14:03 +02:00
parent f0de034889
commit ea61f432f2
2 changed files with 85 additions and 3 deletions

View File

@@ -211,14 +211,38 @@ class FStringFormatter():
self.format_map = util.compile_expression(f'f"""{fstring}"""')
def _init_jinja():
import jinja2
from . import config
if opts := config.get((), "jinja"):
JinjaFormatter.env = env = jinja2.Environment(
**opts.get("environment") or {})
else:
JinjaFormatter.env = jinja2.Environment()
return
if policies := opts.get("policies"):
env.policies.update(policies)
if path := opts.get("filters"):
module = util.import_file(path).__dict__
env.filters.update(
module["__filters__"] if "__filters__" in module else module)
if path := opts.get("tests"):
module = util.import_file(path).__dict__
env.tests.update(
module["__tests__"] if "__tests__" in module else module)
class JinjaFormatter():
"""Generate text by evaluating a Jinja template string"""
env = None
def __init__(self, source, default=NONE, fmt=None):
if self.env is None:
import jinja2
JinjaFormatter.env = jinja2.Environment()
_init_jinja()
self.format_map = self.env.from_string(source).render

View File

@@ -15,7 +15,7 @@ import datetime
import tempfile
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from gallery_dl import formatter, text, util # noqa E402
from gallery_dl import formatter, text, util, config # noqa E402
try:
import jinja2
@@ -25,6 +25,9 @@ except ImportError:
class TestFormatter(unittest.TestCase):
def tearDown(self):
config.clear()
kwdict = {
"a": "hElLo wOrLd",
"b": "äöü",
@@ -487,6 +490,8 @@ class TestFormatter(unittest.TestCase):
@unittest.skipIf(jinja2 is None, "no jinja2")
def test_jinja(self):
formatter.JinjaFormatter.env = None
self._run_test("\fJ {{a}}", self.kwdict["a"])
self._run_test("\fJ {{name}}{{name}} {{a}}", "{}{} {}".format(
self.kwdict["name"], self.kwdict["name"], self.kwdict["a"]))
@@ -495,6 +500,8 @@ class TestFormatter(unittest.TestCase):
@unittest.skipIf(jinja2 is None, "no jinja2")
def test_template_jinja(self):
formatter.JinjaFormatter.env = None
with tempfile.TemporaryDirectory() as tmpdirname:
path1 = os.path.join(tmpdirname, "tpl1")
path2 = os.path.join(tmpdirname, "tpl2")
@@ -514,6 +521,57 @@ class TestFormatter(unittest.TestCase):
with self.assertRaises(OSError):
formatter.parse("\fTJ /")
@unittest.skipIf(jinja2 is None, "no jinja2")
def test_template_jinja_opts(self):
formatter.JinjaFormatter.env = None
with tempfile.TemporaryDirectory() as tmpdirname:
path_filters = os.path.join(tmpdirname, "jinja_filters.py")
path_template = os.path.join(tmpdirname, "jinja_template.txt")
config.set((), "jinja", {
"environment": {
"variable_start_string": "(((",
"variable_end_string" : ")))",
"keep_trailing_newline": True,
},
"filters": path_filters,
})
with open(path_filters, "w") as fp:
fp.write(r"""
import re
def datetime_format(value, format="%H:%M %d-%m-%y"):
return value.strftime(format)
def sanitize(value):
return re.sub(r"\s+", " ", value.strip())
__filters__ = {
"dt_fmt": datetime_format,
"sanitize_whitespace": sanitize,
}
""")
with open(path_template, "w") as fp:
fp.write("""\
Present Day is ((( dt | dt_fmt("%B %d, %Y") )))
Present Time is ((( dt | dt_fmt("%H:%M:%S") )))
Hello ((( s | sanitize_whitespace ))).
I hope there is enough "(((S|sanitize_whitespace)))" for you.
""")
fmt = formatter.parse("\fTJ " + path_template)
self.assertEqual(fmt.format_map(self.kwdict), """\
Present Day is January 01, 2010
Present Time is 00:00:00
Hello SPACE.
I hope there is enough "S P A C E" for you.
""")
def test_module(self):
with tempfile.TemporaryDirectory() as tmpdirname:
path = os.path.join(tmpdirname, "testmod.py")