Hi Colin, hi Matthias, now that the Ubuntu Pangolin was released (congrats!), from what I understand from the Ubuntu release process, it will very soon be the "big merge" time. And the src:lsb package has diverged quite a lot between the Debian and Ubuntu counterparts. Now, while I tried my best to merge the past and actual changes from Ubuntu, there is certainly a diff that needs manual merging (hence discussion). Furthermore, I don't think Ubuntu and Debian really need different src:lsb packages (especially when we can play with dpkg-vendor snippets where needed). So I am willing to put work where needed towards the goal of sharing a single Debian source package. Where do you want to start from? (By the way, one major hurdle is probably the default python version for lsb-release. The attached patch is an attempt at making the python scripts work with both python2.6 and python3 without further change. Comments welcome.) Cheers, OdyX
diff --git a/initdutils.py b/initdutils.py
index 3b5bb10..e911dfa 100644
--- a/initdutils.py
+++ b/initdutils.py
@@ -1,13 +1,10 @@
# Support for scanning init scripts for LSB info
-import re, sys, os, cStringIO
-import cPickle
+# Python3-compatible print() function
+from __future__ import print_function
-try:
- assert True
-except:
- True = 1
- False = 0
+import re, sys, os, io
+import pickle
class RFC822Parser(dict):
"A dictionary-like object."
@@ -15,14 +12,14 @@ class RFC822Parser(dict):
def __init__(self, fileob=None, strob=None, startcol=0, basedict=None):
if not fileob and not strob:
- raise ValueError, 'need a file or string'
+ raise ValueError('need a file or string')
if not basedict:
basedict = {}
super(RFC822Parser, self).__init__(basedict)
if not fileob:
- fileob = cStringIO.StringIO(strob)
+ fileob = io.StringIO(strob)
key = None
for line in fileob:
@@ -79,13 +76,13 @@ def scan_initfile(initfile):
inheaders = RFC822Parser(strob=headerlines)
headers = {}
- for header, body in inheaders.iteritems():
+ for header, body in list(inheaders.items()):
# Ignore empty headers
if not body.strip():
continue
if header in ('Default-Start', 'Default-Stop'):
- headers[header] = map(int, body.split())
+ headers[header] = list(map(int, body.split()))
elif header in ('Required-Start', 'Required-Stop', 'Provides',
'Should-Start', 'Should-Stop'):
headers[header] = body.split()
@@ -103,24 +100,24 @@ def save_facilities(facilities):
return
fh = file(FACILITIES, 'w')
- for facility, entries in facilities.items():
+ for facility, entries in list(facilities.items()):
# Ignore system facilities
if facility.startswith('$'): continue
- for (scriptname, pri) in entries.items():
+ for (scriptname, pri) in list(entries.items()):
start, stop = pri
- print >> fh, "%(scriptname)s %(facility)s %(start)d %(stop)d" % locals()
+ print("%(scriptname)s %(facility)s %(start)d %(stop)d" % locals(), file=fh)
fh.close()
def load_facilities():
facilities = {}
if os.path.exists(FACILITIES):
- for line in open(FACILITIES).xreadlines():
+ for line in open(FACILITIES):
try:
scriptname, name, start, stop = line.strip().split()
facilities.setdefault(name, {})[scriptname] = (int(start),
int(stop))
- except ValueError, x:
- print >> sys.stderr, 'Invalid facility line', line
+ except ValueError as x:
+ print('Invalid facility line', line, file=sys.stderr)
return facilities
@@ -129,7 +126,7 @@ def load_depends():
if os.path.exists(DEPENDS):
independs = RFC822Parser(fileob=file(DEPENDS))
- for initfile, facilities in independs.iteritems():
+ for initfile, facilities in list(independs.items()):
depends[initfile] = facilities.split()
return depends
@@ -142,8 +139,8 @@ def save_depends(depends):
return
fh = file(DEPENDS, 'w')
- for initfile, facilities in depends.iteritems():
- print >> fh, '%s: %s' % (initfile, ' '.join(facilities))
+ for initfile, facilities in list(depends.items()):
+ print('%s: %s' % (initfile, ' '.join(facilities)), file=fh)
fh.close()
# filemap entries are mappings, { (package, filename) : instloc }
@@ -152,7 +149,7 @@ def load_lsbinstall_info():
return {}
fh = open(LSBINSTALL, 'rb')
- filemap = cPickle.load(fh)
+ filemap = pickle.load(fh)
fh.close()
# Just in case it's corrupted somehow
@@ -170,8 +167,8 @@ def save_lsbinstall_info(filemap):
return
fh = open(LSBINSTALL, 'wb')
- cPickle.dump(fh, filemap)
+ pickle.dump(fh, filemap)
fh.close()
if __name__ == '__main__':
- print scan_initfile('init-fragment')
+ print(scan_initfile('init-fragment'))
diff --git a/install_initd b/install_initd
index 4ec8452..3f3e86e 100755
--- a/install_initd
+++ b/install_initd
@@ -1,5 +1,8 @@
#!/usr/bin/python
+# Python3-compatible print() function
+from __future__ import print_function
+
import sys, re, os, initdutils
if len(sys.argv) > 1:
@@ -12,7 +15,7 @@ if len(sys.argv) > 1:
else:
initfile = os.path.join('/etc/init.d', initfile)
else:
- print >> sys.stderr, 'Usage: %s /etc/init.d/<init-script>' % sys.argv[0]
+ print('Usage: %s /etc/init.d/<init-script>' % sys.argv[0], file=sys.stderr)
sys.exit(1)
# Default priorities
@@ -22,19 +25,19 @@ defstop = [0, 1, 6]
# Estimated priorities of these facilities in Debian
os_facilities = {
- "$local_fs" : {'lsb' : (0, 100)},
- "$network" : {'lsb' : (10, 50)},
- "$remote_fs" : {'lsb': (19, 20)},
- "$named" : {'lsb': (19, 19)},
- "$syslog" : {'lsb' : (10, 89)},
+ "$local_fs": {'lsb' : (0, 100)},
+ "$network": {'lsb' : (10, 50)},
+ "$remote_fs": {'lsb': (19, 20)},
+ "$named": {'lsb': (19, 19)},
+ "$syslog": {'lsb' : (10, 89)},
# No longer present in gLSB 1.2; however, required for gLSB 1.1
# compat. Note that these are looser than $portmap and $time;
# anything specifying $netdaemons will be run later, which may not
# be what you want...
- "$netdaemons" : {'lsb': (80, 19)},
+ "$netdaemons": {'lsb': (80, 19)},
# gLSB 1.2
- "$portmap" : {'lsb' : (19, 34)},
- "$time" : {'lsb' : (24, 21)},
+ "$portmap": {'lsb' : (19, 34)},
+ "$time": {'lsb' : (24, 21)},
}
facilities = initdutils.load_facilities()
@@ -51,10 +54,10 @@ if reqstart or shouldstart:
startpri = 5
for facility in reqstart:
if facility not in facilities:
- print >> sys.stderr, 'Missing required start facility', facility
+ print('Missing required start facility', facility, file=sys.stderr)
sys.exit(1)
else:
- for script, pri in facilities[facility].iteritems():
+ for script, pri in list(facilities[facility].items()):
if script != initfile:
start, stop = pri
startpri = max(startpri, start+1)
@@ -63,9 +66,9 @@ if reqstart or shouldstart:
for facility in shouldstart:
if facility not in facilities:
- print >> sys.stderr, 'Missing should-start facility', facility, '(ignored)'
+ print('Missing should-start facility', facility, '(ignored)', file=sys.stderr)
else:
- for script, pri in facilities[facility].iteritems():
+ for script, pri in list(facilities[facility].items()):
if script != initfile:
start, stop = pri
startpri = max(startpri, start+1)
@@ -77,10 +80,10 @@ if reqstop or shouldstop:
stoppri = 95
for facility in reqstop:
if facility not in facilities:
- print >> sys.stderr, 'Missing required stop facility', facility
+ print('Missing required stop facility', facility, file=sys.stderr)
sys.exit(1)
else:
- for script, pri in facilities[facility].iteritems():
+ for script, pri in list(facilities[facility].items()):
if script != initfile:
start, stop = pri
stoppri = min(stoppri, stop-1)
@@ -89,9 +92,9 @@ if reqstop or shouldstop:
for facility in shouldstop:
if facility not in facilities:
- print >> sys.stderr, 'Missing should-stop facility', facility, '(ignored)'
+ print('Missing should-stop facility', facility, '(ignored)', file=sys.stderr)
else:
- for script, pri in facilities[facility].iteritems():
+ for script, pri in list(facilities[facility].items()):
if script != initfile:
start, stop = pri
stoppri = min(stoppri, stop-1)
@@ -105,9 +108,9 @@ provides = headers.get('Provides', [])
if provides:
for facility in provides:
if facility[0] == '$':
- print >> sys.stderr, 'Ignoring system-provided facility', facility
+ print('Ignoring system-provided facility', facility, file=sys.stderr)
continue
- if not facilities.has_key(facility):
+ if facility not in facilities:
facilities[facility] = {}
facilities[facility][initfile] = (startpri, stoppri)
@@ -117,13 +120,13 @@ defstart = headers.get('Default-Start', defstart)
defstop = headers.get('Default-Stop', defstop)
# A set type would be nice... [range(2,6) = 2..5]
-for level in range(2,6):
+for level in range(2, 6):
if level in defstart:
- for i in range(2,6):
+ for i in range(2, 6):
if i not in defstart:
defstart.append(i)
if level in defstop:
- for i in range(2,6):
+ for i in range(2, 6):
if i not in defstop:
defstop.append(i)
diff --git a/lsb_release b/lsb_release
index f8e8a53..abb201f 100755
--- a/lsb_release
+++ b/lsb_release
@@ -17,9 +17,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
+# Python3-compatible print() function
+from __future__ import print_function
+
from optparse import OptionParser
import sys
-import commands
import os
import re
@@ -62,35 +64,35 @@ def main():
if none or options.all or options.version:
verinfo = lsb_release.check_modules_installed()
if not verinfo:
- print >> sys.stderr, "No LSB modules are available."
+ print("No LSB modules are available.", file=sys.stderr)
elif short:
- print ':'.join(verinfo)
+ print(':'.join(verinfo))
else:
- print 'LSB Version:\t' + ':'.join(verinfo)
+ print('LSB Version:\t' + ':'.join(verinfo))
if options.id or options.all:
if short:
- print distinfo.get('ID', 'n/a')
+ print(distinfo.get('ID', 'n/a'))
else:
- print 'Distributor ID:\t%s' % distinfo.get('ID', 'n/a')
+ print('Distributor ID:\t%s' % distinfo.get('ID', 'n/a'))
if options.description or options.all:
if short:
- print distinfo.get('DESCRIPTION', 'n/a')
+ print(distinfo.get('DESCRIPTION', 'n/a'))
else:
- print 'Description:\t%s' % distinfo.get('DESCRIPTION', 'n/a')
+ print('Description:\t%s' % distinfo.get('DESCRIPTION', 'n/a'))
if options.release or options.all:
if short:
- print distinfo.get('RELEASE', 'n/a')
+ print(distinfo.get('RELEASE', 'n/a'))
else:
- print 'Release:\t%s' % distinfo.get('RELEASE', 'n/a')
+ print('Release:\t%s' % distinfo.get('RELEASE', 'n/a'))
if options.codename or options.all:
if short:
- print distinfo.get('CODENAME', 'n/a')
+ print(distinfo.get('CODENAME', 'n/a'))
else:
- print 'Codename:\t%s' % distinfo.get('CODENAME', 'n/a')
+ print('Codename:\t%s' % distinfo.get('CODENAME', 'n/a'))
if __name__ == '__main__':
main()
diff --git a/lsb_release.py b/lsb_release.py
index 2727d13..33c189c 100644
--- a/lsb_release.py
+++ b/lsb_release.py
@@ -17,8 +17,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
+# Python3-compatible print() function
+from __future__ import print_function
+
import sys
-import commands
+import subprocess
import os
import re
@@ -42,9 +45,9 @@ RELEASE_CODENAME_LOOKUP = {
TESTING_CODENAME = 'unknown.new.testing'
-RELEASES_ORDER = RELEASE_CODENAME_LOOKUP.items()
+RELEASES_ORDER = list(RELEASE_CODENAME_LOOKUP.items())
RELEASES_ORDER.sort()
-RELEASES_ORDER = list(zip(*RELEASES_ORDER)[1])
+RELEASES_ORDER = list(list(zip(*RELEASES_ORDER))[1])
RELEASES_ORDER.extend(['stable', 'testing', 'unstable', 'sid'])
def lookup_codename(release, unknown=None):
@@ -120,7 +123,11 @@ except NameError:
# This is Debian-specific at present
def check_modules_installed():
# Find which LSB modules are installed on this system
- output = commands.getoutput("dpkg-query -f '${Version} ${Provides}\n' -W %s 2>/dev/null" % PACKAGES)
+ output = subprocess.Popen(['dpkg-query','-f',"'${Version} ${Provides}\n'",'-W',PACKAGES],
+ env={'LANG': 'C'},
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True).communicate()[0].decode('ascii')
if not output:
return []
@@ -164,22 +171,21 @@ def parse_policy_line(data):
retval[longnames[k]] = v
return retval
-def compare_release(x, y):
+def release_index(x):
suite_x = x[1].get('suite')
- suite_y = y[1].get('suite')
- if suite_x and suite_y:
- if suite_x in RELEASES_ORDER and suite_y in RELEASES_ORDER:
- return RELEASES_ORDER.index(suite_y)-RELEASES_ORDER.index(suite_x)
- else:
- return cmp(suite_x, suite_y)
+ if suite_x in RELEASES_ORDER:
+ return RELEASES_ORDER.index(suite_x)
return 0
def parse_apt_policy():
data = []
- policy = commands.getoutput('LANG=C apt-cache policy 2>/dev/null')
+ policy = subprocess.Popen(['apt-cache','policy'],
+ env={'LANG': 'C'},
+ stdout=subprocess.PIPE,
+ close_fds=True).communicate()[0].decode('ascii')
for line in policy.split('\n'):
line = line.strip()
m = re.match(r'(-?\d+)', line)
@@ -213,15 +219,14 @@ def guess_release_from_apt(origin='Debian', component='main',
if not releases:
return None
- releases.sort()
- releases.reverse()
+ releases.sort(key=lambda tuple: tuple[0],reverse=True)
# We've sorted the list by descending priority, so the first entry should
# be the "main" release in use on the system
max_priority = releases[0][0]
releases = [x for x in releases if x[0] == max_priority]
- releases.sort(compare_release)
+ releases.sort(key=release_index)
return releases[0][1]
@@ -244,8 +249,8 @@ def guess_debian_release():
try:
with open('/etc/debian_version') as debian_version:
release = debian_version.read().strip()
- except IOError, msg:
- print >> sys.stderr, 'Unable to open /etc/debian_version:', str(msg)
+ except IOError as msg:
+ print('Unable to open /etc/debian_version:', str(msg), file=sys.stderr)
release = 'unknown'
if not release[0:1].isalpha():
@@ -315,8 +320,8 @@ def get_lsb_information():
arg = arg[1:-1]
if arg: # Ignore empty arguments
distinfo[var] = arg.strip()
- except IOError, msg:
- print >> sys.stderr, 'Unable to open /etc/lsb-release:', str(msg)
+ except IOError as msg:
+ print('Unable to open /etc/lsb-release:', str(msg), file=sys.stderr)
return distinfo
@@ -332,8 +337,8 @@ def get_distro_information():
return lsbinfo
def test():
- print get_distro_information()
- print check_modules_installed()
+ print(get_distro_information())
+ print(check_modules_installed())
if __name__ == '__main__':
test()
diff --git a/lsbinstall b/lsbinstall
index f007517..30ad303 100755
--- a/lsbinstall
+++ b/lsbinstall
@@ -1,10 +1,13 @@
#!/usr/bin/python
+# Python3-compatible print() function
+from __future__ import print_function
+
import sys
import os
import shutil
import socket
-import commands
+import subprocess
from tempfile import NamedTemporaryFile
from initdutils import load_lsbinstall_info, save_lsbinstall_info
@@ -19,7 +22,7 @@ objecttypes = (
)
def installed_message(objectname):
- print objectname, 'is installed'
+ print(objectname, 'is installed')
def handle_generic_install(options, args, location, showinstloc=False):
filename = args[0]
@@ -40,9 +43,9 @@ def handle_generic_install(options, args, location, showinstloc=False):
if os.path.exists(fileinfo):
try:
os.unlink(fileinfo)
- except (IOError, OSError, os.error), why:
- print >> sys.stderr, 'Removal of %s failed: %s' % (
- instloc, str(why))
+ except (IOError, OSError, os.error) as why:
+ print('Removal of %s failed: %s' % (
+ instloc, str(why)), file=sys.stderr)
sys.exit(1)
# Remove it from the database, even if it was previously removed
@@ -54,27 +57,27 @@ def handle_generic_install(options, args, location, showinstloc=False):
instloc = os.path.join(location, '%s.%s' % (options.package, basename))
if os.path.exists(instloc):
- print >> sys.stderr, 'Unable to install %s: %s exists' % (
- filename, instloc)
+ print('Unable to install %s: %s exists' % (
+ filename, instloc), file=sys.stderr)
sys.exit(1)
if not os.path.exists(location):
try:
os.makedirs(location)
- except (IOError, OSError, os.error), why:
- print >> sys.stderr, 'Unable to create %s to install %s: %s' % (
- location, filename, str(why))
+ except (IOError, OSError, os.error) as why:
+ print('Unable to create %s to install %s: %s' % (
+ location, filename, str(why)), file=sys.stderr)
sys.exit(1)
try:
shutil.copy2(filename, instloc)
- except (IOError, os.error), why:
- print >> sys.stderr, 'Installation of %s as %s failed: %s' % (
- filename, instloc, str(why))
+ except (IOError, os.error) as why:
+ print('Installation of %s as %s failed: %s' % (
+ filename, instloc, str(why)), file=sys.stderr)
sys.exit(1)
if showinstloc:
- print instloc
+ print(instloc)
filemap[(package, filename)] = instloc
save_lsbinstall_info(filemap)
@@ -91,7 +94,7 @@ def handle_service(options, args):
port, proto = pproto.split('/', 1)
port = int(port)
except:
- print >> sys.stderr, 'You must specify a port/protocol pair as the first argument.'
+ print('You must specify a port/protocol pair as the first argument.', file=sys.stderr)
sys.exit(2)
if options.check:
@@ -100,7 +103,7 @@ def handle_service(options, args):
except socket.error:
sys.exit(1)
- print '%d/%s corresponds to service %s' % (port, proto, serv)
+ print('%d/%s corresponds to service %s' % (port, proto, serv))
return
sname = args[1]
@@ -143,7 +146,7 @@ def handle_service(options, args):
laliases += [a]
elif name == lname or name in laliases:
# name shows up, but in wrong protocol/port
- print >> sys.stderr, 'Conflict between specified addition and /etc/services; aborting.'
+ print('Conflict between specified addition and /etc/services; aborting.', file=sys.stderr)
fpout.close()
os.unlink(newfname)
sys.exit(1)
@@ -157,7 +160,7 @@ def handle_service(options, args):
line = '%15s %15s %s' % lname, lpproto, endbits
line = line.rstrip()
- print >> fpout, line
+ print(line, file=fpout)
fpin.close()
fpout.close()
@@ -167,12 +170,12 @@ def handle_service(options, args):
return
fp = open('/etc/services', 'a')
- print >> fp, '%15s %15s %s # Added by lsbinstall for %s' % (
- sname, pproto, ' '.join(saliases), pkg)
+ print('%15s %15s %s # Added by lsbinstall for %s' % (
+ sname, pproto, ' '.join(saliases), pkg), file=fp)
fp.close()
def handle_inet(options, args, parser):
- cmd = 'update-inetd --group LSB '
+ cmd = ['update-inetd','--group','LSB']
alist = list(args[0].split(':'))
if len(alist) < 2:
@@ -184,7 +187,7 @@ def handle_inet(options, args, parser):
if options.remove:
parts = r'%s\s+.*\s+%s\s+.*' % (re.escape(alist[0], alist[1]))
- cmd += '--remove '+commands.mkarg(parts)
+ cmd.extend(['--remove',parts])
elif options.check:
return
else:
@@ -192,9 +195,9 @@ def handle_inet(options, args, parser):
parser.error('The operand must have six colon-separated arguments.')
return
newalist = [alist[0], alist[2], alist[1]] + alist[3:]
- cmd += '--add '+commands.mkarg('\t'.join(newalist))
+ cmd.extend(['--add','\t'.join(newalist)])
- os.system(cmd)
+ subprocess.call(cmd)
pass
def handle_man(options, args):
@@ -264,7 +267,7 @@ def main():
parser.error('Only one argument supported for %s' % options.type)
handle_man(options, args)
else:
- print >> sys.stderr, 'Unsupported type %s' % options.type
+ print('Unsupported type %s' % options.type, file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
diff --git a/remove_initd b/remove_initd
index 0322c7f..29e3dce 100755
--- a/remove_initd
+++ b/remove_initd
@@ -1,5 +1,8 @@
#!/usr/bin/python
+# Python3-compatible print() function
+from __future__ import print_function
+
import sys, re, os, initdutils
if len(sys.argv) > 1:
@@ -12,7 +15,7 @@ if len(sys.argv) > 1:
else:
initfile = os.path.join('/etc/init.d', initfile)
else:
- print >> sys.stderr, 'Usage: %s /etc/init.d/<init-script>' % sys.argv[0]
+ print('Usage: %s /etc/init.d/<init-script>' % sys.argv[0], file=sys.stderr)
sys.exit(1)
headers = initdutils.scan_initfile(initfile)
@@ -25,18 +28,18 @@ if provides:
for facility in provides:
if facility in facilities:
entries = {}
- for entry in facilities[facility].items():
+ for entry in list(facilities[facility].items()):
if entry[0] != initfile:
entries[entry[0]] = entry[1]
facilities[facility] = entries
- for (initscript, needed) in depends.iteritems():
+ for (initscript, needed) in list(depends.items()):
for facility in needed:
if facility[0] == "$":
continue
if not facilities.get(facility) and facility in provides:
- print >> sys.stderr, 'Unable to remove %s: %s needs %s\n' % (
- initfile, initscript, facility)
+ print('Unable to remove %s: %s needs %s\n' % (
+ initfile, initscript, facility), file=sys.stderr)
sys.exit(1)
if initfile in depends:
Attachment:
signature.asc
Description: OpenPGP digital signature