~gary-lasker/software-center/launcher-integration-lp761851

« back to all changes in this revision

Viewing changes to utils/piston-helpers/piston_get_scagent_available_apps.py

  • Committer: Gary Lasker
  • Date: 2012-01-19 16:39:15 UTC
  • mfrom: (2566.1.113 trunk)
  • Revision ID: gary.lasker@canonical.com-20120119163915-lrgq5cdg6rttdn29
merge with trunk and fix conflicts to get 5.1.6 and lots of recent speedup/bug fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
 
3
 
from gi.repository import GObject
4
 
 
5
 
import argparse
6
 
import logging
7
 
import os
8
 
import pickle
9
 
import sys
10
 
 
11
 
import piston_mini_client.auth
12
 
 
13
 
from softwarecenter.enums import (SOFTWARE_CENTER_NAME_KEYRING,
14
 
                                  SOFTWARE_CENTER_SSO_DESCRIPTION,
15
 
                                  )
16
 
from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
17
 
from softwarecenter.backend.piston.scaclient import SoftwareCenterAgentAPI
18
 
from softwarecenter.backend.login_sso import get_sso_backend
19
 
from softwarecenter.backend.restfulclient import UbuntuSSOAPI
20
 
from softwarecenter.utils import clear_token_from_ubuntu_sso
21
 
 
22
 
from gettext import gettext as _
23
 
 
24
 
LOG = logging.getLogger(__name__)
25
 
 
26
 
class SSOLoginHelper(object):
27
 
    def __init__(self, xid=0):
28
 
        self.oauth = None
29
 
        self.xid = xid
30
 
        self.loop = GObject.MainLoop(GObject.main_context_default())
31
 
    
32
 
    def _login_successful(self, sso_backend, oauth_result):
33
 
        self.oauth = oauth_result
34
 
        # FIXME: actually verify the token against ubuntu SSO
35
 
        self.loop.quit()
36
 
 
37
 
    def verify_token(self, token):
38
 
        def _whoami_done(sso, me):
39
 
            self._whoami = me
40
 
            self.loop.quit()
41
 
        self._whoami = None
42
 
        sso = UbuntuSSOAPI(token)
43
 
        sso.connect("whoami", _whoami_done)
44
 
        sso.connect("error", lambda sso, err: self.loop.quit())
45
 
        sso.whoami()
46
 
        self.loop.run()
47
 
        # check if the token is valid
48
 
        if self._whoami is None:
49
 
            return False
50
 
        else:
51
 
            return True
52
 
 
53
 
    def clear_token(self):
54
 
        clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING)
55
 
 
56
 
    def get_oauth_token_sync(self):
57
 
        self.oauth = None
58
 
        sso = get_sso_backend(
59
 
            self.xid, 
60
 
            SOFTWARE_CENTER_NAME_KEYRING,
61
 
            _(SOFTWARE_CENTER_SSO_DESCRIPTION))
62
 
        sso.connect("login-successful", self._login_successful)
63
 
        sso.connect("login-failed", lambda s: self.loop.quit())
64
 
        sso.connect("login-canceled", lambda s: self.loop.quit())
65
 
        sso.login_or_register()
66
 
        self.loop.run()
67
 
        return self.oauth
68
 
 
69
 
if __name__ == "__main__":
70
 
    logging.basicConfig()
71
 
 
72
 
    # command line parser
73
 
    parser = argparse.ArgumentParser(description="Helper for software-center-agent")
74
 
    parser.add_argument("--debug", action="store_true", default=False,
75
 
                        help="enable debug output")
76
 
    parser.add_argument("--ignore-cache", action="store_true", default=False,
77
 
                        help="force ignore cache")
78
 
    parser.add_argument("--parent-xid", default=0,
79
 
                        help="xid of the parent window")
80
 
 
81
 
    subparser = parser.add_subparsers(title="Commands")
82
 
    # available_apps
83
 
    command = subparser.add_parser("available_apps")
84
 
    command.add_argument("lang")
85
 
    command.add_argument("series")
86
 
    command.add_argument("arch")
87
 
    command.set_defaults(command="available_apps")
88
 
 
89
 
    # available_apps_qa
90
 
    command = subparser.add_parser("available_apps_qa")
91
 
    command.add_argument("lang")
92
 
    command.add_argument("series")
93
 
    command.add_argument("arch")
94
 
    command.set_defaults(command="available_apps_qa")
95
 
    # subscriptions
96
 
    command = subparser.add_parser("subscriptions_for_me")
97
 
    command.set_defaults(command="subscriptions_for_me")
98
 
    # exhibits
99
 
    command = subparser.add_parser("exhibits")
100
 
    command.add_argument("lang")
101
 
    command.add_argument("series")
102
 
    command.set_defaults(command="exhibits")
103
 
 
104
 
    args = parser.parse_args()
105
 
 
106
 
    if args.debug:
107
 
        LOG.setLevel(logging.DEBUG)
108
 
 
109
 
    if args.ignore_cache:
110
 
        cachedir = None
111
 
    else:
112
 
        cachedir = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "scaclient")
113
 
 
114
 
 
115
 
    # check if auth is required
116
 
    if args.command in ("available_apps_qa", "subscriptions_for_me"):
117
 
        helper = SSOLoginHelper(args.parent_xid)
118
 
        token = helper.get_oauth_token_sync()
119
 
        # check if the token is valid and reset it if it is not
120
 
        if token and not helper.verify_token(token):
121
 
            helper.clear_token()
122
 
            # re-trigger login
123
 
            token = helper.get_oauth_token_sync()
124
 
        # if we don't have a token, error here
125
 
        if not token:
126
 
            sys.stderr.write("ERROR: can not obtain a oauth token\n")
127
 
            sys.exit(1)
128
 
        
129
 
        auth = piston_mini_client.auth.OAuthAuthorizer(token["token"],
130
 
                                                       token["token_secret"],
131
 
                                                       token["consumer_key"],
132
 
                                                       token["consumer_secret"])
133
 
        scaclient = SoftwareCenterAgentAPI(cachedir=cachedir, auth=auth)
134
 
    else:
135
 
        scaclient = SoftwareCenterAgentAPI(cachedir=cachedir)
136
 
        
137
 
    piston_reply = None
138
 
 
139
 
    # common kwargs
140
 
    if args.command in ("available_apps", "available_apps_qa"):
141
 
        kwargs = {"lang": args.lang,
142
 
                  "series": args.series,
143
 
                  "arch": args.arch
144
 
                  }
145
 
 
146
 
    # handle the args
147
 
    if args.command == "available_apps":
148
 
        try:
149
 
            piston_reply = scaclient.available_apps(**kwargs)
150
 
        except:
151
 
            LOG.exception("available_apps")
152
 
            sys.exit(1)
153
 
 
154
 
    elif args.command == "available_apps_qa":
155
 
        try:
156
 
            piston_reply = scaclient.available_apps_qa(**kwargs)
157
 
        except:
158
 
            LOG.exception("available_apps_qa")
159
 
            sys.exit(1)
160
 
    elif args.command == "subscriptions_for_me":
161
 
        try:
162
 
            piston_reply = scaclient.subscriptions_for_me(complete_only=True)
163
 
            # the new piston API send the data in a nasty format, most
164
 
            # interessting stuff is in the "application" dict, move it
165
 
            # back int othe main object here so that the parser understands it
166
 
            for item in piston_reply:
167
 
                for k, v in item.application.iteritems():
168
 
                    setattr(item, k, v)
169
 
        except:
170
 
            LOG.exception("subscriptions_for_me")
171
 
            sys.exit(1)
172
 
    if args.command == "exhibits":
173
 
        try:
174
 
            piston_reply = scaclient.exhibits(lang=args.lang, series=args.series)
175
 
        except:
176
 
            LOG.exception("exhibits")
177
 
            sys.exit(1)
178
 
 
179
 
    if args.debug:
180
 
        LOG.debug("reply: %s" % piston_reply)
181
 
        for item in piston_reply:
182
 
            for var in vars(item):
183
 
                print "%s: %s" % (var, getattr(item, var))
184
 
            print "\n\n"
185
 
 
186
 
 
187
 
    # print to stdout where its consumed by the parent
188
 
    if piston_reply is not None:
189
 
        try:
190
 
            print pickle.dumps(piston_reply)
191
 
        except IOError:
192
 
            # this can happen if the parent gets killed, no need to trigger
193
 
            # apport for this
194
 
            pass