1
0
mirror of https://github.com/mikf/gallery-dl.git synced 2024-11-22 02:32:33 +01:00

[util] implement 'compile_filter()' (#5262)

https://github.com/mikf/gallery-dl/issues/5262#issuecomment-2477029728

allow (theoretically*) all filter expression statements
to be a list of individual filters

(*) except for 'filename' and 'directory' conditionals,
as dict keys cannot be lists
This commit is contained in:
Mike Fährmann 2024-11-14 21:59:32 +01:00
parent 0b99d9e6b9
commit 5bc3657c59
No known key found for this signature in database
GPG Key ID: 5680CA389D365A88
4 changed files with 20 additions and 7 deletions

View File

@ -598,7 +598,7 @@ class DownloadJob(Job):
skip_filter = cfg("skip-filter") skip_filter = cfg("skip-filter")
if skip_filter: if skip_filter:
self._skipftr = util.compile_expression(skip_filter) self._skipftr = util.compile_filter(skip_filter)
else: else:
self._skipftr = None self._skipftr = None
else: else:
@ -660,7 +660,7 @@ class DownloadJob(Job):
expr = options.get("filter") if options else None expr = options.get("filter") if options else None
if expr: if expr:
condition = util.compile_expression(expr) condition = util.compile_filter(expr)
for hook, callback in hooks.items(): for hook, callback in hooks.items():
self.hooks[hook].append(functools.partial( self.hooks[hook].append(functools.partial(
self._call_hook, callback, condition)) self._call_hook, callback, condition))

View File

@ -38,7 +38,7 @@ class PathFormat():
filename_fmt = extractor.filename_fmt filename_fmt = extractor.filename_fmt
elif isinstance(filename_fmt, dict): elif isinstance(filename_fmt, dict):
self.filename_conditions = [ self.filename_conditions = [
(util.compile_expression(expr), (util.compile_filter(expr),
formatter.parse(fmt, kwdefault).format_map) formatter.parse(fmt, kwdefault).format_map)
for expr, fmt in filename_fmt.items() if expr for expr, fmt in filename_fmt.items() if expr
] ]
@ -57,7 +57,7 @@ class PathFormat():
directory_fmt = extractor.directory_fmt directory_fmt = extractor.directory_fmt
elif isinstance(directory_fmt, dict): elif isinstance(directory_fmt, dict):
self.directory_conditions = [ self.directory_conditions = [
(util.compile_expression(expr), [ (util.compile_filter(expr), [
formatter.parse(fmt, kwdefault).format_map formatter.parse(fmt, kwdefault).format_map
for fmt in fmts for fmt in fmts
]) ])

View File

@ -734,6 +734,12 @@ def compile_expression_tryexcept(expr, name="<expr>", globals=None):
compile_expression = compile_expression_tryexcept compile_expression = compile_expression_tryexcept
def compile_filter(expr, name="<filter>", globals=None):
if not isinstance(expr, str):
expr = "(" + ") and (".join(expr) + ")"
return compile_expression(expr, name, globals)
def import_file(path): def import_file(path):
"""Import a Python module from a filesystem path""" """Import a Python module from a filesystem path"""
path, name = os.path.split(path) path, name = os.path.split(path)
@ -964,10 +970,8 @@ class FilterPredicate():
"""Predicate; True if evaluating the given expression returns True""" """Predicate; True if evaluating the given expression returns True"""
def __init__(self, expr, target="image"): def __init__(self, expr, target="image"):
if not isinstance(expr, str):
expr = "(" + ") and (".join(expr) + ")"
name = "<{} filter>".format(target) name = "<{} filter>".format(target)
self.expr = compile_expression(expr, name) self.expr = compile_filter(expr, name)
def __call__(self, _, kwdict): def __call__(self, _, kwdict):
try: try:

View File

@ -349,6 +349,15 @@ class TestCompileExpression(unittest.TestCase):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
expr({"a": 2}) expr({"a": 2})
def test_compile_filter(self):
expr = util.compile_filter("a + b * c")
self.assertEqual(expr({"a": 1, "b": 2, "c": 3}), 7)
self.assertEqual(expr({"a": 9, "b": 9, "c": 9}), 90)
expr = util.compile_filter(["a % 2 == 0", "b % 3 == 0", "c % 5 == 0"])
self.assertTrue(expr({"a": 4, "b": 6, "c": 10}))
self.assertFalse(expr({"a": 1, "b": 2, "c": 3}))
def test_custom_globals(self): def test_custom_globals(self):
value = {"v": "foobar"} value = {"v": "foobar"}
result = "8843d7f92416211de9ebb963ff4ce28125932878" result = "8843d7f92416211de9ebb963ff4ce28125932878"