summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphaël Barrois <raphael.barrois@polyconseil.fr>2011-09-06 17:18:00 +0200
committerRaphaël Barrois <raphael.barrois@polyconseil.fr>2011-09-06 17:18:00 +0200
commit41c68349cf3925818a6c05477790a2f67d431d39 (patch)
treeb3fe0111b500ec97b28f5c5badb9a4709ca9cc7e
parentd17972e3e21c14ecca91e4238fa0726bd1a68a23 (diff)
downloadfactory-boy-41c68349cf3925818a6c05477790a2f67d431d39.tar
factory-boy-41c68349cf3925818a6c05477790a2f67d431d39.tar.gz
Rewrite all the 'OrderedDeclaration' part.
Signed-off-by: Raphaël Barrois <raphael.barrois@polyconseil.fr>
-rw-r--r--factory/base.py2
-rw-r--r--factory/containers.py181
-rw-r--r--factory/declarations.py41
-rw-r--r--factory/test_base.py9
-rw-r--r--factory/test_containers.py191
-rw-r--r--factory/test_declarations.py18
6 files changed, 151 insertions, 291 deletions
diff --git a/factory/base.py b/factory/base.py
index e5729de..890a7c9 100644
--- a/factory/base.py
+++ b/factory/base.py
@@ -21,7 +21,7 @@
import re
import sys
-from containers import AttributeBuilder, DeclarationDict, ObjectParamsWrapper, StubObject
+from containers import AttributeBuilder, DeclarationDict, StubObject
from declarations import OrderedDeclaration
# Strategies
diff --git a/factory/containers.py b/factory/containers.py
index 8012444..62c8847 100644
--- a/factory/containers.py
+++ b/factory/containers.py
@@ -23,7 +23,12 @@ from declarations import OrderedDeclaration, SubFactory
ATTR_SPLITTER = '__'
-class ObjectParamsWrapper(object):
+
+class CyclicDefinitionError(Exception):
+ """Raised when cyclic definition were found."""
+
+
+class LazyStub(object):
"""A generic container that allows for getting but not setting of attributes.
Attributes are set at initialization time."""
@@ -31,107 +36,45 @@ class ObjectParamsWrapper(object):
initialized = False
def __init__(self, attrs):
- self.attrs = attrs
+ self.__attrs = attrs
+ self.__values = {}
+ self.__pending = []
self.initialized = True
- def __setattr__(self, name, value):
- if not self.initialized:
- return super(ObjectParamsWrapper, self).__setattr__(name, value)
- else:
- raise AttributeError('Setting of object attributes is not allowed')
+ def __fill__(self):
+ res = {}
+ for attr in self.__attrs:
+ res[attr] = getattr(self, attr)
+ return res
def __getattr__(self, name):
- try:
- return self.attrs[name]
- except KeyError:
- raise AttributeError("The param '{0}' does not exist. Perhaps your declarations are out of order?".format(name))
-
-
-class OrderedDict(object):
- def __init__(self, **kwargs):
- self._order = {}
- self._values = {}
- for k, v in kwargs.iteritems():
- self[k] = v
-
- def __contains__(self, key):
- return key in self._values
-
- def __getitem__(self, key):
- return self._values[key]
-
- def __setitem__(self, key, val):
- if key in self:
- del self[key]
- self._values[key] = val
- self._order.setdefault(val.order, set()).add(key)
-
- def __delitem__(self, key):
- self.pop(key)
-
- def pop(self, key):
- val = self._values.pop(key)
- self._order[val.order].remove(key)
- return val
-
- def items(self):
- return list(self.iteritems())
-
- def iteritems(self):
- order = sorted(self._order.keys())
- for i in order:
- for key in self._order[i]:
- yield (key, self._values[key])
-
- def __iter__(self):
- order = sorted(self._order.keys())
- for i in order:
- for k in self._order[i]:
- yield k
-
-
-class DeclarationDict(object):
- """Holds a dict of declarations, keeping OrderedDeclaration at the end."""
- def __init__(self, extra=None):
- if not extra:
- extra = {}
- self._ordered = OrderedDict()
- self._unordered = {}
- self.update(extra)
+ if name in self.__pending:
+ raise CyclicDefinitionError(
+ "Cyclic lazy attribute definition for %s. Current cycle is %r." %
+ (name, self.__pending))
+ elif name in self.__values:
+ return self.__values[name]
+ elif name in self.__attrs:
+ val = self.__attrs[name]
+ if isinstance(val, LazyValue):
+ self.__pending.append(name)
+ val = val.evaluate(self)
+ assert name == self.__pending.pop()
+ self.__values[name] = val
+ return val
+ else:
+ raise AttributeError(
+ "The parameter %s is unknown. Evaluated attributes are %r, definitions are %r." % (name, self.__values, self.__attrs))
- def __setitem__(self, key, value):
- if key in self:
- del self[key]
- if isinstance(value, OrderedDeclaration):
- self._ordered[key] = value
- else:
- self._unordered[key] = value
-
- def __getitem__(self, key):
- """Try in _unordered first, then in _ordered."""
- try:
- return self._unordered[key]
- except KeyError:
- return self._ordered[key]
-
- def __delitem__(self, key):
- if key in self._unordered:
- del self._unordered[key]
+ def __setattr__(self, name, value):
+ if not self.initialized:
+ return super(LazyStub, self).__setattr__(name, value)
else:
- del self._ordered[key]
-
- def pop(self, key, *args):
- assert len(args) <= 1
- try:
- return self._unordered.pop(key)
- except KeyError:
- return self._ordered.pop(key, *args)
+ raise AttributeError('Setting of object attributes is not allowed')
- def update(self, d):
- for k in d:
- self[k] = d[k]
+class DeclarationDict(dict):
def update_with_public(self, d):
"""Updates the DeclarationDict from a class definition dict.
@@ -155,23 +98,29 @@ class DeclarationDict(object):
new.update(extra)
return new
- def __contains__(self, key):
- return key in self._unordered or key in self._ordered
- def items(self):
- return list(self.iteritems())
+class LazyValue(object):
+ def evaluate(self, obj):
+ raise NotImplementedError("This is an abstract method.")
+
+
+class SubFactoryWrapper(LazyValue):
+ def __init__(self, subfactory, subfields, create):
+ self.subfactory = subfactory
+ self.subfields = subfields
+ self.create = create
+
+ def evaluate(self, obj):
+ return self.subfactory.evaluate(self.create, self.subfields)
+
- def iteritems(self):
- for pair in self._unordered.iteritems():
- yield pair
- for pair in self._ordered.iteritems():
- yield pair
+class OrderedDeclarationWrapper(LazyValue):
+ def __init__(self, declaration, sequence):
+ self.declaration = declaration
+ self.sequence = sequence
- def __iter__(self):
- for k in self._unordered:
- yield k
- for k in self._ordered:
- yield k
+ def evaluate(self, obj):
+ return self.declaration.evaluate(self.sequence, obj)
class AttributeBuilder(object):
@@ -196,16 +145,16 @@ class AttributeBuilder(object):
def build(self, create):
self.factory.sequence = self.factory._generate_next_sequence()
- attributes = {}
- for key, val in self._attrs.iteritems():
- if isinstance(val, SubFactory):
- val = val.evaluate(self.factory, create, self._subfields.get(key, {}))
- elif isinstance(val, OrderedDeclaration):
- wrapper = ObjectParamsWrapper(attributes)
- val = val.evaluate(self.factory, wrapper)
- attributes[key] = val
+ wrapped_attrs = {}
+ for k, v in self._attrs.iteritems():
+ if isinstance(v, SubFactory):
+ v = SubFactoryWrapper(v, self._subfields.get(k, {}), create)
+ elif isinstance(v, OrderedDeclaration):
+ v = OrderedDeclarationWrapper(v, self.factory.sequence)
+ wrapped_attrs[k] = v
- return attributes
+ stub = LazyStub(wrapped_attrs)
+ return stub.__fill__()
class StubObject(object):
diff --git a/factory/declarations.py b/factory/declarations.py
index a1e9102..f1112c5 100644
--- a/factory/declarations.py
+++ b/factory/declarations.py
@@ -18,37 +18,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-import threading
-
-global_counter_lock = threading.Lock()
-
-class GlobalCounter(object):
- """A simple global counter.
-
- It is used to order the various OrderedDeclaration together.
- """
-
- _value = 0
-
- @classmethod
- def step(cls):
- with global_counter_lock:
- current = cls._value
- cls._value += 1
- return current
-
-
class OrderedDeclaration(object):
"""A factory declaration.
Ordered declarations keep track of the order in which they're defined so that later declarations
can refer to attributes created by earlier declarations when the declarations are evaluated."""
- _next_order = 0
-
- def __init__(self):
- self.order = GlobalCounter.step()
-
- def evaluate(self, factory, obj):
+ def evaluate(self, sequence, obj):
"""Evaluate this declaration.
Args:
@@ -64,7 +39,7 @@ class LazyAttribute(OrderedDeclaration):
super(LazyAttribute, self).__init__()
self.function = function
- def evaluate(self, factory, obj):
+ def evaluate(self, sequence, obj):
return self.function(obj)
@@ -73,7 +48,7 @@ class SelfAttribute(OrderedDeclaration):
super(SelfAttribute, self).__init__()
self.attribute_name = attribute_name
- def evaluate(self, factory, obj):
+ def evaluate(self, sequence, obj):
return getattr(obj, self.attribute_name)
@@ -83,13 +58,13 @@ class Sequence(OrderedDeclaration):
self.function = function
self.type = type
- def evaluate(self, factory, obj):
- return self.function(self.type(factory.sequence))
+ def evaluate(self, sequence, obj):
+ return self.function(self.type(sequence))
class LazyAttributeSequence(Sequence):
- def evaluate(self, factory, obj):
- return self.function(obj, self.type(factory.sequence))
+ def evaluate(self, sequence, obj):
+ return self.function(obj, self.type(sequence))
class SubFactory(OrderedDeclaration):
@@ -105,7 +80,7 @@ class SubFactory(OrderedDeclaration):
self.defaults = kwargs
self.factory = factory
- def evaluate(self, factory, create, extra):
+ def evaluate(self, create, extra):
"""Evaluate the current definition and fill its attributes.
Uses attributes definition in the following order:
diff --git a/factory/test_base.py b/factory/test_base.py
index 753f116..783e041 100644
--- a/factory/test_base.py
+++ b/factory/test_base.py
@@ -104,11 +104,7 @@ class FactoryTestCase(unittest.TestCase):
class TestObjectFactory(Factory):
one = declarations.LazyAttribute(lambda a: a.does_not_exist )
- try:
- TestObjectFactory()
- self.fail()
- except AttributeError as e:
- self.assertTrue('does not exist' in str(e))
+ self.assertRaises(AttributeError, TestObjectFactory)
def testLazyAttributeSequence(self):
class TestObjectFactory(Factory):
@@ -368,6 +364,7 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
FACTORY_FOR = TestObject
wrapped = declarations.SubFactory(TestObjectFactory)
+ friend = declarations.LazyAttribute(lambda o: o.wrapped.two.four + 1)
class OuterWrappingTestObjectFactory(Factory):
FACTORY_FOR = TestObject
@@ -375,9 +372,9 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
wrap = declarations.SubFactory(WrappingTestObjectFactory,
wrapped__two=declarations.SubFactory(TestObjectFactory, four=4))
-
outer = OuterWrappingTestObjectFactory.build()
self.assertEqual(outer.wrap.wrapped.two.four, 4)
+ self.assertEqual(outer.wrap.friend, 5)
def testStubStrategy(self):
Factory.default_strategy = STUB_STRATEGY
diff --git a/factory/test_containers.py b/factory/test_containers.py
index 627bc86..9cc0378 100644
--- a/factory/test_containers.py
+++ b/factory/test_containers.py
@@ -20,109 +20,51 @@
import unittest
-from containers import AttributeBuilder, DeclarationDict, OrderedDict, ObjectParamsWrapper
import base
+import containers
import declarations
-class ObjectParamsWrapperTestCase(unittest.TestCase):
- def test_read(self):
- vals = {'one': 1, 'two': 2}
- wrapper = ObjectParamsWrapper(vals)
+class LazyStubTestCase(unittest.TestCase):
+ def test_basic(self):
+ stub = containers.LazyStub({'one': 1, 'two': 2})
- self.assertEqual(1, wrapper.one)
- self.assertEqual(2, wrapper.two)
- self.assertRaises(AttributeError, getattr, wrapper, 'three')
- self.assertRaises(AttributeError, setattr, wrapper, 'one', 1)
+ self.assertEqual({'one': 1, 'two': 2}, stub.__fill__())
- def test_standard_attributes(self):
- wrapper = ObjectParamsWrapper({})
- self.assertEqual(ObjectParamsWrapper, wrapper.__class__)
+ def test_setting_values(self):
+ stub = containers.LazyStub({'one': 1, 'two': 2})
+ self.assertRaises(AttributeError, setattr, stub, 'one', 1)
-class OrderedDeclarationMock(object):
- def __init__(self, order):
- self.order = order
+ def test_reading_value(self):
+ stub = containers.LazyStub({'one': 1, 'two': 2})
+ self.assertEqual(1, stub.one)
+ self.assertRaises(AttributeError, getattr, stub, 'three')
-class OrderedDictTestCase(unittest.TestCase):
- def test_basics(self):
- one = OrderedDeclarationMock(1)
- two = OrderedDeclarationMock(2)
- three = OrderedDeclarationMock(3)
- d = OrderedDict(one=one, two=two, three=three)
- self.assertEqual(one, d['one'])
- self.assertEqual(two, d['two'])
- self.assertEqual(three, d['three'])
-
- self.assertTrue('one' in d)
- self.assertTrue('two' in d)
- self.assertTrue('three' in d)
-
- self.assertEqual(one, d.pop('one'))
- self.assertFalse('one' in d)
-
- d['one'] = one
- self.assertTrue('one' in d)
- self.assertEqual(one, d['one'])
-
- self.assertEqual(set(['one', 'two', 'three']),
- set(d))
+ def test_cyclic_definition(self):
+ class LazyAttr(containers.LazyValue):
+ def __init__(self, attrname):
+ self.attrname = attrname
- def test_order(self):
- one = OrderedDeclarationMock(1)
- two = OrderedDeclarationMock(2)
- ten = OrderedDeclarationMock(10)
- d = OrderedDict(one=one, two=two, ten=ten)
+ def evaluate(self, obj):
+ return 1 + getattr(obj, self.attrname)
- self.assertEqual(['one', 'two', 'ten'], list(d))
- self.assertEqual([('one', one), ('two', two), ('ten', ten)],
- d.items())
- self.assertEqual([('one', one), ('two', two), ('ten', ten)],
- list(d.iteritems()))
+ stub = containers.LazyStub({'one': LazyAttr('two'), 'two': LazyAttr('one')})
- def test_insert(self):
- one = OrderedDeclarationMock(1)
- two = OrderedDeclarationMock(2)
- four = OrderedDeclarationMock(4)
- ten = OrderedDeclarationMock(10)
- d = OrderedDict(one=one, two=two, ten=ten)
-
- self.assertEqual(['one', 'two', 'ten'], list(d))
- d['four'] = four
- self.assertEqual(['one', 'two', 'four', 'ten'], list(d))
-
- def test_replace(self):
- one = OrderedDeclarationMock(1)
- two = OrderedDeclarationMock(2)
- three = OrderedDeclarationMock(3)
- ten = OrderedDeclarationMock(10)
- d = OrderedDict(one=one, two=two, ten=ten)
-
- self.assertEqual(['one', 'two', 'ten'], list(d))
- d['one'] = three
+ self.assertRaises(containers.CyclicDefinitionError, getattr, stub, 'one')
- self.assertEqual(three, d['one'])
- self.assertEqual(['two', 'one', 'ten'], list(d))
- def test_order_conflict(self):
- one = OrderedDeclarationMock(1)
- two = OrderedDeclarationMock(1)
-
- d = OrderedDict(one=one, two=two)
- self.assertEqual(set(['one', 'two']), set(d))
-
-
-class OrderedDeclarationFullMock(declarations.OrderedDeclaration):
+class OrderedDeclarationMock(declarations.OrderedDeclaration):
pass
class DeclarationDictTestCase(unittest.TestCase):
def test_basics(self):
- one = OrderedDeclarationFullMock()
+ one = OrderedDeclarationMock()
two = 2
- three = OrderedDeclarationFullMock()
+ three = OrderedDeclarationMock()
- d = DeclarationDict(dict(one=one, two=two, three=three))
+ d = containers.DeclarationDict(dict(one=one, two=two, three=three))
self.assertTrue('one' in d)
self.assertTrue('two' in d)
@@ -142,44 +84,57 @@ class DeclarationDictTestCase(unittest.TestCase):
self.assertEqual(set(['one', 'two', 'three']),
set(d))
- def test_order(self):
- one = OrderedDeclarationFullMock()
+ def test_insert(self):
+ one = OrderedDeclarationMock()
two = 2
- three = OrderedDeclarationFullMock()
+ three = OrderedDeclarationMock()
+ four = OrderedDeclarationMock()
- d = DeclarationDict(dict(one=one, two=two, three=three))
+ d = containers.DeclarationDict(dict(one=one, two=two, four=four))
- self.assertEqual(['two', 'one', 'three'], list(d))
- self.assertEqual([('two', two), ('one', one), ('three', three)],
- list(d.items()))
- self.assertEqual([('two', two), ('one', one), ('three', three)],
- list(d.iteritems()))
+ self.assertEqual(set(['two', 'one', 'four']), set(d))
- def test_insert(self):
- one = OrderedDeclarationFullMock()
+ d['three'] = three
+ self.assertEqual(set(['two', 'one', 'three', 'four']), set(d))
+
+ def test_replace(self):
+ one = OrderedDeclarationMock()
two = 2
- three = OrderedDeclarationFullMock()
- four = OrderedDeclarationFullMock()
+ three = OrderedDeclarationMock()
+ four = OrderedDeclarationMock()
- d = DeclarationDict(dict(one=one, two=two, four=four))
+ d = containers.DeclarationDict(dict(one=one, two=two, three=three))
- self.assertEqual(['two', 'one', 'four'], list(d))
+ self.assertEqual(set(['two', 'one', 'three']), set(d))
- d['three'] = three
- self.assertEqual(['two', 'one', 'three', 'four'], list(d))
+ d['three'] = four
+ self.assertEqual(set(['two', 'one', 'three']), set(d))
+ self.assertEqual(set([two, one, four]), set(d.values()))
- def test_replace(self):
- one = OrderedDeclarationFullMock()
+ def test_copy(self):
+ one = OrderedDeclarationMock()
two = 2
- three = OrderedDeclarationFullMock()
- four = OrderedDeclarationFullMock()
+ three = OrderedDeclarationMock()
+ four = OrderedDeclarationMock()
+
+ d = containers.DeclarationDict(dict(one=one, two=two, three=three))
+ d2 = d.copy({'five': 5})
- d = DeclarationDict(dict(one=one, two=two, three=three))
+ self.assertEqual(5, d2['five'])
+ self.assertFalse('five' in d)
- self.assertEqual(['two', 'one', 'three'], list(d))
+ d.pop('one')
+ self.assertEqual(one, d2['one'])
+
+ d2['two'] = four
+ self.assertEqual(four, d2['two'])
+ self.assertEqual(two, d['two'])
- d['one'] = four
- self.assertEqual(['two', 'three', 'one'], list(d))
+ def test_update_with_public(self):
+ d = containers.DeclarationDict()
+ d.update_with_public({'one': 1, '_two': 2, 'three': 3})
+ self.assertEqual(set(['one', 'three']), set(d))
+ self.assertEqual(set([1, 3]), set(d.values()))
class AttributeBuilderTestCase(unittest.TestCase):
@@ -195,7 +150,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory)
+ ab = containers.AttributeBuilder(FakeFactory)
self.assertEqual({}, ab.build(create=False))
@@ -211,7 +166,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory)
+ ab = containers.AttributeBuilder(FakeFactory)
self.assertEqual({'one': 1}, ab.build(create=False))
def test_extended(self):
@@ -226,7 +181,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory, {'two': 2})
+ ab = containers.AttributeBuilder(FakeFactory, {'two': 2})
self.assertEqual({'one': 1, 'two': 2}, ab.build(create=False))
def test_overridden(self):
@@ -241,7 +196,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory, {'one': 2})
+ ab = containers.AttributeBuilder(FakeFactory, {'one': 2})
self.assertEqual({'one': 2}, ab.build(create=False))
def test_factory_defined_sequence(self):
@@ -258,7 +213,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory)
+ ab = containers.AttributeBuilder(FakeFactory)
self.assertEqual({'one': 'xx1'}, ab.build(create=False))
def test_additionnal_sequence(self):
@@ -275,7 +230,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory, extra={'two': seq})
+ ab = containers.AttributeBuilder(FakeFactory, extra={'two': seq})
self.assertEqual({'one': 1, 'two': 'xx1'}, ab.build(create=False))
def test_replaced_sequence(self):
@@ -293,7 +248,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory, extra={'one': seq2})
+ ab = containers.AttributeBuilder(FakeFactory, extra={'one': seq2})
self.assertEqual({'one': 'yy1'}, ab.build(create=False))
def test_lazy_attribute(self):
@@ -302,7 +257,7 @@ class AttributeBuilderTestCase(unittest.TestCase):
class FakeFactory(object):
@classmethod
def declarations(cls, extra):
- d = DeclarationDict({'one': 1, 'two': la})
+ d = containers.DeclarationDict({'one': 1, 'two': la})
d.update(extra)
return d
@@ -310,13 +265,13 @@ class AttributeBuilderTestCase(unittest.TestCase):
def _generate_next_sequence(cls):
return 1
- ab = AttributeBuilder(FakeFactory)
+ ab = containers.AttributeBuilder(FakeFactory)
self.assertEqual({'one': 1, 'two': 2}, ab.build(create=False))
- ab = AttributeBuilder(FakeFactory, {'one': 4})
+ ab = containers.AttributeBuilder(FakeFactory, {'one': 4})
self.assertEqual({'one': 4, 'two': 8}, ab.build(create=False))
- ab = AttributeBuilder(FakeFactory, {'one': 4, 'three': la})
+ ab = containers.AttributeBuilder(FakeFactory, {'one': 4, 'three': la})
self.assertEqual({'one': 4, 'two': 8, 'three': 8}, ab.build(create=False))
def test_sub_factory(self):
diff --git a/factory/test_declarations.py b/factory/test_declarations.py
index 27d5f9e..f692ccf 100644
--- a/factory/test_declarations.py
+++ b/factory/test_declarations.py
@@ -20,28 +20,12 @@
import unittest
-from declarations import GlobalCounter, OrderedDeclaration, Sequence
-
-class GlobalCounterTestCase(unittest.TestCase):
- def test_incr(self):
- init = GlobalCounter.step()
- mid = GlobalCounter.step()
- last = GlobalCounter.step()
- self.assertEqual(2, last - init)
- self.assertEqual(1, mid - init)
-
+from declarations import OrderedDeclaration, Sequence
class OrderedDeclarationTestCase(unittest.TestCase):
def test_errors(self):
decl = OrderedDeclaration()
self.assertRaises(NotImplementedError, decl.evaluate, None, {})
- def test_order(self):
- decl1 = OrderedDeclaration()
- decl2 = OrderedDeclaration()
- decl3 = Sequence(lambda n: 3 * n)
- self.assertTrue(decl1.order < decl2.order)
- self.assertTrue(decl2.order < decl3.order)
-
if __name__ == '__main__':
unittest.main()