Merge lp:~canonical-isd-hackers/ubuntu-webcatalog/extract_788199 into lp:ubuntu-webcatalog

Proposed by Danny Tamez
Status: Merged
Approved by: Anthony Lenton
Approved revision: 18
Merged at revision: 16
Proposed branch: lp:~canonical-isd-hackers/ubuntu-webcatalog/extract_788199
Merge into: lp:ubuntu-webcatalog
Diff against target: 293 lines (+131/-59)
4 files modified
.bzrignore (+2/-0)
src/webcatalog/management/commands/import_app_install_data.py (+85/-56)
src/webcatalog/static/css/webcatalog.css (+4/-1)
src/webcatalog/tests/test_commands.py (+40/-2)
To merge this branch: bzr merge lp:~canonical-isd-hackers/ubuntu-webcatalog/extract_788199
Reviewer Review Type Date Requested Status
Anthony Lenton (community) Approve
Review via email: mp+63740@code.launchpad.net

Commit message

Adding app description to the app install data command

Description of the change

Adding description to the import app data command by creating a local apt-cache and getting the app's description from the cache.

To post a comment you must log in.
17. By Danny Tamez

Small refactor so that the cache is only gotten once when the command is run.
Also added a bit of css for .description.

18. By Danny Tamez

Moving the white-space css to the <p> element instead of applying to all
of the description.

Revision history for this message
Anthony Lenton (elachuni) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-04-13 09:28:55 +0000
3+++ .bzrignore 2011-06-07 20:56:40 +0000
4@@ -4,3 +4,5 @@
5 django_project/local_settings.py
6 django_project/static/
7 django_project/media_root_dev/*
8+.backup
9+tags
10
11=== modified file 'src/webcatalog/management/commands/import_app_install_data.py'
12--- src/webcatalog/management/commands/import_app_install_data.py 2011-05-06 13:34:39 +0000
13+++ src/webcatalog/management/commands/import_app_install_data.py 2011-06-07 20:56:40 +0000
14@@ -28,9 +28,9 @@
15 import urllib
16 from glob import iglob
17 from optparse import make_option
18-from StringIO import StringIO
19
20 import apt
21+from apt.cache import FetchFailedException
22 from apt_inst import DebFile
23 from django.core.files.images import ImageFile
24 from django.forms.models import construct_instance
25@@ -47,6 +47,36 @@
26 ]
27
28
29+class Cache(object):
30+
31+ def __init__(self, distroseries):
32+ self.distroseries = distroseries
33+
34+ def __enter__(self):
35+ tmp_sources_dir = tempfile.mkdtemp()
36+ self.tmp_sources_dir = tmp_sources_dir
37+ os.makedirs(os.path.join(tmp_sources_dir, 'etc', 'apt'))
38+ tmp_sources_list = os.path.join(
39+ tmp_sources_dir, 'etc', 'apt', 'sources.list')
40+ sources_list = open(tmp_sources_list, 'w+')
41+ sources_list.write(
42+ 'deb http://archive.ubuntu.com/ubuntu {0} main\n'.format(
43+ self.distroseries))
44+ sources_list.close()
45+
46+ cache = apt.Cache(rootdir=tmp_sources_dir, memonly=True)
47+ try:
48+ cache.update(sources_list=tmp_sources_list)
49+ except FetchFailedException:
50+ # Make sure __exit__ still gets called
51+ pass
52+ cache.open()
53+ return cache
54+
55+ def __exit__(self, exc_type, exc_value, exc_traceback):
56+ shutil.rmtree(self.tmp_sources_dir)
57+
58+
59 class Command(LabelCommand):
60
61 help = "Update Application data from app-install-data package."
62@@ -60,40 +90,43 @@
63 )
64 verbosity = 0
65
66- def handle_label(self, distroseries_name, **options):
67- self.verbosity = int(options['verbosity'])
68- data_dir = tempfile.mkdtemp()
69- distroseries, created = DistroSeries.objects.get_or_create(
70- code_name=distroseries_name)
71- if created and self.verbosity > 0:
72- self.stdout.write(
73- "Created a DistroSeries record with codename '{0}'.".format(
74- distroseries_name))
75-
76- # Download app install data when requested.
77- if options['local_app_install_deb'] == '':
78- deb_location = self.get_latest_app_data_for_series(
79- distroseries_name, working_dir=data_dir)
80- else:
81- deb_location = options['local_app_install_deb']
82-
83- # Extract and parse the deb archive.
84- deb_file = DebFile(deb_location)
85- if self.verbosity > 0:
86- self.stdout.write(
87- "Processing application data to update database...\n")
88- deb_file.data.extractall(data_dir)
89- matcher = data_dir + '/usr/share/app-install/desktop/*.desktop'
90- icon_dir = data_dir + '/usr/share/app-install/icons/'
91- for desktop_file in iglob(matcher):
92- self.process_desktop_file(desktop_file, icon_dir, distroseries)
93-
94- shutil.rmtree(data_dir)
95-
96- def get_latest_app_data_for_series(self, distroseries, working_dir):
97+ def handle_label(self, distroseries_name, **options):
98+ with Cache(distroseries_name) as cache:
99+ self.verbosity = int(options['verbosity'])
100+ data_dir = tempfile.mkdtemp()
101+ distroseries, created = DistroSeries.objects.get_or_create(
102+ code_name=distroseries_name)
103+ if created and self.verbosity > 0:
104+ self.stdout.write(
105+ "Created a DistroSeries record with codename '{0}'.".format(
106+ distroseries_name))
107+
108+ # Download app install data when requested.
109+ if options['local_app_install_deb'] == '':
110+ deb_location = self.get_latest_app_data_for_series(
111+ distroseries_name, data_dir, cache)
112+ else:
113+ deb_location = options['local_app_install_deb']
114+
115+ # Extract and parse the deb archive.
116+ deb_file = DebFile(deb_location)
117+ if self.verbosity > 0:
118+ self.stdout.write(
119+ "Processing application data to update database...\n")
120+ deb_file.data.extractall(data_dir)
121+ matcher = data_dir + '/usr/share/app-install/desktop/*.desktop'
122+ icon_dir = data_dir + '/usr/share/app-install/icons/'
123+
124+ for desktop_file in iglob(matcher):
125+ self.process_desktop_file(desktop_file, icon_dir, distroseries,
126+ cache)
127+
128+ shutil.rmtree(data_dir)
129+
130+ def get_latest_app_data_for_series(self, distroseries, working_dir, cache=None):
131 # Write a temporary sources.list, update the cache and access:
132 # cache['app-install-data-ubuntu'].candidate.uri
133- install_data_url = self.get_app_data_uri_for_series(distroseries)
134+ install_data_url = self.get_app_data_uri_for_series(distroseries, cache)
135 rest, sep, deb_filename = install_data_url.rpartition('/')
136
137 if self.verbosity > 0:
138@@ -106,34 +139,21 @@
139 self.stdout.write("Done.\n")
140 return deb_location
141
142- def get_app_data_uri_for_series(self, distroseries):
143- # Create a temporary apt cache to find the uri for the
144- # current version in the given series.
145+ def get_app_data_uri_for_series(self, distroseries, cache=None):
146 if self.verbosity > 0:
147 self.stdout.write(
148 "Determining URI for current version of "
149 "app-install-data in {0}.\n".format(distroseries))
150-
151- # First we create an appropriate temporary sources.list entry.
152- tmp_sources_dir = tempfile.mkdtemp()
153- os.makedirs(os.path.join(tmp_sources_dir, 'etc', 'apt'))
154- tmp_sources_list = os.path.join(
155- tmp_sources_dir, 'etc', 'apt', 'sources.list')
156- sources_list = open(tmp_sources_list, 'w+')
157- sources_list.write(
158- 'deb http://archive.ubuntu.com/ubuntu {0} main\n'.format(
159- distroseries))
160- sources_list.close()
161-
162- cache = apt.Cache(rootdir=tmp_sources_dir, memonly=True)
163- cache.update(sources_list=tmp_sources_list)
164- cache.open()
165- uri = cache['app-install-data'].candidate.uri
166-
167- shutil.rmtree(tmp_sources_dir)
168+ uri = None
169+ if cache == None:
170+ with Cache(distroseries) as cache:
171+ uri = cache['app-install-data'].candidate.uri
172+ else:
173+ uri = cache['app-install-data'].candidate.uri
174 return uri
175
176- def process_desktop_file(self, desktop_file_path, icon_dir, distroseries):
177+ def process_desktop_file(self, desktop_file_path, icon_dir, distroseries,
178+ cache):
179 with open(desktop_file_path, 'r') as desktop_file:
180 data = desktop_file.read()
181 form = ApplicationForm.get_form_from_desktop_data(data)
182@@ -152,6 +172,14 @@
183 else:
184 app = form.save(commit=False)
185 app.distroseries = distroseries
186+ # we don't have the description - just the desktop data, so:
187+ # use the package_name to lookup the app in the cache and get
188+ # the descrption from there
189+ try:
190+ cached_app = cache[app.package_name]
191+ app.description = cached_app.description
192+ except KeyError:
193+ pass
194 app.save()
195 app.update_departments()
196 self.add_icon_to_app(app, icon_dir)
197@@ -162,7 +190,8 @@
198 if self.verbosity > 0:
199 self.stdout.write(
200 u"Skipping {0} as input failed validation: {1}.\n".format(
201- member.name, form.errors).encode('utf-8'))
202+ form.cleaned_data['package_name'],
203+ form.errors).encode('utf-8'))
204
205 def add_icon_to_app(self, app, icon_dir):
206 # If the desktop file specifies an icon, we check for it in the
207
208=== modified file 'src/webcatalog/static/css/webcatalog.css'
209--- src/webcatalog/static/css/webcatalog.css 2011-05-06 15:03:41 +0000
210+++ src/webcatalog/static/css/webcatalog.css 2011-06-07 20:56:40 +0000
211@@ -38,7 +38,10 @@
212 font-size: 14px;
213 line-height: 1.3;
214 }
215-
216+.description p {
217+ white-space: pre-wrap;
218+ font-size:14px;
219+}
220 .screenshot {
221 float: right;
222 margin-right: 16px;
223
224=== modified file 'src/webcatalog/tests/test_commands.py'
225--- src/webcatalog/tests/test_commands.py 2011-05-06 13:38:50 +0000
226+++ src/webcatalog/tests/test_commands.py 2011-06-07 20:56:40 +0000
227@@ -21,6 +21,7 @@
228 absolute_import,
229 with_statement,
230 )
231+from apt.cache import Cache
232 import os
233 import shutil
234 import tempfile
235@@ -54,7 +55,10 @@
236 call_command('import_app_install_data', 'onion', verbosity=0)
237
238 self.assertEqual(1, mock_get_data_fn.call_count)
239- self.assertEqual(('onion', ), mock_get_data_fn.call_args[0])
240+ args = mock_get_data_fn.call_args[0]
241+ self.assertEqual('onion', args[0])
242+ self.assertTrue(args[1].startswith('/tmp/tmp'))
243+ self.assertTrue(isinstance(args[2], Cache))
244
245 def test_get_latest_app_data_for_series(self):
246 # Requested and downloaded from the server.
247@@ -72,7 +76,7 @@
248 'http://example.com/my.deb', os.path.join(tmp_dir, 'my.deb'))
249
250 def test_local_app_install_deb(self):
251- # We don't hit the network when provided a local app-install deb instead.
252+ # We don't hit the network when provided a local app-install deb.
253 with patch('urllib.urlretrieve') as mock_urlretrieve:
254 call_command('import_app_install_data', 'natty',
255 local_app_install_deb=self.factory.get_test_path(
256@@ -176,3 +180,37 @@
257 uri = Command().get_app_data_uri_for_series('natty')
258
259 self.assertEqual('http://example.com/my.deb', uri)
260+
261+ def test_description_added_to_app(self):
262+ self.assertEqual(0, Application.objects.count())
263+
264+ call_command(
265+ 'import_app_install_data', 'natty',
266+ local_app_install_deb=self.factory.get_test_path(
267+ 'app-install-data-test_all.deb'),
268+ verbosity=0)
269+
270+ self.assertEqual(2, Application.objects.count())
271+ firefox = Application.objects.get(package_name='firefox')
272+ scribus = Application.objects.get(package_name='scribus')
273+ firefox_description = 'Firefox delivers safe, easy web browsing.'
274+ scribus_description = 'Scribus is an open source desktop page layout'
275+ self.assertTrue(firefox.description.find(firefox_description) > -1)
276+ self.assertTrue(scribus.description.find(scribus_description) > -1)
277+
278+ def test_descdription_updated_in_app(self):
279+ app = self.factory.make_application(package_name='scribus',
280+ distroseries=self.factory.make_distroseries(code_name='natty'))
281+
282+ call_command(
283+ 'import_app_install_data', 'natty',
284+ local_app_install_deb=self.factory.get_test_path(
285+ 'app-install-data-test_all.deb'),
286+ verbosity=0)
287+
288+ app_reloaded = Application.objects.get(id=app.id)
289+ self.assertEqual(
290+ 'Graphic Page Layout and Publication (Stable)',
291+ app_reloaded.comment)
292+ scribus_description = 'Scribus is an open source desktop page layout'
293+ self.assertTrue(app_reloaded.description.find(scribus_description) > -1)

Subscribers

People subscribed via source and target branches