# Path: easy_karabiner/basexml.py
# class BaseXML(object):
#     xml_parser = etree.XMLParser(strip_cdata=False)
# 
#     @classmethod
#     def unescape(cls, s):
#         return saxutils.unescape(s, {
#                 "&quot;": '"',
#                 "&apos;": "'",
#             })
# 
#     @classmethod
#     def parse(cls, filepath):
#         return etree.parse(filepath).getroot()
# 
#     @classmethod
#     def parse_string(cls, xml_str):
#         return etree.fromstring(xml_str, cls.xml_parser)
# 
#     @classmethod
#     def get_class_name(cls):
#         return cls.__name__
# 
#     @classmethod
#     def is_cdata_text(cls, text):
#         return text.startswith('<![CDATA[') and text.endswith(']]>')
# 
#     @classmethod
#     def remove_cdata_mark(cls, text):
#         return text[len('<![CDATA['):-len(']]>')]
# 
#     @classmethod
#     def create_cdata_text(cls, text):
#         # do NOT use `etree.CDATA`
#         return '<![CDATA[%s]]>' % text
# 
#     @classmethod
#     def assign_text_attribute(cls, etree_element, text):
#         if text is not None:
#             etree_element.text = ensure_utf8(text)
#         else:
#             etree_element.text = text
# 
#     @classmethod
#     def create_tag(cls, name, text=None, **kwargs):
#         et = etree.Element(name, **kwargs)
#         cls.assign_text_attribute(et, text)
#         return et
# 
#     @classmethod
#     def pretty_text(cls, elem, indent="  ", level=0):
#         """WARNING: This method would change the construct of XML tree"""
#         i = "\n" + level * indent
# 
#         if len(elem) == 0:
#             if elem.text is not None:
#                 lines = elem.text.split('\n')
#                 if len(lines) > 1:
#                     if not lines[0].startswith(' '):
#                         lines[0] = (i + indent) + lines[0]
#                     if lines[-1].strip() == '':
#                         lines.pop()
#                     elem.text = (i + indent).join(lines) + i
#         else:
#             for subelem in elem:
#                 BaseXML.pretty_text(subelem, indent, level + 1)
# 
#         return elem
# 
#     @classmethod
#     def to_format_str(cls, xml_tree, pretty_text=True):
#         indent = "  "
#         if pretty_text:
#             BaseXML.pretty_text(xml_tree, indent=indent)
#         xml_string = etree.tostring(xml_tree)
#         xml_string = minidom.parseString(xml_string).toprettyxml(indent=indent)
#         xml_string = cls.unescape(xml_string)
#         return xml_string
# 
#     def to_xml(self):
#         """NOTICE: This method must be a REENTRANT function, which means
#         it should NOT change status or modify any member of `self` object.
#         Because other methods may change the construct of the XML tree.
#         """
#         raise exception.NeedOverrideError()
# 
#     def to_str(self, pretty_text=True, remove_first_line=False):
#         xml_str = self.to_format_str(self.to_xml(), pretty_text=pretty_text)
# 
#         if remove_first_line:
#             lines = xml_str.split('\n')
#             if len(lines[-1].strip()) == 0:
#                 # remove last blank line
#                 lines = lines[1:-1]
#             else:
#                 lines = lines[1:]
#             xml_str = '\n'.join(lines)
# 
#         return xml_str
# 
#     def __str__(self):
#         # `remove_first_line=True` is used to remove version tag in the first line
#         return self.to_str(remove_first_line=True)
# 
# Path: easy_karabiner/fucking_string.py
# def ensure_utf8(s):
#     # convert from any object to `unicode`
#     if not isinstance(s, basestring):
#         s = unicode(s)
# 
#     if isinstance(s, unicode):
#         s = s.encode('utf-8')
#     return unicode(s, encoding='utf-8')
# 
# def is_string_type(s):
#     return isinstance(s, (basestring, unicode, str))


import shlex
import click
        import traceback
from hashlib import sha1
from . import config
from .basexml import BaseXML
from .fucking_string import ensure_utf8, is_string_type

def is_xml_element_equal(node1, node2):
    if len(node1) != len(node2):
        return False
    if node1.tag != node2.tag:
        return False
    if node1.attrib != node2.attrib:
        return False

    text1 = '' if node1.text is None else remove_all_space(node1.text)
    text2 = '' if node2.text is None else remove_all_space(node2.text)
    return text1 == text2


def is_xml_tree_equal(tree1, tree2, ignore_tags=tuple()):
    if tree1.tag == tree2.tag and tree1.tag in ignore_tags:
        return True
    elif is_xml_element_equal(tree1, tree2):
        elems1 = list(tree1)
        elems2 = list(tree2)

        for i in range(len(elems1)):
            if not is_xml_tree_equal(elems1[i], elems2[i], ignore_tags=ignore_tags):
                return False
        return True
    else:
        return False


def assert_xml_equal(xml_tree1, xml_tree2, ignore_tags=tuple()):

# Path: easy_karabiner/basexml.py
# class BaseXML(object):
#     xml_parser = etree.XMLParser(strip_cdata=False)
# 
#     @classmethod
#     def unescape(cls, s):
#         return saxutils.unescape(s, {
#                 "&quot;": '"',
#                 "&apos;": "'",
#             })
# 
#     @classmethod
#     def parse(cls, filepath):
#         return etree.parse(filepath).getroot()
# 
#     @classmethod
#     def parse_string(cls, xml_str):
#         return etree.fromstring(xml_str, cls.xml_parser)
# 
#     @classmethod
#     def get_class_name(cls):
#         return cls.__name__
# 
#     @classmethod
#     def is_cdata_text(cls, text):
#         return text.startswith('<![CDATA[') and text.endswith(']]>')
# 
#     @classmethod
#     def remove_cdata_mark(cls, text):
#         return text[len('<![CDATA['):-len(']]>')]
# 
#     @classmethod
#     def create_cdata_text(cls, text):
#         # do NOT use `etree.CDATA`
#         return '<![CDATA[%s]]>' % text
# 
#     @classmethod
#     def assign_text_attribute(cls, etree_element, text):
#         if text is not None:
#             etree_element.text = ensure_utf8(text)
#         else:
#             etree_element.text = text
# 
#     @classmethod
#     def create_tag(cls, name, text=None, **kwargs):
#         et = etree.Element(name, **kwargs)
#         cls.assign_text_attribute(et, text)
#         return et
# 
#     @classmethod
#     def pretty_text(cls, elem, indent="  ", level=0):
#         """WARNING: This method would change the construct of XML tree"""
#         i = "\n" + level * indent
# 
#         if len(elem) == 0:
#             if elem.text is not None:
#                 lines = elem.text.split('\n')
#                 if len(lines) > 1:
#                     if not lines[0].startswith(' '):
#                         lines[0] = (i + indent) + lines[0]
#                     if lines[-1].strip() == '':
#                         lines.pop()
#                     elem.text = (i + indent).join(lines) + i
#         else:
#             for subelem in elem:
#                 BaseXML.pretty_text(subelem, indent, level + 1)
# 
#         return elem
# 
#     @classmethod
#     def to_format_str(cls, xml_tree, pretty_text=True):
#         indent = "  "
#         if pretty_text:
#             BaseXML.pretty_text(xml_tree, indent=indent)
#         xml_string = etree.tostring(xml_tree)
#         xml_string = minidom.parseString(xml_string).toprettyxml(indent=indent)
#         xml_string = cls.unescape(xml_string)
#         return xml_string
# 
#     def to_xml(self):
#         """NOTICE: This method must be a REENTRANT function, which means
#         it should NOT change status or modify any member of `self` object.
#         Because other methods may change the construct of the XML tree.
#         """
#         raise exception.NeedOverrideError()
# 
#     def to_str(self, pretty_text=True, remove_first_line=False):
#         xml_str = self.to_format_str(self.to_xml(), pretty_text=pretty_text)
# 
#         if remove_first_line:
#             lines = xml_str.split('\n')
#             if len(lines[-1].strip()) == 0:
#                 # remove last blank line
#                 lines = lines[1:-1]
#             else:
#                 lines = lines[1:]
#             xml_str = '\n'.join(lines)
# 
#         return xml_str
# 
#     def __str__(self):
#         # `remove_first_line=True` is used to remove version tag in the first line
#         return self.to_str(remove_first_line=True)
# 
# Path: easy_karabiner/fucking_string.py
# def ensure_utf8(s):
#     # convert from any object to `unicode`
#     if not isinstance(s, basestring):
#         s = unicode(s)
# 
#     if isinstance(s, unicode):
#         s = s.encode('utf-8')
#     return unicode(s, encoding='utf-8')
# 
# def is_string_type(s):
#     return isinstance(s, (basestring, unicode, str))


# Path: easy_karabiner/util.py
import shlex
import click
        import traceback
from hashlib import sha1
from . import config
from .basexml import BaseXML
from .fucking_string import ensure_utf8, is_string_type


def is_xml_element_equal(node1, node2):
    if len(node1) != len(node2):
        return False
    if node1.tag != node2.tag:
        return False
    if node1.attrib != node2.attrib:
        return False

    text1 = '' if node1.text is None else remove_all_space(node1.text)
    text2 = '' if node2.text is None else remove_all_space(node2.text)
    return text1 == text2


def is_xml_tree_equal(tree1, tree2, ignore_tags=tuple()):
    if tree1.tag == tree2.tag and tree1.tag in ignore_tags:
        return True
    elif is_xml_element_equal(tree1, tree2):
        elems1 = list(tree1)
        elems2 = list(tree2)

        for i in range(len(elems1)):
            if not is_xml_tree_equal(elems1[i], elems2[i], ignore_tags=ignore_tags):
                return False
        return True
    else:
        return False


def assert_xml_equal(xml_tree1, xml_tree2, ignore_tags=tuple()):

    if isinstance(xml_tree1, BaseXML):