Re: Updated dh_python to satisfy everybody
On Tue, 20 Jun 2006, Raphael Hertzog wrote:
> On Tue, 20 Jun 2006, Raphael Hertzog wrote:
> > On Mon, 19 Jun 2006, Raphael Hertzog wrote:
> > > - pyversions needs to be modified to not fail if the field
> > > XS-Python-Version is not present. He should in that case
> > > use the information of the debian/pyversions file. I will
> > > hopefully soon provide a patch for this.
> >
> > Here's a patch and the resulting pyversions script. For packages not using
> > XS-Python-Version, they can do "pyversions -r debian/pyversions" and get
> > the list of python packages to build with.
>
> I've slightly updated the patch so that if someone is doing "pyversions -r
> debian/control" and if it would fail, then it tries "debian/pyversions"
> before failing.
Okay yet another update (the last... I promise). Instead of requiring a
parameter you can now call "pyversions -r" and in that case it will check
first for the field in debian/control and then try with debian/pyversions
and if nothing is found, then it will return all the supported versions.
Updated files attached.
Matthias, this time you can safely integrate this version in the official
python package.
Cheers,
--
Raphaël Hertzog
Premier livre français sur Debian GNU/Linux :
http://www.ouaza.com/livre/admin-debian/
--- /usr/bin/pyversions 2006-06-16 15:00:46.000000000 +0200
+++ pyversions 2006-06-20 09:40:55.000000000 +0200
@@ -116,6 +116,36 @@
else:
return ['python%s' % v for v in versions]
+def version_cmp(ver1,ver2):
+ v1=[int(i) for i in ver1.split('.')]
+ v2=[int(i) for i in ver2.split('.')]
+ return cmp(v1,v2)
+
+def requested_versions_bis(vstring, version_only=False):
+ versions = []
+ py_supported_short = supported_versions(version_only=True)
+ for item in vstring.split(','):
+ v=item.split('-')
+ if len(v)>1:
+ if not v[0]:
+ v[0] = py_supported_short[0]
+ if not v[1]:
+ v[1] = py_supported_short[-1]
+ for ver in py_supported_short:
+ try:
+ if version_cmp(ver,v[0]) >= 0 and version_cmp(ver,v[1]) <= 0:
+ versions.append(ver)
+ except ValueError:
+ pass
+ else:
+ if v[0] in py_supported_short:
+ versions.append(v[0])
+ versions.sort(version_cmp)
+ if not version_only:
+ versions=['python'+i for i in versions]
+ return versions
+
+
def installed_versions(version_only=False):
import glob
supported = supported_versions()
@@ -173,7 +203,7 @@
action='store_true', dest='supported')
parser.add_option('-r', '--requested',
help='print the python versions requested by a build; the argument is either the name of a control file or the value of the XS-Python-Version attribute',
- action='store', dest='versions')
+ action='store_true', dest='requested')
parser.add_option('-i', '--installed',
help='print the installed supported python versions',
action='store_true', dest='installed')
@@ -189,13 +219,35 @@
print ' '.join(supported_versions(opts.version_only))
elif opts.installed:
print ' '.join(installed_versions(opts.version_only))
- elif opts.versions:
+ elif opts.requested:
try:
- if os.path.isfile(opts.versions):
- vs = extract_pyversion_attribute(opts.versions, 'Source')
+ if len(args) >= 1:
+ # Use parameters to find out the requested version
+ if os.path.isfile(args[0]):
+ if args[0].find("pyversions") != -1:
+ vs = file(args[0]).readline().rstrip('\n');
+ print ' '.join(requested_versions_bis(vs, opts.version_only))
+ else:
+ vs = extract_pyversion_attribute(args[0], 'Source')
+ print ' '.join(requested_versions(vs, opts.version_only))
+ else:
+ print ' '.join(requested_versions(args[0], opts.version_only))
else:
- vs = opts.versions
- print ' '.join(requested_versions(vs, opts.version_only))
+ # Check debian/control and debian/pyversions to find out
+ # requestd versions
+ done = 0
+ if os.path.isfile("debian/control"):
+ try:
+ vs = extract_pyversion_attribute("debian/control", 'Source')
+ print ' '.join(requested_versions(vs, opts.version_only))
+ done = 1
+ except:
+ pass
+ if not done and os.path.isfile("debian/pyversions"):
+ vs = file("debian/pyversions").readline().rstrip('\n');
+ print ' '.join(requested_versions_bis(vs, opts.version_only))
+ elif not done:
+ print ' '.join(supported_versions(opts.version_only))
except ValueError, msg:
print "%s: %s" % (program, msg)
sys.exit(1)
#! /usr/bin/python
import os, re, sys
try:
SetType = set
except NameError:
import sets
SetType = sets.Set
set = sets.Set
def parse_versions(vstring):
import operator
operators = { None: operator.eq, '=': operator.eq,
'>=': operator.ge, '<=': operator.le,
'<<': operator.lt
}
vinfo = {}
exact_versions = set([])
version_range = set(supported_versions(version_only=True))
relop_seen = False
for field in vstring.split(','):
field = field.strip()
if field == 'all':
vinfo['all'] = 'all'
continue
if field in ('current', 'current_ext'):
vinfo['current'] = field
continue
vinfo.setdefault('versions', set())
ve = re.compile('(>=|<=|<<|=)? *(\d\.\d)$')
m = ve.match(field)
try:
op, v = m.group(1), m.group(2)
if op in (None, '='):
exact_versions.add(v)
else:
relop_seen = True
filtop = operators[op]
version_range = [av for av in version_range if filtop(av ,v)]
except Exception:
raise ValueError, 'error parsing Python-Version attribute'
if 'versions' in vinfo:
vinfo['versions'] = exact_versions
if relop_seen:
vinfo['versions'] = exact_versions.union(version_range)
return vinfo
_supported_versions = None
def supported_versions(version_only=False):
global _supported_versions
if not _supported_versions:
if os.path.exists('/usr/share/python/debian_defaults'):
from ConfigParser import SafeConfigParser
config = SafeConfigParser()
config.readfp(file('/usr/share/python/debian_defaults'))
value = config.get('DEFAULT', 'supported-versions')
_supported_versions = [s.strip() for s in value.split(',')]
else:
cmd = ['/usr/bin/apt-cache', '--no-all-versions',
'show', 'python-all']
try:
import subprocess
p = subprocess.Popen(cmd, bufsize=1,
shell=False, stdout=subprocess.PIPE)
fd = p.stdout
except ImportError:
fd = os.popen(' '.join(cmd))
depends = None
for line in fd:
if line.startswith('Depends:'):
depends = line.split(':', 1)[1].strip().split(',')
fd.close()
depends = [re.sub(r'\s*(\S+)[ (]?.*', r'\1', s) for s in depends]
_supported_versions = depends
if version_only:
return [v[6:] for v in _supported_versions]
else:
return _supported_versions
_default_version = None
def default_version(version_only=False):
global _default_version
if not _default_version:
_default_version = link = os.readlink('/usr/bin/python')
if version_only:
return _default_version[6:]
else:
return _default_version
def requested_versions(vstring, version_only=False):
versions = None
vinfo = parse_versions(vstring)
supported = supported_versions(version_only=True)
if len(vinfo) == 1:
if 'all' in vinfo:
versions = supported
elif 'current' in vinfo:
versions = [default_version(version_only=True)]
else:
versions = vinfo['versions'].intersection(supported)
elif 'all' in vinfo and 'current' in vinfo:
raise ValueError, "both `current' and `all' in version string"
elif 'all' in vinfo:
versions = versions = vinfo['versions'].intersection(supported)
elif 'current' in vinfo:
current = default_version(version_only=True)
if not current in vinfo['versions']:
raise ValueError, "`current' version not in supported versions"
versions = [current]
else:
raise ValueError, 'error in version string'
if not versions:
raise ValueError, 'empty set of versions'
if version_only:
return versions
else:
return ['python%s' % v for v in versions]
def version_cmp(ver1,ver2):
v1=[int(i) for i in ver1.split('.')]
v2=[int(i) for i in ver2.split('.')]
return cmp(v1,v2)
def requested_versions_bis(vstring, version_only=False):
versions = []
py_supported_short = supported_versions(version_only=True)
for item in vstring.split(','):
v=item.split('-')
if len(v)>1:
if not v[0]:
v[0] = py_supported_short[0]
if not v[1]:
v[1] = py_supported_short[-1]
for ver in py_supported_short:
try:
if version_cmp(ver,v[0]) >= 0 and version_cmp(ver,v[1]) <= 0:
versions.append(ver)
except ValueError:
pass
else:
if v[0] in py_supported_short:
versions.append(v[0])
versions.sort(version_cmp)
if not version_only:
versions=['python'+i for i in versions]
return versions
def installed_versions(version_only=False):
import glob
supported = supported_versions()
versions = [os.path.basename(s)
for s in glob.glob('/usr/bin/python[0-9].[0-9]')
if os.path.basename(s) in supported]
versions.sort()
if version_only:
return [v[6:] for v in versions]
else:
return versions
def extract_pyversion_attribute(fn, pkg):
"""read the debian/control file, extract the XS-Python-Version
field; check that XB-Python-Version exists for the package."""
version = None
sversion = None
section = None
for line in file(fn):
line = line.strip()
if line == '':
section = None
elif line.startswith('Source:'):
section = 'Source'
elif line.startswith('Package: ' + pkg):
section = self.name
elif line.startswith('XS-Python-Version:'):
if section != 'Source':
raise ValueError, \
'attribute XS-Python-Version not in Source section'
sversion = line.split(':', 1)[1].strip()
elif line.startswith('XB-Python-Version:'):
if section == pkg:
version = line.split(':', 1)[1].strip()
if pkg == 'Source':
if sversion == None:
raise ValueError, 'missing XS-Python-Version in control file'
return sversion
if version == None:
raise ValueError, \
'missing XB-Python-Version for package `%s' % pkg
return version
def main():
from optparse import OptionParser
usage = '[-v] [-h] [-d|--default] [-s|--supported] [-i|--installed] [-r|--requested <version string>|<control file>]'
parser = OptionParser(usage=usage)
parser.add_option('-d', '--default',
help='print the default python version',
action='store_true', dest='default')
parser.add_option('-s', '--supported',
help='print the supported python versions',
action='store_true', dest='supported')
parser.add_option('-r', '--requested',
help='print the python versions requested by a build; the argument is either the name of a control file or the value of the XS-Python-Version attribute',
action='store_true', dest='requested')
parser.add_option('-i', '--installed',
help='print the installed supported python versions',
action='store_true', dest='installed')
parser.add_option('-v', '--version',
help='print just the version number(s)',
default=False, action='store_true', dest='version_only')
opts, args = parser.parse_args()
program = os.path.basename(sys.argv[0])
if opts.default:
print default_version(opts.version_only)
elif opts.supported:
print ' '.join(supported_versions(opts.version_only))
elif opts.installed:
print ' '.join(installed_versions(opts.version_only))
elif opts.requested:
try:
if len(args) >= 1:
# Use parameters to find out the requested version
if os.path.isfile(args[0]):
if args[0].find("pyversions") != -1:
vs = file(args[0]).readline().rstrip('\n');
print ' '.join(requested_versions_bis(vs, opts.version_only))
else:
vs = extract_pyversion_attribute(args[0], 'Source')
print ' '.join(requested_versions(vs, opts.version_only))
else:
print ' '.join(requested_versions(args[0], opts.version_only))
else:
# Check debian/control and debian/pyversions to find out
# requestd versions
done = 0
if os.path.isfile("debian/control"):
try:
vs = extract_pyversion_attribute("debian/control", 'Source')
print ' '.join(requested_versions(vs, opts.version_only))
done = 1
except:
pass
if not done and os.path.isfile("debian/pyversions"):
vs = file("debian/pyversions").readline().rstrip('\n');
print ' '.join(requested_versions_bis(vs, opts.version_only))
elif not done:
print ' '.join(supported_versions(opts.version_only))
except ValueError, msg:
print "%s: %s" % (program, msg)
sys.exit(1)
else:
print "usage: %s %s" % (program, usage)
sys.exit(1)
if __name__ == '__main__':
main()
Reply to: