diff --git a/docs/configuration.rst b/docs/configuration.rst index 365bdd05..ffc3b53d 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -1485,6 +1485,16 @@ Description Select how to write metadata. to a file's metadata dictionary =========== ===== +metadata.directory +------------------ +=========== ===== +Type ``string`` +Default ``"."`` +Example ``"metadata"`` +Description Directory where metadata files are stored in relative to the + current target location for file downloads. +=========== ===== + metadata.extension ------------------ =========== ===== diff --git a/gallery_dl/postprocessor/metadata.py b/gallery_dl/postprocessor/metadata.py index bc264845..aa50dfd8 100644 --- a/gallery_dl/postprocessor/metadata.py +++ b/gallery_dl/postprocessor/metadata.py @@ -10,6 +10,7 @@ from .common import PostProcessor from .. import util +import os class MetadataPP(PostProcessor): @@ -32,32 +33,46 @@ class MetadataPP(PostProcessor): self.ascii = options.get("ascii", False) ext = "json" + directory = options.get("directory") + if directory: + self._directory = self._directory_custom + sep = os.sep + (os.altsep or "") + self.metadir = directory.rstrip(sep) + os.sep + extfmt = options.get("extension-format") if extfmt: - self.path = self._path_format + self._filename = self._filename_custom self.extfmt = util.Formatter(extfmt).format_map else: - self.path = self._path_append self.extension = options.get("extension", ext) if options.get("bypost"): self.run_metadata, self.run = self.run, self.run_metadata def run(self, pathfmt): - with open(self.path(pathfmt), "w", encoding="utf-8") as file: + path = self._directory(pathfmt) + self._filename(pathfmt) + with open(path, "w", encoding="utf-8") as file: self.write(file, pathfmt.kwdict) - def _path_append(self, pathfmt): - return "{}.{}".format(pathfmt.realpath, self.extension) + def _directory(self, pathfmt): + return pathfmt.realdirectory - def _path_format(self, pathfmt): + def _directory_custom(self, pathfmt): + directory = os.path.join(pathfmt.realdirectory, self.metadir) + os.makedirs(directory, exist_ok=True) + return directory + + def _filename(self, pathfmt): + return pathfmt.filename + "." + self.extension + + def _filename_custom(self, pathfmt): kwdict = pathfmt.kwdict ext = kwdict["extension"] kwdict["extension"] = pathfmt.extension kwdict["extension"] = pathfmt.prefix + self.extfmt(kwdict) - path = pathfmt.realdirectory + pathfmt.build_filename() + filename = pathfmt.build_filename() kwdict["extension"] = ext - return path + return filename def _write_custom(self, file, kwdict): file.write(self.contentfmt(kwdict)) diff --git a/test/test_postprocessor.py b/test/test_postprocessor.py index 17f82c94..629b0d7b 100644 --- a/test/test_postprocessor.py +++ b/test/test_postprocessor.py @@ -7,6 +7,7 @@ # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. +import os import os.path import zipfile import tempfile @@ -156,7 +157,6 @@ class MetadataTest(BasePostprocessorTest): "_private" : "world", }) - self.assertEqual(pp.path , pp._path_append) self.assertEqual(pp.write , pp._write_json) self.assertEqual(pp.ascii , True) self.assertEqual(pp.indent , 2) @@ -242,7 +242,7 @@ class MetadataTest(BasePostprocessorTest): "extension-format": "json", }) - self.assertEqual(pp.path, pp._path_format) + self.assertEqual(pp._filename, pp._filename_custom) with patch("builtins.open", mock_open()) as m: pp.prepare(self.pathfmt) @@ -264,6 +264,31 @@ class MetadataTest(BasePostprocessorTest): path = self.pathfmt.realdirectory + "file.2.EXT-data:tESt" m.assert_called_once_with(path, "w", encoding="utf-8") + def test_metadata_directory(self): + pp = self._create({ + "directory": "metadata", + }) + + with patch("builtins.open", mock_open()) as m: + pp.prepare(self.pathfmt) + pp.run(self.pathfmt) + + path = self.pathfmt.realdirectory + "metadata/file.ext.json" + m.assert_called_once_with(path, "w", encoding="utf-8") + + def test_metadata_directory_2(self): + pp = self._create({ + "directory" : "metadata////", + "extension-format": "json", + }) + + with patch("builtins.open", mock_open()) as m: + pp.prepare(self.pathfmt) + pp.run(self.pathfmt) + + path = self.pathfmt.realdirectory + "metadata/file.json" + m.assert_called_once_with(path, "w", encoding="utf-8") + @staticmethod def _output(mock): return "".join(