diff -Nru software-center-5.1.13.2/data/expunge-cache.py software-center-5.1.14/data/expunge-cache.py --- software-center-5.1.13.2/data/expunge-cache.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/data/expunge-cache.py 2012-03-30 13:37:08.000000000 +0000 @@ -1,4 +1,21 @@ #!/usr/bin/python +# Copyright (C) 2012 Canonical +# +# Authors: +# Michael Vogt +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ Expunge httplib2 caches @@ -7,49 +24,10 @@ import argparse import logging import os -import time import sys +from softwarecenter.expunge import ExpungeCache -class ExpungeCache(object): - - def __init__(self, dirs, args): - self.dirs = dirs - # days to keep data in the cache (0 == disabled) - self.keep_time = 60 * 60 * 24 * args.by_days - self.keep_only_http200 = args.by_unsuccessful_http_states - self.dry_run = args.dry_run - - def _rm(self, f): - if self.dry_run: - print "Would delete: %s" % f - else: - logging.debug("Deleting: %s" % f) - try: - os.unlink(f) - except OSError as e: - logging.warn("When expunging the cache, could not unlink " - "file '%s' (%s)'" % (f, e)) - - def clean(self): - # go over the directories - now = time.time() - for d in self.dirs: - for root, dirs, files in os.walk(d): - for f in files: - fullpath = os.path.join(root, f) - header = open(fullpath).readline().strip() - if not header.startswith("status:"): - logging.debug( - "Skipping files with unknown header: '%s'" % f) - continue - if self.keep_only_http200 and header != "status: 200": - self._rm(fullpath) - if self.keep_time: - mtime = os.path.getmtime(fullpath) - logging.debug("mtime of '%s': '%s" % (f, mtime)) - if (mtime + self.keep_time) < now: - self._rm(fullpath) if __name__ == "__main__": parser = argparse.ArgumentParser( @@ -85,5 +63,8 @@ os.nice(19) # do it - cleaner = ExpungeCache(args.directories, args) + cleaner = ExpungeCache(args.directories, + args.by_days, + args.by_unsuccessful_http_states, + args.dry_run) cleaner.clean() diff -Nru software-center-5.1.13.2/data/piston_generic_helper.py software-center-5.1.14/data/piston_generic_helper.py --- software-center-5.1.13.2/data/piston_generic_helper.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/data/piston_generic_helper.py 2012-03-30 13:37:08.000000000 +0000 @@ -32,6 +32,7 @@ httplib2.debuglevel = 1 import piston_mini_client.auth +import piston_mini_client.failhandlers from piston_mini_client.failhandlers import APIError try: @@ -93,6 +94,11 @@ self.loop.quit() def verify_token_sync(self, token): + """ Verify that the token is valid + + Note that this may raise httplib2 exceptions if the server + is not reachable + """ LOG.debug("verify_token") auth = piston_mini_client.auth.OAuthAuthorizer( token["token"], token["token_secret"], @@ -100,10 +106,10 @@ api = UbuntuSsoAPI(auth=auth) try: res = api.whoami() - except: - LOG.exception("api.whoami failed") - return None - return res + except piston_mini_client.failhandlers.APIError as e: + LOG.exception("api.whoami failed with APIError: '%s'" % e) + return False + return len(res) > 0 def clear_token(self): clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING) @@ -124,10 +130,18 @@ def get_oauth_token_and_verify_sync(self): token = self.get_oauth_token_sync() # check if the token is valid and reset it if it is not - if token and not self.verify_token_sync(token): - self.clear_token() - # re-trigger login - token = self.get_oauth_token_sync() + if token: + # verify token will return false if there is a API error, + # but there maybe httplib2 errors if there is no network, + # so ignore them + try: + if not self.verify_token_sync(token): + self.clear_token() + # re-trigger login once + token = self.get_oauth_token_sync() + except Exception as e: + LOG.warn( + "token could not be verified (network problem?): %s" % e) return token diff -Nru software-center-5.1.13.2/debian/changelog software-center-5.1.14/debian/changelog --- software-center-5.1.13.2/debian/changelog 2012-03-26 17:02:24.000000000 +0000 +++ software-center-5.1.14/debian/changelog 2012-03-30 16:00:50.000000000 +0000 @@ -1,3 +1,48 @@ +software-center (5.1.14) precise; urgency=low + + [ Michael Vogt ] + * lp:~mvo/software-center/lp962580: + - add locking to the expunge helper process to fix bugs that are triggered + if multiple expunge cache processes are run (LP: #962580) + * lp:~mvo/software-center/cache-refresh-glitch: + - ensure that we get a full refresh if a pkg was not available before + show_app is called + * lp:~mvo/software-center/lp940482: + - fix crash if the debfile does not return proper utf8 for the + description (LP: #940482) + * lp:~mvo/software-center/lp966514: + - properly handle network disconnect conditions with the Ubuntu + SSO dialog (LP: #966514) + * lp:~mvo/software-center/lp966879: + - fix for crashes in the installed view treeview (LP: #966879, + LP: #950899) + * lp:~mvo/software-center/lp846204: + - fix ValueError crashes in get_iter due to invalid tree paths + (LP: #846204) + * lp:~mvo/software-center/lp964433: + - disconnect the model from the view before calling set_from_matches + (LP: #964433) + * lp:~mvo/software-center/treeview-keep-state-on-db-cache-change: + - restore the state of the installed view treeview when the + the db or cache changes, such as on an app install or remove + * lp:~mvo/software-center/946393: + - fix installing multiple apps when in a custom list view (LP: #946393) + * lp:~mvo/software-center/lp969050: + - disconnect the view when the model is cleared to avoid a furry of + cursor_changed signals as the rows get removed (LP: #969050) + + [ Gary Lasker ] + * lp:~gary-lasker/software-center/installed-pane-refresh: + - avoid rebuilding the treeview in the installedpane if its not + required (LP: #828887) + * lp:~gary-lasker/software-center/fix-crash-lp967036: + - Small branch to fix a crash due to a UnicodeDecodeError when accessing + the short description for H/W requirements (LP: #967036) + * lp:~gary-lasker/software-center/fix-crash-lp935930: + - fix a crash due to a UnicodeDecodeError (LP: #935930) + + -- Michael Vogt Fri, 30 Mar 2012 18:00:50 +0200 + software-center (5.1.13.2) precise; urgency=low [ kiwinote ] diff -Nru software-center-5.1.13.2/softwarecenter/backend/piston/sso_helper.py software-center-5.1.14/softwarecenter/backend/piston/sso_helper.py --- software-center-5.1.13.2/softwarecenter/backend/piston/sso_helper.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/backend/piston/sso_helper.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2012 Canonical -# -# Authors: -# Michael Vogt -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; version 3. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -from gi.repository import GObject -from gettext import gettext as _ - -from softwarecenter.backend.login_sso import get_sso_backend -from softwarecenter.backend.ubuntusso import UbuntuSSOAPI -from softwarecenter.enums import (SOFTWARE_CENTER_NAME_KEYRING, - SOFTWARE_CENTER_SSO_DESCRIPTION, - ) -from softwarecenter.utils import clear_token_from_ubuntu_sso - - -class SSOLoginHelper(object): - def __init__(self, xid=0): - self.oauth = None - self.xid = xid - self.loop = GObject.MainLoop(GObject.main_context_default()) - - def _login_successful(self, sso_backend, oauth_result): - self.oauth = oauth_result - # FIXME: actually verify the token against ubuntu SSO - self.loop.quit() - - def verify_token(self, token): - def _whoami_done(sso, me): - self._whoami = me - self.loop.quit() - - def _whoami_error(sso, err): - #print "ERRR", err - self.loop.quit() - self._whoami = None - sso = UbuntuSSOAPI() - sso.connect("whoami", _whoami_done) - sso.connect("error", _whoami_error) - sso.whoami() - self.loop.run() - # check if the token is valid - if self._whoami is None: - return False - else: - return True - - def clear_token(self): - clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING) - - def get_oauth_token_and_verify_sync(self): - token = self.get_oauth_token_sync() - # check if the token is valid and reset it if it is not - if token and not self.verify_token(token): - self.clear_token() - # re-trigger login - token = self.get_oauth_token_sync() - return token - - def get_oauth_token_sync(self): - self.oauth = None - sso = get_sso_backend( - self.xid, - SOFTWARE_CENTER_NAME_KEYRING, - _(SOFTWARE_CENTER_SSO_DESCRIPTION)) - sso.connect("login-successful", self._login_successful) - sso.connect("login-failed", lambda s: self.loop.quit()) - sso.connect("login-canceled", lambda s: self.loop.quit()) - sso.login_or_register() - self.loop.run() - return self.oauth diff -Nru software-center-5.1.13.2/softwarecenter/db/debfile.py software-center-5.1.14/softwarecenter/db/debfile.py --- software-center-5.1.13.2/softwarecenter/db/debfile.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/db/debfile.py 2012-03-30 13:37:08.000000000 +0000 @@ -104,7 +104,8 @@ def description(self): if self._deb: description = self._deb._sections["Description"] - return ('\n').join(description.split('\n')[1:]).replace(" .\n", "") + s = ('\n').join(description.split('\n')[1:]).replace(" .\n", "") + return utf8(s) return "" @property diff -Nru software-center-5.1.13.2/softwarecenter/distro/Debian.py software-center-5.1.14/softwarecenter/distro/Debian.py --- software-center-5.1.13.2/softwarecenter/distro/Debian.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/distro/Debian.py 2012-03-30 13:37:08.000000000 +0000 @@ -90,8 +90,6 @@ return apt.apt_pkg.config.find("Apt::Architecture") def get_foreign_architectures(self): - return [] - # Not yet in unstable import subprocess out = subprocess.Popen(['dpkg', '--print-foreign-architectures'], stdout=subprocess.PIPE).communicate()[0].rstrip('\n') diff -Nru software-center-5.1.13.2/softwarecenter/expunge.py software-center-5.1.14/softwarecenter/expunge.py --- software-center-5.1.13.2/softwarecenter/expunge.py 1970-01-01 00:00:00.000000000 +0000 +++ software-center-5.1.14/softwarecenter/expunge.py 2012-03-30 13:37:08.000000000 +0000 @@ -0,0 +1,79 @@ +# Copyright (C) 2009 Canonical +# +# Authors: +# Michael Vogt +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import logging +import os +import time + +from softwarecenter.utils import get_lock, release_lock + + +class ExpungeCache(object): + """ Expunge a httplib2 cache dir based on either age of the cache + file or status of the http data + """ + + def __init__(self, dirs, by_days, by_unsuccessful_http_states, + dry_run=False): + self.dirs = dirs + # days to keep data in the cache (0 == disabled) + self.keep_time = 60 * 60 * 24 * by_days + self.keep_only_http200 = by_unsuccessful_http_states + self.dry_run = dry_run + + def _rm(self, f): + if self.dry_run: + print "Would delete: %s" % f + else: + logging.debug("Deleting: %s" % f) + try: + os.unlink(f) + except OSError as e: + logging.warn("When expunging the cache, could not unlink " + "file '%s' (%s)'" % (f, e)) + + def _cleanup_dir(self, path): + """ cleanup the given directory (and subdirectories) using the + age or http state of the cache + """ + now = time.time() + for root, dirs, files in os.walk(path): + for f in files: + fullpath = os.path.join(root, f) + header = open(fullpath).readline().strip() + if not header.startswith("status:"): + logging.debug( + "Skipping files with unknown header: '%s'" % f) + continue + if self.keep_only_http200 and header != "status: 200": + self._rm(fullpath) + if self.keep_time: + mtime = os.path.getmtime(fullpath) + logging.debug("mtime of '%s': '%s" % (f, mtime)) + if (mtime + self.keep_time) < now: + self._rm(fullpath) + + def clean(self): + # go over the directories + for d in self.dirs: + lock = get_lock(os.path.join(d, "expunge.lock")) + if lock > 0: + self._cleanup_dir(d) + release_lock(lock) + else: + logging.info("dir '%s' locked by another process" % d) diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/models/appstore2.py software-center-5.1.14/softwarecenter/ui/gtk3/models/appstore2.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/models/appstore2.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/models/appstore2.py 2012-03-30 13:37:08.000000000 +0000 @@ -32,6 +32,7 @@ ExecutionTime, SimpleFileDownloader, split_icon_ext, + utf8, ) from softwarecenter.backend import get_install_backend from softwarecenter.backend.reviews import get_review_loader @@ -56,11 +57,14 @@ def __init__(self, untranslated_name, display_name, subcats, pkg_count): self.untranslated_name = untranslated_name - self.display_name = GObject.markup_escape_text(display_name) + self.display_name = GObject.markup_escape_text(utf8(display_name)) #self.subcategories = subcats self.pkg_count = pkg_count self.vis_count = pkg_count + def __repr__(self): + return "[CategoryRowReference: name=%s]" % self.untranslated_name + class UncategorisedRowRef(CategoryRowReference): @@ -75,6 +79,9 @@ display_name, None, pkg_count) + def __repr__(self): + return "[UncategorizedRowReference: name=%s]" % self.untranslated_name + class AppPropertiesHelper(GObject.GObject): """ Baseclass that contains common functions for our @@ -409,6 +416,7 @@ """ set the content of the liststore based on a list of xapian.MSetItems """ + LOG.debug("set_from_matches len(matches)='%s'" % len(matches)) self.current_matches = matches n_matches = len(matches) if n_matches == 0: @@ -432,6 +440,7 @@ self.buffer_icons() def load_range(self, indices, step): + LOG.debug("load_range: %s %s" % (indices, step)) db = self.db.xapiandb matches = self.current_matches @@ -446,7 +455,8 @@ for i in range(start, end): try: row_content = self[(i,)][0] - except IndexError: + except IndexError as e: + LOG.warn("failed to load rows: '%s'" % e) break if row_content: diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/availablepane.py software-center-5.1.14/softwarecenter/ui/gtk3/panes/availablepane.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/availablepane.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/panes/availablepane.py 2012-03-30 13:37:08.000000000 +0000 @@ -487,8 +487,7 @@ ''' Function that installs all applications displayed in the pane. ''' - pkgnames = [] - appnames = [] + apps = [] iconnames = [] self.action_bar.remove_button(ActionButtons.INSTALL) for doc in self.enquirer.get_documents(): @@ -496,11 +495,10 @@ if (pkgname in self.cache and not self.cache[pkgname].is_installed and pkgname not in self.backend.pending_transactions): - pkgnames.append(pkgname) - appnames.append(self.db.get_appname(doc)) + apps.append(self.db.get_application(doc)) # add iconnames iconnames.append(self.db.get_iconname(doc)) - self.backend.install_multiple(pkgnames, appnames, iconnames) + self.backend.install_multiple(apps, iconnames) def set_state(self, nav_item): pass diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/installedpane.py software-center-5.1.14/softwarecenter/ui/gtk3/panes/installedpane.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/installedpane.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/panes/installedpane.py 2012-03-30 13:37:08.000000000 +0000 @@ -226,6 +226,9 @@ self.hide_appview_spinner() + # keep track of the current view by tracking its origin + self.current_displayed_origin = None + # now we are initialized self.emit("installed-pane-created") @@ -322,8 +325,25 @@ self.nonapps_visible = NonAppVisibility.NEVER_VISIBLE self.refresh_apps() + def _save_treeview_state(self): + # store the state + expanded_rows = [] + self.app_view.tree_view.map_expanded_rows( + lambda view, path, data: expanded_rows.append(path.to_string()), + None) + vadj = self.app_view.tree_view_scroll.get_vadjustment().get_value() + return expanded_rows, vadj + + def _restore_treeview_state(self, state): + expanded_rows, vadj = state + for ind in expanded_rows: + path = Gtk.TreePath.new_from_string(ind) + self.app_view.tree_view.expand_row(path, False) + self.app_view.tree_view_scroll.get_vadjustment().set_lower(vadj) + self.app_view.tree_view_scroll.get_vadjustment().set_value(vadj) + #~ @interrupt_build_and_wait - def _build_categorised_installedview(self): + def _build_categorised_installedview(self, keep_state=False): LOG.debug('Rebuilding categorised installedview...') # display the busy cursor and a local spinner while we build the view @@ -332,6 +352,13 @@ window.set_cursor(self.busy_cursor) self.show_installed_view_spinner() + if keep_state: + treeview_state = self._save_treeview_state() + + # disconnect the model to avoid e.g. updates of "cursor-changed" + # AppTreeView.expand_path while the model is in rebuild-flux + self.app_view.set_model(None) + model = self.base_model # base model not treefilter model.clear() @@ -407,6 +434,10 @@ self.app_view._append_appcount(self.installed_count, mode=AppView.INSTALLED_MODE) + self.app_view.set_model(self.treefilter) + if keep_state: + self._restore_treeview_state(treeview_state) + # hide the local spinner self.hide_installed_view_spinner() @@ -422,7 +453,7 @@ GObject.idle_add(profiled_rebuild_categorised_view) - def _build_oneconfview(self): + def _build_oneconfview(self, keep_state=False): LOG.debug('Rebuilding oneconfview for %s...' % self.current_hostid) # display the busy cursor and the local spinner while we build the view @@ -431,6 +462,13 @@ window.set_cursor(self.busy_cursor) self.show_installed_view_spinner() + if keep_state: + treeview_state = self._save_treeview_state() + + # disconnect the model to avoid e.g. updates of "cursor-changed" + # AppTreeView.expand_path while the model is in rebuild-flux + self.app_view.set_model(None) + model = self.base_model # base model not treefilter model.clear() @@ -515,6 +553,10 @@ self.app_view._append_appcount(self.installed_count, mode=AppView.DIFF_MODE) + self.app_view.set_model(self.treefilter) + if keep_state: + self._restore_treeview_state(treeview_state) + # hide the local spinner self.hide_installed_view_spinner() @@ -596,10 +638,11 @@ def refresh_apps(self, *args, **kwargs): """refresh the applist and update the navigation bar """ logging.debug("installedpane refresh_apps") + keep_state = kwargs.get("keep_state", False) if self.current_hostid: - self._build_oneconfview() + self._build_oneconfview(keep_state) else: - self._build_categorised_installedview() + self._build_categorised_installedview(keep_state) def _clear_search(self): # remove the details and clear the search @@ -626,10 +669,18 @@ self.app_view._append_appcount(appcount, mode=AppView.DIFF_MODE) return vis_cats - def on_db_reopen(self, db): - self.refresh_apps(rebuild=True) + def _refresh_on_cache_or_db_change(self): + self.refresh_apps(keep_state=True) self.app_details_view.refresh_app() + def on_db_reopen(self, db): + LOG.debug("on_db_reopen") + self._refresh_on_cache_or_db_change() + + def on_cache_ready(self, cache): + LOG.debug("on_cache_ready") + self._refresh_on_cache_or_db_change() + def on_application_selected(self, appview, app): """callback when an app is selected""" logging.debug("on_application_selected: '%s'" % app) @@ -655,11 +706,19 @@ if self.state.search_term: self._search() self._build_oneconfview() - else: + elif (view_state and + view_state.channel and + view_state.channel.origin is not self.current_displayed_origin): + # we don't need to refresh the full installed view every time it + # is displayed, so we check to see if we are viewing the same + # channel and if so we don't refresh the view, note that the view + # *is* is refreshed whenever the contents change and this is + # sufficient (see LP: #828887) self._build_categorised_installedview() + self.current_displayed_origin = view_state.channel.origin - if self.state.search_term: - self._search(self.state.search_term) + if self.state.search_term: + self._search(self.state.search_term) return True def get_current_app(self): @@ -709,8 +768,11 @@ w.init_view() from softwarecenter.backend.channel import AllInstalledChannel + from softwarecenter.ui.gtk3.panes.softwarepane import DisplayState w.state.channel = AllInstalledChannel() - w.display_overview_page(None, None) + view_state = DisplayState() + view_state.channel = AllInstalledChannel() + w.display_overview_page(None, view_state) win.show() return win diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/softwarepane.py software-center-5.1.14/softwarecenter/ui/gtk3/panes/softwarepane.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/softwarepane.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/panes/softwarepane.py 2012-03-30 16:00:28.000000000 +0000 @@ -254,15 +254,6 @@ def on_cache_ready(self, cache): " refresh the application list when the cache is re-opened " LOG.debug("on_cache_ready") - # it only makes sense to refresh if there is something to - # refresh, otherwise we create a bunch of (not yet needed) - # AppStore objects on startup when the cache sends its - # initial "cache-ready" signal - model = self.app_view.tree_view.get_model() - if model is None: - return - # FIXME: preserve selection too - self.refresh_apps() @wait_for_apt_cache_ready def on_application_activated(self, appview, app): diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/views/appdetailsview.py software-center-5.1.14/softwarecenter/ui/gtk3/views/appdetailsview.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/views/appdetailsview.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/views/appdetailsview.py 2012-03-30 13:37:08.000000000 +0000 @@ -1715,10 +1715,13 @@ # check if app just became available and if so, force full # refresh - if (same_app and - self.pkg_state == PkgStates.NEEDS_SOURCE and - self.app_details.pkg_state != PkgStates.NEEDS_SOURCE): - force = True + if same_app: + # if the app was in one of the states, force refresh if its + # no longer in this state + for state in [PkgStates.NEEDS_SOURCE, PkgStates.NOT_FOUND]: + if (self.pkg_state == state and + self.app_details.pkg_state != state): + force = True self.pkg_state = self.app_details.pkg_state # for compat with the base class diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/views/appview.py software-center-5.1.14/softwarecenter/ui/gtk3/views/appview.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/views/appview.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/views/appview.py 2012-03-30 16:00:28.000000000 +0000 @@ -176,13 +176,16 @@ def set_model(self, model): self.tree_view.set_model(model) + def get_model(self): + return self.tree_view.appmodel + def display_matches(self, matches, is_search=False): # FIXME: installedpane handles display of the trees intimately, # so for the time being lets just return None in the case of our # TreeView displaying an AppTreeStore ... ;( # ... also we dont currently support user sorting in the # installedview, so issue is somewhat moot for the time being... - if isinstance(self.tree_view.appmodel, AppTreeStore): + if isinstance(self.get_model(), AppTreeStore): LOG.debug("display_matches called on AppTreeStore, ignoring") return @@ -197,9 +200,16 @@ not self.user_defined_sort_method): self.set_sort_method_with_no_signal(self._SORT_BY_TOP_RATED) - model = self.tree_view.appmodel + model = self.get_model() + # disconnect the model from the view before running + # set_from_matches to ensure that the _cell_data_func_cb is not + # run when the placeholder items are set, otherwise the purpose + # of the "load-on-demand" is gone and it leads to bugs like + # LP: #964433 + self.set_model(None) if model: model.set_from_matches(matches) + self.set_model(model) self.user_defined_sort_method = False self.tree_view_scroll.get_vadjustment().set_lower(self.vadj) diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/apptreeview.py software-center-5.1.14/softwarecenter/ui/gtk3/widgets/apptreeview.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/apptreeview.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/widgets/apptreeview.py 2012-03-30 13:37:08.000000000 +0000 @@ -20,6 +20,9 @@ AppGenericStore, CategoryRowReference) +LOG = logging.getLogger(__name__) + + class AppTreeView(Gtk.TreeView): """Treeview based view component that takes a AppStore and displays it""" @@ -131,7 +134,14 @@ self.expanded_path = None self._needs_collapse = [] if self.appmodel: - self.appmodel.clear() + # before clearing the model, disconnect it from the view. this + # avoids that the model gets a "cursor_changed" signal for each + # removed row and consequently that _update_selected_row is called + # for rows that are not really selected (LP: #969050) + model = self.get_model() + self.set_model(None) + model.clear() + self.set_model(model) def expand_path(self, path): if path is not None and not isinstance(path, Gtk.TreePath): @@ -144,16 +154,16 @@ if old is not None: start, end = self.get_visible_range() or (None, None) - if (start and start.compare(old) != -1) or \ - (end and end.compare(old) != 1): + if ((start and start.compare(old) != -1) or + (end and end.compare(old) != 1)): self._needs_collapse.append(old) else: try: # try... a lazy solution to Bug #846204 model.row_changed(old, model.get_iter(old)) except: - msg = ("apptreeview.expand_path: Supplied 'old' " - "path is an invalid tree path: '%s'" % old) - logging.debug(msg) + LOG.exception( + "apptreeview.expand_path: Supplied 'old' " + "path is an invalid tree path: '%s'" % old) if path == None: return @@ -485,13 +495,8 @@ path) def _cell_data_func_cb(self, col, cell, model, it, user_data): - path = model.get_path(it) - # this will give us the right underlying model regardless if its - # a TreeModelFilter, a AppTreeStore or a AppListStore - model = self.appmodel - # this will pre-load data *only* on a AppListStore, it has # no effect with a AppTreeStore if model[path][0] is None: diff -Nru software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/labels.py software-center-5.1.14/softwarecenter/ui/gtk3/widgets/labels.py --- software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/labels.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/gtk3/widgets/labels.py 2012-03-30 13:37:08.000000000 +0000 @@ -20,6 +20,7 @@ from gettext import gettext as _ from softwarecenter.hw import get_hw_short_description +from softwarecenter.utils import utf8 class HardwareRequirementsLabel(Gtk.HBox): @@ -70,7 +71,7 @@ s = self.LABEL return _(s) % { "sym": sym, - "hardware": _(get_hw_short_description(self.tag)) + "hardware": _(utf8(get_hw_short_description(self.tag))) } def set_hardware_requirement(self, tag, result): diff -Nru software-center-5.1.13.2/softwarecenter/ui/qml/pkglist.py software-center-5.1.14/softwarecenter/ui/qml/pkglist.py --- software-center-5.1.13.2/softwarecenter/ui/qml/pkglist.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/ui/qml/pkglist.py 2012-03-30 13:37:08.000000000 +0000 @@ -146,13 +146,15 @@ def installPackage(self, pkgname): appname = "" iconname = "" - self.backend.install(pkgname, appname, iconname) + app = Application(appname, pkgname) + self.backend.install(app, iconname) @pyqtSlot(str) def removePackage(self, pkgname): appname = "" iconname = "" - self.backend.remove(pkgname, appname, iconname) + app = Application(appname, pkgname) + self.backend.remove(app, iconname) # searchQuery property (for qml ) def getSearchQuery(self): diff -Nru software-center-5.1.13.2/softwarecenter/utils.py software-center-5.1.14/softwarecenter/utils.py --- software-center-5.1.13.2/softwarecenter/utils.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/utils.py 2012-03-30 13:37:08.000000000 +0000 @@ -628,6 +628,23 @@ return str(uuid.uuid4()) +def get_lock(path): + """ return a lock that can be released with release_lock on success + and -1 on failure + """ + try: + import apt_pkg + return apt_pkg.get_lock(path, False) + except ImportError: + # implement me on non-apt system, I wish python had this in the stdlib + pass + + +def release_lock(lock): + """ release a lock acquired with get_lock """ + os.close(lock) + + class SimpleFileDownloader(GObject.GObject): LOG = logging.getLogger("softwarecenter.simplefiledownloader") diff -Nru software-center-5.1.13.2/softwarecenter/version.py software-center-5.1.14/softwarecenter/version.py --- software-center-5.1.13.2/softwarecenter/version.py 2012-03-26 17:14:45.000000000 +0000 +++ software-center-5.1.14/softwarecenter/version.py 2012-03-30 16:13:14.000000000 +0000 @@ -1,5 +1,5 @@ -VERSION='5.1.13.2' +VERSION='5.1.14' CODENAME='precise' DISTRO='Ubuntu' RELEASE='12.04' diff -Nru software-center-5.1.13.2/test/coverage_summary software-center-5.1.14/test/coverage_summary --- software-center-5.1.13.2/test/coverage_summary 2012-03-26 17:14:35.000000000 +0000 +++ software-center-5.1.14/test/coverage_summary 2012-03-30 16:13:05.000000000 +0000 @@ -1,194 +1,195 @@ -Name Stmts Miss Cover ----------------------------------------------------------------------------------------------------------------------------------------------- -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/__init__ 2 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/channel 181 19 90% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/channel_impl/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/channel_impl/aptchannels 144 49 66% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/fake_review_settings 76 33 57% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/installbackend 36 14 61% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/installbackend_impl/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/installbackend_impl/aptd 490 307 37% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/launchpad 184 112 39% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/login 9 2 78% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/login_sso 96 32 67% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/oneconfhandler/__init__ 17 5 71% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/oneconfhandler/core 97 14 86% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/piston/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/piston/rnrclient 44 29 34% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/piston/rnrclient_fake 147 80 46% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/piston/rnrclient_pristine 80 26 68% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/recagent 121 42 65% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/reviews/__init__ 360 129 64% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/reviews/rnr 205 100 51% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/scagent 78 22 72% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/spawn_helper 88 14 84% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/transactionswatcher 50 19 62% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/ubuntusso 75 38 49% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/unitylauncher 26 11 58% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/weblive 168 104 38% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/backend/weblive_pristine 147 101 31% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/cmdfinder 31 3 90% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/config 28 9 68% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/__init__ 8 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/appfilter 67 11 84% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/application 518 124 76% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/categories 310 36 88% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/database 350 88 75% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/debfile 124 35 72% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/enquire 146 6 96% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/history 36 13 64% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/history_impl/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/history_impl/apthistory 132 33 75% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/pkginfo 107 35 67% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/pkginfo_impl/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/pkginfo_impl/aptcache 521 148 72% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/update 657 62 91% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/db/utils 23 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/distro/Debian 87 65 25% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/distro/Ubuntu 125 51 59% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/distro/__init__ 90 43 52% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/enums 121 8 93% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/gwibber_helper 64 22 66% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/hw 40 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/i18n 46 4 91% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/log 62 14 77% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/netstatus 88 18 80% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/paths 43 8 81% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/plugin 62 4 94% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/region 79 5 94% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/testutils 115 4 97% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/SimpleGtkbuilderApp 18 5 72% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/app 710 352 50% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/aptd_gtk3 44 36 18% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/dialogs/__init__ 80 28 65% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/dialogs/deauthorize_dialog 79 67 15% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/dialogs/dependency_dialogs 79 19 76% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/dialogs/dialog_tos 50 5 90% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/drawing 66 32 52% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/em 33 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/gmenusearch 80 35 56% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/models/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/models/appstore2 267 41 85% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/models/pendingstore 111 65 41% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/availablepane 425 138 68% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/basepane 15 5 67% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/globalpane 58 4 93% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/historypane 252 23 91% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/installedpane 418 120 71% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/pendingpane 95 28 71% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/softwarepane 290 72 75% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/panes/viewswitcher 168 65 61% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/review_gui_helper 794 311 61% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/session/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/session/appmanager 89 12 87% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/session/navhistory 164 17 90% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/session/viewmanager 125 28 78% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/utils 65 12 82% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/appdetailsview 1266 187 85% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/appview 185 31 83% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/catview_gtk 446 61 86% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/pkgnamesview 64 8 88% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/purchaseview 205 83 60% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/views/webkit 60 29 52% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/actionbar 223 79 65% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/apptreeview 438 226 48% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/backforward 101 20 80% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/buttons 410 66 84% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/cellrenderers 308 49 84% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/containers 378 24 94% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/description 791 424 46% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/exhibits 373 59 84% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/imagedialog 35 3 91% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/labels 58 11 81% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/menubutton 64 45 30% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/oneconfviews 98 45 54% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/recommendations 184 36 80% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/reviews 578 112 81% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/searchaid 179 61 66% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/searchentry 89 25 72% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/separators 26 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/spinner 64 2 97% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/stars 362 44 88% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/symbolic_icons 149 10 93% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/thumbnail 340 59 83% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/videoplayer 110 56 49% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/viewport 24 15 38% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/gtk3/widgets/weblivedialog 68 58 15% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/qml/__init__ 0 0 100% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/qml/categoriesmodel 53 21 60% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/qml/pkglist 132 64 52% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/ui/qml/reviewslist 46 3 93% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/utils 428 106 75% -/home/egon/devel/software-center/build-area/software-center-5.1.13.2/softwarecenter/version 4 0 100% -__init__ 0 0 100% -data/plugins/mock_plugin 4 0 100% -gtk3/test_app_view 61 0 100% -gtk3/test_appdetailsview 332 5 98% -gtk3/test_appmanager 51 0 100% -gtk3/test_appstore2 35 0 100% -gtk3/test_catview 172 0 100% -gtk3/test_custom_lists 38 0 100% -gtk3/test_debfile_view 27 0 100% -gtk3/test_dialogs 31 0 100% -gtk3/test_globalpane 13 0 100% -gtk3/test_install_progress 32 0 100% -gtk3/test_installedpane 40 0 100% -gtk3/test_navhistory 135 0 100% -gtk3/test_panes 42 0 100% -gtk3/test_purchase 77 0 100% -gtk3/test_recommendations_widgets 24 0 100% -gtk3/test_reviews 129 2 98% -gtk3/test_search 48 0 100% -gtk3/test_unity_launcher_integration 84 0 100% -gtk3/test_views 40 0 100% -gtk3/test_widgets 161 1 99% -qml/test_ui_qml_helpers 78 0 100% -test_addons 30 0 100% -test_aptd 72 28 61% -test_apthistory 71 1 99% -test_categories 64 0 100% -test_channels 25 0 100% -test_cmdfiner 20 0 100% -test_database 398 1 99% -test_debfileapplication 67 1 99% -test_description_norm 35 0 100% -test_distro 20 0 100% -test_downloader 49 0 100% -test_enquire 28 2 93% -test_gwibber 34 7 79% -test_htmlize 21 0 100% -test_hw 22 0 100% -test_i18n 36 0 100% -test_launchpad 31 1 97% -test_login_backend 19 0 100% -test_mime 25 0 100% -test_netstatus 16 0 100% -test_origin 22 0 100% -test_package_info 59 0 100% -test_pep8 39 1 97% -test_pkginfo 36 1 97% -test_plugin 18 0 100% -test_ppa_iconfilename 41 1 98% -test_purchase_backend 47 23 51% -test_pyflakes 9 0 100% -test_recagent 102 26 75% -test_region 46 0 100% -test_reinstall_purchased 140 0 100% -test_rnr_api 14 0 100% -test_scagent 40 2 95% -test_spawn_helper 17 0 100% -test_startup 39 24 38% -test_testutils 37 0 100% -test_ubuntu_sso_api 19 0 100% -test_utils 104 11 89% -test_where_is_it 51 9 82% -test_xapian 71 1 99% -test_xapian_query 53 1 98% ----------------------------------------------------------------------------------------------------------------------------------------------- -TOTAL 23656 5942 75% +Name Stmts Miss Cover +-------------------------------------------------------------------------------------------------------------------------------------------- +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/__init__ 2 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/channel 181 19 90% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/channel_impl/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/channel_impl/aptchannels 144 49 66% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/fake_review_settings 76 33 57% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/installbackend 36 14 61% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/installbackend_impl/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/installbackend_impl/aptd 490 307 37% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/launchpad 184 112 39% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/login 9 2 78% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/login_sso 96 32 67% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/oneconfhandler/__init__ 17 5 71% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/oneconfhandler/core 97 14 86% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/piston/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/piston/rnrclient 44 29 34% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/piston/rnrclient_fake 147 80 46% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/piston/rnrclient_pristine 80 26 68% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/recagent 121 41 66% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/reviews/__init__ 360 142 61% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/reviews/rnr 205 100 51% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/scagent 78 22 72% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/spawn_helper 88 14 84% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/transactionswatcher 50 19 62% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/ubuntusso 75 38 49% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/unitylauncher 26 11 58% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/weblive 168 104 38% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/backend/weblive_pristine 147 101 31% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/cmdfinder 31 3 90% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/config 28 9 68% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/__init__ 8 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/appfilter 67 11 84% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/application 518 124 76% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/categories 310 36 88% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/database 350 88 75% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/debfile 125 35 72% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/enquire 146 6 96% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/history 36 13 64% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/history_impl/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/history_impl/apthistory 132 33 75% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/pkginfo 107 35 67% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/pkginfo_impl/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/pkginfo_impl/aptcache 521 148 72% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/update 657 62 91% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/db/utils 23 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/distro/Debian 86 61 29% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/distro/Ubuntu 125 51 59% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/distro/__init__ 90 43 52% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/enums 121 8 93% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/expunge 41 28 32% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/gwibber_helper 64 22 66% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/hw 40 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/i18n 46 4 91% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/log 62 14 77% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/netstatus 88 18 80% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/paths 43 8 81% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/plugin 62 4 94% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/region 79 5 94% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/testutils 115 4 97% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/SimpleGtkbuilderApp 18 5 72% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/app 710 356 50% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/aptd_gtk3 44 36 18% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/dialogs/__init__ 80 28 65% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/dialogs/deauthorize_dialog 79 67 15% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/dialogs/dependency_dialogs 79 19 76% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/dialogs/dialog_tos 50 5 90% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/drawing 66 32 52% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/em 33 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/gmenusearch 80 35 56% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/models/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/models/appstore2 274 29 89% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/models/pendingstore 111 65 41% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/availablepane 423 137 68% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/basepane 15 5 67% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/globalpane 58 4 93% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/historypane 252 19 92% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/installedpane 455 142 69% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/pendingpane 95 28 71% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/softwarepane 286 68 76% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/panes/viewswitcher 168 65 61% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/review_gui_helper 794 311 61% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/session/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/session/appmanager 89 12 87% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/session/navhistory 164 17 90% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/session/viewmanager 125 28 78% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/utils 65 12 82% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/appdetailsview 1268 188 85% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/appview 189 31 84% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/catview_gtk 446 61 86% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/pkgnamesview 64 8 88% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/purchaseview 205 83 60% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/views/webkit 60 29 52% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/actionbar 223 79 65% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/apptreeview 440 228 48% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/backforward 101 20 80% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/buttons 410 64 84% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/cellrenderers 308 49 84% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/containers 378 24 94% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/description 791 424 46% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/exhibits 373 63 83% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/imagedialog 35 3 91% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/labels 59 11 81% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/menubutton 64 45 30% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/oneconfviews 98 45 54% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/recommendations 184 36 80% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/reviews 578 112 81% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/searchaid 179 61 66% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/searchentry 89 25 72% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/separators 26 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/spinner 64 2 97% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/stars 362 44 88% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/symbolic_icons 149 10 93% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/thumbnail 340 59 83% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/videoplayer 110 56 49% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/viewport 24 15 38% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/gtk3/widgets/weblivedialog 68 58 15% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/qml/__init__ 0 0 100% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/qml/categoriesmodel 53 21 60% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/qml/pkglist 134 66 51% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/ui/qml/reviewslist 46 3 93% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/utils 436 112 74% +/home/egon/devel/software-center/build-area/software-center-5.1.14/softwarecenter/version 4 0 100% +__init__ 0 0 100% +data/plugins/mock_plugin 4 0 100% +gtk3/test_app_view 61 0 100% +gtk3/test_appdetailsview 332 5 98% +gtk3/test_appmanager 51 0 100% +gtk3/test_appstore2 35 0 100% +gtk3/test_catview 172 0 100% +gtk3/test_custom_lists 38 0 100% +gtk3/test_debfile_view 27 0 100% +gtk3/test_dialogs 31 0 100% +gtk3/test_globalpane 13 0 100% +gtk3/test_install_progress 32 0 100% +gtk3/test_installedpane 40 0 100% +gtk3/test_navhistory 135 0 100% +gtk3/test_panes 42 0 100% +gtk3/test_purchase 77 0 100% +gtk3/test_recommendations_widgets 24 0 100% +gtk3/test_reviews 129 2 98% +gtk3/test_search 48 0 100% +gtk3/test_unity_launcher_integration 84 0 100% +gtk3/test_views 40 0 100% +gtk3/test_widgets 161 1 99% +qml/test_ui_qml_helpers 78 0 100% +test_addons 30 0 100% +test_aptd 72 28 61% +test_apthistory 71 1 99% +test_categories 64 0 100% +test_channels 25 0 100% +test_cmdfiner 20 0 100% +test_database 398 1 99% +test_debfileapplication 67 1 99% +test_description_norm 35 0 100% +test_distro 20 0 100% +test_downloader 49 0 100% +test_enquire 28 2 93% +test_gwibber 34 7 79% +test_htmlize 21 0 100% +test_hw 22 0 100% +test_i18n 36 0 100% +test_launchpad 31 1 97% +test_login_backend 19 0 100% +test_mime 25 0 100% +test_netstatus 16 0 100% +test_origin 22 0 100% +test_package_info 59 0 100% +test_pep8 39 1 97% +test_pkginfo 36 1 97% +test_plugin 18 0 100% +test_ppa_iconfilename 41 1 98% +test_purchase_backend 47 23 51% +test_pyflakes 9 0 100% +test_recagent 102 26 75% +test_region 46 0 100% +test_reinstall_purchased 140 0 100% +test_rnr_api 14 0 100% +test_scagent 40 2 95% +test_spawn_helper 17 0 100% +test_startup 39 24 38% +test_testutils 37 0 100% +test_ubuntu_sso_api 19 0 100% +test_utils 125 14 89% +test_where_is_it 51 9 82% +test_xapian 71 1 99% +test_xapian_query 53 1 98% +-------------------------------------------------------------------------------------------------------------------------------------------- +TOTAL 23775 5999 75% diff -Nru software-center-5.1.13.2/test/test_utils.py software-center-5.1.14/test/test_utils.py --- software-center-5.1.13.2/test/test_utils.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/test/test_utils.py 2012-03-30 13:37:08.000000000 +0000 @@ -1,7 +1,12 @@ #!/usr/bin/python -import os import datetime +import glob +import multiprocessing +import os +import subprocess +import tempfile +import time import unittest from testutils import setup_test_env @@ -152,8 +157,6 @@ class TestExpungeCache(unittest.TestCase): def test_expunge_cache(self): - import subprocess - import tempfile dirname = tempfile.mkdtemp('s-c-testsuite') for name, content in [ ("foo-301", "status: 301"), ("foo-200", "status: 200"), @@ -185,6 +188,28 @@ self.assertFalse(os.path.exists(os.path.join(dirname, "foo-200"))) self.assertTrue(os.path.exists(os.path.join(dirname, "foo-random"))) + def test_expunge_cache_lock(self): + def set_marker(d): + time.sleep(0.5) + target = os.path.join(d, "marker.%s." % os.getpid()) + open(target, "w") + from softwarecenter.expunge import ExpungeCache + tmpdir = tempfile.mkdtemp() + # create two ExpungeCache processes + e1 = ExpungeCache([tmpdir], by_days=0, by_unsuccessful_http_states=True) + e1._cleanup_dir = set_marker + e2 = ExpungeCache([tmpdir], by_days=0, by_unsuccessful_http_states=True) + e2._cleanup_dir = set_marker + t1 = multiprocessing.Process(target=e1.clean) + t1.start() + t2 = multiprocessing.Process(target=e2.clean) + t2.start() + # wait for finish + t1.join() + t2.join() + # ensure that the second one was not called + self.assertEqual(len(glob.glob(os.path.join(tmpdir, "marker.*"))), 1) + if __name__ == "__main__": diff -Nru software-center-5.1.13.2/utils/expunge-cache.py software-center-5.1.14/utils/expunge-cache.py --- software-center-5.1.13.2/utils/expunge-cache.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/utils/expunge-cache.py 2012-03-30 13:37:08.000000000 +0000 @@ -1,4 +1,21 @@ #!/usr/bin/python +# Copyright (C) 2012 Canonical +# +# Authors: +# Michael Vogt +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; version 3. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ Expunge httplib2 caches @@ -7,49 +24,10 @@ import argparse import logging import os -import time import sys +from softwarecenter.expunge import ExpungeCache -class ExpungeCache(object): - - def __init__(self, dirs, args): - self.dirs = dirs - # days to keep data in the cache (0 == disabled) - self.keep_time = 60 * 60 * 24 * args.by_days - self.keep_only_http200 = args.by_unsuccessful_http_states - self.dry_run = args.dry_run - - def _rm(self, f): - if self.dry_run: - print "Would delete: %s" % f - else: - logging.debug("Deleting: %s" % f) - try: - os.unlink(f) - except OSError as e: - logging.warn("When expunging the cache, could not unlink " - "file '%s' (%s)'" % (f, e)) - - def clean(self): - # go over the directories - now = time.time() - for d in self.dirs: - for root, dirs, files in os.walk(d): - for f in files: - fullpath = os.path.join(root, f) - header = open(fullpath).readline().strip() - if not header.startswith("status:"): - logging.debug( - "Skipping files with unknown header: '%s'" % f) - continue - if self.keep_only_http200 and header != "status: 200": - self._rm(fullpath) - if self.keep_time: - mtime = os.path.getmtime(fullpath) - logging.debug("mtime of '%s': '%s" % (f, mtime)) - if (mtime + self.keep_time) < now: - self._rm(fullpath) if __name__ == "__main__": parser = argparse.ArgumentParser( @@ -85,5 +63,8 @@ os.nice(19) # do it - cleaner = ExpungeCache(args.directories, args) + cleaner = ExpungeCache(args.directories, + args.by_days, + args.by_unsuccessful_http_states, + args.dry_run) cleaner.clean() diff -Nru software-center-5.1.13.2/utils/piston-helpers/piston_generic_helper.py software-center-5.1.14/utils/piston-helpers/piston_generic_helper.py --- software-center-5.1.13.2/utils/piston-helpers/piston_generic_helper.py 2012-03-23 13:54:45.000000000 +0000 +++ software-center-5.1.14/utils/piston-helpers/piston_generic_helper.py 2012-03-30 13:37:08.000000000 +0000 @@ -32,6 +32,7 @@ httplib2.debuglevel = 1 import piston_mini_client.auth +import piston_mini_client.failhandlers from piston_mini_client.failhandlers import APIError try: @@ -93,6 +94,11 @@ self.loop.quit() def verify_token_sync(self, token): + """ Verify that the token is valid + + Note that this may raise httplib2 exceptions if the server + is not reachable + """ LOG.debug("verify_token") auth = piston_mini_client.auth.OAuthAuthorizer( token["token"], token["token_secret"], @@ -100,10 +106,10 @@ api = UbuntuSsoAPI(auth=auth) try: res = api.whoami() - except: - LOG.exception("api.whoami failed") - return None - return res + except piston_mini_client.failhandlers.APIError as e: + LOG.exception("api.whoami failed with APIError: '%s'" % e) + return False + return len(res) > 0 def clear_token(self): clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING) @@ -124,10 +130,18 @@ def get_oauth_token_and_verify_sync(self): token = self.get_oauth_token_sync() # check if the token is valid and reset it if it is not - if token and not self.verify_token_sync(token): - self.clear_token() - # re-trigger login - token = self.get_oauth_token_sync() + if token: + # verify token will return false if there is a API error, + # but there maybe httplib2 errors if there is no network, + # so ignore them + try: + if not self.verify_token_sync(token): + self.clear_token() + # re-trigger login once + token = self.get_oauth_token_sync() + except Exception as e: + LOG.warn( + "token could not be verified (network problem?): %s" % e) return token