def test_factory_with_args(self):
        Point  = mutabletuple('Point', [('x', 0), ('y', 0)])
        Vector = mutabletuple('Vector', [('p1', MtFactory(Point, 2)), ('p2', MtFactory(Point, 4, 8))])

        v1     = Vector()
        self.assertEqual(v1, Vector(Point(2, 0), Point(4, 8)))
        self.assertEqual(str(v1), "{'p1': {'x': 2, 'y': 0}, 'p2': {'x': 4, 'y': 8}}")
    def test_nested(self):
        Point  = mutabletuple('Point', [('x', 0), ('y', 0)])
        Vector = mutabletuple('Vector', [('p1', MtFactory(Point)), ('p2', MtFactory(Point))])
        Shape  = mutabletuple('Shape', [('v1', MtFactory(Vector)), ('v2', MtFactory(Vector))])

        s = Shape()
        self.assertEqual(str(s), "{'v1': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}}")
        self.assertEqual(s._asdict(), {'v1': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}})

        s.v1.p2.y = 30
        self.assertEqual(str(s), "{'v1': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 30}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}}")
        self.assertEqual(s._asdict(), {'v1': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 30}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}})
    def test_dict(self):
        Point  = mutabletuple('Point', [('x', 0), ('y', 0)])
        Vector = mutabletuple('Vector', [('p1', MtFactory(Point)), ('p2', MtFactory(Point))])
        Shape  = mutabletuple('Shape', [('v1', MtFactory(Vector)), ('v2', MtFactory(Vector))])

        p = Point(10, 20)
        self.assertEqual(p._asdict(), {'x': 10, 'y': 20})

        s1 = Shape(Vector(Point(3, 4)))
        s2 = Shape()
        s2.merge(s1._asdict())
        self.assertEqual(s1, s2)
 def test_default(self):
     Point = mutabletuple('Point', 'x y z', default=100)
     self.assertEqual(Point(), Point(100, 100, 100))
     self.assertEqual(Point(10), Point(10, 100, 100))
     self.assertEqual(Point(10, 20), Point(10, 20, 100))
     self.assertEqual(Point(10, 20, 30), Point(10, 20, 30))
     self.assertEqual(Point()._asdict(), {'x': 100, 'y': 100, 'z': 100})
    def test_merge(self):
        Point  = mutabletuple('Point', [('x', 0), ('y', 0)])
        Vector = mutabletuple('Vector', [('p1', MtFactory(Point)), ('p2', MtFactory(Point))])
        Shape  = mutabletuple('Shape', [('v1', MtFactory(Vector)), ('v2', MtFactory(Vector))])

        s = Shape()
        d = {'v1': {'p1': {'x': 20}, 'p2': Point(30, 40)}}
        s.merge(d)
        self.assertEqual(str(s), "{'v1': {'p1': {'x': 20, 'y': 0}, 'p2': {'x': 30, 'y': 40}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}}")
        self.assertEqual(s._asdict(), {'v1': {'p1': {'x': 20, 'y': 0}, 'p2': {'x': 30, 'y': 40}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}})

        s = Shape()
        d = OrderedDict([('v1', OrderedDict([('p1', OrderedDict([('x', 20)]))]))])
        s.merge(d)
        self.assertEqual(str(s), "{'v1': {'p1': {'x': 20, 'y': 0}, 'p2': {'x': 0, 'y': 0}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}}")
        self.assertEqual(s._asdict(), {'v1': {'p1': {'x': 20, 'y': 0}, 'p2': {'x': 0, 'y': 0}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}})
 def test_MtNoDefault(self):
     # MtNoDefault is only really useful with we're using a mapping
     #  plus a default value. it's the only way to specify that
     #  some of the fields use the default.
     Point = mutabletuple('Point', {'x':0, 'y':MtNoDefault}, default=5)
     p = Point()
     self.assertEqual(p.x, 0)
     self.assertEqual(p.y, 5)
 def test_setitem(self):
     Point = mutabletuple('Point', 'a b')
     p = Point(1, 2)
     p[0] = 10
     self.assertEqual(list(p), [10, 2])
     p[1] = 20
     self.assertEqual(list(p), [10, 20])
     self.assertRaises(IndexError, p.__setitem__, 2, 3)
    def test_simple(self):
        # Declare members as string
        Point = mutabletuple('Point', 'x y')
        p = Point(10, 20)
        self.assertEqual(str(p), "{'x': 10, 'y': 20}")

        # Declare members as list
        Point = mutabletuple('Point', ['x', 'y'])
        p = Point(10, 20)
        self.assertEqual(str(p), "{'x': 10, 'y': 20}")

        # Declare members as list with default
        Point = mutabletuple('Point', [('x', 10), ('y', 20)])
        p = Point()
        self.assertEqual(str(p), "{'x': 10, 'y': 20}")

        self.assertEqual(Point(10, 11), Point(10, 11))
        self.assertNotEqual(Point(10, 11), Point(10, 12))
 def test_writable(self):
     Point = mutabletuple('Point', ['x', ('y', 10), ('z', 20)], 100)
     p = Point(0)
     self.assertEqual((p.x, p.y, p.z), (0, 10, 20))
     p.x = -1
     self.assertEqual((p.x, p.y, p.z), (-1, 10, 20))
     p.y = -1
     self.assertEqual((p.x, p.y, p.z), (-1, -1, 20))
     p.z = None
     self.assertEqual((p.x, p.y, p.z), (-1, -1, None))
    def test_factory_and_nested(self):
        Point  = mutabletuple('Point', [('x', 0), ('y', 0)])
        Vector = mutabletuple('Vector', [('p1', MtFactory(Point)), ('p2', MtFactory(Point))])
        Shape  = mutabletuple('Shape', [('v1', MtFactory(Vector)), ('v2', MtFactory(Vector))])
        p1     = Point()
        p2     = Point()
        v1     = Vector(Point(0, 0), Point(0, 0))
        v2     = Vector()
        s1     = Shape(Vector(Point(0, 0), Point(0, 0)), Vector())
        s2     = Shape()

        # Test that modifying p2 do not modify p1
        p2.x = 20
        self.assertNotEqual(id(p1), id(p2))
        self.assertEqual(p1, Point())
        self.assertEqual(str(p1), "{'x': 0, 'y': 0}")

        # Test that every new object is unique
        self.assertNotEqual(id(v1), id(v2))
        self.assertNotEqual(id(v1.p1), id(v2.p1))
        self.assertNotEqual(id(v1.p2), id(v2.p2))
        self.assertNotEqual(id(v1.p1), id(v1.p2))
        self.assertNotEqual(id(v2.p1), id(v2.p2))

        # Test that modifying v2 do not modify v1
        v2.p1.x = 20
        self.assertEqual(v1, Vector())
        self.assertEqual(str(v1), "{'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}")


        # Test that every new object is unique
        self.assertNotEqual(id(s1), id(s2))
        self.assertNotEqual(id(s1.v1), id(s2.v1))
        self.assertNotEqual(id(s1.v2), id(s2.v2))
        self.assertNotEqual(id(s1.v1), id(s1.v2))
        self.assertNotEqual(id(s2.v1), id(s2.v2))

        # Test that modifying s2 do not modify s1
        s2.v1.p1.x = 20
        self.assertEqual(s1, Shape())
        self.assertEqual(str(s1), "{'v1': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}, 'v2': {'p1': {'x': 0, 'y': 0}, 'p2': {'x': 0, 'y': 0}}}")
    def test_iteration(self):
        Point = mutabletuple('Point', ['x', ('y', 10), ('z', 20)], [1, 2, 3])
        p = Point()
        self.assertEqual(len(p), 3)

        self.assertEqual(list(iter(p)), [[1, 2, 3], 10, 20])

        for expected, found in zip([[1, 2, 3], 10, 20], p):
            self.assertEqual(expected, found)

        for expected, found in zip((('x', [1, 2, 3]), ('y', 10), ('z', 20)), p.iteritems()):
            self.assertEqual(expected, found)
        p[1] = 20
        self.assertEqual(list(p), [10, 20])
        self.assertRaises(IndexError, p.__setitem__, 2, 3)


# *****************************************************************************
# Pickle test
# *****************************************************************************
# test both pickle and cPickle in 2.x, but just pickle in 3.x
try:
    import cPickle
    pickle_modules = (pickle, cPickle)
except ImportError:
    pickle_modules = (pickle,)

# types used for pickle tests
TestMT0 = mutabletuple('TestMT0', '')
TestMT1 = mutabletuple('TestMT1', 'x y z', default=4)
TestMT2 = mutabletuple('TestMT2', [('mt1', MtFactory(TestMT1, 50, 60, 70)), ('a', 1), ('b', [2, 3, 4])])

# Warning Pickling does not work for mutabletuple that have no default values.
class TestMutableTuplePickle(unittest.TestCase):
    def test_pickle(self):
        for p in (TestMT0(), TestMT1(x=10, y=20, z=30), TestMT2()):
            for module in pickle_modules:
                for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
                    q = module.loads(module.dumps(p, protocol))
                    self.assertEqual(p, q)
                    self.assertEqual(p._fields, q._fields)
                    self.assertNotIn(b'OrderedDict', module.dumps(p, protocol))
 def test_factory_repr(self):
     Point  = mutabletuple('Point', [('x', 0), ('y', 0)])
     self.assertEqual(str(MtFactory(Point, 2)), "{'x': 2, 'y': 0}")
 def test_ordered_dict_simple(self):
     Point = mutabletuple('Point', ['x', 'y'])
     p = Point(10, 20)
     self.assertEqual(p.orderedDict(), OrderedDict([('x', 10), ('y', 20)]))
 def test_getitem(self):
     Point = mutabletuple('Point', 'a b')
     p = Point(1, 2)
     self.assertEqual((p[0], p[1]), (1, 2))
     self.assertEqual(list(p), [1, 2])
     self.assertRaises(IndexError, p.__getitem__, 2)
 def test_unknown_key(self):
     Point = mutabletuple('Point', 'x y')
     p = Point(10, 20)
     self.assertRaises(AttributeError, getattr, p, 'z')
     self.assertRaises(AttributeError, setattr, p, 'z', 30)
 def test_unique_identifier(self):
     Point = mutabletuple('Point', 'x y')
     p = Point(10, 20)
     self.assertTrue(hasattr(p, 'MutableTupleUniqueIdentifier'))