Merge ~albertomilone/ubuntu/+source/software-properties:apt-pkg-transition into ubuntu/+source/software-properties:ubuntu/devel

Proposed by Alberto Milone
Status: Needs review
Proposed branch: ~albertomilone/ubuntu/+source/software-properties:apt-pkg-transition
Merge into: ubuntu/+source/software-properties:ubuntu/devel
Diff against target: 406 lines (+121/-80)
3 files modified
softwareproperties/SoftwareProperties.py (+24/-12)
softwareproperties/gtk/SoftwarePropertiesGtk.py (+49/-35)
softwareproperties/qt/SoftwarePropertiesQt.py (+48/-33)
Reviewer Review Type Date Requested Status
Sebastien Bacher (community) Approve
Julian Andres Klode (community) Needs Fixing
git-ubuntu import Pending
Review via email: mp+416950@code.launchpad.net

Commit message

This makes software-properties{gtk|qt} compatible with the new ubuntu-drivers-common, and its new apt_pkg code.

To post a comment you must log in.
Revision history for this message
Matthew Ruffell (mruffell) wrote :

Hi Alberto,

I tried to build and test your patch, but it fails on the pyflakes3 test:

$ python3 tests/test_pyflakes.py
/home/matthew/Work/lp1964880/alberto/software-properties/softwareproperties/SoftwareProperties.py:29:1 'apt' imported but unused
/home/matthew/Work/lp1964880/alberto/software-properties/softwareproperties/SoftwareProperties.py:753:9 redefinition of unused 'apt' from line 29
E
======================================================================
ERROR: test_pyflakes3_clean (__main__.TestPyflakesClean)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/matthew/Work/lp1964880/alberto/software-properties/tests/test_pyflakes.py", line 21, in test_pyflakes3_clean
    self.assertEqual(subprocess.check_call(['pyflakes3'] + self.paths), 0)
  File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
    raise CalledProcessError(retcode, cmd)

Revision history for this message
Julian Andres Klode (juliank) wrote :

I found a couple of spots worth fixing/considering in the diff

review: Needs Fixing
68577e2... by Alberto Milone

softwareproperties/SoftwareProperties.py: import apt only on demand

66473bd... by Alberto Milone

Do without a couple of tries, and make get_package_id return the installed package when available

Revision history for this message
Alberto Milone (albertomilone) wrote :

I have just pushed a couple of commits which should fix the problems reported by Julian and Matthew. Thanks

Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, I've merged and uploaded but I can't close that one since it's targetting the wrong Vcs, for reference the git repository is reference in debian/control and https://git.launchpad.net/software-properties

I've also updated the depends on ubuntu-drivers-common since the updated code would error out with a pre-apt-refactoring version of the drivers

review: Approve
Revision history for this message
Alberto Milone (albertomilone) wrote :

I understand. Sorry about that. Thanks

Unmerged commits

66473bd... by Alberto Milone

Do without a couple of tries, and make get_package_id return the installed package when available

68577e2... by Alberto Milone

softwareproperties/SoftwareProperties.py: import apt only on demand

ada2244... by Alberto Milone

Use apt_pkg instead of apt, as in ubuntu-drivers-common

Fixes LP: #1964880

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/softwareproperties/SoftwareProperties.py b/softwareproperties/SoftwareProperties.py
2index 3e94731..7fc9862 100644
3--- a/softwareproperties/SoftwareProperties.py
4+++ b/softwareproperties/SoftwareProperties.py
5@@ -26,7 +26,6 @@
6 from __future__ import absolute_import, print_function
7
8 import apt_pkg
9-import apt
10 import copy
11 from hashlib import md5
12 import re
13@@ -828,22 +827,35 @@ class SoftwareProperties(object):
14 except:
15 return False
16
17- def get_package_id(self, ver):
18+ def get_package_id(self, apt_cache, pkg):
19 """ Return the PackageKit package id """
20- assert isinstance(ver, apt.package.Version)
21- return "%s;%s;%s;" % (ver.package.shortname, ver.version,
22- ver.package.architecture())
23+ assert isinstance(pkg, apt_pkg.Package)
24+ cur_ver = pkg.current_ver
25+ if cur_ver:
26+ ver = cur_ver.ver_str
27+ arch = cur_ver.arch
28+ else:
29+ depcache = apt_pkg.DepCache(apt_cache)
30+ candidate = depcache.get_candidate_ver(pkg)
31+ ver = candidate.ver_str
32+ arch = candidate.arch
33+ return "%s;%s;%s;" % (pkg.name, ver, arch)
34
35 @staticmethod
36- def get_dependencies(apt_cache, package_name, pattern=None):
37+ def get_dependencies(apt_cache, package, pattern=None):
38 """ Get the package dependencies, which can be filtered out by a pattern """
39+ depcache = apt_pkg.DepCache(apt_cache)
40+ candidate = depcache.get_candidate_ver(package)
41+
42 dependencies = []
43- for or_group in apt_cache[package_name].candidate.dependencies:
44- for dep in or_group:
45- if dep.rawtype in ["Depends", "PreDepends"]:
46- dependencies.append(dep.name)
47- if pattern:
48- dependencies = [ x for x in dependencies if x.find(pattern) != -1 ]
49+ try:
50+ for dep_list in candidate.depends_list_str.get('Depends'):
51+ for dep_name, dep_ver, dep_op in dep_list:
52+ if dep_name.find(pattern) != -1:
53+ dependencies.append(apt_cache[dep_name])
54+ except (KeyError, TypeError):
55+ return []
56+
57 return dependencies
58
59
60diff --git a/softwareproperties/gtk/SoftwarePropertiesGtk.py b/softwareproperties/gtk/SoftwarePropertiesGtk.py
61index 9b797ac..01e3d28 100644
62--- a/softwareproperties/gtk/SoftwarePropertiesGtk.py
63+++ b/softwareproperties/gtk/SoftwarePropertiesGtk.py
64@@ -26,7 +26,6 @@
65
66 from __future__ import absolute_import, print_function
67
68-import apt
69 import apt_pkg
70 import datetime
71 import dbus
72@@ -228,7 +227,9 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
73 # used to store the handlers of callbacks
74 self.handlers = {}
75
76- self.apt_cache = {}
77+ # Initialise and store the apt cache
78+ self.init_apt_cache()
79+
80 self.pk_task = None
81
82 # Put some life into the user interface:
83@@ -290,6 +291,17 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
84 self.handlers[self.combobox_release_upgrades] = \
85 self.combobox_release_upgrades.connect("changed",
86 self.on_combobox_release_upgrades_changed)
87+ def init_apt_cache(self):
88+ apt_pkg.init_config()
89+ apt_pkg.init_system()
90+ self.apt_cache = apt_pkg.Cache(None)
91+ self.depcache = apt_pkg.DepCache(self.apt_cache)
92+ self.records = apt_pkg.PackageRecords(self.apt_cache)
93+
94+ def update_apt_cache(self):
95+ self.apt_cache = apt_pkg.Cache(None)
96+ self.depcache = apt_pkg.DepCache(self.apt_cache)
97+ self.records = apt_pkg.PackageRecords(self.apt_cache)
98
99 def init_auto_update(self):
100 """ Set up the widgets that allow to configure the update automation """
101@@ -983,7 +995,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
102 # dbus events
103 def on_config_modified(self):
104 """The config was changed and now needs to be saved and reloaded"""
105- apt.apt_pkg.init_config()
106+ apt_pkg.init_config()
107 self.button_revert.set_sensitive(True)
108
109 def on_keys_modified(self):
110@@ -1226,7 +1238,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
111 if not installs_pending:
112 self.progress_bar.set_visible(False)
113 self.clear_changes()
114- self.apt_cache = apt.Cache()
115+ self.update_apt_cache()
116 self.set_driver_action_status()
117 self.update_label_and_icons_from_status()
118 self.button_driver_revert.set_visible(True)
119@@ -1239,19 +1251,20 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
120 installs = []
121 removals = []
122
123+ has_nvidia = False
124 for pkg in self.driver_changes:
125- if pkg.is_installed:
126- removals.append(self.get_package_id(pkg.installed))
127+ if pkg.current_ver:
128+ removals.append(self.get_package_id(self.apt_cache, pkg))
129 # The main NVIDIA package is only a metapackage.
130 # We need to collect its dependencies, so that
131 # we can uninstall the driver properly.
132- if 'nvidia' in pkg.shortname:
133- for dep in self.get_dependencies(self.apt_cache, pkg.shortname, 'nvidia'):
134- dep_pkg = self.apt_cache[dep]
135- if dep_pkg.is_installed:
136- removals.append(self.get_package_id(dep_pkg.installed))
137+ if 'nvidia' in pkg.name:
138+ has_nvidia = True
139+ for dep in self.get_dependencies(self.apt_cache, pkg, 'nvidia'):
140+ if dep.current_ver:
141+ removals.append(self.get_package_id(self.apt_cache, dep))
142 else:
143- installs.append(self.get_package_id(pkg.candidate))
144+ installs.append(self.get_package_id(self.apt_cache, pkg))
145
146 self.cancellable = Gio.Cancellable()
147 try:
148@@ -1269,6 +1282,11 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
149 installs_pending # callback data
150 )
151 if installs:
152+ if has_nvidia:
153+ to_install = []
154+ for item in installs:
155+ name = item.split(';')[0]
156+ to_install.append(name)
157 self.pk_task.install_packages_async(installs,
158 self.cancellable, # cancellable
159 self.on_driver_changes_progress,
160@@ -1376,7 +1394,6 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
161 # WARNING: This is run in a separate thread.
162 self.detect_called = True
163 try:
164- self.apt_cache = apt.Cache()
165 self.devices = detect.system_device_drivers(self.apt_cache)
166 except:
167 # Catch all exceptions and feed them to apport.
168@@ -1395,22 +1412,16 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
169 return
170
171 pkg = None
172- try:
173- if pkg_name:
174- pkg = self.apt_cache[pkg_name]
175- # If the package depends on dkms
176- # we need to install the correct linux metapackage
177- # so that users get the latest headers
178- if 'dkms' in pkg.candidate.record['Depends']:
179- linux_meta = detect.get_linux(self.apt_cache)
180- if (linux_meta and
181- linux_meta not in self.driver_changes):
182- # Install the linux metapackage
183- lmp = self.apt_cache[linux_meta]
184- if not lmp.is_installed:
185- self.driver_changes.append(lmp)
186- except (AttributeError, KeyError):
187- pass
188+ if pkg_name:
189+ pkg = self.apt_cache[pkg_name]
190+ # Add the matching linux modules package when available
191+ try:
192+ modules_package = detect.get_linux_modules_metapackage(self.apt_cache, pkg_name)
193+ modules_package_obj = self.apt_cache[modules_package]
194+ if modules_package and not modules_package_obj.current_ver:
195+ self.driver_changes.append(modules_package_obj)
196+ except KeyError:
197+ pass
198
199 if button.get_active():
200 if pkg in self.driver_changes:
201@@ -1430,7 +1441,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
202
203 if (pkg is not None
204 and pkg not in self.driver_changes
205- and pkg.is_installed):
206+ and pkg.current_ver):
207 self.driver_changes.append(pkg)
208
209 self.button_driver_revert.set_sensitive(bool(self.driver_changes))
210@@ -1492,11 +1503,14 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
211
212 try:
213 pkg = self.apt_cache[pkg_driver_name]
214- installed = pkg.is_installed
215- if pkg.candidate is not None:
216- description = _("Using {} from {}").format(pkg.candidate.summary, pkg.shortname)
217+ installed = pkg.current_ver
218+ candidate = self.depcache.get_candidate_ver(pkg)
219+
220+ if candidate is not None:
221+ self.records.lookup(candidate.file_list[0])
222+ description = _("Using {} from {}").format(self.records.short_desc, pkg_driver_name)
223 else:
224- description = _("Using {}").format(pkg.shortname)
225+ description = _("Using {}").format(pkg_driver_name)
226 except KeyError:
227 print("WARNING: a driver ({}) doesn't have any available package associated: {}".format(pkg_driver_name, current_driver))
228 continue
229@@ -1626,7 +1640,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
230 for device in self.devices:
231 for pkg_name in self.devices[device]['drivers']:
232 pkg = self.apt_cache[pkg_name]
233- if not self.devices[device]['drivers'][pkg_name]['free'] and pkg.is_installed:
234+ if not self.devices[device]['drivers'][pkg_name]['free'] and pkg.current_ver:
235 self.nonfree_drivers = self.nonfree_drivers + 1
236
237 if self.nonfree_drivers > 0:
238diff --git a/softwareproperties/qt/SoftwarePropertiesQt.py b/softwareproperties/qt/SoftwarePropertiesQt.py
239index 332bf06..e9e5818 100644
240--- a/softwareproperties/qt/SoftwarePropertiesQt.py
241+++ b/softwareproperties/qt/SoftwarePropertiesQt.py
242@@ -55,7 +55,6 @@ from .CdromProgress import CdromProgress
243
244 from UbuntuDrivers import detect
245 import sys
246-import apt
247 from functools import partial
248 import aptsources.distro
249 import logging
250@@ -345,6 +344,18 @@ class SoftwarePropertiesQt(SoftwareProperties):
251 self.userinterface.combobox_server.addItem(_("Other..."))
252 self.other_mirrors_index = self.userinterface.combobox_server.count() - 1
253
254+ def init_apt_cache(self):
255+ apt_pkg.init_config()
256+ apt_pkg.init_system()
257+ self.apt_cache = apt_pkg.Cache(None)
258+ self.depcache = apt_pkg.DepCache(self.apt_cache)
259+ self.records = apt_pkg.PackageRecords(self.apt_cache)
260+
261+ def update_apt_cache(self):
262+ self.apt_cache = apt_pkg.Cache(None)
263+ self.depcache = apt_pkg.DepCache(self.apt_cache)
264+ self.records = apt_pkg.PackageRecords(self.apt_cache)
265+
266 def show_distro(self):
267 """
268 Represent the distro information in the user interface
269@@ -736,7 +747,7 @@ class SoftwarePropertiesQt(SoftwareProperties):
270
271 def on_restore_clicked(self):
272 """Restore the original keys"""
273- self.apt_key.update()
274+ self.update_apt_cache()
275 self.show_keys()
276
277 def on_pktask_progress(self, progress, ptype, udata=(None,)):
278@@ -859,7 +870,7 @@ class SoftwarePropertiesQt(SoftwareProperties):
279 if not installs_pending:
280 self.progress_bar.setVisible(False)
281 self.clear_changes()
282- self.apt_cache = apt.Cache()
283+ self.update_apt_cache()
284 self.set_driver_action_status()
285 self.update_label_and_icons_from_status()
286 self.button_driver_revert.setVisible(True)
287@@ -885,19 +896,20 @@ class SoftwarePropertiesQt(SoftwareProperties):
288 installs = []
289 removals = []
290
291+ has_nvidia = False
292 for pkg in self.driver_changes:
293- if pkg.is_installed:
294- removals.append(self.get_package_id(pkg.installed))
295+ if pkg.current_ver:
296+ removals.append(self.get_package_id(self.apt_cache, pkg))
297 # The main NVIDIA package is only a metapackage.
298 # We need to collect its dependencies, so that
299 # we can uninstall the driver properly.
300- if 'nvidia' in pkg.shortname:
301- for dep in self.get_dependencies(self.apt_cache, pkg.shortname, 'nvidia'):
302- dep_pkg = self.apt_cache[dep]
303- if dep_pkg.is_installed:
304- removals.append(self.get_package_id(dep_pkg.installed))
305+ if 'nvidia' in pkg.name:
306+ has_nvidia = True
307+ for dep in self.get_dependencies(self.apt_cache, pkg, 'nvidia'):
308+ if dep.current_ver:
309+ removals.append(self.get_package_id(self.apt_cache, dep))
310 else:
311- installs.append(self.get_package_id(pkg.candidate))
312+ installs.append(self.get_package_id(self.apt_cache, pkg))
313
314 self.cancellable = Gio.Cancellable()
315 try:
316@@ -915,6 +927,11 @@ class SoftwarePropertiesQt(SoftwareProperties):
317 installs_pending # callback data
318 )
319 if installs:
320+ if has_nvidia:
321+ to_install = []
322+ for item in installs:
323+ name = item.split(';')[0]
324+ to_install.append(name)
325 self.pk_task.install_packages_async(installs,
326 self.cancellable, # cancellable
327 self.on_driver_changes_progress,
328@@ -1019,8 +1036,8 @@ class SoftwarePropertiesQt(SoftwareProperties):
329 def detect_drivers(self):
330 # WARNING: This is run in a separate thread.
331 self.detect_called = True
332+ self.init_apt_cache()
333 try:
334- self.apt_cache = apt.Cache()
335 self.devices = detect.system_device_drivers(self.apt_cache)
336 except:
337 # Catch all exceptions and feed them to apport.
338@@ -1039,21 +1056,17 @@ class SoftwarePropertiesQt(SoftwareProperties):
339 return
340
341 pkg = None
342- try:
343- if pkg_name:
344- pkg = self.apt_cache[pkg_name]
345- # If the package depends on dkms
346- # we need to install the correct linux metapackage
347- # so that users get the latest headers
348- if 'dkms' in pkg.candidate.record['Depends']:
349- linux_meta = detect.get_linux(self.apt_cache)
350- if (linux_meta and linux_meta not in self.driver_changes):
351- # Install the linux metapackage
352- lmp = self.apt_cache[linux_meta]
353- if not lmp.is_installed:
354- self.driver_changes.append(lmp)
355- except KeyError:
356- pass
357+
358+ if pkg_name:
359+ pkg = self.apt_cache[pkg_name]
360+ # Add the matching linux modules package when available
361+ try:
362+ modules_package = detect.get_linux_modules_metapackage(self.apt_cache, pkg_name)
363+ modules_package_obj = self.apt_cache[modules_package]
364+ if modules_package and not modules_package_obj.current_ver:
365+ self.driver_changes.append(modules_package_obj)
366+ except KeyError:
367+ pass
368
369 if button.isChecked():
370 if pkg in self.driver_changes:
371@@ -1069,7 +1082,7 @@ class SoftwarePropertiesQt(SoftwareProperties):
372 if modalias not in self.orig_selection:
373 self.orig_selection[modalias] = button
374
375- if (pkg is not None and pkg not in self.driver_changes and pkg.is_installed):
376+ if (pkg is not None and pkg not in self.driver_changes and pkg.current_ver):
377 self.driver_changes.append(pkg)
378
379 self.button_driver_revert.setEnabled(bool(self.driver_changes))
380@@ -1137,11 +1150,13 @@ None if not applicable
381
382 try:
383 pkg = self.apt_cache[pkg_driver_name]
384- installed = pkg.is_installed
385- if pkg.candidate is not None:
386- description = _("Using {} from {}").format(pkg.candidate.summary, pkg.shortname)
387+ installed = pkg.current_ver or False
388+ candidate = self.depcache.get_candidate_ver(pkg)
389+ if candidate is not None:
390+ self.records.lookup(candidate.file_list[0])
391+ description = _("Using {} from {}").format(self.records.short_desc, pkg_driver_name)
392 else:
393- description = _("Using {}").format(pkg.shortname)
394+ description = _("Using {}").format(pkg_driver_name)
395 except KeyError:
396 print("WARNING: a driver ({}) doesn't have any available package associated: {}".format(pkg_driver_name, current_driver))
397 continue
398@@ -1277,7 +1292,7 @@ licence=licence)
399 for device in self.devices:
400 for pkg_name in self.devices[device]['drivers']:
401 pkg = self.apt_cache[pkg_name]
402- if not self.devices[device]['drivers'][pkg_name]['free'] and pkg.is_installed:
403+ if not self.devices[device]['drivers'][pkg_name]['free'] and pkg.current_ver:
404 self.nonfree_drivers = self.nonfree_drivers + 1
405
406 if self.nonfree_drivers > 0:

Subscribers

People subscribed via source and target branches