Merge lp:~mvo/software-center/unity-lens-plus-wildcard-fix into lp:software-center

Proposed by Michael Vogt
Status: Merged
Merged at revision: 3124
Proposed branch: lp:~mvo/software-center/unity-lens-plus-wildcard-fix
Merge into: lp:software-center
Diff against target: 454 lines (+155/-45)
13 files modified
apt_xapian_index_plugin/software_center.py (+6/-1)
data/software-center.menu.in (+20/-6)
setup.py (+4/-4)
softwarecenter/db/categories.py (+4/-2)
softwarecenter/db/database.py (+2/-0)
softwarecenter/db/update.py (+5/-5)
softwarecenter/enums.py (+4/-4)
softwarecenter/ui/gtk3/panes/availablepane.py (+9/-0)
softwarecenter/utils.py (+2/-3)
softwarecenter/version.py (+2/-2)
tests/test_database.py (+57/-17)
tests/test_xapian.py (+28/-1)
tests/utils.py (+12/-0)
To merge this branch: bzr merge lp:~mvo/software-center/unity-lens-plus-wildcard-fix
Reviewer Review Type Date Requested Status
Gary Lasker (community) Approve
Review via email: mp+120152@code.launchpad.net

Description of the change

This branch adds a "Dash Search Plugins" subcategory to Tweaks&Themes.
It also adds a workaround for a bug that the xapian query parser will
not work if there is a "-" in the query term

To post a comment you must log in.
Revision history for this message
Gary Lasker (gary-lasker) wrote :

Hi Michael, and thanks for doing this work. So, I can see the "Dash Search Plugins" subcategory in the Tweaks&Themes section, and it shows two lenses - the AskUbuntu lens and a Wikipedia lens. However, if I search all categories for the string "unity-lens-" I can actually see quite a few more lenses that are hidden in the technical items. I'm not quite sure how we want to fix this, or even if it is a problem. It seems, however, that we'll want all of the lenses to appear in the subcategory. Please let me know what you think.

Also, could you please describe just a little more detail about the Xapian workaround you added? Is there a bug for this issue by chance? Maybe you could provide a test case to demonstrate how the error is manifested?

Finally, I am getting an error in the new unit test that you added to test_xapian.py. It seems I'm not getting any results back for the query. Possibly it's something simple on my end. Please let me know. Here's the error:

PYTHONPATH=. python tests/test_xapian.py
F......No handlers could be found for logger "softwarecenter.distro.ubuntu"
.
======================================================================
FAIL: test_wildcard_bug1025579_workaround (__main__.AptXapianIndexTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_xapian.py", line 126, in test_wildcard_bug1025579_workaround
    self.assertNotEqual(len(mset), 0)
AssertionError: 0 == 0

----------------------------------------------------------------------
Ran 8 tests in 0.097s

FAILED (failures=1)

Many thanks!

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

This code looks good and I'll set it as approved so as not to block it. We can tweak if needed/as needed in future branches, and this gets us the feature which is excellent. Michael, please just take a look at the unit test issue. I'm sure it's passing on your machine so I'm probably just missing something on my end.

Thanks again for this! It's great to have this for FF.

review: Approve
Revision history for this message
Michael Vogt (mvo) wrote :

Thanks for the review Gary. Its probably failing for you because you are not using the current quantal version of apt-xapian-index that I uploaded to fix the same problem in there too (that "-" is special). I will add a test skip decorator probably that tests for the version of a-x-i.

3109. By Michael Vogt

tests/test_xapian.py: skip test for wildcard bug1026679 as the fix was added in quantals apt-xapian-index only

3110. By Michael Vogt

update db schema because we have the new APM key and add test for ensuring that the APM values are setup correclty

3111. By Michael Vogt

use xapian.inmemory_open() for DB tests that do not need to be persistent

3112. By Michael Vogt

add explicit testcase for the xapian query parser "-" workaround/bug

3113. By Michael Vogt

tests/test_database.py: reference the upstream xapian ticket

3114. By Michael Vogt

apt_xapian_index_plugin/software_center.py: include package name terms in a-x-i plugin too

3115. By Michael Vogt

make sure category flags are applied for subcategories as well

3116. By Michael Vogt

data/software-center.menu.in: add nonapps-visible flag to unity-lens

Revision history for this message
Michael Vogt (mvo) wrote :

On Sat, Aug 18, 2012 at 06:39:17AM -0000, Gary Lasker wrote:
> Hi Michael, and thanks for doing this work. So, I can see the "Dash Search Plugins" subcategory in the Tweaks&Themes section, and it shows two lenses - the AskUbuntu lens and a Wikipedia lens. However, if I search all categories for the string "unity-lens-" I can actually see quite a few more lenses that are hidden in the technical items. I'm not quite sure how we want to fix this, or even if it is a problem. It seems, however, that we'll want all of the lenses to appear in the subcategory. Please let me know what you think.

Thanks for the review. There was a flag missing to always make the
nonapps visible. There was also a bug in the subcategory part of the
available pane that prevented the flag from getting used. This should
all be fixed now.

> Also, could you please describe just a little more detail about the Xapian workaround you added? Is there a bug for this issue by chance? Maybe you could provide a test case to demonstrate how the error is manifested?

I added a TestCase for tihs now, it includes a link to the quoting
problem of the xapian query parser (http://trac.xapian.org/ticket/128)

> Finally, I am getting an error in the new unit test that you added to test_xapian.py. It seems I'm not getting any results back for the query. Possibly it's something simple on my end. Please let me know. Here's the error:
[..]

This seems to be caused by running on precise, I exclude this test
now if precise is used, there is no "XPM" term in the xapian db on
precise.

Cheers and enjoy your vacation.

Cheers,
 Michael

3117. By Michael Vogt

pep8 fixes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'apt_xapian_index_plugin/software_center.py'
2--- apt_xapian_index_plugin/software_center.py 2012-07-02 09:51:31 +0000
3+++ apt_xapian_index_plugin/software_center.py 2012-08-21 13:19:20 +0000
4@@ -10,7 +10,10 @@
5 CustomKeys,
6 XapianValues,
7 )
8-from softwarecenter.db.update import WEIGHT_DESKTOP_NAME
9+from softwarecenter.db.update import (
10+ WEIGHT_DESKTOP_NAME,
11+ get_pkgname_terms,
12+ )
13 from softwarecenter.distro import get_distro
14
15
16@@ -104,6 +107,8 @@
17 # add s-c values/terms for the name
18 document.add_term("AA"+name)
19 document.add_value(XapianValues.APPNAME, name)
20+ for t in get_pkgname_terms(pkg.name):
21+ document.add_term(t)
22 self.indexer.index_text_without_positions(
23 name, WEIGHT_DESKTOP_NAME)
24 # we pretend to be an application
25
26=== modified file 'data/software-center.menu.in'
27--- data/software-center.menu.in 2012-05-15 02:39:12 +0000
28+++ data/software-center.menu.in 2012-08-21 13:19:20 +0000
29@@ -332,16 +332,13 @@
30 <Include>
31 <And>
32 <Or>
33- <SCPkgnameWildcard>ttf*</SCPkgnameWildcard>
34- <SCPkgnameWildcard>otf*</SCPkgnameWildcard>
35+ <SCPkgnameWildcard>ttf-*</SCPkgnameWildcard>
36+ <SCPkgnameWildcard>otf-*</SCPkgnameWildcard>
37 <SCSection>fonts</SCSection>
38 <SCSection>restricted/fonts</SCSection>
39 <SCSection>universe/fonts</SCSection>
40 <SCSection>multiverse/fonts</SCSection>
41 </Or>
42- <Not>
43- <SCPkgname>ttfm</SCPkgname>
44- </Not>
45 </And>
46 </Include>
47 </Menu>
48@@ -528,7 +525,24 @@
49 <Menu>
50 <_Name>Themes &amp; Tweaks</_Name>
51 <SCIcon>preferences-other</SCIcon>
52- <Include><Category>Settings</Category></Include>
53+ <Include>
54+ <Category>Settings</Category>
55+ </Include>
56+
57+ <!-- Sub-categories for the Themes -->
58+ <Menu>
59+ <_Name>Dash Search Plugins</_Name>
60+ <Flags>
61+ <Flag>nonapps-visible</Flag>
62+ </Flags>
63+ <SCIcon>preferences-other</SCIcon>
64+ <Include>
65+ <And>
66+ <SCPkgnameWildcard>unity-lens-*</SCPkgnameWildcard>
67+ </And>
68+ </Include>
69+ </Menu>
70+
71 </Menu>
72
73 <!-- System -->
74
75=== modified file 'setup.py'
76--- setup.py 2012-07-23 11:48:24 +0000
77+++ setup.py 2012-08-21 13:19:20 +0000
78@@ -69,10 +69,10 @@
79 DISTRO = platform.dist()[0]
80 RELEASE = platform.dist()[1]
81 open("softwarecenter/version.py", "w").write("""
82-VERSION='%s'
83-CODENAME='%s'
84-DISTRO='%s'
85-RELEASE='%s'
86+VERSION = '%s'
87+CODENAME = '%s'
88+DISTRO = '%s'
89+RELEASE = '%s'
90 """ % (VERSION, CODENAME, DISTRO, RELEASE))
91
92
93
94=== modified file 'softwarecenter/db/categories.py'
95--- softwarecenter/db/categories.py 2012-08-17 07:46:59 +0000
96+++ softwarecenter/db/categories.py 2012-08-21 13:19:20 +0000
97@@ -399,8 +399,10 @@
98 query = xapian.Query(xapian_op, query, q)
99 elif operator_elem.tag == "SCPkgnameWildcard":
100 LOG.debug("adding tag: %s" % operator_elem.text)
101- # query both axi and s-c
102- s = "pkg_wildcard:%s" % qtext
103+ # query both axi and s-c and ensure that the pkgname is
104+ # mangled to workaround xapians query parser lack of
105+ # quoting :/
106+ s = "pkg_wildcard:%s" % qtext.replace("-", "_")
107 q = self.db.xapian_parser.parse_query(s,
108 xapian.QueryParser.FLAG_WILDCARD)
109 query = xapian.Query(xapian_op, query, q)
110
111=== modified file 'softwarecenter/db/database.py'
112--- softwarecenter/db/database.py 2012-08-14 14:45:47 +0000
113+++ softwarecenter/db/database.py 2012-08-21 13:19:20 +0000
114@@ -204,7 +204,9 @@
115 xapian_parser.add_boolean_prefix("section", "XS")
116 xapian_parser.add_boolean_prefix("origin", "XOC")
117 xapian_parser.add_prefix("pkg_wildcard", "XP")
118+ xapian_parser.add_prefix("pkg_wildcard", "XPM")
119 xapian_parser.add_prefix("pkg_wildcard", "AP")
120+ xapian_parser.add_prefix("pkg_wildcard", "APM")
121 xapian_parser.set_default_op(xapian.Query.OP_AND)
122 return xapian_parser
123
124
125=== modified file 'softwarecenter/db/update.py'
126--- softwarecenter/db/update.py 2012-08-01 04:37:06 +0000
127+++ softwarecenter/db/update.py 2012-08-21 13:19:20 +0000
128@@ -118,10 +118,10 @@
129
130
131 def get_pkgname_terms(pkgname):
132- result = ["AP" + pkgname]
133- if '-' in pkgname:
134- # we need this to work around xapian oddness
135- result.append(pkgname.replace('-', '_'))
136+ result = ["AP" + pkgname,
137+ # workaround xapian oddness by providing a "mangled" version
138+ # with a different prefix
139+ "APM" + pkgname.replace('-', '_')]
140 return result
141
142
143@@ -239,7 +239,7 @@
144 doc_key = self.FIELD_TO_XAPIAN[key]
145 doc.add_value(doc_key, value)
146 # add terms to the xapian database
147- get_terms = self.FIELD_TO_TERMS.get(key, lambda i: i)
148+ get_terms = self.FIELD_TO_TERMS.get(key, lambda i: [])
149 for t in get_terms(value):
150 doc.add_term(t)
151
152
153=== modified file 'softwarecenter/enums.py'
154--- softwarecenter/enums.py 2012-08-01 04:26:27 +0000
155+++ softwarecenter/enums.py 2012-08-21 13:19:20 +0000
156@@ -61,7 +61,7 @@
157
158 # version of the database, every time something gets added (like
159 # terms for mime-type) increase this (but keep as a string!)
160-DB_SCHEMA_VERSION = "6"
161+DB_SCHEMA_VERSION = "7"
162
163 # the default limit for a search
164 DEFAULT_SEARCH_LIMIT = 10000
165@@ -253,9 +253,9 @@
166
167 # visibility of non applications in the search results
168 class NonAppVisibility:
169- (ALWAYS_VISIBLE,
170- MAYBE_VISIBLE,
171- NEVER_VISIBLE) = range(3)
172+ ALWAYS_VISIBLE = "non-apps-always-visible"
173+ MAYBE_VISIBLE = "non-apps-maybe-visible"
174+ NEVER_VISIBLE = "non-apps-never-visible"
175
176
177 # application actions
178
179=== modified file 'softwarecenter/ui/gtk3/panes/availablepane.py'
180--- softwarecenter/ui/gtk3/panes/availablepane.py 2012-07-19 09:37:04 +0000
181+++ softwarecenter/ui/gtk3/panes/availablepane.py 2012-08-21 13:19:20 +0000
182@@ -696,7 +696,9 @@
183
184 def display_app_view_page(self, view_state):
185 category = view_state.category
186+ subcategory = view_state.subcategory
187 self.set_category(category)
188+ self.set_subcategory(subcategory)
189
190 result = self.display_list_page(view_state)
191
192@@ -790,10 +792,17 @@
193 current_page = self.notebook.get_current_page()
194 return current_page == self.Pages.PURCHASE
195
196+ def set_subcategory(self, subcategory):
197+ LOG.debug('set_subcategory: %s' % subcategory)
198+ self.state.subcategory = subcategory
199+ self._apply_filters_for_category_or_subcategory(subcategory)
200+
201 def set_category(self, category):
202 LOG.debug('set_category: %s' % category)
203 self.state.category = category
204+ self._apply_filters_for_category_or_subcategory(category)
205
206+ def _apply_filters_for_category_or_subcategory(self, category):
207 # apply flags
208 if category:
209 if 'nonapps-visible' in category.flags:
210
211=== modified file 'softwarecenter/utils.py'
212--- softwarecenter/utils.py 2012-08-16 14:44:29 +0000
213+++ softwarecenter/utils.py 2012-08-21 13:19:20 +0000
214@@ -663,9 +663,8 @@
215 # set new global datadir
216 softwarecenter.paths.datadir = datadir
217 # also alter the app-install path
218- path = "%s/desktop/software-center.menu" % \
219- softwarecenter.paths.APP_INSTALL_PATH
220- if not os.path.exists(path):
221+ path = "./build/share/app-install/desktop/software-center.menu"
222+ if os.path.exists(path):
223 softwarecenter.paths.APP_INSTALL_PATH = './build/share/app-install'
224 logging.warn("using local APP_INSTALL_PATH: %s" %
225 softwarecenter.paths.APP_INSTALL_PATH)
226
227=== modified file 'softwarecenter/version.py'
228--- softwarecenter/version.py 2012-08-01 04:37:06 +0000
229+++ softwarecenter/version.py 2012-08-21 13:19:20 +0000
230@@ -1,5 +1,5 @@
231
232-VERSION = '5.3.3.1'
233-CODENAME = 'quantal'
234+VERSION = '5.3.7'
235+CODENAME = 'UNRELEASED'
236 DISTRO = 'Ubuntu'
237 RELEASE = '12.10'
238
239=== modified file 'tests/test_database.py'
240--- tests/test_database.py 2012-08-15 12:11:14 +0000
241+++ tests/test_database.py 2012-08-21 13:19:20 +0000
242@@ -13,6 +13,7 @@
243 from tests.utils import (
244 DATA_DIR,
245 get_test_db,
246+ get_test_db_from_app_install_data,
247 get_test_pkg_info,
248 do_events,
249 make_software_center_agent_subscription_dict,
250@@ -77,24 +78,26 @@
251 self.assertEqual(res, [ v2, v1, v0 ])
252
253
254+ def _get_db_from_test_app_install_data(self):
255+ db = xapian.inmemory_open()
256+ res = update_from_app_install_data(db, self.cache,
257+ datadir=os.path.join(DATA_DIR, "desktop"))
258+ self.assertTrue(res)
259+ self.assertEqual(db.get_doccount(), 5)
260+ return db
261+
262 def test_update_from_desktop_file(self):
263 # ensure we index with german locales to test i18n
264 os.environ["LANGUAGE"] = "de"
265- db = xapian.WritableDatabase(TEST_DB,
266- xapian.DB_CREATE_OR_OVERWRITE)
267- res = update_from_app_install_data(db, self.cache,
268- datadir=os.path.join(DATA_DIR, "desktop"))
269- self.assertTrue(res)
270- self.assertEqual(db.get_doccount(), 5)
271+ datadir = os.path.join(DATA_DIR, "desktop")
272+ db = get_test_db_from_app_install_data(datadir)
273 # test if Name[de] was picked up
274 i=0
275 for it in db.postlist("AAUbuntu Software Zentrum"):
276 i+=1
277- self.assertEqual(i, 1)
278
279 def test_update_from_appstream_xml(self):
280- db = xapian.WritableDatabase(TEST_DB,
281- xapian.DB_CREATE_OR_OVERWRITE)
282+ db = xapian.inmemory_open()
283 res = update_from_appstream_xml(db, self.cache,
284 os.path.join(DATA_DIR, "app-info"))
285 self.assertTrue(res)
286@@ -113,8 +116,7 @@
287 def test_update_from_var_lib_apt_lists(self):
288 # ensure we index with german locales to test i18n
289 os.environ["LANGUAGE"] = "de"
290- db = xapian.WritableDatabase(TEST_DB,
291- xapian.DB_CREATE_OR_OVERWRITE)
292+ db = xapian.inmemory_open()
293 res = update_from_var_lib_apt_lists(db, self.cache,
294 listsdir=os.path.join(DATA_DIR, "app-info"))
295 self.assertTrue(res)
296@@ -137,8 +139,7 @@
297 self.assertTrue(found_gettext_translation)
298
299 def test_update_from_json_string(self):
300- db = xapian.WritableDatabase(TEST_DB,
301- xapian.DB_CREATE_OR_OVERWRITE)
302+ db = xapian.inmemory_open()
303 cache = apt.Cache()
304 p = os.path.join(DATA_DIR, "app-info-json", "apps.json")
305 res = update_from_json_string(db, cache, open(p).read(), origin=p)
306@@ -146,8 +147,7 @@
307 self.assertEqual(db.get_doccount(), 1)
308
309 def test_build_from_software_center_agent(self):
310- db = xapian.WritableDatabase(TEST_DB,
311- xapian.DB_CREATE_OR_OVERWRITE)
312+ db = xapian.inmemory_open()
313 cache = apt.Cache()
314 # monkey patch distro to ensure we get data
315 distro = softwarecenter.distro.get_distro()
316@@ -343,8 +343,7 @@
317 # staging does not have a valid cert
318 os.environ["PISTON_MINI_CLIENT_DISABLE_SSL_VALIDATION"] = "1"
319 cache = get_test_pkg_info()
320- db = xapian.WritableDatabase(TEST_DB,
321- xapian.DB_CREATE_OR_OVERWRITE)
322+ db = xapian.inmemory_open()
323 res = update_from_software_center_agent(db, cache, ignore_cache=True)
324 self.assertTrue(res)
325
326@@ -702,6 +701,47 @@
327 self.assertEqual(app.archive_suite, "")
328
329
330+class XapianQueryParserWorkarounds(unittest.TestCase):
331+ """This TestCase demonstrates the issues around the query
332+ parser wildcard support if the "-" char is part of the
333+ pkgname and tests the workaround for this
334+
335+ (http://trac.xapian.org/ticket/128)
336+ """
337+
338+ def setUp(self):
339+ datadir = os.path.join(DATA_DIR, "desktop")
340+ self.db = get_test_db_from_app_install_data(datadir)
341+
342+ def test_name_mangling_for_query_parser(self):
343+ # test that pkgnames with "-" get added in a mangled form
344+ i=0
345+ for it in self.db.postlist("APMsoftware_center"):
346+ i+=1
347+ self.assertEqual(i, 1)
348+
349+ def test_query_parser_wildcard(self):
350+ enquire = xapian.Enquire(self.db)
351+ parser = xapian.QueryParser()
352+ parser.set_database(self.db)
353+ parser.add_prefix("pkg_wildcard", "AP")
354+ # this demonstrates the xapian bug with the query parser
355+ # and "-" special chars, note that once this test fails (i.e.
356+ # the returned mset is "1" we can remove this workaround
357+ query = parser.parse_query(
358+ "pkg_wildcard:software-*", xapian.QueryParser.FLAG_WILDCARD)
359+ enquire.set_query(query)
360+ mset = enquire.get_mset(0, 100)
361+ self.assertEqual(len(mset), 0)
362+ # and the workaround
363+ parser.add_prefix("pkg_wildcard", "APM")
364+ query = parser.parse_query(
365+ "pkg_wildcard:software_*", xapian.QueryParser.FLAG_WILDCARD)
366+ enquire.set_query(query)
367+ mset = enquire.get_mset(0, 100)
368+ self.assertEqual(len(mset), 1)
369+
370+
371 class TrackDBTestCase(unittest.TestCase):
372
373 def test_track_db_open(self):
374
375=== modified file 'tests/test_xapian.py'
376--- tests/test_xapian.py 2012-07-02 09:51:31 +0000
377+++ tests/test_xapian.py 2012-08-21 13:19:20 +0000
378@@ -1,5 +1,6 @@
379+import os
380+import platform
381 import unittest
382-import os
383 import xapian
384
385 from mock import Mock, patch
386@@ -103,6 +104,31 @@
387 #print len(matches)
388 self.assertTrue(len(matches) > 0)
389
390+
391+class AptXapianIndexTestCase(unittest.TestCase):
392+
393+ # this will fail on precise so we skip the test there
394+ @unittest.skipIf(platform.dist()[2] == "precise" and
395+ not os.path.exists("/var/lib/apt-xapian-index/index"),
396+ "Need populated apt-xapian-index for this test")
397+ def test_wildcard_bug1025579_workaround(self):
398+ db = xapian.Database("/var/lib/apt-xapian-index/index")
399+ enquire = xapian.Enquire(db)
400+ parser = xapian.QueryParser()
401+ parser.set_database(db)
402+ # this is the gist, the mangled version of the XPM term
403+ parser.add_prefix("pkg_wildcard", "XPM")
404+ parser.add_prefix("pkg_wildcard", "XP")
405+ parser.add_prefix("pkg_wildcard", "AP")
406+ s = 'pkg_wildcard:unity_lens_*'
407+ query = parser.parse_query(s, xapian.QueryParser.FLAG_WILDCARD)
408+ enquire.set_query(query)
409+ mset = enquire.get_mset(0, 100)
410+ for m in mset:
411+ self.assertTrue(m.document.get_data().startswith("unity-lens-"))
412+ self.assertNotEqual(len(mset), 0)
413+
414+
415 class XapianPluginsTestCase(unittest.TestCase):
416
417 def make_mock_document(self):
418@@ -146,5 +172,6 @@
419 got_values.add(args[0])
420 self.assertTrue(expected_values.issubset(got_values))
421
422+
423 if __name__ == "__main__":
424 unittest.main()
425
426=== modified file 'tests/utils.py'
427--- tests/utils.py 2012-05-31 12:50:01 +0000
428+++ tests/utils.py 2012-08-21 13:19:20 +0000
429@@ -44,6 +44,8 @@
430 )
431 from softwarecenter.ui.gtk3.utils import get_sc_icon_theme
432 from softwarecenter.utils import get_uuid
433+from softwarecenter.db.update import update_from_app_install_data
434+
435
436 m_dbus = m_polkit = m_aptd = None
437
438@@ -107,6 +109,16 @@
439 return db
440
441
442+def get_test_db_from_app_install_data(datadir):
443+ db = xapian.inmemory_open()
444+ cache = get_pkg_info()
445+ cache.open()
446+ res = update_from_app_install_data(db, cache, datadir)
447+ if res is False:
448+ raise AssertionError("Failed to build db from '%s'" % datadir)
449+ return db
450+
451+
452 def get_test_install_backend():
453 backend = get_install_backend()
454 return backend

Subscribers

People subscribed via source and target branches