summaryrefslogtreecommitdiffstats
path: root/gallery_dl/postprocessor
diff options
context:
space:
mode:
Diffstat (limited to 'gallery_dl/postprocessor')
-rw-r--r--gallery_dl/postprocessor/classify.py5
-rw-r--r--gallery_dl/postprocessor/common.py20
-rw-r--r--gallery_dl/postprocessor/compare.py19
-rw-r--r--gallery_dl/postprocessor/exec.py72
-rw-r--r--gallery_dl/postprocessor/metadata.py64
-rw-r--r--gallery_dl/postprocessor/mtime.py1
-rw-r--r--gallery_dl/postprocessor/ugoira.py5
-rw-r--r--gallery_dl/postprocessor/zip.py13
8 files changed, 106 insertions, 93 deletions
diff --git a/gallery_dl/postprocessor/classify.py b/gallery_dl/postprocessor/classify.py
index 0106903..eda092d 100644
--- a/gallery_dl/postprocessor/classify.py
+++ b/gallery_dl/postprocessor/classify.py
@@ -32,13 +32,16 @@ class ClassifyPP(PostProcessor):
for ext in exts
}
+ job.hooks["prepare"].append(self.prepare)
+ job.hooks["file"].append(self.move)
+
def prepare(self, pathfmt):
ext = pathfmt.extension
if ext in self.mapping:
# set initial paths to enable download skips
self._build_paths(pathfmt, self.mapping[ext])
- def run(self, pathfmt):
+ def move(self, pathfmt):
ext = pathfmt.extension
if ext in self.mapping:
# rebuild paths in case the filename extension changed
diff --git a/gallery_dl/postprocessor/common.py b/gallery_dl/postprocessor/common.py
index 64f978e..ef211e6 100644
--- a/gallery_dl/postprocessor/common.py
+++ b/gallery_dl/postprocessor/common.py
@@ -16,25 +16,5 @@ class PostProcessor():
name = self.__class__.__name__[:-2].lower()
self.log = job.get_logger("postprocessor." + name)
- @staticmethod
- def prepare(pathfmt):
- """Update file paths, etc."""
-
- @staticmethod
- def run(pathfmt):
- """Execute the postprocessor for a file"""
-
- @staticmethod
- def run_metadata(pathfmt):
- """Execute the postprocessor for a file"""
-
- @staticmethod
- def run_after(pathfmt):
- """Execute postprocessor after moving a file to its target location"""
-
- @staticmethod
- def run_final(pathfmt, status):
- """Postprocessor finalization after all files have been downloaded"""
-
def __repr__(self):
return self.__class__.__name__
diff --git a/gallery_dl/postprocessor/compare.py b/gallery_dl/postprocessor/compare.py
index 0d11844..ca416c9 100644
--- a/gallery_dl/postprocessor/compare.py
+++ b/gallery_dl/postprocessor/compare.py
@@ -16,22 +16,25 @@ class ComparePP(PostProcessor):
def __init__(self, job, options):
PostProcessor.__init__(self, job)
- if options.get("action") == "enumerate":
- self.run = self._run_enumerate
if options.get("shallow"):
- self.compare = self._compare_size
+ self._compare = self._compare_size
+ job.hooks["file"].append(
+ self.enumerate
+ if options.get("action") == "enumerate" else
+ self.compare
+ )
- def run(self, pathfmt):
+ def compare(self, pathfmt):
try:
- if self.compare(pathfmt.realpath, pathfmt.temppath):
+ if self._compare(pathfmt.realpath, pathfmt.temppath):
pathfmt.delete = True
except OSError:
pass
- def _run_enumerate(self, pathfmt):
+ def enumerate(self, pathfmt):
num = 1
try:
- while not self.compare(pathfmt.realpath, pathfmt.temppath):
+ while not self._compare(pathfmt.realpath, pathfmt.temppath):
pathfmt.prefix = str(num) + "."
pathfmt.set_extension(pathfmt.extension, False)
num += 1
@@ -39,7 +42,7 @@ class ComparePP(PostProcessor):
except OSError:
pass
- def compare(self, f1, f2):
+ def _compare(self, f1, f2):
return self._compare_size(f1, f2) and self._compare_content(f1, f2)
@staticmethod
diff --git a/gallery_dl/postprocessor/exec.py b/gallery_dl/postprocessor/exec.py
index cbe51ae..205f42e 100644
--- a/gallery_dl/postprocessor/exec.py
+++ b/gallery_dl/postprocessor/exec.py
@@ -24,54 +24,58 @@ class ExecPP(PostProcessor):
def __init__(self, job, options):
PostProcessor.__init__(self, job)
- args = options["command"]
- final = options.get("final", False)
+ if options.get("async", False):
+ self._exec = self._exec_async
+
+ args = options["command"]
if isinstance(args, str):
- if final:
- self._format = self._format_args_directory
- else:
- self._format = self._format_args_path
if "{}" not in args:
args += " {}"
self.args = args
- self.shell = True
+ execute = self.exec_string
else:
- self._format = self._format_args_list
self.args = [util.Formatter(arg) for arg in args]
- self.shell = False
-
- if final:
- self.run_after = PostProcessor.run_after
- else:
- self.run_final = PostProcessor.run_final
-
- if options.get("async", False):
- self._exec = self._exec_async
+ execute = self.exec_list
+
+ events = options.get("event")
+ if events is None:
+ events = ("after",)
+ if options.get("final"):
+ self.log.warning("'final' is deprecated, "
+ "use '\"event\": \"finalize\"' instead")
+ events = ("finalize",)
+ elif isinstance(events, str):
+ events = events.split(",")
+ for event in events:
+ job.hooks[event].append(execute)
+
+ def exec_list(self, pathfmt, status=None):
+ if status:
+ return
- def run_after(self, pathfmt):
- self._exec(self._format(pathfmt))
-
- def run_final(self, pathfmt, status):
- if status == 0:
- self._exec(self._format(pathfmt))
-
- def _format_args_path(self, pathfmt):
- return self.args.replace("{}", quote(pathfmt.realpath))
-
- def _format_args_directory(self, pathfmt):
- return self.args.replace("{}", quote(pathfmt.realdirectory))
-
- def _format_args_list(self, pathfmt):
kwdict = pathfmt.kwdict
kwdict["_directory"] = pathfmt.realdirectory
kwdict["_filename"] = pathfmt.filename
kwdict["_path"] = pathfmt.realpath
- return [arg.format_map(kwdict) for arg in self.args]
- def _exec(self, args):
+ args = [arg.format_map(kwdict) for arg in self.args]
+ self._exec(args, False)
+
+ def exec_string(self, pathfmt, status=None):
+ if status:
+ return
+
+ if status is None and pathfmt.realpath:
+ args = self.args.replace("{}", quote(pathfmt.realpath))
+ else:
+ args = self.args.replace("{}", quote(pathfmt.realdirectory))
+
+ self._exec(args, True)
+
+ def _exec(self, args, shell):
self.log.debug("Running '%s'", args)
- retcode = subprocess.Popen(args, shell=self.shell).wait()
+ retcode = subprocess.Popen(args, shell=shell).wait()
if retcode:
self.log.warning(
"Executing '%s' returned with non-zero exit status (%d)",
diff --git a/gallery_dl/postprocessor/metadata.py b/gallery_dl/postprocessor/metadata.py
index f88dde7..27f9c03 100644
--- a/gallery_dl/postprocessor/metadata.py
+++ b/gallery_dl/postprocessor/metadata.py
@@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
-"""Write metadata to JSON files"""
+"""Write metadata to external files"""
from .common import PostProcessor
from .. import util
@@ -24,7 +24,7 @@ class MetadataPP(PostProcessor):
cfmt = options.get("content-format") or options.get("format")
if isinstance(cfmt, list):
cfmt = "\n".join(cfmt) + "\n"
- self.contentfmt = util.Formatter(cfmt).format_map
+ self._content_fmt = util.Formatter(cfmt).format_map
ext = "txt"
elif mode == "tags":
self.write = self._write_tags
@@ -39,47 +39,68 @@ class MetadataPP(PostProcessor):
if directory:
self._directory = self._directory_custom
sep = os.sep + (os.altsep or "")
- self.metadir = directory.rstrip(sep) + os.sep
+ self._metadir = directory.rstrip(sep) + os.sep
+ filename = options.get("filename")
extfmt = options.get("extension-format")
- if extfmt:
+ if filename:
self._filename = self._filename_custom
- self.extfmt = util.Formatter(extfmt).format_map
+ self._filename_fmt = util.Formatter(filename).format_map
+ elif extfmt:
+ self._filename = self._filename_extfmt
+ self._extension_fmt = util.Formatter(extfmt).format_map
else:
self.extension = options.get("extension", ext)
- if options.get("bypost"):
- self.run_metadata, self.run = self.run, self.run_metadata
+ events = options.get("event")
+ if events is None:
+ events = ("file",)
+ if options.get("bypost"):
+ self.log.warning("'bypost' is deprecated, use '\"event\": "
+ "\"post\"' and 'filename' instead")
+ events = ("metadata",)
+ elif isinstance(events, str):
+ events = events.split(",")
+ for event in events:
+ job.hooks[event].append(self.run)
def run(self, pathfmt):
- path = self._directory(pathfmt) + self._filename(pathfmt)
- with open(path, "w", encoding="utf-8") as file:
- self.write(file, pathfmt.kwdict)
+ directory = self._directory(pathfmt)
+ path = directory + self._filename(pathfmt)
+
+ try:
+ with open(path, "w", encoding="utf-8") as fp:
+ self.write(fp, pathfmt.kwdict)
+ except FileNotFoundError:
+ os.makedirs(directory, exist_ok=True)
+ with open(path, "w", encoding="utf-8") as fp:
+ self.write(fp, pathfmt.kwdict)
def _directory(self, pathfmt):
return pathfmt.realdirectory
def _directory_custom(self, pathfmt):
- directory = os.path.join(pathfmt.realdirectory, self.metadir)
- os.makedirs(directory, exist_ok=True)
- return directory
+ return os.path.join(pathfmt.realdirectory, self._metadir)
def _filename(self, pathfmt):
- return pathfmt.filename + "." + self.extension
+ return (pathfmt.filename or "metadata") + "." + self.extension
def _filename_custom(self, pathfmt):
+ return self._filename_fmt(pathfmt.kwdict)
+
+ def _filename_extfmt(self, pathfmt):
kwdict = pathfmt.kwdict
ext = kwdict["extension"]
kwdict["extension"] = pathfmt.extension
- kwdict["extension"] = pathfmt.prefix + self.extfmt(kwdict)
+ kwdict["extension"] = pathfmt.prefix + self._extension_fmt(kwdict)
filename = pathfmt.build_filename()
kwdict["extension"] = ext
return filename
- def _write_custom(self, file, kwdict):
- file.write(self.contentfmt(kwdict))
+ def _write_custom(self, fp, kwdict):
+ fp.write(self._content_fmt(kwdict))
- def _write_tags(self, file, kwdict):
+ def _write_tags(self, fp, kwdict):
tags = kwdict.get("tags") or kwdict.get("tag_string")
if not tags:
@@ -91,11 +112,10 @@ class MetadataPP(PostProcessor):
taglist = tags.split(" ")
tags = taglist
- file.write("\n".join(tags))
- file.write("\n")
+ fp.write("\n".join(tags) + "\n")
- def _write_json(self, file, kwdict):
- util.dump_json(util.filter_dict(kwdict), file, self.ascii, self.indent)
+ def _write_json(self, fp, kwdict):
+ util.dump_json(util.filter_dict(kwdict), fp, self.ascii, self.indent)
__postprocessor__ = MetadataPP
diff --git a/gallery_dl/postprocessor/mtime.py b/gallery_dl/postprocessor/mtime.py
index b8a4988..e4c28ea 100644
--- a/gallery_dl/postprocessor/mtime.py
+++ b/gallery_dl/postprocessor/mtime.py
@@ -17,6 +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)
def run(self, pathfmt):
mtime = pathfmt.kwdict.get(self.key)
diff --git a/gallery_dl/postprocessor/ugoira.py b/gallery_dl/postprocessor/ugoira.py
index 1afba86..14eaa8d 100644
--- a/gallery_dl/postprocessor/ugoira.py
+++ b/gallery_dl/postprocessor/ugoira.py
@@ -49,6 +49,9 @@ class UgoiraPP(PostProcessor):
else:
self.prevent_odd = False
+ job.hooks["prepare"].append(self.prepare)
+ job.hooks["file"].append(self.convert)
+
def prepare(self, pathfmt):
self._frames = None
@@ -65,7 +68,7 @@ class UgoiraPP(PostProcessor):
if self.delete:
pathfmt.set_extension(self.extension)
- def run(self, pathfmt):
+ def convert(self, pathfmt):
if not self._frames:
return
diff --git a/gallery_dl/postprocessor/zip.py b/gallery_dl/postprocessor/zip.py
index a6e5bc3..e820280 100644
--- a/gallery_dl/postprocessor/zip.py
+++ b/gallery_dl/postprocessor/zip.py
@@ -38,12 +38,11 @@ class ZipPP(PostProcessor):
self.args = (self.path[:-1] + ext, "a",
self.COMPRESSION_ALGORITHMS[algorithm], True)
- if options.get("mode") == "safe":
- self.run = self._write_safe
- else:
- self.run = self._write
+ job.hooks["file"].append(
+ self.write_safe if options.get("mode") == "safe" else self.write)
+ job.hooks["finalize"].append(self.finalize)
- def _write(self, pathfmt, zfile=None):
+ def write(self, pathfmt, zfile=None):
# 'NameToInfo' is not officially documented, but it's available
# for all supported Python versions and using it directly is a lot
# faster than calling getinfo()
@@ -55,11 +54,11 @@ class ZipPP(PostProcessor):
zfile.write(pathfmt.temppath, pathfmt.filename)
pathfmt.delete = self.delete
- def _write_safe(self, pathfmt):
+ def write_safe(self, pathfmt):
with zipfile.ZipFile(*self.args) as zfile:
self._write(pathfmt, zfile)
- def run_final(self, pathfmt, status):
+ def finalize(self, pathfmt, status):
if self.zfile:
self.zfile.close()