Example #1
0
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import doctest
from unittest import mock

from lxml import doctestcompare
import six

CHECKER = doctestcompare.LXMLOutputChecker()
PARSE_XML = doctest.register_optionflag('PARSE_XML')


class RequestSideEffect(object):
    def __init__(self):
        self.actions = []
        self.started = False

    def append(self, resp=None, ex=None):
        if not self.started:
            self.actions.append((resp, ex))

    def __call__(self, *args, **kwargs):
        if not self.started:
            self.started = True
Example #2
0
    def assertXMLEqual(self, s1, s2, entity=None):
        """Assert that the two XML fragments are equal, tolerating the following
        variations:
          * whitespace outside of element content and attribute values.
          * order of attributes.
          * order of certain child elements (see `sort_elements` in this
            function).

        Parameters:
          * s1 and s2 are string representations of an XML fragment. The
            strings may be Unicode strings or UTF-8 encoded byte strings.
            The strings may contain an encoding declaration even when
            they are Unicode strings.

            Note: An encoding declaration is the `encoding` attribute in the
            XML declaration (aka XML processing statement), e.g.:
                <?xml version="1.0" encoding="utf-8" ?>
        """

        # Ensure Unicode strings and remove encoding from XML declaration
        encoding_pattern = re.compile(
            r'^<\?xml +(([a-zA-Z0-9_]+=".*")?) +' +
            r'encoding="utf-8" +(([a-zA-Z0-9_]+=".*")?) *\?>')
        encoding_repl = r'<?xml \1 \3 ?>'
        s1 = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s1))
        s2 = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s2))

        parser = etree.XMLParser(remove_blank_text=True)
        x1 = etree.XML(s1, parser=parser)
        x2 = etree.XML(s2, parser=parser)

        # Sort certain elements

        def sort_children(root, sort_elements):
            for tag, attr in sort_elements:
                # elems is a list of elements with this tag name
                elems = root.xpath("//*[local-name() = $tag]", tag=tag)
                if len(elems) > 0:
                    parent = elems[0].getparent()
                    first = None
                    after = None
                    for i in range(0, len(parent)):
                        if parent[i].tag == tag and first is None:
                            first = i
                        if parent[i].tag != tag and first is not None:
                            after = i
                    # The following changes the original XML tree:
                    # The following pylint warning can safely be disabled, see
                    # http://stackoverflow.com/a/25314665
                    # pylint: disable=cell-var-from-loop
                    parent[first:after] = sorted(elems,
                                                 key=lambda e: e.attrib[attr])

        sort_elements = [
            # Sort sibling elements with <first> tag by its <second> attribute
            ("IPARAMVALUE", "NAME"),
            ("PROPERTY", "NAME"),
            ("PARAMETER", "NAME"),
        ]
        sort_children(x1, sort_elements)
        sort_children(x2, sort_elements)

        ns1 = _ensure_unicode(etree.tostring(x1))
        ns2 = _ensure_unicode(etree.tostring(x2))

        checker = doctestcompare.LXMLOutputChecker()
        # This tolerates differences in whitespace and attribute order
        if not checker.check_output(ns1, ns2, 0):
            diff = checker.output_difference(doctest.Example("", ns1), ns2, 0)
            raise AssertionError("XML is not as expected in %s: %s"%\
                                 (entity, diff))
Example #3
0
def get_set_nodes(e, setname, create=False):
    """Return the attributes set nodes (create one if requested)
    setname can for example be meta_attributes
    """
    l = [c for c in e.iterchildren(setname)]
    if l:
        return l
    if create:
        import idmgmt
        elem = etree.SubElement(e, setname, id="")
        elem.set("id", idmgmt.new(elem, e.get("id")))
        l.append(elem)
    return l


_checker = doctestcompare.LXMLOutputChecker()


def xml_equals_unordered(a, b):
    "used by xml_equals to compare xml trees without ordering"

    def fail(msg):
        common_debug("%s!=%s: %s" % (a.tag, b.tag, msg))
        return False

    def tagflat(x):
        return isinstance(x.tag, basestring) and x.tag or x.text

    def sortby(v):
        if v.tag == 'primitive':
            return v.tag
Example #4
0
def assertXMLEqual(s_act, s_exp, entity):
    """
    Assert that the two XML fragments are equal, tolerating the following
    variations:

      * whitespace outside of element content and attribute values.
      * order of attributes.
      * order of certain child elements (see `sort_elements` in this
        function).

    Parameters:

      * s_act and s_exp are string representations of an XML fragment. The
        strings may be Unicode strings or UTF-8 encoded byte strings.
        The strings may contain an encoding declaration even when
        they are Unicode strings.

        Note: An encoding declaration is the `encoding` attribute in the
        XML declaration (aka XML processing statement), e.g.:
            <?xml version="1.0" encoding="utf-8" ?>

      * entity (string): A human readable identification for what is compared.
    """

    # Make sure that None values are already excluded by the caller
    assert isinstance(s_act, (six.text_type, six.binary_type))
    assert isinstance(s_exp, (six.text_type, six.binary_type))

    # Ensure Unicode strings and remove encoding from XML declaration
    encoding_pattern = re.compile(
        r'^<\?xml +(([a-zA-Z0-9_]+=".*")?) +' +
        r'encoding="utf-8" +(([a-zA-Z0-9_]+=".*")?) *\?>')
    encoding_repl = r'<?xml \1 \3 ?>'
    s_act = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s_act))
    s_exp = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s_exp))

    parser = etree.XMLParser(remove_blank_text=True)
    try:
        # Note: lxml.etree.XML() has issues with unicode strings as input,
        # so we pass UTF-8 encoded byte strings. See lxml bug
        # https://bugs.launchpad.net/lxml/+bug/1902364 for a similar issue
        # with lxml.etree.fromstring().
        x_act = etree.XML(_ensure_bytes(s_act), parser=parser)
        x_exp = etree.XML(_ensure_bytes(s_exp), parser=parser)
    except etree.XMLSyntaxError as exc:
        raise AssertionError("XML cannot be validated for %s: %s" %
                             (entity, exc))

    def sort_embedded(root, sort_elements):
        """
        Helper function for `sort_children()`, in support of embedded
        objects. This function invokes sort_children() on each embedded
        object in `root`, after unembedding the embedded object.

        Parameters:
          root (etree.Element):
            XML tree of the CIM-XML representation of the CIM element that
            contains an embedded CIM object (e.g. the CIM element may be
            an INSTANCE XML element and one of its PROPERTY child elements
            has a value that is an embedded CIM instance).
        """
        emb_elems = root.xpath("//*[@EmbeddedObject or @EMBEDDEDOBJECT]"
                               "/*[local-name() = 'VALUE' or "
                               "local-name() = 'VALUE.ARRAY']")
        for emb_elem in emb_elems:
            elem = xml_unembed(emb_elem.text)
            sort_children(elem, sort_elements)
            emb_elem.text = xml_embed(elem)

    def sort_children(root, sort_elements):
        """
        Sort certain elements in the `root` parameter to facilitate
        comparison of two XML documents.

        In addition, make sure this is also applied to any embedded
        objects (in their unembedded state).
        """
        sort_embedded(root, sort_elements)
        for tag, attr in sort_elements:
            # elems is a list of elements with this tag name
            elems = root.xpath("//*[local-name() = $tag]", tag=tag)
            if elems:
                parent = elems[0].getparent()
                first = None
                after = None
                for i, p in enumerate(parent):
                    # TODO 6/18 AM: Loop above should probably be on elems
                    if p.tag == tag and first is None:
                        first = i
                    if p.tag != tag and first is not None:
                        after = i
                # The following changes the original XML tree:
                # The following pylint warning can safely be disabled, see
                # https://stackoverflow.com/a/25314665
                # pylint: disable=cell-var-from-loop
                parent[first:after] = sorted(elems,
                                             key=lambda e: e.attrib[attr])

    sort_elements = [
        # Sort sibling elements with <first> tag by its <second> attribute
        ("IPARAMVALUE", "NAME"),
        ("PROPERTY", "NAME"),
        ("PROPERTY.ARRAY", "NAME"),
        ("PARAMETER", "NAME"),
        ("KEYBINDING", "NAME"),
    ]
    sort_children(x_act, sort_elements)
    sort_children(x_exp, sort_elements)

    ns_act = _ensure_unicode(etree.tostring(x_act))
    ns_exp = _ensure_unicode(etree.tostring(x_exp))

    checker = doctestcompare.LXMLOutputChecker()

    # This tolerates differences in whitespace and attribute order
    if not checker.check_output(ns_act, ns_exp, 0):
        diff = checker.output_difference(doctest.Example("", ns_exp), ns_act,
                                         0)
        raise AssertionError("XML is not as expected in %s: %s" %
                             (entity, diff))
 def equals(self, rhs):
   checker = doctestcompare.LXMLOutputChecker()
   return checker.check_output(self._xml, rhs, 0)