Merge lp:~brian-murray/update-notifier/python3 into lp:update-notifier/ubuntu

Proposed by Brian Murray
Status: Merged
Merged at revision: 716
Proposed branch: lp:~brian-murray/update-notifier/python3
Merge into: lp:update-notifier/ubuntu
Diff against target: 552 lines (+106/-74)
8 files modified
data/apt_check.py (+35/-25)
data/backend_helper.py (+17/-14)
data/hooks.py (+25/-19)
data/package-data-downloader (+9/-7)
debian/changelog (+9/-0)
debian/control (+9/-7)
debian/rules (+1/-1)
tests/test_package-data-downloader.py (+1/-1)
To merge this branch: bzr merge lp:~brian-murray/update-notifier/python3
Reviewer Review Type Date Requested Status
Adam Conrad Pending
Steve Langasek Pending
Review via email: mp+110429@code.launchpad.net

This proposal supersedes a proposal from 2012-06-13.

Description of the change

Porting of update-notifier to python3.

This is also dependent on python3-debian being available.

To post a comment you must log in.
Revision history for this message
Adam Conrad (adconrad) wrote : Posted in a previous version of this proposal

Looks good to me, with the latest revision.

review: Approve
Revision history for this message
Steve Langasek (vorlon) wrote : Posted in a previous version of this proposal

+ outstream.write("\n".join(map([p.name for p in pkgs])))

isn't the map() redundant here?

-SYNPATIC_DESKTOP = ["--desktop",
- "/usr/share/applications/synaptic.desktop",
+SYNPATIC_DESKTOP = ["--desktop",
+ "/usr/share/applications/synaptic.desktop",

Unrelated, but I guess the variable name could be spell-checked :)

There's one point in the data/package-data-downloader massive PEP8 fix-up (sorry about that) where I notice the indent level has changed (a couple of lines that were outside of 'with' blocks have been moved into them). That one's an ok no-op, but it makes me wonder if there are any others hiding in the large diff. Was the PEP8 reformatting of the file done automatically, or by hand? I don't think an eyeball review of the diff is useful to catch any bugs here, so we should probably rely on a sane automatic transformation.

review: Approve
Revision history for this message
Steve Langasek (vorlon) wrote : Posted in a previous version of this proposal

Merge conflict from landing the PEP8 whitespace changes separately on each branch; should be resolved so we can review.

review: Needs Fixing
Revision history for this message
Brian Murray (brian-murray) wrote : Posted in a previous version of this proposal

My local diff of package-data-downloader is only showing the following:

--- ../main/data/package-data-downloader 2012-06-13 15:54:04.000000000 -0700
+++ data/package-data-downloader 2012-06-13 15:51:18.000000000 -0700
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 # -*- coding: utf-8 -*-
 """Process new requests to download per-package data"""
 # Copyright (C) 2012 Canonical Ltd
@@ -16,13 +16,15 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

+from __future__ import print_function
+
 import glob
 import os
 import sys
 import subprocess
 import re
 import traceback
-import urllib
+import urllib.request
 import debian.deb822
 import string
 import apt
@@ -184,7 +186,7 @@ def process_download_requests():
                 pass

         if proxies:
- urllib._urlopener = urllib.FancyURLopener(proxies)
+ urllib.request._urlopener = urllib.request.FancyURLopener(proxies)
     except Exception:
         pass

@@ -209,13 +211,13 @@ def process_download_requests():
         files = []
         sums = []
         for para in hook.iter_paragraphs(open(file)):
- if para.has_key('script'):
+ if 'script' in para:
                 if not files:
                     record_failure(relfile)
                     break
                 command = [para['script']]

- if para.has_key('should-download'):
+ if 'should-download' in para:
                     db = debconf.DebconfCommunicator('update-notifier')
                     try:
                         should = db.get(para['should-download'])
@@ -230,8 +232,8 @@ def process_download_requests():
                 # Download each file and verify the sum
                 try:
                     for i in range(len(files)):
- print "%s: downloading %s" % (relfile, files[i])
- dest_file = urllib.urlretrieve(files[i])[0]
+ print("%s: downloading %s" % (relfile, files[i]))
+ dest_file = urllib.request.urlretrieve(files[i])[0]
                         output = subprocess.check_output(["sha256sum", dest_file])
                         output = output.split(' ')[0]
                         if output == sums[i]:

I hope that Launchpad is just slow here.

716. By Brian Murray

merge with upstream

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/apt_check.py'
2--- data/apt_check.py 2012-06-12 09:09:32 +0000
3+++ data/apt_check.py 2012-06-14 22:18:20 +0000
4@@ -1,5 +1,6 @@
5-#!/usr/bin/python
6+#!/usr/bin/python3
7
8+from __future__ import print_function
9
10 #nice apt-get -s -o Debug::NoLocking=true upgrade | grep ^Inst
11
12@@ -15,27 +16,32 @@
13 DISTRO = subprocess.Popen(["lsb_release","-c","-s"],
14 stdout=subprocess.PIPE).communicate()[0].strip()
15
16+
17 def _(msg):
18 return gettext.dgettext("update-notifier", msg)
19
20+
21 def _handleException(type, value, tb):
22 sys.stderr.write("E: "+ _("Unknown Error: '%s' (%s)") % (type,value))
23 sys.exit(-1)
24
25-def clean(cache,depcache):
26+
27+def clean(cache, depcache):
28 " unmark (clean) all changes from the given depcache "
29 # mvo: looping is too inefficient with the new auto-mark code
30 #for pkg in cache.Packages:
31 # depcache.MarkKeep(pkg)
32 depcache.init()
33
34-def saveDistUpgrade(cache,depcache):
35+
36+def saveDistUpgrade(cache, depcache):
37 """ this functions mimics a upgrade but will never remove anything """
38 depcache.upgrade(True)
39 if depcache.del_count > 0:
40- clean(cache,depcache)
41+ clean(cache, depcache)
42 depcache.upgrade()
43
44+
45 def isSecurityUpgrade(ver):
46 " check if the given version is a security update (or masks one) "
47 security_pockets = [("Ubuntu", "%s-security" % DISTRO),
48@@ -48,12 +54,13 @@
49 return True
50 return False
51
52+
53 def write_package_names(outstream, cache, depcache):
54 " write out package names that change to outstream "
55- pkgs = filter(lambda pkg:
56- depcache.marked_install(pkg) or depcache.marked_upgrade(pkg),
57- cache.packages)
58- outstream.write("\n".join(map(lambda p: p.name, pkgs)))
59+ pkgs = [pkg for pkg in cache.packages if depcache.marked_install(pkg) or
60+ depcache.marked_upgrade(pkg)]
61+ outstream.write("\n".join(map([p.name for p in pkgs])))
62+
63
64 def write_human_readable_summary(outstream, upgrades, security_updates):
65 " write out human summary summary to outstream "
66@@ -67,6 +74,8 @@
67 "%i updates are security updates.",
68 security_updates) % security_updates)
69 outstream.write("\n")
70+
71+
72 def init():
73 " init the system, be nice "
74 # FIXME: do a ionice here too?
75@@ -74,24 +83,25 @@
76 apt_pkg.init()
77 # force apt to build its caches in memory for now to make sure
78 # that there is no race when the pkgcache file gets re-generated
79- apt_pkg.config.set("Dir::Cache::pkgcache","")
80-
81+ apt_pkg.config.set("Dir::Cache::pkgcache", "")
82+
83+
84 def run(options=None):
85
86 # we are run in "are security updates installed automatically?"
87 # question mode
88 if options.security_updates_unattended:
89 res = apt_pkg.config.find_i("APT::Periodic::Unattended-Upgrade", 0)
90- #print res
91+ #print(res)
92 sys.exit(res)
93
94 # get caches
95 try:
96 cache = apt_pkg.Cache(apt.progress.base.OpProgress())
97- except SystemError, e:
98+ except SystemError as e:
99 sys.stderr.write("E: "+ _("Error: Opening the cache (%s)") % e)
100 sys.exit(-1)
101- depcache = apt_pkg.DepCache(cache)
102+ depcache = apt_pkg.GetDepCache(cache)
103
104 # read the pin files
105 depcache.read_pinfile()
106@@ -108,8 +118,8 @@
107
108 # do the upgrade (not dist-upgrade!)
109 try:
110- saveDistUpgrade(cache,depcache)
111- except SystemError, e:
112+ saveDistUpgrade(cache, depcache)
113+ except SystemError as e:
114 sys.stderr.write("E: "+ _("Error: Marking the upgrade (%s)") % e)
115 sys.exit(-1)
116
117@@ -128,16 +138,16 @@
118 continue
119
120 # check for security upgrades
121- upgrades = upgrades + 1
122+ upgrades = upgrades + 1
123 if isSecurityUpgrade(cand_ver):
124 security_updates += 1
125 continue
126
127- # now check for security updates that are masked by a
128+ # now check for security updates that are masked by a
129 # canidate version from another repo (-proposed or -updates)
130 for ver in pkg.version_list:
131 if (inst_ver and apt_pkg.version_compare(ver.ver_str, inst_ver.ver_str) <= 0):
132- #print "skipping '%s' " % ver.VerStr
133+ #print("skipping '%s' " % ver.VerStr)
134 continue
135 if isSecurityUpgrade(ver):
136 security_updates += 1
137@@ -149,19 +159,19 @@
138 elif options and options.readable_output:
139 write_human_readable_summary(sys.stdout, upgrades, security_updates)
140 else:
141- # print the number of regular upgrades and the number of
142+ # print the number of regular upgrades and the number of
143 # security upgrades
144- sys.stderr.write("%s;%s" % (upgrades,security_updates))
145+ sys.stderr.write("%s;%s" % (upgrades, security_updates))
146
147 # return the number of upgrades (if its used as a module)
148- return(upgrades,security_updates)
149-
150-
151-if __name__ == "__main__":
152+ return(upgrades, security_updates)
153+
154+
155+if __name__ == "__main__":
156 # setup a exception handler to make sure that uncaught stuff goes
157 # to the notifier
158 sys.excepthook = _handleException
159-
160+
161 # gettext
162 APP="update-notifier"
163 DIR="/usr/share/locale"
164
165=== modified file 'data/backend_helper.py'
166--- data/backend_helper.py 2011-08-10 13:54:37 +0000
167+++ data/backend_helper.py 2012-06-14 22:18:20 +0000
168@@ -1,4 +1,4 @@
169-#!/usr/bin/python
170+#!/usr/bin/python3
171
172 import argparse
173 import dbus
174@@ -8,8 +8,8 @@
175 import sys
176
177 GKSU = ["/usr/bin/gksu"]
178-SYNPATIC_DESKTOP = ["--desktop",
179- "/usr/share/applications/synaptic.desktop",
180+SYNAPTIC_DESKTOP = ["--desktop",
181+ "/usr/share/applications/synaptic.desktop",
182 "--"]
183 HAVE_APTDAEMON = False
184 try:
185@@ -18,6 +18,7 @@
186 except ImportError:
187 pass
188
189+
190 # show updates
191 def show_updates():
192 """ show updates using update-manager """
193@@ -38,9 +39,10 @@
194 dia.run()
195 Gtk.main()
196 return trans.exit == enums.EXIT_SUCCESS
197-
198+
199+
200 def _install_all_updates_gksu():
201- cmd = GKSU + SYNPATIC_DESKTOP + [ "/usr/sbin/synaptic ",
202+ cmd = GKSU + SYNAPTIC_DESKTOP + ["/usr/sbin/synaptic ",
203 "--dist-upgrade-mode",
204 "--non-interactive",
205 "--hide-main-window",
206@@ -48,6 +50,7 @@
207 ]
208 return subprocess.call(cmd)
209
210+
211 def install_all_updates():
212 """ install all updates either with synaptic or aptdaemon """
213 if HAVE_APTDAEMON:
214@@ -69,14 +72,16 @@
215 Gtk.main()
216 return trans.exit == enums.EXIT_SUCCESS
217
218+
219 def _check_updates_gtk():
220- cmd = GKSU + SYNPATIC_DESKTOP + ["/usr/sbin/synaptic",
221+ cmd = GKSU + SYNAPTIC_DESKTOP + ["/usr/sbin/synaptic",
222 "--update-at-startup",
223 "--non-interactive",
224 "--hide-main-window",
225 ]
226 subprocess.call(cmd)
227
228+
229 def check_updates():
230 """ check for updates either with aptdaemon or synaptic """
231 if HAVE_APTDAEMON:
232@@ -88,7 +93,7 @@
233 # start packagemanager
234 def start_packagemanager():
235 if os.path.exists("/usr/sbin/synaptic"):
236- cmd = GKSU + SYNPATIC_DESKTOP + ["/usr/sbin/synaptic"]
237+ cmd = GKSU + SYNAPTIC_DESKTOP + ["/usr/sbin/synaptic"]
238 return subprocess.call(cmd)
239 elif os.path.exists("/usr/bin/software-center"):
240 return subprocess.call(["/usr/bin/software-center"])
241@@ -111,18 +116,17 @@
242 if os.path.exists("/usr/bin/software-center"):
243 subprocess.call(["/usr/bin/software-center"])
244
245+
246 def _add_cdrom_synaptic(mount_path):
247- cmd = GKSU + SYNPATIC_DESKTOP + ["synaptic", "--add-cdrom", mount_path]
248+ cmd = GKSU + SYNAPTIC_DESKTOP + ["synaptic", "--add-cdrom", mount_path]
249 return subprocess.call(cmd)
250
251+
252 def add_cdrom(mount_path):
253 if os.path.exists("/usr/sbin/synaptic"):
254 _add_cdrom_synaptic(mount_path)
255 else:
256 _add_cdrom_sp(mount_path)
257-
258-
259-
260
261
262 if __name__ == "__main__":
263@@ -149,7 +153,7 @@
264 command = subparser.add_parser("add_cdrom")
265 command.add_argument("mount_path")
266 command.set_defaults(command="add_cdrom")
267-
268+
269 args = parser.parse_args()
270 if args.debug:
271 logging.basicConfig(level=logging.DEBUG)
272@@ -159,10 +163,9 @@
273 func_name = args.command
274 f_kwargs = {}
275 f = globals()[func_name]
276- if args.command == "add_cdrom":
277+ if args.command == "add_cdrom":
278 f_kwargs["mount_path"] = args.mount_path
279 res = f(**f_kwargs)
280
281 if not res:
282 sys.exit(1)
283-
284
285=== modified file 'data/hooks.py'
286--- data/hooks.py 2010-08-23 08:58:54 +0000
287+++ data/hooks.py 2012-06-14 22:18:20 +0000
288@@ -1,19 +1,26 @@
289-#!/usr/bin/python2.4
290+#!/usr/bin/python3
291+
292+from __future__ import print_function
293
294 from optparse import OptionParser
295-import user, string, dircache, sys, os.path
296-
297-
298+
299+import dircache
300+import os.path
301+import string
302+import sys
303+import user
304+
305+
306 class HookFiles(object):
307 """ represents all hook files """
308
309 # the hooks are stored here
310 hookDir = "/var/lib/update-notifier/user.d/"
311-
312+
313 class HookFile(object):
314 """ represents a single hook file """
315- __slots__ = [ "filename", "mtime", "cmd_run", "seen" ]
316-
317+ __slots__ = ["filename", "mtime", "cmd_run", "seen"]
318+
319 def __init__(self, filename):
320 self.filename = filename
321 self.mtime = os.stat(HookFiles.hookDir+filename).st_mtime
322@@ -24,17 +31,16 @@
323 """ show the summary for the notification """
324 # FIXME: read rfc822 style file and get the i18n version of
325 # "Name"
326- pass
327+ pass
328 summary = property(summary)
329
330 def description(self):
331 """ show a long description for the notification """
332 # FIXME: read rfc822 style file and get the i18n version of
333 # "Description", convert "\n" -> " " and strstrip it afterwards
334- pass
335+ pass
336 description = property(description)
337
338-
339 def __init__(self):
340 self._hooks = {}
341 self._readSeenFile()
342@@ -49,25 +55,25 @@
343 if os.path.exists(hooks_seen):
344 for line in open(hooks_seen):
345 filename, mtime, cmd_run = string.split(line)
346- if os.path.exists(self.hookDir+filename) and \
347- not self._hooks.has_key(filename):
348+ if os.path.exists(self.hookDir + filename) and \
349+ not filename in self._hooks:
350 h = self.HookFile(filename)
351 h.mtime = mtime
352 h.cmd_run = cmd_run
353 h.seen = True
354 # check if file was motified since we last saw it
355- if os.stat(self.hookDir+filename).st_mtime > int(mtime):
356+ if os.stat(self.hookDir + filename).st_mtime > int(mtime):
357 h.seen = False
358 self._hooks[filename] = h
359
360 def _update(self):
361 """ update hook dict with the current state on the fs """
362 for hook in dircache.listdir(self.hookDir):
363- if self._hooks.has_key(hook):
364+ if hook in self._hooks:
365 # we have it already, check if it was motified since
366 # we last saw it
367 h = self._hooks[hook]
368- if os.stat(self.hookDir+hook).st_mtime > int(h.mtime):
369+ if os.stat(self.hookDir + hook).st_mtime > int(h.mtime):
370 h.seen = False
371 else:
372 self._hooks[hook] = self.HookFile(hook)
373@@ -80,19 +86,20 @@
374 if not self._hooks[hook].seen:
375 new.append(self._hooks[hook])
376 return new
377-
378+
379
380 def check():
381 hooks = HookFiles()
382 new = hooks.checkNew()
383 return len(new)
384
385+
386 def test():
387 hooks = HookFiles()
388 new = hooks.checkNew()
389- print "Hooks: %s" % len(new)
390+ print("Hooks: %s" % len(new))
391 for hook in hooks._hooks:
392- print hooks._hooks[hook].notification
393+ print(hooks._hooks[hook].notification)
394
395
396 if __name__ == "__main__":
397@@ -105,7 +112,6 @@
398 default=False, help="run test")
399 (options, args) = parser.parse_args()
400
401-
402 if options.check:
403 sys.exit(check())
404 elif options.run:
405
406=== modified file 'data/package-data-downloader'
407--- data/package-data-downloader 2012-06-13 22:49:33 +0000
408+++ data/package-data-downloader 2012-06-14 22:18:20 +0000
409@@ -1,4 +1,4 @@
410-#!/usr/bin/python
411+#!/usr/bin/python3
412 # -*- coding: utf-8 -*-
413 """Process new requests to download per-package data"""
414 # Copyright (C) 2012 Canonical Ltd
415@@ -16,13 +16,15 @@
416 # with this program; if not, write to the Free Software Foundation, Inc.,
417 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
418
419+from __future__ import print_function
420+
421 import glob
422 import os
423 import sys
424 import subprocess
425 import re
426 import traceback
427-import urllib
428+import urllib.request
429 import debian.deb822
430 import string
431 import apt
432@@ -184,7 +186,7 @@
433 pass
434
435 if proxies:
436- urllib._urlopener = urllib.FancyURLopener(proxies)
437+ urllib.request._urlopener = urllib.request.FancyURLopener(proxies)
438 except Exception:
439 pass
440
441@@ -209,13 +211,13 @@
442 files = []
443 sums = []
444 for para in hook.iter_paragraphs(open(file)):
445- if para.has_key('script'):
446+ if 'script' in para:
447 if not files:
448 record_failure(relfile)
449 break
450 command = [para['script']]
451
452- if para.has_key('should-download'):
453+ if 'should-download' in para:
454 db = debconf.DebconfCommunicator('update-notifier')
455 try:
456 should = db.get(para['should-download'])
457@@ -230,8 +232,8 @@
458 # Download each file and verify the sum
459 try:
460 for i in range(len(files)):
461- print "%s: downloading %s" % (relfile, files[i])
462- dest_file = urllib.urlretrieve(files[i])[0]
463+ print("%s: downloading %s" % (relfile, files[i]))
464+ dest_file = urllib.request.urlretrieve(files[i])[0]
465 output = subprocess.check_output(["sha256sum", dest_file])
466 output = output.split(' ')[0]
467 if output == sums[i]:
468
469=== modified file 'debian/changelog'
470--- debian/changelog 2012-06-12 09:12:28 +0000
471+++ debian/changelog 2012-06-14 22:18:20 +0000
472@@ -1,3 +1,12 @@
473+update-notifier (0.119ubuntu14) UNRELEASED; urgency=low
474+
475+ * Port to Python 3
476+ - Use the new python-apt API since the legacy API is not available
477+ in Python 3.
478+ - Various and pyflakes, whitespace, style, line length fixes.
479+
480+ -- Brian Murray <brian@ubuntu.com> Tue, 12 Jun 2012 08:35:48 -0700
481+
482 update-notifier (0.119ubuntu13) quantal; urgency=low
483
484 * data/apt_check.py:
485
486=== modified file 'debian/control'
487--- debian/control 2012-05-14 22:31:36 +0000
488+++ debian/control 2012-06-14 22:18:20 +0000
489@@ -12,25 +12,27 @@
490 libx11-dev,
491 autotools-dev,
492 libappindicator3-dev,
493- po-debconf
494+ po-debconf,
495+ python3
496 Standards-Version: 3.8.4
497 Vcs-Bzr: http://bazaar.launchpad.net/~ubuntu-core-dev/update-notifier/ubuntu
498+X-Python3-Version: >= 3.2
499
500 Package: update-notifier
501 Architecture: any
502 Depends: ${shlibs:Depends},
503 ${misc:Depends},
504 update-notifier-common (= ${source:Version}),
505- python,
506- python-dbus,
507+ python3,
508+ python3-dbus,
509 update-manager-gnome | update-manager,
510 notification-daemon,
511 gksu
512 Recommends: apport-gtk,
513- python-aptdaemon.gtk3widgets | synaptic,
514+ python3-aptdaemon.gtk3widgets | synaptic,
515 software-properties-gtk,
516 anacron,
517- aptdaemon
518+ python3-aptdaemon
519 Suggests: ubuntu-system-service
520 Description: Daemon which notifies about package updates
521 Puts an icon in the user's notification area when package updates are
522@@ -42,8 +44,8 @@
523 Pre-Depends: dpkg (>= 1.15.7.2)
524 Depends: ${shlibs:Depends},
525 ${misc:Depends},
526- python,
527- python-apt (>= 0.6.12), python-debian, debconf
528+ python3,
529+ python3-apt (>= 0.6.12), python3-debian, debconf
530 Recommends: libpam-modules (>= 1.0.1-9ubuntu3)
531 Suggests: gksu
532 Description: Files shared between update-notifier and other packages
533
534=== modified file 'debian/rules'
535--- debian/rules 2010-06-01 13:28:36 +0000
536+++ debian/rules 2012-06-14 22:18:20 +0000
537@@ -3,4 +3,4 @@
538 export LDFLAGS += -Wl,-z,defs -Wl,-O1 -Wl,--as-needed
539
540 %:
541- dh $@
542+ dh $@ --with python3
543
544=== modified file 'tests/test_package-data-downloader.py'
545--- tests/test_package-data-downloader.py 2012-03-23 09:11:45 +0000
546+++ tests/test_package-data-downloader.py 2012-06-14 22:18:20 +0000
547@@ -1,4 +1,4 @@
548-#!/usr/bin/python
549+#!/usr/bin/python3
550
551 import os
552 import shutil

Subscribers

People subscribed via source and target branches

to all changes: