Merge lp:~mvo/software-center/replace-restfulclient-with-piston into lp:software-center

Proposed by Michael Vogt
Status: Merged
Merged at revision: 2637
Proposed branch: lp:~mvo/software-center/replace-restfulclient-with-piston
Merge into: lp:software-center
Diff against target: 1365 lines (+377/-662)
19 files modified
debian/control (+0/-1)
softwarecenter/backend/login.py (+0/-7)
softwarecenter/backend/oneconfhandler/core.py (+6/-13)
softwarecenter/backend/piston/ubuntusso_pristine.py (+22/-0)
softwarecenter/backend/reviews/__init__.py (+3/-5)
softwarecenter/backend/reviews/rnr.py (+11/-13)
softwarecenter/backend/scagent.py (+32/-27)
softwarecenter/backend/spawn_helper.py (+24/-0)
softwarecenter/backend/ubuntusso.py (+50/-255)
softwarecenter/enums.py (+5/-0)
softwarecenter/paths.py (+1/-3)
test/gtk3/test_views.py (+2/-0)
test/test_reviews.py (+3/-2)
test/test_ubuntu_sso_api.py (+6/-11)
utils/piston-helpers/piston_generic_helper.py (+209/-0)
utils/piston-helpers/piston_get_review_stats_helper.py (+0/-65)
utils/piston-helpers/piston_get_scagent_available_apps.py (+0/-197)
utils/piston-helpers/piston_get_useful_votes_helper.py (+0/-46)
utils/submit_review_gtk3.py (+3/-17)
To merge this branch: bzr merge lp:~mvo/software-center/replace-restfulclient-with-piston
Reviewer Review Type Date Requested Status
software-store-developers Pending
Review via email: mp+87636@code.launchpad.net

Description of the change

This branch removes the need for lazr.restfulclient by replacing it with a piston-mini-client based helper.

It also cleansup the use of the piston-mini-client helpers and unifies most of them into the piston_generic_helper.

To post a comment you must log in.
Revision history for this message
Kiwinote (kiwinote) wrote :

in line 118 of backend/scagent.py we want 'exhibits' rather than 'exhiits'

Revision history for this message
Gary Lasker (gary-lasker) wrote :

Hi mvo! So I made the fix that kiwinote mentioned above, plus some small fixes that I *think* are needed to make Ubuntu SSO work, and finally some pyflakes cleanup. I pushed this to:

  lp:~gary-lasker/software-center/replace-restfulclient-with-piston-tweaks

Please take a look at the SSO changes in particular as I want to be sure these are correct.

I think that if these small changes look rigfht to you, we are good to go for this branch. Let's talk tomorrow if you like, to make sure everything's just right.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added symlink 'data/piston_generic_helper.py'
2=== target is u'../utils/piston-helpers/piston_generic_helper.py'
3=== removed symlink 'data/piston_get_review_stats_helper.py'
4=== target was u'../utils/piston-helpers/piston_get_review_stats_helper.py'
5=== removed symlink 'data/piston_get_scagent_available_apps.py'
6=== target was u'../utils/piston-helpers/piston_get_scagent_available_apps.py'
7=== removed symlink 'data/piston_get_useful_votes_helper.py'
8=== target was u'../utils/piston-helpers/piston_get_useful_votes_helper.py'
9=== modified file 'debian/control'
10--- debian/control 2011-12-06 14:22:20 +0000
11+++ debian/control 2012-01-05 15:32:23 +0000
12@@ -40,7 +40,6 @@
13 policykit-1,
14 policykit-1-gnome | policykit-1-kde,
15 python-xdg,
16- python-lazr.restfulclient,
17 ubuntu-sso-client (>= 0.99.6),
18 python-piston-mini-client (>= 0.1+bzr29),
19 oneconf (>= 0.2.6),
20
21=== modified file 'softwarecenter/backend/login.py'
22--- softwarecenter/backend/login.py 2011-09-15 14:24:14 +0000
23+++ softwarecenter/backend/login.py 2012-01-05 15:32:23 +0000
24@@ -49,10 +49,3 @@
25 raise NotImplemented
26 def cancel_login(self):
27 self.emit("login-canceled")
28- @property
29- def new_account_url(self):
30- return self.NEW_ACCOUNT_URL
31- @property
32- def forgoten_password_url(self):
33- return self.FORGOT_PASSWORD_URL
34-
35
36=== modified file 'softwarecenter/backend/oneconfhandler/core.py'
37--- softwarecenter/backend/oneconfhandler/core.py 2011-10-26 12:01:19 +0000
38+++ softwarecenter/backend/oneconfhandler/core.py 2012-01-05 15:32:23 +0000
39@@ -22,7 +22,7 @@
40 from oneconf.enums import MIN_TIME_WITHOUT_ACTIVITY
41
42 from softwarecenter.backend.login_sso import get_sso_backend
43-from softwarecenter.backend.restfulclient import get_ubuntu_sso_backend
44+from softwarecenter.backend.ubuntusso import get_ubuntu_sso_backend
45 from softwarecenter.utils import clear_token_from_ubuntu_sso
46
47 import datetime
48@@ -172,10 +172,11 @@
49 def _maybe_login_successful(self, sso, oauth_result):
50 """ called after we have the token, then we go and figure out our name """
51 logging.debug("_maybe_login_successful")
52- token = oauth_result
53- self.ssoapi = get_ubuntu_sso_backend(token)
54+ self.ssoapi = get_ubuntu_sso_backend()
55 self.ssoapi.connect("whoami", self._whoami_done)
56 self.ssoapi.connect("error", self._whoami_error)
57+ # this will automatically verify the keyring token and retrigger
58+ # login (once) if its expired
59 self.ssoapi.whoami()
60
61 def _whoami_done(self, ssologin, result):
62@@ -184,13 +185,5 @@
63
64 def _whoami_error(self, ssologin, e):
65 logging.error("whoami error '%s'" % e)
66- # HACK: clear the token from the keyring assuming that it expired
67- # or got deauthorized by the user on the website
68- # this really should be done by ubuntu-sso-client itself
69- import lazr.restfulclient.errors
70- errortype = lazr.restfulclient.errors.HTTPError
71- if (type(e) == errortype):
72- LOG.warn("authentication error, resetting token and retrying")
73- clear_token_from_ubuntu_sso(self.appname)
74- self._share_inventory(False)
75- return
76+ self._share_inventory(False)
77+ return
78
79=== added file 'softwarecenter/backend/piston/ubuntusso_pristine.py'
80--- softwarecenter/backend/piston/ubuntusso_pristine.py 1970-01-01 00:00:00 +0000
81+++ softwarecenter/backend/piston/ubuntusso_pristine.py 2012-01-05 15:32:23 +0000
82@@ -0,0 +1,22 @@
83+from piston_mini_client import PistonAPI, returns_json
84+from piston_mini_client.validators import oauth_protected
85+
86+# These are factored out as constants for if you need to work against a
87+# server that doesn't support both schemes (like http-only dev servers)
88+PUBLIC_API_SCHEME = 'http'
89+AUTHENTICATED_API_SCHEME = 'https'
90+
91+
92+# this is only here because:
93+# a) ubuntu-sso-client does not support verifying if the credentials
94+# are still valid
95+# b) the restful client interface is not really needed because we just
96+# need this one single call
97+class UbuntuSsoAPI(PistonAPI):
98+ default_service_root = 'http://localhost:8000/api/2.0'
99+
100+ @oauth_protected
101+ @returns_json
102+ def whoami(self, id=None):
103+ return self._get('accounts?ws.op=me',
104+ scheme=AUTHENTICATED_API_SCHEME)
105
106=== modified file 'softwarecenter/backend/reviews/__init__.py'
107--- softwarecenter/backend/reviews/__init__.py 2011-11-07 10:04:33 +0000
108+++ softwarecenter/backend/reviews/__init__.py 2012-01-05 15:32:23 +0000
109@@ -19,6 +19,7 @@
110 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
111
112 import datetime
113+import json
114 import logging
115 import operator
116 import os
117@@ -107,13 +108,10 @@
118 return False
119
120 # run the command and add watcher
121- cmd = [os.path.join(
122- softwarecenter.paths.datadir, PistonHelpers.GET_USEFUL_VOTES),
123- "--username", user,
124- ]
125 spawn_helper = SpawnHelper()
126 spawn_helper.connect("data-available", self._on_usefulness_data)
127- spawn_helper.run(cmd)
128+ spawn_helper.run_generic_piston_helper(
129+ "RatingsAndReviewsAPI", "get_usefulness", username=user)
130
131 def _on_usefulness_data(self, spawn_helper, results):
132 '''called if usefulness retrieved from server'''
133
134=== modified file 'softwarecenter/backend/reviews/rnr.py'
135--- softwarecenter/backend/reviews/rnr.py 2011-11-07 08:26:13 +0000
136+++ softwarecenter/backend/reviews/rnr.py 2012-01-05 15:32:23 +0000
137@@ -128,22 +128,20 @@
138 except OSError:
139 days_delta = 0
140 LOG.debug("refresh with days_delta: %s" % days_delta)
141+ # FIXME: the server currently has bug (#757695) so we
142+ # can not turn this on just yet and need to use
143+ # the old "catch-all" review-stats for now
144 #origin = "any"
145 #distroseries = self.distro.get_codename()
146- cmd = [os.path.join(
147- softwarecenter.paths.datadir, PistonHelpers.GET_REVIEW_STATS),
148- # FIXME: the server currently has bug (#757695) so we
149- # can not turn this on just yet and need to use
150- # the old "catch-all" review-stats for now
151- #"--origin", origin,
152- #"--distroseries", distroseries,
153- ]
154+ spawn_helper = SpawnHelper()
155+ spawn_helper.connect("data-available", self._on_review_stats_data, callback)
156 if days_delta:
157- cmd += ["--days-delta", str(days_delta)]
158- spawn_helper = SpawnHelper()
159- spawn_helper.connect("data-available", self._on_review_stats_data, callback)
160- spawn_helper.run(cmd)
161-
162+ spawn_helper.run_generic_piston_helper(
163+ "RatingsAndReviewsAPI", "review_stats", days=days_delta)
164+ else:
165+ spawn_helper.run_generic_piston_helper(
166+ "RatingsAndReviewsAPI", "review_stats")
167+
168 def _on_review_stats_data(self, spawn_helper, piston_review_stats, callback):
169 """ process stdout from the helper """
170 review_stats = self.REVIEW_STATS_CACHE
171
172=== modified file 'softwarecenter/backend/scagent.py'
173--- softwarecenter/backend/scagent.py 2012-01-03 15:20:56 +0000
174+++ softwarecenter/backend/scagent.py 2012-01-05 15:32:23 +0000
175@@ -20,6 +20,7 @@
176 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
177
178 from gi.repository import GObject
179+import json
180 import logging
181 import os
182
183@@ -56,14 +57,7 @@
184 GObject.GObject.__init__(self)
185 self.distro = get_distro()
186 self.ignore_cache = ignore_cache
187- binary = os.path.join(
188- softwarecenter.paths.datadir, PistonHelpers.SOFTWARE_CENTER_AGENT)
189- self.HELPER_CMD = [binary]
190- if self.ignore_cache:
191- self.HELPER_CMD.append("--ignore-cache")
192- if xid:
193- self.HELPER_CMD.append("--parent-xid")
194- self.HELPER_CMD.append(str(xid))
195+ self.xid = xid
196
197 def query_available(self, series_name=None, arch_tag=None):
198 self._query_available(series_name, arch_tag, for_qa=False)
199@@ -78,41 +72,52 @@
200 if not arch_tag:
201 arch_tag = get_current_arch()
202 # build the command
203- cmd = self.HELPER_CMD[:]
204+ spawner = SpawnHelper()
205+ spawner.parent_xid = self.xid
206+ spawner.ignore_cache = self.ignore_cache
207+ spawner.connect("data-available", self._on_query_available_data)
208+ spawner.connect("error", lambda spawner, err: self.emit("error", err))
209 if for_qa:
210- cmd.append("available_apps_qa")
211+ spawner.needs_auth = True
212+ spawner.run_generic_piston_helper(
213+ "SoftwareCenterAgentAPI",
214+ "available_apps_qa",
215+ lang=get_langugage(),
216+ series=series_name,
217+ arch=arch_tag)
218 else:
219- cmd.append("available_apps")
220- cmd += [language,
221- series_name,
222- arch_tag,
223- ]
224- spawner = SpawnHelper()
225- spawner.connect("data-available", self._on_query_available_data)
226- spawner.connect("error", lambda spawner, err: self.emit("error", err))
227- spawner.run(cmd)
228+ spawner.run_generic_piston_helper(
229+ "SoftwareCenterAgentAPI",
230+ "available_apps",
231+ lang=get_language(),
232+ series=series_name,
233+ arch=arch_tag)
234+
235 def _on_query_available_data(self, spawner, piston_available):
236 self.emit("available", piston_available)
237
238 def query_available_for_me(self, oauth_token, openid_identifier):
239- cmd = self.HELPER_CMD[:]
240- cmd.append("subscriptions_for_me")
241 spawner = SpawnHelper()
242+ spawner.parent_xid = self.xid
243+ spawner.ignore_cache = self.ignore_cache
244 spawner.connect("data-available", self._on_query_available_for_me_data)
245 spawner.connect("error", lambda spawner, err: self.emit("error", err))
246- spawner.run(cmd)
247+ spawner.needs_auth = True
248+ spawner.run_generic_piston_helper(
249+ "SoftwareCenterAgentAPI", "subscriptions_for_me")
250 def _on_query_available_for_me_data(self, spawner, piston_available_for_me):
251 self.emit("available-for-me", piston_available_for_me)
252
253 def query_exhibits(self):
254- cmd = self.HELPER_CMD[:]
255- cmd.append("exhibits")
256- cmd.append(get_language())
257- cmd.append(self.distro.get_codename())
258 spawner = SpawnHelper()
259+ spawner.parent_xid = self.xid
260+ spawner.ignore_cache = self.ignore_cache
261 spawner.connect("data-available", self._on_exhibits_data_available)
262 spawner.connect("error", lambda spawner, err: self.emit("error", err))
263- spawner.run(cmd)
264+ spawner.run_generic_piston_helper(
265+ "SoftwareCenterAgentAPI", "exhiits",
266+ lang=get_language(), series=self.distro.get_codename())
267+
268 def _on_exhibits_data_available(self, spawner, exhibits):
269 for exhibit in exhibits:
270 # special case, if there is no title provided by the server
271
272=== modified file 'softwarecenter/backend/spawn_helper.py'
273--- softwarecenter/backend/spawn_helper.py 2011-09-15 14:24:14 +0000
274+++ softwarecenter/backend/spawn_helper.py 2012-01-05 15:32:23 +0000
275@@ -30,6 +30,9 @@
276 import os
277 import json
278
279+import softwarecenter.paths
280+from softwarecenter.paths import PistonHelpers
281+
282 from gi.repository import GObject
283
284 LOG = logging.getLogger(__name__)
285@@ -59,6 +62,27 @@
286 self._io_watch = None
287 self._child_watch = None
288 self._cmd = None
289+ self.needs_auth = False
290+ self.ignore_cache = False
291+ self.parent_xid = None
292+
293+ def run_generic_piston_helper(self, klass, func, **kwargs):
294+ binary = os.path.join(
295+ softwarecenter.paths.datadir, PistonHelpers.GENERIC_HELPER)
296+ cmd = [binary]
297+ cmd += ["--datadir", softwarecenter.paths.datadir]
298+ if self.needs_auth:
299+ cmd.append("--needs-auth")
300+ if self.ignore_cache:
301+ cmd.append("--ignore-cache")
302+ if self.parent_xid:
303+ cmd.append("--parent-xid")
304+ cmd.append(str(xid))
305+ cmd += [klass, func]
306+ if kwargs:
307+ cmd.append(json.dumps(kwargs))
308+ LOG.debug("run_generic_piston_helper()")
309+ self.run(cmd)
310
311 def run(self, cmd):
312 self._cmd = cmd
313
314=== renamed file 'softwarecenter/backend/restfulclient.py' => 'softwarecenter/backend/ubuntusso.py'
315--- softwarecenter/backend/restfulclient.py 2012-01-05 09:53:52 +0000
316+++ softwarecenter/backend/ubuntusso.py 2012-01-05 15:32:23 +0000
317@@ -19,134 +19,29 @@
318 # this program; if not, write to the Free Software Foundation, Inc.,
319 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
320
321-import os
322
323 from gi.repository import GObject
324
325 import logging
326-import threading
327-
328-from softwarecenter.enums import BUY_SOMETHING_HOST
329-
330-# possible workaround for bug #599332 is to try to import lazr.restful
331-# import lazr.restful
332-# import lazr.restfulclient
333-
334-from lazr.restfulclient.resource import ServiceRoot
335-from lazr.restfulclient.authorize import BasicHttpAuthorizer
336-from lazr.restfulclient.authorize.oauth import OAuthAuthorizer
337-from oauth.oauth import OAuthToken
338-
339-from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
340-from Queue import Queue
341+import os
342+
343+import softwarecenter.paths
344+from softwarecenter.paths import PistonHelpers
345+
346+import piston_mini_client.auth
347
348 # mostly for testing
349 from fake_review_settings import FakeReviewSettings, network_delay
350-
351-from login import LoginBackend
352+from spawn_helper import SpawnHelper
353+
354+from softwarecenter.utils import clear_token_from_ubuntu_sso
355+
356+from gettext import gettext as _
357
358 LOG = logging.getLogger(__name__)
359
360-UBUNTU_SSO_SERVICE = os.environ.get(
361- "USSOC_SERVICE_URL", "https://login.ubuntu.com/api/1.0")
362-UBUNTU_SOFTWARE_CENTER_AGENT_SERVICE = BUY_SOMETHING_HOST+"/api/1.0"
363-
364-class AttributesObject(object):
365- """ convinient object to hold attributes """
366- MAX_REPR_STRING_SIZE = 30
367-
368- def __repr__(self):
369- s = "<'%s': " % self.__class__.__name__
370- for key in vars(self):
371- value = str(getattr(self, key))
372- if len(value) > self.MAX_REPR_STRING_SIZE:
373- value = "%s..." % value[:self.MAX_REPR_STRING_SIZE]
374- s += "%s='%s';" % (key, value)
375- s += ">"
376- return s
377-
378-
379-def restful_collection_to_real_python(restful_list):
380- """ take a restful and convert it to a python list with real python
381- objects
382- """
383- l = []
384- for entry in restful_list:
385- o = AttributesObject()
386- for attr in entry.lp_attributes:
387- setattr(o, attr, getattr(entry, attr))
388- l.append(o)
389- return l
390-
391-class RestfulClientWorker(threading.Thread):
392- """ a generic worker thread for a lazr.restfulclient """
393-
394- def __init__(self, authorizer, service_root):
395- """ init the thread """
396- threading.Thread.__init__(self)
397- self._service_root_url = service_root
398- self._authorizer = authorizer
399- self._pending_requests = Queue()
400- self._shutdown = False
401- self.daemon = True
402- self.error = None
403- self._cachedir = os.path.join(SOFTWARE_CENTER_CACHE_DIR,
404- "restfulclient")
405-
406- def run(self):
407- """
408- Main thread run interface, logs into launchpad
409- """
410- LOG.debug("lp worker thread run")
411- try:
412- self.service = ServiceRoot(self._authorizer,
413- self._service_root_url,
414- self._cachedir)
415- except:
416- logging.exception("worker thread can not connect to service root")
417- self.error = "ERROR_SERVICE_ROOT"
418- self._shutdown = True
419- return
420- # loop
421- self._wait_for_commands()
422-
423- def shutdown(self):
424- """Request shutdown"""
425- self._shutdown = True
426-
427- def queue_request(self, func, args, kwargs, result_callback, error_callback):
428- """
429- queue a (remote) command for execution, the result_callback will
430- call with the result_list when done (that function will be
431- called async)
432- """
433- self._pending_requests.put((func, args, kwargs, result_callback, error_callback))
434-
435- def _wait_for_commands(self):
436- """internal helper that waits for commands"""
437- while True:
438- while not self._pending_requests.empty():
439- LOG.debug("found pending request")
440- (func_str, args, kwargs, result_callback, error_callback) = self._pending_requests.get()
441- # run func async
442- try:
443- func = self.service
444- for part in func_str.split("."):
445- func = getattr(func, part)
446- res = func(*args, **kwargs)
447- except Exception ,e:
448- error_callback(e)
449- else:
450- result_callback(res)
451- self._pending_requests.task_done()
452- # wait a bit
453- import time
454- time.sleep(0.1)
455- if (self._shutdown and
456- self._pending_requests.empty()):
457- return
458-
459 class UbuntuSSOAPI(GObject.GObject):
460+ """ Ubuntu SSO interface using the oauth token from the keyring """
461
462 __gsignals__ = {
463 "whoami" : (GObject.SIGNAL_RUN_LAST,
464@@ -160,52 +55,27 @@
465
466 }
467
468- def __init__(self, token):
469+ def __init__(self):
470 GObject.GObject.__init__(self)
471- self._whoami = None
472- self._error = None
473- self.service = UBUNTU_SSO_SERVICE
474- self.token = token
475- token = OAuthToken(self.token["token"], self.token["token_secret"])
476- authorizer = OAuthAuthorizer(self.token["consumer_key"],
477- self.token["consumer_secret"],
478- access_token=token)
479- # we need to init the GObject.init_threads()
480- # - if we do it globally s-c will crash on exit (LP: #907568)
481- # - if we don't do it, s-c will hang in worker_thread.start()
482- # (even though threads_init is deprecated and according to the
483- # docs is run automatically nowdays)
484- # - if we do it here some apps will still crash
485- self.worker_thread = RestfulClientWorker(authorizer, self.service)
486- self.worker_thread.start()
487- GObject.timeout_add(200, self._monitor_thread)
488-
489- def _monitor_thread(self):
490- # glib bit of the threading, runs in the main thread
491- if self._whoami is not None:
492- self.emit("whoami", self._whoami)
493- self._whoami = None
494- if self._error is not None:
495- self.emit("error", self._error)
496- self._error = None
497- return True
498-
499- def _thread_whoami_done(self, result):
500- self._whoami = result
501-
502- def _thread_whoami_error(self, e):
503- self._error = e
504+
505+ def _on_whoami_data(self, spawner, piston_whoami):
506+ self.emit("whoami", piston_whoami)
507
508 def whoami(self):
509+ """ trigger request for the getting account information, this
510+ will also verify if the current token is valid and if not
511+ trigger a cleanup/re-authenticate
512+ """
513 LOG.debug("whoami called")
514- self.worker_thread.queue_request("accounts.me", (), {},
515- self._thread_whoami_done,
516- self._thread_whoami_error)
517-
518+ spawner = SpawnHelper()
519+ spawner.connect("data-available", self._on_whoami_data)
520+ spawner.connect("error", lambda spawner, err: self.emit("error", err))
521+ spawner.needs_auth = True
522+ spawner.run_generic_piston_helper("UbuntuSsoAPI", "whoami")
523
524 class UbuntuSSOAPIFake(UbuntuSSOAPI):
525
526- def __init__(self, token):
527+ def __init__(self):
528 GObject.GObject.__init__(self)
529 self._fake_settings = FakeReviewSettings()
530
531@@ -231,83 +101,18 @@
532 def _make_error():
533 return 'HTTP Error 401: Unauthorized'
534
535-def get_ubuntu_sso_backend(token):
536+def get_ubuntu_sso_backend():
537 """
538 factory that returns an ubuntu sso loader singelton
539 """
540 if "SOFTWARE_CENTER_FAKE_REVIEW_API" in os.environ:
541- ubuntu_sso_class = UbuntuSSOAPIFake(token)
542+ ubuntu_sso_class = UbuntuSSOAPIFake()
543 LOG.warn('Using fake Ubuntu SSO API. Only meant for testing purposes')
544 else:
545- ubuntu_sso_class = UbuntuSSOAPI(token)
546+ ubuntu_sso_class = UbuntuSSOAPI()
547 return ubuntu_sso_class
548
549
550-class UbuntuSSOlogin(LoginBackend):
551-
552- NEW_ACCOUNT_URL = "https://login.launchpad.net/+standalone-login"
553- FORGOT_PASSWORD_URL = "https://login.ubuntu.com/+forgot_password"
554-
555- SSO_AUTHENTICATE_FUNC = "authentications.authenticate"
556-
557- def __init__(self):
558- LoginBackend.__init__(self)
559- self.service = UBUNTU_SSO_SERVICE
560- # we get a dict here with the following keys:
561- # token
562- # consumer_key (also the openid identifier)
563- # consumer_secret
564- # token_secret
565- # name (that is just 'software-center')
566- self.oauth_credentials = None
567- self._oauth_credentials = None
568- self._login_failure = None
569- self.worker_thread = None
570-
571- def shutdown(self):
572- self.worker_thread.shutdown()
573-
574- def login(self, username=None, password=None):
575- if not username or not password:
576- self.emit("need-username-password")
577- return
578- authorizer = BasicHttpAuthorizer(username, password)
579- self.worker_thread = RestfulClientWorker(authorizer, self.service)
580- self.worker_thread.start()
581- kwargs = { "token_name" : "software-center",
582- }
583- self.worker_thread.queue_request(self.SSO_AUTHENTICATE_FUNC, (), kwargs,
584- self._thread_authentication_done,
585- self._thread_authentication_error)
586- GObject.timeout_add(200, self._monitor_thread)
587-
588- def _monitor_thread(self):
589- # glib bit of the threading, runs in the main thread
590- if self._oauth_credentials:
591- self.emit("login-successful", self._oauth_credentials)
592- self.oauth_credentials = self._oauth_credentials
593- self._oauth_credentials = None
594- if self._login_failure:
595- self.emit("login-failed")
596- self._login_failure = None
597- return True
598-
599- def _thread_authentication_done(self, result):
600- # runs in the thread context, can not touch gui or glib
601- #print "_authentication_done", result
602- self._oauth_credentials = result
603-
604- def _thread_authentication_error(self, e):
605- # runs in the thread context, can not touch gui or glib
606- #print "_authentication_error", type(e)
607- self._login_failure = e
608-
609- def __del__(self):
610- #print "del"
611- if self.worker_thread:
612- self.worker_thread.shutdown()
613-
614-
615 # test code
616 def _login_success(lp, token):
617 print "success", lp, token
618@@ -323,40 +128,30 @@
619 password = sys.stdin.readline().strip()
620 sso.login(user, password)
621
622-def _error(scaagent, errormsg):
623- print "_error:", errormsg
624-def _whoami(sso, whoami):
625- print "whoami: ", whoami
626-
627 # interactive test code
628 if __name__ == "__main__":
629+ def _whoami(sso, result):
630+ print "res: ", result
631+ Gtk.main_quit()
632+ def _error(sso, result):
633+ print "err: ", result
634+ Gtk.main_quit()
635+ def _dbus_maybe_login_successful(ssologin, oauth_result):
636+ print "got token, verify it now"
637+ sso = UbuntuSSOAPI()
638+ sso.connect("whoami", _whoami)
639+ sso.connect("error", _error)
640+ sso.whoami()
641+
642+ from gi.repository import Gtk
643 import sys
644 logging.basicConfig(level=logging.DEBUG)
645-
646- if len(sys.argv) < 2:
647- print "need an argument, one of: 'sso', 'ssologin'"
648- sys.exit(1)
649-
650- elif sys.argv[1] == "sso":
651- def _dbus_maybe_login_successful(ssologin, oauth_result):
652- sso = UbuntuSSOAPI(oauth_result)
653- sso.connect("whoami", _whoami)
654- sso.connect("error", _error)
655- sso.whoami()
656- from login_sso import get_sso_backend
657- backend = get_sso_backend("", "appname", "help_text")
658- backend.connect("login-successful", _dbus_maybe_login_successful)
659- backend.login_or_register()
660-
661- elif sys.argv[1] == "ssologin":
662- ssologin = UbuntuSSOlogin()
663- ssologin.connect("login-successful", _login_success)
664- ssologin.connect("login-failed", _login_failed)
665- ssologin.connect("need-username-password", _login_need_user_and_password)
666- ssologin.login()
667-
668- else:
669- print "unknown option"
670- sys.exit(1)
671+ softwarecenter.paths.datadir = "./data"
672+
673+ from login_sso import get_sso_backend
674+ backend = get_sso_backend("", "appname", "help_text")
675+ backend.connect("login-successful", _dbus_maybe_login_successful)
676+ backend.login_or_register()
677+ Gtk.main()
678
679
680
681=== modified file 'softwarecenter/enums.py'
682--- softwarecenter/enums.py 2011-12-16 12:50:18 +0000
683+++ softwarecenter/enums.py 2012-01-05 15:32:23 +0000
684@@ -34,6 +34,11 @@
685 BUY_SOMETHING_HOST = os.environ.get("SOFTWARE_CENTER_BUY_HOST") or "https://software-center.ubuntu.com"
686 BUY_SOMETHING_HOST_ANONYMOUS = os.environ.get("SOFTWARE_CENTER_BUY_HOST") or "http://software-center.ubuntu.com"
687
688+# for the sso login
689+UBUNTU_SSO_SERVICE = os.environ.get(
690+ "USSOC_SERVICE_URL", "https://login.ubuntu.com/")
691+SSO_LOGIN_HOST = UBUNTU_SSO_SERVICE
692+
693 # version of the database, every time something gets added (like
694 # terms for mime-type) increase this (but keep as a string!)
695 DB_SCHEMA_VERSION = "6"
696
697=== modified file 'softwarecenter/paths.py'
698--- softwarecenter/paths.py 2011-09-13 12:45:56 +0000
699+++ softwarecenter/paths.py 2012-01-05 15:32:23 +0000
700@@ -86,9 +86,7 @@
701 # piston helpers
702 class PistonHelpers:
703 GET_REVIEWS = "piston_get_reviews_helper.py"
704- GET_REVIEW_STATS = "piston_get_review_stats_helper.py"
705- GET_USEFUL_VOTES = "piston_get_useful_votes_helper.py"
706- SOFTWARE_CENTER_AGENT = "piston_get_scagent_available_apps.py"
707+ GENERIC_HELPER = "piston_generic_helper.py"
708
709 X2GO_HELPER = "x2go_helper.py"
710
711
712=== modified file 'test/gtk3/test_views.py'
713--- test/gtk3/test_views.py 2011-11-15 10:54:54 +0000
714+++ test/gtk3/test_views.py 2012-01-05 15:32:23 +0000
715@@ -13,6 +13,8 @@
716
717 import softwarecenter.paths
718 softwarecenter.paths.datadir = "../data"
719+import os
720+os.environ["PYTHONPATH"] = "../"
721
722 class TestViews(unittest.TestCase):
723
724
725=== modified file 'test/test_reviews.py'
726--- test/test_reviews.py 2011-11-04 14:52:52 +0000
727+++ test/test_reviews.py 2012-01-05 15:32:23 +0000
728@@ -11,6 +11,7 @@
729
730 import softwarecenter.paths
731 softwarecenter.paths.SOFTWARE_CENTER_CACHE_DIR = tempfile.mkdtemp()
732+softwarecenter.paths.datadir = "../data"
733
734 from softwarecenter.backend.reviews.rnr import (
735 ReviewLoaderSpawningRNRClient as ReviewLoader)
736@@ -51,6 +52,6 @@
737 main_loop.iteration()
738
739 if __name__ == "__main__":
740- #import logging
741- #logging.basicConfig(level=logging.DEBUG)
742+ import logging
743+ logging.basicConfig(level=logging.DEBUG)
744 unittest.main()
745
746=== modified file 'test/test_ubuntu_sso_api.py'
747--- test/test_ubuntu_sso_api.py 2011-06-11 07:59:59 +0000
748+++ test/test_ubuntu_sso_api.py 2012-01-05 15:32:23 +0000
749@@ -6,10 +6,10 @@
750
751 import os
752 import unittest
753-from softwarecenter.backend.restfulclient import (UbuntuSSOAPIFake,
754- UbuntuSSOAPI,
755- get_ubuntu_sso_backend,
756- )
757+from softwarecenter.backend.ubuntusso import (UbuntuSSOAPIFake,
758+ UbuntuSSOAPI,
759+ get_ubuntu_sso_backend,
760+ )
761
762 class TestSSOAPI(unittest.TestCase):
763 """ tests the ubuntu sso backend stuff """
764@@ -24,17 +24,12 @@
765 set([x for x in dir(sso_fake) if not x.startswith("_")]))
766
767 def test_get_ubuntu_backend(self):
768- token = { 'token' : 'tokenvalue',
769- 'token_secret' : 'tokensecretvalue',
770- 'consumer_key' : 'consumerkeyvalue',
771- 'consumer_secret' : 'consumersecretvalue',
772- }
773 # test that we get the real one
774- self.assertEqual(type(get_ubuntu_sso_backend(token)),
775+ self.assertEqual(type(get_ubuntu_sso_backend()),
776 UbuntuSSOAPI)
777 # test that we get the fake one
778 os.environ["SOFTWARE_CENTER_FAKE_REVIEW_API"] = "1"
779- self.assertEqual(type(get_ubuntu_sso_backend(token)),
780+ self.assertEqual(type(get_ubuntu_sso_backend()),
781 UbuntuSSOAPIFake)
782 # clean the environment
783 del os.environ["SOFTWARE_CENTER_FAKE_REVIEW_API"]
784
785=== added file 'utils/piston-helpers/piston_generic_helper.py'
786--- utils/piston-helpers/piston_generic_helper.py 1970-01-01 00:00:00 +0000
787+++ utils/piston-helpers/piston_generic_helper.py 2012-01-05 15:32:23 +0000
788@@ -0,0 +1,209 @@
789+#!/usr/bin/python
790+# Copyright (C) 2011 Canonical
791+#
792+# Authors:
793+# Michael Vogt
794+#
795+# This program is free software; you can redistribute it and/or modify it under
796+# the terms of the GNU General Public License as published by the Free Software
797+# Foundation; version 3.
798+#
799+# This program is distributed in the hope that it will be useful, but WITHOUT
800+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
801+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
802+# details.
803+#
804+# You should have received a copy of the GNU General Public License along with
805+# this program; if not, write to the Free Software Foundation, Inc.,
806+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
807+
808+import argparse
809+import logging
810+import os
811+import json
812+import pickle
813+import sys
814+
815+from gi.repository import GObject
816+
817+# useful for debugging
818+if "SOFTWARE_CENTER_DEBUG_HTTP" in os.environ:
819+ import httplib2
820+ httplib2.debuglevel = 1
821+
822+import piston_mini_client.auth
823+
824+try:
825+ import softwarecenter
826+except ImportError:
827+ if os.path.exists("../softwarecenter"):
828+ sys.path.insert(0, "../")
829+ else:
830+ sys.path.insert(0, "/usr/share/software-center")
831+
832+import softwarecenter.paths
833+from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
834+from softwarecenter.backend.login_sso import get_sso_backend
835+
836+from softwarecenter.enums import (SOFTWARE_CENTER_NAME_KEYRING,
837+ SOFTWARE_CENTER_SSO_DESCRIPTION,
838+ )
839+
840+# the piston import
841+from softwarecenter.backend.piston.ubuntusso_pristine import UbuntuSsoAPI
842+from softwarecenter.backend.piston.rnrclient import RatingsAndReviewsAPI
843+from softwarecenter.backend.piston.scaclient import SoftwareCenterAgentAPI
844+
845+RatingsAndReviewsAPI # pyflakes
846+UbuntuSsoAPI # pyflakes
847+SoftwareCenterAgentAPI # pyflakes
848+
849+# patch default_service_root to the one we use
850+from softwarecenter.enums import SSO_LOGIN_HOST
851+UbuntuSsoAPI.default_service_root = SSO_LOGIN_HOST+"/api/1.0"
852+
853+from gettext import gettext as _
854+
855+# helper that is only used to verify that the token is ok
856+# and trigger cleanup if not
857+class SSOLoginHelper(object):
858+
859+ def __init__(self, xid=0):
860+ self.oauth = None
861+ self.xid = xid
862+ self.loop = GObject.MainLoop(GObject.main_context_default())
863+
864+ def _login_successful(self, sso_backend, oauth_result):
865+ LOG.debug("_login_successful")
866+ self.oauth = oauth_result
867+ # FIXME: actually verify the token against ubuntu SSO
868+ self.loop.quit()
869+
870+ def verify_token_sync(self, token):
871+ LOG.debug("verify_token")
872+ auth = piston_mini_client.auth.OAuthAuthorizer(token["token"],
873+ token["token_secret"],
874+ token["consumer_key"],
875+ token["consumer_secret"])
876+ api = UbuntuSsoAPI(auth=auth)
877+ try:
878+ res = api.whoami()
879+ except:
880+ LOG.exception("api.whoami failed")
881+ return None
882+ return res
883+
884+ def clear_token(self):
885+ clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING)
886+
887+ def get_oauth_token_sync(self):
888+ self.oauth = None
889+ sso = get_sso_backend(
890+ self.xid,
891+ SOFTWARE_CENTER_NAME_KEYRING,
892+ _(SOFTWARE_CENTER_SSO_DESCRIPTION))
893+ sso.connect("login-successful", self._login_successful)
894+ sso.connect("login-failed", lambda s: self.loop.quit())
895+ sso.connect("login-canceled", lambda s: self.loop.quit())
896+ sso.login_or_register()
897+ self.loop.run()
898+ return self.oauth
899+
900+ def get_oauth_token_and_verify_sync(self):
901+ token = self.get_oauth_token_sync()
902+ # check if the token is valid and reset it if it is not
903+ if token and not self.verify_token_sync(token):
904+ self.clear_token()
905+ # re-trigger login
906+ token = self.get_oauth_token_sync()
907+ return token
908+
909+
910+
911+LOG = logging.getLogger(__name__)
912+
913+if __name__ == "__main__":
914+ logging.basicConfig()
915+
916+ # command line parser
917+ parser = argparse.ArgumentParser(
918+ description="Backend helper for piston-mini-client based APIs")
919+ parser.add_argument("--debug", action="store_true", default=False,
920+ help="enable debug output")
921+ parser.add_argument("--datadir", default="/usr/share/software-center",
922+ help="setup alternative datadir")
923+ parser.add_argument("--ignore-cache", action="store_true", default=False,
924+ help="force ignore cache")
925+ parser.add_argument("--needs-auth", default=False, action="store_true",
926+ help="need oauth credentials")
927+ parser.add_argument("--output", default="pickle",
928+ help="output result as [pickle|json|text]")
929+ parser.add_argument("--parent-xid", default=0,
930+ help="xid of the parent window")
931+ parser.add_argument('klass', help='class to use')
932+ parser.add_argument('function', help='function to call')
933+ parser.add_argument('kwargs', nargs="?",
934+ help='kwargs for the function call as json')
935+ args = parser.parse_args()
936+
937+ if args.debug:
938+ logging.basicConfig(level=logging.DEBUG)
939+ LOG.setLevel(logging.DEBUG)
940+
941+ if args.ignore_cache:
942+ cachedir = None
943+ else:
944+ cachedir = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "piston-helper")
945+
946+ # check what we need to call
947+ klass = globals()[args.klass]
948+ func = args.function
949+ kwargs = json.loads(args.kwargs or '{}')
950+
951+ softwarecenter.paths.datadir = args.datadir
952+
953+ if args.needs_auth:
954+ helper = SSOLoginHelper(args.parent_xid)
955+ token = helper.get_oauth_token_and_verify_sync()
956+ # if we don't have a token, error here
957+ if not token:
958+ sys.stderr.write("ERROR: can not obtain a oauth token\n")
959+ sys.exit(1)
960+
961+ auth = piston_mini_client.auth.OAuthAuthorizer(token["token"],
962+ token["token_secret"],
963+ token["consumer_key"],
964+ token["consumer_secret"])
965+ api = klass(cachedir=cachedir, auth=auth)
966+ else:
967+ api = klass()
968+
969+ piston_reply = None
970+ # handle the args
971+ f = getattr(api, func)
972+ try:
973+ piston_reply = f(**kwargs)
974+ except:
975+ LOG.exception("urclient_apps")
976+ sys.exit(1)
977+
978+ # print to stdout where its consumed by the parent
979+ if piston_reply is None:
980+ LOG.warn("no data")
981+ sys.exit(0)
982+
983+ # check what format to use
984+ if args.output == "pickle":
985+ res = pickle.dumps(piston_reply)
986+ elif args.output == "json":
987+ res = json.dumps(piston_reply)
988+ elif args.output == "text":
989+ res = piston_reply
990+
991+ # and output it
992+ try:
993+ print res
994+ except IOError:
995+ # this can happen if the parent gets killed, no need to trigger
996+ # apport for this
997+ pass
998
999=== removed file 'utils/piston-helpers/piston_get_review_stats_helper.py'
1000--- utils/piston-helpers/piston_get_review_stats_helper.py 2011-07-13 14:25:55 +0000
1001+++ utils/piston-helpers/piston_get_review_stats_helper.py 1970-01-01 00:00:00 +0000
1002@@ -1,65 +0,0 @@
1003-#!/usr/bin/python
1004-
1005-import os
1006-import pickle
1007-import logging
1008-import sys
1009-
1010-from optparse import OptionParser
1011-
1012-from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
1013-from softwarecenter.backend.piston.rnrclient import RatingsAndReviewsAPI
1014-
1015-LOG = logging.getLogger(__name__)
1016-
1017-if __name__ == "__main__":
1018- logging.basicConfig()
1019-
1020- # common options for optparse go here
1021- parser = OptionParser()
1022-
1023- # check options
1024- parser.add_option("--origin", default="any")
1025- parser.add_option("--distroseries", default="any")
1026- parser.add_option("--days-delta", default=None)
1027- parser.add_option("--debug",
1028- action="store_true", default=False)
1029- parser.add_option("--no-pickle",
1030- action="store_true", default=False)
1031- (options, args) = parser.parse_args()
1032-
1033- if options.debug:
1034- LOG.setLevel(logging.DEBUG)
1035-
1036- cachedir = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "rnrclient")
1037- rnrclient = RatingsAndReviewsAPI(cachedir=cachedir)
1038-
1039- kwargs = {"origin": options.origin,
1040- "distroseries": options.distroseries,
1041- }
1042- if options.days_delta:
1043- kwargs["days"] = int(options.days_delta)
1044-
1045- # depending on the time delta, use a different call
1046- piston_review_stats = []
1047- try:
1048- piston_review_stats = rnrclient.review_stats(**kwargs)
1049- except:
1050- LOG.exception("get_review_stats")
1051- sys.exit(1)
1052-
1053- # useful for debugging
1054- if options.no_pickle:
1055- print "\n".join(["pkgname=%s total=%s avg=%s" % (s.package_name,
1056- s.ratings_total,
1057- s.ratings_average)
1058- for s in piston_review_stats])
1059- else:
1060- # print to stdout where its consumed by the parent
1061- try:
1062- print pickle.dumps(piston_review_stats)
1063- except IOError:
1064- # this can happen if the parent gets killed, no need to trigger
1065- # apport for this
1066- sys.exit(1)
1067-
1068
1069=== removed file 'utils/piston-helpers/piston_get_scagent_available_apps.py'
1070--- utils/piston-helpers/piston_get_scagent_available_apps.py 2012-01-05 09:53:52 +0000
1071+++ utils/piston-helpers/piston_get_scagent_available_apps.py 1970-01-01 00:00:00 +0000
1072@@ -1,197 +0,0 @@
1073-#!/usr/bin/python
1074-
1075-from gi.repository import GObject
1076-
1077-import argparse
1078-import logging
1079-import os
1080-import pickle
1081-import sys
1082-
1083-import piston_mini_client.auth
1084-
1085-from softwarecenter.enums import (SOFTWARE_CENTER_NAME_KEYRING,
1086- SOFTWARE_CENTER_SSO_DESCRIPTION,
1087- )
1088-from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
1089-from softwarecenter.backend.piston.scaclient import SoftwareCenterAgentAPI
1090-from softwarecenter.backend.login_sso import get_sso_backend
1091-from softwarecenter.backend.restfulclient import UbuntuSSOAPI
1092-from softwarecenter.utils import clear_token_from_ubuntu_sso
1093-
1094-from gettext import gettext as _
1095-
1096-LOG = logging.getLogger(__name__)
1097-
1098-class SSOLoginHelper(object):
1099- def __init__(self, xid=0):
1100- self.oauth = None
1101- self.xid = xid
1102- self.loop = GObject.MainLoop(GObject.main_context_default())
1103-
1104- def _login_successful(self, sso_backend, oauth_result):
1105- LOG.debug("_login_successful")
1106- self.oauth = oauth_result
1107- # FIXME: actually verify the token against ubuntu SSO
1108- self.loop.quit()
1109-
1110- def verify_token(self, token):
1111- LOG.debug("verify_token")
1112- def _whoami_done(sso, me):
1113- self._whoami = me
1114- self.loop.quit()
1115- self._whoami = None
1116- sso = UbuntuSSOAPI(token)
1117- sso.connect("whoami", _whoami_done)
1118- sso.connect("error", lambda sso, err: self.loop.quit())
1119- sso.whoami()
1120- self.loop.run()
1121- LOG.debug("verify_token finished")
1122- # check if the token is valid
1123- if self._whoami is None:
1124- return False
1125- else:
1126- return True
1127-
1128- def clear_token(self):
1129- clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING)
1130-
1131- def get_oauth_token_sync(self):
1132- self.oauth = None
1133- sso = get_sso_backend(
1134- self.xid,
1135- SOFTWARE_CENTER_NAME_KEYRING,
1136- _(SOFTWARE_CENTER_SSO_DESCRIPTION))
1137- sso.connect("login-successful", self._login_successful)
1138- sso.connect("login-failed", lambda s: self.loop.quit())
1139- sso.connect("login-canceled", lambda s: self.loop.quit())
1140- sso.login_or_register()
1141- self.loop.run()
1142- return self.oauth
1143-
1144-if __name__ == "__main__":
1145- logging.basicConfig()
1146-
1147- # command line parser
1148- parser = argparse.ArgumentParser(description="Helper for software-center-agent")
1149- parser.add_argument("--debug", action="store_true", default=False,
1150- help="enable debug output")
1151- parser.add_argument("--ignore-cache", action="store_true", default=False,
1152- help="force ignore cache")
1153- parser.add_argument("--parent-xid", default=0,
1154- help="xid of the parent window")
1155-
1156- subparser = parser.add_subparsers(title="Commands")
1157- # available_apps
1158- command = subparser.add_parser("available_apps")
1159- command.add_argument("lang")
1160- command.add_argument("series")
1161- command.add_argument("arch")
1162- command.set_defaults(command="available_apps")
1163-
1164- # available_apps_qa
1165- command = subparser.add_parser("available_apps_qa")
1166- command.add_argument("lang")
1167- command.add_argument("series")
1168- command.add_argument("arch")
1169- command.set_defaults(command="available_apps_qa")
1170- # subscriptions
1171- command = subparser.add_parser("subscriptions_for_me")
1172- command.set_defaults(command="subscriptions_for_me")
1173- # exhibits
1174- command = subparser.add_parser("exhibits")
1175- command.add_argument("lang")
1176- command.add_argument("series")
1177- command.set_defaults(command="exhibits")
1178-
1179- args = parser.parse_args()
1180-
1181- if args.debug:
1182- LOG.setLevel(logging.DEBUG)
1183-
1184- if args.ignore_cache:
1185- cachedir = None
1186- else:
1187- cachedir = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "scaclient")
1188-
1189-
1190- # check if auth is required
1191- if args.command in ("available_apps_qa", "subscriptions_for_me"):
1192- helper = SSOLoginHelper(args.parent_xid)
1193- token = helper.get_oauth_token_sync()
1194- # check if the token is valid and reset it if it is not
1195- if token and not helper.verify_token(token):
1196- helper.clear_token()
1197- # re-trigger login
1198- token = helper.get_oauth_token_sync()
1199- # if we don't have a token, error here
1200- if not token:
1201- sys.stderr.write("ERROR: can not obtain a oauth token\n")
1202- sys.exit(1)
1203-
1204- auth = piston_mini_client.auth.OAuthAuthorizer(token["token"],
1205- token["token_secret"],
1206- token["consumer_key"],
1207- token["consumer_secret"])
1208- scaclient = SoftwareCenterAgentAPI(cachedir=cachedir, auth=auth)
1209- else:
1210- scaclient = SoftwareCenterAgentAPI(cachedir=cachedir)
1211-
1212- piston_reply = None
1213-
1214- # common kwargs
1215- if args.command in ("available_apps", "available_apps_qa"):
1216- kwargs = {"lang": args.lang,
1217- "series": args.series,
1218- "arch": args.arch
1219- }
1220-
1221- # handle the args
1222- if args.command == "available_apps":
1223- try:
1224- piston_reply = scaclient.available_apps(**kwargs)
1225- except:
1226- LOG.exception("available_apps")
1227- sys.exit(1)
1228-
1229- elif args.command == "available_apps_qa":
1230- try:
1231- piston_reply = scaclient.available_apps_qa(**kwargs)
1232- except:
1233- LOG.exception("available_apps_qa")
1234- sys.exit(1)
1235- elif args.command == "subscriptions_for_me":
1236- try:
1237- piston_reply = scaclient.subscriptions_for_me(complete_only=True)
1238- # the new piston API send the data in a nasty format, most
1239- # interessting stuff is in the "application" dict, move it
1240- # back int othe main object here so that the parser understands it
1241- for item in piston_reply:
1242- for k, v in item.application.iteritems():
1243- setattr(item, k, v)
1244- except:
1245- LOG.exception("subscriptions_for_me")
1246- sys.exit(1)
1247- if args.command == "exhibits":
1248- try:
1249- piston_reply = scaclient.exhibits(lang=args.lang, series=args.series)
1250- except:
1251- LOG.exception("exhibits")
1252- sys.exit(1)
1253-
1254- if args.debug:
1255- LOG.debug("reply: %s" % piston_reply)
1256- for item in piston_reply:
1257- for var in vars(item):
1258- print "%s: %s" % (var, getattr(item, var))
1259- print "\n\n"
1260-
1261-
1262- # print to stdout where its consumed by the parent
1263- if piston_reply is not None:
1264- try:
1265- print pickle.dumps(piston_reply)
1266- except IOError:
1267- # this can happen if the parent gets killed, no need to trigger
1268- # apport for this
1269- pass
1270
1271=== removed file 'utils/piston-helpers/piston_get_useful_votes_helper.py'
1272--- utils/piston-helpers/piston_get_useful_votes_helper.py 2011-08-19 11:25:58 +0000
1273+++ utils/piston-helpers/piston_get_useful_votes_helper.py 1970-01-01 00:00:00 +0000
1274@@ -1,46 +0,0 @@
1275-#!/usr/bin/python
1276-
1277-import pickle
1278-import logging
1279-import sys
1280-
1281-from optparse import OptionParser
1282-from softwarecenter.backend.piston.rnrclient import RatingsAndReviewsAPI
1283-from piston_mini_client import APIError
1284-
1285-LOG = logging.getLogger(__name__)
1286-
1287-if __name__ == "__main__":
1288- logging.basicConfig()
1289-
1290- # common options for optparse go here
1291- parser = OptionParser()
1292-
1293- # check options
1294- parser.add_option("--username", default=None)
1295- (options, args) = parser.parse_args()
1296-
1297- rnrclient = RatingsAndReviewsAPI()
1298-
1299- useful_votes = []
1300-
1301- if options.username:
1302- try:
1303- useful_votes = rnrclient.get_usefulness(username=options.username)
1304- except ValueError as e:
1305- LOG.error("failed to parse '%s'" % e.doc)
1306- except APIError, e:
1307- LOG.warn("_get_useful_votes_helper: no usefulness able to be retrieved for username: %s" % (options.username))
1308- LOG.debug("_get_reviews_threaded: no reviews able to be retrieved: %s" % e)
1309- except:
1310- LOG.exception("_get_useful_votes_helper")
1311- sys.exit(1)
1312-
1313- # print to stdout where its consumed by the parent
1314- try:
1315- print pickle.dumps(useful_votes)
1316- except IOError:
1317- # this can happen if the parent gets killed, no need to trigger
1318- # apport for this
1319- pass
1320-
1321
1322=== modified file 'utils/submit_review_gtk3.py'
1323--- utils/submit_review_gtk3.py 2011-10-24 07:49:37 +0000
1324+++ utils/submit_review_gtk3.py 2012-01-05 15:32:23 +0000
1325@@ -50,7 +50,7 @@
1326 from gettext import gettext as _
1327 from optparse import OptionParser
1328
1329-from softwarecenter.backend.restfulclient import get_ubuntu_sso_backend
1330+from softwarecenter.backend.ubuntusso import get_ubuntu_sso_backend
1331
1332 import piston_mini_client
1333
1334@@ -490,6 +490,8 @@
1335 self.ssoapi = get_ubuntu_sso_backend(self.token)
1336 self.ssoapi.connect("whoami", self._whoami_done)
1337 self.ssoapi.connect("error", self._whoami_error)
1338+ # this will automatically verify the token and retrigger login
1339+ # if its expired
1340 self.ssoapi.whoami()
1341
1342 def _whoami_done(self, ssologin, result):
1343@@ -500,22 +502,6 @@
1344
1345 def _whoami_error(self, ssologin, e):
1346 logging.error("whoami error '%s'" % e)
1347- # HACK: clear the token from the keyring assuming that it expired
1348- # or got deauthorized by the user on the website
1349- # this really should be done by ubuntu-sso-client itself
1350- import lazr.restfulclient.errors
1351- # compat with maverick, it does not have Unauthorized yet
1352- if hasattr(lazr.restfulclient.errors, "Unauthorized"):
1353- errortype = lazr.restfulclient.errors.Unauthorized
1354- else:
1355- errortype = lazr.restfulclient.errors.HTTPError
1356- if (type(e) == errortype and
1357- self._whoami_token_reset_nr == 0):
1358- logging.warn("authentication error, reseting token and retrying")
1359- clear_token_from_ubuntu_sso(self.appname)
1360- self._whoami_token_reset_nr += 1
1361- self.login(show_register=False)
1362- return
1363 # show error
1364 self.status_spinner.hide()
1365 self.login_status_label.set_markup('<b><big>%s</big></b>' % _("Failed to log in"))

Subscribers

People subscribed via source and target branches