]> git.madduck.net Git - etc/taskwarrior.git/blob - tasklib/lazy.py

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Loosen the version requirement for six
[etc/taskwarrior.git] / tasklib / lazy.py
1 """
2 Provides lazy implementations for Task and TaskQuerySet.
3 """
4
5
6 class LazyUUIDTask(object):
7     """
8     A lazy wrapper around Task object, referenced by UUID.
9
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
13       Task object.
14     """
15
16     def __init__(self, tw, uuid):
17         self._tw = tw
18         self._uuid = uuid
19
20     def __getitem__(self, key):
21         # LazyUUIDTask does not provide anything else other than 'uuid'
22         if key is 'uuid':
23             return self._uuid
24         else:
25             self.replace()
26             return self[key]
27
28     def __getattr__(self, name):
29         # Getattr is called only if the attribute could not be found using
30         # normal means
31         self.replace()
32         return getattr(self, name)
33
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']
38
39     def __hash__(self):
40         return self['uuid'].__hash__()
41
42     def __repr__(self):
43         return "LazyUUIDTask: {0}".format(self._uuid)
44
45     def __copy__(self):
46         return LazyUUIDTask(self._tw, self._uuid)
47
48     def __deepcopy__(self, memo):
49         return LazyUUIDTask(self._tw, self._uuid)
50
51     @property
52     def saved(self):
53         """
54         Implementation of the 'saved' property. Always returns True.
55         """
56         return True
57
58     @property
59     def _modified_fields(self):
60         return set()
61
62     @property
63     def modified(self):
64         return False
65
66     def replace(self):
67         """
68         Performs conversion to the regular Task object, referenced by the
69         stored UUID.
70         """
71
72         replacement = self._tw.tasks.get(uuid=self._uuid)
73         self.__class__ = replacement.__class__
74         self.__dict__ = replacement.__dict__
75
76
77 class LazyUUIDTaskSet(object):
78     """
79     A lazy wrapper around TaskQuerySet object, for tasks referenced by UUID.
80
81     - Supports 'in' operator with LazyUUIDTask or Task objects
82     - If iteration over the objects in the LazyUUIDTaskSet is requested, the
83       LazyUUIDTaskSet will be converted to QuerySet and evaluated
84     """
85
86     def __init__(self, tw, uuids):
87         self._tw = tw
88         self._uuids = set(uuids)
89
90     def __getattr__(self, name):
91         # Getattr is called only if the attribute could not be found using
92         # normal means
93
94         if name.startswith('__'):
95             # If some internal method was being search, do not convert
96             # to TaskQuerySet just because of that
97             raise AttributeError
98         else:
99             self.replace()
100             return getattr(self, name)
101
102     def __repr__(self):
103         return "LazyUUIDTaskSet([{0}])".format(', '.join(self._uuids))
104
105     def __eq__(self, other):
106         return set(t['uuid'] for t in other) == self._uuids
107
108     def __ne__(self, other):
109         return not (self == other)
110
111     def __contains__(self, task):
112         return task['uuid'] in self._uuids
113
114     def __len__(self):
115         return len(self._uuids)
116
117     def __iter__(self):
118         for uuid in self._uuids:
119             yield LazyUUIDTask(self._tw, uuid)
120
121     def __sub__(self, other):
122         return self.difference(other)
123
124     def __isub__(self, other):
125         return self.difference_update(other)
126
127     def __rsub__(self, other):
128         return LazyUUIDTaskSet(self._tw,
129             set(t['uuid'] for t in other) - self._uuids)
130
131     def __or__(self, other):
132         return self.union(other)
133
134     def __ior__(self, other):
135         return self.update(other)
136
137     def __ror__(self, other):
138         return self.union(other)
139
140     def __xor__(self, other):
141         return self.symmetric_difference(other)
142
143     def __ixor__(self, other):
144         return self.symmetric_difference_update(other)
145
146     def __rxor__(self, other):
147         return self.symmetric_difference(other)
148
149     def __and__(self, other):
150         return self.intersection(other)
151
152     def __iand__(self, other):
153         return self.intersection_update(other)
154
155     def __rand__(self, other):
156         return self.intersection(other)
157
158     def __le__(self, other):
159         return self.issubset(other)
160
161     def __ge__(self, other):
162         return self.issuperset(other)
163
164     def issubset(self, other):
165         return all([task in other for task in self])
166
167     def issuperset(self, other):
168         return all([task in self for task in other])
169
170     def union(self, other):
171         return LazyUUIDTaskSet(self._tw,
172             self._uuids | set(t['uuid'] for t in other))
173
174     def intersection(self, other):
175         return LazyUUIDTaskSet(self._tw,
176             self._uuids & set(t['uuid'] for t in other))
177
178     def difference(self, other):
179         return LazyUUIDTaskSet(self._tw,
180             self._uuids - set(t['uuid'] for t in other))
181
182     def symmetric_difference(self, other):
183         return LazyUUIDTaskSet(self._tw,
184             self._uuids ^ set(t['uuid'] for t in other))
185
186     def update(self, other):
187         self._uuids |= set(t['uuid'] for t in other)
188         return self
189
190     def intersection_update(self, other):
191         self._uuids &= set(t['uuid'] for t in other)
192         return self
193
194     def difference_update(self, other):
195         self._uuids -= set(t['uuid'] for t in other)
196         return self
197
198     def symmetric_difference_update(self, other):
199         self._uuids ^= set(t['uuid'] for t in other)
200         return self
201
202     def add(self, task):
203         self._uuids.add(task['uuid'])
204
205     def remove(self, task):
206         self._uuids.remove(task['uuid'])
207
208     def pop(self):
209         return self._uuids.pop()
210
211     def clear(self):
212         self._uuids.clear()
213
214     def replace(self):
215         """
216         Performs conversion to the regular TaskQuerySet object, referenced by
217         the stored UUIDs.
218         """
219
220         replacement = self._tw.tasks.filter(' '.join(self._uuids))
221         self.__class__ = replacement.__class__
222         self.__dict__ = replacement.__dict__