Item multi inherit fixed

This commit is contained in:
nramirezuy 2013-07-17 15:22:08 -03:00
parent 0a5bbbaed3
commit 7871acd665
2 changed files with 80 additions and 7 deletions

View File

@ -24,18 +24,21 @@ class Field(dict):
class ItemMeta(ABCMeta):
def __new__(mcs, class_name, bases, attrs):
new_bases = tuple(base._class for base in bases if hasattr(base, '_class'))
_class = super(ItemMeta, mcs).__new__(mcs, 'x_' + class_name, new_bases, attrs)
fields = {}
new_attrs = {}
for n, v in six.iteritems(attrs):
for n in dir(_class):
v = getattr(_class, n)
if isinstance(v, Field):
fields[n] = v
else:
new_attrs[n] = v
elif n in attrs:
new_attrs[n] = attrs[n]
cls = super(ItemMeta, mcs).__new__(mcs, class_name, bases, new_attrs)
cls.fields = cls.fields.copy()
cls.fields.update(fields)
return cls
new_attrs['fields'] = fields
new_attrs['_class'] = _class
return super(ItemMeta, mcs).__new__(mcs, class_name, bases, new_attrs)
class DictItem(MutableMapping, BaseItem):

View File

@ -134,6 +134,76 @@ class ItemTest(unittest.TestCase):
self.assertEqual(list(i.keys()), ['keys'])
self.assertEqual(list(i.values()), [3])
def test_metaclass_multiple_inheritance_simple(self):
class A(Item):
save = Field(default='A')
class B(A): pass
class C(Item):
save = Field(default='C')
class D(B, C): pass
self.assertEqual(D(save='X')['save'], 'X')
self.assertEqual(D.fields, {'save': {'default': 'A'}})
# D class inverted
class E(C, B): pass
self.assertEqual(E(save='X')['save'], 'X')
self.assertEqual(E.fields, {'save': {'default': 'C'}})
def test_metaclass_multiple_inheritance_diamond(self):
class A(Item):
save = Field(default='A')
load = Field(default='A')
class B(A): pass
class C(A):
save = Field(default='C')
class D(B, C):
load = Field(default='D')
self.assertEqual(D(save='X')['save'], 'X')
self.assertEqual(D(load='X')['load'], 'X')
self.assertEqual(D.fields, {'save': {'default': 'C'},
'load': {'default': 'D'}})
# D class inverted
class E(C, B):
load = Field(default='E')
self.assertEqual(E(save='X')['save'], 'X')
self.assertEqual(E(load='X')['load'], 'X')
self.assertEqual(E.fields, {'save': {'default': 'C'},
'load': {'default': 'E'}})
def test_metaclass_multiple_inheritance_without_metaclass(self):
class A(Item):
save = Field(default='A')
class B(A): pass
class C(object):
not_allowed = Field(default='not_allowed')
save = Field(default='C')
class D(B, C): pass
self.assertRaises(KeyError, D, not_allowed='value')
self.assertEqual(D(save='X')['save'], 'X')
self.assertEqual(D.fields, {'save': {'default': 'A'}})
# D class inverted
class E(C, B): pass
self.assertRaises(KeyError, E, not_allowed='value')
self.assertEqual(E(save='X')['save'], 'X')
self.assertEqual(E.fields, {'save': {'default': 'A'}})
def test_to_dict(self):
class TestItem(Item):
name = Field()