pax_global_header00006660000000000000000000000064131660171660014521gustar00rootroot0000000000000052 comment=32eafad8979eb379458ec118d27ad451599db451 .gitignore000066400000000000000000000000111316601716600130450ustar00rootroot00000000000000.* *.pyc .travis.yml000066400000000000000000000002251316601716600131750ustar00rootroot00000000000000language: python python: - "2.7" - "3.3" - "3.4" - "3.5" install: - pip install pytest virtualenv script: - py.test -v tests LICENSE000066400000000000000000000021321316601716600120700ustar00rootroot00000000000000Copyright (c) 2011, Edward George, based on code contained within the virtualenv project. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. MANIFEST.in000066400000000000000000000000371316601716600126230ustar00rootroot00000000000000include README include LICENSE README000066400000000000000000000027051316601716600117510ustar00rootroot00000000000000virtualenv cloning script. A script for cloning a non-relocatable virtualenv. Virtualenv provides a way to make virtualenv's relocatable which could then be copied as we wanted. However making a virtualenv relocatable this way breaks the no-site-packages isolation of the virtualenv as well as other aspects that come with relative paths and '/usr/bin/env' shebangs that may be undesirable. Also, the .pth and .egg-link rewriting doesn't seem to work as intended. This attempts to overcome these issues and provide a way to easily clone an existing virtualenv. It performs the following: - copies sys.argv[1] dir to sys.argv[2] - updates the hardcoded VIRTUAL_ENV variable in the activate script to the new repo location. (--relocatable doesn't touch this) - updates the shebangs of the various scripts in bin to the new python if they pointed to the old python. (version numbering is retained.) it can also change '/usr/bin/env python' shebangs to be absolute too, though this functionality is not exposed at present. - checks sys.path of the cloned virtualenv and if any of the paths are from the old environment it finds any .pth or .egg-link files within sys.path located in the new environment and makes sure any absolute paths to the old environment are updated to the new environment. - finally it double checks sys.path again and will fail if there are still paths from the old environment present. NOTE: This script requires Python >= 2.5 changelog.md000066400000000000000000000002611316601716600133350ustar00rootroot00000000000000# Changelog ## version 0.3.0 - Added support for Python 3. - Fixed a bug with writing unicode in .pth files incorrectly. - Fixed support for paths involving symbolic links. clonevirtualenv.py000066400000000000000000000251121316601716600146600ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import with_statement import logging import optparse import os import os.path import re import shutil import subprocess import sys import itertools version_info = (0, 2, 6) __version__ = '.'.join(map(str, version_info)) logger = logging.getLogger() if sys.version_info < (2, 6): next = lambda gen: gen.next() env_bin_dir = 'bin' if sys.platform == 'win32': env_bin_dir = 'Scripts' class UserError(Exception): pass def _dirmatch(path, matchwith): """Check if path is within matchwith's tree. >>> _dirmatch('/home/foo/bar', '/home/foo/bar') True >>> _dirmatch('/home/foo/bar/', '/home/foo/bar') True >>> _dirmatch('/home/foo/bar/etc', '/home/foo/bar') True >>> _dirmatch('/home/foo/bar2', '/home/foo/bar') False >>> _dirmatch('/home/foo/bar2/etc', '/home/foo/bar') False """ matchlen = len(matchwith) if (path.startswith(matchwith) and path[matchlen:matchlen + 1] in [os.sep, '']): return True return False def _virtualenv_sys(venv_path): "obtain version and path info from a virtualenv." executable = os.path.join(venv_path, env_bin_dir, 'python') # Must use "executable" as the first argument rather than as the # keyword argument "executable" to get correct value from sys.path p = subprocess.Popen([executable, '-c', 'import sys;' 'print (sys.version[:3]);' 'print ("\\n".join(sys.path));'], env={}, stdout=subprocess.PIPE) stdout, err = p.communicate() assert not p.returncode and stdout lines = stdout.decode('utf-8').splitlines() return lines[0], filter(bool, lines[1:]) def clone_virtualenv(src_dir, dst_dir): if not os.path.exists(src_dir): raise UserError('src dir %r does not exist' % src_dir) if os.path.exists(dst_dir): raise UserError('dest dir %r exists' % dst_dir) #sys_path = _virtualenv_syspath(src_dir) logger.info('cloning virtualenv \'%s\' => \'%s\'...' % (src_dir, dst_dir)) shutil.copytree(src_dir, dst_dir, symlinks=True, ignore=shutil.ignore_patterns('*.pyc')) version, sys_path = _virtualenv_sys(dst_dir) logger.info('fixing scripts in bin...') fixup_scripts(src_dir, dst_dir, version) has_old = lambda s: any(i for i in s if _dirmatch(i, src_dir)) if has_old(sys_path): # only need to fix stuff in sys.path if we have old # paths in the sys.path of new python env. right? logger.info('fixing paths in sys.path...') fixup_syspath_items(sys_path, src_dir, dst_dir) v_sys = _virtualenv_sys(dst_dir) remaining = has_old(v_sys[1]) assert not remaining, v_sys fix_symlink_if_necessary(src_dir, dst_dir) def fix_symlink_if_necessary(src_dir, dst_dir): #sometimes the source virtual environment has symlinks that point to itself #one example is $OLD_VIRTUAL_ENV/local/lib points to $OLD_VIRTUAL_ENV/lib #this function makes sure #$NEW_VIRTUAL_ENV/local/lib will point to $NEW_VIRTUAL_ENV/lib #usually this goes unnoticed unless one tries to upgrade a package though pip, so this bug is hard to find. logger.info("scanning for internal symlinks that point to the original virtual env") for dirpath, dirnames, filenames in os.walk(dst_dir): for a_file in itertools.chain(filenames, dirnames): full_file_path = os.path.join(dirpath, a_file) if os.path.islink(full_file_path): target = os.path.realpath(full_file_path) if target.startswith(src_dir): new_target = target.replace(src_dir, dst_dir) logger.debug('fixing symlink in %s' % (full_file_path,)) os.remove(full_file_path) os.symlink(new_target, full_file_path) def fixup_scripts(old_dir, new_dir, version, rewrite_env_python=False): bin_dir = os.path.join(new_dir, env_bin_dir) root, dirs, files = next(os.walk(bin_dir)) pybinre = re.compile(r'pythonw?([0-9]+(\.[0-9]+(\.[0-9]+)?)?)?$') for file_ in files: filename = os.path.join(root, file_) if file_ in ['python', 'python%s' % version, 'activate_this.py']: continue elif file_.startswith('python') and pybinre.match(file_): # ignore other possible python binaries continue elif file_.endswith('.pyc'): # ignore compiled files continue elif file_ == 'activate' or file_.startswith('activate.'): fixup_activate(os.path.join(root, file_), old_dir, new_dir) elif os.path.islink(filename): fixup_link(filename, old_dir, new_dir) elif os.path.isfile(filename): fixup_script_(root, file_, old_dir, new_dir, version, rewrite_env_python=rewrite_env_python) def fixup_script_(root, file_, old_dir, new_dir, version, rewrite_env_python=False): old_shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(old_dir)) new_shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(new_dir)) env_shebang = '#!/usr/bin/env python' filename = os.path.join(root, file_) with open(filename, 'rb') as f: if f.read(2) != b'#!': # no shebang return f.seek(0) lines = f.readlines() if not lines: # warn: empty script return def rewrite_shebang(version=None): logger.debug('fixing %s' % filename) shebang = new_shebang if version: shebang = shebang + version shebang = (shebang + '\n').encode('utf-8') with open(filename, 'wb') as f: f.write(shebang) f.writelines(lines[1:]) try: bang = lines[0].decode('utf-8').strip() except UnicodeDecodeError: # binary file return # This takes care of the scheme in which shebang is of type # '#!/venv/bin/python3' while the version of system python # is of type 3.x e.g. 3.5. short_version = bang[len(old_shebang):] if not bang.startswith('#!'): return elif bang == old_shebang: rewrite_shebang() elif (bang.startswith(old_shebang) and bang[len(old_shebang):] == version): rewrite_shebang(version) elif (bang.startswith(old_shebang) and short_version and bang[len(old_shebang):] == short_version): rewrite_shebang(short_version) elif rewrite_env_python and bang.startswith(env_shebang): if bang == env_shebang: rewrite_shebang() elif bang[len(env_shebang):] == version: rewrite_shebang(version) else: # can't do anything return def fixup_activate(filename, old_dir, new_dir): logger.debug('fixing %s' % filename) with open(filename, 'rb') as f: data = f.read().decode('utf-8') data = data.replace(old_dir, new_dir) with open(filename, 'wb') as f: f.write(data.encode('utf-8')) def fixup_link(filename, old_dir, new_dir, target=None): logger.debug('fixing %s' % filename) if target is None: target = os.readlink(filename) origdir = os.path.dirname(os.path.abspath(filename)).replace( new_dir, old_dir) if not os.path.isabs(target): target = os.path.abspath(os.path.join(origdir, target)) rellink = True else: rellink = False if _dirmatch(target, old_dir): if rellink: # keep relative links, but don't keep original in case it # traversed up out of, then back into the venv. # so, recreate a relative link from absolute. target = target[len(origdir):].lstrip(os.sep) else: target = target.replace(old_dir, new_dir, 1) # else: links outside the venv, replaced with absolute path to target. _replace_symlink(filename, target) def _replace_symlink(filename, newtarget): tmpfn = "%s.new" % filename os.symlink(newtarget, tmpfn) os.rename(tmpfn, filename) def fixup_syspath_items(syspath, old_dir, new_dir): for path in syspath: if not os.path.isdir(path): continue path = os.path.normcase(os.path.abspath(path)) if _dirmatch(path, old_dir): path = path.replace(old_dir, new_dir, 1) if not os.path.exists(path): continue elif not _dirmatch(path, new_dir): continue root, dirs, files = next(os.walk(path)) for file_ in files: filename = os.path.join(root, file_) if filename.endswith('.pth'): fixup_pth_file(filename, old_dir, new_dir) elif filename.endswith('.egg-link'): fixup_egglink_file(filename, old_dir, new_dir) def fixup_pth_file(filename, old_dir, new_dir): logger.debug('fixup_pth_file %s' % filename) with open(filename, 'r') as f: lines = f.readlines() has_change = False for num, line in enumerate(lines): line = (line.decode('utf-8') if hasattr(line, 'decode') else line).strip() if not line or line.startswith('#') or line.startswith('import '): continue elif _dirmatch(line, old_dir): lines[num] = line.replace(old_dir, new_dir, 1) has_change = True if has_change: with open(filename, 'w') as f: payload = os.linesep.join([l.strip() for l in lines]) + os.linesep f.write(payload) def fixup_egglink_file(filename, old_dir, new_dir): logger.debug('fixing %s' % filename) with open(filename, 'rb') as f: link = f.read().decode('utf-8').strip() if _dirmatch(link, old_dir): link = link.replace(old_dir, new_dir, 1) with open(filename, 'wb') as f: link = (link + '\n').encode('utf-8') f.write(link) def main(): parser = optparse.OptionParser("usage: %prog [options]" " /path/to/existing/venv /path/to/cloned/venv") parser.add_option('-v', action="count", dest='verbose', default=False, help='verbosity') options, args = parser.parse_args() try: old_dir, new_dir = args except ValueError: print("virtualenv-clone %s" % (__version__,)) parser.error("not enough arguments given.") old_dir = os.path.realpath(old_dir) new_dir = os.path.realpath(new_dir) loglevel = (logging.WARNING, logging.INFO, logging.DEBUG)[min(2, options.verbose)] logging.basicConfig(level=loglevel, format='%(message)s') try: clone_virtualenv(old_dir, new_dir) except UserError: e = sys.exc_info()[1] parser.error(str(e)) if __name__ == '__main__': main() setup.py000066400000000000000000000027141316601716600126030ustar00rootroot00000000000000import sys from setuptools.command.test import test as TestCommand from setuptools import setup if __name__ == '__main__' and sys.version_info < (2, 5): raise SystemExit("Python >= 2.5 required for virtualenv-clone") test_requirements = [ 'virtualenv', 'tox', 'pytest' ] class ToxTest(TestCommand): def finalize_options(self): TestCommand.finalize_options(self) self.test_args = [] self.test_suite = True def run_tests(self): import tox tox.cmdline() setup(name="virtualenv-clone", version='0.3.0', description='script to clone virtualenvs.', author='Edward George', author_email='edwardgeorge@gmail.com', url='http://github.com/edwardgeorge/virtualenv-clone', license="MIT", py_modules=["clonevirtualenv"], entry_points={ 'console_scripts': [ 'virtualenv-clone=clonevirtualenv:main', ]}, classifiers=[ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Intended Audience :: Developers", "Development Status :: 3 - Alpha", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", ], tests_require=test_requirements, cmdclass={'test': ToxTest} ) tests/000077500000000000000000000000001316601716600122275ustar00rootroot00000000000000tests/__init__.py000066400000000000000000000015211316601716600143370ustar00rootroot00000000000000import os import shutil import subprocess import tempfile from unittest import TestCase # Global test variables tmplocation = tempfile.mkdtemp() venv_path = os.path.realpath(os.path.join(tmplocation,'srs_venv')) clone_path = os.path.realpath(os.path.join(tmplocation,'clone_venv')) versions = ['2.7', '3.3', '3.4', '3.5'] def clean(): if os.path.exists(tmplocation): shutil.rmtree(tmplocation) class TestBase(TestCase): def setUp(self): """Clean from previous testing""" clean() """Create a virtualenv to clone""" assert subprocess.call(['virtualenv', venv_path]) == 0,\ "Error running virtualenv" # verify starting point... assert os.path.exists(venv_path), 'Virtualenv to clone does not exists' def tearDown(self): """Clean up our testing""" clean() tests/test_dirmatch.py000066400000000000000000000013751316601716600154410ustar00rootroot00000000000000from unittest import TestCase import clonevirtualenv class TestVirtualenvDirmatch(TestCase): def test_dirmatch(self): assert clonevirtualenv._dirmatch('/home/foo/bar', '/home/foo/bar') assert clonevirtualenv._dirmatch('/home/foo/bar/', '/home/foo/bar') assert clonevirtualenv._dirmatch('/home/foo/bar/etc', '/home/foo/bar') assert clonevirtualenv._dirmatch('/home/foo/bar/etc/', '/home/foo/bar') assert not clonevirtualenv._dirmatch('/home/foo/bar2', '/home/foo/bar') assert not clonevirtualenv._dirmatch('/home/foo/bar2/etc', '/home/foo/bar') assert not clonevirtualenv._dirmatch('/home/foo/bar/', '/home/foo/bar/etc') assert not clonevirtualenv._dirmatch('/home/foo/bar', '/home/foo/bar/etc') tests/test_fixup_scripts.py000066400000000000000000000153641316601716600165530ustar00rootroot00000000000000from tests import venv_path, clone_path, TestBase, tmplocation import os import clonevirtualenv import sys import time import stat """ Fixup scripts meerly just walks bin dir and calls to fixup_link, fixup_activate, fixup_script_ """ class TestFixupScripts(TestBase): def test_fixup_activate(self): file_ = os.path.join(venv_path, 'bin', 'activate') with open(file_, 'rb') as f: data = f.read().decode('utf-8') # verify initial state assert venv_path in data assert clone_path not in data assert os.path.basename(clone_path) not in data clonevirtualenv.fixup_activate(file_, venv_path, clone_path) with open(file_, 'rb') as f: data = f.read().decode('utf-8') # verify changes assert venv_path not in data assert os.path.basename(venv_path) not in data assert clone_path in data def test_fixup_abs_link(self): link = os.path.join(tmplocation, 'symlink') assert os.path.isabs(link), 'Expected abs path link for test' os.symlink('original_location', link) assert os.readlink(link) == 'original_location' clonevirtualenv._replace_symlink(link, 'new_location') assert link == os.path.join(tmplocation, 'symlink') assert os.readlink(link) == 'new_location' def test_fixup_rel_link(self): link = os.path.relpath(os.path.join(tmplocation, 'symlink')) assert not os.path.isabs(link),\ 'Expected relative path link for test' os.symlink('original_location', link) assert os.readlink(link) == 'original_location' clonevirtualenv._replace_symlink(link, 'new_location') assert link == os.path.relpath(os.path.join(tmplocation, 'symlink')) assert os.readlink(link) == 'new_location' def test_fixup_script_(self): script = '''#!%s/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'console_scripts' import sys if __name__ == '__main__': print('Testing VirtualEnv-Clone!') sys.exit()''' % venv_path # want to do this manually, # so going to call clone before the file exists # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() root = os.path.join(clone_path, 'bin') new_ = os.path.join(clone_path, 'bin', 'clonetest') # write the file straight to the cloned with open(new_, 'w') as f: f.write(script) # run fixup clonevirtualenv.fixup_script_(root, 'clonetest', venv_path, clone_path, '2.7') with open(new_, 'r') as f: data = f.read() assert venv_path not in data assert clone_path in data def test_fixup_script_no_shebang(self): '''Verify if there is no shebang nothing is altered''' script = '''%s/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'console_scripts' import sys if __name__ == '__main__': print('Testing VirtualEnv-Clone!') sys.exit()''' % venv_path # want to do this manually, # so going to call clone before the file exists # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() root = os.path.join(clone_path, 'bin') new_ = os.path.join(clone_path, 'bin', 'clonetest') # write the file straight to the cloned with open(new_, 'w') as f: f.write(script) # run fixup clonevirtualenv.fixup_script_(root, 'clonetest', venv_path, clone_path, '2.7') with open(new_, 'r') as f: data = f.read() assert venv_path in data assert clone_path not in data assert clone_path + '/bin/python2.7' not in data def test_fixup_script_version(self): '''Verify if version is updated''' script = '''#!%s/bin/python2.7 # EASY-INSTALL-ENTRY-SCRIPT: 'console_scripts' import sys if __name__ == '__main__': print('Testing VirtualEnv-Clone!') sys.exit()''' % venv_path # want to do this manually, # so going to call clone before the file exists # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() root = os.path.join(clone_path, 'bin') new_ = os.path.join(clone_path, 'bin', 'clonetest') # write the file straight to the cloned with open(new_, 'w') as f: f.write(script) # run fixup clonevirtualenv.fixup_script_(root, 'clonetest', venv_path, clone_path, '2.7') with open(new_, 'r') as f: data = f.read() assert venv_path not in data assert clone_path in data assert clone_path + '/bin/python2.7' in data def test_fixup_script_different_version(self): '''Verify if version is updated''' script = '''#!%s/bin/python2 # EASY-INSTALL-ENTRY-SCRIPT: 'console_scripts' import sys if __name__ == '__main__': print('Testing VirtualEnv-Clone!') sys.exit()''' % venv_path # want to do this manually, # so going to call clone before the file exists # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() root = os.path.join(clone_path, 'bin') new_ = os.path.join(clone_path, 'bin', 'clonetest') # write the file straight to the cloned with open(new_, 'w') as f: f.write(script) # run fixup clonevirtualenv.fixup_script_(root, 'clonetest', venv_path, clone_path, '2.7') with open(new_, 'r') as f: data = f.read() assert venv_path not in data assert clone_path in data assert clone_path + '/bin/python2' in data def test_fixup_pth_file(self): '''Prior to version 0.2.7, the method fixup_pth_file() wrongly wrote unicode files''' content = os.linesep.join(('/usr/local/bin/someFile', '/tmp/xyzzy', '/usr/local/someOtherFile', '')) pth = '/tmp/test_fixup_pth_file.pth' with open(pth, 'w') as fd: fd.write(content) # Find size of file - should be plain ASCII/UTF-8... org_stat = os.stat(pth) assert len(content) == org_stat[stat.ST_SIZE] # Now sleep for 2 seconds, then call fixup_pth_file(). This should ensure that the stat.ST_MTIME has # changed if the file has been changed/rewritten time.sleep(2) clonevirtualenv.fixup_pth_file(pth, '/usr/local', '/usr/xyzzy') new_stat = os.stat(pth) assert org_stat[stat.ST_MTIME] != new_stat[stat.ST_MTIME] # File should have changed assert org_stat[stat.ST_SIZE] == new_stat[stat.ST_SIZE] # Substituting local->xyzzy - size should be the same os.remove(pth) tests/test_virtualenv_clone.py000066400000000000000000000054641316601716600172300ustar00rootroot00000000000000import os from pytest import raises import clonevirtualenv import sys from tests import venv_path, clone_path, TestBase class TestVirtualenvClone(TestBase): def test_clone_with_no_args(self): sys.argv = ['virtualenv-clone'] with raises(SystemExit): clonevirtualenv.main() def test_clone_with_1_arg(self): sys.argv = ['virtualenv-clone', venv_path] with raises(SystemExit): clonevirtualenv.main() def test_clone_with_bad_src(self): sys.argv = ['virtualenv-clone', os.path.join('this','venv','does','not','exist'), clone_path] with raises(SystemExit): clonevirtualenv.main() def test_clone_exists(self): """Verify a cloned virtualenv exists""" # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() # verify cloned venv exists at the path specified assert os.path.exists(clone_path), 'Cloned Virtualenv does not exists' def test_clone_contents(self): """Walk the virtualenv and verify clonedenv contents""" sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() version = clonevirtualenv._virtualenv_sys(venv_path)[0] for root, dirs, files in os.walk(venv_path): clone_root = root.replace(venv_path,clone_path) for dir_ in dirs: dir_in_clone = os.path.join(clone_root,dir_) assert os.path.exists(dir_in_clone),\ 'Directory %s is missing from cloned virtualenv' % dir_ for file_ in files: if file_.endswith('.pyc') or\ file_.endswith('.exe') or\ file_.endswith('.egg') or\ file_ in ['python', 'python%s' % version]: # binarys fail reading and # compiled will be recompiled continue file_in_clone = os.path.join(clone_root,file_) assert os.path.exists(file_in_clone),\ 'File %s is missing from cloned virtualenv' % file_ if os.path.islink(file_in_clone): target = os.readlink(file_in_clone) assert venv_path != target assert venv_path not in target assert os.path.basename(venv_path) not in target continue with open(file_in_clone, 'rb') as f: lines = f.read().decode('utf-8') assert venv_path not in lines,\ 'Found source path in cloned file %s' % file_in_clone # def test_clone_egglink_file(self): # subprocess(['touch',os.path.join(venv_path,'lib','python','site-packages','mypackage.py']) tests/test_virtualenv_sys.py000066400000000000000000000053351316601716600167430ustar00rootroot00000000000000import os import subprocess from unittest import TestCase import clonevirtualenv import sys from tests import venv_path, clone_path, versions, clean def start_version_test(): ran_once = False for version in versions: # create a virtualenv if subprocess.call(['virtualenv', '-p', 'python' + version, venv_path]) != 0: continue ran_once = True yield version assert ran_once, "All versions were skipped." class TestVirtualenvSys(TestCase): def setUp(self): """Clean from previous testing""" clean() def tearDown(self): """Clean up our testing""" clean() def test_virtualenv_versions(self): """Verify version for created virtualenvs""" for version in start_version_test(): venv_version = clonevirtualenv._virtualenv_sys(venv_path)[0] assert version == venv_version, 'Expected version %s' % version # clean so next venv can be made clean() def test_virtualenv_syspath(self): """Verify syspath for created virtualenvs""" for version in start_version_test(): sys_path = clonevirtualenv._virtualenv_sys(venv_path)[1] paths = [path for path in sys_path] assert paths, "There should be path information" # clean so next venv can be made clean() def test_clone_version(self): """Verify version for cloned virtualenvs""" for version in start_version_test(): # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() clone_version = clonevirtualenv._virtualenv_sys(clone_path)[0] assert version == clone_version, 'Expected version %s' % version # clean so next venv can be made clean() def test_clone_syspath(self): """ Verify syspath for cloned virtualenvs This really is a test for fixup_syspath as well """ for version in start_version_test(): # run virtualenv-clone sys.argv = ['virtualenv-clone', venv_path, clone_path] clonevirtualenv.main() sys_path = clonevirtualenv._virtualenv_sys(clone_path)[1] paths = [path for path in sys_path] assert paths, "There should be path information" assert venv_path not in paths,\ "There is reference to the source virtualenv" for path in paths: assert os.path.basename(venv_path) not in path,\ "There is reference to the source virtualenv:\n%s" % path # clean so next venv can be made clean() tox.ini000066400000000000000000000001551316601716600124010ustar00rootroot00000000000000[tox] envlist = py27,py33,py34,py35,py36 [testenv] commands = py.test -v [] deps = pytest virtualenv