utils.python: added equal_attributes() to compare two objects arbitrary attributes

Sign-Off: Rolando Espinoza La fuente
This commit is contained in:
Rolando Espinoza La fuente 2010-02-19 17:57:48 -04:00
parent 7235040936
commit 7ddd4441e3
2 changed files with 74 additions and 1 deletions

View File

@ -1,7 +1,8 @@
import operator
import unittest
from scrapy.utils.python import str_to_unicode, unicode_to_str, \
memoizemethod_noargs, isbinarytext
memoizemethod_noargs, isbinarytext, equal_attributes
class UtilsPythonTestCase(unittest.TestCase):
def test_str_to_unicode(self):
@ -61,5 +62,52 @@ class UtilsPythonTestCase(unittest.TestCase):
# finally some real binary bytes
assert isbinarytext("\x02\xa3")
def test_equal_attributes(self):
class Obj:
pass
a = Obj()
b = Obj()
# no attributes given return False
self.failIf(equal_attributes(a, b, []))
# not existent attributes
self.failIf(equal_attributes(a, b, ['x', 'y']))
a.x = 1
b.x = 1
# equal attribute
self.failUnless(equal_attributes(a, b, ['x']))
b.y = 2
# obj1 has no attribute y
self.failIf(equal_attributes(a, b, ['x', 'y']))
a.y = 2
# equal attributes
self.failUnless(equal_attributes(a, b, ['x', 'y']))
a.y = 1
# differente attributes
self.failIf(equal_attributes(a, b, ['x', 'y']))
# test callable
a.meta = {}
b.meta = {}
self.failUnless(equal_attributes(a, b, ['meta']))
# compare ['meta']['a']
a.meta['z'] = 1
b.meta['z'] = 1
get_z = operator.itemgetter('z')
get_meta = operator.attrgetter('meta')
compare_z = lambda obj: get_z(get_meta(obj))
self.failUnless(equal_attributes(a, b, [compare_z, 'x']))
# fail z equality
a.meta['z'] = 2
self.failIf(equal_attributes(a, b, [compare_z, 'x']))
if __name__ == "__main__":
unittest.main()

View File

@ -216,3 +216,28 @@ def get_func_args(func):
else:
raise TypeError('%s is not callable' % type(func))
return func_args
def equal_attributes(obj1, obj2, attributes):
"""Compare two objects attributes"""
# not attributes given return False by default
if not attributes:
return False
for attr in attributes:
# support callables like itemgetter
if callable(attr):
if not attr(obj1) == attr(obj2):
return False
else:
# check that objects has attribute
if not hasattr(obj1, attr):
return False
if not hasattr(obj2, attr):
return False
# compare object attributes
if not getattr(obj1, attr) == getattr(obj2, attr):
return False
# all attributes equal
return True