Merge lp:~cmiller/desktopcouch/preconditionfailed-lp707321 into lp:desktopcouch

Proposed by Chad Miller
Status: Merged
Approved by: Chad Miller
Approved revision: 269
Merged at revision: 268
Proposed branch: lp:~cmiller/desktopcouch/preconditionfailed-lp707321
Merge into: lp:desktopcouch
Diff against target: 170 lines (+104/-15)
2 files modified
desktopcouch/records/database.py (+14/-10)
desktopcouch/records/tests/test_mocked_server.py (+90/-5)
To merge this branch: bzr merge lp:~cmiller/desktopcouch/preconditionfailed-lp707321
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Eric Casteleijn (community) Approve
Review via email: mp+56246@code.launchpad.net

Commit message

Change creation of the Database object to EAFP. LBYL is impossible with HTTP and no locking. If create-flag is set, then go do it and swallow an exception about it already existing. (LP: #707321)

In addition, simplify that code so it makes fewer round-trips to the server.

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

Looks good, let's land it and run it past one of the bug reporters to see if it fixes it for them.

review: Approve
269. By Chad Miller

Attach bug.

Revision history for this message
Roberto Alsina (ralsina) wrote :

Looks good to me :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'desktopcouch/records/database.py'
--- desktopcouch/records/database.py 2011-01-27 20:00:45 +0000
+++ desktopcouch/records/database.py 2011-04-04 19:13:27 +0000
@@ -43,7 +43,7 @@
43# pylint: enable=F040143# pylint: enable=F0401
4444
45from couchdb import Server45from couchdb import Server
46from couchdb.http import ResourceNotFound, ResourceConflict46from couchdb.http import ResourceNotFound, ResourceConflict, PreconditionFailed
47from couchdb.design import ViewDefinition47from couchdb.design import ViewDefinition
4848
49from desktopcouch.records import Record49from desktopcouch.records import Record
@@ -134,17 +134,21 @@
134 """Reconnect after losing connection."""134 """Reconnect after losing connection."""
135 self._server = self._server_class(uri or self.server_uri,135 self._server = self._server_class(uri or self.server_uri,
136 **self._server_class_extras)136 **self._server_class_extras)
137 if self._database_name not in self._server:137 if self._create:
138 if self._create:138 try:
139 self._server.create(self._database_name)139 self._server.create(self._database_name)
140 except PreconditionFailed:
141 pass # Not an error to want it created and DB exists.
142
143 try:
144 if self.db is None:
145 self.db = self._server[self._database_name]
140 else:146 else:
141 raise NoSuchDatabase(self._database_name)147 # Monkey-patch the object the user already uses. Oook!
142 if self.db is None:148 new_db = self._server[self._database_name]
143 self.db = self._server[self._database_name]149 self.db.resource = new_db.resource
144 else:150 except ResourceNotFound:
145 # Monkey-patch the object the user already uses. Oook!151 raise NoSuchDatabase(self._database_name)
146 new_db = self._server[self._database_name]
147 self.db.resource = new_db.resource
148152
149 def _temporary_query(self, map_fun, reduce_fun=None, language='javascript',153 def _temporary_query(self, map_fun, reduce_fun=None, language='javascript',
150 wrapper=None, **options):154 wrapper=None, **options):
151155
=== modified file 'desktopcouch/records/tests/test_mocked_server.py'
--- desktopcouch/records/tests/test_mocked_server.py 2011-01-25 17:58:49 +0000
+++ desktopcouch/records/tests/test_mocked_server.py 2011-04-04 19:13:27 +0000
@@ -17,7 +17,7 @@
17# Authors: Manuel de la Pena<manuel@canonical.com>17# Authors: Manuel de la Pena<manuel@canonical.com>
18"""Test the database code mocking the db access."""18"""Test the database code mocking the db access."""
1919
20from couchdb.http import ResourceNotFound20from couchdb.http import ResourceNotFound, PreconditionFailed
21from mocker import MockerTestCase, ANY, KWARGS21from mocker import MockerTestCase, ANY, KWARGS
2222
23from desktopcouch.application.server import DesktopDatabase23from desktopcouch.application.server import DesktopDatabase
@@ -31,8 +31,7 @@
31 testcase.server_class(testcase.uri, ctx=testcase.ctx,31 testcase.server_class(testcase.uri, ctx=testcase.ctx,
32 oauth_tokens=testcase.oauth_tokens)32 oauth_tokens=testcase.oauth_tokens)
33 testcase.mocker.result(testcase.server_class)33 testcase.mocker.result(testcase.server_class)
34 testcase.dbname in testcase.server_class34 testcase.server_class.create(testcase.dbname)
35 testcase.mocker.result(True)
36 testcase.server_class[testcase.dbname]35 testcase.server_class[testcase.dbname]
37 testcase.mocker.result(testcase.server_class)36 testcase.mocker.result(testcase.server_class)
38 testcase.server_class.info()37 testcase.server_class.info()
@@ -61,6 +60,92 @@
61 views_factory=testcase.views_factory)60 views_factory=testcase.views_factory)
6261
6362
63class TestMockedCouchDatabaseCreateStates(MockerTestCase):
64 def setUp(self):
65 """Set up tests."""
66 super(TestMockedCouchDatabaseCreateStates, self).setUp()
67 self.record_factory = self.mocker.mock()
68 self.server_class = self.mocker.mock()
69 self.oauth_tokens = self.mocker.mock()
70 self.ctx = self.mocker.mock()
71 self.uri = 'uri'
72 self.dbname = self._testMethodName
73
74 def test_create_already_exists(self):
75 """Access DB with create=True, when it already exists."""
76 self.server_class(self.uri, ctx=self.ctx,
77 oauth_tokens=self.oauth_tokens)
78 self.mocker.result(self.server_class)
79 self.server_class.create(self.dbname)
80 self.mocker.throw(PreconditionFailed)
81
82 self.server_class[self.dbname]
83 self.mocker.result(self.server_class)
84 self.server_class.info()
85 self.mocker.result({'update_seq': []})
86
87 self.mocker.replay()
88 database = DesktopDatabase(self.dbname, uri=self.uri,
89 record_factory=self.record_factory, create=True,
90 server_class=self.server_class,
91 oauth_tokens=self.oauth_tokens, ctx=self.ctx)
92
93 def test_create_new(self):
94 """Access DB with create=True, when it doesn't exist."""
95 self.server_class(self.uri, ctx=self.ctx,
96 oauth_tokens=self.oauth_tokens)
97 self.mocker.result(self.server_class)
98 self.server_class.create(self.dbname)
99 self.mocker.result(self.server_class)
100 self.server_class[self.dbname]
101 self.mocker.result(self.server_class)
102 info = self.mocker.mock()
103 self.server_class.info()
104 self.mocker.result(info)
105 info["update_seq"]
106 self.mocker.result({})
107 self.mocker.replay()
108 database = DesktopDatabase(self.dbname, uri=self.uri,
109 record_factory=self.record_factory, create=True,
110 server_class=self.server_class,
111 oauth_tokens=self.oauth_tokens, ctx=self.ctx)
112
113 def test_no_create_not_exists(self):
114 """Access DB with create=False, when it already exists."""
115 self.server_class(self.uri, ctx=self.ctx,
116 oauth_tokens=self.oauth_tokens)
117 self.mocker.result(self.server_class)
118
119 self.server_class[self.dbname]
120 self.mocker.throw(ResourceNotFound)
121
122 self.mocker.replay()
123 self.assertRaises(NoSuchDatabase,
124 DesktopDatabase, self.dbname, uri=self.uri,
125 record_factory=self.record_factory, create=False,
126 server_class=self.server_class,
127 oauth_tokens=self.oauth_tokens, ctx=self.ctx)
128
129 def test_no_create_already_exists(self):
130 """Access DB with create=False, when it doesn't exist."""
131 self.server_class(self.uri, ctx=self.ctx,
132 oauth_tokens=self.oauth_tokens)
133 self.mocker.result(self.server_class)
134 self.server_class[self.dbname]
135 self.mocker.result(self.server_class)
136 info = self.mocker.mock()
137 self.server_class.info()
138 self.mocker.result(info)
139 info["update_seq"]
140 self.mocker.result({})
141
142 self.mocker.replay()
143 database = DesktopDatabase(self.dbname, uri=self.uri,
144 record_factory=self.record_factory, create=False,
145 server_class=self.server_class,
146 oauth_tokens=self.oauth_tokens, ctx=self.ctx)
147
148
64class TestMockedCouchDatabaseDeprecated(MockerTestCase):149class TestMockedCouchDatabaseDeprecated(MockerTestCase):
65 """Test the deprecated API."""150 """Test the deprecated API."""
66151
@@ -199,8 +284,8 @@
199 self.server_class(self.uri, ctx=self.ctx,284 self.server_class(self.uri, ctx=self.ctx,
200 oauth_tokens=self.oauth_tokens)285 oauth_tokens=self.oauth_tokens)
201 self.mocker.result(self.server_class)286 self.mocker.result(self.server_class)
202 self.dbname in self.server_class287 self.server_class[self.dbname]
203 self.mocker.result(False)288 self.mocker.throw(ResourceNotFound)
204 self.mocker.replay()289 self.mocker.replay()
205 self.assertRaises(NoSuchDatabase, DesktopDatabase, self.dbname,290 self.assertRaises(NoSuchDatabase, DesktopDatabase, self.dbname,
206 uri=self.uri, record_factory=self.record_factory, create=False,291 uri=self.uri, record_factory=self.record_factory, create=False,

Subscribers

People subscribed via source and target branches