Merge lp:~robru/gwibber/accounts-fixup into lp:~barry/gwibber/py3

Proposed by Robert Bruce Park
Status: Merged
Merged at revision: 1438
Proposed branch: lp:~robru/gwibber/accounts-fixup
Merge into: lp:~barry/gwibber/py3
Diff against target: 630 lines (+122/-104)
13 files modified
gwibber/gwibber/protocols/flickr.py (+9/-12)
gwibber/gwibber/protocols/foursquare.py (+8/-8)
gwibber/gwibber/service/dispatcher.py (+2/-3)
gwibber/gwibber/testing/helpers.py (+11/-3)
gwibber/gwibber/testing/mocks.py (+1/-1)
gwibber/gwibber/tests/test_account.py (+21/-28)
gwibber/gwibber/tests/test_authentication.py (+9/-6)
gwibber/gwibber/tests/test_flickr.py (+9/-10)
gwibber/gwibber/tests/test_foursquare.py (+5/-5)
gwibber/gwibber/tests/test_protocols.py (+2/-6)
gwibber/gwibber/utils/account.py (+35/-14)
gwibber/gwibber/utils/authentication.py (+3/-3)
gwibber/gwibber/utils/base.py (+7/-5)
To merge this branch: bzr merge lp:~robru/gwibber/accounts-fixup
Reviewer Review Type Date Requested Status
Barry Warsaw Needs Fixing
Review via email: mp+125593@code.launchpad.net

Description of the change

Account class no longer inherits from dict.

The important keys that I was able to identify have been upgraded to instance attributes, I've created an Account.config dict as a catch-all to hold anything else that we may not yet know about, and I put in a logger so that one day we may record in action the full gamut of what values to expect here. It might actually turn out that the config dict is entirely irrelevant, but I'm not sure enough of that to do away with it just yet.

This merge makes changes to the flickr and foursquare plugins so that they can correctly access the new Account attributes, and of course all manner of test fixups as well.

This one should be relatively uncontroversial. The only thing that might be confusing is that I did away with Account.global_id because that information is contained within the new Account.id.

To post a comment you must log in.
lp:~robru/gwibber/accounts-fixup updated
1442. By Robert Bruce Park

Fixup some access token stuff that got lost in the shuffle.

1443. By Robert Bruce Park

Fix up some tests that were still testing against dict behavior.

1444. By Robert Bruce Park

Ok, for real this time, there are NO MORE things using account['dict_key'] syntax.

I confirmed it with grep -R this time ;-)

Revision history for this message
Robert Bruce Park (robru) wrote :

Ok barry, earlier today I had mentioned that in this branch the tests were passing, but there was actually a bug that I noticed interactively, that the test suite didn't get because it mocked too aggressively. I looked into this further, and it turned out that we had two different FakeAccount classes in two different places, and one of them was still inheriting from dict, which means that some tests that were expecting dictlike behavior from the Account class were still passing, even though Account class itself was not inheriting from dict. In other words, we had some tests that were not written with the intention of testing the Account class, but contained some code that assumed Account was inheriting from dict, and the mock we were using *did* inherit from dict, so the test passed, even though the real live Account class would have failed that test because it was no longer inheriting from dict.

That is all fixed now, I've unified the two different FakeAccount classes, *none* of them are inheriting from dict any longer, and *all* the code is now correct.

As you can see, I've added some instance attributes to the Account class, for the most important things, and then everything else I've just kind of shoved into this new Account.config dict. I still don't fully know every single thing that can possibly go into that dict, but different plugins do it differently. Eg, Flickr has two different tokens that it shoves in there, and FourSquare only has one token. I think ultimately we will want to get rid of the config dict and have instance attributes for everything. Until then though, this is a big leap in the right direction, with some really important instance attributes defined, and Account no longer inheriting from dict.

I've taken care to update Flickr and FourSquare for these changes, but you'll have to make sure whatever you're doing with Facebook takes this into account.

Revision history for this message
Barry Warsaw (barry) wrote :

Setting to Needs Fixing because there are some conflicts against lp:~barry/gwibber/py3 now. Sorry about that, but I think you're the best person to resolve those conflicts. Please do so and I'll review/merge.

review: Needs Fixing
lp:~robru/gwibber/accounts-fixup updated
1445. By Robert Bruce Park

Rebased onto barry's updated branch, fixup Base._account and Account.id.

All tests pass.

1446. By Robert Bruce Park

Abolish Account.config and upgrade all it's members to instance attributes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'gwibber/gwibber/protocols/flickr.py'
2--- gwibber/gwibber/protocols/flickr.py 2012-09-20 22:17:28 +0000
3+++ gwibber/gwibber/protocols/flickr.py 2012-09-21 16:43:27 +0000
4@@ -54,28 +54,25 @@
5 :return: The id, called NSID by the Flickr service.
6 :rtype: str
7 """
8- if 'user_nsid' not in self.account:
9+ if self._account.user_id is None:
10 # Try to log in.
11 if not self._login():
12 return None
13- return self.account.get('user_nsid')
14+ return self._account.user_id
15
16 def _locked_login(self, old_token):
17 if old_token is None:
18 log.debug('Logging into Flickr')
19 else:
20 log.debug('Re-authenticating to Flickr')
21- result = Authentication(self.account).login()
22+ result = Authentication(self._account).login()
23 if result is None:
24 log.error('No Flickr authentication results received')
25 elif 'AccessToken' in result:
26- massaged_result = Results()
27- massaged_result.update_from(
28- result,
29- 'username', 'user_nsid', 'AccessToken', 'TokenSecret',
30- AccessToken='access_token',
31- TokenSecret='secret_token')
32- self.account.update(massaged_result)
33+ self._account.user_name = result.get('username')
34+ self._account.user_id = result.get('user_nsid')
35+ self._account.access_token = result.get('AccessToken')
36+ self._account.secret_token = result.get('TokenSecret')
37 log.debug('Flickr AccessToken received')
38 else:
39 log.error('No AccessToken in Flickr session: {!r}', result)
40@@ -105,7 +102,7 @@
41 if 'text' in results:
42 results['content'] = results['html'] = results['text']
43 results['service'] = 'flickr'
44- results['account'] = self.account.get('id')
45+ results['account'] = self._account.id
46 raw_time = data.get('dateupload')
47 if raw_time is not None:
48 try:
49@@ -142,7 +139,7 @@
50 if user_id is None:
51 log.error('Flickr: No NSID available')
52 raise AuthorizationError(
53- self.account['id'], 'No Flickr user id available')
54+ self._account.id, 'No Flickr user id available')
55 # The user is logged into Flickr.
56 GET_arguments = dict(
57 api_key = API_KEY,
58
59=== modified file 'gwibber/gwibber/protocols/foursquare.py'
60--- gwibber/gwibber/protocols/foursquare.py 2012-09-20 16:26:53 +0000
61+++ gwibber/gwibber/protocols/foursquare.py 2012-09-21 16:43:27 +0000
62@@ -59,7 +59,7 @@
63 log.debug('{} to FourSquare'.format(
64 'Re-authenticating' if old_token else 'Logging in'))
65
66- result = Authentication(self.account, log).login()
67+ result = Authentication(self._account, log).login()
68 if result is None:
69 log.error('No FourSquare authentication results received.')
70 return
71@@ -71,27 +71,27 @@
72 data = get_json(SELF_URL.format(access_token=token)) or {}
73 user = data.get('response', {}).get('user', {})
74 uid = user['id']
75- self.account.update(username=_full_name(user),
76- access_token=token,
77- user_id=uid)
78+ self._account.access_token = token
79+ self._account.user_name = _full_name(user)
80+ self._account.user_id = uid
81 log.debug('FourSquare UID is: {}', uid)
82
83 def _get_access_token(self):
84 """Return an access token, logging in if necessary."""
85- token = self.account.get('access_token')
86+ token = self._account.access_token
87 if token is not None:
88 return token
89 if not self._login():
90 log.error('No FourSquare authenticate results received.')
91 return None
92- return self.account.get('access_token')
93+ return self._account.access_token
94
95 def receive(self):
96 """Gets a list of each friend's most recent check-ins."""
97 token = self._get_access_token()
98 if token is None:
99 raise AuthorizationError(
100- self.account, 'No FourSquare user id available')
101+ self._account, 'No FourSquare user id available')
102 # We are successfully logged in.
103 result = get_json(RECENT_URL.format(access_token=token))
104
105@@ -109,7 +109,7 @@
106 tz_offset = checkin.get('timeZoneOffset', 0)
107 epoch = checkin.get('createdAt')
108 self._publish(
109- account_id=self.account['id'],
110+ account_id=self._account.id,
111 message_id=checkin_id,
112 stream='messages',
113 sender=_full_name(user),
114
115=== modified file 'gwibber/gwibber/service/dispatcher.py'
116--- gwibber/gwibber/service/dispatcher.py 2012-09-18 21:27:54 +0000
117+++ gwibber/gwibber/service/dispatcher.py 2012-09-21 16:43:27 +0000
118@@ -142,7 +142,7 @@
119 if not self.online:
120 return
121 for account in self.account_manager.get_all():
122- if account['send_enabled']:
123+ if account.send_enabled:
124 account.protocol('send', message)
125
126 @dbus.service.method('com.Gwibber.Service', out_signature='s')
127@@ -160,8 +160,7 @@
128 # features is set to a harmless empty list.
129 protocol = protocol_manager.protocols.get(protocol_name)
130 features = [operation for operation in dir(protocol)
131- if operation != 'info' and not operation.startswith('_')
132- ]
133+ if not operation.startswith('_')]
134 return json.dumps(features)
135
136 @dbus.service.method('com.Gwibber.Service',
137
138=== modified file 'gwibber/gwibber/testing/helpers.py'
139--- gwibber/gwibber/testing/helpers.py 2012-09-20 22:17:28 +0000
140+++ gwibber/gwibber/testing/helpers.py 2012-09-21 16:43:27 +0000
141@@ -22,10 +22,18 @@
142 import threading
143
144
145-class FakeAccount(dict):
146+class FakeAuth:
147+ pass
148+
149+
150+class FakeAccount:
151 """A fake account object for testing purposes."""
152
153 def __init__(self, service=None):
154+ self.access_token = None
155+ self.user_name = None
156+ self.user_id = None
157+ self.config = {}
158+ self.auth = FakeAuth()
159 self.login_lock = threading.Lock()
160- self.global_id = 'fake global id'
161- self['id'] = 'faker/than fake'
162+ self.id = 'faker/than fake'
163
164=== modified file 'gwibber/gwibber/testing/mocks.py'
165--- gwibber/gwibber/testing/mocks.py 2012-09-21 14:11:34 +0000
166+++ gwibber/gwibber/testing/mocks.py 2012-09-21 16:43:27 +0000
167@@ -107,7 +107,7 @@
168 """
169
170 def __init__(self):
171- self.items = [(True, 'key', 'value')]
172+ self.items = [(True, 'send_enabled', True)]
173
174 def next(self):
175 if self.items:
176
177=== modified file 'gwibber/gwibber/tests/test_account.py'
178--- gwibber/gwibber/tests/test_account.py 2012-09-20 22:17:28 +0000
179+++ gwibber/gwibber/tests/test_account.py 2012-09-21 16:43:27 +0000
180@@ -70,21 +70,16 @@
181 self.account = Account(self.account_service)
182
183 def test_account_auth(self):
184- # Test that the constructor initializes the 'auth' key.
185- auth = self.account['auth']
186- self.assertEqual(len(auth), 4)
187- self.assertEqual(auth['id'], 'fake credentials')
188- self.assertEqual(auth['method'], 'fake method')
189- self.assertEqual(auth['mechanism'], 'fake mechanism')
190- self.assertEqual(auth['parameters'], 'fake parameters')
191-
192- def test_account_global_id(self):
193- # Test the account's global id.
194- self.assertEqual(self.account.global_id, 'fake_id')
195+ # Test that the constructor initializes the 'auth' attribute.
196+ auth = self.account.auth
197+ self.assertEqual(auth.id, 'fake credentials')
198+ self.assertEqual(auth.method, 'fake method')
199+ self.assertEqual(auth.mechanism, 'fake mechanism')
200+ self.assertEqual(auth.parameters, 'fake parameters')
201
202 def test_account_id(self):
203 # The 'id' key of the account gets the full service name.
204- self.assertEqual(self.account['id'], 'fake_id/fake_service')
205+ self.assertEqual(self.account.id, 'fake_id/flickr')
206
207 def test_account_service(self):
208 # The protocol attribute refers directly to the protocol used.
209@@ -101,7 +96,7 @@
210 def test_on_account_changed(self):
211 # Account.on_account_changed() gets called during the Account
212 # constructor. Test that it has the expected original key value.
213- self.assertEqual(self.account['key'], 'value')
214+ self.assertEqual(self.account.send_enabled, True)
215
216 def test_iter_filter(self):
217 # The get_settings_iter() filters everything that doesn't start with
218@@ -115,7 +110,7 @@
219 # Start by simulating a change in the account service.
220 other_iter = SettingsIterMock()
221 other_iter.items = [
222- (True, 'ant', 'one'),
223+ (True, 'send_enabled', False),
224 (True, 'bee', 'two'),
225 (True, 'cat', 'three'),
226 ]
227@@ -129,10 +124,9 @@
228 # Simulate the signal.
229 self._callback(self.account_service, self._callback_account)
230 # Have the expected updates occurred?
231- self.assertEqual(self.account['ant'], 'one')
232- self.assertEqual(self.account['bee'], 'two')
233- self.assertEqual(self.account['cat'], 'three')
234- self.assertNotIn('dog', self.account)
235+ self.assertEqual(self.account.send_enabled, False)
236+ self.assertFalse(hasattr(self.account, 'bee'))
237+ self.assertFalse(hasattr(self.account, 'cat'))
238
239 def test_enabled(self):
240 # .enabled() just passes through from the account service.
241@@ -188,7 +182,7 @@
242 pass
243 manager = AccountManager(refresh)
244 manager.add_new_account(self.account_service)
245- self.assertIn('fake global id', manager._accounts)
246+ self.assertIn('faker/than fake', manager._accounts)
247
248 def test_account_manager_enabled_event(self):
249 # Mimic a reaction to the enabled-event callback.
250@@ -198,7 +192,7 @@
251 refreshed = True
252 accounts_manager.get_account().list_services.return_value = []
253 manager = AccountManager(refresh)
254- manager._on_enabled_event(accounts_manager, 'fake global id')
255+ manager._on_enabled_event(accounts_manager, 'faker/than fake')
256 self.assertTrue(refreshed)
257
258 def test_account_manager_delete_account_no_account(self):
259@@ -210,21 +204,20 @@
260 nonlocal refreshed
261 refreshed = True
262 manager = AccountManager(refresh)
263- self.assertNotIn('fake global id', manager._accounts)
264- manager._on_account_deleted(accounts_manager, 'fake global id')
265- self.assertNotIn('fake global id', manager._accounts)
266+ self.assertNotIn('faker/than fake', manager._accounts)
267+ manager._on_account_deleted(accounts_manager, 'faker/than fake')
268+ self.assertNotIn('faker/than fake', manager._accounts)
269 self.assertFalse(refreshed)
270
271 def test_account_manager_delete_account(self):
272- # Deleting an account removes the global_id from the mapping. But if
273- # that global id is missing, then it does not cause an exception.
274+ # Deleting an account removes the id from the mapping. But if
275+ # that id is missing, then it does not cause an exception.
276 refreshed = False
277 def refresh():
278 nonlocal refreshed
279 refreshed = True
280 manager = AccountManager(refresh)
281 manager.add_new_account(self.account_service)
282- # Now manager._accounts has a 'fake global id' key.
283- manager._on_account_deleted(accounts_manager, 'fake global id')
284- self.assertNotIn('fake global id', manager._accounts)
285+ manager._on_account_deleted(accounts_manager, 'faker/than fake')
286+ self.assertNotIn('faker/than fake', manager._accounts)
287 self.assertTrue(refreshed)
288
289=== modified file 'gwibber/gwibber/tests/test_authentication.py'
290--- gwibber/gwibber/tests/test_authentication.py 2012-08-22 22:37:45 +0000
291+++ gwibber/gwibber/tests/test_authentication.py 2012-09-21 16:43:27 +0000
292@@ -26,6 +26,8 @@
293 import unittest
294
295 from gwibber.utils.authentication import Authentication
296+from gwibber.testing.helpers import FakeAccount
297+
298
299 try:
300 # Python 3.3
301@@ -64,16 +66,17 @@
302 """Test authentication."""
303
304 def setUp(self):
305- self.account = dict(auth=dict(id='my id',
306- method='some method',
307- parameters='change me',
308- mechanism=['whatever']))
309+ self.account = FakeAccount()
310+ self.account.auth.id = 'my id'
311+ self.account.auth.method = 'some method'
312+ self.account.auth.parameters = 'change me'
313+ self.account.auth.mechanism = ['whatever']
314 self.logger = Logger()
315
316 @mock.patch('gwibber.utils.authentication.Signon', FakeSignon)
317 def test_successful_login(self):
318 # Prevent an error in the callback.
319- self.account['auth']['parameters'] = False
320+ self.account.auth.parameters = False
321 authenticator = Authentication(self.account, self.logger)
322 reply = authenticator.login()
323 self.assertEqual(reply, 'auth reply')
324@@ -86,7 +89,7 @@
325 # Trigger an error in the callback.
326 class Error:
327 message = 'who are you?'
328- self.account['auth']['parameters'] = Error
329+ self.account.auth.parameters = Error
330 authenticator = Authentication(self.account, self.logger)
331 reply = authenticator.login()
332 self.assertIsNone(reply)
333
334=== modified file 'gwibber/gwibber/tests/test_flickr.py'
335--- gwibber/gwibber/tests/test_flickr.py 2012-09-21 14:11:34 +0000
336+++ gwibber/gwibber/tests/test_flickr.py 2012-09-21 16:43:27 +0000
337@@ -66,9 +66,8 @@
338 @mock.patch('gwibber.utils.download.urlopen',
339 FakeData('gwibber.tests.data', 'flickr-nophotos.dat'))
340 def test_already_logged_in(self):
341- # Try to get the data when the 'user_nsid' key is already in the
342- # account; i.e. already logged in.
343- self.account['user_nsid'] = 'anne'
344+ # Try to get the data when already logged in.
345+ self.account.user_id = 'anne'
346 # There's no data, and no way to test that the user_nsid was actually
347 # used, except for the side effect of not getting an
348 # AuthorizationError.
349@@ -82,7 +81,7 @@
350 def side_effect():
351 # Sorry, the login is unsuccessful, even though it adds a
352 # user_nsid key to the account.
353- self.account['user_nsid'] = 'bart'
354+ self.account.user_id = 'bart'
355 return False
356 with mock.patch.object(self.protocol, '_login',
357 side_effect=side_effect):
358@@ -95,7 +94,7 @@
359 # succeeds.
360 def side_effect():
361 # Perform a successful login.
362- self.account['user_nsid'] = 'cate'
363+ self.account.user_id = 'cate'
364 return True
365 with mock.patch.object(self.protocol, '_login',
366 side_effect=side_effect):
367@@ -135,10 +134,10 @@
368 # AccessToken, but this fails.
369 self.assertEqual(self.protocol.images(), [])
370 # Make sure our account data got properly updated.
371- self.assertEqual(self.account['username'], 'Bob Dobbs')
372- self.assertEqual(self.account['user_nsid'], 'bob')
373- self.assertEqual(self.account['access_token'], '123')
374- self.assertEqual(self.account['secret_token'], 'abc')
375+ self.assertEqual(self.account.user_name, 'Bob Dobbs')
376+ self.assertEqual(self.account.user_id, 'bob')
377+ self.assertEqual(self.account.access_token, '123')
378+ self.assertEqual(self.account.secret_token, 'abc')
379
380 def test_get(self):
381 # Make sure that the REST GET url looks right.
382@@ -177,7 +176,7 @@
383 # JSON Flickr data into the format expected internally.
384 #
385 # Start by setting up a fake account id.
386- self.account['id'] = 'lerxst'
387+ self.account.id = 'lerxst'
388 with mock.patch.object(self.protocol, '_get_nsid', return_value='jim'):
389 images = self.protocol.images()
390 self.assertEqual(len(images), 3)
391
392=== modified file 'gwibber/gwibber/tests/test_foursquare.py'
393--- gwibber/gwibber/tests/test_foursquare.py 2012-09-21 14:11:34 +0000
394+++ gwibber/gwibber/tests/test_foursquare.py 2012-09-21 16:43:27 +0000
395@@ -67,8 +67,8 @@
396 return_value=None)
397 def test_unsuccessful_authentication(self, *mocks):
398 self.assertFalse(self.protocol._login())
399- self.assertNotIn('username', self.account)
400- self.assertNotIn('user_id', self.account)
401+ self.assertIsNone(self.account.user_name)
402+ self.assertIsNone(self.account.user_id)
403
404 @mock.patch('gwibber.utils.authentication.Authentication.login',
405 return_value=dict(AccessToken='tokeny goodness'))
406@@ -80,8 +80,8 @@
407 id='1234567'))))
408 def test_successful_authentication(self, *mocks):
409 self.assertTrue(self.protocol._login())
410- self.assertEqual(self.account['username'], 'Bob Loblaw')
411- self.assertEqual(self.account['user_id'], '1234567')
412+ self.assertEqual(self.account.user_name, 'Bob Loblaw')
413+ self.assertEqual(self.account.user_id, '1234567')
414
415 @mock.patch('gwibber.utils.base.Model', TestModel)
416 @mock.patch('gwibber.utils.download.urlopen',
417@@ -89,7 +89,7 @@
418 @mock.patch('gwibber.protocols.foursquare.FourSquare._login',
419 return_value=True)
420 def test_receive(self, *mocks):
421- self.account['access_token'] = 'tokeny goodness'
422+ self.account.access_token = 'tokeny goodness'
423 self.assertEqual(0, TestModel.get_n_rows())
424 self.protocol.receive()
425 self.assertEqual(1, TestModel.get_n_rows())
426
427=== modified file 'gwibber/gwibber/tests/test_protocols.py'
428--- gwibber/gwibber/tests/test_protocols.py 2012-09-20 16:26:53 +0000
429+++ gwibber/gwibber/tests/test_protocols.py 2012-09-21 16:43:27 +0000
430@@ -27,6 +27,7 @@
431
432 from gwibber.protocols.flickr import Flickr
433 from gwibber.protocols.twitter import Twitter
434+from gwibber.testing.helpers import FakeAccount
435 from gwibber.utils.base import Base
436 from gwibber.utils.manager import ProtocolManager
437 from gwibber.utils.model import (
438@@ -64,11 +65,6 @@
439 self.assertNotEqual(protocol_class, Base)
440
441
442-class FakeAccount(dict):
443- def __init__(self):
444- self.login_lock = threading.Lock()
445-
446-
447 class MyProtocol(Base):
448 """Simplest possible protocol implementation to allow testing of Base."""
449
450@@ -84,7 +80,7 @@
451 _private = noop
452
453 def _locked_login(self, old_token):
454- self.account['access_token'] = 'fake_token'
455+ self._account.access_token = 'fake_token'
456
457
458 class TestProtocols(unittest.TestCase):
459
460=== modified file 'gwibber/gwibber/utils/account.py'
461--- gwibber/gwibber/utils/account.py 2012-09-19 20:05:40 +0000
462+++ gwibber/gwibber/utils/account.py 2012-09-21 16:43:27 +0000
463@@ -14,6 +14,7 @@
464
465 """The libaccounts account service wrapper."""
466
467+
468 __all__ = [
469 'Account',
470 'AccountManager',
471@@ -30,7 +31,7 @@
472 from gwibber.utils.model import COLUMN_INDICES, Model
473
474
475-log = logging.getLogger('gwibber.accounts')
476+log = logging.getLogger('gwibber.service')
477
478
479 class AccountManager:
480@@ -78,7 +79,7 @@
481
482 def add_new_account(self, account_service):
483 new_account = Account(account_service)
484- self._accounts[new_account.global_id] = new_account
485+ self._accounts[new_account.id] = new_account
486
487 def get_all(self):
488 return self._accounts.values()
489@@ -87,30 +88,43 @@
490 return self._accounts.get(account_id, default)
491
492
493-class Account(dict):
494+class AuthData:
495+ """This class serves as a sub-namespace for Account instances."""
496+
497+ def __init__(self, auth_data):
498+ self.id = auth_data.get_credentials_id()
499+ self.method = auth_data.get_method()
500+ self.mechanism = auth_data.get_mechanism()
501+ self.parameters = auth_data.get_parameters()
502+
503+
504+class Account:
505 """A thin wrapper around libaccounts API."""
506+ access_token = None
507+ secret_token = None
508+ send_enabled = None
509+ user_name = None
510+ user_id = None
511+ auth = None
512+ id = None
513
514 def __init__(self, account_service):
515 self.account_service = account_service
516 auth_data = account_service.get_auth_data()
517- self['auth'] = dict(
518- id = auth_data.get_credentials_id(),
519- method = auth_data.get_method(),
520- mechanism = auth_data.get_mechanism(),
521- parameters = auth_data.get_parameters(),
522- )
523+ self.auth = AuthData(account_service.get_auth_data())
524
525+ # The provider in libaccounts should match the name of our protocol.
526 account = account_service.get_account()
527- self.global_id = account.id
528- service_name = account_service.get_service().get_name()
529- self['id'] = '{}/{}'.format(self.global_id, service_name)
530- # The provider in libaccounts should match the name of our protocol.
531 protocol_name = account.get_provider_name()
532 protocol_class = protocol_manager.protocols.get(protocol_name)
533 if protocol_class is None:
534 raise UnsupportedProtocolError(protocol_name)
535 self.protocol = protocol_class(self)
536
537+ # account.id is a number, and the protocol_name is a word, so
538+ # the resulting id will look something like '6/twitter' or '2/facebook'
539+ self.id = '{}/{}'.format(account.id, protocol_name)
540+
541 account_service.connect('changed', self._on_account_changed, account)
542 self._on_account_changed(account_service, account)
543
544@@ -129,7 +143,11 @@
545 while True:
546 success, key, value = settings.next()
547 if success:
548- self[key] = value
549+ log.debug('{} got {}: {}'.format(self.id, key, value))
550+ # Testing for tuple membership makes this easy to
551+ # expand later, if necessary.
552+ if key in ('send_enabled',):
553+ setattr(self, key, value)
554 else:
555 break
556
557@@ -138,3 +156,6 @@
558
559 def __eq__(self, other):
560 return self.account_service == other.account_service
561+
562+ def __ne__(self, other):
563+ return self.account_service != other.account_service
564
565=== modified file 'gwibber/gwibber/utils/authentication.py'
566--- gwibber/gwibber/utils/authentication.py 2012-09-05 22:09:44 +0000
567+++ gwibber/gwibber/utils/authentication.py 2012-09-21 16:43:27 +0000
568@@ -35,12 +35,12 @@
569 self._authenticating = False
570
571 def login(self):
572- auth = self.account['auth']
573- self.auth_session = Signon.AuthSession.new(auth['id'], auth['method'])
574+ auth = self.account.auth
575+ self.auth_session = Signon.AuthSession.new(auth.id, auth.method)
576 self._authenticating = True
577 self._loop = GObject.MainLoop()
578 self.auth_session.process(
579- auth['parameters'], auth['mechanism'],
580+ auth.parameters, auth.mechanism,
581 self._login_cb, None)
582 if self._authenticating:
583 self._loop.run()
584
585=== modified file 'gwibber/gwibber/utils/base.py'
586--- gwibber/gwibber/utils/base.py 2012-09-21 14:11:34 +0000
587+++ gwibber/gwibber/utils/base.py 2012-09-21 16:43:27 +0000
588@@ -36,11 +36,13 @@
589 MESSAGE_IDX = COLUMN_INDICES['message']
590 IDS_IDX = COLUMN_INDICES['message_ids']
591
592+
593 # This is a mapping from Dee.SharedModel row keys to the DeeModelIters
594 # representing the rows matching those keys. It is used for quickly finding
595 # duplicates when we want to insert new rows into the model.
596 _seen_messages = {}
597
598+
599 # Protocol __call__() methods run in threads, so we need to serialize
600 # publishing new data into the SharedModel.
601 _publish_lock = threading.Lock()
602@@ -110,7 +112,7 @@
603 _SYNCHRONIZE = False
604
605 def __init__(self, account):
606- self.account = account
607+ self._account = account
608
609 def __call__(self, operation, *args, **kwargs):
610 """Call an operation, i.e. a method, with arguments in a sub-thread.
611@@ -220,15 +222,15 @@
612 # changed because thread A is already logged in. It does not try to
613 # log in again, but also returns True since the access token has
614 # changed. IOW, thread B is also already logged in via thread A.
615- old_token = self.account.get('access_token')
616- with self.account.login_lock:
617- if self.account.get('access_token') == old_token:
618+ old_token = self._account.access_token
619+ with self._account.login_lock:
620+ if self._account.access_token == old_token:
621 self._locked_login(old_token)
622 # This test must be performed while the login lock is acquired,
623 # otherwise it's possible for another thread to come in between
624 # the release of the login lock and the test, and change the
625 # access token.
626- return self.account.get('access_token') != old_token
627+ return self._account.access_token != old_token
628
629 def _locked_login(self, old_token):
630 """Login operation stub. This must be implemented by subclasses."""

Subscribers

People subscribed via source and target branches