def test_pypy(self): sorted(Interpreter.parse('pypy').items()) == \ [('debug', None), ('name', 'pypy'), ('options', ()), ('path', ''), ('version', None)] sorted(Interpreter.parse('#! /usr/bin/pypy --foo').items()) == \ [('debug', None), ('name', 'pypy'), ('options', ('--foo',)), ('path', '/usr/bin/'), ('version', None)] Interpreter('pypy').sitedir( version='2.0') == '/usr/lib/pypy/dist-packages/'
def test_python34(self): i = Interpreter('python3.4') self.assertEqual(i.soabi(), 'cpython-34m') self.assertEqual(i.check_extname('foo.so'), r'foo.cpython-34m-MYARCH.so') self.assertIsNone(i.check_extname('foo.cpython-32m.so')) # different version self.assertIsNone(i.check_extname('foo.cpython-34m-OTHER.so')) # different architecture self.assertEqual(i.check_extname('foo.cpython-34m.so'), r'foo.cpython-34m-MYARCH.so') self.assertIsNone(i.check_extname('foo.abi3.so')) self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), r'foo/bar/baz.cpython-34m-MYARCH.so')
def test_python27dbg(self): i = Interpreter('python2.7-dbg') self.assertEqual(i.soabi(), '') self.assertEqual(i.check_extname('foo.so'), 'foo.MYARCH_d.so') self.assertEqual(i.check_extname('foo_d.so'), 'foo.MYARCH_d.so') self.assertIsNone(i.check_extname('foo.MYARCH_d.so')) self.assertIsNone( i.check_extname('foo.OTHER_d.so')) # different architecture self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), 'foo/bar/baz.MYARCH_d.so')
def fix_locations(package, interpreter, versions, options): """Move files to the right location.""" # make a copy since we change version later interpreter = Interpreter(interpreter) for version in versions: interpreter.version = version dstdir = interpreter.sitedir(package) for srcdir in interpreter.old_sitedirs(package): if isdir(srcdir): # TODO: what about relative symlinks? log.debug('moving files from %s to %s', srcdir, dstdir) share_files(srcdir, dstdir, interpreter, options) try: os.removedirs(srcdir) except OSError: pass # do the same with debug locations dstdir = interpreter.sitedir(package, gdb=True) for srcdir in interpreter.old_sitedirs(package, gdb=True): if isdir(srcdir): log.debug('moving files from %s to %s', srcdir, dstdir) share_files(srcdir, dstdir, interpreter, options) try: os.removedirs(srcdir) except OSError: pass
def test_python36(self): i = Interpreter('python3.6') self.assertEqual(i.soabi(), 'cpython-36m') self.assertEqual(i.check_extname('foo.so'), r'foo.cpython-36m-MYARCH.so') self.assertIsNone( i.check_extname('foo.cpython-32m.so')) # different version self.assertIsNone(i.check_extname( 'foo.cpython-36m-OTHER.so')) # different architecture self.assertEqual(i.check_extname('foo.cpython-36m.so'), r'foo.cpython-36m-MYARCH.so') self.assertIsNone(i.check_extname('foo.abi3.so')) self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), r'foo/bar/baz.cpython-36m-MYARCH.so')
def fix_locations(package, interpreter, versions, options): """Move files to the right location.""" # make a copy since we change version later interpreter = Interpreter(interpreter) for version in versions: interpreter.version = version dstdir = interpreter.sitedir(package) for srcdir in interpreter.old_sitedirs(package): if isdir(srcdir): # TODO: what about relative symlinks? log.debug('moving files from %s to %s', srcdir, dstdir) share_files(srcdir, dstdir, interpreter, options) parent_dir = '/'.join(srcdir.split('/')[:-1]) while parent_dir: if exists(parent_dir): if os.listdir(parent_dir): break os.rmdir(parent_dir) parent_dir = dirname(parent_dir) # do the same with debug locations dstdir = interpreter.sitedir(package, gdb=True) for srcdir in interpreter.old_sitedirs(package, gdb=True): if isdir(srcdir): log.debug('moving files from %s to %s', srcdir, dstdir) share_files(srcdir, dstdir, interpreter, options) parent_dir = '/'.join(srcdir.split('/')[:-1]) while parent_dir: if exists(parent_dir): if os.listdir(parent_dir): break os.rmdir(parent_dir) parent_dir = dirname(parent_dir)
def test_python32dbg(self): i = Interpreter('python3.2-dbg') self.assertEqual(i.soabi(), 'cpython-32dmu') self.assertEqual(i.check_extname('foo.so'), r'foo.cpython-32dmu.so') self.assertIsNone( i.check_extname('foo.cpython-33m.so')) # different version self.assertIsNone(i.check_extname( 'foo.cpython-32dmu-OTHER.so')) # different architecture self.assertIsNone(i.check_extname('foo.abi3.so')) self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), r'foo/bar/bazmodule.cpython-32dmu.so')
def get_requested_versions(impl, vrange=None, available=None): """Return a set of requested and supported Python versions. :param impl: interpreter implementation :param available: if set to `True`, return installed versions only, if set to `False`, return requested versions that are not installed. By default returns all requested versions. :type available: bool >>> sorted(get_requested_versions('cpython3', '')) == sorted(supported('cpython3')) True >>> sorted(get_requested_versions('cpython3', '-')) == sorted(supported('cpython3')) True >>> get_requested_versions('cpython3', '>= 5.0') set() """ if isinstance(vrange, str): vrange = VersionRange(vrange) if not vrange: versions = set(supported(impl)) else: minv = Version(major=0, minor=0) if vrange.minver is None else vrange.minver maxv = Version(major=99, minor=99) if vrange.maxver is None else vrange.maxver if minv == maxv: versions = set([minv] if minv in supported(impl) else tuple()) else: versions = set(v for v in supported(impl) if minv <= v < maxv) if available is not None: # to avoid circular imports global Interpreter if Interpreter is None: from dhpython.interpreter import Interpreter if available: interpreter = Interpreter(impl=impl) versions = set(v for v in versions if exists(interpreter.binary(v))) elif available is False: interpreter = Interpreter(impl=impl) versions = set(v for v in versions if not exists(interpreter.binary(v))) return versions
def test_python27dbg(self): i = Interpreter('python2.7-dbg') self.assertEqual(i.soabi(), '') self.assertEqual(i.check_extname('foo.so'), 'foo.MYARCH_d.so') self.assertEqual(i.check_extname('foo_d.so'), 'foo.MYARCH_d.so') self.assertIsNone(i.check_extname('foo.MYARCH_d.so')) self.assertIsNone(i.check_extname('foo.OTHER_d.so')) # different architecture self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), 'foo/bar/bazmodule.MYARCH_d.so')
def test_python32dbg(self): i = Interpreter('python3.2-dbg') self.assertEqual(i.soabi(), 'cpython-32dmu') self.assertEqual(i.check_extname('foo.so'), r'foo.cpython-32dmu.so') self.assertIsNone(i.check_extname('foo.cpython-33m.so')) # different version self.assertIsNone(i.check_extname('foo.cpython-32dmu-OTHER.so')) # different architecture self.assertIsNone(i.check_extname('foo.abi3.so')) self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), r'foo/bar/bazmodule.cpython-32dmu.so')
def handle_bin_dir(self, dpath, file_names): if self.options.no_shebang_rewrite or self.options.ignore_shebangs: return for fn in file_names: fpath = join(dpath, fn) if fix_shebang(fpath, self.options.shebang): try: res = Interpreter.from_file(fpath) except Exception as e: log.debug('cannot parse shebang %s: %s', fpath, e) else: self.result['shebangs'].add(res)
def test_python26dbg(self): i = Interpreter('python2.6-dbg') self.assertEqual(i.soabi(), '') self.assertIsNone(i.check_extname('foo_d.so')) self.assertEqual(i.check_extname('foo.so'), 'foo_d.so') self.assertEqual(i.check_extname('foo/bar/bazmodule.so'), 'foo/bar/bazmodule_d.so')
def __init__(self, interpreter, package, dpath=None, options=None): self.interpreter = interpreter self.impl = interpreter.impl self.package = package if not dpath: self.proot = "debian/%s" % self.package else: dpath = dpath.strip('/') self.proot = join('debian', self.package, dpath) self.dpath = dpath del dpath self.options = options self.result = {'requires.txt': set(), 'egg-info': set(), 'nsp.txt': set(), 'shebangs': set(), 'public_vers': set(), 'private_dirs': {}, 'compile': False, 'ext_vers': set(), 'ext_no_version': set()} for root, dirs, file_names in os.walk(self.proot): if interpreter.should_ignore(root): del dirs[:] continue self.current_private_dir = self.current_pub_version = None version = interpreter.parse_public_dir(root) if version: self.current_dir_is_public = True if version is True: version = None else: self.current_pub_version = version else: self.current_dir_is_public = False if self.current_dir_is_public: if root.endswith('-packages'): if version is not None: self.result['public_vers'].add(version) for name in ('test', 'tests'): if name in dirs: log.debug('removing dist-packages/%s (too common name)', name) rmtree(join(root, name)) dirs.remove(name) else: self.current_private_dir = self.check_private_dir(root) if not self.current_private_dir: # i.e. not a public dir and not a private dir is_bin_dir = self.is_bin_dir(root) if is_bin_dir: self.handle_bin_dir(root, file_names) else: # not a public, private or bin directory # continue with a subdirectory continue for name in dirs: dpath = join(root, name) if self.is_unwanted_dir(dpath): rmtree(dpath) dirs.remove(name) continue if self.is_egg_dir(root): self.handle_egg_dir(root, file_names) continue # check files for fn in sorted(file_names): # sorted() to make sure .so files are handled before .so.foo fpath = join(root, fn) if self.is_unwanted_file(fpath): log.debug('removing unwanted: %s', fpath) os.remove(fpath) continue if self.is_egg_file(fpath): self.handle_egg_file(fpath) continue if not exists(fpath): # possibly removed while handling .so symlinks if islink(fpath) and '.so.' in split(fpath)[-1]: # dangling symlink to (now removed/renamed) .so file # which wasn't removed yet (see test203's quux.so.0) log.info('removing dangling symlink: %s', fpath) os.remove(fpath) continue fext = splitext(fn)[-1][1:] if fext == 'so': if not self.options.no_ext_rename: fpath = self.rename_ext(fpath) ver = self.handle_ext(fpath) ver = ver or version if ver: self.current_result.setdefault('ext_vers', set()).add(ver) else: self.current_result.setdefault('ext_no_version', set()).add(fpath) if self.current_private_dir: if exists(fpath) and fext != 'so': mode = os.stat(fpath)[ST_MODE] if mode & S_IXUSR or mode & S_IXGRP or mode & S_IXOTH: if (options.no_shebang_rewrite or fix_shebang(fpath, self.options.shebang)) and \ not self.options.ignore_shebangs: try: res = Interpreter.from_file(fpath) except Exception as e: log.debug('cannot parse shebang %s: %s', fpath, e) else: self.current_result.setdefault('shebangs', set()).add(res) if fext == 'py' and self.handle_public_module(fpath) is not False: self.current_result['compile'] = True if not dirs: # try to remove directory if it's empty (and its parent if it's empty afterwards) while root: try: os.rmdir(root) log.debug('removing empty directory: %s', root) except Exception: break root = root.rsplit('/', 1)[0] if not root.startswith(self.proot): break log.debug("package %s details = %s", package, self.result)
def test_version(self): i = Interpreter(impl='cpython2') self.assertEqual(str(i), 'python') self.assertEqual(i.binary('2.7'), '/usr/bin/python2.7')
def test_python31dbg(self): i = Interpreter('python3.1-dbg') self.assertEqual(i.soabi(), '') self.assertIsNone(i.check_extname('foo.so')) self.assertIsNone(i.check_extname('foo.abi3.so')) self.assertIsNone(i.check_extname('foo/bar/bazmodule.so'))
def test_pypy(self): sorted(Interpreter.parse('pypy').items()) == \ [('debug', None), ('name', 'pypy'), ('options', ()), ('path', ''), ('version', None)] sorted(Interpreter.parse('#! /usr/bin/pypy --foo').items()) == \ [('debug', None), ('name', 'pypy'), ('options', ('--foo',)), ('path', '/usr/bin/'), ('version', None)] Interpreter('pypy').sitedir(version='2.0') == '/usr/lib/pypy/dist-packages/'
def __init__(self, interpreter, package, dpath=None, options=None): self.interpreter = interpreter self.impl = interpreter.impl self.package = package if not dpath: self.proot = "debian/%s" % self.package else: dpath = dpath.strip('/') self.proot = join('debian', self.package, dpath) self.dpath = dpath del dpath self.options = options self.result = { 'requires.txt': set(), 'nsp.txt': set(), 'shebangs': set(), 'public_vers': set(), 'private_dirs': {}, 'compile': False, 'ext_vers': set(), 'ext_no_version': set() } for root, dirs, file_names in os.walk(self.proot): if interpreter.should_ignore(root): del dirs[:] continue self.current_private_dir = None self.current_pub_version = version = interpreter.parse_public_version( root) if self.current_pub_version: # i.e. a public site-packages directory if root.endswith('-packages'): self.result['public_vers'].add(version) else: self.current_private_dir = self.check_private_dir(root) if not self.current_private_dir: # i.e. not a public dir and not a private dir is_bin_dir = self.is_bin_dir(root) if is_bin_dir: self.handle_bin_dir(root, file_names) else: # not a public, private or bin directory # continue with a subdirectory continue for name in dirs: dpath = join(root, name) if self.is_unwanted_dir(dpath): rmtree(dpath) dirs.remove(name) continue if self.is_egg_dir(root): self.handle_egg_dir(root, file_names) continue # check files for fn in sorted(file_names): # sorted() to make sure .so files are handled before .so.foo fpath = join(root, fn) if self.is_unwanted_file(fpath): log.debug('removing unwanted: %s', fpath) os.remove(fpath) continue if self.is_egg_file(fpath): self.handle_egg_file(fpath) continue if not exists(fpath): # possibly removed while handling .so symlinks if islink(fpath) and '.so.' in split(fpath)[-1]: # dangling symlink to (now removed/renamed) .so file # which wasn't removed yet (see test203's quux.so.0) log.info('removing dangling symlink: %s', fpath) os.remove(fpath) continue fext = splitext(fn)[-1][1:] if fext == 'so': if not self.options.no_ext_rename: fpath = self.rename_ext(fpath) ver = self.handle_ext(fpath) ver = ver or version if ver: self.current_result.setdefault('ext_vers', set()).add(ver) else: self.current_result.setdefault('ext_no_version', set()).add(fpath) if self.current_private_dir: if exists(fpath) and fext != 'so': mode = os.stat(fpath)[ST_MODE] if mode & S_IXUSR or mode & S_IXGRP or mode & S_IXOTH: if (options.no_shebang_rewrite or fix_shebang(fpath, self.options.shebang)) and \ not self.options.ignore_shebangs: try: res = Interpreter.from_file(fpath) except Exception as e: log.debug('cannot parse shebang %s: %s', fpath, e) else: self.current_result.setdefault( 'shebangs', set()).add(res) if fext == 'py' and self.handle_public_module( fpath) is not False: self.current_result['compile'] = True log.debug("package %s details = %s", package, self.result)