Skip to content

Commit

Permalink
support 'filter' option for post processors (#1460)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikf committed Jun 4, 2021
1 parent 4cf4043 commit 3cbbefd
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 19 deletions.
6 changes: 6 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2936,11 +2936,17 @@ Example
"name" : "zip",
"compression": "store",
"extension" : "cbz",
"filter" : "extension not in ('zip', 'rar')",
"whitelist" : ["mangadex", "exhentai", "nhentai"]
}
Description
An ``object`` containing a ``"name"`` attribute specifying the
post-processor type, as well as any of its `options <Postprocessor Options_>`__.

It is possible to set a ``"filter"`` expression similar to
`image-filter <extractor.*.image-filter_>`_ to only run a post-processor
condionally.

It is also possible set a ``"whitelist"`` or ``"blacklist"`` to
only enable or disable a post-processor for the specified
extractor categories.
Expand Down
18 changes: 18 additions & 0 deletions gallery_dl/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import errno
import logging
import operator
import functools
import collections
from . import extractor, downloader, postprocessor
from . import config, text, util, output, exception
Expand Down Expand Up @@ -459,6 +460,23 @@ def initialize(self, kwdict=None):
for callback in self.hooks["init"]:
callback(pathfmt)

def register_hooks(self, hooks, options=None):
expr = options.get("filter") if options else None

if expr:
condition = util.compile_expression(expr)
for hook, callback in hooks.items():
self.hooks[hook].append(functools.partial(
self._call_hook, callback, condition))
else:
for hook, callback in hooks.items():
self.hooks[hook].append(callback)

@staticmethod
def _call_hook(callback, condition, pathfmt):
if condition(pathfmt.kwdict):
callback(pathfmt)

def _build_blacklist(self):
wlist = self.extractor.config("whitelist")
if wlist is not None:
Expand Down
7 changes: 3 additions & 4 deletions gallery_dl/postprocessor/classify.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# Copyright 2018-2020 Mike Fährmann
# Copyright 2018-2021 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
Expand Down Expand Up @@ -31,9 +31,8 @@ def __init__(self, job, options):
for directory, exts in mapping.items()
for ext in exts
}

job.hooks["prepare"].append(self.prepare)
job.hooks["file"].append(self.move)
job.register_hooks(
{"prepare": self.prepare, "file": self.move}, options)

def prepare(self, pathfmt):
ext = pathfmt.extension
Expand Down
7 changes: 4 additions & 3 deletions gallery_dl/postprocessor/compare.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# Copyright 2020 Mike Fährmann
# Copyright 2020-2021 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
Expand All @@ -18,11 +18,12 @@ def __init__(self, job, options):
PostProcessor.__init__(self, job)
if options.get("shallow"):
self._compare = self._compare_size
job.hooks["file"].append(

job.register_hooks({"file": (
self.enumerate
if options.get("action") == "enumerate" else
self.compare
)
)}, options)

def compare(self, pathfmt):
try:
Expand Down
3 changes: 1 addition & 2 deletions gallery_dl/postprocessor/exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ def __init__(self, job, options):
events = ("after",)
elif isinstance(events, str):
events = events.split(",")
for event in events:
job.hooks[event].append(execute)
job.register_hooks({event: execute for event in events}, options)

def exec_list(self, pathfmt, status=None):
if status:
Expand Down
3 changes: 1 addition & 2 deletions gallery_dl/postprocessor/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ def __init__(self, job, options):
events = ("file",)
elif isinstance(events, str):
events = events.split(",")
for event in events:
job.hooks[event].append(self.run)
job.register_hooks({event: self.run for event in events}, options)

def run(self, pathfmt):
directory = self._directory(pathfmt)
Expand Down
4 changes: 2 additions & 2 deletions gallery_dl/postprocessor/mtime.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# Copyright 2019-2020 Mike Fährmann
# Copyright 2019-2021 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
Expand All @@ -17,7 +17,7 @@ class MtimePP(PostProcessor):
def __init__(self, job, options):
PostProcessor.__init__(self, job)
self.key = options.get("key", "date")
job.hooks["file"].append(self.run)
job.register_hooks({"file": self.run}, options)

def run(self, pathfmt):
mtime = pathfmt.kwdict.get(self.key)
Expand Down
4 changes: 2 additions & 2 deletions gallery_dl/postprocessor/ugoira.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ def __init__(self, job, options):
else:
self.prevent_odd = False

job.hooks["prepare"].append(self.prepare)
job.hooks["file"].append(self.convert)
job.register_hooks(
{"prepare": self.prepare, "file": self.convert}, options)

def prepare(self, pathfmt):
self._frames = None
Expand Down
10 changes: 6 additions & 4 deletions gallery_dl/postprocessor/zip.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# Copyright 2018-2020 Mike Fährmann
# Copyright 2018-2021 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
Expand Down Expand Up @@ -38,9 +38,11 @@ def __init__(self, job, options):
self.args = (self.path[:-1] + ext, "a",
self.COMPRESSION_ALGORITHMS[algorithm], True)

job.hooks["file"].append(
self.write_safe if options.get("mode") == "safe" else self.write)
job.hooks["finalize"].append(self.finalize)
job.register_hooks({
"file":
self.write_safe if options.get("mode") == "safe" else self.write,
"finalize": self.finalize,
}, options)

def write(self, pathfmt, zfile=None):
# 'NameToInfo' is not officially documented, but it's available
Expand Down
4 changes: 4 additions & 0 deletions test/test_postprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def __init__(self):
self.get_logger = logging.getLogger
self.hooks = collections.defaultdict(list)

def register_hooks(self, hooks, options):
for hook, callback in hooks.items():
self.hooks[hook].append(callback)


class TestPostprocessorModule(unittest.TestCase):

Expand Down

0 comments on commit 3cbbefd

Please sign in to comment.