Share Pastebin
Guest
Public paste!

Eduardo Padoan

By: a guest | Feb 17th, 2008 | Syntax: Python | Size: 5.27 KB | Hits: 416 | Expires: Never
Copy text to clipboard
  1. import unittest
  2. from copy import copy
  3.  
  4.  
  5. class Proto(object):
  6.     """ A prototype object.
  7.    """
  8.  
  9.     def __init__(self, wrapped=None, proto=None):
  10.         self._wrapped = wrapped
  11.         self.proto = proto
  12.         self._protos = [proto] # +/- like __mro__
  13.  
  14.         try:
  15.             # instantialize the state of the clone
  16.             self.init(self)
  17.         except AttributeError:
  18.             pass
  19.  
  20.     def __getattr__(self, name):
  21.         #### diferential inheritance ####
  22.         # __getattr__ is only called
  23.         # when the attribute is not found
  24.         try:
  25.             value = getattr(self._wrapped, name)
  26.         except AttributeError:
  27.             for proto in self._protos:
  28.                 try:
  29.                     value = getattr(proto, name)
  30.                     break
  31.                 except AttributeError:
  32.                     continue
  33.             else:
  34.                 raise AttributeError('Object %r have no %s attribute.'
  35.                                      % (self, name))
  36.         return value
  37.  
  38.     def __repr__(self):
  39.         return '<object %r>' % self._wrapped
  40.  
  41.     @property
  42.     def protos(self):
  43.         for proto in self._protos:
  44.             if proto is not None:
  45.                 yield proto
  46.                 # ask the protos for its protos...
  47.                 for super_proto in proto.protos:
  48.                     if super_proto is not None:
  49.                         yield super_proto
  50.  
  51.     def clone(self):
  52.         """ Create a new object, based on this one.
  53.        """
  54.         wrapped = self._wrapped
  55.         try:
  56.             # if the object is immutable,
  57.             # no problem sharing it
  58.             hash(wrapped)
  59.             return Proto(wrapped, self)
  60.         except TypeError:
  61.             return Proto(copy(wrapped), self)
  62.  
  63.     def append_proto(self, proto):
  64.         self._protos.append(proto)
  65.  
  66.     def prepend_proto(self, proto):
  67.         self._protos.insert(0, proto)
  68.  
  69.     def remove_proto(self, proto):
  70.         self._protos.remove(proto)
  71.  
  72.  
  73. class TestProto(unittest.TestCase):
  74.  
  75.     def test_wraps(self):
  76.         obj = Proto('hello')
  77.         self.assertFalse(obj.isupper())
  78.         self.assertTrue(obj.islower())
  79.         self.assertTrue(obj.isalpha())
  80.         c1 = obj.clone()
  81.         self.assertFalse(c1.isdigit())
  82.         self.assertFalse(c1.isspace())
  83.         self.assertEqual(c1.title(), 'Hello')
  84.         self.assertRaises(AttributeError, getattr, c1, 'append')
  85.  
  86.     def test_clone_and_protos(self):
  87.         obj = Proto(42)
  88.         self.assertEqual(repr(obj), '<object 42>')
  89.         self.assertEqual(None, obj.proto)
  90.         clone = obj.clone()
  91.         proto_a = clone.proto
  92.         proto_b = list(clone.protos).pop()
  93.         self.assertEqual(proto_a, proto_b)
  94.         self.assertNotEqual(obj.proto, proto_a)
  95.         self.assertNotEqual(obj.proto, proto_b)
  96.         self.assertEqual(list(clone.protos), [obj])
  97.  
  98.         c2 = clone.clone()
  99.         c3 = c2.clone()
  100.         c4 = c3.clone()
  101.         self.assertEqual(list(c2.protos), [clone, obj])
  102.         self.assertEqual(list(c3.protos), [c2, clone, obj])
  103.         self.assertEqual(list(c4.protos), [c3, c2, clone, obj])
  104.  
  105.     def test_init(self):
  106.         Movie = Proto("Movie")
  107.         def init(self):
  108.             self.cast = []
  109.         Movie.init = init
  110.         some_movie = Movie.clone()
  111.         self.assertEqual(some_movie.cast, [])
  112.         some_movie.cast.append('Some Actor')
  113.         another_movie  = Movie.clone()
  114.         self.assertEqual(another_movie.cast, [])
  115.         self.assertNotEqual(another_movie.cast, some_movie.cast)
  116.  
  117.     def test_inheritance(self):
  118.         obj = Proto('foo')
  119.         obj.bar = 'baz'
  120.         c1 = obj.clone()
  121.         self.assertEqual(obj.bar, c1.bar)
  122.         self.assertEqual(c1.bar, 'baz')
  123.         obj.baz = 'foo'
  124.         self.assertEqual(obj.baz, c1.baz)
  125.         self.assertEqual(c1.baz, 'foo')
  126.         obj.quux = 'foobar'
  127.         self.assertEqual(obj.quux, c1.quux)
  128.         self.assertEqual(c1.quux, 'foobar')
  129.  
  130.         c2 = c1.clone()
  131.         c3 = c2.clone()
  132.  
  133.         self.assertEqual(obj.bar, c2.bar)
  134.         self.assertEqual(c2.bar, 'baz')
  135.         self.assertEqual(obj.quux, c2.quux)
  136.         self.assertEqual(c2.quux, 'foobar')
  137.  
  138.         self.assertEqual(obj.bar, c3.bar)
  139.         self.assertEqual(c3.bar, 'baz')
  140.         self.assertEqual(obj.quux, c3.quux)
  141.         self.assertEqual(c3.quux, 'foobar')
  142.  
  143.         self.assertEqual(c2.bar, c3.bar)
  144.         self.assertEqual(c1.bar, c2.bar)
  145.         self.assertEqual(c1.bar, c3.bar)
  146.  
  147.         self.assertEqual(c2.quux, c3.quux)
  148.         self.assertEqual(c1.quux, c2.quux)
  149.         self.assertEqual(c1.quux, c3.quux)
  150.  
  151.         obj.bar = 42
  152.         self.assertEqual(obj.bar, c3.bar)
  153.         self.assertEqual(c3.bar, 42)
  154.  
  155.         obj2 = Proto('bar')
  156.         c3.prepend_proto(obj2)
  157.         obj2.baz = 'hello'
  158.         self.assertEqual(c3.bar, 42)
  159.         self.assertEqual(c3.baz, 'hello')
  160.  
  161.         obj3 = Proto('baz')
  162.         c3.append_proto(obj3)
  163.         obj3.quuuux = 'quuuux'
  164.         obj3.bar = 'quuuux'
  165.         self.assertEqual(c3.bar, 42)
  166.         self.assertEqual(c3.baz, 'hello')
  167.         self.assertEqual(c3.quuuux, 'quuuux')
  168.  
  169.         c3.remove_proto(obj3)
  170.         self.assertRaises(AttributeError, getattr, obj3, 'quuux')
  171.  
  172.  
  173. if __name__ == '__main__':
  174.     unittest.main()