diff options
Diffstat (limited to 'test/test_formatter.py')
| -rw-r--r-- | test/test_formatter.py | 159 |
1 files changed, 141 insertions, 18 deletions
diff --git a/test/test_formatter.py b/test/test_formatter.py index 646f179..3305983 100644 --- a/test/test_formatter.py +++ b/test/test_formatter.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright 2021-2023 Mike Fährmann +# Copyright 2021-2025 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 @@ -15,11 +15,19 @@ 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 +except ImportError: + jinja2 = None class TestFormatter(unittest.TestCase): + def tearDown(self): + config.clear() + kwdict = { "a": "hElLo wOrLd", "b": "äöü", @@ -27,16 +35,23 @@ class TestFormatter(unittest.TestCase): "d": {"a": "foo", "b": 0, "c": None}, "i": 2, "l": ["a", "b", "c"], + "L": [ + {"name": "John Doe" , "age": 42, "email": "jd@example.org"}, + {"name": "Jane Smith" , "age": 24, "email": None}, + {"name": "Max Mustermann", "age": False}, + ], "n": None, "s": " \n\r\tSPACE ", + "S": " \n\r\tS P A\tC\nE ", "h": "<p>foo </p> & bar <p> </p>", "u": "'< / >'", "t": 1262304000, - "ds": "2010-01-01T01:00:00+0100", + "ds": "2010-01-01T01:00:00+01:00", "dt": datetime.datetime(2010, 1, 1), "dt_dst": datetime.datetime(2010, 6, 1), "i_str": "12345", "f_str": "12.45", + "lang": "en", "name": "Name", "title1": "Title", "title2": "", @@ -50,6 +65,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{a!c}", "Hello world") self._run_test("{a!C}", "Hello World") self._run_test("{s!t}", "SPACE") + self._run_test("{S!t}", "S P A\tC\nE") self._run_test("{a!U}", self.kwdict["a"]) self._run_test("{u!U}", "'< / >'") self._run_test("{a!H}", self.kwdict["a"]) @@ -65,13 +81,22 @@ class TestFormatter(unittest.TestCase): self._run_test("{n!S}", "") self._run_test("{t!d}", datetime.datetime(2010, 1, 1)) self._run_test("{t!d:%Y-%m-%d}", "2010-01-01") + self._run_test("{t!D}" , datetime.datetime(2010, 1, 1)) + self._run_test("{ds!D}", datetime.datetime(2010, 1, 1)) + self._run_test("{dt!D}", datetime.datetime(2010, 1, 1)) + self._run_test("{t!D:%Y-%m-%d}", "2010-01-01") self._run_test("{dt!T}", "1262304000") self._run_test("{l!j}", '["a","b","c"]') self._run_test("{dt!j}", '"2010-01-01 00:00:00"') self._run_test("{a!g}", "hello-world") - self._run_test("{a!L}", 11) - self._run_test("{l!L}", 3) - self._run_test("{d!L}", 3) + self._run_test("{lang!L}", "English") + self._run_test("{'fr'!L}", "French") + self._run_test("{a!L}", None) + self._run_test("{a!n}", 11) + self._run_test("{l!n}", 3) + self._run_test("{d!n}", 3) + self._run_test("{s!W}", "SPACE") + self._run_test("{S!W}", "S P A C E") self._run_test("{i_str!i}", 12345) self._run_test("{i_str!f}", 12345.0) self._run_test("{f_str!f}", 12.45) @@ -201,7 +226,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{j:[b:]}" , v) self._run_test("{j:[b::]}" , v) - def test_maxlen(self): + def test_specifier_maxlen(self): v = self.kwdict["a"] self._run_test("{a:L5/foo/}" , "foo") self._run_test("{a:L50/foo/}", v) @@ -209,7 +234,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{a:L50/foo/>51}", "foo") self._run_test("{a:Lab/foo/}", "foo") - def test_join(self): + def test_specifier_join(self): self._run_test("{l:J}" , "abc") self._run_test("{l:J,}" , "a,b,c") self._run_test("{l:J,/}" , "a,b,c") @@ -221,7 +246,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{a:J/}" , self.kwdict["a"]) self._run_test("{a:J, /}" , self.kwdict["a"]) - def test_replace(self): + def test_specifier_replace(self): self._run_test("{a:Rh/C/}" , "CElLo wOrLd") self._run_test("{a!l:Rh/C/}", "Cello world") self._run_test("{a!u:Rh/C/}", "HELLO WORLD") @@ -230,12 +255,12 @@ class TestFormatter(unittest.TestCase): self._run_test("{a!l:Rl//}" , "heo word") self._run_test("{name:Rame/othing/}", "Nothing") - def test_datetime(self): + def test_specifier_datetime(self): self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z}", "2010-01-01 00:00:00") - self._run_test("{ds:D%Y}", "2010-01-01T01:00:00+0100") + self._run_test("{ds:D%Y}", "2010-01-01T01:00:00+01:00") self._run_test("{l:D%Y}", "None") - def test_offset(self): + def test_specifier_offset(self): self._run_test("{dt:O 01:00}", "2010-01-01 01:00:00") self._run_test("{dt:O+02:00}", "2010-01-01 02:00:00") self._run_test("{dt:O-03:45}", "2009-12-31 20:15:00") @@ -246,7 +271,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z/O1}", "2010-01-01 01:00:00") self._run_test("{t!d:O2}", "2010-01-01 02:00:00") - def test_offset_local(self): + def test_specifier_offset_local(self): ts = self.kwdict["dt"].replace( tzinfo=datetime.timezone.utc).timestamp() offset = time.localtime(ts).tm_gmtoff @@ -261,7 +286,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{dt_dst:O}", str(dt)) self._run_test("{dt_dst:Olocal}", str(dt)) - def test_sort(self): + def test_specifier_sort(self): self._run_test("{l:S}" , "['a', 'b', 'c']") self._run_test("{l:Sa}", "['a', 'b', 'c']") self._run_test("{l:Sd}", "['c', 'b', 'a']") @@ -293,6 +318,19 @@ class TestFormatter(unittest.TestCase): with self.assertRaises(ValueError): self._run_test("{a:Xfoo/ */}", "hello wo *") + def test_specifier_map(self): + self._run_test("{L:Mname/}" , + "['John Doe', 'Jane Smith', 'Max Mustermann']") + self._run_test("{L:Mage/}" , + "[42, 24, False]") + + self._run_test("{a:Mname}", self.kwdict["a"]) + self._run_test("{n:Mname}", "None") + self._run_test("{title4:Mname}", "0") + + with self.assertRaises(ValueError): + self._run_test("{t:Mname", "") + def test_chain_special(self): # multiple replacements self._run_test("{a:Rh/C/RE/e/RL/l/}", "Cello wOrld") @@ -314,6 +352,9 @@ class TestFormatter(unittest.TestCase): # sort and join self._run_test("{a:S/J}", " ELLOdhlorw") + # map and join + self._run_test("{L:Mname/J-}", "John Doe-Jane Smith-Max Mustermann") + def test_separator(self): orig_separator = formatter._SEPARATOR try: @@ -420,7 +461,6 @@ 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( @@ -428,7 +468,6 @@ class TestFormatter(unittest.TestCase): self._run_test("\fF foo-'\"{a.upper()}\"'-bar", """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") @@ -449,6 +488,90 @@ class TestFormatter(unittest.TestCase): with self.assertRaises(OSError): formatter.parse("\fTF /") + @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"])) + self._run_test("\fJ foo-'\"{{a | upper}}\"'-bar", + """foo-'"{}"'-bar""".format(self.kwdict["a"].upper())) + + @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") + + with open(path1, "w") as fp: + fp.write("{{a}}") + fmt1 = formatter.parse("\fTJ " + path1) + + with open(path2, "w") as fp: + fp.write("foo-'\"{{a | upper}}\"'-bar") + fmt2 = formatter.parse("\fTJ " + 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("\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") @@ -488,10 +611,10 @@ def noarg(): fmt4 = formatter.parse("\fM " + path + ":lengths") self.assertEqual(fmt1.format_map(self.kwdict), "'Title' by Name") - self.assertEqual(fmt2.format_map(self.kwdict), "136") + self.assertEqual(fmt2.format_map(self.kwdict), "168") self.assertEqual(fmt3.format_map(self.kwdict), "'Title' by Name") - self.assertEqual(fmt4.format_map(self.kwdict), "136") + self.assertEqual(fmt4.format_map(self.kwdict), "168") with self.assertRaises(TypeError): self.assertEqual(fmt0.format_map(self.kwdict), "") |
