Merge lp:~eday/burrow/doc-updates into lp:burrow

Proposed by Eric Day
Status: Merged
Approved by: Eric Day
Approved revision: 37
Merged at revision: 37
Proposed branch: lp:~eday/burrow/doc-updates
Merge into: lp:burrow
Diff against target: 523 lines (+183/-13)
4 files modified
burrow/backend/__init__.py (+145/-13)
burrow/backend/http.py (+2/-0)
burrow/backend/memory.py (+15/-0)
burrow/backend/sqlite.py (+21/-0)
To merge this branch: bzr merge lp:~eday/burrow/doc-updates
Reviewer Review Type Date Requested Status
Burrow Core Team Pending
Review via email: mp+72754@code.launchpad.net

Description of the change

More docs for backend modules.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'burrow/backend/__init__.py'
2--- burrow/backend/__init__.py 2011-08-19 00:07:39 +0000
3+++ burrow/backend/__init__.py 2011-08-24 17:01:25 +0000
4@@ -20,6 +20,9 @@
5
6 import burrow.common
7
8+# Since this is an interface, arguments are unused. Ignore warnings in pylint.
9+# pylint: disable=W0613
10+
11
12 class Backend(burrow.common.Module):
13 '''Interface that backend modules must implement.'''
14@@ -34,48 +37,165 @@
15 thread_pool.spawn_n(self._clean)
16
17 def delete_accounts(self, filters=None):
18- '''Delete accounts, which includes all queues and messages
19- for the accounts. With no filters, this will delete all data
20- for the entire server, so it should be used with caution.
21+ '''Delete accounts, which includes all queues and messages within
22+ the accounts. With no filters, this will delete all data for the
23+ entire server, so it should be used with caution.
24
25 :param filters: Optional dict of filters for the request. Valid
26- filters are 'marker', 'limit', and 'detail'. Valid values
27- for 'detail' are 'none', 'id', and 'all'. Default value for
28- 'detail' is 'none'.
29- :returns: Generator which will loop through all messages if
30- 'detail' is not 'none'.
31+ filters are 'marker', 'limit', and 'detail'. The 'marker'
32+ value is the last seen account ID for use in pagination,
33+ and only accounts after this ID will be affected. If the
34+ 'marker' value is not given or not found, it will start from
35+ the beginning. The 'limit' value is the number of accounts
36+ to delete for the request. If 'limit' is not given, it will
37+ delete them all. Valid values for 'detail' are 'none', 'id',
38+ and 'all'. Default value for 'detail' is 'none'.
39+
40+ :returns: Generator which will loop through all accounts if
41+ 'detail' is not 'none'. If 'detail' is 'none', the generator
42+ will stop on the first iteration, but it still must be called
43+ to finish the request.
44 '''
45 return []
46
47 def get_accounts(self, filters=None):
48+ '''Get a list of accounts, possibly filtered. This uses the same
49+ parameters and return type as :func:`delete_accounts()`, except
50+ the default value for 'detail' in 'filters' is 'id'.'''
51 return []
52
53 def delete_queues(self, account, filters=None):
54+ '''Delete queues within an account, which includes all messages
55+ within the queues. With no filters, this will delete all data
56+ for the entire account, so it should be used with caution.
57+
58+ :param account: Account to delete the queues from.
59+
60+ :param filters: Optional dict of filters for the request. Valid
61+ filters are 'marker', 'limit', and 'detail'. The 'marker'
62+ value is the last seen queue ID for use in pagination, and
63+ only queues after this ID will be affected. If the 'marker'
64+ value is not given or not found, it will start from the
65+ beginning. The 'limit' value is the number of queues to
66+ delete for the request. If 'limit' is not given, it will
67+ delete them all. Valid values for 'detail' are 'none', 'id',
68+ and 'all'. Default value for 'detail' is 'none'.
69+
70+ :returns: Generator which will loop through all queues if 'detail'
71+ is not 'none'. If 'detail' is 'none', the generator will stop
72+ on the first iteration, but it still must be called to finish
73+ the request.
74+ '''
75 return []
76
77 def get_queues(self, account, filters=None):
78+ '''Get a list of queues, possibly filtered. This uses the same
79+ parameters and return type as :func:`delete_queues()`, except
80+ the default value for 'detail' in 'filters' is 'id'.'''
81 return []
82
83 def delete_messages(self, account, queue, filters=None):
84+ '''Delete messages within a queue. With no filters, this will
85+ delete all messages in the queue, so it should be used with
86+ caution.
87+
88+ :param account: Account to delete the messages from.
89+
90+ :param queue: Queue within the given account to delete the
91+ messages from.
92+
93+ :param filters: Optional dict of filters for the request. Valid
94+ filters are 'marker', 'limit', 'match_hidden', 'wait', and
95+ 'detail'. The 'marker' value is the last seen message ID for
96+ use in pagination, and only messages after this ID will be
97+ affected. If the 'marker' value is not given or not found,
98+ it will start from the beginning. The 'limit' value is the
99+ number of messages to delete for the request. If 'limit'
100+ is not given, it will delete them all. If 'match_hidden'
101+ is True, the request will match all messages, even if their
102+ 'hide' value is non-zero, otherwise messages with a 'hide'
103+ value of non-zero are skipped. If 'wait' is given, this is the
104+ number of seconds for the request to wait for a message if no
105+ messages can be found. Valid values for 'detail' are 'none',
106+ 'id', 'attributes', 'body', and 'all'. Default value for
107+ 'detail' is 'none'.
108+
109+ :returns: Generator which will loop through all messages if 'detail'
110+ is not 'none'. If 'detail' is 'none', the generator will stop
111+ on the first iteration, but it still must be called to finish
112+ the request.
113+ '''
114 return []
115
116 def get_messages(self, account, queue, filters=None):
117+ '''Get a list of messages, possibly filtered. This uses the same
118+ parameters and return type as :func:`delete_messages()`, except
119+ the default value for 'detail' in 'filters' is 'all'.'''
120 return []
121
122 def update_messages(self, account, queue, attributes, filters=None):
123+ '''Update a list of messages, possibly filtered. In addition to
124+ the parameters and return type used in :func:`delete_messages()`,
125+ this also requires:
126+
127+ :param attributes: Attributes to set as described in
128+ :func:`create_message()`
129+ '''
130 return []
131
132 def create_message(self, account, queue, message, body, attributes=None):
133+ '''Create a new message in the given account and queue.
134+
135+ :param account: Account to create the messages in.
136+
137+ :param queue: Queue within the given account to create the
138+ messages in.
139+
140+ :param message: Message ID to use within the queue, which is
141+ always unique. When a message of the same ID already exists,
142+ the old message is overwritten with this new one.
143+
144+ :param body: Body of the message.
145+
146+ :param attributes: A dict of initial attributes to set. Valid
147+ attributes are 'ttl' and 'hide'. The value of 'ttl' is the
148+ number of seconds from when the request is made for the message
149+ to be removed automatically by the server. The value of 'hide'
150+ is the number of seconds from when the request is made for
151+ the message to stay hidden from requests that do not have the
152+ 'match_hidden' filter given as True.
153+
154+ :returns: True if the message was created, False if a message
155+ with the same ID existed and was replaced.
156+ '''
157 return True
158
159 def delete_message(self, account, queue, message, filters=None):
160+ '''Same as :func:`delete_messages()`, except only delete the
161+ given message ID.
162+
163+ :returns: The message detail according to 'detail' in 'filters,
164+ or None if 'detail' is 'none'.
165+ '''
166 return None
167
168 def get_message(self, account, queue, message, filters=None):
169+ '''Same as :func:`get_messages()`, except only get the given
170+ message ID.
171+
172+ :returns: The message detail according to 'detail' in 'filters,
173+ or None if 'detail' is 'none'.
174+ '''
175 return None
176
177 def update_message(self, account, queue, message, attributes,
178 filters=None):
179+ '''Same as :func:`update_messages()`, except only update the
180+ given message ID.
181+
182+ :returns: The message detail according to 'detail' in 'filters,
183+ or None if 'detail' is 'none'.
184+ '''
185 return None
186
187 def clean(self):
188@@ -91,6 +211,7 @@
189 eventlet.sleep(1)
190
191 def _get_attributes(self, attributes, ttl=None, hide=None):
192+ '''Helper method to parse attributes for implementations to use.'''
193 if attributes is not None:
194 ttl = attributes.get('ttl', ttl)
195 hide = attributes.get('hide', hide)
196@@ -101,6 +222,8 @@
197 return ttl, hide
198
199 def _get_detail(self, filters, default=None):
200+ '''Helper method to parse account and queue detail for
201+ implementations to use.'''
202 detail = default if filters is None else filters.get('detail', default)
203 if detail == 'none':
204 detail = None
205@@ -109,6 +232,8 @@
206 return detail
207
208 def _get_message_detail(self, filters, default=None):
209+ '''Helper method to parse message detail for implementations
210+ to use.'''
211 detail = default if filters is None else filters.get('detail', default)
212 options = ['id', 'attributes', 'body', 'all']
213 if detail == 'none':
214@@ -122,7 +247,7 @@
215 a visible message.'''
216 queue = '%s/%s' % (account, queue)
217 if queue in self.queues:
218- for count in xrange(0, self.queues[queue].getting()):
219+ for _count in xrange(0, self.queues[queue].getting()):
220 self.queues[queue].put(0)
221
222 def wait(self, account, queue, seconds):
223@@ -139,17 +264,21 @@
224
225
226 def wait_without_attributes(method):
227- def wrapper(self, account, queue, filters=None):
228+ '''Decorator that will wait for messages with the method does not
229+ take attributes.'''
230+ def __wrapper__(self, account, queue, filters=None):
231 original = lambda: method(self, account, queue, filters)
232 return wait(self, account, queue, filters, original)
233- return wrapper
234+ return __wrapper__
235
236
237 def wait_with_attributes(method):
238- def wrapper(self, account, queue, attributes, filters=None):
239+ '''Decorator that will wait for messages with the method takes
240+ attributes.'''
241+ def __wrapper__(self, account, queue, attributes, filters=None):
242 original = lambda: method(self, account, queue, attributes, filters)
243 return wait(self, account, queue, filters, original)
244- return wrapper
245+ return __wrapper__
246
247
248 def wait(self, account, queue, filters, method):
249@@ -173,8 +302,11 @@
250
251
252 class NotFound(Exception):
253+ '''Raised when an account, queue, or message can not be found.'''
254 pass
255
256
257 class InvalidArguments(Exception):
258+ '''Raised when the given arguments are invalid, usually from attributes
259+ or filters.'''
260 pass
261
262=== modified file 'burrow/backend/http.py'
263--- burrow/backend/http.py 2011-08-19 00:07:39 +0000
264+++ burrow/backend/http.py 2011-08-24 17:01:25 +0000
265@@ -109,6 +109,7 @@
266 pass
267
268 def _add_parameters(self, url, attributes=None, filters=None):
269+ '''Add attributes and filters on to the URL as query parameters.'''
270 separator = '?'
271 if attributes is not None:
272 parameters = ['ttl', 'hide']
273@@ -127,6 +128,7 @@
274 return url
275
276 def _request(self, method, url, *args, **kwargs):
277+ '''Perform the request and handle the response.'''
278 connection = httplib.HTTPConnection(*self.server)
279 connection.request(method, '/v1.0' + url, *args, **kwargs)
280 response = connection.getresponse()
281
282=== modified file 'burrow/backend/memory.py'
283--- burrow/backend/memory.py 2011-08-19 00:07:39 +0000
284+++ burrow/backend/memory.py 2011-08-24 17:01:25 +0000
285@@ -175,6 +175,7 @@
286 self.prev = None
287
288 def detail(self, detail):
289+ '''Format detail response for this item.'''
290 if detail == 'id':
291 return self.id
292 elif detail == 'all':
293@@ -193,6 +194,7 @@
294 self.index = {}
295
296 def add(self, item):
297+ '''Add a new item to the list.'''
298 if self.first is None:
299 self.first = item
300 if self.last is not None:
301@@ -203,9 +205,11 @@
302 return item
303
304 def count(self):
305+ '''Return a count of the number of items in the list.'''
306 return len(self.index)
307
308 def delete(self, id):
309+ '''Delete an item from the list by id.'''
310 item = self.index.pop(id)
311 if item.next is not None:
312 item.next.prev = item.prev
313@@ -217,6 +221,7 @@
314 self.last = item.prev
315
316 def get(self, id, create=False):
317+ '''Get an item from the list by id.'''
318 if id in self.index:
319 return self.index[id]
320 elif create:
321@@ -224,6 +229,7 @@
322 raise burrow.backend.NotFound()
323
324 def iter(self, filters=None):
325+ '''Iterate through all items in the list, possibly filtered.'''
326 if filters is None:
327 marker = None
328 limit = None
329@@ -245,6 +251,7 @@
330 item = item.next
331
332 def reset(self):
333+ '''Remove all items in the list.'''
334 if self.count() == 0:
335 raise burrow.backend.NotFound()
336 self.first = None
337@@ -253,6 +260,7 @@
338
339
340 class Account(Item):
341+ '''A type of item representing an account.'''
342
343 def __init__(self, id=None):
344 super(Account, self).__init__(id)
345@@ -260,10 +268,12 @@
346
347
348 class Accounts(IndexedList):
349+ '''A type of list representing an account list.'''
350
351 item_class = Account
352
353 def delete_queue(self, account, queue):
354+ '''Delete a queue within the given account.'''
355 account = self.get(account)
356 if account is not None:
357 account.queues.delete(queue)
358@@ -271,6 +281,7 @@
359 self.delete(account.id)
360
361 def get_queue(self, account, queue, create=False):
362+ '''Get a queue within the given the account.'''
363 if account in self.index:
364 account = self.index[account]
365 elif create:
366@@ -281,6 +292,7 @@
367
368
369 class Queue(Item):
370+ '''A type of item representing a queue.'''
371
372 def __init__(self, id=None):
373 super(Queue, self).__init__(id)
374@@ -288,11 +300,13 @@
375
376
377 class Queues(IndexedList):
378+ '''A type of list representing a queue list.'''
379
380 item_class = Queue
381
382
383 class Message(Item):
384+ '''A type of item representing a message.'''
385
386 def __init__(self, id=None):
387 super(Message, self).__init__(id)
388@@ -319,6 +333,7 @@
389
390
391 class Messages(IndexedList):
392+ '''A type of list representing a message list.'''
393
394 item_class = Message
395
396
397=== modified file 'burrow/backend/sqlite.py'
398--- burrow/backend/sqlite.py 2011-08-19 00:07:39 +0000
399+++ burrow/backend/sqlite.py 2011-08-24 17:01:25 +0000
400@@ -30,6 +30,8 @@
401
402
403 class Backend(burrow.backend.Backend):
404+ '''Backend implemention that uses SQLite to store the account, queue,
405+ and message data.'''
406
407 def __init__(self, config):
408 super(Backend, self).__init__(config)
409@@ -83,6 +85,8 @@
410 self._delete_accounts(ids)
411
412 def _delete_accounts(self, ids):
413+ '''Delete all accounts with the given row IDs, which includes
414+ cascading deletes for all queues and messages as well.'''
415 ids = tuple(ids)
416 query_values = '(?' + (',?' * (len(ids) - 1)) + ')'
417 queue_ids = []
418@@ -103,6 +107,7 @@
419 self.db.execute(query + query_values, ids)
420
421 def _detail(self, row, detail):
422+ '''Format the account or queue detail from the given row.'''
423 if detail == 'id':
424 return row[0]
425 elif detail == 'all':
426@@ -117,6 +122,8 @@
427 yield self._detail(row, detail)
428
429 def _get_accounts(self, query, filters):
430+ '''Build the SQL query to get accounts and check for empty
431+ responses.'''
432 values = tuple()
433 if filters is None:
434 marker = None
435@@ -142,6 +149,7 @@
436 raise burrow.backend.NotFound()
437
438 def _get_account(self, account):
439+ '''Get the rowid for a given account ID.'''
440 query = 'SELECT rowid FROM accounts WHERE account=?'
441 rows = self.db.execute(query, (account,)).fetchall()
442 if len(rows) == 0:
443@@ -165,6 +173,8 @@
444 self._check_empty_account(account_rowid)
445
446 def _delete_queues(self, ids):
447+ '''Delete all queues with the given row IDs, which includes
448+ cascading deletes for all messages as well.'''
449 ids = tuple(ids)
450 query_values = '(?' + (',?' * (len(ids) - 1)) + ')'
451 query = 'DELETE FROM messages WHERE queue IN '
452@@ -173,6 +183,7 @@
453 self.db.execute(query + query_values, ids)
454
455 def _check_empty_account(self, account_rowid):
456+ '''Check to see if an account is empty, and if so, remove it.'''
457 query = 'SELECT rowid FROM queues WHERE account=? LIMIT 1'
458 if len(self.db.execute(query, (account_rowid,)).fetchall()) == 0:
459 query = 'DELETE FROM accounts WHERE rowid=?'
460@@ -187,6 +198,8 @@
461 yield self._detail(row, detail)
462
463 def _get_queues(self, query, account_rowid, filters):
464+ '''Build the SQL query to get queues and check for empty
465+ responses.'''
466 query += ' WHERE account=?'
467 values = (account_rowid,)
468 if filters is None:
469@@ -213,6 +226,7 @@
470 raise burrow.backend.NotFound()
471
472 def _get_queue(self, account_rowid, queue):
473+ '''Get the rowid for a given queue ID.'''
474 query = 'SELECT rowid FROM queues WHERE account=? AND queue=?'
475 rows = self.db.execute(query, (account_rowid, queue)).fetchall()
476 if len(rows) == 0:
477@@ -238,18 +252,21 @@
478 self._check_empty_queue(account_rowid, queue_rowid)
479
480 def _delete_messages(self, ids):
481+ '''Delete all messages with the given row IDs.'''
482 ids = tuple(ids)
483 query_values = '(?' + (',?' * (len(ids) - 1)) + ')'
484 query = 'DELETE FROM messages WHERE rowid IN '
485 self.db.execute(query + query_values, ids)
486
487 def _check_empty_queue(self, account_rowid, queue_rowid):
488+ '''Check to see if a queue is empty, and if so, remove it.'''
489 query = 'SELECT rowid FROM messages WHERE queue=? LIMIT 1'
490 if len(self.db.execute(query, (queue_rowid,)).fetchall()) == 0:
491 self.db.execute('DELETE FROM queues WHERE rowid=?', (queue_rowid,))
492 self._check_empty_account(account_rowid)
493
494 def _message_detail(self, row, detail):
495+ '''Format the message detail from the given row.'''
496 if detail == 'id':
497 return row[0]
498 elif detail == 'body':
499@@ -277,6 +294,8 @@
500 yield self._message_detail(row, detail)
501
502 def _get_messages(self, query, queue_rowid, filters):
503+ '''Build the SQL query to get messages and check for empty
504+ responses.'''
505 query += ' WHERE queue=?'
506 values = (queue_rowid,)
507 if filters is None:
508@@ -307,6 +326,7 @@
509 raise burrow.backend.NotFound()
510
511 def _get_message(self, queue_rowid, message, full=False):
512+ '''Get the rowid for a given message ID.'''
513 if full:
514 query = 'SELECT rowid,message,ttl,hide,body'
515 else:
516@@ -348,6 +368,7 @@
517 self.notify(account, queue)
518
519 def _update_messages(self, ttl, hide, ids):
520+ '''Build the SQL query to update messages.'''
521 query = 'UPDATE messages SET '
522 query_values = ' WHERE rowid IN (?' + (',?' * (len(ids) - 1)) + ')'
523 values = []

Subscribers

People subscribed via source and target branches