summaryrefslogtreecommitdiffstats
path: root/contrib/python/fonttools/fontTools/misc/xmlWriter.py
diff options
context:
space:
mode:
authorshumkovnd <[email protected]>2023-11-10 14:39:34 +0300
committershumkovnd <[email protected]>2023-11-10 16:42:24 +0300
commit77eb2d3fdcec5c978c64e025ced2764c57c00285 (patch)
treec51edb0748ca8d4a08d7c7323312c27ba1a8b79a /contrib/python/fonttools/fontTools/misc/xmlWriter.py
parentdd6d20cadb65582270ac23f4b3b14ae189704b9d (diff)
KIKIMR-19287: add task_stats_drawing script
Diffstat (limited to 'contrib/python/fonttools/fontTools/misc/xmlWriter.py')
-rw-r--r--contrib/python/fonttools/fontTools/misc/xmlWriter.py204
1 files changed, 204 insertions, 0 deletions
diff --git a/contrib/python/fonttools/fontTools/misc/xmlWriter.py b/contrib/python/fonttools/fontTools/misc/xmlWriter.py
new file mode 100644
index 00000000000..9a8dc3e3b7f
--- /dev/null
+++ b/contrib/python/fonttools/fontTools/misc/xmlWriter.py
@@ -0,0 +1,204 @@
+"""xmlWriter.py -- Simple XML authoring class"""
+
+from fontTools.misc.textTools import byteord, strjoin, tobytes, tostr
+import sys
+import os
+import string
+
+INDENT = " "
+
+
+class XMLWriter(object):
+ def __init__(
+ self,
+ fileOrPath,
+ indentwhite=INDENT,
+ idlefunc=None,
+ encoding="utf_8",
+ newlinestr="\n",
+ ):
+ if encoding.lower().replace("-", "").replace("_", "") != "utf8":
+ raise Exception("Only UTF-8 encoding is supported.")
+ if fileOrPath == "-":
+ fileOrPath = sys.stdout
+ if not hasattr(fileOrPath, "write"):
+ self.filename = fileOrPath
+ self.file = open(fileOrPath, "wb")
+ self._closeStream = True
+ else:
+ self.filename = None
+ # assume writable file object
+ self.file = fileOrPath
+ self._closeStream = False
+
+ # Figure out if writer expects bytes or unicodes
+ try:
+ # The bytes check should be first. See:
+ # https://github.com/fonttools/fonttools/pull/233
+ self.file.write(b"")
+ self.totype = tobytes
+ except TypeError:
+ # This better not fail.
+ self.file.write("")
+ self.totype = tostr
+ self.indentwhite = self.totype(indentwhite)
+ if newlinestr is None:
+ self.newlinestr = self.totype(os.linesep)
+ else:
+ self.newlinestr = self.totype(newlinestr)
+ self.indentlevel = 0
+ self.stack = []
+ self.needindent = 1
+ self.idlefunc = idlefunc
+ self.idlecounter = 0
+ self._writeraw('<?xml version="1.0" encoding="UTF-8"?>')
+ self.newline()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ self.close()
+
+ def close(self):
+ if self._closeStream:
+ self.file.close()
+
+ def write(self, string, indent=True):
+ """Writes text."""
+ self._writeraw(escape(string), indent=indent)
+
+ def writecdata(self, string):
+ """Writes text in a CDATA section."""
+ self._writeraw("<![CDATA[" + string + "]]>")
+
+ def write8bit(self, data, strip=False):
+ """Writes a bytes() sequence into the XML, escaping
+ non-ASCII bytes. When this is read in xmlReader,
+ the original bytes can be recovered by encoding to
+ 'latin-1'."""
+ self._writeraw(escape8bit(data), strip=strip)
+
+ def write_noindent(self, string):
+ """Writes text without indentation."""
+ self._writeraw(escape(string), indent=False)
+
+ def _writeraw(self, data, indent=True, strip=False):
+ """Writes bytes, possibly indented."""
+ if indent and self.needindent:
+ self.file.write(self.indentlevel * self.indentwhite)
+ self.needindent = 0
+ s = self.totype(data, encoding="utf_8")
+ if strip:
+ s = s.strip()
+ self.file.write(s)
+
+ def newline(self):
+ self.file.write(self.newlinestr)
+ self.needindent = 1
+ idlecounter = self.idlecounter
+ if not idlecounter % 100 and self.idlefunc is not None:
+ self.idlefunc()
+ self.idlecounter = idlecounter + 1
+
+ def comment(self, data):
+ data = escape(data)
+ lines = data.split("\n")
+ self._writeraw("<!-- " + lines[0])
+ for line in lines[1:]:
+ self.newline()
+ self._writeraw(" " + line)
+ self._writeraw(" -->")
+
+ def simpletag(self, _TAG_, *args, **kwargs):
+ attrdata = self.stringifyattrs(*args, **kwargs)
+ data = "<%s%s/>" % (_TAG_, attrdata)
+ self._writeraw(data)
+
+ def begintag(self, _TAG_, *args, **kwargs):
+ attrdata = self.stringifyattrs(*args, **kwargs)
+ data = "<%s%s>" % (_TAG_, attrdata)
+ self._writeraw(data)
+ self.stack.append(_TAG_)
+ self.indent()
+
+ def endtag(self, _TAG_):
+ assert self.stack and self.stack[-1] == _TAG_, "nonmatching endtag"
+ del self.stack[-1]
+ self.dedent()
+ data = "</%s>" % _TAG_
+ self._writeraw(data)
+
+ def dumphex(self, data):
+ linelength = 16
+ hexlinelength = linelength * 2
+ chunksize = 8
+ for i in range(0, len(data), linelength):
+ hexline = hexStr(data[i : i + linelength])
+ line = ""
+ white = ""
+ for j in range(0, hexlinelength, chunksize):
+ line = line + white + hexline[j : j + chunksize]
+ white = " "
+ self._writeraw(line)
+ self.newline()
+
+ def indent(self):
+ self.indentlevel = self.indentlevel + 1
+
+ def dedent(self):
+ assert self.indentlevel > 0
+ self.indentlevel = self.indentlevel - 1
+
+ def stringifyattrs(self, *args, **kwargs):
+ if kwargs:
+ assert not args
+ attributes = sorted(kwargs.items())
+ elif args:
+ assert len(args) == 1
+ attributes = args[0]
+ else:
+ return ""
+ data = ""
+ for attr, value in attributes:
+ if not isinstance(value, (bytes, str)):
+ value = str(value)
+ data = data + ' %s="%s"' % (attr, escapeattr(value))
+ return data
+
+
+def escape(data):
+ data = tostr(data, "utf_8")
+ data = data.replace("&", "&amp;")
+ data = data.replace("<", "&lt;")
+ data = data.replace(">", "&gt;")
+ data = data.replace("\r", "&#13;")
+ return data
+
+
+def escapeattr(data):
+ data = escape(data)
+ data = data.replace('"', "&quot;")
+ return data
+
+
+def escape8bit(data):
+ """Input is Unicode string."""
+
+ def escapechar(c):
+ n = ord(c)
+ if 32 <= n <= 127 and c not in "<&>":
+ return c
+ else:
+ return "&#" + repr(n) + ";"
+
+ return strjoin(map(escapechar, data.decode("latin-1")))
+
+
+def hexStr(s):
+ h = string.hexdigits
+ r = ""
+ for c in s:
+ i = byteord(c)
+ r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+ return r