Skip to content
Snippets Groups Projects
Commit 09e35ccf authored by Piotr Ożarowski's avatar Piotr Ożarowski
Browse files

dh_python2:

* ignore dh's -O option
* allow multiple -p options
* add -N option
parent d968e970
No related branches found
No related tags found
No related merge requests found
......@@ -22,7 +22,6 @@
import logging
from os import makedirs
from os.path import exists, join, dirname
from sys import exit
log = logging.getLogger('dh_python')
......@@ -30,7 +29,7 @@ log = logging.getLogger('dh_python')
class DebHelper(object):
"""Reinvents the wheel / some dh functionality (Perl is ugly ;-P)"""
def __init__(self, package=None):
def __init__(self, packages=None, no_packages=None):
self.packages = {}
self.python_version = None
source_section = True
......@@ -50,7 +49,9 @@ class DebHelper(object):
if binary_package:
if binary_package.startswith('python3'):
continue
if package and binary_package != package:
if packages and binary_package not in packages:
continue
if no_packages and binary_package in no_packages:
continue
if line.startswith('Source:'):
self.source_name = line[7:].strip()
......@@ -59,7 +60,9 @@ class DebHelper(object):
if binary_package.startswith('python3'):
log.debug('skipping Python 3.X package: %s', binary_package)
continue
if package and binary_package != package:
if packages and binary_package not in packages:
continue
if no_packages and binary_package in no_packages:
continue
self.packages[binary_package] = {'substvars': {},
'autoscripts': {},
......@@ -71,7 +74,7 @@ class DebHelper(object):
# TODO: if arch doesn't match current architecture:
#del self.packages[binary_package]
self.packages[binary_package]['arch'] = arch
log.debug('source=%s, binary packages=%s', self.source_name,\
log.debug('source=%s, binary packages=%s', self.source_name, \
self.packages.keys())
def addsubstvar(self, package, name, value):
......
......@@ -125,13 +125,13 @@ def guess_dependency(req, version):
query = "'%s-?*\.egg-info'" % name # TODO: .dist-info
if version:
query = "%s | grep '/python%s/\|/pyshared/'" %\
query = "%s | grep '/python%s/\|/pyshared/'" % \
(query, vrepr(version))
else:
query = "%s | grep '/python2\../\|/pyshared/'" % query
log.debug("invoking dpkg -S %s", query)
process = Popen("/usr/bin/dpkg -S %s" % query,\
process = Popen("/usr/bin/dpkg -S %s" % query, \
shell=True, stdout=PIPE, stderr=PIPE)
if process.wait() != 0:
log.error('Cannot find package that provides %s. '
......
......@@ -24,8 +24,7 @@ import logging
import re
from cPickle import dumps
from os import symlink
from sys import exit
from debpython.version import getver, vrepr
from debpython.version import getver
log = logging.getLogger('dh_python')
SHEBANG_RE = re.compile(r'^#!\s*/usr/bin/(?:env\s+)?(python(\d+\.\d+)?(?:-dbg)?).*')
......
......@@ -27,7 +27,7 @@ import os
import re
import sys
from filecmp import dircmp, cmpfiles
from optparse import OptionParser
from optparse import OptionParser, SUPPRESS_HELP
from os.path import isdir, islink, exists, join
from shutil import rmtree, copy as fcopy
from stat import ST_MODE, S_IXUSR, S_IXGRP, S_IXOTH
......@@ -88,7 +88,7 @@ def fix_locations(package):
log.error('files for version %s '
'found in two locations:\n %s\n %s',
ver, location, found_versions[ver])
sys.exit(2)
exit(2)
if not isdir(dstdir):
os.makedirs(dstdir)
# TODO: what about relative symlinks?
......@@ -116,27 +116,28 @@ def share(package, stats, options):
if package.endswith('-dbg'):
# nothing to share in debug packages
return
pv_2x = debsorted(i for i in stats['public_vers'] if i[0] == 2)
if len(pv_2x) > 1:
for pos, version1 in enumerate(pv_2x):
pubvers = debsorted(i for i in stats['public_vers'] if i[0] == 2)
if len(pubvers) > 1:
for pos, version1 in enumerate(pubvers):
dir1 = sitedir(version1, package)
for version2 in pv_2x[pos + 1:]:
for version2 in pubvers[pos + 1:]:
dir2 = sitedir(version2, package)
dc = dircmp(dir1, dir2)
share_2x(dir1, dir2, dc)
elif len(pv_2x) == 1:
elif len(pubvers) == 1:
# TODO: remove this once file conflicts will not be needed anymore
move_to_pyshared(sitedir(pv_2x[0], package))
move_to_pyshared(sitedir(pubvers[0], package))
for version in stats['public_ext']:
create_ext_links(sitedir(version, package))
if options.guess_versions and pv_2x:
if options.guess_versions and pubvers:
versions = get_requested_versions(options.vrange)
for version in (i for i in versions if i[0] == 2):
if version not in pv_2x:
if version not in pubvers:
log.debug('guessing files for Python %s', vrepr(version))
versions_without_ext = debsorted(set(pv_2x) - stats['public_ext'])
versions_without_ext = debsorted(set(pubvers) -\
stats['public_ext'])
if not versions_without_ext:
log.error('you most probably have to build extension '
'for python%s.', vrepr(version))
......@@ -199,9 +200,9 @@ def create_ext_links(dir1):
def share_2x(dir1, dir2, dc=None):
"""Move common files to pyshared and create symlinks in original
locations."""
debian, package, path = dir1.split('/', 2)
debian, package, path = dir2.split('/', 3)
# dir1 starts with debian/packagename/usr/lib/pythonX.Y/*-packages/
dstdir = join(debian, package, 'usr/share/pyshared/',\
dstdir = join(debian, package, 'usr/share/pyshared/', \
'/'.join(dir1.split('/')[6:]))
if not exists(dstdir):
os.makedirs(dstdir)
......@@ -408,36 +409,29 @@ def dependencies(package, stats, options):
'(%s shebang versions: %s', private_dir, versions)
exit(13)
elif len(versions) == 1: # one hardcoded version
interpreter = "python%d.%d" % versions[0]
if interpreter not in depends:
depends.append(interpreter)
depends.append("python%d.%d" % versions[0])
# TODO: if versions[0] not in requested_versions: FTBFS
else: # no hardcoded versions
dep = args = ''
elif details.get('compile', False):
# no hardcoded versions, but there's something to compile
args = ''
vr = options.vrange
if vr:
args += "-V %s" % vrange_str(vr)
if vr[0]: # minumum version specified
dep = "python (>= %s)" % vrepr(vr[0])
depends.append("python (>= %s)" % vrepr(vr[0]))
if vr[1]: # maximum version specified
dep += ", python (<< %s)" % vrepr(vr[1])
dep = dep.lstrip(', ')
if details.get('compile', False):
for pattern in options.regexpr or []:
args += " -X '%s'" % pattern.replace("'", r"\'")
rtscripts.append((private_dir, args))
depends.append("python (<< %s)" % vrepr(vr[1]))
dep = dep or 'python'
if dep not in depends:
depends.append(dep)
for pattern in options.regexpr or []:
args += " -X '%s'" % pattern.replace("'", r"\'")
rtscripts.append((private_dir, args))
if options.guess_deps:
for fn in stats['requires.txt']:
for i in parse_pydep(fn):
depends.append(i)
log.debug('D=%s; R=%s; S=%s; E=%s, RT=%s', depends, recommends,\
log.debug('D=%s; R=%s; S=%s; E=%s, RT=%s', depends, recommends, \
suggests, enhances, rtscripts)
return depends, recommends, suggests, enhances, rtscripts
......@@ -465,10 +459,8 @@ def parse_pydep(fname):
################################################################
def main():
if exists('debian/pycompat'):
sys.exit(0) # be compatible with old dh_python
usage = '%prog -p PACKAGE [-V [X.Y][-][A.B]] DIR_OR_FILE [-X REGEXPR]\n'
parser = OptionParser(usage, version='%prog 2.0~alpha1',
parser = OptionParser(usage, version='%prog 2.0~beta1',
option_class=Option)
parser.add_option('--no-guessing-versions', action='store_false',
dest='guess_versions', default=True,
......@@ -482,20 +474,24 @@ def main():
default=False, help='turn verbose mode one')
# arch=False->arch:all only, arch=True->arch:any only, None->all of them
parser.add_option('-i', '--indep', action='store_false',
dest='arch', default=None, help='Act on architecture independent packages')
dest='arch', default=None,
help='Act on architecture independent packages')
parser.add_option('-a', '--arch', action='store_true',
dest='arch', help='Act on architecture dependent packages')
parser.add_option('-q', '--quiet', action='store_false', dest='verbose',
default=True, help='be quiet')
parser.add_option('-p', '--package', dest='package',
help='specify Debian package name to be processed')
parser.add_option('-p', '--package', action='append', dest='package',
help='Act on the package named PACKAGE')
parser.add_option('-N', '--no-package', action='append', dest='no_package',
help='Do not act on the specified package')
parser.add_option('-V', type='version_range', dest='vrange',
help='specify list of supported Python versions. ' +\
'See pycompile(1) for examples')
parser.add_option('-X', '--exclude', action='append',
dest='regexpr',
parser.add_option('-X', '--exclude', action='append', dest='regexpr',
help='exclude items that match given REGEXPR. You may use this option'
'multiple times to build up a list of things to exclude.')
# ignore some debhelper options:
parser.add_option('-O', help=SUPPRESS_HELP)
(options, args) = parser.parse_args()
# regexpr option type is not used so lets check patterns here
......@@ -505,7 +501,7 @@ def main():
pattern = re.compile(pattern)
except:
log.error('regular expression is not valid: %s', pattern)
sys.exit(1)
exit(1)
if not options.vrange and exists('debian/pyversions'):
log.debug('parsing version range from debian/pyversions')
......@@ -529,7 +525,7 @@ def main():
log.debug('options: %s', options)
log.debug('args: %s', args)
dh = DebHelper(options.package)
dh = DebHelper(options.package, options.no_package)
if not options.vrange and dh.python_version:
options.vrange = parse_pycentral_vrange(dh.python_version)
......@@ -555,11 +551,11 @@ def main():
dh.add_rtupdate(package, i)
if stats['public_vers']:
dh.addsubstvar(package, 'python:Versions',\
dh.addsubstvar(package, 'python:Versions', \
', '.join(sorted(vrepr(stats['public_vers']))))
ps = package.split('-', 1)
if len(ps) > 1 and ps[0] == 'python':
dh.addsubstvar(package, 'python:Provides',\
dh.addsubstvar(package, 'python:Provides', \
', '.join("python%s-%s" % (i, ps[1])\
for i in sorted(vrepr(stats['public_vers']))))
......@@ -585,9 +581,9 @@ def main():
elif ext_for is False: # extension's version not detected
if options.vrange and '-' not in vrange_str(options.vrange):
ver = vrange_str(options.vrange)
else: # try shebang ...
ver = (list(v for i, v in details.get('shebangs', []) if v)\
or [None])[0] or DEFAULT # ... or use default one
else: # try shebang or defaukt Python version
ver = (list(v for i, v in details.get('shebangs', [])
if v) or [None])[0] or DEFAULT
args += " -V %s" % vrepr(ver)
else:
args += " -V %s" % vrepr(ext_for.pop())
......
......@@ -25,7 +25,6 @@
import logging
import optparse
import sys
from glob import glob1
from os import environ, remove, walk
from os.path import exists, isdir, isfile, join
from subprocess import Popen, PIPE
......@@ -65,7 +64,7 @@ def destroyer(): # ;-)
log.debug('removing %s', filename)
remove(filename)
counter += 1
except:
except IOError:
log.error('cannot remove %s', filename)
except GeneratorExit:
if counter:
......@@ -99,7 +98,7 @@ def get_package_files(package_name):
def main():
usage = '%prog [-p PACKAGE | DIR_OR_FILE]'
parser = optparse.OptionParser(usage, version='%prog 0.1')
parser = optparse.OptionParser(usage, version='%prog 0.9')
parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
default=False, help='turn verbose more one')
parser.add_option('-q', '--quiet', action='store_false', dest='verbose',
......
......@@ -39,7 +39,6 @@ from debpython.tools import memoize
logging.basicConfig(format='%(levelname).1s: %(module)s:%(lineno)d: '
'%(message)s')
log = logging.getLogger('pycompile')
# TODO: /usr/share/python3/foo/3.1-/bar/-3.5/baz.py
STDINS = {}
"""TODO: move it to manpage
......@@ -69,11 +68,11 @@ def get_directory_files(dname):
def get_package_files(package_name):
"""Generate *.py file names available in given package."""
process = Popen("/usr/bin/dpkg -L %s" % package_name, shell=True,\
process = Popen("/usr/bin/dpkg -L %s" % package_name, shell=True, \
stdout=PIPE, stderr=PIPE)
if process.wait() != 0:
log.error('cannot get content of %s', package_name)
sys.exit(2)
exit(2)
for line in process.stdout:
line = line.strip('\n')
if line.endswith('.py'):
......@@ -163,55 +162,36 @@ def py_compile(version):
if not isinstance(version, basestring):
version = vrepr(version)
cmd = "python%s -m py_compile -" % version
#if pyr_mode:
# cmd += ' -R'
stdin = Popen(cmd, bufsize=1, shell=True, stdin=PIPE).stdin
while True:
filename = (yield)
stdin.write(filename + '\n')
def compile(files, versions, pyr_mode=False, e_patterns=None):
def compile(files, versions, e_patterns=None):
global STDINS
# start Python interpreters that will handle byte compilation
for version in versions:
if (version, pyr_mode) not in STDINS:
if version not in STDINS:
coroutine = py_compile(version)
coroutine.next()
STDINS[(version, pyr_mode)] = coroutine
STDINS[version] = coroutine
skip_dirs = set()
# byte compile files
for fn, versions_to_compile in filter_files(files, e_patterns, versions):
if not pyr_mode and exists("%sc" % fn):
if exists("%sc" % fn):
continue
elif pyr_mode:
pycache_dir = join(dirname(fn), '__pycache__')
if pycache_dir not in skip_dirs and not exists(pycache_dir):
try:
mkdir(pycache_dir)
except Exception, e:
log.error("cannot create directory %s: %r", pycache_dir, e)
skip_dirs.add(pycache_dir)
continue
for version in versions_to_compile:
pipe = STDINS[(version, pyr_mode)]
pipe = STDINS[version]
pipe.send(fn)
################################################################
def doctest(*args, **kwargs):
import doctest
sys.exit(doctest.testmod())
def main():
usage = '%prog [-V [X.Y][-][A.B]] DIR_OR_FILE [-X REGEXPR]\n' + \
' %prog -p PACKAGE'
parser = optparse.OptionParser(usage, version='%prog 0.1',
parser = optparse.OptionParser(usage, version='%prog 0.9',
option_class=Option)
parser.add_option('--doctest', action='callback', callback=doctest,
help=optparse.SUPPRESS_HELP)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
default=False, help='turn verbose more one')
parser.add_option('-q', '--quiet', action='store_false', dest='verbose',
......@@ -230,8 +210,6 @@ newer), '2.5-2.7' (version 2.5 or 2.6), '-3.0' (all supported 2.X versions)""")
dest='regexpr', type='regexpr',
help='exclude items that match given REGEXPR. You may use this option \
multiple times to build up a list of things to exclude.')
parser.add_option('-R', action='store_true', default=False,
dest='pyr_mode', help='PEP 3147 mode')
(options, args) = parser.parse_args()
......@@ -251,19 +229,16 @@ multiple times to build up a list of things to exclude.')
versions = get_requested_versions(options.vrange, available=True)
if not versions:
log.error('Requested versions are not installed')
sys.exit(3)
exit(3)
if options.package and args: # package's private directories
# get requested Python version
if not options.pyr_mode:
compile_versions = debsorted(versions)[:1]
else:
compile_versions = versions
compile_versions = debsorted(versions)[:1]
log.debug('compile versions: %s', versions)
pkg_files = tuple(get_package_files(options.package))
for item in args:
e_patterns = get_exclude_patterns(item, options.regexpr,\
e_patterns = get_exclude_patterns(item, options.regexpr, \
compile_versions)
if not exists(item):
log.warn('No such file or directory: %s', item)
......@@ -271,25 +246,23 @@ multiple times to build up a list of things to exclude.')
log.debug('byte compiling %s using Python %s',
item, compile_versions)
files = get_private_files(pkg_files, item)
compile(files, compile_versions, options.pyr_mode, e_patterns)
compile(files, compile_versions, e_patterns)
elif options.package: # package's public modules
# no need to limit versions here, it's either pyr mode or version is
# hardcoded in path / via -V option
e_patterns = get_exclude_patterns()
files = get_package_files(options.package)
files = get_public_files(files, versions)
compile(files, versions, options.pyr_mode, e_patterns)
compile(files, versions, e_patterns)
elif args: # other directories/files (public ones mostly)
if not options.pyr_mode:
versions = debsorted(versions)[:1]
versions = debsorted(versions)[:1]
for item in args:
e_patterns = get_exclude_patterns(item, options.regexpr, versions)
files = get_directory_files(item)
compile(files, versions, options.pyr_mode, e_patterns)
compile(files, versions, e_patterns)
else:
parser.print_usage()
sys.exit(1)
exit(1)
if __name__ == '__main__':
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment