diff options
| author | shumkovnd <[email protected]> | 2023-11-10 14:39:34 +0300 |
|---|---|---|
| committer | shumkovnd <[email protected]> | 2023-11-10 16:42:24 +0300 |
| commit | 77eb2d3fdcec5c978c64e025ced2764c57c00285 (patch) | |
| tree | c51edb0748ca8d4a08d7c7323312c27ba1a8b79a /contrib/python/fonttools/fontTools/misc/xmlWriter.py | |
| parent | dd6d20cadb65582270ac23f4b3b14ae189704b9d (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.py | 204 |
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("&", "&") + data = data.replace("<", "<") + data = data.replace(">", ">") + data = data.replace("\r", " ") + return data + + +def escapeattr(data): + data = escape(data) + data = data.replace('"', """) + 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 |
