[postprocessor:metadata] implement 'mode: modify' (#2640)
This commit is contained in:
@@ -3312,14 +3312,15 @@ Type
|
|||||||
Default
|
Default
|
||||||
``"json"``
|
``"json"``
|
||||||
Description
|
Description
|
||||||
Select how to write metadata.
|
Selects how to process metadata.
|
||||||
|
|
||||||
* ``"json"``: all metadata using `json.dump()
|
* ``"json"``: write metadata using `json.dump()
|
||||||
<https://docs.python.org/3/library/json.html#json.dump>`_
|
<https://docs.python.org/3/library/json.html#json.dump>`_
|
||||||
* ``"tags"``: ``tags`` separated by newlines
|
* ``"tags"``: write ``tags`` separated by newlines
|
||||||
* ``"custom"``: result of applying `metadata.content-format`_
|
* ``"custom"``: write the result of applying `metadata.content-format`_
|
||||||
to a file's metadata dictionary
|
to a file's metadata dictionary
|
||||||
* ``"delete"``: remove metadata entries specified in `metadata.fields`_
|
* ``"modify"``: add or modify metadata entries
|
||||||
|
* ``"delete"``: remove metadata entries
|
||||||
|
|
||||||
|
|
||||||
metadata.filename
|
metadata.filename
|
||||||
@@ -3411,11 +3412,27 @@ Description
|
|||||||
metadata.fields
|
metadata.fields
|
||||||
---------------
|
---------------
|
||||||
Type
|
Type
|
||||||
``list`` of ``strings``
|
* ``list`` of ``strings``
|
||||||
|
* ``object`` (`field name` -> `format string`_)
|
||||||
Example
|
Example
|
||||||
``["blocked", "watching", "status[creator][name]"]``
|
* .. code:: json
|
||||||
|
|
||||||
|
["blocked", "watching", "status[creator][name]"]
|
||||||
|
|
||||||
|
* .. code:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"blocked" : "***",
|
||||||
|
"watching" : "\fE 'yes' if watching else 'no'",
|
||||||
|
"status[username]": "{status[creator][name]!l}"
|
||||||
|
}
|
||||||
|
|
||||||
Description
|
Description
|
||||||
List of metadata field names to remove for ``"mode": "delete"``.
|
* ``"mode": "delete"``:
|
||||||
|
A list of metadata field names to remove.
|
||||||
|
* ``"mode": "modify"``:
|
||||||
|
An object with metadata field names mapping to a `format string`_
|
||||||
|
whose result is assigned to said field name.
|
||||||
|
|
||||||
|
|
||||||
metadata.content-format
|
metadata.content-format
|
||||||
|
|||||||
@@ -30,6 +30,13 @@ class MetadataPP(PostProcessor):
|
|||||||
elif mode == "tags":
|
elif mode == "tags":
|
||||||
self.write = self._write_tags
|
self.write = self._write_tags
|
||||||
ext = "txt"
|
ext = "txt"
|
||||||
|
elif mode == "modify":
|
||||||
|
self.run = self._run_modify
|
||||||
|
self.fields = {
|
||||||
|
name: formatter.parse(value, None, util.identity).format_map
|
||||||
|
for name, value in options.get("fields").items()
|
||||||
|
}
|
||||||
|
ext = None
|
||||||
elif mode == "delete":
|
elif mode == "delete":
|
||||||
self.run = self._run_delete
|
self.run = self._run_delete
|
||||||
self.fields = options.get("fields")
|
self.fields = options.get("fields")
|
||||||
@@ -118,6 +125,19 @@ class MetadataPP(PostProcessor):
|
|||||||
def _run_stdout(self, pathfmt):
|
def _run_stdout(self, pathfmt):
|
||||||
self.write(sys.stdout, pathfmt.kwdict)
|
self.write(sys.stdout, pathfmt.kwdict)
|
||||||
|
|
||||||
|
def _run_modify(self, pathfmt):
|
||||||
|
kwdict = pathfmt.kwdict
|
||||||
|
for key, func in self.fields.items():
|
||||||
|
obj = kwdict
|
||||||
|
try:
|
||||||
|
while "[" in key:
|
||||||
|
name, _, key = key.partition("[")
|
||||||
|
obj = obj[name]
|
||||||
|
key = key.rstrip("]")
|
||||||
|
obj[key] = func(kwdict)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def _run_delete(self, pathfmt):
|
def _run_delete(self, pathfmt):
|
||||||
kwdict = pathfmt.kwdict
|
kwdict = pathfmt.kwdict
|
||||||
for key in self.fields:
|
for key in self.fields:
|
||||||
|
|||||||
@@ -339,15 +339,39 @@ class MetadataTest(BasePostprocessorTest):
|
|||||||
{"category": "test", "extension": "ext", "filename": "file"}
|
{"category": "test", "extension": "ext", "filename": "file"}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
def test_metadata_modify(self):
|
||||||
|
kwdict = {"foo": 0, "bar": {"bax": 1, "bay": 2, "baz": 3}}
|
||||||
|
self._create({
|
||||||
|
"mode": "modify",
|
||||||
|
"fields": {
|
||||||
|
"foo" : "{filename}-{foo!s}",
|
||||||
|
"foo2" : "\fE bar['bax'] + 122",
|
||||||
|
"bar[baz]": "{_now}",
|
||||||
|
"bar[ba2]": "test",
|
||||||
|
},
|
||||||
|
}, kwdict)
|
||||||
|
pdict = self.pathfmt.kwdict
|
||||||
|
|
||||||
|
self.assertIsNot(kwdict, pdict)
|
||||||
|
self.assertEqual(pdict["foo"], kwdict["foo"])
|
||||||
|
self.assertEqual(pdict["bar"], kwdict["bar"])
|
||||||
|
|
||||||
|
self._trigger()
|
||||||
|
|
||||||
|
self.assertEqual(pdict["foo"] , "file-0")
|
||||||
|
self.assertEqual(pdict["foo2"] , 123)
|
||||||
|
self.assertEqual(pdict["bar"]["ba2"], "test")
|
||||||
|
self.assertIsInstance(pdict["bar"]["baz"], datetime)
|
||||||
|
|
||||||
def test_metadata_delete(self):
|
def test_metadata_delete(self):
|
||||||
kwdict = {"foo": 0, "bar": {"bax": 1, "bay": 2, "baz": 3}}
|
kwdict = {"foo": 0, "bar": {"bax": 1, "bay": 2, "baz": 3}}
|
||||||
self._create({"mode": "delete", "fields": ["foo", "bar[baz]"]}, kwdict)
|
self._create({"mode": "delete", "fields": ["foo", "bar[baz]"]}, kwdict)
|
||||||
pdict = self.pathfmt.kwdict
|
pdict = self.pathfmt.kwdict
|
||||||
|
|
||||||
|
self.assertIsNot(kwdict, pdict)
|
||||||
self.assertEqual(pdict["foo"], kwdict["foo"])
|
self.assertEqual(pdict["foo"], kwdict["foo"])
|
||||||
self.assertEqual(pdict["bar"], kwdict["bar"])
|
self.assertEqual(pdict["bar"], kwdict["bar"])
|
||||||
|
|
||||||
self.assertIsNot(kwdict, pdict)
|
|
||||||
del kwdict["foo"]
|
del kwdict["foo"]
|
||||||
del kwdict["bar"]["baz"]
|
del kwdict["bar"]["baz"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user