Merge lp:~aaronp/software-center/enhance-usefulness into lp:software-center

Proposed by Aaron Peachey
Status: Merged
Merged at revision: 1760
Proposed branch: lp:~aaronp/software-center/enhance-usefulness
Merge into: lp:software-center
Diff against target: 208 lines (+125/-8)
6 files modified
softwarecenter/app.py (+3/-1)
softwarecenter/db/reviews.py (+58/-2)
softwarecenter/paths.py (+1/-0)
softwarecenter/utils.py (+10/-5)
utils/get_useful_votes_helper.py (+45/-0)
utils/submit_review.py (+8/-0)
To merge this branch: bzr merge lp:~aaronp/software-center/enhance-usefulness
Reviewer Review Type Date Requested Status
software-store-developers Pending
Review via email: mp+59610@code.launchpad.net

Commit message

enhance usefulness functionality to add support for getting user's votes from the server at startup and anytime we get the username of the user

Description of the change

- fix bug that causes crash when submitting usefulness because unused usefulness UI doesn't contain all elements that need to be updated since adding the error details expander (r1755)
- add support for getting user's votes from server by first loading them from local cache and then spawning a retrieval process in the background to populate them from the server once a response is received. Load from cache whenever UsefulnessCache object is created except upon startup (app.py) when we try to get them from the server (r1756-1758)
- don't update username into local config if the one we have is the same as the one we want to update. (r1759)
- if we DO update a new username into local config, try to update the UsefulnessCache from the server using the new username (as it's likely we didn't get it from the server at startup) (r1759)

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added symlink 'data/get_useful_votes_helper.py'
2=== target is u'../utils/get_useful_votes_helper.py'
3=== modified file 'softwarecenter/app.py'
4--- softwarecenter/app.py 2011-04-29 14:38:29 +0000
5+++ softwarecenter/app.py 2011-05-01 07:52:26 +0000
6@@ -61,7 +61,7 @@
7 from paths import SOFTWARE_CENTER_ICON_CACHE_DIR
8
9 from plugin import PluginManager
10-from db.reviews import get_review_loader
11+from db.reviews import get_review_loader, UsefulnessCache
12 from distro import get_distro
13 from apt.aptcache import AptCache
14 from gettext import gettext as _
15@@ -169,6 +169,8 @@
16 self.review_loader = get_review_loader(self.cache, self.db)
17 # FIXME: add some kind of throttle, I-M-S here
18 self.review_loader.refresh_review_stats(self.on_review_stats_loaded)
19+ #load usefulness votes from server when app starts
20+ self.useful_cache = UsefulnessCache(True)
21
22 # additional icons come from app-install-data
23 self.icons = gtk.icon_theme_get_default()
24
25=== modified file 'softwarecenter/db/reviews.py'
26--- softwarecenter/db/reviews.py 2011-04-29 14:28:01 +0000
27+++ softwarecenter/db/reviews.py 2011-05-01 07:52:26 +0000
28@@ -59,16 +59,72 @@
29
30 USEFULNESS_CACHE = {}
31
32- def __init__(self):
33+ def __init__(self, try_server=False):
34+ self.rnrclient = RatingsAndReviewsAPI()
35 fname = "usefulness.p"
36 self.USEFULNESS_CACHE_FILE = os.path.join(SOFTWARE_CENTER_CACHE_DIR,
37 fname)
38+
39+ self._retrieve_votes_from_cache()
40+ #Only try to get votes from the server if required, otherwise just use cache
41+ if try_server:
42+ self._retrieve_votes_from_server()
43+
44+ def _retrieve_votes_from_cache(self):
45 if os.path.exists(self.USEFULNESS_CACHE_FILE):
46 try:
47 self.USEFULNESS_CACHE = cPickle.load(open(self.USEFULNESS_CACHE_FILE))
48 except:
49- LOG.exception("usefulness cache load failure")
50+ LOG.exception("usefulness cache load fallback failure")
51 os.rename(self.USEFULNESS_CACHE_FILE, self.USEFULNESS_CACHE_FILE+".fail")
52+ return
53+
54+ def _retrieve_votes_from_server(self):
55+ LOG.debug("_retrieve_votes_from_server started")
56+ user = get_person_from_config()
57+
58+ if not user:
59+ LOG.warn("Could not get usefulness from server, no username in config file")
60+ return False
61+
62+ # run the command and add watcher
63+ cmd = [os.path.join(softwarecenter.paths.datadir, GET_USEFUL_VOTES_HELPER),
64+ "--username", user,
65+ ]
66+ try:
67+ (pid, stdin, stdout, stderr) = glib.spawn_async(
68+ cmd, flags = glib.SPAWN_DO_NOT_REAP_CHILD,
69+ standard_output=True, standard_error=True)
70+ glib.child_watch_add(pid, self._usefulness_loaded, data=(stdout, stderr))
71+ return True
72+ except Exception as e:
73+ LOG.warn("failed to launch: '%s' (error: '%s')" % (cmd, e))
74+ return False
75+
76+ def _usefulness_loaded(self, pid, status, (stdout, stderr)):
77+ '''called if usefulness retrieved from server'''
78+ LOG.debug("_usefulness_loaded started")
79+ # get status code
80+ res = os.WEXITSTATUS(status)
81+ # check stderr
82+ err = os.read(stderr, 4*1024)
83+ if err:
84+ LOG.warn("got error from helper: '%s'" % err)
85+ os.close(stderr)
86+ # read the raw data
87+ data = ""
88+ while True:
89+ s = os.read(stdout, 1024)
90+ if not s: break
91+ data += s
92+ os.close(stdout)
93+
94+ results = cPickle.loads(data)
95+ self.USEFULNESS_CACHE.clear()
96+ for result in results:
97+ self.USEFULNESS_CACHE[str(result['review_id'])] = result['useful']
98+ if not self.save_usefulness_cache_file():
99+ LOG.warn("Read usefulness results from server but failed to write to cache")
100
101 def save_usefulness_cache_file(self):
102 """write the dict out to cache file"""
103
104=== modified file 'softwarecenter/paths.py'
105--- softwarecenter/paths.py 2011-04-19 18:21:55 +0000
106+++ softwarecenter/paths.py 2011-05-01 07:52:26 +0000
107@@ -58,6 +58,7 @@
108 SUBMIT_USEFULNESS_APP = "submit_usefulness.py"
109 GET_REVIEWS_HELPER = "get_reviews_helper.py"
110 GET_REVIEW_STATS_HELPER = "get_review_stats_helper.py"
111+GET_USEFUL_VOTES_HELPER = "get_useful_votes_helper.py"
112
113 # there was a bug in maverick 3.0.3 (#652151) that could lead to a empty
114 # root owned directory in ~/.cache/software-center - we remove it here
115
116=== modified file 'softwarecenter/utils.py'
117--- softwarecenter/utils.py 2011-04-28 12:32:58 +0000
118+++ softwarecenter/utils.py 2011-05-01 07:52:26 +0000
119@@ -379,11 +379,16 @@
120 """
121 # FIXME: ideally this would be stored in ubuntu-sso-client
122 # but it dosn't so we store it here
123- config = get_config()
124- if not config.has_section("reviews"):
125- config.add_section("reviews")
126- config.set("reviews", "username", username)
127- config.write()
128+ curr_name = get_person_from_config()
129+ if curr_name != username:
130+ config = get_config()
131+ if not config.has_section("reviews"):
132+ config.add_section("reviews")
133+ config.set("reviews", "username", username)
134+ config.write()
135+ from db.reviews import UsefulnessCache
136+ usefulness = UsefulnessCache(True)
137+ return
138
139 def get_person_from_config():
140 """ get the username value for Ubuntu SSO from the config file
141
142=== added file 'utils/get_useful_votes_helper.py'
143--- utils/get_useful_votes_helper.py 1970-01-01 00:00:00 +0000
144+++ utils/get_useful_votes_helper.py 2011-05-01 07:52:26 +0000
145@@ -0,0 +1,45 @@
146+#!/usr/bin/python
147+
148+import pickle
149+import simplejson
150+import logging
151+
152+from optparse import OptionParser
153+from softwarecenter.backend.rnrclient import RatingsAndReviewsAPI
154+from piston_mini_client import APIError
155+
156+LOG = logging.getLogger(__name__)
157+
158+if __name__ == "__main__":
159+ logging.basicConfig()
160+
161+ # common options for optparse go here
162+ parser = OptionParser()
163+
164+ # check options
165+ parser.add_option("--username", default=None)
166+ (options, args) = parser.parse_args()
167+
168+ rnrclient = RatingsAndReviewsAPI()
169+
170+ useful_votes = []
171+
172+ if options.username:
173+ try:
174+ useful_votes = rnrclient.get_usefulness(username=options.username)
175+ except simplejson.decoder.JSONDecodeError, e:
176+ LOG.error("failed to parse '%s'" % e.doc)
177+ except APIError, e:
178+ LOG.warn("_get_useful_votes_helper: no usefulness able to be retrieved for username: %s" % (options.username))
179+ LOG.debug("_get_reviews_threaded: no reviews able to be retrieved: %s" % e)
180+ except:
181+ LOG.exception("_get_useful_votes_helper")
182+
183+ # print to stdout where its consumed by the parent
184+ try:
185+ print pickle.dumps(useful_votes)
186+ except IOError:
187+ # this can happen if the parent gets killed, no need to trigger
188+ # apport for this
189+ pass
190+
191
192=== modified file 'utils/submit_review.py'
193--- utils/submit_review.py 2011-04-29 15:00:11 +0000
194+++ utils/submit_review.py 2011-05-01 07:52:26 +0000
195@@ -1105,6 +1105,14 @@
196 def run(self):
197 self.login()
198
199+ # override UI update methods from BaseApp to prevent them
200+ # causing errors if called when UI is hidden
201+ def _clear_status_imagery(self):
202+ pass
203+
204+ def _change_status(self, type, message):
205+ pass
206+
207
208 if __name__ == "__main__":
209

Subscribers

People subscribed via source and target branches