Merge lp:~robru/friends/model-cleanup into lp:friends
- model-cleanup
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Ken VanDine |
Approved revision: | 178 |
Merged at revision: | 175 |
Proposed branch: | lp:~robru/friends/model-cleanup |
Merge into: | lp:friends |
Diff against target: |
316 lines (+118/-22) 7 files modified
friends/protocols/facebook.py (+10/-3) friends/protocols/twitter.py (+10/-7) friends/tests/test_facebook.py (+14/-3) friends/tests/test_identica.py (+1/-1) friends/tests/test_protocols.py (+49/-0) friends/tests/test_twitter.py (+9/-1) friends/utils/base.py (+25/-7) |
To merge this branch: | bzr merge lp:~robru/friends/model-cleanup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Ken VanDine | Approve | ||
Review via email: mp+156704@code.launchpad.net |
Commit message
Thread replies properly, and fix up likes/unlikes to modify model data upon success.
Description of the change
Alright Ken, just like you asked, replies are threading and likes/unlikes are updating the model contents as you'd expect. Not sure how we overlooked this originally ;-)
Anyway, I did the model alteration stuff with a fairly simple API in the Base class, rather than having to import the Model into the protocol classes, which is a bit hacky.
As usual, excellent test coverage is included.
PS Jenkins bot (ps-jenkins) wrote : | # |
Ken VanDine (ken-vandine) wrote : | # |
Looks good and does fix the issue. To test it I connected debug_slave.py to row-changed and called the like/unlike APIs. I consistently saw the value of likes get incremented/
PS Jenkins bot (ps-jenkins) : | # |
Robert Bruce Park (robru) wrote : | # |
That is quite strange. I wonder if that might actually be a dbus synchronization issue rather than anything specific to the code I wrote. Because the way I wrote it, it changes the one value right after the other, although not in an atomic way.
Preview Diff
1 | === modified file 'friends/protocols/facebook.py' | |||
2 | --- friends/protocols/facebook.py 2013-03-16 00:54:45 +0000 | |||
3 | +++ friends/protocols/facebook.py 2013-04-02 21:50:28 +0000 | |||
4 | @@ -226,6 +226,8 @@ | |||
5 | 226 | This includes messages, statuses, wall posts, events, etc. | 226 | This includes messages, statuses, wall posts, events, etc. |
6 | 227 | """ | 227 | """ |
7 | 228 | self._like(obj_id, 'POST') | 228 | self._like(obj_id, 'POST') |
8 | 229 | self._inc_cell(obj_id, 'likes') | ||
9 | 230 | self._set_cell(obj_id, 'liked', True) | ||
10 | 229 | return obj_id | 231 | return obj_id |
11 | 230 | 232 | ||
12 | 231 | @feature | 233 | @feature |
13 | @@ -235,9 +237,11 @@ | |||
14 | 235 | This includes messages, statuses, wall posts, events, etc. | 237 | This includes messages, statuses, wall posts, events, etc. |
15 | 236 | """ | 238 | """ |
16 | 237 | self._like(obj_id, 'DELETE') | 239 | self._like(obj_id, 'DELETE') |
17 | 240 | self._dec_cell(obj_id, 'likes') | ||
18 | 241 | self._set_cell(obj_id, 'liked', False) | ||
19 | 238 | return obj_id | 242 | return obj_id |
20 | 239 | 243 | ||
22 | 240 | def _send(self, obj_id, message, endpoint): | 244 | def _send(self, obj_id, message, endpoint, stream='messages'): |
23 | 241 | url = API_BASE.format(id=obj_id) + endpoint | 245 | url = API_BASE.format(id=obj_id) + endpoint |
24 | 242 | token = self._get_access_token() | 246 | token = self._get_access_token() |
25 | 243 | 247 | ||
26 | @@ -251,7 +255,9 @@ | |||
27 | 251 | 255 | ||
28 | 252 | url = API_BASE.format(id=new_id) | 256 | url = API_BASE.format(id=new_id) |
29 | 253 | entry = Downloader(url, params=dict(access_token=token)).get_json() | 257 | entry = Downloader(url, params=dict(access_token=token)).get_json() |
31 | 254 | return self._publish_entry(entry) | 258 | return self._publish_entry( |
32 | 259 | stream=stream, | ||
33 | 260 | entry=entry) | ||
34 | 255 | 261 | ||
35 | 256 | @feature | 262 | @feature |
36 | 257 | def send(self, message, obj_id='me'): | 263 | def send(self, message, obj_id='me'): |
37 | @@ -270,7 +276,8 @@ | |||
38 | 270 | obj_id can be the id of any Facebook object that supports being | 276 | obj_id can be the id of any Facebook object that supports being |
39 | 271 | commented on, which will generally be Posts. | 277 | commented on, which will generally be Posts. |
40 | 272 | """ | 278 | """ |
42 | 273 | return self._send(obj_id, message, '/comments') | 279 | return self._send(obj_id, message, '/comments', |
43 | 280 | stream='reply_to/{}'.format(obj_id)) | ||
44 | 274 | 281 | ||
45 | 275 | @feature | 282 | @feature |
46 | 276 | def delete(self, obj_id): | 283 | def delete(self, obj_id): |
47 | 277 | 284 | ||
48 | === modified file 'friends/protocols/twitter.py' | |||
49 | --- friends/protocols/twitter.py 2013-03-20 01:24:15 +0000 | |||
50 | +++ friends/protocols/twitter.py 2013-04-02 21:50:28 +0000 | |||
51 | @@ -248,9 +248,10 @@ | |||
52 | 248 | def send_thread(self, message_id, message): | 248 | def send_thread(self, message_id, message): |
53 | 249 | """Send a reply message to message_id. | 249 | """Send a reply message to message_id. |
54 | 250 | 250 | ||
58 | 251 | Note that you have to @mention the message_id owner's screen name in | 251 | This method takes care to prepend the @mention to the start of |
59 | 252 | order for Twitter to actually accept this as a reply. Otherwise it | 252 | your tweet if you forgot it. Without this, Twitter will just |
60 | 253 | will just be an ordinary tweet. | 253 | consider it a regular message, and it won't be part of any |
61 | 254 | conversation. | ||
62 | 254 | """ | 255 | """ |
63 | 255 | try: | 256 | try: |
64 | 256 | sender = '@{}'.format(self._fetch_cell(message_id, 'sender_nick')) | 257 | sender = '@{}'.format(self._fetch_cell(message_id, 'sender_nick')) |
65 | @@ -261,7 +262,8 @@ | |||
66 | 261 | url = self._api_base.format(endpoint='statuses/update') | 262 | url = self._api_base.format(endpoint='statuses/update') |
67 | 262 | tweet = self._get_url(url, dict(in_reply_to_status_id=message_id, | 263 | tweet = self._get_url(url, dict(in_reply_to_status_id=message_id, |
68 | 263 | status=message)) | 264 | status=message)) |
70 | 264 | return self._publish_tweet(tweet) | 265 | return self._publish_tweet( |
71 | 266 | tweet, stream='reply_to/{}'.format(message_id)) | ||
72 | 265 | 267 | ||
73 | 266 | # https://dev.twitter.com/docs/api/1.1/post/statuses/destroy/%3Aid | 268 | # https://dev.twitter.com/docs/api/1.1/post/statuses/destroy/%3Aid |
74 | 267 | @feature | 269 | @feature |
75 | @@ -303,10 +305,9 @@ | |||
76 | 303 | """Announce to the world your undying love for a tweet.""" | 305 | """Announce to the world your undying love for a tweet.""" |
77 | 304 | url = self._api_base.format(endpoint='favorites/create') | 306 | url = self._api_base.format(endpoint='favorites/create') |
78 | 305 | self._get_url(url, dict(id=message_id)) | 307 | self._get_url(url, dict(id=message_id)) |
79 | 308 | self._inc_cell(message_id, 'likes') | ||
80 | 309 | self._set_cell(message_id, 'liked', True) | ||
81 | 306 | return message_id | 310 | return message_id |
82 | 307 | # I don't think we need to publish this tweet because presumably the | ||
83 | 308 | # user has clicked the 'favorite' button on the message that's already | ||
84 | 309 | # in the stream. | ||
85 | 310 | 311 | ||
86 | 311 | # https://dev.twitter.com/docs/api/1.1/post/favorites/destroy | 312 | # https://dev.twitter.com/docs/api/1.1/post/favorites/destroy |
87 | 312 | @feature | 313 | @feature |
88 | @@ -314,6 +315,8 @@ | |||
89 | 314 | """Renounce your undying love for a tweet.""" | 315 | """Renounce your undying love for a tweet.""" |
90 | 315 | url = self._api_base.format(endpoint='favorites/destroy') | 316 | url = self._api_base.format(endpoint='favorites/destroy') |
91 | 316 | self._get_url(url, dict(id=message_id)) | 317 | self._get_url(url, dict(id=message_id)) |
92 | 318 | self._dec_cell(message_id, 'likes') | ||
93 | 319 | self._set_cell(message_id, 'liked', False) | ||
94 | 317 | return message_id | 320 | return message_id |
95 | 318 | 321 | ||
96 | 319 | # https://dev.twitter.com/docs/api/1.1/get/search/tweets | 322 | # https://dev.twitter.com/docs/api/1.1/get/search/tweets |
97 | 320 | 323 | ||
98 | === modified file 'friends/tests/test_facebook.py' | |||
99 | --- friends/tests/test_facebook.py 2013-03-16 00:54:45 +0000 | |||
100 | +++ friends/tests/test_facebook.py 2013-04-02 21:50:28 +0000 | |||
101 | @@ -269,7 +269,8 @@ | |||
102 | 269 | 'http://facebook.com/post_id') | 269 | 'http://facebook.com/post_id') |
103 | 270 | 270 | ||
104 | 271 | token.assert_called_once_with() | 271 | token.assert_called_once_with() |
106 | 272 | publish.assert_called_with({'id': 'post_id'}) | 272 | publish.assert_called_with(entry={'id': 'post_id'}, |
107 | 273 | stream='messages') | ||
108 | 273 | self.assertEqual( | 274 | self.assertEqual( |
109 | 274 | dload.mock_calls, | 275 | dload.mock_calls, |
110 | 275 | [mock.call(), | 276 | [mock.call(), |
111 | @@ -298,7 +299,8 @@ | |||
112 | 298 | 'http://facebook.com/new_post_id') | 299 | 'http://facebook.com/new_post_id') |
113 | 299 | 300 | ||
114 | 300 | token.assert_called_once_with() | 301 | token.assert_called_once_with() |
116 | 301 | publish.assert_called_with({'id': 'post_id'}) | 302 | publish.assert_called_with(entry={'id': 'post_id'}, |
117 | 303 | stream='messages') | ||
118 | 302 | self.assertEqual( | 304 | self.assertEqual( |
119 | 303 | dload.mock_calls, | 305 | dload.mock_calls, |
120 | 304 | [mock.call(), | 306 | [mock.call(), |
121 | @@ -327,7 +329,8 @@ | |||
122 | 327 | 'http://facebook.com/private_message_id') | 329 | 'http://facebook.com/private_message_id') |
123 | 328 | 330 | ||
124 | 329 | token.assert_called_once_with() | 331 | token.assert_called_once_with() |
126 | 330 | publish.assert_called_with({'id': 'comment_id'}) | 332 | publish.assert_called_with(entry={'id': 'comment_id'}, |
127 | 333 | stream='reply_to/post_id') | ||
128 | 331 | self.assertEqual( | 334 | self.assertEqual( |
129 | 332 | dload.mock_calls, | 335 | dload.mock_calls, |
130 | 333 | [mock.call(), | 336 | [mock.call(), |
131 | @@ -427,9 +430,13 @@ | |||
132 | 427 | dload().get_json.return_value = True | 430 | dload().get_json.return_value = True |
133 | 428 | token = self.protocol._get_access_token = mock.Mock( | 431 | token = self.protocol._get_access_token = mock.Mock( |
134 | 429 | return_value='face') | 432 | return_value='face') |
135 | 433 | inc_cell = self.protocol._inc_cell = mock.Mock() | ||
136 | 434 | set_cell = self.protocol._set_cell = mock.Mock() | ||
137 | 430 | 435 | ||
138 | 431 | self.assertEqual(self.protocol.like('post_id'), 'post_id') | 436 | self.assertEqual(self.protocol.like('post_id'), 'post_id') |
139 | 432 | 437 | ||
140 | 438 | inc_cell.assert_called_once_with('post_id', 'likes') | ||
141 | 439 | set_cell.assert_called_once_with('post_id', 'liked', True) | ||
142 | 433 | token.assert_called_once_with() | 440 | token.assert_called_once_with() |
143 | 434 | dload.assert_called_with( | 441 | dload.assert_called_with( |
144 | 435 | 'https://graph.facebook.com/post_id/likes', | 442 | 'https://graph.facebook.com/post_id/likes', |
145 | @@ -441,9 +448,13 @@ | |||
146 | 441 | dload.get_json.return_value = True | 448 | dload.get_json.return_value = True |
147 | 442 | token = self.protocol._get_access_token = mock.Mock( | 449 | token = self.protocol._get_access_token = mock.Mock( |
148 | 443 | return_value='face') | 450 | return_value='face') |
149 | 451 | dec_cell = self.protocol._dec_cell = mock.Mock() | ||
150 | 452 | set_cell = self.protocol._set_cell = mock.Mock() | ||
151 | 444 | 453 | ||
152 | 445 | self.assertEqual(self.protocol.unlike('post_id'), 'post_id') | 454 | self.assertEqual(self.protocol.unlike('post_id'), 'post_id') |
153 | 446 | 455 | ||
154 | 456 | dec_cell.assert_called_once_with('post_id', 'likes') | ||
155 | 457 | set_cell.assert_called_once_with('post_id', 'liked', False) | ||
156 | 447 | token.assert_called_once_with() | 458 | token.assert_called_once_with() |
157 | 448 | dload.assert_called_once_with( | 459 | dload.assert_called_once_with( |
158 | 449 | 'https://graph.facebook.com/post_id/likes', | 460 | 'https://graph.facebook.com/post_id/likes', |
159 | 450 | 461 | ||
160 | === modified file 'friends/tests/test_identica.py' | |||
161 | --- friends/tests/test_identica.py 2013-03-14 19:14:03 +0000 | |||
162 | +++ friends/tests/test_identica.py 2013-04-02 21:50:28 +0000 | |||
163 | @@ -150,7 +150,7 @@ | |||
164 | 150 | '1234', | 150 | '1234', |
165 | 151 | 'Why yes, I would love to respond to your tweet @pumpichank!') | 151 | 'Why yes, I would love to respond to your tweet @pumpichank!') |
166 | 152 | 152 | ||
168 | 153 | publish.assert_called_with('tweet') | 153 | publish.assert_called_with('tweet', stream='reply_to/1234') |
169 | 154 | get_url.assert_called_with( | 154 | get_url.assert_called_with( |
170 | 155 | 'http://identi.ca/api/statuses/update.json', | 155 | 'http://identi.ca/api/statuses/update.json', |
171 | 156 | dict(status= | 156 | dict(status= |
172 | 157 | 157 | ||
173 | === modified file 'friends/tests/test_protocols.py' | |||
174 | --- friends/tests/test_protocols.py 2013-03-19 00:43:13 +0000 | |||
175 | +++ friends/tests/test_protocols.py 2013-04-02 21:50:28 +0000 | |||
176 | @@ -370,6 +370,55 @@ | |||
177 | 370 | self.assertEqual(TestModel.get_row(1)[COLUMN_INDICES['sender']], | 370 | self.assertEqual(TestModel.get_row(1)[COLUMN_INDICES['sender']], |
178 | 371 | 'tedtholomew') | 371 | 'tedtholomew') |
179 | 372 | 372 | ||
180 | 373 | @mock.patch('friends.utils.base.Model', TestModel) | ||
181 | 374 | @mock.patch('friends.utils.base._seen_ids', {}) | ||
182 | 375 | def test_inc_cell(self): | ||
183 | 376 | base = Base(FakeAccount()) | ||
184 | 377 | self.assertEqual(0, TestModel.get_n_rows()) | ||
185 | 378 | self.assertTrue(base._publish(message_id='1234', likes=10, liked=True)) | ||
186 | 379 | base._inc_cell('1234', 'likes') | ||
187 | 380 | row = TestModel.get_row(0) | ||
188 | 381 | self.assertEqual( | ||
189 | 382 | list(row), | ||
190 | 383 | ['base', 88, '1234', '', '', '', '', False, '', '', '', '', 11, | ||
191 | 384 | True, '', '', '', '', '', '', '', 0.0, 0.0]) | ||
192 | 385 | |||
193 | 386 | @mock.patch('friends.utils.base.Model', TestModel) | ||
194 | 387 | @mock.patch('friends.utils.base._seen_ids', {}) | ||
195 | 388 | def test_dec_cell(self): | ||
196 | 389 | base = Base(FakeAccount()) | ||
197 | 390 | self.assertEqual(0, TestModel.get_n_rows()) | ||
198 | 391 | self.assertTrue(base._publish(message_id='1234', likes=10, liked=True)) | ||
199 | 392 | base._dec_cell('1234', 'likes') | ||
200 | 393 | row = TestModel.get_row(0) | ||
201 | 394 | self.assertEqual( | ||
202 | 395 | list(row), | ||
203 | 396 | ['base', 88, '1234', '', '', '', '', False, '', '', '', '', 9, | ||
204 | 397 | True, '', '', '', '', '', '', '', 0.0, 0.0]) | ||
205 | 398 | |||
206 | 399 | @mock.patch('friends.utils.base.Model', TestModel) | ||
207 | 400 | @mock.patch('friends.utils.base._seen_ids', {}) | ||
208 | 401 | def test_set_cell(self): | ||
209 | 402 | base = Base(FakeAccount()) | ||
210 | 403 | self.assertEqual(0, TestModel.get_n_rows()) | ||
211 | 404 | self.assertTrue(base._publish(message_id='1234', likes=10, liked=True)) | ||
212 | 405 | base._set_cell('1234', 'likes', 500) | ||
213 | 406 | base._set_cell('1234', 'liked', False) | ||
214 | 407 | base._set_cell('1234', 'message_id', '5678') | ||
215 | 408 | row = TestModel.get_row(0) | ||
216 | 409 | self.assertEqual( | ||
217 | 410 | list(row), | ||
218 | 411 | ['base', 88, '5678', '', '', '', '', False, '', '', '', '', 500, | ||
219 | 412 | False, '', '', '', '', '', '', '', 0.0, 0.0]) | ||
220 | 413 | |||
221 | 414 | @mock.patch('friends.utils.base.Model', TestModel) | ||
222 | 415 | @mock.patch('friends.utils.base._seen_ids', {}) | ||
223 | 416 | def test_fetch_cell(self): | ||
224 | 417 | base = Base(FakeAccount()) | ||
225 | 418 | self.assertEqual(0, TestModel.get_n_rows()) | ||
226 | 419 | self.assertTrue(base._publish(message_id='1234', likes=10, liked=True)) | ||
227 | 420 | self.assertEqual(base._fetch_cell('1234', 'likes'), 10) | ||
228 | 421 | |||
229 | 373 | def test_basic_login(self): | 422 | def test_basic_login(self): |
230 | 374 | # Try to log in twice. The second login attempt returns False because | 423 | # Try to log in twice. The second login attempt returns False because |
231 | 375 | # it's already logged in. | 424 | # it's already logged in. |
232 | 376 | 425 | ||
233 | === modified file 'friends/tests/test_twitter.py' | |||
234 | --- friends/tests/test_twitter.py 2013-03-19 04:17:58 +0000 | |||
235 | +++ friends/tests/test_twitter.py 2013-04-02 21:50:28 +0000 | |||
236 | @@ -383,7 +383,7 @@ | |||
237 | 383 | 'Why yes, I would love to respond to your tweet @pumpichank!'), | 383 | 'Why yes, I would love to respond to your tweet @pumpichank!'), |
238 | 384 | 'tweet permalink') | 384 | 'tweet permalink') |
239 | 385 | 385 | ||
241 | 386 | publish.assert_called_with('tweet') | 386 | publish.assert_called_with('tweet', stream='reply_to/1234') |
242 | 387 | get_url.assert_called_with( | 387 | get_url.assert_called_with( |
243 | 388 | 'https://api.twitter.com/1.1/statuses/update.json', | 388 | 'https://api.twitter.com/1.1/statuses/update.json', |
244 | 389 | dict(status='Why yes, I would love to respond to your ' | 389 | dict(status='Why yes, I would love to respond to your ' |
245 | @@ -471,18 +471,26 @@ | |||
246 | 471 | 471 | ||
247 | 472 | def test_like(self): | 472 | def test_like(self): |
248 | 473 | get_url = self.protocol._get_url = mock.Mock() | 473 | get_url = self.protocol._get_url = mock.Mock() |
249 | 474 | inc_cell = self.protocol._inc_cell = mock.Mock() | ||
250 | 475 | set_cell = self.protocol._set_cell = mock.Mock() | ||
251 | 474 | 476 | ||
252 | 475 | self.assertEqual(self.protocol.like('1234'), '1234') | 477 | self.assertEqual(self.protocol.like('1234'), '1234') |
253 | 476 | 478 | ||
254 | 479 | inc_cell.assert_called_once_with('1234', 'likes') | ||
255 | 480 | set_cell.assert_called_once_with('1234', 'liked', True) | ||
256 | 477 | get_url.assert_called_with( | 481 | get_url.assert_called_with( |
257 | 478 | 'https://api.twitter.com/1.1/favorites/create.json', | 482 | 'https://api.twitter.com/1.1/favorites/create.json', |
258 | 479 | dict(id='1234')) | 483 | dict(id='1234')) |
259 | 480 | 484 | ||
260 | 481 | def test_unlike(self): | 485 | def test_unlike(self): |
261 | 482 | get_url = self.protocol._get_url = mock.Mock() | 486 | get_url = self.protocol._get_url = mock.Mock() |
262 | 487 | dec_cell = self.protocol._dec_cell = mock.Mock() | ||
263 | 488 | set_cell = self.protocol._set_cell = mock.Mock() | ||
264 | 483 | 489 | ||
265 | 484 | self.assertEqual(self.protocol.unlike('1234'), '1234') | 490 | self.assertEqual(self.protocol.unlike('1234'), '1234') |
266 | 485 | 491 | ||
267 | 492 | dec_cell.assert_called_once_with('1234', 'likes') | ||
268 | 493 | set_cell.assert_called_once_with('1234', 'liked', False) | ||
269 | 486 | get_url.assert_called_with( | 494 | get_url.assert_called_with( |
270 | 487 | 'https://api.twitter.com/1.1/favorites/destroy.json', | 495 | 'https://api.twitter.com/1.1/favorites/destroy.json', |
271 | 488 | dict(id='1234')) | 496 | dict(id='1234')) |
272 | 489 | 497 | ||
273 | === modified file 'friends/utils/base.py' | |||
274 | --- friends/utils/base.py 2013-03-20 01:19:39 +0000 | |||
275 | +++ friends/utils/base.py 2013-04-02 21:50:28 +0000 | |||
276 | @@ -503,15 +503,33 @@ | |||
277 | 503 | message = None | 503 | message = None |
278 | 504 | raise FriendsError(message or str(error)) | 504 | raise FriendsError(message or str(error)) |
279 | 505 | 505 | ||
280 | 506 | def _calculate_row_cell(self, message_id, column_name): | ||
281 | 507 | """Find x,y coords in the model based on message_id and column_name.""" | ||
282 | 508 | row_id = _seen_ids.get(message_id) | ||
283 | 509 | col_idx = COLUMN_INDICES.get(column_name) | ||
284 | 510 | if None in (row_id, col_idx): | ||
285 | 511 | raise FriendsError('Cell could not be found.') | ||
286 | 512 | return row_id, col_idx | ||
287 | 513 | |||
288 | 506 | def _fetch_cell(self, message_id, column_name): | 514 | def _fetch_cell(self, message_id, column_name): |
289 | 507 | """Find a column value associated with a specific message_id.""" | 515 | """Find a column value associated with a specific message_id.""" |
297 | 508 | row_id = _seen_ids.get(message_id) | 516 | row_id, col_idx = self._calculate_row_cell(message_id, column_name) |
298 | 509 | col_idx = COLUMN_INDICES.get(column_name) | 517 | return Model.get_row(row_id)[col_idx] |
299 | 510 | if None not in (row_id, col_idx): | 518 | |
300 | 511 | row = Model.get_row(row_id) | 519 | def _set_cell(self, message_id, column_name, value): |
301 | 512 | return row[col_idx] | 520 | """Set a column value associated with a specific message_id.""" |
302 | 513 | else: | 521 | row_id, col_idx = self._calculate_row_cell(message_id, column_name) |
303 | 514 | raise FriendsError('Value could not be found.') | 522 | Model.get_row(row_id)[col_idx] = value |
304 | 523 | |||
305 | 524 | def _inc_cell(self, message_id, column_name): | ||
306 | 525 | """Increment a column value associated with a specific message_id.""" | ||
307 | 526 | row_id, col_idx = self._calculate_row_cell(message_id, column_name) | ||
308 | 527 | Model.get_row(row_id)[col_idx] += 1 | ||
309 | 528 | |||
310 | 529 | def _dec_cell(self, message_id, column_name): | ||
311 | 530 | """Decrement a column value associated with a specific message_id.""" | ||
312 | 531 | row_id, col_idx = self._calculate_row_cell(message_id, column_name) | ||
313 | 532 | Model.get_row(row_id)[col_idx] -= 1 | ||
314 | 515 | 533 | ||
315 | 516 | def _new_book_client(self, source): | 534 | def _new_book_client(self, source): |
316 | 517 | client = EBook.BookClient.new(source) | 535 | client = EBook.BookClient.new(source) |
FAILED: Continuous integration, rev:178 /code.launchpad .net/~robru/ friends/ model-cleanup/ +merge/ 156704/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ friends- ci/16/ jenkins. qa.ubuntu. com/job/ friends- raring- amd64-ci/ 16
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ friends- ci/16/rebuild
http://