Commits

Jesper Nøhr committed f0e5992

FollowAble things now map via a metaclass and are returned accordingly

Comments (0)

Files changed (2)

src/rewsfeed/models.py

     # --
 
     def __repr__(self):
-        return '<'+', '.join([ '%s=%s' % (k, v[0:255]) for k, v in self.kw.iteritems() ])+'>'
+        return '<'+self.__class__.__name__+': '+', '.join([ '%s=%s' % (k, v[0:255]) for k, v in self.kw.iteritems() ])+'>'
 
+class FollowAbleConstruct(object):
+    def __init__(self):
+        self.prefixes = { }
+
+    def class_from_prefix(self, prefix):
+        for p, klass in self.prefixes.iteritems():
+            if p == prefix[:2]:
+                return klass
+        return None
+        
+fac = FollowAbleConstruct()
+        
+class FollowAbleMeta(type):
+    def __new__(cls, name, bases, attrs):
+        new_cls = type.__new__(cls, name, bases, attrs)
+
+        if not name in ('FollowAble',):
+            prefix = attrs.get('prefix')
+            
+            def prefix_key(*args, **kwargs):
+                return prefix+attrs.get('key')(*args, **kwargs)                
+
+            new_cls.key = prefix_key
+
+            fac.prefixes[prefix] = new_cls
+            
+        return new_cls
+    
 class FollowAble(DictAbstracted):
+    __metaclass__ = FollowAbleMeta
+    
     def follow(self, other_thing):
         """
         Follows another thing. Adds both forward and reverse
         blocked_key = Op.BLOCKED_KEY+self.key()
 
         for thing in self.network.sdiff((follows_key, blocked_key)):
-            yield self.__class__(self.network, **self.network.hgetall(Op.DATA_KEY+thing))
+            yield fac.class_from_prefix(thing)(self.network, **self.network.hgetall(Op.DATA_KEY+thing))
 
     def followers(self):
         followers_key = Op.FOLLOWERS_KEY+self.key()
         blocks_key = Op.BLOCKS_KEY+self.key()
 
         for thing in self.network.sdiff((followers_key, blocks_key)):
-            yield self.__class__(self.network, **self.network.hgetall(Op.DATA_KEY+thing))
+            yield fac.class_from_prefix(thing)(self.network, **self.network.hgetall(Op.DATA_KEY+thing))
         
     # -- Events
 
 
 # Set up a simple User.
 class User(FollowAble):
+    prefix = 'U+'
+    
     def key(self, extra=''):
-        return 'U+'+md5(self.kw['username']+extra).hexdigest()
+        return md5(self.kw['username']+extra).hexdigest()
 
 # And a simple Repository.
 class Repository(FollowAble):
+    prefix = 'R+'
+    
     def key(self, extra=''):
-        return 'R+'+md5(self.kw['username']+self.kw['slug']+extra).hexdigest()
+        return md5(self.kw['username']+self.kw['slug']+extra).hexdigest()
     
 class TestNetwork(unittest.TestCase):
     def test_network_init(self):
         spamalot(num_users*4)
 
         self.assertEquals(len(list(self.u1.newsfeed(BaseEvent, 0, num_users*4))), 67*5)
+
+class TestUserFollowsRepo(unittest.TestCase):
+    def setUp(self):
+        self.n = Network('events')
+        self.n.conn.flushdb()
+
+        self.u1 = User(self.n, username='user1')
+        self.u1.save()
+
+        self.u2 = User(self.n, username='user2')
+        self.u2.save()
+
+        self.repo = Repository(self.n, username='user1', slug='testhest')
+        self.repo.save()
         
+    def test_user_follow_repo(self):
+        self.u1.follow(self.repo)
+
+        for thing in self.u1.following():
+            self.assertTrue(repr(thing).startswith("<Repository"))
+            self.assertTrue(isinstance(thing, Repository))
+            
+        for who in self.repo.followers():
+            self.assertTrue(repr(who).startswith("<User"))
+            self.assertTrue(isinstance(who, User))
+            
 if __name__ == "__main__":
     unittest.main()