From 605f6fba2c519cb69e9555d14ee042e2d75da7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Wed, 7 Aug 2024 09:43:02 +0200 Subject: [PATCH] [pp:metadata] implement 'base-directory' option (#5262, #5728) --- docs/configuration.rst | 23 +++++++++++++++++++---- gallery_dl/postprocessor/metadata.py | 23 ++++++++++++++++++++--- test/test_postprocessor.py | 21 +++++++++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index 9615e34c..87e6f5d6 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -160,8 +160,7 @@ Default ``false`` Description Use an extractor's current target directory as - `base-directory `__ - for any spawned child extractors. + base-directory_ for any spawned child extractors. extractor.*.parent-metadata @@ -5548,8 +5547,23 @@ Example * ``"metadata"`` * ``["..", "metadata", "\fF {id // 500 * 500}"]`` Description - Directory where metadata files are stored in relative to the - current target location for file downloads. + Directory where metadata files are stored in + relative to `metadata.base-directory`_. + + +metadata.base-directory +----------------------- +Type + * ``bool`` + * |Path|_ +Default + ``false`` +Description + Selects the relative location for metadata files. + + * ``false``: current target location for file downloads (base-directory_ + directory_) + * ``true``: current base-directory_ location + * any |Path|_: custom location metadata.extension @@ -6561,6 +6575,7 @@ Description .. |open()| replace:: the built-in ``open()`` function .. |json.dump()| replace:: ``json.dump()`` +.. _directory: `extractor.*.directory`_ .. _base-directory: `extractor.*.base-directory`_ .. _date-format: `extractor.*.date-format`_ .. _deviantart.metadata: `extractor.deviantart.metadata`_ diff --git a/gallery_dl/postprocessor/metadata.py b/gallery_dl/postprocessor/metadata.py index a520a34c..e89b1700 100644 --- a/gallery_dl/postprocessor/metadata.py +++ b/gallery_dl/postprocessor/metadata.py @@ -55,6 +55,20 @@ class MetadataPP(PostProcessor): self._json_encode = self._make_encoder(options, 4).encode ext = "json" + base_directory = options.get("base-directory") + if base_directory: + if base_directory is True: + self._base = lambda p: p.basedirectory + else: + sep = os.sep + altsep = os.altsep + base_directory = util.expand_path(base_directory) + if altsep and altsep in base_directory: + base_directory = base_directory.replace(altsep, sep) + if base_directory[-1] != sep: + base_directory += sep + self._base = lambda p: base_directory + directory = options.get("directory") if isinstance(directory, list): self._directory = self._directory_format @@ -147,11 +161,14 @@ class MetadataPP(PostProcessor): except Exception: pass - def _directory(self, pathfmt): + def _base(self, pathfmt): return pathfmt.realdirectory + def _directory(self, pathfmt): + return self._base(pathfmt) + def _directory_custom(self, pathfmt): - return os.path.join(pathfmt.realdirectory, self._metadir) + return os.path.join(self._base(pathfmt), self._metadir) def _directory_format(self, pathfmt): formatters = pathfmt.directory_formatters @@ -161,7 +178,7 @@ class MetadataPP(PostProcessor): pathfmt.directory_conditions = () segments = pathfmt.build_directory(pathfmt.kwdict) directory = pathfmt.clean_path(os.sep.join(segments) + os.sep) - return os.path.join(pathfmt.realdirectory, directory) + return os.path.join(self._base(pathfmt), directory) finally: pathfmt.directory_conditions = conditions pathfmt.directory_formatters = formatters diff --git a/test/test_postprocessor.py b/test/test_postprocessor.py index 3e6d1dfa..edd85756 100644 --- a/test/test_postprocessor.py +++ b/test/test_postprocessor.py @@ -452,6 +452,27 @@ class MetadataTest(BasePostprocessorTest): path = self.pathfmt.realdirectory + "../json/12500/file.ext.json" m.assert_called_once_with(path, "w", encoding="utf-8") + def test_metadata_basedirectory(self): + self._create({"base-directory": True}) + + with patch("builtins.open", mock_open()) as m: + self._trigger() + + path = self.pathfmt.basedirectory + "file.ext.json" + m.assert_called_once_with(path, "w", encoding="utf-8") + + def test_metadata_basedirectory_custom(self): + self._create({ + "base-directory": "/home/test", + "directory": "meta", + }) + + with patch("builtins.open", mock_open()) as m: + self._trigger() + + path = "/home/test/meta/file.ext.json" + m.assert_called_once_with(path, "w", encoding="utf-8") + def test_metadata_filename(self): self._create({ "filename" : "{category}_{filename}_/meta/\n\r.data",