All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
   2 Provides lazy implementations for Task and TaskQuerySet.
 
   6 class LazyUUIDTask(object):
 
   8     A lazy wrapper around Task object, referenced by UUID.
 
  10     - Supports comparison with LazyUUIDTask or Task objects (equality by UUIDs)
 
  11     - If any attribute other than 'uuid' requested, a lookup in the
 
  12       backend will be performed and this object will be replaced by a proper
 
  16     def __init__(self, tw, uuid):
 
  20     def __getitem__(self, key):
 
  21         # LazyUUIDTask does not provide anything else other than 'uuid'
 
  28     def __getattr__(self, name):
 
  29         # Getattr is called only if the attribute could not be found using
 
  32         return getattr(self, name)
 
  34     def __eq__(self, other):
 
  35         if other and other['uuid']:
 
  36             # For saved Tasks, just define equality by equality of uuids
 
  37             return self['uuid'] == other['uuid']
 
  39     def __ne__(self, other):
 
  40         return not self.__eq__(other)
 
  43         return self['uuid'].__hash__()
 
  46         return "LazyUUIDTask: {0}".format(self._uuid)
 
  49         return LazyUUIDTask(self._tw, self._uuid)
 
  51     def __deepcopy__(self, memo):
 
  52         return LazyUUIDTask(self._tw, self._uuid)
 
  57         Implementation of the 'saved' property. Always returns True.
 
  62     def _modified_fields(self):
 
  71         Performs conversion to the regular Task object, referenced by the
 
  75         replacement = self._tw.tasks.get(uuid=self._uuid)
 
  76         self.__class__ = replacement.__class__
 
  77         self.__dict__ = replacement.__dict__
 
  80 class LazyUUIDTaskSet(object):
 
  82     A lazy wrapper around TaskQuerySet object, for tasks referenced by UUID.
 
  84     - Supports 'in' operator with LazyUUIDTask or Task objects
 
  85     - If iteration over the objects in the LazyUUIDTaskSet is requested, the
 
  86       LazyUUIDTaskSet will be converted to QuerySet and evaluated
 
  89     def __init__(self, tw, uuids):
 
  91         self._uuids = set(uuids)
 
  93     def __getattr__(self, name):
 
  94         # Getattr is called only if the attribute could not be found using
 
  97         if name.startswith('__'):
 
  98             # If some internal method was being search, do not convert
 
  99             # to TaskQuerySet just because of that
 
 103             return getattr(self, name)
 
 106         return "LazyUUIDTaskSet([{0}])".format(', '.join(self._uuids))
 
 108     def __eq__(self, other):
 
 109         return set(t['uuid'] for t in other) == self._uuids
 
 111     def __ne__(self, other):
 
 112         return not (self == other)
 
 114     def __contains__(self, task):
 
 115         return task['uuid'] in self._uuids
 
 118         return len(self._uuids)
 
 121         for uuid in self._uuids:
 
 122             yield LazyUUIDTask(self._tw, uuid)
 
 124     def __sub__(self, other):
 
 125         return self.difference(other)
 
 127     def __isub__(self, other):
 
 128         return self.difference_update(other)
 
 130     def __rsub__(self, other):
 
 131         return LazyUUIDTaskSet(self._tw,
 
 132                                set(t['uuid'] for t in other) - self._uuids)
 
 134     def __or__(self, other):
 
 135         return self.union(other)
 
 137     def __ior__(self, other):
 
 138         return self.update(other)
 
 140     def __ror__(self, other):
 
 141         return self.union(other)
 
 143     def __xor__(self, other):
 
 144         return self.symmetric_difference(other)
 
 146     def __ixor__(self, other):
 
 147         return self.symmetric_difference_update(other)
 
 149     def __rxor__(self, other):
 
 150         return self.symmetric_difference(other)
 
 152     def __and__(self, other):
 
 153         return self.intersection(other)
 
 155     def __iand__(self, other):
 
 156         return self.intersection_update(other)
 
 158     def __rand__(self, other):
 
 159         return self.intersection(other)
 
 161     def __le__(self, other):
 
 162         return self.issubset(other)
 
 164     def __ge__(self, other):
 
 165         return self.issuperset(other)
 
 167     def issubset(self, other):
 
 168         return all([task in other for task in self])
 
 170     def issuperset(self, other):
 
 171         return all([task in self for task in other])
 
 173     def union(self, other):
 
 174         return LazyUUIDTaskSet(self._tw,
 
 175                                self._uuids | set(t['uuid'] for t in other))
 
 177     def intersection(self, other):
 
 178         return LazyUUIDTaskSet(self._tw,
 
 179                                self._uuids & set(t['uuid'] for t in other))
 
 181     def difference(self, other):
 
 182         return LazyUUIDTaskSet(self._tw,
 
 183                                self._uuids - set(t['uuid'] for t in other))
 
 185     def symmetric_difference(self, other):
 
 186         return LazyUUIDTaskSet(self._tw,
 
 187                                self._uuids ^ set(t['uuid'] for t in other))
 
 189     def update(self, other):
 
 190         self._uuids |= set(t['uuid'] for t in other)
 
 193     def intersection_update(self, other):
 
 194         self._uuids &= set(t['uuid'] for t in other)
 
 197     def difference_update(self, other):
 
 198         self._uuids -= set(t['uuid'] for t in other)
 
 201     def symmetric_difference_update(self, other):
 
 202         self._uuids ^= set(t['uuid'] for t in other)
 
 206         self._uuids.add(task['uuid'])
 
 208     def remove(self, task):
 
 209         self._uuids.remove(task['uuid'])
 
 212         return self._uuids.pop()
 
 219         Performs conversion to the regular TaskQuerySet object, referenced by
 
 223         replacement = self._tw.tasks.filter(' '.join(self._uuids))
 
 224         self.__class__ = replacement.__class__
 
 225         self.__dict__ = replacement.__dict__