inkstitch/lib/metadata.py

86 wiersze
2.2 KiB
Python

import json
import re
from collections.abc import MutableMapping
import inkex
from lxml import etree
from .utils.settings import DEFAULT_METADATA, global_settings
def strip_namespace(tag):
"""Remove xml namespace from a tag name.
>>> {http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}namedview
<<< namedview
"""
match = re.match(r'^\{[^}]+\}(.+)$', tag)
if match:
return match.group(1)
else:
return tag
class InkStitchMetadata(MutableMapping):
"""Helper class to get and set inkstitch-specific metadata attributes.
Operates on a document and acts like a dict. Setting an item adds or
updates a metadata element in the document. Getting an item retrieves
a metadata element's text contents or None if an element by that name
doesn't exist.
"""
def __init__(self, document):
super().__init__()
self.document = document
self.metadata = document.metadata
for setting in DEFAULT_METADATA:
if self[setting] is None:
self[setting] = global_settings[f'default_{setting}']
# Because this class inherints from MutableMapping, all we have to do is
# implement these five methods and we get a full dict-like interface.
def __setitem__(self, name, value):
item = self._find_item(name)
item.text = json.dumps(value)
def _find_item(self, name, create=True):
tag = inkex.addNS(name, "inkstitch")
item = self.metadata.find(tag)
if item is None and create:
item = etree.SubElement(self.metadata, tag)
return item
def __getitem__(self, name):
item = self._find_item(name)
try:
return json.loads(item.text)
except (ValueError, TypeError):
return None
def __delitem__(self, name):
item = self._find_item(name, create=False)
if item is not None:
self.metadata.remove(item)
def __iter__(self):
for child in self.metadata:
if child.prefix == "inkstitch":
yield strip_namespace(child.tag)
def __len__(self):
i = 0
for i, item in enumerate(self):
pass
return i + 1
def __json__(self):
return dict(self)