Для юнит-тестов понадобилось сравнивать xml'и (порядок тегов имеет значение, порядок атрибутов - нет), готового не нашел, написал своё. Может кому понадобится.


import elementtree.ElementTree as ET
from cStringIO import StringIO

class Inspectable(object):
def _get_attrs(self):
attrs = self.__class__.__dict__.copy()
attrs.update(self.__dict__.copy())
return sorted(((k,v)
for k,v in attrs.items()
if not (k.startswith('_') or callable(v)) and v),
key=lambda x:x)

def __str__(self):
attrs_values = ‘, ’.join(“%s=%r” % (k, v)
for k,v in self._get_attrs()) or ‘None’
return “%s: %s” % (self.__class__.__name__, attrs_values)

def __repr__(self):
return “<%s>” % (self.__str__(),)

def __unicode__(self):
attrs_values = ‘, ’.join(u“%s=%s” % (k, v)
for k,v in self._get_attrs()) or u'None'
return u“%s: %s” % (self.__class__.__name__, attrs_values)


class XMLMockWrapper(Inspectable):
def __init__(self, xml):
assert isinstance(xml, str)
self.xml = xml
self.et = ET.ElementTree().parse(StringIO(xml))

@staticmethod
def _compare_payloads(one, another):
if (one == another) or \
(one is None and isinstance(another, str) and another.strip() == ‘') or \
(isinstance(one, str) and one.strip() == ’' and another is None) or \
(isinstance(one, str) and isinstance(another, str) and one.strip() == another.strip()):
return True
else:
return False

@staticmethod
def _compare_et(one, another):
# first of all, compare tag name
if one.tag != another.tag:
return False
# compare tag attributes
if one.attrib != another.attrib:
return False
# compare text
if not self._compare_payloads(one.text, another.text):
return False
# compare children
for one_child, another_child in zip(one.getchildren(), another.getchildren()):
if not XMLMockWrapper._compare_et(one_child, another_child):
return False
# all ok
return True

def __eq__(self, them):
assert isinstance(them, (str, XMLMockWrapper))
if isinstance(them, str):
them = XMLMockWrapper(them)
return self._compare_et(self.et, them.et)


Inspectable - переосмысление поста Алекса Лебедева