simplify metaclass logic, punt on trying to divine intent in multiple inheritance case

This commit is contained in:
Chris McDonough
2012-10-09 02:38:20 -04:00
parent ac6d6d9f21
commit eba97d15fc
2 changed files with 64 additions and 17 deletions

View File

@@ -1917,6 +1917,7 @@ class _SchemaNode(object):
class _SchemaMeta(type):
def __init__(cls, name, bases, clsattrs):
nodes = []
for name, value in clsattrs.items():
if isinstance(value, _SchemaNode):
delattr(cls, name)
@@ -1925,16 +1926,15 @@ class _SchemaMeta(type):
if value.raw_title is _marker:
value.title = name.replace('_', ' ').title()
nodes.append((value._order, value))
cls.__class_schema_nodes__ = nodes
# Combine all attrs from this class and its subclasses.
extended = []
for i, c in enumerate(reversed(cls.__mro__)):
nodes.sort()
cls.__class_schema_nodes__ = [ n[1] for n in nodes ]
# Combine all attrs from this class and its _SchemaNode superclasses.
cls.__all_schema_nodes__ = []
for c in reversed(cls.__mro__):
csn = getattr(c, '__class_schema_nodes__', [])
extended.extend([(i, x, y) for x, y in csn])
# Sort the attrs to maintain the order as defined, and assign to the
# class.
extended.sort()
cls.__all_schema_nodes__ = [x[2] for x in extended]
cls.__all_schema_nodes__.extend(csn)
# metaclass spelling compatibility across Python 2 and Python 3
SchemaNode = _SchemaMeta(

View File

@@ -2631,6 +2631,56 @@ class TestMappingSchemaInheritance(unittest.TestCase):
]
)
def test_single_inheritance2(self):
import colander
class One(colander.Schema):
a = colander.SchemaNode(
colander.Int(),
id='a1',
)
b = colander.SchemaNode(
colander.Int(),
id='b1',
)
d = colander.SchemaNode(
colander.Int(),
id='d1',
)
class Two(One):
a = colander.SchemaNode(
colander.String(),
id='a2',
)
c = colander.SchemaNode(
colander.String(),
id='c2',
)
e = colander.SchemaNode(
colander.String(),
id='e2',
)
class Three(Two):
b = colander.SchemaNode(
colander.Bool(),
id='b3',
)
d = colander.SchemaNode(
colander.Bool(),
id='d3',
)
f = colander.SchemaNode(
colander.Bool(),
id='f3',
)
inst = Three()
c = inst.children
self.assertEqual(len(c), 6)
result = [ x.id for x in c ]
self.assertEqual(result, ['a2', 'b3', 'd3', 'c2', 'e2', 'f3'])
def test_multiple_inheritance(self):
import colander
class One(colander.Schema):
@@ -2661,7 +2711,7 @@ class TestMappingSchemaInheritance(unittest.TestCase):
id='e2',
)
class Three(One, Two):
class Three(Two, One):
b = colander.SchemaNode(
colander.Bool(),
id='b3',
@@ -2676,13 +2726,10 @@ class TestMappingSchemaInheritance(unittest.TestCase):
)
inst = Three()
self.assertEqual(len(inst.children), 6)
self.assertEqual(inst.children[0].id, 'a1')
self.assertEqual(inst.children[1].id, 'b3')
self.assertEqual(inst.children[2].id, 'd3')
self.assertEqual(inst.children[3].id, 'c2')
self.assertEqual(inst.children[4].id, 'e2')
self.assertEqual(inst.children[5].id, 'f3')
c = inst.children
self.assertEqual(len(c), 6)
result = [ x.id for x in c ]
self.assertEqual(result, ['a2', 'b3', 'd3', 'c2', 'e2', 'f3'])
def test_insert_before_failure(self):
import colander