From 5591a16cd73fa4a4c820e996686156056fc44565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Mon, 3 Nov 2025 13:22:39 +0100 Subject: [PATCH] [formatter] add 'Lb' format specifier - 'L' for bytes --- docs/formatting.md | 10 ++++++++++ gallery_dl/formatter.py | 23 +++++++++++++++-------- test/test_formatter.py | 13 +++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/docs/formatting.md b/docs/formatting.md index b81069cf..7adfee88 100644 --- a/docs/formatting.md +++ b/docs/formatting.md @@ -293,6 +293,16 @@ Format specifiers can be used for advanced formatting by using the options provi {foo:L3/long/} long + + Lb<maxlen>/<ext>/ + Same as L, but applies to the bytes() representation of a string in filesystem encoding + {foo_ja:Lb15/長い/} + フー・バー + + + {foo_ja:Lb8/長い/} + 長い + X<maxlen>/<ext>/ Limit output to <maxlen> characters. Cut output and add <ext> to its end if its length exceeds <maxlen> diff --git a/gallery_dl/formatter.py b/gallery_dl/formatter.py index 04f5cc8d..0f4f35ee 100644 --- a/gallery_dl/formatter.py +++ b/gallery_dl/formatter.py @@ -413,12 +413,20 @@ def _parse_conversion(format_spec, default): def _parse_maxlen(format_spec, default): maxlen, replacement, format_spec = format_spec.split(_SEPARATOR, 2) - maxlen = text.parse_int(maxlen[1:]) fmt = _build_format_func(format_spec, default) - def mlen(obj): - obj = fmt(obj) - return obj if len(obj) <= maxlen else replacement + if maxlen[1] == "b": + maxlen = text.parse_int(maxlen[2:]) + + def mlen(obj): + obj = fmt(obj) + return obj if len(obj.encode(_ENCODING)) <= maxlen else replacement + else: + maxlen = text.parse_int(maxlen[1:]) + + def mlen(obj): + obj = fmt(obj) + return obj if len(obj) <= maxlen else replacement return mlen @@ -501,13 +509,12 @@ def _parse_sort(format_spec, default): fmt = _build_format_func(format_spec, default) if "d" in args or "r" in args: - def sort_desc(obj): + def sort(obj): return fmt(sorted(obj, reverse=True)) - return sort_desc else: - def sort_asc(obj): + def sort(obj): return fmt(sorted(obj)) - return sort_asc + return sort def _parse_limit(format_spec, default): diff --git a/test/test_formatter.py b/test/test_formatter.py index b4603c06..0ad9461b 100644 --- a/test/test_formatter.py +++ b/test/test_formatter.py @@ -248,6 +248,19 @@ class TestFormatter(unittest.TestCase): self._run_test("{a:L50/foo/>51}", "foo") self._run_test("{a:Lab/foo/}", "foo") + def test_specifier_maxlen_bytes(self): + v = self.kwdict["a"] + self._run_test("{a:Lb5/foo/}" , "foo") + self._run_test("{a:Lb50/foo/}", v) + self._run_test("{a:Lb50/foo/>50}", " " * 39 + v) + self._run_test("{a:Lb50/foo/>51}", "foo") + self._run_test("{a:Lbab/foo/}", "foo") + + v = self.kwdict["j"] + self._run_test("{j:Lb5/foo/}" , "foo") + self._run_test("{j:Lb50/foo/}", v) + self._run_test("{j:Lbab/foo/}", "foo") + def test_specifier_join(self): self._run_test("{l:J}" , "abc") self._run_test("{l:J,}" , "a,b,c")