import collections
import html
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
from enum import Enum
from enum import auto as autostr
from pathlib import Path
from typing import IO, Any, Tuple, Union
import filetype
auto = autostr
class AutoStrEnum(Enum):
@staticmethod
def _generate_next_value_(name, *_):
return name
def dict_update_recursive(dict1, dict2):
# https://gist.github.com/angstwad/bf22d1822c38a92ec0a9
for k in dict2:
if (k in dict1 and isinstance(dict1[k], dict) and
isinstance(dict2[k], collections.Mapping)):
dict_update_recursive(dict1[k], dict2[k])
else:
dict1[k] = dict2[k]
def is_svg(file: Union[IO, bytes, str]) -> bool:
try:
_, element = next(xml_etree.iterparse(file, ("start",)))
return element.tag == "{http://www.w3.org/2000/svg}svg"
except (StopIteration, xml_etree.ParseError):
return False
def svg_dimensions(file: Union[IO, bytes, str]) -> Tuple[int, int]:
attrs = xml_etree.parse(file).getroot().attrib
try:
width = round(float(attrs.get("width", attrs["viewBox"].split()[3])))
except (KeyError, IndexError, ValueError, TypeError):
width = 256
try:
height = round(float(attrs.get("height", attrs["viewBox"].split()[4])))
except (KeyError, IndexError, ValueError, TypeError):
height = 256
return (width, height)
def guess_mime(file: IO) -> str:
if is_svg(file):
return "image/svg+xml"
file.seek(0, 0)
return filetype.guess_mime(file) or "application/octet-stream"
def plain2html(text: str) -> str:
return html.escape(text)\
.replace("\n", "
")\
.replace("\t", " " * 4)
def serialize_value_for_qml(value: Any) -> Any:
if hasattr(value, "__class__") and issubclass(value.__class__, Enum):
return value.value
if isinstance(value, Path):
return f"file://{value!s}"
return value