Merge lp:~pedronis/u1db/rest-all-docs into lp:u1db

Proposed by Samuele Pedroni
Status: Merged
Approved by: Samuele Pedroni
Approved revision: 430
Merged at revision: 430
Proposed branch: lp:~pedronis/u1db/rest-all-docs
Merge into: lp:u1db
Diff against target: 202 lines (+104/-29)
5 files modified
u1db/remote/http_app.py (+28/-0)
u1db/remote/http_database.py (+17/-6)
u1db/tests/test_backends.py (+23/-23)
u1db/tests/test_http_app.py (+15/-0)
u1db/tests/test_http_database.py (+21/-0)
To merge this branch: bzr merge lp:~pedronis/u1db/rest-all-docs
Reviewer Review Type Date Requested Status
Eric Casteleijn (community) Approve
Stuart Langridge (community) Approve
Lucio Torre (community) Approve
Review via email: mp+129426@code.launchpad.net

Commit message

support get_all_docs over the rest api, returning the current with a x-u1db-genertion header is optional

Description of the change

support get_all_docs but without returning the cur gen over the rest api, instead return -1 from http_database for that

To post a comment you must log in.
lp:~pedronis/u1db/rest-all-docs updated
430. By Samuele Pedroni

support returning gen in rest all-docs with a header but its absence is ok and we fallback to -1

Revision history for this message
Lucio Torre (lucio.torre) :
review: Approve
Revision history for this message
Stuart Langridge (sil) :
review: Approve
Revision history for this message
Eric Casteleijn (thisfred) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'u1db/remote/http_app.py'
2--- u1db/remote/http_app.py 2012-10-02 16:10:27 +0000
3+++ u1db/remote/http_app.py 2012-10-12 14:02:18 +0000
4@@ -273,6 +273,34 @@
5
6
7 @url_to_resource.register
8+class AllDocsResource(object):
9+ """All Documents resource."""
10+
11+ url_pattern = "/{dbname}/all-docs"
12+
13+ def __init__(self, dbname, state, responder):
14+ self.responder = responder
15+ self.db = state.open_database(dbname)
16+
17+ @http_method(include_deleted=parse_bool)
18+ def get(self, include_deleted=False):
19+ gen, docs = self.db.get_all_docs(include_deleted=include_deleted)
20+ self.responder.content_type = 'application/json'
21+ # returning a x-u1db-generation header is optional
22+ # HTTPDatabase will fallback to return -1 if it's missing
23+ self.responder.start_response(200,
24+ headers={'x-u1db-generation': str(gen)})
25+ self.responder.start_stream(),
26+ for doc in docs:
27+ entry = dict(
28+ doc_id=doc.doc_id, doc_rev=doc.rev, content=doc.get_json(),
29+ has_conflicts=doc.has_conflicts)
30+ self.responder.stream_entry(entry)
31+ self.responder.end_stream()
32+ self.responder.finish_response()
33+
34+
35+@url_to_resource.register
36 class DocResource(object):
37 """Document resource."""
38
39
40=== modified file 'u1db/remote/http_database.py'
41--- u1db/remote/http_database.py 2012-10-10 14:54:25 +0000
42+++ u1db/remote/http_database.py 2012-10-12 14:02:18 +0000
43@@ -105,20 +105,31 @@
44 doc.has_conflicts = has_conflicts
45 return doc
46
47+ def _build_docs(self, res):
48+ for doc_dict in json.loads(res):
49+ doc = self._factory(
50+ doc_dict['doc_id'], doc_dict['doc_rev'], doc_dict['content'])
51+ doc.has_conflicts = doc_dict['has_conflicts']
52+ yield doc
53+
54 def get_docs(self, doc_ids, check_for_conflicts=True,
55 include_deleted=False):
56 if not doc_ids:
57- return
58+ return []
59 doc_ids = ','.join(doc_ids)
60 res, headers = self._request(
61 'GET', ['docs'], {
62 "doc_ids": doc_ids, "include_deleted": include_deleted,
63 "check_for_conflicts": check_for_conflicts})
64- for doc_dict in json.loads(res):
65- doc = self._factory(
66- doc_dict['doc_id'], doc_dict['doc_rev'], doc_dict['content'])
67- doc.has_conflicts = doc_dict['has_conflicts']
68- yield doc
69+ return self._build_docs(res)
70+
71+ def get_all_docs(self, include_deleted=False):
72+ res, headers = self._request(
73+ 'GET', ['all-docs'], {"include_deleted": include_deleted})
74+ gen = -1
75+ if 'x-u1db-generation' in headers:
76+ gen = int(headers['x-u1db-generation'])
77+ return gen, list(self._build_docs(res))
78
79 def _allocate_doc_id(self):
80 return 'D-%s' % (uuid.uuid4().hex,)
81
82=== modified file 'u1db/tests/test_backends.py'
83--- u1db/tests/test_backends.py 2012-10-11 20:48:58 +0000
84+++ u1db/tests/test_backends.py 2012-10-12 14:02:18 +0000
85@@ -276,6 +276,29 @@
86 def test_get_docs_empty_list(self):
87 self.assertEqual([], list(self.db.get_docs([])))
88
89+ def test_get_all_docs_empty(self):
90+ self.assertEqual([], list(self.db.get_all_docs()[1]))
91+
92+ def test_get_all_docs(self):
93+ doc1 = self.db.create_doc_from_json(simple_doc)
94+ doc2 = self.db.create_doc_from_json(nested_doc)
95+ self.assertEqual(
96+ sorted([doc1, doc2]), sorted(list(self.db.get_all_docs()[1])))
97+
98+ def test_get_all_docs_exclude_deleted(self):
99+ doc1 = self.db.create_doc_from_json(simple_doc)
100+ doc2 = self.db.create_doc_from_json(nested_doc)
101+ self.db.delete_doc(doc2)
102+ self.assertEqual([doc1], list(self.db.get_all_docs()[1]))
103+
104+ def test_get_all_docs_include_deleted(self):
105+ doc1 = self.db.create_doc_from_json(simple_doc)
106+ doc2 = self.db.create_doc_from_json(nested_doc)
107+ self.db.delete_doc(doc2)
108+ self.assertEqual(
109+ sorted([doc1, doc2]),
110+ sorted(list(self.db.get_all_docs(include_deleted=True)[1])))
111+
112 def test_handles_nested_content(self):
113 doc = self.db.create_doc_from_json(nested_doc)
114 self.assertGetDoc(self.db, doc.doc_id, doc.rev, nested_doc, False)
115@@ -408,29 +431,6 @@
116 doc = self.make_document('/a', None, simple_doc)
117 self.assertRaises(errors.InvalidDocId, self.db.put_doc, doc)
118
119- def test_get_all_docs_empty(self):
120- self.assertEqual([], list(self.db.get_all_docs()[1]))
121-
122- def test_get_all_docs(self):
123- doc1 = self.db.create_doc_from_json(simple_doc)
124- doc2 = self.db.create_doc_from_json(nested_doc)
125- self.assertEqual(
126- sorted([doc1, doc2]), sorted(list(self.db.get_all_docs()[1])))
127-
128- def test_get_all_docs_exclude_deleted(self):
129- doc1 = self.db.create_doc_from_json(simple_doc)
130- doc2 = self.db.create_doc_from_json(nested_doc)
131- self.db.delete_doc(doc2)
132- self.assertEqual([doc1], list(self.db.get_all_docs()[1]))
133-
134- def test_get_all_docs_include_deleted(self):
135- doc1 = self.db.create_doc_from_json(simple_doc)
136- doc2 = self.db.create_doc_from_json(nested_doc)
137- self.db.delete_doc(doc2)
138- self.assertEqual(
139- sorted([doc1, doc2]),
140- sorted(list(self.db.get_all_docs(include_deleted=True)[1])))
141-
142 def test_get_all_docs_generation(self):
143 self.db.create_doc_from_json(simple_doc)
144 self.db.create_doc_from_json(nested_doc)
145
146=== modified file 'u1db/tests/test_http_app.py'
147--- u1db/tests/test_http_app.py 2012-10-02 16:10:27 +0000
148+++ u1db/tests/test_http_app.py 2012-10-12 14:02:18 +0000
149@@ -780,6 +780,21 @@
150 "has_conflicts": False}]
151 self.assertEqual(expected, json.loads(resp.body))
152
153+ def test_get_all_docs(self):
154+ doc1 = self.db0.create_doc_from_json('{"x": 1}', doc_id='doc1')
155+ doc2 = self.db0.create_doc_from_json('{"x": 1}', doc_id='doc2')
156+ resp = self.app.get('/db0/all-docs')
157+ self.assertEqual(200, resp.status)
158+ self.assertEqual(
159+ 'application/json', resp.header('content-type'))
160+ def doc_to_dic(doc):
161+ return dict(doc_id=doc.doc_id, doc_rev=doc.rev,
162+ content=doc.get_json(),
163+ has_conflicts=doc.has_conflicts)
164+ expected = sorted([doc_to_dic(doc1), doc_to_dic(doc2)])
165+ self.assertEqual(expected, sorted(json.loads(resp.body)))
166+ self.assertEqual(2, int(resp.header('x-u1db-generation')))
167+
168 def test_get_sync_info(self):
169 self.db0._set_replica_gen_and_trans_id('other-id', 1, 'T-transid')
170 resp = self.app.get('/db0/sync-from/other-id')
171
172=== modified file 'u1db/tests/test_http_database.py'
173--- u1db/tests/test_http_database.py 2012-10-10 14:54:25 +0000
174+++ u1db/tests/test_http_database.py 2012-10-12 14:02:18 +0000
175@@ -148,6 +148,27 @@
176 self.assertRaises(errors.HTTPError,
177 self.db.get_doc, 'something-something')
178
179+ def test_get_all_docs_gen_included(self):
180+ self.response_val = ('[{"doc_id": "doc", "doc_rev": "db:1",'
181+ ' "content": "{}", "has_conflicts": false}]',
182+ {'x-u1db-generation': 2})
183+ gen, docs = self.db.get_all_docs(include_deleted=True)
184+ self.assertEqual(2, gen)
185+ self.assertEqual(1, len(docs))
186+ self.assertEqual(
187+ ('GET', ['all-docs'], {'include_deleted': True}, None, None),
188+ self.got)
189+
190+ def test_get_all_docs_gen_absent(self):
191+ self.response_val = ('[{"doc_id": "doc", "doc_rev": "db:1",'
192+ ' "content": "{}", "has_conflicts": false}]', {})
193+ gen, docs = self.db.get_all_docs()
194+ self.assertEqual(-1, gen)
195+ self.assertEqual(1, len(docs))
196+ self.assertEqual(
197+ ('GET', ['all-docs'], {'include_deleted': False}, None, None),
198+ self.got)
199+
200 def test_create_doc_from_json_with_id(self):
201 self.response_val = {'rev': 'doc-rev'}, {}
202 new_doc = self.db.create_doc_from_json('{"v": 1}', doc_id='doc-id')

Subscribers

People subscribed via source and target branches