Merge lp:~nataliabidart/ubuntuone-client/login-email-password-for-everyone into lp:ubuntuone-client

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 1122
Merged at revision: 1117
Proposed branch: lp:~nataliabidart/ubuntuone-client/login-email-password-for-everyone
Merge into: lp:ubuntuone-client
Diff against target: 1262 lines (+647/-296)
7 files modified
contrib/login_email_password.py (+19/-8)
tests/platform/linux/test_credentials.py (+15/-30)
tests/platform/test_credentials.py (+391/-111)
tests/platform/windows/test_credentials.py (+95/-16)
ubuntuone/platform/credentials/__init__.py (+76/-49)
ubuntuone/platform/credentials/linux.py (+11/-70)
ubuntuone/platform/credentials/windows.py (+40/-12)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-client/login-email-password-for-everyone
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) ran tests Approve
Manuel de la Peña (community) Approve
Review via email: mp+72735@code.launchpad.net

Commit message

- CredentialsManagementTool provides login_email_password in both platforms (LP: #831043).
- Filtering signals by appname in credentials windows side (LP: #818190).

Description of the change

You can test this on both linux and windows by running:

PYTHONPATH=. contrib/login_email_password.py

You will be prompted by email and password, and the result will be printed in the terminal.
In windows, please be sure to have latest ussoc service running and in the PYTHONPATH.

To post a comment you must log in.
1119. By Natalia Bidart

Typo.

Revision history for this message
Alejandro J. Cura (alecu) wrote :

Very nice cleanup branch.

Some issues:

----

There's a latent issue in making the variable "done" an instance variable in CredentialsManagementTool, and using it through all the inlineCallbacks generators in this class.

The "done" should be different for each of this generators, since more than one can be used at once.

I strongly believe instance variables *are not* clean to use here, and that they should be left as variables local to the generator. And perhaps we can have callback_done and errback_done get the "done" deferred from each generator via functools.partial.

----

This docstring is wrong (looks duplicated from the one above):

    def CredentialsStored(self):
        """Signal thrown when the credentials were cleared."""

----

The empty line should be restored before class CredentialsError.

----

review: Needs Fixing (just eyeballed the code)
1120. By Natalia Bidart

Merged trunk in.

1121. By Natalia Bidart

Fixes from review.

Revision history for this message
Manuel de la Peña (mandel) wrote :

Looks good to me.

review: Approve
1122. By Natalia Bidart

Merged trunk in.

Revision history for this message
Alejandro J. Cura (alecu) wrote :

Looks great!

review: Approve (ran tests)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'contrib/login_email_password.py' (properties changed: -x to +x)
2--- contrib/login_email_password.py 2011-07-29 17:57:25 +0000
3+++ contrib/login_email_password.py 2011-08-26 17:23:37 +0000
4@@ -16,6 +16,12 @@
5 # with this program. If not, see <http://www.gnu.org/licenses/>.
6 """Script that shows the qt gui."""
7
8+import sys
9+
10+if sys.platform != 'win32':
11+ from twisted.internet import glib2reactor
12+ glib2reactor.install()
13+
14 # pylint: disable=F0401, E1101
15 from twisted.internet import reactor
16 from twisted.internet.defer import inlineCallbacks
17@@ -23,18 +29,23 @@
18
19
20 @inlineCallbacks
21-def main():
22+def main(email='whomever@canonical.com', password='whatever'):
23 """Perform a client request to be logged in."""
24 credtool = CredentialsManagementTool()
25-
26- creds = yield credtool.login_email_password(
27- email='whomever@canonical.com',
28- password='whatever',
29- )
30- print "creds found", creds
31+ print 'Trying to get credentials for email:', email
32+ try:
33+ creds = yield credtool.login_email_password(email=email,
34+ password=password)
35+ print "creds found!", creds
36+ except Exception, e:
37+ print "creds error!", e
38 reactor.stop()
39
40
41 if __name__ == '__main__':
42- main()
43+ print 'Enter email:'
44+ email = raw_input()
45+ print 'Enter password:'
46+ password = raw_input()
47+ main(email=email, password=password)
48 reactor.run()
49
50=== modified file 'tests/platform/linux/test_credentials.py'
51--- tests/platform/linux/test_credentials.py 2011-08-16 13:44:20 +0000
52+++ tests/platform/linux/test_credentials.py 2011-08-26 17:23:37 +0000
53@@ -885,12 +885,9 @@
54 """Find credentials and error."""
55 FakedSSOService.error_dict = {'failure': 'really'}
56
57- try:
58- yield self.client.find_credentials()
59- except CredentialsError, e:
60- self.assertEqual(e[0], FakedSSOService.error_dict)
61- else:
62- self.fail('Must not succeed!')
63+ e = yield self.assertFailure(self.client.find_credentials(),
64+ CredentialsError)
65+ self.assertEqual(e[0], FakedSSOService.error_dict)
66
67 @inlineCallbacks
68 def test_clear_credentials(self):
69@@ -907,12 +904,9 @@
70 """Clear credentials and error."""
71 FakedSSOService.error_dict = {'failure': 'really'}
72
73- try:
74- yield self.client.clear_credentials()
75- except CredentialsError, e:
76- self.assertEqual(e[0], FakedSSOService.error_dict)
77- else:
78- self.fail('Must not succeed!')
79+ e = yield self.assertFailure(self.client.clear_credentials(),
80+ CredentialsError)
81+ self.assertEqual(e[0], FakedSSOService.error_dict)
82
83 @inlineCallbacks
84 def test_store_credentials(self):
85@@ -929,12 +923,9 @@
86 """Store credentials and error."""
87 FakedSSOService.error_dict = {'failure': 'really'}
88
89- try:
90- yield self.client.store_credentials({'test': 'me'})
91- except CredentialsError, e:
92- self.assertEqual(e[0], FakedSSOService.error_dict)
93- else:
94- self.fail('Must not succeed!')
95+ e = yield self.assertFailure(self.client.store_credentials({'0': '1'}),
96+ CredentialsError)
97+ self.assertEqual(e[0], FakedSSOService.error_dict)
98
99 @inlineCallbacks
100 def test_register(self):
101@@ -956,12 +947,9 @@
102 """Register and error."""
103 FakedSSOService.error_dict = {'failure': 'really'}
104
105- try:
106- yield self.client.register()
107- except CredentialsError, e:
108- self.assertEqual(e[0], FakedSSOService.error_dict)
109- else:
110- self.fail('Must not succeed!')
111+ e = yield self.assertFailure(self.client.register(),
112+ CredentialsError)
113+ self.assertEqual(e[0], FakedSSOService.error_dict)
114
115 @inlineCallbacks
116 def test_login(self):
117@@ -983,9 +971,6 @@
118 """Login and error."""
119 FakedSSOService.error_dict = {'failure': 'really'}
120
121- try:
122- yield self.client.login()
123- except CredentialsError, e:
124- self.assertEqual(e[0], FakedSSOService.error_dict)
125- else:
126- self.fail('Must not succeed!')
127+ e = yield self.assertFailure(self.client.login(),
128+ CredentialsError)
129+ self.assertEqual(e[0], FakedSSOService.error_dict)
130
131=== modified file 'tests/platform/test_credentials.py'
132--- tests/platform/test_credentials.py 2011-08-18 13:13:37 +0000
133+++ tests/platform/test_credentials.py 2011-08-26 17:23:37 +0000
134@@ -22,127 +22,407 @@
135 import urllib
136 import urlparse
137
138-from mocker import MockerTestCase, MATCH
139+from collections import defaultdict
140+from functools import wraps
141+
142 from twisted.internet import defer
143 from twisted.trial.unittest import TestCase
144
145 from ubuntuone import clientdefs
146 from ubuntuone.platform.credentials import (
147 BASE_PING_URL,
148+ CredentialsError,
149 CredentialsManagementTool,
150+ NO_OP,
151 PING_URL,
152 platform_data,
153 )
154-
155-
156-class TestCredentialsManagementTool(MockerTestCase):
157- """Test the credentials management tool mocking the proxy."""
158-
159- def setUp(self):
160- """Set the diff tests."""
161- super(TestCredentialsManagementTool, self).setUp()
162- self.get_cred_proxy = self.mocker.mock()
163- self.proxy = self.mocker.mock()
164- self.management_tool = CredentialsManagementTool()
165- self.management_tool.get_creds_proxy = self.get_cred_proxy
166-
167- def test_find_credentials(self):
168- """Test that we do ask for the credentials correctly."""
169- signals = ['creds_found', 'creds_not_found', 'creds_erro']
170- self.get_cred_proxy()
171- self.mocker.result(self.proxy)
172- self.proxy.register_to_credentials_found(MATCH(callable))
173- self.mocker.result(signals[0])
174- self.proxy.register_to_credentials_not_found(MATCH(callable))
175- self.mocker.result(signals[1])
176- self.proxy.register_to_credentials_error(MATCH(callable))
177- self.mocker.result(signals[2])
178- self.proxy.find_credentials(reply_handler=MATCH(callable),
179- error_handler=MATCH(callable))
180- self.mocker.replay()
181- return self.management_tool.find_credentials()
182-
183- def test_clear_credentials(self):
184- """Test that we clear the credentials correctly."""
185- signals = ['creds_cleared', 'creds_error']
186- self.get_cred_proxy()
187- self.mocker.result(self.proxy)
188- self.proxy.register_to_credentials_cleared(MATCH(callable))
189- self.mocker.result(signals[0])
190- self.proxy.register_to_credentials_error(MATCH(callable))
191- self.mocker.result(signals[1])
192- self.proxy.clear_credentials(reply_handler=MATCH(callable),
193- error_handler=MATCH(callable))
194- self.mocker.replay()
195- return self.management_tool.clear_credentials()
196-
197- def test_store_credentials(self):
198- """Test that we store the credentials correctly."""
199- token = 'token'
200- signals = ['creds_stored','creds_error']
201- self.get_cred_proxy()
202- self.mocker.result(self.proxy)
203- self.proxy.register_to_credentials_stored(MATCH(callable))
204- self.mocker.result(signals[0])
205- self.proxy.register_to_credentials_error(MATCH(callable))
206- self.mocker.result(signals[1])
207- self.proxy.store_credentials(token, reply_handler=MATCH(callable),
208- error_handler=MATCH(callable))
209- self.mocker.replay()
210- return self.management_tool.store_credentials(token)
211-
212- def test_register(self):
213- """Test that we correctly register."""
214- window_id = 10
215- window_id_dict = dict(window_id=str(window_id))
216- signals = ['creds_found', 'creds_denied', 'creds_error']
217- self.get_cred_proxy()
218- self.mocker.result(self.proxy)
219- self.proxy.register_to_credentials_found(MATCH(callable))
220- self.mocker.result(signals[0])
221- self.proxy.register_to_authorization_denied(MATCH(callable))
222- self.mocker.result(signals[1])
223- self.proxy.register_to_credentials_error(MATCH(callable))
224- self.mocker.result(signals[2])
225- self.proxy.register(window_id_dict, reply_handler=MATCH(callable),
226- error_handler=MATCH(callable))
227- self.mocker.replay()
228- return self.management_tool.register(window_id=window_id)
229-
230- def test_login_email_password(self):
231- """Test that we login correctly."""
232- email = 'email'
233- password = 'password'
234- arg_dict = dict(email=email, password=password)
235- signals = ['creds_found', 'creds_denied', 'creds_error']
236- self.get_cred_proxy()
237- self.mocker.result(self.proxy)
238- self.proxy.register_to_credentials_found(MATCH(callable))
239- self.mocker.result(signals[0])
240- self.proxy.register_to_credentials_error(MATCH(callable))
241- self.mocker.result(signals[1])
242- self.proxy.login_email_password(arg_dict, reply_handler=MATCH(callable),
243- error_handler=MATCH(callable))
244- self.mocker.replay()
245- return self.management_tool.login_email_password(email=email,
246- password=password)
247-
248- def test_cleanup_but_no_remove(self):
249- """The cleanup method works on handlers that have no remove method."""
250- self.management_tool._cleanup_signals = ["test signal 1", "test sig 2"]
251- self.management_tool.cleanup(None)
252-
253-
254-class TestDeferredCredentialsManagementTool(TestCredentialsManagementTool):
255- """Test the credentials management tool mocking the proxy in a deferred."""
256-
257- def setUp(self):
258- """Set the diff tests."""
259- super(TestDeferredCredentialsManagementTool, self).setUp()
260- real_get_cred_proxy = self.mocker.mock()
261- self.get_cred_proxy = lambda: defer.succeed(real_get_cred_proxy())
262- self.management_tool = CredentialsManagementTool()
263- self.management_tool.get_creds_proxy = self.get_cred_proxy
264+from contrib.testing.testcase import FAKED_CREDENTIALS
265+
266+
267+class FakedSignal(object):
268+ """A faked signal."""
269+
270+ def __init__(self, name, callback):
271+ self.name = name
272+ self.callback = callback
273+ self.removed = False
274+ self.remove = lambda: setattr(self, 'removed', True)
275+
276+
277+class FakedProxy(object):
278+ """Fake a CredentialsManagement proxy."""
279+
280+ error_dict = None
281+ error_handler = None
282+
283+ def __init__(self, *args, **kwargs):
284+ self._credentials = None
285+ self._args = None
286+ self._kwargs = None
287+ self._signals = []
288+ self._receivers = defaultdict(list)
289+ self._called = defaultdict(list)
290+
291+ def connect_to_signal(self, signal_name, callback):
292+ """Keep track of connected signals."""
293+ self._receivers[signal_name].append(callback)
294+ result = FakedSignal(signal_name, callback)
295+ self._signals.append(result)
296+ return result
297+
298+ def maybe_emit_error(f):
299+ """Decorator to fake a CredentialsError signal."""
300+
301+ @wraps(f)
302+ def inner(self, *args, **kwargs):
303+ """Fake a CredentialsError signal."""
304+ if self.error_dict is None and self.error_handler is None:
305+ f(self, *args, **kwargs)
306+
307+ reply_handler = kwargs.pop('reply_handler', NO_OP)
308+ error_handler = kwargs.pop('error_handler', NO_OP)
309+ if self.error_handler is not None:
310+ error_handler(self.error_handler)
311+ else:
312+ reply_handler()
313+
314+ if self.error_dict is not None:
315+ self.CredentialsError(self.error_dict)
316+
317+ return inner
318+
319+ def record_call(f):
320+ """Decorator to record calls to 'f'."""
321+
322+ @wraps(f)
323+ def inner(self, *a, **kw):
324+ """Record the call to 'f' and call it."""
325+ self._called[f.__name__].append((a, kw))
326+ return f(self, *a, **kw)
327+
328+ return inner
329+
330+ def emit_signal(f):
331+ """Decorator to emit a signal."""
332+
333+ @wraps(f)
334+ def inner(self, *args, **kwargs):
335+ """Emit the signal."""
336+ for cb in self._receivers[f.__name__]:
337+ cb(*args, **kwargs)
338+
339+ return inner
340+
341+ @emit_signal
342+ def AuthorizationDenied(self):
343+ """Signal thrown when the user denies the authorization."""
344+
345+ @emit_signal
346+ def CredentialsFound(self, credentials):
347+ """Signal thrown when the credentials are found."""
348+
349+ @emit_signal
350+ def CredentialsNotFound(self):
351+ """Signal thrown when the credentials are not found."""
352+
353+ @emit_signal
354+ def CredentialsCleared(self):
355+ """Signal thrown when the credentials were cleared."""
356+
357+ @emit_signal
358+ def CredentialsStored(self):
359+ """Signal thrown when the credentials were stored."""
360+
361+ @emit_signal
362+ def CredentialsError(self, error_dict):
363+ """Signal thrown when there is a problem getting the credentials."""
364+
365+ @record_call
366+ @maybe_emit_error
367+ def find_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
368+ """Look for the credentials for an application."""
369+ if self._credentials is not None:
370+ self.CredentialsFound(self._credentials)
371+ else:
372+ self.CredentialsNotFound()
373+
374+ @record_call
375+ @maybe_emit_error
376+ def clear_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
377+ """Clear the credentials for an application."""
378+ self._credentials = None
379+ self.CredentialsCleared()
380+
381+ @record_call
382+ @maybe_emit_error
383+ def store_credentials(self, credentials,
384+ reply_handler=NO_OP, error_handler=NO_OP):
385+ """Store the token for an application."""
386+ self._credentials = credentials
387+ self.CredentialsStored()
388+
389+ @record_call
390+ @maybe_emit_error
391+ def register(self, dict_arg,
392+ reply_handler=NO_OP, error_handler=NO_OP):
393+ """Get credentials if found else prompt GUI to register."""
394+ creds = self._credentials
395+ if creds is not None and len(creds) > 0:
396+ self.CredentialsFound(creds)
397+ elif creds == {}:
398+ # fake an AuthorizationDenied
399+ self.AuthorizationDenied()
400+ elif creds is None:
401+ # fake the adding of the credentials
402+ self._credentials = FAKED_CREDENTIALS
403+ self.CredentialsFound(FAKED_CREDENTIALS)
404+
405+ @record_call
406+ @maybe_emit_error
407+ def login(self, dict_arg,
408+ reply_handler=NO_OP, error_handler=NO_OP):
409+ """Get credentials if found else prompt GUI to login."""
410+ self.register(dict_arg, reply_handler, error_handler)
411+
412+ @record_call
413+ @maybe_emit_error
414+ def login_email_password(self, dict_arg,
415+ reply_handler=NO_OP, error_handler=NO_OP):
416+ """Fake login_email_password."""
417+ self.register(dict_arg, reply_handler, error_handler)
418+
419+
420+class FakedPlatformSource(object):
421+ """Faked the platform source."""
422+
423+ def get_creds_proxy(self):
424+ """Return a new faked proxy every time, so we can test proxy caching."""
425+ return FakedProxy()
426+
427+
428+class CredentialsManagementToolTestCase(TestCase):
429+ """Test case for the object that manages Ubuntu One credentials."""
430+
431+ timeout = 3
432+ error_dict = None
433+ error_handler = None
434+
435+ @defer.inlineCallbacks
436+ def setUp(self):
437+ yield super(CredentialsManagementToolTestCase, self).setUp()
438+ self.cred_tool = CredentialsManagementTool()
439+ self.patch(self.cred_tool, 'get_platform_source', FakedPlatformSource)
440+ self.proxy = yield self.cred_tool.get_creds_proxy()
441+ self.proxy.error_dict = self.error_dict
442+ self.proxy.error_handler = self.error_handler
443+
444+ self.window_id_arg = {'window_id': '803'}
445+ self.email_password_arg = {'email': 'foo@bar.com', 'password': 'yadda'}
446+
447+ @defer.inlineCallbacks
448+ def test_proxy_is_reused(self):
449+ """The inner proxy is re-used."""
450+ proxy1 = yield self.cred_tool.get_creds_proxy()
451+ proxy2 = yield self.cred_tool.get_creds_proxy()
452+ self.assertIs(proxy1, proxy2)
453+
454+
455+class ArgsTestCase(CredentialsManagementToolTestCase):
456+ """Test case to check that proper arguments are passed to SSO backend."""
457+
458+ @defer.inlineCallbacks
459+ def assert_method_called(self, method_name, *args, **kwargs):
460+ """Test that 'method_name' was called once with 'args' and 'kwargs."""
461+ self.assertIn(method_name, self.proxy._called)
462+
463+ calls = self.proxy._called[method_name]
464+ msg = '%s must be called only once (got %s instead).'
465+ self.assertEqual(len(calls), 1, msg % (method_name, len(calls)))
466+
467+ actual_args, actual_kwargs = calls[0]
468+ self.assertEqual(args, actual_args)
469+
470+ reply_handler = actual_kwargs.pop('reply_handler', None)
471+ self.assertIsNotNone(reply_handler, 'Must provide a reply_handler')
472+ d = defer.Deferred()
473+ reply_handler(deferred=d)
474+ yield d
475+ self.assertTrue(d.called)
476+
477+ error_handler = actual_kwargs.pop('error_handler', None)
478+ self.assertIsNotNone(error_handler, 'Must provide a error_handler')
479+ d = defer.Deferred()
480+ error_handler(error='foo', deferred=d)
481+ e = yield self.assertFailure(d, CredentialsError)
482+ self.assertEqual(e.message, 'foo')
483+
484+ self.assertEqual(kwargs, actual_kwargs)
485+
486+ @defer.inlineCallbacks
487+ def test_find_credentials(self):
488+ """The find_credentials method calls proper method."""
489+ yield self.cred_tool.find_credentials()
490+
491+ self.assert_method_called('find_credentials')
492+
493+ @defer.inlineCallbacks
494+ def test_clear_credentials(self):
495+ """The clear_credentials method calls proper method."""
496+ yield self.cred_tool.clear_credentials()
497+
498+ self.assert_method_called('clear_credentials')
499+
500+ @defer.inlineCallbacks
501+ def test_store_credentials(self):
502+ """The store_credentials method calls proper method."""
503+ yield self.cred_tool.store_credentials(FAKED_CREDENTIALS)
504+
505+ self.assert_method_called('store_credentials', FAKED_CREDENTIALS)
506+
507+ @defer.inlineCallbacks
508+ def test_register(self):
509+ """The register method calls proper method."""
510+ yield self.cred_tool.register(**self.window_id_arg)
511+
512+ self.assert_method_called('register', self.window_id_arg)
513+
514+ @defer.inlineCallbacks
515+ def test_login(self):
516+ """The login method calls proper method."""
517+ yield self.cred_tool.login(**self.window_id_arg)
518+
519+ self.assert_method_called('login', self.window_id_arg)
520+
521+ @defer.inlineCallbacks
522+ def test_login_email_password(self):
523+ """The login method calls proper method."""
524+ yield self.cred_tool.login_email_password(**self.email_password_arg)
525+
526+ self.assert_method_called('login_email_password',
527+ self.email_password_arg)
528+
529+
530+class NoErrorWithCredsTestCase(CredentialsManagementToolTestCase):
531+ """Test case when there was no error, and credentials are present."""
532+
533+ token = {'test': 'me'}
534+
535+ @defer.inlineCallbacks
536+ def do_test(self, method, expected=None, **kwargs):
537+ """Perform the test itself."""
538+ if self.token is not None:
539+ self.proxy.store_credentials(self.token)
540+ else:
541+ yield self.proxy.clear_credentials()
542+ actual = yield method(**kwargs)
543+ self.assertEqual(expected, actual)
544+
545+ @defer.inlineCallbacks
546+ def test_find_credentials(self):
547+ """The find_credentials method calls proper method."""
548+ yield self.do_test(self.cred_tool.find_credentials, self.token)
549+
550+ @defer.inlineCallbacks
551+ def test_clear_credentials(self):
552+ """The clear_credentials method calls proper method."""
553+ yield self.do_test(self.cred_tool.clear_credentials, None)
554+
555+ @defer.inlineCallbacks
556+ def test_store_credentials(self):
557+ """The store_credentials method calls proper method."""
558+ yield self.do_test(self.cred_tool.store_credentials, None,
559+ token=FAKED_CREDENTIALS)
560+
561+ @defer.inlineCallbacks
562+ def test_register(self):
563+ """The register method calls proper method."""
564+ yield self.do_test(self.cred_tool.register, self.token,
565+ **self.window_id_arg)
566+
567+ @defer.inlineCallbacks
568+ def test_login(self):
569+ """The login method calls proper method."""
570+ yield self.do_test(self.cred_tool.login, self.token,
571+ **self.window_id_arg)
572+
573+ @defer.inlineCallbacks
574+ def test_login_email_password(self):
575+ """The login_email_password method calls proper method."""
576+ yield self.do_test(self.cred_tool.login_email_password, self.token,
577+ **self.email_password_arg)
578+
579+
580+class NoErrorNoCredsTestCase(NoErrorWithCredsTestCase):
581+ """Test case when there was no error, and credentials are not present."""
582+
583+ token = None
584+
585+ @defer.inlineCallbacks
586+ def test_find_credentials(self):
587+ """The find_credentials method calls proper method."""
588+ yield self.do_test(self.cred_tool.find_credentials, {})
589+
590+ @defer.inlineCallbacks
591+ def test_register(self):
592+ """The register method calls proper method."""
593+ yield self.do_test(self.cred_tool.register, FAKED_CREDENTIALS,
594+ **self.window_id_arg)
595+
596+ @defer.inlineCallbacks
597+ def test_register_authorization_denied(self):
598+ """The register method calls proper method."""
599+ self.token = {}
600+ yield self.do_test(self.cred_tool.register, None,
601+ **self.window_id_arg)
602+
603+ @defer.inlineCallbacks
604+ def test_login(self):
605+ """The login method calls proper method."""
606+ yield self.do_test(self.cred_tool.login, FAKED_CREDENTIALS,
607+ **self.window_id_arg)
608+
609+ @defer.inlineCallbacks
610+ def test_login_authorization_denied(self):
611+ """The login method calls proper method."""
612+ self.token = {}
613+ yield self.do_test(self.cred_tool.login, None, **self.window_id_arg)
614+
615+ @defer.inlineCallbacks
616+ def test_login_email_password(self):
617+ """The login_email_password method calls proper method."""
618+ yield self.do_test(self.cred_tool.login_email_password,
619+ FAKED_CREDENTIALS, **self.email_password_arg)
620+
621+
622+class WithCredentialsErrorTestCase(NoErrorNoCredsTestCase):
623+ """Test case when there was a CredentialsError sent from the proxy."""
624+
625+ error_dict = expected = {'error_type': 'Test'}
626+
627+ @defer.inlineCallbacks
628+ def do_test(self, method, expected=None, **kwargs):
629+ """Perform the test itself."""
630+ exc = yield self.assertFailure(method(**kwargs), Exception)
631+ self.assertIsInstance(exc, CredentialsError)
632+ self.assertEqual(self.expected, exc.args[0])
633+
634+
635+class WithErrorHandlerCalledTestCase(WithCredentialsErrorTestCase):
636+ """Test case when the error handler was called."""
637+
638+ error_dict = None
639+ error_handler = expected = {'error_type': 'Another Test'}
640+
641+
642+class SignalsRemovedTestCase(NoErrorWithCredsTestCase):
643+
644+ @defer.inlineCallbacks
645+ def do_test(self, method, expected=None, **kwargs):
646+ """Perform the test itself."""
647+ yield method(**kwargs)
648+ for signal in self.proxy._signals:
649+ self.assertTrue(signal.removed)
650
651
652 class PingURLPlatformDetails(TestCase):
653
654=== modified file 'tests/platform/windows/test_credentials.py'
655--- tests/platform/windows/test_credentials.py 2011-08-16 15:43:52 +0000
656+++ tests/platform/windows/test_credentials.py 2011-08-26 17:23:37 +0000
657@@ -20,6 +20,8 @@
658 from twisted.internet import defer
659 from twisted.trial.unittest import TestCase
660
661+from contrib.testing.testcase import FAKED_CREDENTIALS
662+from ubuntuone.platform.credentials import APP_NAME
663 from ubuntuone.platform.credentials.windows import (
664 CredentialsManagement,
665 RemovableSignal,
666@@ -27,9 +29,7 @@
667
668 TEST_APP_NAME = "test application"
669 TEST_ERROR_DICT = {}
670-TEST_CREDENTIALS = {
671- "token": "1234token",
672-}
673+TEST_CREDENTIALS = FAKED_CREDENTIALS
674
675
676 class FakeSSOProxy(object):
677@@ -77,11 +77,15 @@
678 return defer.succeed(None)
679
680 def register(self, app_name, options):
681- """Store the U1 credentials."""
682+ """Register."""
683 return defer.succeed(None)
684
685 def login(self, app_name, options):
686- """Store the U1 credentials."""
687+ """Login."""
688+ return defer.succeed(None)
689+
690+ def login_email_password(self, app_name, options):
691+ """Login using email and password."""
692 return defer.succeed(None)
693
694
695@@ -92,13 +96,27 @@
696 """Initialize this fake instance."""
697 self.proxy = FakeSSOProxy()
698
699+ def test_creation(self):
700+ """When creating, bind properly to self.proxy."""
701+ rs = RemovableSignal(self.proxy, "test", lambda *a: None)
702+ self.assertIs(self.proxy.test, rs)
703+
704 def test_dunder_callable(self):
705 """__call__ works as expected."""
706 sample_store = []
707- test_cb = lambda app_name, creds: sample_store.append(creds)
708- rs = RemovableSignal(self.proxy, "on_credentials_found_cb", test_cb)
709- rs(TEST_APP_NAME, TEST_CREDENTIALS)
710- self.assertEqual(sample_store[0], TEST_CREDENTIALS)
711+ expected = object()
712+ test_cb = lambda res: sample_store.append(res)
713+ rs = RemovableSignal(self.proxy, "on_credentials_found_cb", test_cb)
714+ rs(APP_NAME, expected)
715+ self.assertEqual(sample_store, [expected])
716+
717+ def test_dunder_filters_other_apps(self):
718+ """__call__ filters by app_name."""
719+ sample_store = []
720+ test_cb = lambda res: sample_store.append(res)
721+ rs = RemovableSignal(self.proxy, "on_credentials_found_cb", test_cb)
722+ rs('other app name', object())
723+ self.assertEqual(sample_store, [])
724
725 def test_remove(self):
726 """The signal has a .remove that removes the callback."""
727@@ -114,12 +132,22 @@
728 """Tests for CredentialsManagement."""
729
730 timeout = 5
731+ app_name = APP_NAME
732
733 def setUp(self):
734 """Initialize these tests."""
735+ self._called = False
736 self.proxy = FakeSSOProxy()
737 self.cm = CredentialsManagement(self.proxy)
738
739+ def _set_called(self, *args, **kwargs):
740+ """Helper to keep track calls."""
741+ self._called = (args, kwargs)
742+
743+ def assert_callback_called(self, expected):
744+ """Test that _called helper holds 'expected'."""
745+ self.assertEqual(self._called, expected)
746+
747 def test_find_credentials(self):
748 """Test the find_credentials method."""
749 d = defer.Deferred()
750@@ -161,17 +189,50 @@
751 self.cm.login({}, reply_handler=ok, error_handler=error)
752 return d
753
754+ def test_login_email_password(self):
755+ """Test the login_email_password method."""
756+ d = defer.Deferred()
757+ ok = lambda: d.callback("ok")
758+ error = lambda *args: d.errback(args)
759+ self.cm.login_email_password({'email': 'foo', 'password': 'bar'},
760+ reply_handler=ok, error_handler=error)
761+ return d
762+
763 def test_register_to_credentials_found(self):
764 """Test the register_to_credentials_found method."""
765- cb = lambda creds: self.assertEqual(creds, TEST_CREDENTIALS)
766- other_cb = self.cm.register_to_credentials_found(cb)
767- other_cb(TEST_APP_NAME, TEST_CREDENTIALS)
768+ signal = self.cm.register_to_credentials_found(self._set_called)
769+ signal(self.app_name, TEST_CREDENTIALS)
770+ self.assert_callback_called(((TEST_CREDENTIALS,), {}))
771
772 def test_register_to_credentials_not_found(self):
773 """Test the register_to_credentials_not_found method."""
774- cb = lambda: None
775- other_cb = self.cm.register_to_credentials_not_found(cb)
776- other_cb(TEST_APP_NAME)
777+ signal = self.cm.register_to_credentials_not_found(self._set_called)
778+ signal(self.app_name)
779+ self.assert_callback_called(((), {}))
780+
781+ def test_register_to_credentials_stored(self):
782+ """Test the register_to_credentials_stored method."""
783+ signal = self.cm.register_to_credentials_stored(self._set_called)
784+ signal(self.app_name)
785+ self.assert_callback_called(((), {}))
786+
787+ def test_register_to_credentials_cleared(self):
788+ """Test the register_to_credentials_cleared method."""
789+ signal = self.cm.register_to_credentials_cleared(self._set_called)
790+ signal(self.app_name)
791+ self.assert_callback_called(((), {}))
792+
793+ def test_register_to_credentials_error(self):
794+ """Test the register_to_credentials_error method."""
795+ signal = self.cm.register_to_credentials_error(self._set_called)
796+ signal(self.app_name)
797+ self.assert_callback_called(((), {}))
798+
799+ def test_register_to_authorization_denied(self):
800+ """Test the register_to_authorization_denied method."""
801+ signal = self.cm.register_to_authorization_denied(self._set_called)
802+ signal(self.app_name, TEST_ERROR_DICT)
803+ self.assert_callback_called(((TEST_ERROR_DICT,), {}))
804
805 def _verify_not_called_twice(self, signal_name, *args):
806 """Test that the callback is not called twice."""
807@@ -199,7 +260,7 @@
808
809 def test_not_called_twice_credentials_found(self):
810 """Test that on_credentials_found is not called twice."""
811- self._verify_not_called_twice("credentials_found", TEST_APP_NAME,
812+ self._verify_not_called_twice("credentials_found", self.app_name,
813 TEST_CREDENTIALS)
814
815 def test_not_called_twice_credentials_not_found(self):
816@@ -213,3 +274,21 @@
817 def test_not_called_twice_credentials_error(self):
818 """Test that on_credentials_error is not called twice."""
819 self._verify_not_called_twice("credentials_error", TEST_ERROR_DICT)
820+
821+ def test_connect_to_signal(self):
822+ """The connect_to_signal method is correct."""
823+ for signal_name in self.cm._SIGNAL_TO_CALLBACK_MAPPING:
824+ match = self.cm.connect_to_signal(signal_name, self._set_called)
825+ expected = object()
826+ match(APP_NAME, expected)
827+ self.assertEqual(self._called, ((expected,), {}))
828+
829+
830+class CredentialsManagementOtherAppNameTestCase(CredentialsManagementTestCase):
831+ """Tests for CredentialsManagement when the app name differs."""
832+
833+ app_name = 'other app name'
834+
835+ def assert_callback_called(self, expected):
836+ """Test that _called helper does not hold 'expected'."""
837+ self.assertEqual(self._called, False)
838
839=== modified file 'ubuntuone/platform/credentials/__init__.py'
840--- ubuntuone/platform/credentials/__init__.py 2011-08-18 15:30:53 +0000
841+++ ubuntuone/platform/credentials/__init__.py 2011-08-26 17:23:37 +0000
842@@ -25,6 +25,8 @@
843 import urllib
844 import sys
845
846+from functools import partial
847+
848 from twisted.internet import defer
849
850 from ubuntuone import clientdefs
851@@ -83,6 +85,15 @@
852
853 def __init__(self):
854 self._cleanup_signals = []
855+ self._proxy = None
856+
857+ def callback(self, result, deferred):
858+ """Fire 'deferred' with success, sending 'result' as result."""
859+ deferred.callback(result)
860+
861+ def errback(self, error, deferred):
862+ """Fire 'deferred' with error sending a CredentialsError."""
863+ deferred.errback(CredentialsError(error))
864
865 def cleanup(self, _):
866 """Disconnect all the DBus signals."""
867@@ -93,16 +104,23 @@
868
869 return _
870
871- def get_creds_proxy(self):
872- """Call the get_proxy_fn, and perhaps wrap the result in a defer."""
873+ def get_platform_source(self):
874+ """Platform-specific source."""
875 if sys.platform == 'win32':
876 from ubuntuone.platform.credentials import windows
877 source = windows
878 else:
879 from ubuntuone.platform.credentials import linux
880 source = linux
881- result = defer.maybeDeferred(source.get_creds_proxy)
882- return result
883+ return source
884+
885+ @defer.inlineCallbacks
886+ def get_creds_proxy(self):
887+ """Call the platform-dependent get_creds_proxy caching the result."""
888+ if self._proxy is None:
889+ source = self.get_platform_source()
890+ self._proxy = yield source.get_creds_proxy()
891+ defer.returnValue(self._proxy)
892
893 @log_call(logger.debug)
894 @defer.inlineCallbacks
895@@ -128,19 +146,21 @@
896
897 proxy = yield self.get_creds_proxy()
898
899- sig = proxy.register_to_credentials_found(d.callback)
900- self._cleanup_signals.append(sig)
901-
902- sig = proxy.register_to_credentials_not_found(lambda: d.callback({}))
903- self._cleanup_signals.append(sig)
904-
905- sig = proxy.register_to_credentials_error(
906- lambda error_dict: d.errback(CredentialsError(error_dict)))
907+ sig = proxy.connect_to_signal('CredentialsFound', d.callback)
908+ self._cleanup_signals.append(sig)
909+
910+ sig = proxy.connect_to_signal('CredentialsNotFound',
911+ partial(self.callback, result={}, deferred=d))
912+ self._cleanup_signals.append(sig)
913+
914+ sig = proxy.connect_to_signal('CredentialsError',
915+ partial(self.errback, deferred=d))
916 self._cleanup_signals.append(sig)
917
918 done = defer.Deferred()
919- proxy.find_credentials(reply_handler=lambda: done.callback(None),
920- error_handler=lambda *a: done.errback(a))
921+ proxy.find_credentials(
922+ reply_handler=partial(self.callback, result=None, deferred=done),
923+ error_handler=partial(self.errback, deferred=done))
924
925 yield done
926
927@@ -161,16 +181,19 @@
928 d.addBoth(self.cleanup)
929
930 proxy = yield self.get_creds_proxy()
931- sig = proxy.register_to_credentials_cleared(lambda: d.callback(None))
932+
933+ sig = proxy.connect_to_signal('CredentialsCleared',
934+ partial(self.callback, result=None, deferred=d))
935 self._cleanup_signals.append(sig)
936
937- sig = proxy.register_to_credentials_error(
938- lambda error_dict: d.errback(CredentialsError(error_dict)))
939+ sig = proxy.connect_to_signal('CredentialsError',
940+ partial(self.errback, deferred=d))
941 self._cleanup_signals.append(sig)
942
943 done = defer.Deferred()
944- proxy.clear_credentials(reply_handler=lambda: done.callback(None),
945- error_handler=lambda *a: done.errback(a))
946+ proxy.clear_credentials(
947+ reply_handler=partial(self.callback, result=None, deferred=done),
948+ error_handler=partial(self.errback, deferred=done))
949
950 yield done
951
952@@ -193,17 +216,19 @@
953 d.addBoth(self.cleanup)
954
955 proxy = yield self.get_creds_proxy()
956- sig = proxy.register_to_credentials_stored(lambda: d.callback(None))
957+
958+ sig = proxy.connect_to_signal('CredentialsStored',
959+ partial(self.callback, result=None, deferred=d))
960 self._cleanup_signals.append(sig)
961
962- sig = proxy.register_to_credentials_error(
963- lambda error_dict: d.errback(CredentialsError(error_dict)))
964+ sig = proxy.connect_to_signal('CredentialsError',
965+ partial(self.errback, deferred=d))
966 self._cleanup_signals.append(sig)
967
968 done = defer.Deferred()
969 proxy.store_credentials(token,
970- reply_handler=lambda: done.callback(None),
971- error_handler=lambda *a: done.errback(a))
972+ reply_handler=partial(self.callback, result=None, deferred=done),
973+ error_handler=partial(self.errback, deferred=done))
974
975 yield done
976
977@@ -235,20 +260,21 @@
978
979 proxy = yield self.get_creds_proxy()
980
981- sig = proxy.register_to_credentials_found(d.callback)
982- self._cleanup_signals.append(sig)
983-
984- sig = proxy.register_to_authorization_denied(lambda: d.callback(None))
985- self._cleanup_signals.append(sig)
986-
987- sig = proxy.register_to_credentials_error(
988- lambda error_dict: d.errback(CredentialsError(error_dict)))
989+ sig = proxy.connect_to_signal('CredentialsFound', d.callback)
990+ self._cleanup_signals.append(sig)
991+
992+ sig = proxy.connect_to_signal('AuthorizationDenied',
993+ partial(self.callback, result=None, deferred=d))
994+ self._cleanup_signals.append(sig)
995+
996+ sig = proxy.connect_to_signal('CredentialsError',
997+ partial(self.errback, deferred=d))
998 self._cleanup_signals.append(sig)
999
1000 done = defer.Deferred()
1001 proxy.register({'window_id': str(window_id)},
1002- reply_handler=lambda: done.callback(None),
1003- error_handler=lambda *a: done.errback(a))
1004+ reply_handler=partial(self.callback, result=None, deferred=done),
1005+ error_handler=partial(self.errback, deferred=done))
1006
1007 yield done
1008
1009@@ -282,20 +308,21 @@
1010
1011 proxy = yield self.get_creds_proxy()
1012
1013- sig = proxy.register_to_credentials_found(d.callback)
1014- self._cleanup_signals.append(sig)
1015-
1016- sig = proxy.register_to_authorization_denied(lambda: d.callback(None))
1017- self._cleanup_signals.append(sig)
1018-
1019- sig = proxy.register_to_credentials_error(
1020- lambda error_dict: d.errback(CredentialsError(error_dict)))
1021+ sig = proxy.connect_to_signal('CredentialsFound', d.callback)
1022+ self._cleanup_signals.append(sig)
1023+
1024+ sig = proxy.connect_to_signal('AuthorizationDenied',
1025+ partial(self.callback, result=None, deferred=d))
1026+ self._cleanup_signals.append(sig)
1027+
1028+ sig = proxy.connect_to_signal('CredentialsError',
1029+ partial(self.errback, deferred=d))
1030 self._cleanup_signals.append(sig)
1031
1032 done = defer.Deferred()
1033 proxy.login({'window_id': str(window_id)},
1034- reply_handler=lambda: done.callback(None),
1035- error_handler=lambda *a: done.errback(a))
1036+ reply_handler=partial(self.callback, result=None, deferred=done),
1037+ error_handler=partial(self.errback, deferred=done))
1038
1039 yield done
1040
1041@@ -320,17 +347,17 @@
1042
1043 proxy = yield self.get_creds_proxy()
1044
1045- sig = proxy.register_to_credentials_found(d.callback)
1046+ sig = proxy.connect_to_signal('CredentialsFound', d.callback)
1047 self._cleanup_signals.append(sig)
1048
1049- sig = proxy.register_to_credentials_error(
1050- lambda x, error_dict: d.errback(CredentialsError(error_dict)))
1051+ sig = proxy.connect_to_signal('CredentialsError',
1052+ partial(self.errback, deferred=d))
1053 self._cleanup_signals.append(sig)
1054
1055 done = defer.Deferred()
1056 proxy.login_email_password({'email': email, 'password': password},
1057- reply_handler=lambda: done.callback(None),
1058- error_handler=lambda *a: done.errback(a))
1059+ reply_handler=partial(self.callback, result=None, deferred=done),
1060+ error_handler=partial(self.errback, deferred=done))
1061
1062 yield done
1063
1064
1065=== modified file 'ubuntuone/platform/credentials/linux.py'
1066--- ubuntuone/platform/credentials/linux.py 2011-08-16 13:44:20 +0000
1067+++ ubuntuone/platform/credentials/linux.py 2011-08-26 17:23:37 +0000
1068@@ -233,75 +233,16 @@
1069 reply_handler=reply_handler, error_handler=error_handler)
1070
1071
1072-class CredentialsManagementProxy(object):
1073- """Proxy that allows to work with the dbus api.
1074-
1075- This proxy has been added to hide the exact details of
1076- how the signals are connected. This allows the reuse of
1077- the CredentialsManagementTool in diff platforms.
1078- """
1079-
1080- def __init__(self):
1081- """Create a new instance."""
1082- bus = dbus.SessionBus()
1083- try:
1084- obj = bus.get_object(DBUS_BUS_NAME,
1085- DBUS_CREDENTIALS_PATH,
1086- follow_name_owner_changes=True)
1087- self.proxy = dbus.Interface(obj, DBUS_CREDENTIALS_IFACE)
1088- except:
1089- logger.exception('get_creds_proxy:')
1090- raise
1091-
1092- def find_credentials(self, *args, **kwargs):
1093- """Relay the find_credentials method."""
1094- return self.proxy.find_credentials(*args, **kwargs)
1095-
1096- def clear_credentials(self, *args, **kwargs):
1097- """Relay the clear_credentials method."""
1098- return self.proxy.clear_credentials(*args, **kwargs)
1099-
1100- def store_credentials(self, *args, **kwargs):
1101- """Relay the store_credentials method."""
1102- return self.proxy.store_credentials(*args, **kwargs)
1103-
1104- def register(self, *args, **kwargs):
1105- """Relay the register method."""
1106- return self.proxy.register(*args, **kwargs)
1107-
1108- def login(self, *args, **kwargs):
1109- """Relay the login method."""
1110- return self.proxy.login(*args, **kwargs)
1111-
1112- def login_email_password(self, *args, **kwargs):
1113- """Relay the login method."""
1114- return self.proxy.login_email_password(*args, **kwargs)
1115-
1116- def register_to_credentials_stored(self, callback):
1117- """Register to the CredentialsStored dbus signal."""
1118- return self.proxy.connect_to_signal('CredentialsStored', callback)
1119-
1120- def register_to_credentials_cleared(self, callback):
1121- """Register to the CredentialsCleared dbus signal."""
1122- return self.proxy.connect_to_signal('CredentialsCleared', callback)
1123-
1124- def register_to_credentials_found(self, callback):
1125- """Register to the CredentialsFound dbus signal."""
1126- return self.proxy.connect_to_signal('CredentialsFound', callback)
1127-
1128- def register_to_credentials_not_found(self, callback):
1129- """Register to the CredentialsFound dbus signal."""
1130- return self.proxy.connect_to_signal('CredentialsNotFound', callback)
1131-
1132- def register_to_authorization_denied(self, callback):
1133- """Register to the AuthorizationDenied dbus signal."""
1134- return self.proxy.connect_to_signal('AuthorizationDenied', callback)
1135-
1136- def register_to_credentials_error(self, callback):
1137- """Register to the CredentialsError dbus signal."""
1138- return self.proxy.connect_to_signal('CredentialsError', callback)
1139-
1140-
1141 def get_creds_proxy():
1142 """Get the CredentialsManagement proxy."""
1143- return CredentialsManagementProxy()
1144+ bus = dbus.SessionBus()
1145+ try:
1146+ obj = bus.get_object(DBUS_BUS_NAME,
1147+ DBUS_CREDENTIALS_PATH,
1148+ follow_name_owner_changes=True)
1149+ proxy = dbus.Interface(obj, DBUS_CREDENTIALS_IFACE)
1150+ except:
1151+ logger.exception('get_creds_proxy:')
1152+ raise
1153+
1154+ return proxy
1155
1156=== modified file 'ubuntuone/platform/credentials/windows.py'
1157--- ubuntuone/platform/credentials/windows.py 2011-08-16 13:44:20 +0000
1158+++ ubuntuone/platform/credentials/windows.py 2011-08-26 17:23:37 +0000
1159@@ -30,6 +30,7 @@
1160 from ubuntuone.platform.credentials import (
1161 APP_NAME,
1162 DESCRIPTION,
1163+ logger,
1164 NO_OP,
1165 PING_URL,
1166 TC_URL,
1167@@ -44,13 +45,26 @@
1168 self.proxy = proxy
1169 self.signal_name = signal_name
1170 self.callback = callback
1171- setattr(self.proxy, signal_name, callback)
1172+ setattr(self.proxy, signal_name, self)
1173
1174 def __call__(self, *args, **kwargs):
1175 """Call this instance."""
1176- func = getattr(self.proxy, self.signal_name, None)
1177- if func is not None:
1178- return func(*args, **kwargs)
1179+ app_name = args[0] if len(args) > 0 else None
1180+ logger.debug('Handling signal_name: %r, app_name: %r.',
1181+ self.signal_name, app_name)
1182+
1183+ if app_name != APP_NAME:
1184+ # This fixed bug #818190: filter signals not related to APP_NAME
1185+ logger.info('Received %r but app_name %r does not match %r, ' \
1186+ 'exiting.', self.signal_name, app_name, APP_NAME)
1187+ return
1188+
1189+ if self.callback is not None:
1190+ # drop the app name, callers do not care about it
1191+ args = args[1:]
1192+ logger.debug('Calling %r with args %r and kwargs %r.',
1193+ self.callback, args, kwargs)
1194+ return self.callback(*args, **kwargs)
1195
1196 def remove(self):
1197 """Remove this signal."""
1198@@ -61,10 +75,25 @@
1199 class CredentialsManagement(object):
1200 """Object that manages Ubuntu One credentials."""
1201
1202+ _SIGNAL_TO_CALLBACK_MAPPING = {
1203+ 'AuthorizationDenied': 'on_authorization_denied_cb',
1204+ 'CredentialsCleared': 'on_credentials_cleared_cb',
1205+ 'CredentialsError': 'on_credentials_error_cb',
1206+ 'CredentialsFound': 'on_credentials_found_cb',
1207+ 'CredentialsNotFound': 'on_credentials_not_found_cb',
1208+ 'CredentialsStored': 'on_credentials_stored_cb',
1209+ }
1210+
1211 def __init__(self, proxy, *args, **kwargs):
1212 super(CredentialsManagement, self).__init__(*args, **kwargs)
1213 self.sso_proxy = proxy
1214
1215+ def connect_to_signal(self, signal_name, callback):
1216+ """Register 'callback' to be called when 'signal_name' is emitted."""
1217+ cb_name = self._SIGNAL_TO_CALLBACK_MAPPING[signal_name]
1218+ match = RemovableSignal(self.sso_proxy, cb_name, callback)
1219+ return match
1220+
1221 def find_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
1222 """Ask the Ubuntu One credentials."""
1223 d = self.sso_proxy.find_credentials(APP_NAME, {})
1224@@ -97,7 +126,8 @@
1225 d = self.sso_proxy.login(APP_NAME, params)
1226 d.addCallbacks(lambda _: reply_handler(), error_handler)
1227
1228- def login_email_password(self, args, reply_handler=NO_OP, error_handler=NO_OP):
1229+ def login_email_password(self, args,
1230+ reply_handler=NO_OP, error_handler=NO_OP):
1231 """Get credentials if found else login to Ubuntu One."""
1232 params = {PING_URL_KEY: PING_URL}
1233 params.update(args)
1234@@ -116,16 +146,13 @@
1235
1236 def register_to_credentials_found(self, callback):
1237 """Register to the CredentialsFound dbus signal."""
1238- # XXX: we are not filtering by app name (bug #818190)
1239- pass_credentials = lambda app_name, creds: callback(creds)
1240 return RemovableSignal(self.sso_proxy, "on_credentials_found_cb",
1241- pass_credentials)
1242+ callback)
1243
1244 def register_to_credentials_not_found(self, callback):
1245 """Register to the CredentialsFound dbus signal."""
1246- pass_empty = lambda *args: callback()
1247 return RemovableSignal(self.sso_proxy, "on_credentials_not_found_cb",
1248- pass_empty)
1249+ callback)
1250
1251 def register_to_authorization_denied(self, callback):
1252 """Register to the AuthorizationDenied dbus signal."""
1253@@ -142,6 +169,7 @@
1254 def get_creds_proxy():
1255 """Get the CredentialsManagement proxy."""
1256 client = UbuntuSSOClient()
1257- client = yield client.connect()
1258+ yield client.connect()
1259 yield client.cred_management.register_to_signals()
1260- defer.returnValue(CredentialsManagement(client.cred_management))
1261+ result = CredentialsManagement(client.cred_management)
1262+ defer.returnValue(result)

Subscribers

People subscribed via source and target branches