From eba97d15fc4ed20ead70e5d8fdb616a41f1a4687 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 9 Oct 2012 02:38:20 -0400 Subject: [PATCH] simplify metaclass logic, punt on trying to divine intent in multiple inheritance case --- colander/__init__.py | 18 +++++----- colander/tests/test_colander.py | 63 ++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/colander/__init__.py b/colander/__init__.py index f364efc..fe5384f 100644 --- a/colander/__init__.py +++ b/colander/__init__.py @@ -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( diff --git a/colander/tests/test_colander.py b/colander/tests/test_colander.py index 6d8667f..98c7585 100644 --- a/colander/tests/test_colander.py +++ b/colander/tests/test_colander.py @@ -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