diff --git a/docs/configuration.rst b/docs/configuration.rst index 190e8981..e2390c06 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -4411,6 +4411,16 @@ Description i.e. fields whose name starts with an underscore. +metadata.skip +------------- +Type + ``bool`` +Default + ``false`` +Description + Do not overwrite already existing files. + + metadata.archive ---------------- Type diff --git a/gallery_dl/postprocessor/metadata.py b/gallery_dl/postprocessor/metadata.py index 9667a413..714f4fef 100644 --- a/gallery_dl/postprocessor/metadata.py +++ b/gallery_dl/postprocessor/metadata.py @@ -87,6 +87,7 @@ class MetadataPP(PostProcessor): self.omode = options.get("open", omode) self.encoding = options.get("encoding", "utf-8") self.private = options.get("private", False) + self.skip = options.get("skip", False) def run(self, pathfmt): archive = self.archive @@ -96,6 +97,9 @@ class MetadataPP(PostProcessor): directory = self._directory(pathfmt) path = directory + self._filename(pathfmt) + if self.skip and os.path.exists(path): + return + try: with open(path, self.omode, encoding=self.encoding) as fp: self.write(fp, pathfmt.kwdict) diff --git a/test/test_postprocessor.py b/test/test_postprocessor.py index 650bf596..c78d7b03 100644 --- a/test/test_postprocessor.py +++ b/test/test_postprocessor.py @@ -428,11 +428,46 @@ class MetadataTest(BasePostprocessorTest): self.assertNotIn("baz", pdict["bar"]) self.assertEqual(kwdict["bar"], pdict["bar"]) + # no errors for deleted/undefined fields self._trigger() self.assertNotIn("foo", pdict) self.assertNotIn("baz", pdict["bar"]) self.assertEqual(kwdict["bar"], pdict["bar"]) + def test_metadata_option_skip(self): + self._create({"skip": True}) + + with patch("builtins.open", mock_open()) as m, \ + patch("os.path.exists") as e: + e.return_value = True + self._trigger() + + self.assertTrue(e.called) + self.assertTrue(not m.called) + self.assertTrue(not len(self._output(m))) + + with patch("builtins.open", mock_open()) as m, \ + patch("os.path.exists") as e: + e.return_value = False + self._trigger() + + self.assertTrue(e.called) + self.assertTrue(m.called) + self.assertGreater(len(self._output(m)), 0) + + path = self.pathfmt.realdirectory + "file.ext.json" + m.assert_called_once_with(path, "w", encoding="utf-8") + + def test_metadata_option_skip_false(self): + self._create({"skip": False}) + + with patch("builtins.open", mock_open()) as m, \ + patch("os.path.exists") as e: + self._trigger() + + self.assertTrue(not e.called) + self.assertTrue(m.called) + @staticmethod def _output(mock): return "".join(