Merge lp://qastaging/~thisfred/desktopcouch/couchdb-conflicts into lp://qastaging/desktopcouch

Proposed by Eric Casteleijn
Status: Merged
Approved by: Elliot Murphy
Approved revision: 3
Merged at revision: not available
Proposed branch: lp://qastaging/~thisfred/desktopcouch/couchdb-conflicts
Merge into: lp://qastaging/desktopcouch
Diff against target: None lines
To merge this branch: bzr merge lp://qastaging/~thisfred/desktopcouch/couchdb-conflicts
Reviewer Review Type Date Requested Status
Elliot Murphy (community) Approve
Review via email: mp+8684@code.qastaging.launchpad.net

Commit message

[r=statik] Add new update_fields method.

To post a comment you must log in.
Revision history for this message
Eric Casteleijn (thisfred) wrote :

This provides a method 'update_fields' that allows guaranteed conflict free updating of certain fields in a record. This should be used everywhere that we don't care to handle conflicts ourselves. Caveat: Will overwrite values in the specified fields (but not other fields) rather than create conflict documents, which doesn't seem to be possible from couchdb-python.

3. By Eric Casteleijn

unchanged: attach bug

Revision history for this message
Elliot Murphy (statik) wrote :

looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'desktopcouch/records/server.py'
2--- desktopcouch/records/server.py 2009-07-08 17:48:11 +0000
3+++ desktopcouch/records/server.py 2009-07-13 12:22:21 +0000
4@@ -21,10 +21,11 @@
5 """The Desktop Couch Records API."""
6
7 from couchdb import Server
8-from couchdb.client import ResourceNotFound
9+from couchdb.client import ResourceNotFound, ResourceConflict
10
11 from record import Record
12
13+
14 class NoSuchDatabase(Exception):
15 "Exception for trying to use a non-existent database"
16
17@@ -67,23 +68,23 @@
18 '-p %s -s | cut -d" " -f7 | cut -d "," -f1) 2>/dev/null | ' + \
19 'grep "TCP " | grep LISTEN | ' + \
20 'awk \'{print $8}\' | cut -d":" -f2'
21- actual_lsof_cmd = lsofcmd % (local_files.FILE_INI,
22+ actual_lsof_cmd = lsofcmd % (local_files.FILE_INI,
23 local_files.FILE_PID)
24 stdout, stderr = subprocess.Popen(actual_lsof_cmd, shell=True,
25 stdout=subprocess.PIPE).communicate()
26 port = stdout.strip()
27 except:
28 port = 5984
29- if not port:
30+ if not port:
31 port = 5984
32 return port
33-
34- def query(self, map_fun, reduce_fun=None, language='javascript',
35+
36+ def query(self, map_fun, reduce_fun=None, language='javascript',
37 wrapper=None, **options):
38 """Pass-through to CouchDB query"""
39- return self.db.query(map_fun, reduce_fun, language,
40+ return self.db.query(map_fun, reduce_fun, language,
41 wrapper, **options)
42-
43+
44 def get_record(self, record_id):
45 """Get a record from back end storage."""
46 try:
47@@ -106,11 +107,24 @@
48 record_id = self._add_record(record_data)
49 return record_id
50
51+ def update_fields(self, doc_id, fields):
52+ """Safely update a number of fields. 'fields' being a
53+ dictionary with fieldname: value for only the fields we want
54+ to change the value of.
55+ """
56+ while True:
57+ doc = self.db[doc_id]
58+ doc.update(fields)
59+ try:
60+ self.db[doc.id] = doc
61+ except ResourceConflict:
62+ continue
63+ break
64+
65 def _add_record(self, data):
66 """Add a new record to the storage backend."""
67 return self.db.create(data)
68
69- #FIXME: NEEDS TEST
70 def delete_record(self, record_id):
71 """Delete record with given id"""
72 record = self.db[record_id]
73@@ -119,7 +133,6 @@
74 'deleted'] = True
75 self.db[record_id] = record
76
77- #FIXME: NEEDS TEST
78 def record_exists(self, record_id):
79 """Check if record with given id exists"""
80 if record_id not in self.db:
81
82=== modified file 'desktopcouch/records/tests/test_server.py'
83--- desktopcouch/records/tests/test_server.py 2009-07-08 17:48:11 +0000
84+++ desktopcouch/records/tests/test_server.py 2009-07-13 12:22:21 +0000
85@@ -80,3 +80,20 @@
86 self.assert_(self.database.record_exists(record_id))
87 self.database.delete_record(record_id)
88 self.assert_(not self.database.record_exists(record_id))
89+
90+ def test_update_fields(self):
91+ """Test the update_fields method."""
92+ dictionary = {'record_number': 0, 'field1': 1, 'field2': 2}
93+ record = Record(dictionary, record_type="http://example.com/")
94+ record_id = self.database.put_record(record)
95+ # manipulate the database 'out of view'
96+ non_working_copy = self.database.get_record(record_id)
97+ non_working_copy['field2'] = 22
98+ non_working_copy['field3'] = 3
99+ self.database.put_record(non_working_copy)
100+ self.database.update_fields(record_id, {'field1': 11})
101+ working_copy = self.database.get_record(record_id)
102+ self.assertEqual(0, working_copy['record_number'])
103+ self.assertEqual(11, working_copy['field1'])
104+ self.assertEqual(22, working_copy['field2'])
105+ self.assertEqual(3, working_copy['field3'])

Subscribers

People subscribed via source and target branches