Commits

Brent Tubbs  committed 90b53f2

use metaclass to provide key when not passed into Field init. Less repetitive.

  • Participants
  • Parent commits 6e8682c
  • Tags 0.0.8

Comments (0)

Files changed (2)

 
 setup(
     name='trollop',
-    version='0.0.7',
+    version='0.0.8',
     author='Brent Tubbs',
     author_email='brent.tubbs@gmail.com',
 	packages=find_packages(),

File trollop/lib.py

         return Member(self, 'me')
 
 
+
+class Closable(object):
+    """
+    Mixin for Trello objects for which you're allowed to PUT to <id>/closed.
+    """
+    def close(self):
+        path = self._prefix + self._id + '/closed'
+        params = {'value': 'true'}
+        result = self._conn.put(path, params=params)
+
+
+class Field(object):
+    """
+    A simple field on a Trello object.  Maps the attribute to a key in the
+    object's _data dict.
+    """
+
+    def __init__(self, key=None):
+        self.key = key
+
+    def __get__(self, instance, owner):
+        # Accessing instance._data will trigger a fetch from Trello if the
+        # _data attribute isn't already present.
+        return instance._data[self.key]
+
+
+class DateField(Field):
+
+    def __get__(self, instance, owner):
+        raw = super(DateField, self).__get__(instance, owner)
+        return isodate.parse_datetime(raw)
+
+
+class ObjectField(Field):
+    """
+    Maps an idSomething string attr on an object to another object type.
+    """
+
+    def __init__(self, key, cls):
+
+        self.key = key
+        self.cls = cls
+
+    def __get__(self, instance, owner):
+        return self.related_instance(instance._conn, instance._data[self.key])
+
+    def related_instance(self, conn, obj_id):
+        return get_class(self.cls)(conn, obj_id)
+
+
+class ListField(ObjectField):
+    """
+    Like an ObjectField, but a list of them.  For fleshing out things like
+    idMembers.
+    """
+
+    def __get__(self, instance, owner):
+        ids = instance._data[self.key]
+        conn = instance._conn
+        return [self.related_instance(conn, id) for id in ids]
+
+
+class SubList(object):
+    """
+    Kinda like a ListField, but for things listed under a URL subpath (like
+    /boards/<id>/cards), as opposed to a list of ids in the document body
+    itself.
+    """
+
+    def __init__(self, cls):
+        # cls may be a name of a class, or the class itself
+        self.cls = cls
+
+        # A dict of sublists, by instance id
+        self._lists = {}
+
+    def __get__(self, instance, owner):
+        if not instance._id in self._lists:
+            cls = get_class(self.cls)
+            path = instance._prefix + instance._id + cls._prefix
+            data = json.loads(instance._conn.get(path))
+            self._lists[instance._id] = [cls(instance._conn, d['id'], d) for d in data]
+        return self._lists[instance._id]
+
+
+class TrelloMeta(type):
+    """
+    Metaclass for LazyTrello objects, allowing documents to have Field
+    attributes that know their names without them having to be explicitly
+    passed to __init__.
+    """
+    def __new__(cls, name, bases, dct):
+        for k, v in dct.items():
+            # For every Field on the class that wasn't initted with an explicit
+            # 'key', set the field name as the key.
+            if isinstance(v, Field) and v.key is None:
+                v.key = k
+        return super(TrelloMeta, cls).__new__(cls, name, bases, dct)
+
+
 class LazyTrello(object):
     """
     Parent class for Trello objects (cards, lists, boards, members, etc).  This
     should always be subclassed, never used directly.
     """
+
+    __metaclass__ = TrelloMeta
+
     # The Trello API path where objects of this type may be found. eg '/cards/'
     @property
     def _prefix(self):
             raise AttributeError("%r object has no attribute %r" %
                                  (type(self).__name__, attr))
 
+### BEGIN ACTUAL WRAPPER OBJECTS
 
-class Closable(object):
-    """
-    Mixin for Trello objects for which you're allowed to PUT to <id>/closed.
-    """
-    def close(self):
-        path = self._prefix + self._id + '/closed'
-        params = {'value': 'true'}
-        result = self._conn.put(path, params=params)
-
-
-class Field(object):
-    """
-    A simple field on a Trello object.  Maps the attribute to a key in the
-    object's _data dict.
-    """
-    # Accessing obj._data will trigger a fetch from Trello if _data isn't
-    # already present.
-
-    def __init__(self, key):
-        self.key = key
-
-    def __get__(self, instance, owner):
-        return instance._data[self.key]
-
-
-class DateField(Field):
-
-    def __get__(self, instance, owner):
-        strdata = instance._data[self.key]
-        return isodate.parse_datetime(strdata)
-
-
-class ObjectField(Field):
-    """
-    Maps an idSomething string attr on an object to another object type.
-    """
-
-    def __init__(self, key, cls):
-
-        self.key = key
-        self.cls = cls
-
-    def __get__(self, instance, owner):
-        return self.related_instance(instance._conn, instance._data[self.key])
-
-    def related_instance(self, conn, obj_id):
-        return get_class(self.cls)(conn, obj_id)
-
-
-class ListField(ObjectField):
-    """
-    Like an ObjectField, but a list of them.  For fleshing out things like
-    idMembers.
-    """
-
-    def __get__(self, instance, owner):
-        ids = instance._data[self.key]
-        conn = instance._conn
-        return [self.related_instance(conn, id) for id in ids]
-
-
-class SubList(object):
-    """
-    Kinda like a ListField, but for things listed under a URL subpath (like
-    /boards/<id>/cards), as opposed to a list of ids in the document body
-    itself.
-    """
-
-    def __init__(self, cls):
-        # cls may be a name of a class, or the class itself
-        self.cls = cls
-
-        # A dict of sublists, by instance id
-        self._lists = {}
-
-    def __get__(self, instance, owner):
-        if not instance._id in self._lists:
-            cls = get_class(self.cls)
-            path = instance._prefix + instance._id + cls._prefix
-            data = json.loads(instance._conn.get(path))
-            self._lists[instance._id] = [cls(instance._conn, d['id'], d) for d in data]
-        return self._lists[instance._id]
-
-### BEGIN ACTUAL WRAPPER OBJECTS
 
 class Action(LazyTrello):
 
     _prefix = '/actions/'
-    data = Field('data')
-    type = Field('type')
-    date = DateField('date')
+    data = Field()
+    type = Field()
+    date = DateField()
     creator = ObjectField('idMemberCreator', 'Member')
 
 
 
     _prefix = '/boards/'
 
-    url = Field('url')
-    name = Field('name')
-    pinned = Field('pinned')
-    prefs = Field('prefs')
-    desc = Field('desc')
-    closed = Field('closed')
+    url = Field()
+    name = Field()
+    pinned = Field()
+    prefs = Field()
+    desc = Field()
+    closed = Field()
 
     organization = ObjectField('idOrganization', 'Organization')
 
 
     _prefix = '/cards/'
 
-    url = Field('url')
-    closed = Field('closed')
-    name = Field('name')
-    badges = Field('badges')
-    checkItemStates = Field('checkItemStates')
-    desc = Field('desc')
-    labels = Field('labels')
+    url = Field()
+    closed = Field()
+    name = Field()
+    badges = Field()
+    checkItemStates = Field()
+    desc = Field()
+    labels = Field()
 
     board = ObjectField('idBoard', 'Board')
     list = ObjectField('idList', 'List')
 class Checklist(LazyTrello):
 
     _prefix = '/checklists/'
-    checkitems = Field('checkitems')
-    name = Field('name')
+    checkitems = Field()
+    name = Field()
     board = ObjectField('idBoard', 'Board')
     cards = SubList('Card')
 
 
     _prefix = '/lists/'
 
-    closed = Field('closed')
-    name = Field('name')
-    url = Field('url')
+    closed = Field()
+    name = Field()
+    url = Field()
     board = ObjectField('idBoard', 'Board')
     cards = SubList('Card')
 
 
     _prefix = '/members/'
 
-    url = Field('url')
+    url = Field()
     fullname = Field('fullName')
-    username = Field('username')
+    username = Field()
 
     actions = SubList('Action')
     boards = SubList('Board')
 
     _prefix = '/notifications/'
 
-    data = Field('data')
-    date = DateField('date')
-    type = Field('type')
-    unread = Field('unread')
+    data = Field()
+    date = DateField()
+    type = Field()
+    unread = Field()
 
     creator = ObjectField('idMemberCreator', 'Member')
 
 
     _prefix = '/organizations/'
 
-    url = Field('url')
-    desc = Field('desc')
+    url = Field()
+    desc = Field()
     displayname = Field('displayName')
-    name = Field('name')
+    name = Field()
 
     actions = SubList('Action')
     boards = SubList('Board')