Merge lp:~barry/apturl/py3 into lp:apturl

Proposed by Barry Warsaw
Status: Merged
Merged at revision: 126
Proposed branch: lp:~barry/apturl/py3
Merge into: lp:apturl
Diff against target: 1084 lines (+219/-210)
21 files modified
AptUrl/AptUrl.py (+31/-30)
AptUrl/Helpers.py (+18/-8)
AptUrl/Parser.py (+2/-2)
AptUrl/UI.py (+0/-1)
AptUrl/gtk/GtkUI.py (+23/-16)
AptUrl/gtk/backend/__init__.py (+2/-2)
AptUrl/kde/KdeUI.py (+27/-41)
apturl-gtk (+2/-3)
apturl-kde (+7/-8)
debian/apturl-common.install (+2/-2)
debian/apturl-kde.install (+1/-1)
debian/apturl.install (+2/-2)
debian/changelog (+21/-0)
debian/compat (+1/-1)
debian/control (+16/-15)
debian/pycompat (+0/-1)
debian/rules (+7/-4)
po/apturl.pot (+40/-41)
setup.py (+5/-5)
tests/test_apturl_parse.py (+9/-17)
tests/test_helpers.py (+3/-10)
To merge this branch: bzr merge lp:~barry/apturl/py3
Reviewer Review Type Date Requested Status
Stéphane Graber Approve
Michael Vogt Pending
Review via email: mp+109949@code.launchpad.net

Description of the change

A working port to Python 3.

To post a comment you must log in.
Revision history for this message
Stéphane Graber (stgraber) wrote :

Things that I can't easily check just through the proposal:
 - Does the package actually build? The concern here being the use of "python3 ./setup.py install --install-layout=deb"
 - "#desc = "%s\n\n%s" % (summary, Helpers.format_description(description))" in KDEui.py, why was that line commented rather than removed if "desc" isn't used?

Besides that, the rest looks good, so with an answer to these two, +1

review: Approve
Revision history for this message
Barry Warsaw (barry) wrote :

On Jun 12, 2012, at 10:42 PM, Stéphane Graber wrote:

>Things that I can't easily check just through the proposal:

> - Does the package actually build? The concern here being the use of "python3 ./setup.py install --install-layout=deb"

I'm testing this now, but it requires unreleased versions of update-manager
and aptdaemon, so it's a bit tricky. :) I certainly won't upload it until
both those are released and the apturl build is tested.

> - "#desc = "%s\n\n%s" % (summary, Helpers.format_description(description))" in KDEui.py, why was that line commented rather than removed if "desc" isn't used?

You can't tell from the diff, but there's other code commented out below that
references it. I suppose I should just remove all the commented out code
instead.

>Besides that, the rest looks good, so with an answer to these two, +1

Thanks!

lp:~barry/apturl/py3 updated
133. By Barry Warsaw

+ Port setup.py to Python 3.
+ Fix python3-update-manager dependencies.
+ override_dh_auto_build to build with Python 3.
+ python3 setup.py install needs --root

Revision history for this message
Barry Warsaw (barry) wrote :

With the new uploads of update-manager and aptdaemon, this should be ready to go.

lp:~barry/apturl/py3 updated
134. By Barry Warsaw

apturl now must require python3-aptdaemon.gtk3widgets (i.e. not |
synaptic) due to the Python 3 port of update-manager.

Revision history for this message
Barry Warsaw (barry) wrote :

<xnox> then why Except: #Python 3 [20:44]
<xnox> 204 - homepage = pkgobj.homepage
<xnox> 205 + try:
<xnox> 206 + homepage = pkgobj.homepage
<xnox> 207 + except AttributeError:
<xnox> 208 + # Python 3
<xnox> 209 + homepage = pkgobj.versions[0].homepage

<xnox> then I would expect universal_newlines=True in the Popen as well, if
       you were playing it safe ;-) [20:45]
<xnox> +from __future__ import print_function
<xnox> 460 - desc = "%s\n\n%s" % (summary,
       Helpers.format_description(description)) [20:46]
<xnox> 461 + #desc = "%s\n\n%s" % (summary,
       Helpers.format_description(description))
<xnox> intentional comment out?
<xnox> are we meant to install 597
       +usr/lib/python3/*-packages/apturl-*.egg-info ? [20:47]

<xnox> ok.
<xnox> barry: debian/compat == 8
<xnox> use 9
<xnox> 8 was really a temp thing.
<xnox> and precise has 9 [20:48]

Revision history for this message
Barry Warsaw (barry) wrote :

<cjwatson> barry: The new apt API exists for py2 as well, and it's important
           to port to it because the old one is slated to go away
<cjwatson> (given that the new one has been around since lucid)
<barry> cjwatson: agreed. i'll get rid of the old api
<barry> (or mostly the try/excepts around the old api calls) [20:52]
<cjwatson> (Also, pkgobj.candidate.homepage maybe?)

<cjwatson> + verStr = self.cache[apturl.package].candidate_version [20:53]
<cjwatson> that looks wrong, .candidate.version perhaps

Revision history for this message
Barry Warsaw (barry) wrote :

<cjwatson> + # be locked via apt_pkg.GetLock()
<cjwatson> whitespace change only here in a comment, but maybe update the
           comment to .get_lock()

lp:~barry/apturl/py3 updated
135. By Barry Warsaw

Change debian/compat == 9

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'AptUrl/AptUrl.py'
2--- AptUrl/AptUrl.py 2012-06-11 20:34:59 +0000
3+++ AptUrl/AptUrl.py 2012-06-14 00:37:19 +0000
4@@ -20,17 +20,15 @@
5 # along with AptUrl; if not, write to the Free Software
6 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7
8-import sys
9 import apt
10 import apt_pkg
11-import gettext
12
13 import aptsources.distro
14 from . import Parser
15 from . import Helpers
16 from .Helpers import _
17
18-from aptsources.sourceslist import SourcesList, is_mirror
19+from aptsources.sourceslist import SourcesList
20 from optparse import OptionParser
21
22 import os
23@@ -55,8 +53,6 @@
24 self.ui = ui
25
26 def enableSection(self, apturl):
27- added = False
28-
29 # parse sources.list
30 sourceslist = SourcesList()
31 distro = aptsources.distro.get_distro()
32@@ -74,7 +70,8 @@
33 if not self.ui.askEnableSections(apturl.section):
34 return RESULT_CANCELT
35 if not self.ui.doEnableSection(apturl.section):
36- self.ui.error(_("Enabling '%s' failed") % ", ".join(apturl.section))
37+ self.ui.error(_("Enabling '%s' failed") %
38+ ", ".join(apturl.section))
39 return RESULT_ERROR
40 self.ui.doUpdate()
41 self.openCache()
42@@ -114,9 +111,9 @@
43 raise
44 self.ui.error(_("Invalid /etc/apt/sources.list file"), strerr)
45 return False
46- if self.cache._depcache.BrokenCount > 0:
47+ if self.cache._depcache.broken_count > 0:
48 err_header = _("Software index is broken")
49- err_body = _("This is a major failure of your software "
50+ err_body = _("This is a major failure of your software "
51 "management system. Please check for broken packages "
52 "with synaptic, check the file permissions and "
53 "correctness of the file '/etc/apt/sources.list' and "
54@@ -126,7 +123,7 @@
55 self.ui.error(err_header, err_body)
56 return False
57 return True
58-
59+
60 def parseArgs(self):
61 parser = OptionParser()
62 parser.add_option("-p", "--http-proxy", dest="http_proxy",
63@@ -151,15 +148,15 @@
64 str(e))
65 return []
66 return (apturl_list)
67-
68+
69 def verifyInstall(self, apturl):
70 " verify that the install package actually is installed "
71 # check if the package got actually installed
72 self.openCache()
73 pkg = self.cache[apturl.package]
74- if (not pkg.isInstalled or
75- pkg._pkg.CurrentState != apt_pkg.CurStateInstalled or
76- self.cache._depcache.BrokenCount > 0):
77+ if (not pkg.is_installed or
78+ pkg._pkg.current_state != apt_pkg.CURSTATE_INSTALLED or
79+ self.cache._depcache.broken_count > 0):
80 return False
81 return True
82
83@@ -167,12 +164,12 @@
84 # global return code
85 ret = RESULT_OK
86 ui = self.ui
87-
88+
89 # parse arguments
90 apturl_list = self.parseArgs()
91 if not apturl_list:
92 return RESULT_BADARGS
93-
94+
95 # open cache
96 if not self.openCache():
97 return RESULT_ERROR
98@@ -183,7 +180,8 @@
99 # evalAptUrl()
100
101 if not apturl.schema in ("apt", "apt+http"):
102- self.ui.error(_("Can not deal with protocol '%s' ") % apturl.schema)
103+ self.ui.error(_("Can not deal with protocol '%s' ")
104+ % apturl.schema)
105 continue
106
107 if apturl.section:
108@@ -196,7 +194,7 @@
109 ui.doUpdate()
110 if not self.openCache():
111 return RESULT_ERROR
112-
113+
114 # now check the package
115 if apturl.package not in self.cache:
116 try:
117@@ -207,11 +205,14 @@
118 ui.error(_("Package '%s' is virtual.") % apturl.package)
119 continue
120 else:
121- ui.error(_("Could not find package '%s'.") % apturl.package)
122+ ui.error(_("Could not find package '%s'.")
123+ % apturl.package)
124 continue
125-
126- if self.cache[apturl.package].isInstalled and apturl.minver is None:
127- ui.message(_("Package '%s' is already installed") % apturl.package)
128+
129+ if (self.cache[apturl.package].is_installed and
130+ apturl.minver is None):
131+ ui.message(_("Package '%s' is already installed")
132+ % apturl.package)
133 continue
134
135 # ask the user
136@@ -220,20 +221,21 @@
137 if not ui.askInstallPackage(apturl.package, sum, desc, homepage):
138 ret = RESULT_CANCELT
139 continue
140-
141+
142 # try to install it
143 try:
144- self.cache[apturl.package].markInstall()
145+ self.cache[apturl.package].mark_install()
146 except SystemError as e:
147 ui.error(_("Can not install '%s' (%s) ") % (apturl.package, e))
148 continue
149 if apturl.minver is not None:
150- verStr = self.cache[apturl.package].candidateVersion
151- if apt_pkg.VersionCompare(verStr, apturl.minver) < 1:
152- ui.error(_("Package '%s' requests minimal version '%s', but "
153- "only '%s' is available") % (apturl.package,
154- apturl.minver,
155- verStr))
156+ verStr = self.cache[apturl.package].candidate_version
157+ if apt_pkg.version_compare(verStr, apturl.minver) < 1:
158+ ui.error(_(
159+ "Package '%s' requests minimal version '%s', but "
160+ "only '%s' is available") % (apturl.package,
161+ apturl.minver,
162+ verStr))
163 continue
164
165 # install it
166@@ -244,4 +246,3 @@
167
168 # return values
169 return ret
170-
171
172=== modified file 'AptUrl/Helpers.py'
173--- AptUrl/Helpers.py 2012-06-11 21:35:40 +0000
174+++ AptUrl/Helpers.py 2012-06-14 00:37:19 +0000
175@@ -39,25 +39,35 @@
176 return str
177
178 def get_dist():
179- return subprocess.Popen(["lsb_release","-c","-s"],stdout=subprocess.PIPE).communicate()[0].strip()
180+ return subprocess.Popen(["lsb_release","-c","-s"],
181+ stdout=subprocess.PIPE).communicate()[0].strip()
182
183
184 def parse_pkg(pkgobj):
185 summary = ""
186 description = ""
187- if pkgobj.description.count("\n") > 0:
188- summary, description = pkgobj.description.split('\n', 1)
189+ try:
190+ pkg_description = pkgobj.description
191+ except AttributeError:
192+ # Python 3
193+ pkg_description = pkgobj.versions[0].description
194+ if pkg_description.count("\n") > 0:
195+ summary, description = pkg_description.split('\n', 1)
196 else:
197- summary = pkgobj.description
198+ summary = pkg_description
199 lines = description.rstrip('\n').split('\n')
200 if len(lines) > 1 and lines[-1].startswith('Homepage: '):
201 homepage = lines[-1].split(' ', 1)[1]
202 description = '\n'.join(lines[:-1])
203 else:
204- homepage = pkgobj.homepage
205+ try:
206+ homepage = pkgobj.homepage
207+ except AttributeError:
208+ # Python 3
209+ homepage = pkgobj.versions[0].homepage
210 return (summary, description, homepage)
211
212 def format_description(description):
213- const = 'APTURL_DOUBLE_EMPTY_LINE_PLACEHOLDER'
214- return description.replace('\n\n', const).replace('\n', ' ').replace(
215- const, '\n\n')
216+ const = 'APTURL_DOUBLE_EMPTY_LINE_PLACEHOLDER'
217+ return description.replace('\n\n', const).replace('\n', ' ').replace(
218+ const, '\n\n')
219
220=== modified file 'AptUrl/Parser.py'
221--- AptUrl/Parser.py 2012-06-11 21:35:40 +0000
222+++ AptUrl/Parser.py 2012-06-14 00:37:19 +0000
223@@ -23,7 +23,6 @@
224 import os
225 import string
226 from string import Template
227-from subprocess import Popen, PIPE
228 from .Helpers import get_dist
229 from .Helpers import _
230
231@@ -82,7 +81,8 @@
232 " test if the url matches the internal whitelist "
233 for char in raw_url:
234 if not char in whitelist:
235- raise InvalidUrlException(raw_url, _("Non whitelist char in the uri"))
236+ raise InvalidUrlException(
237+ raw_url, _("Non whitelist char in the uri"))
238 return True
239
240 def set_value(apt_url, s):
241
242=== modified file 'AptUrl/UI.py'
243--- AptUrl/UI.py 2012-06-11 20:34:59 +0000
244+++ AptUrl/UI.py 2012-06-14 00:37:19 +0000
245@@ -1,5 +1,4 @@
246
247-from . import Helpers
248 from .Helpers import _, _n
249
250 class AbstractUI(object):
251
252=== modified file 'AptUrl/gtk/GtkUI.py'
253--- AptUrl/gtk/GtkUI.py 2012-06-11 20:34:59 +0000
254+++ AptUrl/gtk/GtkUI.py 2012-06-14 00:37:19 +0000
255@@ -5,14 +5,11 @@
256 from gi.repository import Gdk
257 from gi.repository import GObject
258 GObject.threads_init()
259-import subprocess
260+
261+import os
262 import sys
263-
264-import os
265-import os.path
266-
267 import apt_pkg
268-
269+import subprocess
270
271 from AptUrl.UI import AbstractUI
272 from AptUrl import Helpers
273@@ -20,13 +17,22 @@
274
275 from .backend import get_backend
276
277+
278+APTURL_UI_FILE = os.environ.get(
279+ # Set this envar to use a test .ui file.
280+ 'APTURL_UI_FILE',
281+ # System file to use if the envar is not set.
282+ '/usr/share/apturl/apturl-gtk.ui'
283+ )
284+
285+
286 class GtkUI(AbstractUI):
287 def __init__(self):
288 Gtk.init_check(sys.argv)
289 # create empty dialog
290 self.dia_xml = Gtk.Builder()
291 self.dia_xml.set_translation_domain("apturl")
292- self.dia_xml.add_from_file('/usr/share/apturl/apturl-gtk.ui')
293+ self.dia_xml.add_from_file(APTURL_UI_FILE)
294 self.dia = self.dia_xml.get_object('confirmation_dialog')
295 self.dia.realize()
296 self.backend = get_backend(self.dia)
297@@ -37,7 +43,8 @@
298 Gtk.main_quit()
299
300 # generic dialogs
301- def _get_dialog(self, dialog_type, summary, msg="", buttons=Gtk.ButtonsType.CLOSE):
302+ def _get_dialog(self, dialog_type, summary, msg="",
303+ buttons=Gtk.ButtonsType.CLOSE):
304 " internal helper for dialog construction "
305 d = Gtk.MessageDialog(parent=self.dia,
306 flags=Gtk.DialogFlags.MODAL,
307@@ -50,7 +57,7 @@
308 d.realize()
309 d.get_window().set_functions(Gdk.WMFunction.MOVE)
310 return d
311-
312+
313 def error(self, summary, msg=""):
314 d = self._get_dialog(Gtk.MessageType.ERROR, summary, msg)
315 d.run()
316@@ -73,7 +80,7 @@
317 if res != Gtk.ResponseType.YES:
318 return False
319 return True
320-
321+
322 # specific dialogs
323 def askEnableChannel(self, channel, channel_info_html):
324 summary = _("Enable additional software channel")
325@@ -115,7 +122,7 @@
326 return False
327 return True
328
329-
330+
331 def doEnableChannel(self, channelpath, channelkey):
332 cmd = ["gksu",
333 "--desktop", "/usr/share/applications/gnome-app-install.desktop",
334@@ -155,25 +162,25 @@
335 tbuf.set_text(desc)
336 description_text_view.set_buffer(tbuf)
337 dia.set_icon(Gtk.IconTheme.get_default().load_icon('deb', 16, False))
338-
339+
340 # check if another package manager is already running
341 # FIXME: just checking for the existance of the file is
342 # not sufficient, it need to be tested if it can
343- # be locked via apt_pkg.GetLock()
344- # - but that needs to run as root
345+ # be locked via apt_pkg.GetLock()
346+ # - but that needs to run as root
347 # - a dbus helper might be the best answer here
348 #args = (update_button_status, dia_xml.get_object("yes_button"),
349 # dia_xml.get_object("infolabel"))
350 #args[0](*args[1:])
351 #timer_id = GObject.timeout_add(750, *args )
352-
353+
354 # show the dialog
355 res = dia.run()
356 #GObject.source_remove(timer_id)
357 if res != Gtk.ResponseType.YES:
358 dia.hide()
359 return False
360-
361+
362 # don't set on-top while installing
363 dia.set_keep_above(False)
364 return True
365
366=== modified file 'AptUrl/gtk/backend/__init__.py'
367--- AptUrl/gtk/backend/__init__.py 2011-07-22 12:04:26 +0000
368+++ AptUrl/gtk/backend/__init__.py 2012-06-14 00:37:19 +0000
369@@ -45,7 +45,7 @@
370 not "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" in os.environ):
371 # check if the gtkwidgets are installed as well
372 try:
373- from InstallBackendAptdaemon import InstallBackendAptdaemon
374+ from .InstallBackendAptdaemon import InstallBackendAptdaemon
375 return InstallBackendAptdaemon(*args, **kwargs)
376 except ImportError:
377 import logging
378@@ -53,7 +53,7 @@
379 # try synaptic
380 if (os.path.exists("/usr/sbin/synaptic") and
381 not "UPDATE_MANAGER_FORCE_BACKEND_APTDAEMON" in os.environ):
382- from InstallBackendSynaptic import InstallBackendSynaptic
383+ from .InstallBackendSynaptic import InstallBackendSynaptic
384 return InstallBackendSynaptic(*args, **kwargs)
385 # nothing found, raise
386 raise Exception("No working backend found, please try installing "
387
388=== modified file 'AptUrl/kde/KdeUI.py'
389--- AptUrl/kde/KdeUI.py 2012-06-11 20:34:59 +0000
390+++ AptUrl/kde/KdeUI.py 2012-06-14 00:37:19 +0000
391@@ -1,6 +1,6 @@
392 # -*- coding: utf-8 -*-
393
394-from __future__ import print_funcion
395+from __future__ import print_function
396
397 from PyQt4.QtCore import *
398 from PyQt4.QtGui import *
399@@ -9,19 +9,20 @@
400 from PyKDE4.kdeui import *
401 from PyKDE4.kdecore import *
402
403-import subprocess
404-from tempfile import NamedTemporaryFile
405-
406 import os
407-import os.path
408-
409-import time
410-import thread
411 import apt_pkg
412+import subprocess
413
414 from AptUrl.UI import AbstractUI
415-from AptUrl import Helpers
416-from AptUrl.Helpers import utf8, _, _n
417+from AptUrl.Helpers import _
418+
419+APTURL_UI_FILE = os.environ.get(
420+ # Set this envar to use a test .ui file.
421+ 'APTURL_UI_FILE',
422+ # System file to use if the envar is not set.
423+ '/usr/share/apturl/apturl-qt.ui'
424+ )
425+
426
427 class AptUrlDialog(KDialog):
428 def __init__(self,parent=None):
429@@ -34,6 +35,7 @@
430 else:
431 KDialog.reject(self)
432
433+
434 class KdeUI(AbstractUI):
435 def __init__(self):
436 self.dialog = AptUrlDialog()
437@@ -41,7 +43,7 @@
438 self.d = QWidget(self.dialog)
439 self.dialog.setMainWidget(self.d)
440
441- uic.loadUi('/usr/share/apturl/apturl-qt.ui', self.d)
442+ uic.loadUi(APTURL_UI_FILE, self.d)
443 self.d.image_label.setPixmap(KIcon("application-x-deb").pixmap(64,64))
444
445 # generic dialogs
446@@ -97,7 +99,8 @@
447 "software-properties-kde",
448 "--enable-component", "%s" % ' '.join(sections)]
449 try:
450- output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
451+ output = subprocess.Popen(
452+ cmd, stdout=subprocess.PIPE).communicate()[0]
453 except OSError as e:
454 print("Execution failed: %s" % e, file=sys.stderr)
455 return True
456@@ -129,7 +132,7 @@
457 def askInstallPackage(self, package, summary, description, homepage):
458 header = "<h2>" + _("Install additional software?") + "</h2>"
459 body = _("Do you want to install package '%s'?") % package
460- desc = "%s\n\n%s" % (summary, Helpers.format_description(description))
461+ #desc = "%s\n\n%s" % (summary, Helpers.format_description(description))
462
463 self.d.header_label.setText(header)
464 self.d.body_label.setText(body)
465@@ -145,36 +148,19 @@
466
467 # progress etc
468 def doUpdate(self):
469- p = subprocess.Popen(['qapt-batch',
470- '--attach', str(self.dialog.winId()),
471- '--update'
472- ])
473- self._wait_for_install_package(p)
474+ subprocess.check_call([
475+ 'qapt-batch',
476+ '--attach', str(self.dialog.winId()),
477+ '--update'
478+ ])
479
480 def doInstall(self, apturl):
481- p = subprocess.Popen(['qapt-batch',
482- '--attach', str(self.dialog.winId()),
483- '--install',
484- apturl.package
485- ])
486- self._wait_for_install_package(p)
487- return True
488-
489- # helpers
490- def _wait_for_p(self, p, lock):
491- " helper for the thread to wait for process p to finish "
492- p.wait()
493- lock.release()
494-
495- def _wait_for_install_package(self, p):
496- # wait for qapt-batch
497- lock = thread.allocate_lock()
498- lock.acquire()
499- thread.start_new_thread(self._wait_for_p, (p, lock))
500-
501- while lock.locked():
502- time.sleep(0.01)
503- return True
504+ subprocess.check_call([
505+ 'qapt-batch',
506+ '--attach', str(self.dialog.winId()),
507+ '--install',
508+ apturl.package
509+ ])
510
511
512 if __name__ == "__main__":
513
514=== modified file 'apturl-gtk'
515--- apturl-gtk 2012-06-11 20:34:59 +0000
516+++ apturl-gtk 2012-06-14 00:37:19 +0000
517@@ -1,4 +1,4 @@
518-#!/usr/bin/python
519+#!/usr/bin/python3
520 #
521 # Copyright (c) 2007-2008 Canonical
522 #
523@@ -22,13 +22,12 @@
524 # along with AptUrl; if not, write to the Free Software
525 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
526
527+from __future__ import print_function
528
529 # ignore apt's "API not stable yet" warning
530 import warnings
531 warnings.filterwarnings("ignore", category=FutureWarning, append=1)
532
533-from __future__ import print_function
534-
535 import sys
536 import gettext
537 from gettext import gettext as _
538
539=== modified file 'apturl-kde'
540--- apturl-kde 2012-06-11 20:34:59 +0000
541+++ apturl-kde 2012-06-14 00:37:19 +0000
542@@ -1,4 +1,4 @@
543-#!/usr/bin/python
544+#!/usr/bin/python3
545 # -*- coding: utf-8 -*-
546 #
547 # Copyright © 2009 Harald Sitter <apachelogger@ubuntu.com>
548@@ -22,13 +22,12 @@
549 # along with AptUrl; if not, write to the Free Software
550 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
551
552+from __future__ import print_function
553
554 # ignore apt's "API not stable yet" warning
555 import warnings
556 warnings.filterwarnings("ignore", category=FutureWarning, append=1)
557
558-from __future__ import print_function
559-
560 import sys
561 import gettext
562 from gettext import gettext as _
563@@ -58,18 +57,18 @@
564 if __name__ == "__main__":
565 appName = "apturl"
566 catalog = ""
567- programName = ki18n ("AptUrl")
568+ programName = ki18n (b"AptUrl")
569 version = "1.0"
570- description = ki18n ("AptUrl for Kubuntu")
571+ description = ki18n (b"AptUrl for Kubuntu")
572 license = KAboutData.License_GPL
573- copyright = ki18n ("© Harald Sitter")
574- text = ki18n ("none")
575+ copyright = ki18n ("© Harald Sitter".encode('utf-8'))
576+ text = ki18n (b"none")
577 homePage = "http://www.kubuntu.org/"
578 bugEmail = ""
579
580 about = KAboutData (appName, catalog, programName, version, description,
581 license, copyright, text, homePage, bugEmail)
582- about.addAuthor(ki18n("Harald Sitter"), KLocalizedString(),
583+ about.addAuthor(ki18n(b"Harald Sitter"), KLocalizedString(),
584 "apachelogger@ubuntu.com")
585 KCmdLineArgs.init([""],about)
586
587
588=== modified file 'debian/apturl-common.install'
589--- debian/apturl-common.install 2011-03-30 13:46:50 +0000
590+++ debian/apturl-common.install 2012-06-14 00:37:19 +0000
591@@ -1,7 +1,7 @@
592 etc/
593 usr/bin/apturl
594-usr/lib/python2.?/*-packages/AptUrl/*py*
595-usr/lib/python2.?/*-packages/apturl-*.egg-info
596+usr/lib/python3/*-packages/AptUrl/*py*
597+usr/lib/python3/*-packages/apturl-*.egg-info
598 usr/share/kde4/services
599 usr/share/locale
600 usr/share/applications
601
602=== modified file 'debian/apturl-kde.install'
603--- debian/apturl-kde.install 2010-12-17 14:42:22 +0000
604+++ debian/apturl-kde.install 2012-06-14 00:37:19 +0000
605@@ -1,3 +1,3 @@
606 usr/bin/apturl-kde
607-usr/lib/python2.?/*-packages/AptUrl/kde/*py*
608+usr/lib/python3/*-packages/AptUrl/kde/*py*
609 usr/share/apturl/*-qt.ui
610
611=== modified file 'debian/apturl.install'
612--- debian/apturl.install 2011-07-22 12:04:26 +0000
613+++ debian/apturl.install 2012-06-14 00:37:19 +0000
614@@ -1,5 +1,5 @@
615 usr/bin/apturl-gtk
616-usr/lib/python2.?/*-packages/AptUrl/gtk/*py*
617-usr/lib/python2.?/*-packages/AptUrl/gtk/backend/
618+usr/lib/python3/*-packages/AptUrl/gtk/*py*
619+usr/lib/python3/*-packages/AptUrl/gtk/backend/
620 usr/share/apturl/*-gtk.ui
621 usr/share/gconf
622
623=== modified file 'debian/changelog'
624--- debian/changelog 2012-06-12 16:09:13 +0000
625+++ debian/changelog 2012-06-14 00:37:19 +0000
626@@ -12,6 +12,27 @@
627 to avoid attempts to destroy it without a thread context.
628 - Open temporary synaptic selections file in text mode.
629
630+ [ Barry Warsaw ]
631+ * Additional Python 3 fixes:
632+ + Port setup.py to Python 3.
633+ + Use the new python-apt API since the legacy API is not available in
634+ Python 3.
635+ + ki18n() takes bytes.
636+ + Fix relative imports so the code can be run from source.
637+ + Fixed some additional packaging paths.
638+ + Fix typos in __future__ imports.
639+ + Change #! lines to use python3.
640+ + Changed debian/control and debian/rules to use python3.
641+ + Change debian/compat == 8
642+ + apturl now must require python3-aptdaemon.gtk3widgets (i.e. not |
643+ synaptic) due to the Python 3 port of update-manager.
644+ * Other changes:
645+ + Remove the need for threads in the KDE front-end.
646+ + Enable running the test suite via `python3 -m unittest discover`
647+ + i18n updates.
648+ + Various and sundry pyflakes, whitespace, style, line length, and
649+ spelling fixes.
650+
651 -- Brian Murray <brian@ubuntu.com> Mon, 11 Jun 2012 10:32:52 -0700
652
653 apturl (0.5.1ubuntu3) precise; urgency=low
654
655=== modified file 'debian/compat'
656--- debian/compat 2009-09-10 11:45:36 +0000
657+++ debian/compat 2012-06-14 00:37:19 +0000
658@@ -1,1 +1,1 @@
659-7
660+8
661
662=== modified file 'debian/control'
663--- debian/control 2012-03-13 18:45:45 +0000
664+++ debian/control 2012-06-14 00:37:19 +0000
665@@ -2,23 +2,26 @@
666 Section: admin
667 Priority: optional
668 Maintainer: Michael Vogt <mvo@ubuntu.com>
669-Build-Depends: debhelper (>= 7.0.50~),
670+Build-Depends: debhelper (>= 8),
671 intltool,
672- python-dev,
673- python-distutils-extra
674-XS-Python-Version: current
675+ python3-dev,
676+ python3-distutils-extra,
677+ python3-update-manager,
678+ python3-aptdaemon
679+X-Python3-Version: >= 3.2
680 Standards-Version: 3.9.1
681 Vcs-Bzr: http://bazaar.launchpad.net/~ubuntu-core-dev/apturl/ubuntu/
682 Vcs-Browser: http://bazaar.launchpad.net/~ubuntu-core-dev/apturl/ubuntu/files
683
684 Package: apturl-common
685 Architecture: any
686-Depends: ${python:Depends},
687+Depends: ${python3:Depends},
688 ${shlibs:Depends},
689 ${misc:Depends},
690- python-apt
691+ python3-apt,
692+ python3-update-manager,
693+ python3-aptdaemon
694 Replaces: apturl (<< 0.3.6ubuntu2)
695-XB-Python-Version: ${python:Versions}
696 Description: install packages using the apt protocol - common data
697 AptUrl is a simple graphical application that takes an URL (which follows the
698 apt-protocol) as a command line option, parses it and carries out the
699@@ -30,18 +33,17 @@
700
701 Package: apturl
702 Architecture: any
703-Depends: ${python:Depends},
704+Depends: ${python3:Depends},
705 ${shlibs:Depends},
706 ${misc:Depends},
707 apturl-common (= ${binary:Version}),
708 gnome-icon-theme (>= 2.14.0-1),
709- python-gi,
710+ python3-gi,
711 software-properties-gtk,
712- python-aptdaemon.gtk3widgets | synaptic,
713+ python3-aptdaemon.gtk3widgets,
714 gir1.2-gtk-3.0,
715 gir1.2-webkit-3.0
716 Recommends: libgtk2-perl (>= 1:1.130)
717-XB-Python-Version: ${python:Versions}
718 Description: install packages using the apt protocol - GTK+ frontend
719 AptUrl is a simple graphical application that takes an URL (which follows the
720 apt-protocol) as a command line option, parses it and carries out the
721@@ -53,16 +55,15 @@
722
723 Package: apturl-kde
724 Architecture: any
725-Depends: ${python:Depends},
726+Depends: ${python3:Depends},
727 ${shlibs:Depends},
728 ${misc:Depends},
729- python-qt4,
730- python-kde4,
731+ python3-pyqt4,
732+ python3-pykde4,
733 apturl-common (= ${binary:Version}),
734 kdesudo,
735 qapt-batch,
736 software-properties-kde (>= 0.75.2)
737-XB-Python-Version: ${python:Versions}
738 Description: install packages using the apt protocol - KDE frontend
739 AptUrl is a simple graphical application that takes an URL (which follows the
740 apt-protocol) as a command line option, parses it and carries out the
741
742=== removed file 'debian/pycompat'
743--- debian/pycompat 2007-07-02 09:31:04 +0000
744+++ debian/pycompat 1970-01-01 00:00:00 +0000
745@@ -1,1 +0,0 @@
746-2
747\ No newline at end of file
748
749=== modified file 'debian/rules'
750--- debian/rules 2010-12-17 14:42:22 +0000
751+++ debian/rules 2012-06-14 00:37:19 +0000
752@@ -1,15 +1,18 @@
753 #!/usr/bin/make -f
754 %:
755- dh --with python2 $@
756+ dh $@ --with python3
757
758 override_dh_auto_clean:
759 rm -f AptUrl/Version.py
760
761+override_dh_auto_build:
762+ python3 setup.py build
763+
764 override_dh_auto_install:
765- python ./setup.py install --prefix=$(CURDIR)/debian/tmp/usr
766+ python3 ./setup.py install --root=$(CURDIR)/debian/tmp --install-layout=deb
767
768-override_dh_install:
769- dh_install --sourcedir=debian/tmp --fail-missing
770+override_dh_auto_test:
771+ python3 -m unittest discover -vv
772
773
774 PKG=apturl
775
776=== modified file 'po/apturl.pot'
777--- po/apturl.pot 2009-01-08 19:46:00 +0000
778+++ po/apturl.pot 2012-06-14 00:37:19 +0000
779@@ -8,47 +8,52 @@
780 msgstr ""
781 "Project-Id-Version: PACKAGE VERSION\n"
782 "Report-Msgid-Bugs-To: \n"
783-"POT-Creation-Date: 2009-01-08 20:26+0100\n"
784+"POT-Creation-Date: 2012-06-12 17:39-0400\n"
785 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
786 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
787 "Language-Team: LANGUAGE <LL@li.org>\n"
788+"Language: \n"
789 "MIME-Version: 1.0\n"
790 "Content-Type: text/plain; charset=CHARSET\n"
791 "Content-Transfer-Encoding: 8bit\n"
792-"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
793
794-#: ../apturl:50
795+#: ../apturl-gtk:51 ../apturl-kde:54
796 msgid "User requested interrupt."
797 msgstr ""
798
799-#: ../AptUrl/Parser.py:79
800+#: ../AptUrl/Parser.py:85
801 msgid "Non whitelist char in the uri"
802 msgstr ""
803
804-#: ../AptUrl/Parser.py:91
805-msgid "No ':' in the uri"
806-msgstr ""
807-
808-#: ../AptUrl/Parser.py:117
809+#: ../AptUrl/Parser.py:93
810 msgid "Whitespace in key=value"
811 msgstr ""
812
813-#: ../AptUrl/Parser.py:123
814+#: ../AptUrl/Parser.py:99
815 #, python-format
816 msgid "Exception '%s'"
817 msgstr ""
818
819-#: ../AptUrl/AptUrl.py:78
820+#: ../AptUrl/Parser.py:109
821+#, python-format
822+msgid "Url string '%s' too long"
823+msgstr ""
824+
825+#: ../AptUrl/Parser.py:115
826+msgid "No ':' in the uri"
827+msgstr ""
828+
829+#: ../AptUrl/AptUrl.py:73
830 #, python-format
831 msgid "Enabling '%s' failed"
832 msgstr ""
833
834-#: ../AptUrl/AptUrl.py:94
835+#: ../AptUrl/AptUrl.py:91
836 #, python-format
837 msgid "Unknown channel '%s'"
838 msgstr ""
839
840-#: ../AptUrl/AptUrl.py:95
841+#: ../AptUrl/AptUrl.py:92
842 #, python-format
843 msgid "The channel '%s' is not known"
844 msgstr ""
845@@ -88,74 +93,70 @@
846 msgid "Can not deal with protocol '%s' "
847 msgstr ""
848
849-#: ../AptUrl/AptUrl.py:202
850+#: ../AptUrl/AptUrl.py:205
851 #, python-format
852 msgid "Package '%s' is virtual."
853 msgstr ""
854
855-#: ../AptUrl/AptUrl.py:205
856+#: ../AptUrl/AptUrl.py:208
857 #, python-format
858 msgid "Could not find package '%s'."
859 msgstr ""
860
861-#: ../AptUrl/AptUrl.py:209
862+#: ../AptUrl/AptUrl.py:214
863 #, python-format
864 msgid "Package '%s' is already installed"
865 msgstr ""
866
867-#: ../AptUrl/AptUrl.py:223
868+#: ../AptUrl/AptUrl.py:229
869 #, python-format
870 msgid "Can not install '%s' (%s) "
871 msgstr ""
872
873-#: ../AptUrl/AptUrl.py:228
874+#: ../AptUrl/AptUrl.py:235
875 #, python-format
876 msgid "Package '%s' requests minimal version '%s', but only '%s' is available"
877 msgstr ""
878
879-#: ../AptUrl/UI.py:17
880+#: ../AptUrl/UI.py:16
881 msgid "Enable additional components"
882 msgstr ""
883
884-#: ../AptUrl/UI.py:18
885-#, python-format
886-msgid "Do you want to enable the following component: '%s'?"
887-msgid_plural "Do you want to enable the following components: '%s'?"
888-msgstr[0] ""
889-msgstr[1] ""
890-
891-#: ../AptUrl/UI.py:25
892+#: ../AptUrl/UI.py:24 ../AptUrl/gtk/GtkUI.py:86 ../AptUrl/kde/KdeUI.py:82
893 msgid "Enable additional software channel"
894 msgstr ""
895
896-#: ../AptUrl/UI.py:26
897+#: ../AptUrl/UI.py:25 ../AptUrl/gtk/GtkUI.py:87 ../AptUrl/kde/KdeUI.py:83
898 #, python-format
899 msgid "Do you want to enable the following software channel: '%s'?"
900 msgstr ""
901
902-#: ../AptUrl/gtk/GtkUI.py:117
903+#: ../AptUrl/gtk/GtkUI.py:151 ../AptUrl/kde/KdeUI.py:133
904 msgid "Install additional software?"
905 msgstr ""
906
907-#: ../AptUrl/gtk/GtkUI.py:118
908+#: ../AptUrl/gtk/GtkUI.py:152 ../AptUrl/kde/KdeUI.py:134
909 #, python-format
910 msgid "Do you want to install package '%s'?"
911 msgstr ""
912
913-#: ../data/apturl.glade.h:1
914+#. kate: space-indent on; indent-width 4; mixedindent off; indent-mode python;
915+#: ../data/apturl-gtk.ui.h:1
916 msgid "Description"
917 msgstr ""
918
919-#: ../data/apturl.glade.h:2
920+#: ../data/apturl-gtk.ui.h:2
921 msgid "_Install"
922 msgstr ""
923
924 #: ../data/apturl.schemas.in.h:1
925-msgid "Run the command in a terminal"
926+msgid "Whether the specified command should handle \"apt\" URLs"
927 msgstr ""
928
929 #: ../data/apturl.schemas.in.h:2
930-msgid "The command used to handle \"apt\" URLs, if enabled."
931+msgid ""
932+"True if the command specified in the \"command\" key should handle \"apt\" "
933+"URLs."
934 msgstr ""
935
936 #: ../data/apturl.schemas.in.h:3
937@@ -163,17 +164,15 @@
938 msgstr ""
939
940 #: ../data/apturl.schemas.in.h:4
941-msgid ""
942-"True if the command specified in the \"command\" key should handle \"apt\" "
943-"URLs."
944+msgid "The command used to handle \"apt\" URLs, if enabled."
945 msgstr ""
946
947 #: ../data/apturl.schemas.in.h:5
948+msgid "Run the command in a terminal"
949+msgstr ""
950+
951+#: ../data/apturl.schemas.in.h:6
952 msgid ""
953 "True if the command used to handle this type of URL should be run in a "
954 "terminal."
955 msgstr ""
956-
957-#: ../data/apturl.schemas.in.h:6
958-msgid "Whether the specified command should handle \"apt\" URLs"
959-msgstr ""
960
961=== modified file 'setup.py'
962--- setup.py 2011-07-22 12:04:26 +0000
963+++ setup.py 2012-06-14 00:37:19 +0000
964@@ -1,4 +1,4 @@
965-#!/usr/bin/env python
966+#!/usr/bin/env python3
967
968 from distutils.core import setup
969 from DistUtilsExtra.command import *
970@@ -9,13 +9,13 @@
971 # look/set what version we have
972 changelog = "debian/changelog"
973 if os.path.exists(changelog):
974- head = open(changelog).readline()
975+ with open(changelog, encoding='utf-8') as fp:
976+ head = fp.readline()
977 match = re.compile(".*\((.*)\).*").match(head)
978 if match:
979 version = match.group(1)
980- f = open("AptUrl/Version.py", "w")
981- f.write("VERSION=\"%s\"\n" % version)
982- f.close()
983+ with open("AptUrl/Version.py", "w") as fp:
984+ print('VERSION="{}"'.format(version))
985
986 GETTEXT_NAME="apturl"
987 I18NFILES = []
988
989=== added file 'tests/__init__.py'
990=== renamed file 'tests/apturlparse.py' => 'tests/test_apturl_parse.py'
991--- tests/apturlparse.py 2012-06-11 20:34:59 +0000
992+++ tests/test_apturl_parse.py 2012-06-14 00:37:19 +0000
993@@ -1,17 +1,13 @@
994-#!/usr/bin/python
995-
996 from __future__ import print_function
997
998-import sys
999-sys.path.insert(0, "../")
1000-
1001 import unittest
1002+
1003 from AptUrl import Parser
1004
1005
1006-class TestUrl(unittest.TestCase):
1007+class UrlTests(unittest.TestCase):
1008 mapping = { 'kernel':"2.6.23-17-generic",
1009- 'distro':"hardy" }
1010+ 'distro':"hardy" }
1011
1012 testValues = ( ('apt:3ddesktop', [{'package':'3ddesktop',
1013 'schema': 'apt'}] ),
1014@@ -32,11 +28,11 @@
1015 ('apt:2vcard?minver=1.0',
1016 [{'package':'2vcard', 'schema': 'apt',
1017 'minver': '1.0' }]),
1018- ('apt:owl,newbiedoc,python-pykaraoke?dist=gutsy',
1019+ ('apt:owl,newbiedoc,python-pykaraoke?dist=gutsy',
1020 [{'package':'owl', 'schema':'apt'},
1021 {'package':'newbiedoc', 'schema':'apt'},
1022 {'package':'python-pykaraoke', 'schema':'apt', 'dist':'gutsy'}]),
1023- ('apt:python-pykaraoke?dist=gutsy,owl,newbiedoc',
1024+ ('apt:python-pykaraoke?dist=gutsy,owl,newbiedoc',
1025 [{'package':'python-pykaraoke', 'schema':'apt', 'dist':'gutsy'},
1026 {'package':'owl', 'schema':'apt'},
1027 {'package':'newbiedoc', 'schema':'apt'}]),
1028@@ -60,20 +56,16 @@
1029 }]),
1030 )
1031
1032- def testValidParse(self):
1033- for (v, e) in self.testValues:
1034- print("Testing: '%s'" % v)
1035+ def test_valid_parse(self):
1036+ for v, e in self.testValues:
1037+ #print("Testing: '%s'" % v)
1038 result_list = Parser.parse(v, self.mapping)
1039 for dictionary in e:
1040 for key in dictionary:
1041 self.assertEqual(getattr(result_list[e.index(dictionary)],
1042- key), dictionary[key])
1043+ key), dictionary[key])
1044
1045 def test_pkgname_too_long(self):
1046 self.assertRaises(
1047 Parser.InvalidUrlException, Parser.parse,
1048 "apt:" + 100 * "veryverylong")
1049-
1050-
1051-if __name__ == "__main__":
1052- unittest.main()
1053
1054=== modified file 'tests/test_helpers.py'
1055--- tests/test_helpers.py 2012-06-11 21:35:40 +0000
1056+++ tests/test_helpers.py 2012-06-14 00:37:19 +0000
1057@@ -1,24 +1,17 @@
1058-#!/usr/bin/python
1059-
1060-import sys
1061-sys.path.insert(0, "../")
1062-
1063 import unittest
1064+
1065 from AptUrl.Helpers import parse_pkg
1066
1067+
1068 class MockPkg(object):
1069 def __init__(self, descr):
1070 self.description = descr
1071 self.homepage = None
1072
1073-class testHelpers(unittest.TestCase):
1074
1075+class HelpersTest(unittest.TestCase):
1076 def test_parse_pkg(self):
1077 pkgobj = MockPkg("summary\ndescr\n")
1078 self.assertEqual(parse_pkg(pkgobj), ('summary','descr\n',None))
1079 pkgobj = MockPkg("summary only")
1080 self.assertEqual(parse_pkg(pkgobj), ('summary only','',None))
1081-
1082-if __name__ == "__main__":
1083- unittest.main()
1084-

Subscribers

People subscribed via source and target branches