Merge lp:~elachuni/software-center/pep8-test-part16 into lp:software-center

Proposed by Anthony Lenton
Status: Merged
Merged at revision: 2862
Proposed branch: lp:~elachuni/software-center/pep8-test-part16
Merge into: lp:software-center
Prerequisite: lp:~elachuni/software-center/pep8-test-part15
Diff against target: 1252 lines (+267/-159)
6 files modified
softwarecenter/db/history_impl/apthistory.py (+22/-19)
softwarecenter/db/history_impl/packagekit.py (+11/-7)
softwarecenter/db/pkginfo.py (+57/-18)
softwarecenter/db/update.py (+164/-104)
softwarecenter/db/utils.py (+7/-4)
test/test_pep8.py (+6/-7)
To merge this branch: bzr merge lp:~elachuni/software-center/pep8-test-part16
Reviewer Review Type Date Requested Status
software-store-developers Pending
Review via email: mp+97568@code.launchpad.net

Description of the change

Made several files under softwarecenter/db/ pass the pep8 test.

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
=== modified file 'softwarecenter/db/history_impl/apthistory.py'
--- softwarecenter/db/history_impl/apthistory.py 2011-12-02 14:30:56 +0000
+++ softwarecenter/db/history_impl/apthistory.py 2012-03-15 04:06:19 +0000
@@ -33,7 +33,7 @@
3333
34try:34try:
35 import cPickle as pickle35 import cPickle as pickle
36 pickle # pyflakes36 pickle # pyflakes
37except ImportError:37except ImportError:
38 import pickle38 import pickle
3939
@@ -43,20 +43,22 @@
43from softwarecenter.utils import ExecutionTime43from softwarecenter.utils import ExecutionTime
44from softwarecenter.db.history import Transaction, PackageHistory44from softwarecenter.db.history import Transaction, PackageHistory
4545
46
46def ascii_lower(key):47def ascii_lower(key):
47 ascii_trans_table = string.maketrans(string.ascii_uppercase,48 ascii_trans_table = string.maketrans(string.ascii_uppercase,
48 string.ascii_lowercase)49 string.ascii_lowercase)
49 return key.translate(ascii_trans_table)50 return key.translate(ascii_trans_table)
5051
52
51class AptTransaction(Transaction):53class AptTransaction(Transaction):
52 PKGACTIONS=["Install", "Upgrade", "Downgrade", "Remove", "Purge"]54 PKGACTIONS = ["Install", "Upgrade", "Downgrade", "Remove", "Purge"]
5355
54 def __init__(self, sec):56 def __init__(self, sec):
55 self.start_date = datetime.strptime(sec["Start-Date"],57 self.start_date = datetime.strptime(sec["Start-Date"],
56 "%Y-%m-%d %H:%M:%S")58 "%Y-%m-%d %H:%M:%S")
57 # set the object attributes "install", "upgrade", "downgrade",59 # set the object attributes "install", "upgrade", "downgrade",
58 # "remove", "purge", error60 # "remove", "purge", error
59 for k in self.PKGACTIONS+["Error"]:61 for k in self.PKGACTIONS + ["Error"]:
60 # we use ascii_lower for issues described in LP: #58120762 # we use ascii_lower for issues described in LP: #581207
61 attr = ascii_lower(k)63 attr = ascii_lower(k)
62 if k in sec:64 if k in sec:
@@ -68,13 +70,14 @@
68 @staticmethod70 @staticmethod
69 def _fixup_history_item(s):71 def _fixup_history_item(s):
70 """ strip history item string and add missing ")" if needed """72 """ strip history item string and add missing ")" if needed """
71 s=s.strip()73 s = s.strip()
72 # remove the infomation about the architecture74 # remove the infomation about the architecture
73 s = re.sub(":\w+", "", s)75 s = re.sub(":\w+", "", s)
74 if "(" in s and not s.endswith(")"):76 if "(" in s and not s.endswith(")"):
75 s+=")"77 s += ")"
76 return s78 return s
7779
80
78class AptHistory(PackageHistory):81class AptHistory(PackageHistory):
7982
80 def __init__(self, use_cache=True):83 def __init__(self, use_cache=True):
@@ -95,6 +98,7 @@
95 @property98 @property
96 def transactions(self):99 def transactions(self):
97 return self._transactions100 return self._transactions
101
98 @property102 @property
99 def history_ready(self):103 def history_ready(self):
100 return self._history_ready104 return self._history_ready
@@ -114,7 +118,7 @@
114 cachetime = os.path.getmtime(p)118 cachetime = os.path.getmtime(p)
115 except:119 except:
116 LOG.exception("failed to load cache")120 LOG.exception("failed to load cache")
117 for history_gz_file in sorted(glob.glob(self.history_file+".*.gz"),121 for history_gz_file in sorted(glob.glob(self.history_file + ".*.gz"),
118 cmp=self._mtime_cmp):122 cmp=self._mtime_cmp):
119 if os.path.getmtime(history_gz_file) < cachetime:123 if os.path.getmtime(history_gz_file) < cachetime:
120 LOG.debug("skipping already cached '%s'" % history_gz_file)124 LOG.debug("skipping already cached '%s'" % history_gz_file)
@@ -124,8 +128,8 @@
124 if use_cache:128 if use_cache:
125 pickle.dump(self._transactions, open(p, "w"))129 pickle.dump(self._transactions, open(p, "w"))
126 self._history_ready = True130 self._history_ready = True
127 131
128 def _scan(self, history_file, rescan = False):132 def _scan(self, history_file, rescan=False):
129 LOG.debug("_scan: '%s' (%s)" % (history_file, rescan))133 LOG.debug("_scan: '%s' (%s)" % (history_file, rescan))
130 try:134 try:
131 tagfile = apt_pkg.TagFile(open(history_file))135 tagfile = apt_pkg.TagFile(open(history_file))
@@ -136,7 +140,7 @@
136 # keep the UI alive140 # keep the UI alive
137 while self.main_context.pending():141 while self.main_context.pending():
138 self.main_context.iteration()142 self.main_context.iteration()
139 # ignore records with 143 # ignore records with
140 try:144 try:
141 trans = AptTransaction(stanza)145 trans = AptTransaction(stanza)
142 except (KeyError, ValueError):146 except (KeyError, ValueError):
@@ -151,16 +155,16 @@
151 # so we could (and should) do a binary search155 # so we could (and should) do a binary search
152 if not trans in self._transactions:156 if not trans in self._transactions:
153 self._transactions.insert(0, trans)157 self._transactions.insert(0, trans)
154 158
155 def _on_apt_history_changed(self, monitor, afile, other_file, event):159 def _on_apt_history_changed(self, monitor, afile, other_file, event):
156 if event == Gio.FileMonitorEvent.CHANGES_DONE_HINT:160 if event == Gio.FileMonitorEvent.CHANGES_DONE_HINT:
157 self._scan(self.history_file, rescan = True)161 self._scan(self.history_file, rescan=True)
158 if self.update_callback:162 if self.update_callback:
159 self.update_callback()163 self.update_callback()
160 164
161 def set_on_update(self,update_callback):165 def set_on_update(self, update_callback):
162 self.update_callback=update_callback166 self.update_callback = update_callback
163 167
164 def get_installed_date(self, pkg_name):168 def get_installed_date(self, pkg_name):
165 installed_date = None169 installed_date = None
166 for trans in self._transactions:170 for trans in self._transactions:
@@ -169,7 +173,7 @@
169 installed_date = trans.start_date173 installed_date = trans.start_date
170 return installed_date174 return installed_date
171 return installed_date175 return installed_date
172 176
173 def _find_in_terminal_log(self, date, term_file):177 def _find_in_terminal_log(self, date, term_file):
174 found = False178 found = False
175 term_lines = []179 term_lines = []
@@ -191,9 +195,8 @@
191 term_lines = self._find_in_terminal_log(date, open(term))195 term_lines = self._find_in_terminal_log(date, open(term))
192 # now search the older history196 # now search the older history
193 if not term_lines:197 if not term_lines:
194 for f in glob.glob(term+".*.gz"):198 for f in glob.glob(term + ".*.gz"):
195 term_lines = self._find_in_terminal_log(date, gzip.open(f))199 term_lines = self._find_in_terminal_log(date, gzip.open(f))
196 if term_lines:200 if term_lines:
197 return term_lines201 return term_lines
198 return term_lines202 return term_lines
199
200203
=== modified file 'softwarecenter/db/history_impl/packagekit.py'
--- softwarecenter/db/history_impl/packagekit.py 2011-12-02 14:30:56 +0000
+++ softwarecenter/db/history_impl/packagekit.py 2012-03-15 04:06:19 +0000
@@ -22,6 +22,7 @@
2222
23LOG = logging.getLogger(__name__)23LOG = logging.getLogger(__name__)
2424
25
25class PackagekitTransaction(Transaction):26class PackagekitTransaction(Transaction):
26 def __init__(self, pktrans):27 def __init__(self, pktrans):
27 self.start_date = datetime.strptime(pktrans.props.timespec,28 self.start_date = datetime.strptime(pktrans.props.timespec,
@@ -31,7 +32,8 @@
31 self.upgrade = []32 self.upgrade = []
32 self.downgrade = []33 self.downgrade = []
33 self.remove = []34 self.remove = []
34 self.purge = [] # can't happen with a Packagekit backend (is mapped to remove)35 self.purge = [] # can't happen with a Packagekit backend (is mapped
36 # to remove)
3537
36 # parse transaction data38 # parse transaction data
37 lines = pktrans.props.data.split('\n')39 lines = pktrans.props.data.split('\n')
@@ -51,13 +53,15 @@
51 elif action == 'removing':53 elif action == 'removing':
52 self.remove.append(package_name)54 self.remove.append(package_name)
53 else:55 else:
54 # ignore other actions (include cleanup, downloading and untrusted)56 # ignore other actions (include cleanup, downloading and
57 # untrusted)
55 continue58 continue
56 except:59 except:
57 LOG.warn("malformed line emitted by PackageKit, was %s" % line)60 LOG.warn("malformed line emitted by PackageKit, was %s" % line)
5861
62
59class PackagekitHistory(PackageHistory):63class PackagekitHistory(PackageHistory):
60 """ Represents the history of the transactions """ 64 """ Represents the history of the transactions """
6165
62 def __init__(self, use_cache=True):66 def __init__(self, use_cache=True):
63 self._use_cache = use_cache67 self._use_cache = use_cache
@@ -66,9 +70,9 @@
6670
67 self._client = PackageKitGlib.Client()71 self._client = PackageKitGlib.Client()
68 self._client.get_old_transactions_async(0,72 self._client.get_old_transactions_async(0,
69 None, # cancellable73 None, # cancellable
70 lambda *args, **kwargs: None, None, # progress callback74 lambda *args, **kwargs: None, None, # progress callback
71 self._transactions_received, None)75 self._transactions_received, None)
7276
73 @property77 @property
74 def history_ready(self):78 def history_ready(self):
@@ -86,7 +90,7 @@
8690
87 def get_installed_date(self, pkg_name):91 def get_installed_date(self, pkg_name):
88 """Return the date that the given package name got instaled """92 """Return the date that the given package name got instaled """
89 return None93 pass
9094
91 def _transactions_received(self, client, async_result, user_data):95 def _transactions_received(self, client, async_result, user_data):
92 try:96 try:
9397
=== modified file 'softwarecenter/db/pkginfo.py'
--- softwarecenter/db/pkginfo.py 2012-02-14 09:51:45 +0000
+++ softwarecenter/db/pkginfo.py 2012-03-15 04:06:19 +0000
@@ -18,28 +18,36 @@
1818
19from gi.repository import GObject19from gi.repository import GObject
2020
21
21class _Version:22class _Version:
22 @property23 @property
23 def description(self):24 def description(self):
24 pass25 pass
26
25 @property27 @property
26 def downloadable(self):28 def downloadable(self):
27 pass29 pass
30
28 @property31 @property
29 def summary(self):32 def summary(self):
30 pass33 pass
34
31 @property35 @property
32 def size(self):36 def size(self):
33 return self.pkginfo.get_size(self.name)37 return self.pkginfo.get_size(self.name)
38
34 @property39 @property
35 def installed_size(self):40 def installed_size(self):
36 return 041 return 0
42
37 @property43 @property
38 def version(self):44 def version(self):
39 pass45 pass
46
40 @property47 @property
41 def origins(self):48 def origins(self):
42 return []49 return []
50
43 @property51 @property
44 def not_automatic(self):52 def not_automatic(self):
45 """ should not be installed/upgraded automatically, the user needs53 """ should not be installed/upgraded automatically, the user needs
@@ -47,22 +55,26 @@
47 """55 """
48 return False56 return False
4957
58
50class _Package:59class _Package:
51 def __init__(self, name, pkginfo):60 def __init__(self, name, pkginfo):
52 self.name = name61 self.name = name
53 self.pkginfo = pkginfo62 self.pkginfo = pkginfo
63
54 def __str__(self):64 def __str__(self):
55 return repr(self).replace('<', '<pkgname=%s ' % self.name)65 return repr(self).replace('<', '<pkgname=%s ' % self.name)
66
56 @property67 @property
57 def installed(self):68 def installed(self):
58 """ returns a _Version object """69 """ returns a _Version object """
59 if not self.pkginfo.is_installed(self.name):70 if self.pkginfo.is_installed(self.name):
60 return None71 return self.pkginfo.get_installed(self.name)
61 return self.pkginfo.get_installed(self.name)72
62 @property73 @property
63 def candidate(self):74 def candidate(self):
64 """ returns a _Version object """75 """ returns a _Version object """
65 return self.pkginfo.get_candidate(self.name)76 return self.pkginfo.get_candidate(self.name)
77
66 @property78 @property
67 def versions(self):79 def versions(self):
68 """ a list of available versions (as _Version) to install """80 """ a list of available versions (as _Version) to install """
@@ -71,18 +83,23 @@
71 @property83 @property
72 def is_installed(self):84 def is_installed(self):
73 return self.pkginfo.is_installed(self.name)85 return self.pkginfo.is_installed(self.name)
86
74 @property87 @property
75 def is_upgradable(self):88 def is_upgradable(self):
76 return self.pkginfo.is_upgradable(self.name)89 return self.pkginfo.is_upgradable(self.name)
90
77 @property91 @property
78 def section(self):92 def section(self):
79 return self.pkginfo.get_section(self.name)93 return self.pkginfo.get_section(self.name)
94
80 @property95 @property
81 def website(self):96 def website(self):
82 return self.pkginfo.get_website(self.name)97 return self.pkginfo.get_website(self.name)
98
83 @property99 @property
84 def installed_files(self):100 def installed_files(self):
85 return self.pkginfo.get_installed_files(self.name)101 return self.pkginfo.get_installed_files(self.name)
102
86 @property103 @property
87 def description(self):104 def description(self):
88 return self.pkginfo.get_description(self.name)105 return self.pkginfo.get_description(self.name)
@@ -91,22 +108,24 @@
91 def license(self):108 def license(self):
92 return self.pkginfo.get_license(self.name)109 return self.pkginfo.get_license(self.name)
93110
111
94class PackageInfo(GObject.GObject):112class PackageInfo(GObject.GObject):
95 """ abstract interface for the packageinfo information """113 """ abstract interface for the packageinfo information """
96114
97 __gsignals__ = {'cache-ready': (GObject.SIGNAL_RUN_FIRST,115 __gsignals__ = {'cache-ready': (GObject.SIGNAL_RUN_FIRST,
98 GObject.TYPE_NONE,116 GObject.TYPE_NONE,
99 ()),117 ()),
100 'cache-invalid':(GObject.SIGNAL_RUN_FIRST,118 'cache-invalid': (GObject.SIGNAL_RUN_FIRST,
101 GObject.TYPE_NONE,119 GObject.TYPE_NONE,
102 ()),120 ()),
103 'cache-broken':(GObject.SIGNAL_RUN_FIRST,121 'cache-broken': (GObject.SIGNAL_RUN_FIRST,
104 GObject.TYPE_NONE,122 GObject.TYPE_NONE,
105 ()),123 ()),
106 }124 }
107125
108 def __getitem__(self, k):126 def __getitem__(self, k):
109 return _Package(k, self)127 return _Package(k, self)
128
110 def __contains__(self, pkgname):129 def __contains__(self, pkgname):
111 return False130 return False
112131
@@ -114,10 +133,12 @@
114 def version_compare(v1, v2):133 def version_compare(v1, v2):
115 """ compare two versions """134 """ compare two versions """
116 return cmp(v1, v2)135 return cmp(v1, v2)
136
117 @staticmethod137 @staticmethod
118 def upstream_version_compare(v1, v2):138 def upstream_version_compare(v1, v2):
119 """ compare two versions, but ignore the distro specific revisions """139 """ compare two versions, but ignore the distro specific revisions """
120 return cmp(v1, v2)140 return cmp(v1, v2)
141
121 @staticmethod142 @staticmethod
122 def upstream_version(v):143 def upstream_version(v):
123 """ Return the "upstream" version number of the given version """144 """ Return the "upstream" version number of the given version """
@@ -125,34 +146,47 @@
125146
126 def is_installed(self, pkgname):147 def is_installed(self, pkgname):
127 pass148 pass
149
128 def is_available(self, pkgname):150 def is_available(self, pkgname):
129 pass151 pass
152
130 def get_installed(self, pkgname):153 def get_installed(self, pkgname):
131 pass154 pass
155
132 def get_candidate(self, pkgname):156 def get_candidate(self, pkgname):
133 pass157 pass
158
134 def get_versions(self, pkgname):159 def get_versions(self, pkgname):
135 return []160 return []
136161
137 def get_section(self, pkgname):162 def get_section(self, pkgname):
138 pass163 pass
164
139 def get_summary(self, pkgname):165 def get_summary(self, pkgname):
140 pass166 pass
167
141 def get_description(self, pkgname):168 def get_description(self, pkgname):
142 pass169 pass
170
143 def get_website(self, pkgname):171 def get_website(self, pkgname):
144 pass172 pass
173
145 def get_installed_files(self, pkgname):174 def get_installed_files(self, pkgname):
146 return []175 return []
176
147 def get_size(self, pkgname):177 def get_size(self, pkgname):
148 return -1178 return -1
179
149 def get_installed_size(self, pkgname):180 def get_installed_size(self, pkgname):
150 return -1181 return -1
182
151 def get_origins(self, pkgname):183 def get_origins(self, pkgname):
152 return []184 return []
185
153 def get_origin(self, pkgname):186 def get_origin(self, pkgname):
154 """ :return: unique origin as string """187 """ :return: unique origin as string """
155 return ''188 return ''
189
156 def get_addons(self, pkgname, ignore_installed=False):190 def get_addons(self, pkgname, ignore_installed=False):
157 """ :return: a tuple of pkgnames (recommends, suggests) """191 """ :return: a tuple of pkgnames (recommends, suggests) """
158 return ([], [])192 return ([], [])
@@ -167,27 +201,30 @@
167 which will be removed if the package is installed."""201 which will be removed if the package is installed."""
168 return []202 return []
169203
170 def get_total_size_on_install(self, pkgname, 204 def get_total_size_on_install(self, pkgname,
171 addons_install=None, addons_remove=None,205 addons_install=None, addons_remove=None,
172 archive_suite=None):206 archive_suite=None):
173 """ Returns a tuple (download_size, installed_size)207 """ Returns a tuple (download_size, installed_size)
174 with disk size in KB calculated for pkgname installation208 with disk size in KB calculated for pkgname installation
175 plus addons change and a (optional) archive_suite that the 209 plus addons change and a (optional) archive_suite that the
176 package comes from210 package comes from
177 """211 """
178 return (0, 0)212 return (0, 0)
179213
180 def open(self):214 def open(self):
181 """ 215 """
182 (re)open the cache, this sends cache-invalid, cache-ready signals216 (re)open the cache, this sends cache-invalid, cache-ready signals
183 """217 """
184 pass218 pass
219
185 @property220 @property
186 def ready(self):221 def ready(self):
187 pass222 pass
188223
189# singleton224# singleton
190pkginfo = None225pkginfo = None
226
227
191def get_pkg_info():228def get_pkg_info():
192 global pkginfo229 global pkginfo
193 if pkginfo is None:230 if pkginfo is None:
@@ -196,6 +233,8 @@
196 from softwarecenter.db.pkginfo_impl.aptcache import AptCache233 from softwarecenter.db.pkginfo_impl.aptcache import AptCache
197 pkginfo = AptCache()234 pkginfo = AptCache()
198 else:235 else:
199 from softwarecenter.db.pkginfo_impl.packagekit import PackagekitInfo236 from softwarecenter.db.pkginfo_impl.packagekit import (
200 pkginfo = PackagekitInfo() 237 PackagekitInfo,
238 )
239 pkginfo = PackagekitInfo()
201 return pkginfo240 return pkginfo
202241
=== modified file 'softwarecenter/db/update.py'
--- softwarecenter/db/update.py 2012-02-28 22:35:19 +0000
+++ softwarecenter/db/update.py 2012-03-15 04:06:19 +0000
@@ -36,15 +36,15 @@
36# py3 compat36# py3 compat
37try:37try:
38 from configparser import RawConfigParser, NoOptionError38 from configparser import RawConfigParser, NoOptionError
39 RawConfigParser # pyflakes39 RawConfigParser # pyflakes
40 NoOptionError # pyflakes40 NoOptionError # pyflakes
41except ImportError:41except ImportError:
42 from ConfigParser import RawConfigParser, NoOptionError42 from ConfigParser import RawConfigParser, NoOptionError
4343
44# py3 compat44# py3 compat
45try:45try:
46 import cPickle as pickle46 import cPickle as pickle
47 pickle # pyflakes47 pickle # pyflakes
48except ImportError:48except ImportError:
49 import pickle49 import pickle
5050
@@ -101,6 +101,7 @@
101# Enable Xapian's CJK tokenizer (see LP: #745243)101# Enable Xapian's CJK tokenizer (see LP: #745243)
102os.environ['XAPIAN_CJK_NGRAM'] = '1'102os.environ['XAPIAN_CJK_NGRAM'] = '1'
103103
104
104class AppInfoParserBase(object):105class AppInfoParserBase(object):
105 """ base class for reading AppInfo meta-data """106 """ base class for reading AppInfo meta-data """
106107
@@ -108,8 +109,10 @@
108109
109 def get_desktop(self, key, translated=True):110 def get_desktop(self, key, translated=True):
110 """ get a AppInfo entry for the given key """111 """ get a AppInfo entry for the given key """
112
111 def has_option_desktop(self, key):113 def has_option_desktop(self, key):
112 """ return True if there is a given AppInfo info """114 """ return True if there is a given AppInfo info """
115
113 def _get_desktop_list(self, key, split_str=";"):116 def _get_desktop_list(self, key, split_str=";"):
114 result = []117 result = []
115 try:118 try:
@@ -120,6 +123,7 @@
120 except (NoOptionError, KeyError):123 except (NoOptionError, KeyError):
121 pass124 pass
122 return result125 return result
126
123 def _apply_mapping(self, key):127 def _apply_mapping(self, key):
124 # strip away bogus prefixes128 # strip away bogus prefixes
125 if key.startswith("X-AppInstall-"):129 if key.startswith("X-AppInstall-"):
@@ -127,12 +131,15 @@
127 if key in self.MAPPING:131 if key in self.MAPPING:
128 return self.MAPPING[key]132 return self.MAPPING[key]
129 return key133 return key
134
130 def get_desktop_categories(self):135 def get_desktop_categories(self):
131 return self._get_desktop_list("Categories")136 return self._get_desktop_list("Categories")
137
132 def get_desktop_mimetypes(self):138 def get_desktop_mimetypes(self):
133 if not self.has_option_desktop("MimeType"):139 if not self.has_option_desktop("MimeType"):
134 return []140 return []
135 return self._get_desktop_list("MimeType")141 return self._get_desktop_list("MimeType")
142
136 @property143 @property
137 def desktopf(self):144 def desktopf(self):
138 """ return the file that the AppInfo comes from """145 """ return the file that the AppInfo comes from """
@@ -142,29 +149,29 @@
142 """ map the data we get from the software-center-agent """149 """ map the data we get from the software-center-agent """
143150
144 # map from requested key to sca_application attribute151 # map from requested key to sca_application attribute
145 MAPPING = { 'Name' : 'name',152 MAPPING = {'Name': 'name',
146 'Price' : 'price',153 'Price': 'price',
147 'Package' : 'package_name',154 'Package': 'package_name',
148 'Categories' : 'categories',155 'Categories': 'categories',
149 'Channel' : 'channel',156 'Channel': 'channel',
150 'Signing-Key-Id' : 'signing_key_id',157 'Signing-Key-Id': 'signing_key_id',
151 'License' : 'license',158 'License': 'license',
152 'Date-Published' : 'date_published',159 'Date-Published': 'date_published',
153 'PPA' : 'archive_id',160 'PPA': 'archive_id',
154 'Screenshot-Url' : 'screenshot_url',161 'Screenshot-Url': 'screenshot_url',
155 'Thumbnail-Url' : 'thumbnail_url',162 'Thumbnail-Url': 'thumbnail_url',
156 'Video-Url' : 'video_embedded_html_url',163 'Video-Url': 'video_embedded_html_url',
157 'Icon-Url' : 'icon_url',164 'Icon-Url': 'icon_url',
158 'Support-Url' : 'support_url',165 'Support-Url': 'support_url',
159 'Description' : 'Description',166 'Description': 'Description',
160 'Comment' : 'Comment',167 'Comment': 'Comment',
161 'Version' : 'version',168 'Version': 'version',
162 'Supported-Distros': 'series',169 'Supported-Distros': 'series',
163 # tags are special, see _apply_exception170 # tags are special, see _apply_exception
164 }171 }
165172
166 # map from requested key to a static data element173 # map from requested key to a static data element
167 STATIC_DATA = { 'Type' : 'Application',174 STATIC_DATA = {'Type': 'Application',
168 }175 }
169176
170 def __init__(self, sca_application):177 def __init__(self, sca_application):
@@ -179,19 +186,23 @@
179 # we no longer keep thumbnail versions of screenshots on the server186 # we no longer keep thumbnail versions of screenshots on the server
180 if (hasattr(self.sca_application, "screenshot_url") and187 if (hasattr(self.sca_application, "screenshot_url") and
181 not hasattr(self.sca_application, "thumbnail_url")):188 not hasattr(self.sca_application, "thumbnail_url")):
182 self.sca_application.thumbnail_url = self.sca_application.screenshot_url189 self.sca_application.thumbnail_url = \
190 self.sca_application.screenshot_url
183 if hasattr(self.sca_application, "description"):191 if hasattr(self.sca_application, "description"):
184 self.sca_application.Comment = self.sca_application.description.split("\n")[0].strip()192 comment = self.sca_application.description.split("\n")[0].strip()
193 self.sca_application.Comment = comment
185 self.sca_application.Description = "\n".join(194 self.sca_application.Description = "\n".join(
186 self.sca_application.description.split("\n")[1:]).strip()195 self.sca_application.description.split("\n")[1:]).strip()
187196
188 # debtags is send as a list, but we need it as a comma seperated string197 # debtags is send as a list, but we need it as a comma seperated string
189 self.sca_application.Tags = ",".join(getattr(self.sca_application, "debtags", []))198 self.sca_application.Tags = ",".join(getattr(self.sca_application,
199 "debtags", []))
190200
191 # we only support a single video currently :/201 # we only support a single video currently :/
192 if hasattr(self.sca_application, "video_embedded_html_urls"):202 if hasattr(self.sca_application, "video_embedded_html_urls"):
193 if self.sca_application.video_embedded_html_urls:203 if self.sca_application.video_embedded_html_urls:
194 self.sca_application.video_embedded_html_url = self.sca_application.video_embedded_html_urls[0]204 video_url = self.sca_application.video_embedded_html_urls[0]
205 self.sca_application.video_embedded_html_url = video_url
195206
196 # XXX 2012-01-16 bug=917109207 # XXX 2012-01-16 bug=917109
197 # We can remove these work-arounds once the above bug is fixed on208 # We can remove these work-arounds once the above bug is fixed on
@@ -199,7 +210,8 @@
199 # to make the parser happy. Note: available_apps api call includes210 # to make the parser happy. Note: available_apps api call includes
200 # these already, it's just the apps with subscriptions_for_me which211 # these already, it's just the apps with subscriptions_for_me which
201 # don't currently.212 # don't currently.
202 self.sca_application.channel = AVAILABLE_FOR_PURCHASE_MAGIC_CHANNEL_NAME213 self.sca_application.channel = \
214 AVAILABLE_FOR_PURCHASE_MAGIC_CHANNEL_NAME
203 if not hasattr(self.sca_application, 'categories'):215 if not hasattr(self.sca_application, 'categories'):
204 self.sca_application.categories = ""216 self.sca_application.categories = ""
205217
@@ -207,16 +219,16 @@
207 # attribute appropriately so that the channel-adding magic works219 # attribute appropriately so that the channel-adding magic works
208 if hasattr(self.sca_application, "archive_root"):220 if hasattr(self.sca_application, "archive_root"):
209 u = urlparse(self.sca_application.archive_root)221 u = urlparse(self.sca_application.archive_root)
210 if u.scheme == "http" and u.netloc == "archive.canonical.com":222 if u.scheme == "http" and u.netloc == "archive.canonical.com":
211 distroseries = get_distro().get_codename()223 distroseries = get_distro().get_codename()
212 self.sca_application.channel = "%s-partner" % distroseries224 self.sca_application.channel = "%s-partner" % distroseries
213 if u.scheme == "http" and u.netloc == "extras.ubuntu.com":225 if u.scheme == "http" and u.netloc == "extras.ubuntu.com":
214 self.sca_application.channel = "ubuntu-extras"226 self.sca_application.channel = "ubuntu-extras"
215 227
216 # support multiple screenshots228 # support multiple screenshots
217 if hasattr(self.sca_application, "screenshot_urls"):229 if hasattr(self.sca_application, "screenshot_urls"):
218 # ensure to html-quote "," as this is also our seperator230 # ensure to html-quote "," as this is also our seperator
219 s = ",".join([url.replace(",", "%2C") 231 s = ",".join([url.replace(",", "%2C")
220 for url in self.sca_application.screenshot_urls])232 for url in self.sca_application.screenshot_urls])
221 self.sca_application.screenshot_url = s233 self.sca_application.screenshot_url = s
222234
@@ -227,7 +239,8 @@
227239
228 def get_desktop_categories(self):240 def get_desktop_categories(self):
229 try:241 try:
230 return ['DEPARTMENT:' + self.sca_application.department[-1]] + self._get_desktop_list("Categories")242 return (['DEPARTMENT:' + self.sca_application.department[-1]] +
243 self._get_desktop_list("Categories"))
231 except:244 except:
232 return self._get_desktop_list("Categories")245 return self._get_desktop_list("Categories")
233246
@@ -251,17 +264,17 @@
251 PistonResponseObject.from_dict(sca_subscription.application))264 PistonResponseObject.from_dict(sca_subscription.application))
252265
253 SUBSCRIPTION_MAPPING = {266 SUBSCRIPTION_MAPPING = {
254 # this key can be used to get the original deb_line that the 267 # this key can be used to get the original deb_line that the
255 # server returns, it will be at the distroseries that was current268 # server returns, it will be at the distroseries that was current
256 # at purchase time269 # at purchase time
257 'Deb-Line-Orig' : 'deb_line',270 'Deb-Line-Orig': 'deb_line',
258 # this is what s-c will always use, the deb_line updated to the271 # this is what s-c will always use, the deb_line updated to the
259 # current distroseries, note that you should ensure that the app272 # current distroseries, note that you should ensure that the app
260 # is not in state: PkgStates.PURCHASED_BUT_NOT_AVAILABLE_FOR_SERIES273 # is not in state: PkgStates.PURCHASED_BUT_NOT_AVAILABLE_FOR_SERIES
261 'Deb-Line' : 'deb_line',274 'Deb-Line': 'deb_line',
262 'Purchased-Date' : 'purchase_date',275 'Purchased-Date': 'purchase_date',
263 'License-Key' : 'license_key',276 'License-Key': 'license_key',
264 'License-Key-Path' : 'license_key_path',277 'License-Key-Path': 'license_key_path',
265 }278 }
266279
267 MAPPING = dict(280 MAPPING = dict(
@@ -313,47 +326,52 @@
313326
314class JsonTagSectionParser(AppInfoParserBase):327class JsonTagSectionParser(AppInfoParserBase):
315328
316 MAPPING = { 'Name' : 'application_name',329 MAPPING = {'Name': 'application_name',
317 'Comment' : 'description',330 'Comment': 'description',
318 'Price' : 'price',331 'Price': 'price',
319 'Package' : 'package_name',332 'Package': 'package_name',
320 'Categories' : 'categories',333 'Categories': 'categories',
321 }334 }
322335
323 def __init__(self, tag_section, url):336 def __init__(self, tag_section, url):
324 self.tag_section = tag_section337 self.tag_section = tag_section
325 self.url = url338 self.url = url
339
326 def get_desktop(self, key, translated=True):340 def get_desktop(self, key, translated=True):
327 return self.tag_section[self._apply_mapping(key)]341 return self.tag_section[self._apply_mapping(key)]
342
328 def has_option_desktop(self, key):343 def has_option_desktop(self, key):
329 return self._apply_mapping(key) in self.tag_section344 return self._apply_mapping(key) in self.tag_section
345
330 @property346 @property
331 def desktopf(self):347 def desktopf(self):
332 return self.url348 return self.url
333349
350
334class AppStreamXMLParser(AppInfoParserBase):351class AppStreamXMLParser(AppInfoParserBase):
335352
336 MAPPING = { 'Name' : 'name',353 MAPPING = {'Name': 'name',
337 'Comment' : 'summary',354 'Comment': 'summary',
338 'Package' : 'pkgname',355 'Package': 'pkgname',
339 'Categories' : 'appcategories',356 'Categories': 'appcategories',
340 'Keywords' : 'keywords',357 'Keywords': 'keywords',
341 'MimeType' : 'mimetypes',358 'MimeType': 'mimetypes',
342 'Icon' : 'icon',359 'Icon': 'icon',
343 }360 }
344361
345 LISTS = { "appcategories" : "appcategory",362 LISTS = {"appcategories": "appcategory",
346 "keywords" : "keyword",363 "keywords": "keyword",
347 "mimetypes" : "mimetype",364 "mimetypes": "mimetype",
348 }365 }
349366
350 # map from requested key to a static data element367 # map from requested key to a static data element
351 STATIC_DATA = { 'Type' : 'Application',368 STATIC_DATA = {'Type': 'Application',
352 }369 }
353370
354 def __init__(self, appinfo_xml, xmlfile):371 def __init__(self, appinfo_xml, xmlfile):
355 self.appinfo_xml = appinfo_xml372 self.appinfo_xml = appinfo_xml
356 self.xmlfile = xmlfile373 self.xmlfile = xmlfile
374
357 def get_desktop(self, key, translated=True):375 def get_desktop(self, key, translated=True):
358 if key in self.STATIC_DATA:376 if key in self.STATIC_DATA:
359 return self.STATIC_DATA[key]377 return self.STATIC_DATA[key]
@@ -362,14 +380,18 @@
362 return self._parse_with_lists(key)380 return self._parse_with_lists(key)
363 else:381 else:
364 return self._parse_value(key, translated)382 return self._parse_value(key, translated)
383
365 def get_desktop_categories(self):384 def get_desktop_categories(self):
366 return self._get_desktop_list("Categories", split_str=',')385 return self._get_desktop_list("Categories", split_str=',')
386
367 def get_desktop_mimetypes(self):387 def get_desktop_mimetypes(self):
368 if not self.has_option_desktop("MimeType"):388 if not self.has_option_desktop("MimeType"):
369 return []389 return []
370 return self._get_desktop_list("MimeType", split_str=',')390 return self._get_desktop_list("MimeType", split_str=',')
391
371 def _parse_value(self, key, translated):392 def _parse_value(self, key, translated):
372 locale = getdefaultlocale(('LANGUAGE','LANG','LC_CTYPE','LC_ALL'))[0]393 locale = getdefaultlocale(('LANGUAGE', 'LANG', 'LC_CTYPE',
394 'LC_ALL'))[0]
373 for child in self.appinfo_xml.iter(key):395 for child in self.appinfo_xml.iter(key):
374 if translated:396 if translated:
375 if child.get("lang") == locale:397 if child.get("lang") == locale:
@@ -381,28 +403,31 @@
381 return child.text403 return child.text
382 if translated:404 if translated:
383 return self._parse_value(key, False)405 return self._parse_value(key, False)
384 else:406
385 return None
386 def _parse_with_lists(self, key):407 def _parse_with_lists(self, key):
387 l=[]408 l = []
388 for listroot in self.appinfo_xml.iter(key):409 for listroot in self.appinfo_xml.iter(key):
389 for child in listroot.iter(self.LISTS[key]):410 for child in listroot.iter(self.LISTS[key]):
390 l.append(child.text)411 l.append(child.text)
391 return ",".join(l)412 return ",".join(l)
413
392 def has_option_desktop(self, key):414 def has_option_desktop(self, key):
393 if key in self.STATIC_DATA:415 if key in self.STATIC_DATA:
394 return True416 return True
395 key = self._apply_mapping(key)417 key = self._apply_mapping(key)
396 return not self.appinfo_xml.find(key) is None418 return not self.appinfo_xml.find(key) is None
419
397 @property420 @property
398 def desktopf(self):421 def desktopf(self):
399 subelm = self.appinfo_xml.find("id")422 subelm = self.appinfo_xml.find("id")
400 return subelm.text423 return subelm.text
401424
425
402class DesktopTagSectionParser(AppInfoParserBase):426class DesktopTagSectionParser(AppInfoParserBase):
403 def __init__(self, tag_section, tagfile):427 def __init__(self, tag_section, tagfile):
404 self.tag_section = tag_section428 self.tag_section = tag_section
405 self.tagfile = tagfile429 self.tagfile = tagfile
430
406 def get_desktop(self, key, translated=True):431 def get_desktop(self, key, translated=True):
407 # strip away bogus prefixes432 # strip away bogus prefixes
408 if key.startswith("X-AppInstall-"):433 if key.startswith("X-AppInstall-"):
@@ -422,7 +447,8 @@
422 # then try the i18n version of the key (in [de_DE] or447 # then try the i18n version of the key (in [de_DE] or
423 # [de]) but ignore errors and return the untranslated one then448 # [de]) but ignore errors and return the untranslated one then
424 try:449 try:
425 locale = getdefaultlocale(('LANGUAGE','LANG','LC_CTYPE','LC_ALL'))[0]450 locale = getdefaultlocale(('LANGUAGE', 'LANG', 'LC_CTYPE',
451 'LC_ALL'))[0]
426 if locale:452 if locale:
427 if self.has_option_desktop("%s-%s" % (key, locale)):453 if self.has_option_desktop("%s-%s" % (key, locale)):
428 return self.tag_section["%s-%s" % (key, locale)]454 return self.tag_section["%s-%s" % (key, locale)]
@@ -434,18 +460,22 @@
434 pass460 pass
435 # and then the untranslated field461 # and then the untranslated field
436 return self.tag_section[key]462 return self.tag_section[key]
463
437 def has_option_desktop(self, key):464 def has_option_desktop(self, key):
438 # strip away bogus prefixes465 # strip away bogus prefixes
439 if key.startswith("X-AppInstall-"):466 if key.startswith("X-AppInstall-"):
440 key = key[len("X-AppInstall-"):]467 key = key[len("X-AppInstall-"):]
441 return key in self.tag_section468 return key in self.tag_section
469
442 @property470 @property
443 def desktopf(self):471 def desktopf(self):
444 return self.tagfile472 return self.tagfile
445473
474
446class DesktopConfigParser(RawConfigParser, AppInfoParserBase):475class DesktopConfigParser(RawConfigParser, AppInfoParserBase):
447 " thin wrapper that is tailored for xdg Desktop files "476 " thin wrapper that is tailored for xdg Desktop files "
448 DE = "Desktop Entry"477 DE = "Desktop Entry"
478
449 def get_desktop(self, key, translated=True):479 def get_desktop(self, key, translated=True):
450 " get generic option under 'Desktop Entry'"480 " get generic option under 'Desktop Entry'"
451 # never translate the pkgname481 # never translate the pkgname
@@ -471,28 +501,34 @@
471 # then try the i18n version of the key (in [de_DE] or501 # then try the i18n version of the key (in [de_DE] or
472 # [de]) but ignore errors and return the untranslated one then502 # [de]) but ignore errors and return the untranslated one then
473 try:503 try:
474 locale = getdefaultlocale(('LANGUAGE','LANG','LC_CTYPE','LC_ALL'))[0]504 locale = getdefaultlocale(('LANGUAGE', 'LANG', 'LC_CTYPE',
505 'LC_ALL'))[0]
475 if locale:506 if locale:
476 if self.has_option_desktop("%s[%s]" % (key, locale)):507 if self.has_option_desktop("%s[%s]" % (key, locale)):
477 return self.get(self.DE, "%s[%s]" % (key, locale))508 return self.get(self.DE, "%s[%s]" % (key, locale))
478 if "_" in locale:509 if "_" in locale:
479 locale_short = locale.split("_")[0]510 locale_short = locale.split("_")[0]
480 if self.has_option_desktop("%s[%s]" % (key, locale_short)):511 if self.has_option_desktop("%s[%s]" % (key, locale_short)):
481 return self.get(self.DE, "%s[%s]" % (key, locale_short))512 return self.get(self.DE, "%s[%s]" %
513 (key, locale_short))
482 except ValueError:514 except ValueError:
483 pass515 pass
484 # and then the untranslated field516 # and then the untranslated field
485 return self.get(self.DE, key)517 return self.get(self.DE, key)
518
486 def has_option_desktop(self, key):519 def has_option_desktop(self, key):
487 " test if there is the option under 'Desktop Entry'"520 " test if there is the option under 'Desktop Entry'"
488 return self.has_option(self.DE, key)521 return self.has_option(self.DE, key)
522
489 def read(self, filename):523 def read(self, filename):
490 self._filename = filename524 self._filename = filename
491 RawConfigParser.read(self, filename)525 RawConfigParser.read(self, filename)
526
492 @property527 @property
493 def desktopf(self):528 def desktopf(self):
494 return self._filename529 return self._filename
495530
531
496def ascii_upper(key):532def ascii_upper(key):
497 """Translate an ASCII string to uppercase533 """Translate an ASCII string to uppercase
498 in a locale-independent manner."""534 in a locale-independent manner."""
@@ -500,13 +536,15 @@
500 string.ascii_uppercase)536 string.ascii_uppercase)
501 return key.translate(ascii_trans_table)537 return key.translate(ascii_trans_table)
502538
539
503def index_name(doc, name, term_generator):540def index_name(doc, name, term_generator):
504 """ index the name of the application """541 """ index the name of the application """
505 doc.add_value(XapianValues.APPNAME, name)542 doc.add_value(XapianValues.APPNAME, name)
506 doc.add_term("AA"+name)543 doc.add_term("AA" + name)
507 w = globals()["WEIGHT_DESKTOP_NAME"]544 w = globals()["WEIGHT_DESKTOP_NAME"]
508 term_generator.index_text_without_positions(name, w)545 term_generator.index_text_without_positions(name, w)
509546
547
510def update(db, cache, datadir=None):548def update(db, cache, datadir=None):
511 if not datadir:549 if not datadir:
512 datadir = softwarecenter.paths.APP_INSTALL_DESKTOP_PATH550 datadir = softwarecenter.paths.APP_INSTALL_DESKTOP_PATH
@@ -514,7 +552,9 @@
514 update_from_var_lib_apt_lists(db, cache)552 update_from_var_lib_apt_lists(db, cache)
515 # add db global meta-data553 # add db global meta-data
516 LOG.debug("adding popcon_max_desktop '%s'" % popcon_max)554 LOG.debug("adding popcon_max_desktop '%s'" % popcon_max)
517 db.set_metadata("popcon_max_desktop", xapian.sortable_serialise(float(popcon_max)))555 db.set_metadata("popcon_max_desktop",
556 xapian.sortable_serialise(float(popcon_max)))
557
518558
519def update_from_json_string(db, cache, json_string, origin):559def update_from_json_string(db, cache, json_string, origin):
520 """ index from a json string, should include origin url (free form string)560 """ index from a json string, should include origin url (free form string)
@@ -524,6 +564,7 @@
524 index_app_info_from_parser(parser, db, cache)564 index_app_info_from_parser(parser, db, cache)
525 return True565 return True
526566
567
527def update_from_var_lib_apt_lists(db, cache, listsdir=None):568def update_from_var_lib_apt_lists(db, cache, listsdir=None):
528 """ index the files in /var/lib/apt/lists/*AppInfo """569 """ index the files in /var/lib/apt/lists/*AppInfo """
529 try:570 try:
@@ -544,18 +585,21 @@
544 index_app_info_from_parser(parser, db, cache)585 index_app_info_from_parser(parser, db, cache)
545 return True586 return True
546587
588
547def update_from_single_appstream_file(db, cache, filename):589def update_from_single_appstream_file(db, cache, filename):
548 from lxml import etree590 from lxml import etree
549591
550 tree = etree.parse(open(filename))592 tree = etree.parse(open(filename))
551 root = tree.getroot()593 root = tree.getroot()
552 if not root.tag == "applications":594 if not root.tag == "applications":
553 LOG.error("failed to read '%s' expected Applications root tag" % filename)595 LOG.error("failed to read '%s' expected Applications root tag" %
596 filename)
554 return597 return
555 for appinfo in root.iter("application"):598 for appinfo in root.iter("application"):
556 parser = AppStreamXMLParser(appinfo, filename)599 parser = AppStreamXMLParser(appinfo, filename)
557 index_app_info_from_parser(parser, db, cache)600 index_app_info_from_parser(parser, db, cache)
558601
602
559def update_from_appstream_xml(db, cache, xmldir=None):603def update_from_appstream_xml(db, cache, xmldir=None):
560 if not xmldir:604 if not xmldir:
561 xmldir = softwarecenter.paths.APPSTREAM_XML_PATH605 xmldir = softwarecenter.paths.APPSTREAM_XML_PATH
@@ -573,12 +617,13 @@
573 update_from_single_appstream_file(db, cache, appstream_xml)617 update_from_single_appstream_file(db, cache, appstream_xml)
574 return True618 return True
575619
620
576def update_from_app_install_data(db, cache, datadir=None):621def update_from_app_install_data(db, cache, datadir=None):
577 """ index the desktop files in $datadir/desktop/*.desktop """622 """ index the desktop files in $datadir/desktop/*.desktop """
578 if not datadir:623 if not datadir:
579 datadir = softwarecenter.paths.APP_INSTALL_DESKTOP_PATH624 datadir = softwarecenter.paths.APP_INSTALL_DESKTOP_PATH
580 context = GObject.main_context_default()625 context = GObject.main_context_default()
581 for desktopf in glob(datadir+"/*.desktop"):626 for desktopf in glob(datadir + "/*.desktop"):
582 LOG.debug("processing %s" % desktopf)627 LOG.debug("processing %s" % desktopf)
583 # process events628 # process events
584 while context.pending():629 while context.pending():
@@ -599,7 +644,9 @@
599 LOG.warning(warning_text)644 LOG.warning(warning_text)
600 return True645 return True
601646
602def add_from_purchased_but_needs_reinstall_data(purchased_but_may_need_reinstall_list, db, cache):647
648def add_from_purchased_but_needs_reinstall_data(
649 purchased_but_may_need_reinstall_list, db, cache):
603 """Add application that have been purchased but may require a reinstall650 """Add application that have been purchased but may require a reinstall
604651
605 This adds a inmemory database to the main db with the special652 This adds a inmemory database to the main db with the special
@@ -632,9 +679,10 @@
632 # add new in memory db to the main db679 # add new in memory db to the main db
633 db.add_database(db_purchased)680 db.add_database(db_purchased)
634 # return a query681 # return a query
635 query = xapian.Query("AH"+PURCHASED_NEEDS_REINSTALL_MAGIC_CHANNEL_NAME)682 query = xapian.Query("AH" + PURCHASED_NEEDS_REINSTALL_MAGIC_CHANNEL_NAME)
636 return query683 return query
637684
685
638def update_from_software_center_agent(db, cache, ignore_cache=False,686def update_from_software_center_agent(db, cache, ignore_cache=False,
639 include_sca_qa=False):687 include_sca_qa=False):
640 """ update index based on the software-center-agent data """688 """ update index based on the software-center-agent data """
@@ -644,6 +692,7 @@
644 sca.available = available692 sca.available = available
645 sca.good_data = True693 sca.good_data = True
646 loop.quit()694 loop.quit()
695
647 def _error_cb(sca, error):696 def _error_cb(sca, error):
648 LOG.warn("error: %s" % error)697 LOG.warn("error: %s" % error)
649 sca.available = []698 sca.available = []
@@ -690,10 +739,12 @@
690 # app name is the data739 # app name is the data
691 if parser.has_option_desktop("X-Ubuntu-Software-Center-Name"):740 if parser.has_option_desktop("X-Ubuntu-Software-Center-Name"):
692 name = parser.get_desktop("X-Ubuntu-Software-Center-Name")741 name = parser.get_desktop("X-Ubuntu-Software-Center-Name")
693 untranslated_name = parser.get_desktop("X-Ubuntu-Software-Center-Name", translated=False)742 untranslated_name = parser.get_desktop("X-Ubuntu-Software-Center-Name",
743 translated=False)
694 elif parser.has_option_desktop("X-GNOME-FullName"):744 elif parser.has_option_desktop("X-GNOME-FullName"):
695 name = parser.get_desktop("X-GNOME-FullName")745 name = parser.get_desktop("X-GNOME-FullName")
696 untranslated_name = parser.get_desktop("X-GNOME-FullName", translated=False)746 untranslated_name = parser.get_desktop("X-GNOME-FullName",
747 translated=False)
697 else:748 else:
698 name = parser.get_desktop("Name")749 name = parser.get_desktop("Name")
699 untranslated_name = parser.get_desktop("Name", translated=False)750 untranslated_name = parser.get_desktop("Name", translated=False)
@@ -713,16 +764,18 @@
713 arches = parser.get_desktop("X-AppInstall-Architectures")764 arches = parser.get_desktop("X-AppInstall-Architectures")
714 doc.add_value(XapianValues.ARCHIVE_ARCH, arches)765 doc.add_value(XapianValues.ARCHIVE_ARCH, arches)
715 native_archs = get_current_arch() in arches.split(',')766 native_archs = get_current_arch() in arches.split(',')
716 foreign_archs = list(set(arches.split(',')) & set(get_foreign_architectures()))767 foreign_archs = list(set(arches.split(',')) &
717 if not (native_archs or foreign_archs): return768 set(get_foreign_architectures()))
769 if not (native_archs or foreign_archs):
770 return
718 if not native_archs and foreign_archs:771 if not native_archs and foreign_archs:
719 pkgname_extension = ':' + foreign_archs[0]772 pkgname_extension = ':' + foreign_archs[0]
720 # package name773 # package name
721 pkgname = parser.get_desktop("X-AppInstall-Package") + pkgname_extension774 pkgname = parser.get_desktop("X-AppInstall-Package") + pkgname_extension
722 doc.add_term("AP"+pkgname)775 doc.add_term("AP" + pkgname)
723 if '-' in pkgname:776 if '-' in pkgname:
724 # we need this to work around xapian oddness777 # we need this to work around xapian oddness
725 doc.add_term(pkgname.replace('-','_'))778 doc.add_term(pkgname.replace('-', '_'))
726 doc.add_value(XapianValues.PKGNAME, pkgname)779 doc.add_value(XapianValues.PKGNAME, pkgname)
727 doc.add_value(XapianValues.DESKTOP_FILE, parser.desktopf)780 doc.add_value(XapianValues.DESKTOP_FILE, parser.desktopf)
728 # display name781 # display name
@@ -731,21 +784,21 @@
731 # cataloged_times784 # cataloged_times
732 if "catalogedtime" in axi_values:785 if "catalogedtime" in axi_values:
733 if pkgname in cataloged_times:786 if pkgname in cataloged_times:
734 doc.add_value(axi_values["catalogedtime"], 787 doc.add_value(axi_values["catalogedtime"],
735 xapian.sortable_serialise(cataloged_times[pkgname]))788 xapian.sortable_serialise(cataloged_times[pkgname]))
736 # pocket (main, restricted, ...)789 # pocket (main, restricted, ...)
737 if parser.has_option_desktop("X-AppInstall-Section"):790 if parser.has_option_desktop("X-AppInstall-Section"):
738 archive_section = parser.get_desktop("X-AppInstall-Section")791 archive_section = parser.get_desktop("X-AppInstall-Section")
739 doc.add_term("AS"+archive_section)792 doc.add_term("AS" + archive_section)
740 doc.add_value(XapianValues.ARCHIVE_SECTION, archive_section)793 doc.add_value(XapianValues.ARCHIVE_SECTION, archive_section)
741 # section (mail, base, ..)794 # section (mail, base, ..)
742 if pkgname in cache and cache[pkgname].candidate:795 if pkgname in cache and cache[pkgname].candidate:
743 section = cache[pkgname].section796 section = cache[pkgname].section
744 doc.add_term("AE"+section)797 doc.add_term("AE" + section)
745 # channel (third party stuff)798 # channel (third party stuff)
746 if parser.has_option_desktop("X-AppInstall-Channel"):799 if parser.has_option_desktop("X-AppInstall-Channel"):
747 archive_channel = parser.get_desktop("X-AppInstall-Channel")800 archive_channel = parser.get_desktop("X-AppInstall-Channel")
748 doc.add_term("AH"+archive_channel)801 doc.add_term("AH" + archive_channel)
749 doc.add_value(XapianValues.ARCHIVE_CHANNEL, archive_channel)802 doc.add_value(XapianValues.ARCHIVE_CHANNEL, archive_channel)
750 # signing key (third party)803 # signing key (third party)
751 if parser.has_option_desktop("X-AppInstall-Signing-Key-Id"):804 if parser.has_option_desktop("X-AppInstall-Signing-Key-Id"):
@@ -758,7 +811,7 @@
758 # date published811 # date published
759 if parser.has_option_desktop("X-AppInstall-Date-Published"):812 if parser.has_option_desktop("X-AppInstall-Date-Published"):
760 date_published = parser.get_desktop("X-AppInstall-Date-Published")813 date_published = parser.get_desktop("X-AppInstall-Date-Published")
761 if (date_published and 814 if (date_published and
762 re.match("\d+-\d+-\d+ \d+:\d+:\d+", date_published)):815 re.match("\d+-\d+-\d+ \d+:\d+:\d+", date_published)):
763 # strip the subseconds from the end of the published date string816 # strip the subseconds from the end of the published date string
764 date_published = str(date_published).split(".")[0]817 date_published = str(date_published).split(".")[0]
@@ -772,7 +825,7 @@
772 date_published_sec = time.mktime(825 date_published_sec = time.mktime(
773 time.strptime(date_published,826 time.strptime(date_published,
774 "%Y-%m-%d %H:%M:%S"))827 "%Y-%m-%d %H:%M:%S"))
775 doc.add_value(axi_values["catalogedtime"], 828 doc.add_value(axi_values["catalogedtime"],
776 xapian.sortable_serialise(date_published_sec))829 xapian.sortable_serialise(date_published_sec))
777 # purchased date830 # purchased date
778 if parser.has_option_desktop("X-AppInstall-Purchased-Date"):831 if parser.has_option_desktop("X-AppInstall-Purchased-Date"):
@@ -798,7 +851,7 @@
798 doc.add_value(XapianValues.ARCHIVE_PPA, archive_ppa)851 doc.add_value(XapianValues.ARCHIVE_PPA, archive_ppa)
799 # add archive origin data here so that its available even if852 # add archive origin data here so that its available even if
800 # the PPA is not (yet) enabled853 # the PPA is not (yet) enabled
801 doc.add_term("XOO"+"lp-ppa-%s" % archive_ppa.replace("/", "-"))854 doc.add_term("XOO" + "lp-ppa-%s" % archive_ppa.replace("/", "-"))
802 # screenshot (for third party)855 # screenshot (for third party)
803 if parser.has_option_desktop("X-AppInstall-Screenshot-Url"):856 if parser.has_option_desktop("X-AppInstall-Screenshot-Url"):
804 url = parser.get_desktop("X-AppInstall-Screenshot-Url")857 url = parser.get_desktop("X-AppInstall-Screenshot-Url")
@@ -836,15 +889,15 @@
836 doc.add_value(XapianValues.ICON, icon)889 doc.add_value(XapianValues.ICON, icon)
837 # write out categories890 # write out categories
838 for cat in parser.get_desktop_categories():891 for cat in parser.get_desktop_categories():
839 doc.add_term("AC"+cat.lower())892 doc.add_term("AC" + cat.lower())
840 categories_string = ";".join(parser.get_desktop_categories())893 categories_string = ";".join(parser.get_desktop_categories())
841 doc.add_value(XapianValues.CATEGORIES, categories_string)894 doc.add_value(XapianValues.CATEGORIES, categories_string)
842 for mime in parser.get_desktop_mimetypes():895 for mime in parser.get_desktop_mimetypes():
843 doc.add_term("AM"+mime.lower())896 doc.add_term("AM" + mime.lower())
844 # get type (to distinguish between apps and packages897 # get type (to distinguish between apps and packages
845 if parser.has_option_desktop("Type"):898 if parser.has_option_desktop("Type"):
846 type = parser.get_desktop("Type")899 type = parser.get_desktop("Type")
847 doc.add_term("AT"+type.lower())900 doc.add_term("AT" + type.lower())
848 # check gettext domain901 # check gettext domain
849 if parser.has_option_desktop("X-Ubuntu-Gettext-Domain"):902 if parser.has_option_desktop("X-Ubuntu-Gettext-Domain"):
850 domain = parser.get_desktop("X-Ubuntu-Gettext-Domain")903 domain = parser.get_desktop("X-Ubuntu-Gettext-Domain")
@@ -867,14 +920,14 @@
867 tags = parser.get_desktop("X-AppInstall-Tags")920 tags = parser.get_desktop("X-AppInstall-Tags")
868 if tags:921 if tags:
869 for tag in tags.split(","):922 for tag in tags.split(","):
870 doc.add_term("XT"+tag.strip())923 doc.add_term("XT" + tag.strip())
871 # ENFORCE region blacklist by not registering the app at all924 # ENFORCE region blacklist by not registering the app at all
872 region = get_region_cached()925 region = get_region_cached()
873 if region:926 if region:
874 countrycode = region["countrycode"].lower()927 countrycode = region["countrycode"].lower()
875 if "%s%s" % (REGION_BLACKLIST_TAG, countrycode) in tags:928 if "%s%s" % (REGION_BLACKLIST_TAG, countrycode) in tags:
876 LOG.info("skipping region restricted app: '%s'" % name)929 LOG.info("skipping region restricted app: '%s'" % name)
877 return None930 return
878931
879 # popcon932 # popcon
880 # FIXME: popularity not only based on popcon but also933 # FIXME: popularity not only based on popcon but also
@@ -882,7 +935,7 @@
882 if parser.has_option_desktop("X-AppInstall-Popcon"):935 if parser.has_option_desktop("X-AppInstall-Popcon"):
883 popcon = float(parser.get_desktop("X-AppInstall-Popcon"))936 popcon = float(parser.get_desktop("X-AppInstall-Popcon"))
884 # sort_by_value uses string compare, so we need to pad here937 # sort_by_value uses string compare, so we need to pad here
885 doc.add_value(XapianValues.POPCON, 938 doc.add_value(XapianValues.POPCON,
886 xapian.sortable_serialise(popcon))939 xapian.sortable_serialise(popcon))
887 global popcon_max940 global popcon_max
888 popcon_max = max(popcon_max, popcon)941 popcon_max = max(popcon_max, popcon)
@@ -922,7 +975,7 @@
922 doc = make_doc_from_parser(parser, cache)975 doc = make_doc_from_parser(parser, cache)
923 if not doc:976 if not doc:
924 LOG.debug("make_doc_from_parser() returned '%s', ignoring" % doc)977 LOG.debug("make_doc_from_parser() returned '%s', ignoring" % doc)
925 return 978 return
926 term_generator.set_document(doc)979 term_generator.set_document(doc)
927 name = doc.get_data()980 name = doc.get_data()
928981
@@ -935,10 +988,11 @@
935988
936 pkgname = doc.get_value(XapianValues.PKGNAME)989 pkgname = doc.get_value(XapianValues.PKGNAME)
937 # add packagename as meta-data too990 # add packagename as meta-data too
938 term_generator.index_text_without_positions(pkgname, WEIGHT_APT_PKGNAME)991 term_generator.index_text_without_positions(pkgname,
992 WEIGHT_APT_PKGNAME)
939993
940 # now add search data from the desktop file994 # now add search data from the desktop file
941 for key in ["GenericName","Comment", "X-AppInstall-Description"]:995 for key in ["GenericName", "Comment", "X-AppInstall-Description"]:
942 if not parser.has_option_desktop(key):996 if not parser.has_option_desktop(key):
943 continue997 continue
944 s = parser.get_desktop(key)998 s = parser.get_desktop(key)
@@ -954,15 +1008,17 @@
954 # add data from the apt cache1008 # add data from the apt cache
955 if pkgname in cache and cache[pkgname].candidate:1009 if pkgname in cache and cache[pkgname].candidate:
956 s = cache[pkgname].candidate.summary1010 s = cache[pkgname].candidate.summary
957 term_generator.index_text_without_positions(s, WEIGHT_APT_SUMMARY)1011 term_generator.index_text_without_positions(s,
1012 WEIGHT_APT_SUMMARY)
958 s = cache[pkgname].candidate.description1013 s = cache[pkgname].candidate.description
959 term_generator.index_text_without_positions(s, WEIGHT_APT_DESCRIPTION)1014 term_generator.index_text_without_positions(s,
1015 WEIGHT_APT_DESCRIPTION)
960 for origin in cache[pkgname].candidate.origins:1016 for origin in cache[pkgname].candidate.origins:
961 doc.add_term("XOA"+origin.archive)1017 doc.add_term("XOA" + origin.archive)
962 doc.add_term("XOC"+origin.component)1018 doc.add_term("XOC" + origin.component)
963 doc.add_term("XOL"+origin.label)1019 doc.add_term("XOL" + origin.label)
964 doc.add_term("XOO"+origin.origin)1020 doc.add_term("XOO" + origin.origin)
965 doc.add_term("XOS"+origin.site)1021 doc.add_term("XOS" + origin.site)
9661022
967 # add our keywords (with high priority)1023 # add our keywords (with high priority)
968 keywords = None1024 keywords = None
@@ -973,16 +1029,18 @@
973 if keywords:1029 if keywords:
974 for s in keywords.split(";"):1030 for s in keywords.split(";"):
975 if s:1031 if s:
976 term_generator.index_text_without_positions(s, WEIGHT_DESKTOP_KEYWORD)1032 term_generator.index_text_without_positions(s,
1033 WEIGHT_DESKTOP_KEYWORD)
977 # now add it1034 # now add it
978 db.add_document(doc)1035 db.add_document(doc)
9791036
1037
980def rebuild_database(pathname, debian_sources=True, appstream_sources=False):1038def rebuild_database(pathname, debian_sources=True, appstream_sources=False):
981 #cache = apt.Cache(memonly=True)1039 #cache = apt.Cache(memonly=True)
982 cache = get_pkg_info()1040 cache = get_pkg_info()
983 cache.open()1041 cache.open()
984 old_path = pathname+"_old"1042 old_path = pathname + "_old"
985 rebuild_path = pathname+"_rb"1043 rebuild_path = pathname + "_rb"
9861044
987 if not os.path.exists(rebuild_path):1045 if not os.path.exists(rebuild_path):
988 try:1046 try:
@@ -1000,7 +1058,8 @@
10001058
1001 #check if old unrequired version of db still exists on filesystem1059 #check if old unrequired version of db still exists on filesystem
1002 if os.path.exists(old_path):1060 if os.path.exists(old_path):
1003 LOG.warn("Existing xapian old db was not previously cleaned: '%s'." % old_path)1061 LOG.warn("Existing xapian old db was not previously cleaned: '%s'." %
1062 old_path)
1004 if os.access(old_path, os.W_OK):1063 if os.access(old_path, os.W_OK):
1005 #remove old unrequired db before beginning1064 #remove old unrequired db before beginning
1006 shutil.rmtree(old_path)1065 shutil.rmtree(old_path)
@@ -1009,7 +1068,6 @@
1009 LOG.warn("Please check you have the relevant permissions.")1068 LOG.warn("Please check you have the relevant permissions.")
1010 return False1069 return False
10111070
1012
1013 # write it1071 # write it
1014 db = xapian.WritableDatabase(rebuild_path, xapian.DB_CREATE_OR_OVERWRITE)1072 db = xapian.WritableDatabase(rebuild_path, xapian.DB_CREATE_OR_OVERWRITE)
10151073
@@ -1017,7 +1075,8 @@
1017 update(db, cache)1075 update(db, cache)
1018 if appstream_sources:1076 if appstream_sources:
1019 if os.path.exists('./data/app-stream/appdata.xml'):1077 if os.path.exists('./data/app-stream/appdata.xml'):
1020 update_from_appstream_xml(db, cache, './data/app-stream/appdata.xml');1078 update_from_appstream_xml(db, cache,
1079 './data/app-stream/appdata.xml')
1021 else:1080 else:
1022 update_from_appstream_xml(db, cache)1081 update_from_appstream_xml(db, cache)
10231082
@@ -1038,5 +1097,6 @@
1038 shutil.rmtree(old_path)1097 shutil.rmtree(old_path)
1039 return True1098 return True
1040 except:1099 except:
1041 LOG.warn("Cannot copy refreshed database to correct location: '%s'." % pathname)1100 LOG.warn("Cannot copy refreshed database to correct location: '%s'." %
1101 pathname)
1042 return False1102 return False
10431103
=== modified file 'softwarecenter/db/utils.py'
--- softwarecenter/db/utils.py 2012-02-17 14:23:58 +0000
+++ softwarecenter/db/utils.py 2012-03-15 04:06:19 +0000
@@ -18,18 +18,20 @@
1818
19import xapian19import xapian
2020
21
21def get_query_for_pkgnames(pkgnames):22def get_query_for_pkgnames(pkgnames):
22 """ return a xapian query that matches exactly the list of pkgnames """23 """ return a xapian query that matches exactly the list of pkgnames """
23 query = xapian.Query()24 query = xapian.Query()
24 for pkgname in pkgnames:25 for pkgname in pkgnames:
25 query = xapian.Query(xapian.Query.OP_OR,26 query = xapian.Query(xapian.Query.OP_OR,
26 query,27 query,
27 xapian.Query("XP"+pkgname))28 xapian.Query("XP" + pkgname))
28 query = xapian.Query(xapian.Query.OP_OR,29 query = xapian.Query(xapian.Query.OP_OR,
29 query,30 query,
30 xapian.Query("AP"+pkgname))31 xapian.Query("AP" + pkgname))
31 return query32 return query
32 33
34
33def get_installed_apps_list(db):35def get_installed_apps_list(db):
34 """ return a list of installed applications """36 """ return a list of installed applications """
35 apps = set()37 apps = set()
@@ -41,11 +43,12 @@
41 apps.add(db.get_application(doc))43 apps.add(db.get_application(doc))
42 return apps44 return apps
4345
46
44def get_installed_package_list():47def get_installed_package_list():
45 """ return a set of all of the currently installed packages """48 """ return a set of all of the currently installed packages """
46 from softwarecenter.db.pkginfo import get_pkg_info49 from softwarecenter.db.pkginfo import get_pkg_info
47 installed_pkgs = set()50 installed_pkgs = set()
48 cache=get_pkg_info()51 cache = get_pkg_info()
49 for pkg in cache:52 for pkg in cache:
50 if pkg.is_installed:53 if pkg.is_installed:
51 installed_pkgs.add(pkg.name)54 installed_pkgs.add(pkg.name)
5255
=== modified file 'test/test_pep8.py'
--- test/test_pep8.py 2012-03-15 04:06:19 +0000
+++ test/test_pep8.py 2012-03-15 04:06:19 +0000
@@ -7,16 +7,15 @@
7setup_test_env()7setup_test_env()
88
9# Only test these two packages for now:9# Only test these two packages for now:
10import softwarecenter.db.pkginfo_impl10import softwarecenter.db
11import softwarecenter.ui.gtk311import softwarecenter.ui
12import softwarecenter.ui.qml
1312
14class PackagePep8TestCase(unittest.TestCase):13class PackagePep8TestCase(unittest.TestCase):
15 maxDiff = None14 maxDiff = None
16 packages = [softwarecenter.ui.qml,15 packages = [softwarecenter.ui,
17 softwarecenter.ui.gtk3,16 softwarecenter.db]
18 softwarecenter.db.pkginfo_impl]17 exclude = ['history.py', 'enquire.py', 'debfile.py', 'database.py',
19 exclude = []18 'categories.py', 'application.py', 'appfilter.py', '__init__.py']
2019
21 def message(self, text):20 def message(self, text):
22 self.errors.append(text)21 self.errors.append(text)