File Explorer

/var/lang/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

easy_xml.py5.4 KB · 171 lines
# Copyright (c) 2011 Google Inc. All rights reserved.# Use of this source code is governed by a BSD-style license that can be# found in the LICENSE file. import localeimport osimport reimport sysfrom functools import reduce  def XmlToString(content, encoding="utf-8", pretty=False):    """Writes the XML content to disk, touching the file only if it has changed.     Visual Studio files have a lot of pre-defined structures.  This function makes    it easy to represent these structures as Python data structures, instead of    having to create a lot of function calls.     Each XML element of the content is represented as a list composed of:    1. The name of the element, a string,    2. The attributes of the element, a dictionary (optional), and    3+. The content of the element, if any.  Strings are simple text nodes and        lists are child elements.     Example 1:        <test/>    becomes        ['test']     Example 2:        <myelement a='value1' b='value2'>           <childtype>This is</childtype>           <childtype>it!</childtype>        </myelement>     becomes        ['myelement', {'a':'value1', 'b':'value2'},           ['childtype', 'This is'],           ['childtype', 'it!'],        ]     Args:      content:  The structured content to be converted.      encoding: The encoding to report on the first XML line.      pretty: True if we want pretty printing with indents and new lines.     Returns:      The XML content as a string.    """    # We create a huge list of all the elements of the file.    xml_parts = ['<?xml version="1.0" encoding="%s"?>' % encoding]    if pretty:        xml_parts.append("\n")    _ConstructContentList(xml_parts, content, pretty)     # Convert it to a string    return "".join(xml_parts)  def _ConstructContentList(xml_parts, specification, pretty, level=0):    """Appends the XML parts corresponding to the specification.     Args:      xml_parts: A list of XML parts to be appended to.      specification:  The specification of the element.  See EasyXml docs.      pretty: True if we want pretty printing with indents and new lines.      level: Indentation level.    """    # The first item in a specification is the name of the element.    if pretty:        indentation = "  " * level        new_line = "\n"    else:        indentation = ""        new_line = ""    name = specification[0]    if not isinstance(name, str):        raise Exception(            "The first item of an EasyXml specification should be "            "a string.  Specification was " + str(specification)        )    xml_parts.append(indentation + "<" + name)     # Optionally in second position is a dictionary of the attributes.    rest = specification[1:]    if rest and isinstance(rest[0], dict):        for at, val in sorted(rest[0].items()):            xml_parts.append(f' {at}="{_XmlEscape(val, attr=True)}"')        rest = rest[1:]    if rest:        xml_parts.append(">")        all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True)        multi_line = not all_strings        if multi_line and new_line:            xml_parts.append(new_line)        for child_spec in rest:            # If it's a string, append a text node.            # Otherwise recurse over that child definition            if isinstance(child_spec, str):                xml_parts.append(_XmlEscape(child_spec))            else:                _ConstructContentList(xml_parts, child_spec, pretty, level + 1)        if multi_line and indentation:            xml_parts.append(indentation)        xml_parts.append(f"</{name}>{new_line}")    else:        xml_parts.append("/>%s" % new_line)  def WriteXmlIfChanged(    content, path, encoding="utf-8", pretty=False, win32=(sys.platform == "win32")):    """Writes the XML content to disk, touching the file only if it has changed.     Args:      content:  The structured content to be written.      path: Location of the file.      encoding: The encoding to report on the first line of the XML file.      pretty: True if we want pretty printing with indents and new lines.    """    xml_string = XmlToString(content, encoding, pretty)    if win32 and os.linesep != "\r\n":        xml_string = xml_string.replace("\n", "\r\n")     try:  # getdefaultlocale() was removed in Python 3.11        default_encoding = locale.getdefaultlocale()[1]    except AttributeError:        default_encoding = locale.getencoding()     if default_encoding and default_encoding.upper() != encoding.upper():        xml_string = xml_string.encode(encoding)     # Get the old content    try:        with open(path) as file:            existing = file.read()    except OSError:        existing = None     # It has changed, write it    if existing != xml_string:        with open(path, "wb") as file:            file.write(xml_string)  _xml_escape_map = {    '"': "&quot;",    "'": "&apos;",    "<": "&lt;",    ">": "&gt;",    "&": "&amp;",    "\n": "&#xA;",    "\r": "&#xD;",}  _xml_escape_re = re.compile("(%s)" % "|".join(map(re.escape, _xml_escape_map.keys())))  def _XmlEscape(value, attr=False):    """Escape a string for inclusion in XML."""     def replace(match):        m = match.string[match.start() : match.end()]        # don't replace single quotes in attrs        if attr and m == "'":            return m        return _xml_escape_map[m]     return _xml_escape_re.sub(replace, value)