simplify metaclass logic, punt on trying to divine intent in multiple inheritance case
This commit is contained in:
@@ -1917,6 +1917,7 @@ class _SchemaNode(object):
|
|||||||
class _SchemaMeta(type):
|
class _SchemaMeta(type):
|
||||||
def __init__(cls, name, bases, clsattrs):
|
def __init__(cls, name, bases, clsattrs):
|
||||||
nodes = []
|
nodes = []
|
||||||
|
|
||||||
for name, value in clsattrs.items():
|
for name, value in clsattrs.items():
|
||||||
if isinstance(value, _SchemaNode):
|
if isinstance(value, _SchemaNode):
|
||||||
delattr(cls, name)
|
delattr(cls, name)
|
||||||
@@ -1925,16 +1926,15 @@ class _SchemaMeta(type):
|
|||||||
if value.raw_title is _marker:
|
if value.raw_title is _marker:
|
||||||
value.title = name.replace('_', ' ').title()
|
value.title = name.replace('_', ' ').title()
|
||||||
nodes.append((value._order, value))
|
nodes.append((value._order, value))
|
||||||
cls.__class_schema_nodes__ = nodes
|
|
||||||
# Combine all attrs from this class and its subclasses.
|
nodes.sort()
|
||||||
extended = []
|
cls.__class_schema_nodes__ = [ n[1] for n in nodes ]
|
||||||
for i, c in enumerate(reversed(cls.__mro__)):
|
|
||||||
|
# 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__', [])
|
csn = getattr(c, '__class_schema_nodes__', [])
|
||||||
extended.extend([(i, x, y) for x, y in csn])
|
cls.__all_schema_nodes__.extend(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]
|
|
||||||
|
|
||||||
# metaclass spelling compatibility across Python 2 and Python 3
|
# metaclass spelling compatibility across Python 2 and Python 3
|
||||||
SchemaNode = _SchemaMeta(
|
SchemaNode = _SchemaMeta(
|
||||||
|
|||||||
@@ -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):
|
def test_multiple_inheritance(self):
|
||||||
import colander
|
import colander
|
||||||
class One(colander.Schema):
|
class One(colander.Schema):
|
||||||
@@ -2661,7 +2711,7 @@ class TestMappingSchemaInheritance(unittest.TestCase):
|
|||||||
id='e2',
|
id='e2',
|
||||||
)
|
)
|
||||||
|
|
||||||
class Three(One, Two):
|
class Three(Two, One):
|
||||||
b = colander.SchemaNode(
|
b = colander.SchemaNode(
|
||||||
colander.Bool(),
|
colander.Bool(),
|
||||||
id='b3',
|
id='b3',
|
||||||
@@ -2676,13 +2726,10 @@ class TestMappingSchemaInheritance(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
inst = Three()
|
inst = Three()
|
||||||
self.assertEqual(len(inst.children), 6)
|
c = inst.children
|
||||||
self.assertEqual(inst.children[0].id, 'a1')
|
self.assertEqual(len(c), 6)
|
||||||
self.assertEqual(inst.children[1].id, 'b3')
|
result = [ x.id for x in c ]
|
||||||
self.assertEqual(inst.children[2].id, 'd3')
|
self.assertEqual(result, ['a2', 'b3', 'd3', 'c2', 'e2', 'f3'])
|
||||||
self.assertEqual(inst.children[3].id, 'c2')
|
|
||||||
self.assertEqual(inst.children[4].id, 'e2')
|
|
||||||
self.assertEqual(inst.children[5].id, 'f3')
|
|
||||||
|
|
||||||
def test_insert_before_failure(self):
|
def test_insert_before_failure(self):
|
||||||
import colander
|
import colander
|
||||||
|
|||||||
Reference in New Issue
Block a user