def pipe_output(read, write): from os import environ environ = environ.copy() from subprocess import Popen vupdate = Popen( ('venv-update', 'venv=', '--version'), env=environ, stdout=write, close_fds=True, ) from os import close from testing.capture_subprocess import read_all close(write) result = read_all(read) vupdate.wait() result = result.decode('US-ASCII') print(result) uncolored = uncolor(result) assert uncolored.startswith('> ') # FIXME: Sometimes this is 'python -m', sometimes 'python2.7 -m'. Weird. import virtualenv assert uncolored.endswith(''' > virtualenv --version %s ''' % virtualenv.__version__) return result, uncolored
def test_conflicting_reqs(tmpdir): tmpdir.chdir() T.requirements(''' dependant_package conflicting_package ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) assert err == ( "conflicting-package 1 has requirement many-versions-package<2, but you'll " 'have many-versions-package 3 which is incompatible.\n' # TODO: do we still need to append our own error? 'Error: version conflict: many-versions-package 3 (venv/{}) ' '<-> many-versions-package<2 ' '(from conflicting_package->-r requirements.txt (line 3))\n'.format( PYTHON_LIB, )) out = T.uncolor(out) assert_something_went_wrong(out) assert_venv_marked_invalid(tmpdir.join('venv'))
def it_gives_the_same_python_version_as_we_started_with(tmpdir): other_python = OtherPython() with tmpdir.as_cwd(): requirements('') # first simulate some unrelated use of venv-update # this guards against statefulness in the venv-update scratch dir venv_update('unrelated_venv', '--', '--version') run('virtualenv', '--python', other_python.interpreter, 'venv') initial_version = assert_python_version(other_python.version_prefix) venv_update_symlink_pwd() out, err = run('./venv/bin/python', 'venv_update.py') assert err == '' out = uncolor(out) assert out.startswith('''\ > virtualenv Keeping valid virtualenv from previous run. > venv/bin/python -m pip.__main__ install pip-faster==%s ''' % __version__) final_version = assert_python_version(other_python.version_prefix) assert final_version == initial_version
def test_override_requirements_file(tmpdir): tmpdir.chdir() enable_coverage() requirements('') Path('.').ensure_dir('requirements.d').join('venv-update.txt').write('''\ venv-update==%s pure_python_package ''' % __version__) out, err = venv_update() err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert ( '\n> pip install --find-links=file://%s/home/.cache/pip-faster/wheelhouse -r requirements.d/venv-update.txt\n' % tmpdir ) in out assert ( '\nSuccessfully installed pip-1.5.6 pure-python-package-0.2.0 venv-update-%s' % __version__ ) in out assert '\n Successfully uninstalled pure-python-package\n' in out expected = '\n'.join(( 'venv-update==%s' % __version__, 'wheel==0.29.0', '' )) assert pip_freeze() == expected
def test_multiple_issues(tmpdir): # Make it a bit worse. The output should show all three issues. tmpdir.chdir() T.requirements('flake8==2.2.5') T.venv_update() T.run('./virtualenv_run/bin/pip', 'uninstall', '--yes', 'pyflakes') T.requirements(''' # flake8 2.2.5 requires mccabe>=0.2.1 and pep8>=1.5.7, so this isn't satisfiable flake8==2.2.5 mccabe==0.2 pep8==1.0 ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) assert err == '' out = T.uncolor(out) assert ''' Cleaning up... Error: version conflict: mccabe 0.2 <-> mccabe>=0.2.1 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Error: version conflict: pep8 1.0 <-> pep8>=1.5.7 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Error: unmet dependency: pyflakes>=0.8.1 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Something went wrong! Sending 'virtualenv_run' back in time, so make knows it's invalid. ''' in out
def test_circular_dependencies(): """pip-faster should be able to install packages with circular dependencies.""" venv = make_venv() out, err = run( venv.join('bin/pip-faster').strpath, 'install', '-vv', # show debug logging 'circular-dep-a', ) err = strip_pip_warnings(err) assert err.strip() == ( 'Circular dependency! circular-dep-a==1.0 ' '(from circular-dep-b==1.0->circular-dep-a)' ) out = uncolor(out) assert ''' tracing: circular-dep-a already queued: circular-dep-b==1.0 (from circular-dep-a) tracing: circular-dep-b==1.0 (from circular-dep-a) ''' in out frozen_requirements = pip_freeze(str(venv)).split('\n') assert 'circular-dep-a==1.0' in frozen_requirements assert 'circular-dep-b==1.0' in frozen_requirements
def test_update_while_active(tmpdir): tmpdir.chdir() enable_coverage() requirements('') venv_update() assert 'project-with-c' not in pip_freeze() # An arbitrary small package: project_with_c requirements('project_with_c') venv_update_symlink_pwd() out, err = run( 'sh', '-c', '. venv/bin/activate && python venv_update.py venv= venv --python=venv/bin/python' ) out = uncolor(out) err = strip_pip_warnings(err) assert err == '' assert out.startswith('''\ > virtualenv venv --python=venv/bin/python Keeping valid virtualenv from previous run. ''') assert 'project-with-c' in pip_freeze()
def test_override_requirements_file(tmpdir): tmpdir.chdir() requirements('') Path('.').ensure_dir('requirements.d').join('venv-update.txt').write('''\ pip-faster==%s pure_python_package ''' % __version__) out, err = venv_update() err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert ' '.join(( '\n> venv/bin/python -m pip.__main__ install', '-r requirements.d/venv-update.txt\n', )) in out expected = ('\nSuccessfully installed pip-1.5.6 pip-faster-%s pure-python-package-0.2.0 virtualenv-1.11.6' % __version__) assert expected in out assert '\n Successfully uninstalled pure-python-package\n' in out expected = '\n'.join(( 'pip-faster==%s' % __version__, 'virtualenv==1.11.6', 'wheel==0.29.0', '' )) assert pip_freeze() == expected
def test_cant_wheel_package(tmpdir): with tmpdir.as_cwd(): enable_coverage(tmpdir) requirements('cant-wheel-package\npure-python-package') out, err = venv_update() assert err == '' out = uncolor(out) # for unknown reasons, py27 has an extra line with four spaces in this output, where py26 does not. out = out.replace('\n \n', '\n') assert ''' ---------------------------------------- Failed building wheel for cant-wheel-package Running setup.py bdist_wheel for pure-python-package Destination directory: %s/home/.cache/pip-faster/wheelhouse''' % tmpdir + ''' SLOW!! no wheel found after building (couldn't be wheeled?): cant-wheel-package (from -r requirements.txt (line 1)) Installing collected packages: cant-wheel-package, pure-python-package Running setup.py install for cant-wheel-package Could not find .egg-info directory in install record for cant-wheel-package (from -r requirements.txt (line 1)) Successfully installed cant-wheel-package pure-python-package Cleaning up... > pip uninstall --yes coverage coverage-enable-subprocess ''' in out # noqa assert pip_freeze().startswith('cant-wheel-package==0.1.0\n')
def test_override_requirements_file(tmpdir): tmpdir.chdir() enable_coverage() requirements('') Path('.').join('requirements-bootstrap.txt').write('''\ venv-update==%s pure_python_package ''' % __version__) out, err = venv_update( 'bootstrap-deps=', '-r', 'requirements-bootstrap.txt', ) err = strip_pip_warnings(err) # pip>=10 doesn't complain about installing an empty requirements file. assert err == '' out = uncolor(out) # installing venv-update may downgrade / upgrade pip out = re.sub(' pip-[0-9.]+ ', ' ', out) assert '\n> pip install -r requirements-bootstrap.txt\n' in out assert ( '\nSuccessfully installed pure-python-package-0.2.1 venv-update-%s' % __version__ ) in out assert '\n Successfully uninstalled pure-python-package-0.2.1\n' in out expected = '\n'.join(( 'venv-update==' + __version__, '' )) assert pip_freeze() == expected
def pipe_output(read, write): from os import environ environ = environ.copy() environ['HOME'] = str(Path('.').realpath()) from subprocess import Popen vupdate = Popen( ('venv-update', '--version'), env=environ, stdout=write, close_fds=True, ) from os import close from testing.capture_subprocess import read_all close(write) result = read_all(read) vupdate.wait() result = result.decode('US-ASCII') uncolored = uncolor(result) assert uncolored.startswith('> ') # FIXME: Sometimes this is 'python -m', sometimes 'python2.7 -m'. Weird. assert uncolored.endswith('''\ -m virtualenv virtualenv_run --version 1.11.6 ''') return result, uncolored
def test_conflicting_reqs(tmpdir): tmpdir.chdir() T.requirements(''' # flake8 2.2.5 requires mccabe>=0.2.1, so this isn't satisfiable flake8==2.2.5 mccabe==0.2 ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) assert err == '' out = T.uncolor(out) assert ( ''' Cleaning up... Error: version conflict: mccabe 0.2 (virtualenv_run/%s)''' ''' <-> mccabe>=0.2.1 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Something went wrong! Sending 'virtualenv_run' back in time, so make knows it's invalid. ''' % PYTHON_LIB ) in out
def test_circular_dependencies(tmpdir): """pip-faster should be able to install packages with circular dependencies.""" tmpdir.chdir() venv = enable_coverage(tmpdir, 'venv') pip = venv.join('bin/pip').strpath run(pip, 'install', 'pip-faster==' + __version__) out, err = run( venv.join('bin/pip-faster').strpath, 'install', '-vv', # show debug logging 'circular-dep-a', ) assert err == '' out = uncolor(out) assert out.endswith(''' tracing: circular-dep-a adding sub-requirement circular-dep-b==1.0 (from circular-dep-a) tracing: circular-dep-b==1.0 (from circular-dep-a) adding sub-requirement circular-dep-a==1.0 (from circular-dep-b==1.0->circular-dep-a) already analyzed: circular-dep-b==1.0 (from circular-dep-a) tracing: circular-dep-a==1.0 (from circular-dep-b==1.0->circular-dep-a) Circular dependency! circular-dep-a==1.0 (from circular-dep-b==1.0->circular-dep-a) ''') frozen_requirements = pip_freeze(str(venv)).split('\n') assert 'circular-dep-a==1.0' in frozen_requirements assert 'circular-dep-b==1.0' in frozen_requirements
def it_gives_the_same_python_version_as_we_started_with(tmpdir): other_python = OtherPython() with tmpdir.as_cwd(): requirements('') # first simulate some unrelated use of venv-update # this guards against statefulness in the venv-update scratch dir venv_update('venv=', 'unrelated_venv', 'pip-command=', 'true') run('virtualenv', '--python', other_python.interpreter, 'venv') initial_version = assert_python_version(other_python.version_prefix) venv_update_symlink_pwd() out, err = run('./venv/bin/python', 'venv_update.py') err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out.startswith('''\ > virtualenv venv Keeping valid virtualenv from previous run. > rm -rf venv/local > pip install venv-update=={} '''.format(__version__)) final_version = assert_python_version(other_python.version_prefix) assert final_version == initial_version
def test_override_requirements_file(tmpdir): tmpdir.chdir() enable_coverage() requirements('') Path('.').join('requirements-bootstrap.txt').write('''\ venv-update==%s pure_python_package ''' % __version__) out, err = venv_update( 'bootstrap-deps=', '-r', 'requirements-bootstrap.txt', ) err = strip_pip_warnings(err) assert err == ('You must give at least one requirement to install ' '(see "pip help install")\n') out = uncolor(out) assert '\n> pip install -r requirements-bootstrap.txt\n' in out assert ( '\nSuccessfully installed pure-python-package-0.2.1 venv-update-%s' % __version__) in out assert '\n Successfully uninstalled pure-python-package-0.2.1\n' in out expected = '\n'.join( ('appdirs==1.4.0', 'packaging==16.8', 'pip==9.0.1', 'pyparsing==2.1.10', 'setuptools==34.1.1', 'six==1.10.0', 'venv-update==' + __version__, 'wheel==0.29.0', '')) assert pip_freeze() == expected
def test_conflicting_reqs(tmpdir): tmpdir.chdir() T.requirements(''' dependant_package conflicting_package ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) assert err == '' out = T.uncolor(out) assert ( ''' Cleaning up... Error: version conflict: many-versions-package 3 (venv/%s)''' ''' <-> many-versions-package<2 (from conflicting-package->-r requirements.txt (line 3)) Storing debug log for failure in %s/home/.pip/pip.log Something went wrong! Sending 'venv' back in time, so make knows it's invalid. ''' % (PYTHON_LIB, tmpdir)) in out assert_venv_marked_invalid(tmpdir.join('venv'))
def test_conflicting_reqs(tmpdir): tmpdir.chdir() T.requirements(''' dependant_package conflicting_package ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) assert err == ( "conflicting-package 1 has requirement many-versions-package<2, but you'll " 'have many-versions-package 3 which is incompatible.\n' # TODO: do we still need to append our own error? 'Error: version conflict: many-versions-package 3 (venv/{}) ' '<-> many-versions-package<2 ' '(from conflicting_package->-r requirements.txt (line 3))\n'.format( PYTHON_LIB, ) ) out = T.uncolor(out) assert_something_went_wrong(out) assert_venv_marked_invalid(tmpdir.join('venv'))
def test_conflicting_reqs(tmpdir): tmpdir.chdir() T.requirements(''' dependant_package conflicting_package ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) assert err == '' out = T.uncolor(out) assert ( ''' Cleaning up... Error: version conflict: many-versions-package 3 (venv/%s)''' ''' <-> many-versions-package<2 (from conflicting-package->-r requirements.txt (line 3)) Storing debug log for failure in %s/home/.pip/pip.log Something went wrong! Sending 'venv' back in time, so make knows it's invalid. ''' % (PYTHON_LIB, tmpdir) ) in out assert_venv_marked_invalid(tmpdir.join('venv'))
def test_args_backward(tmpdir): tmpdir.chdir() enable_coverage() requirements('') with pytest.raises(CalledProcessError) as excinfo: venv_update('venv=', 'requirements.txt') # py26 doesn't have a consistent exit code: # http://bugs.python.org/issue15033 assert excinfo.value.returncode != 0 out, err = excinfo.value.result err = strip_coverage_warnings(err) err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out.rsplit('\n', 4)[-4:] == [ '> virtualenv requirements.txt', 'ERROR: File already exists and is not a directory.', 'Please provide a different path or delete the file.', '', ] assert Path('requirements.txt').isfile() assert Path('requirements.txt').read() == '' assert not Path('myvenv').exists()
def test_override_requirements_file(tmpdir): tmpdir.chdir() enable_coverage() requirements('') Path('.').join('requirements-bootstrap.txt').write('''\ venv-update==%s pure_python_package ''' % __version__) out, err = venv_update( 'bootstrap-deps=', '-r', 'requirements-bootstrap.txt', ) err = strip_pip_warnings(err) # pip>=10 doesn't complain about installing an empty requirements file. assert err == '' out = uncolor(out) assert '\n> pip install -r requirements-bootstrap.txt\n' in out assert ( '\nSuccessfully installed pure-python-package-0.2.1 venv-update-%s' % __version__ ) in out assert '\n Successfully uninstalled pure-python-package-0.2.1\n' in out expected = '\n'.join(( 'venv-update==' + __version__, '' )) assert pip_freeze() == expected
def it_can_handle_a_bad_findlink(tmpdir): venv = tmpdir.join('venv') install_coverage(venv) pip = venv.join('bin/pip').strpath run(pip, 'install', 'venv-update==' + __version__) out, err = run( str(venv.join('bin/pip-faster')), 'install', '-vvv', '--find-links', 'git+wat://not/a/thing', 'pure-python-package', ) out = uncolor(out) err = strip_pip_warnings(err) expected = '''\ Successfully built pure-python-package Installing collected packages: pure-python-package ''' assert expected in out # Between this there's: # 'changing mode of .../venv/bin/pure-python-script to 775' # but that depends on umask _, rest = out.split(expected) expected2 = '''\ Successfully installed pure-python-package-0.2.1 Cleaning up... ''' assert expected2 in rest assert err == ( " Url 'git+wat://not/a/thing' is ignored. " 'It is either a non-existing path or lacks a specific scheme.\n' ) assert 'pure-python-package==0.2.1' in pip_freeze(str(venv)).split('\n')
def test_update_invalidated_while_active(tmpdir): tmpdir.chdir() enable_coverage() requirements('') venv_update() assert 'project-with-c' not in pip_freeze() # An arbitrary small package: project_with_c requirements('project-with-c') venv_update_symlink_pwd() out, err = run( 'sh', '-c', '. venv/bin/activate && python venv_update.py venv= --system-site-packages venv' ) err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out.startswith('''\ > virtualenv --system-site-packages venv Removing invalidated virtualenv. (system-site-packages changed, to True) ''') assert 'project-with-c' in pip_freeze()
def test_multiple_issues(tmpdir): # Make it a bit worse. The output should show all three issues. tmpdir.chdir() T.requirements('flake8==2.2.5') T.venv_update() T.run('./virtualenv_run/bin/pip', 'uninstall', '--yes', 'pyflakes') T.requirements(''' # flake8 2.2.5 requires mccabe>=0.2.1 and pep8>=1.5.7, so this isn't satisfiable flake8==2.2.5 mccabe==0.2 pep8==1.0 ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) assert err == '' out = T.uncolor(out) assert ( ''' Cleaning up... Error: version conflict: mccabe 0.2 (virtualenv_run/%s)''' ''' <-> mccabe>=0.2.1 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Error: version conflict: pep8 1.0 (virtualenv_run/%s) ''' '''<-> pep8>=1.5.7 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Error: unmet dependency: pyflakes>=0.8.1 (from flake8==2.2.5 (from -r requirements.txt (line 3))) Something went wrong! Sending 'virtualenv_run' back in time, so make knows it's invalid. ''' % (PYTHON_LIB, PYTHON_LIB) ) in out
def test_circular_dependencies(): """pip-faster should be able to install packages with circular dependencies.""" venv = make_venv() out, err = run( venv.join('bin/pip-faster').strpath, 'install', '-vv', # show debug logging 'circular-dep-a', ) err = strip_pip_warnings(err) assert err == ( 'Circular dependency! circular-dep-a==1.0 ' '(from circular-dep-b==1.0->circular-dep-a)\n' ) out = uncolor(out) assert out.endswith(''' tracing: circular-dep-a already queued: circular-dep-b==1.0 (from circular-dep-a) tracing: circular-dep-b==1.0 (from circular-dep-a) ''') frozen_requirements = pip_freeze(str(venv)).split('\n') assert 'circular-dep-a==1.0' in frozen_requirements assert 'circular-dep-b==1.0' in frozen_requirements
def it_can_handle_a_bad_findlink(tmpdir): venv = tmpdir.join('venv') install_coverage(venv) pip = venv.join('bin/pip').strpath run(pip, 'install', 'venv-update==' + __version__) out, err = run( str(venv.join('bin/pip-faster')), 'install', '-vvv', '--find-links', 'git+wat://not/a/thing', 'pure-python-package', ) out = uncolor(out) err = strip_pip_warnings(err) expected = '''\ Successfully built pure-python-package Installing collected packages: pure-python-package ''' assert expected in out # Between this there's: # 'changing mode of .../venv/bin/pure-python-script to 775' # but that depends on umask _, rest = out.split(expected) expected2 = '''\ Successfully installed pure-python-package-0.2.1 Cleaning up... ''' assert expected2 in rest assert "Url 'git+wat://not/a/thing' is ignored." in err assert 'pure-python-package==0.2.1' in pip_freeze(str(venv)).split('\n')
def test_cant_wheel_package(tmpdir): with tmpdir.as_cwd(): enable_coverage() install_coverage() requirements('cant-wheel-package\npure-python-package') out, err = venv_update() err = strip_pip_warnings(err) assert err == '' out = uncolor(out) # for unknown reasons, py27 has an extra line with four spaces in this output, where py26 does not. out = out.replace('\n \n', '\n') assert ''' ---------------------------------------- Failed building wheel for cant-wheel-package Running setup.py bdist_wheel for pure-python-package Destination directory: %s/home/.cache/pip-faster/wheelhouse''' % tmpdir + ''' SLOW!! no wheel found after building (couldn't be wheeled?): cant-wheel-package==0.1.0 Installing collected packages: cant-wheel-package, pure-python-package Running setup.py install for cant-wheel-package Could not find .egg-info directory in install record for cant-wheel-package (from -r requirements.txt (line 1)) Successfully installed cant-wheel-package pure-python-package Cleaning up... ''' in out # noqa assert pip_freeze().startswith('cant-wheel-package==0.1.0\n')
def test_editable_egg_conflict(tmpdir): conflicting_package = tmpdir / 'tmp/conflicting_package' many_versions_package_2 = tmpdir / 'tmp/many_versions_package_2' from shutil import copytree copytree( str(T.TOP / 'tests/testing/packages/conflicting_package'), str(conflicting_package), ) copytree( str(T.TOP / 'tests/testing/packages/many_versions_package_2'), str(many_versions_package_2), ) with many_versions_package_2.as_cwd(): from sys import executable as python T.run(python, 'setup.py', 'bdist_egg', '--dist-dir', str(conflicting_package)) with tmpdir.as_cwd(): T.requirements('-r %s/requirements.d/coverage.txt' % T.TOP) T.venv_update() T.requirements('-e %s' % conflicting_package) with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) assert err == '' out = T.uncolor(out) expected = '\nSuccessfully installed many-versions-package conflicting-package\n' assert expected in out rest = out.rsplit(expected, 1)[-1] if True: # :pragma:nocover:pylint:disable=using-constant-test # Debian de-vendorizes the version of pip it ships try: from sysconfig import get_python_version except ImportError: # <= python2.6 from distutils.sysconfig import get_python_version assert ( '''\ Cleaning up... Error: version conflict: many-versions-package 2 (tmp/conflicting_package/many_versions_package-2-py{0}.egg)''' ''' <-> many-versions-package<2 (from conflicting-package==1->-r requirements.txt (line 1)) Storing debug log for failure in {1}/home/.pip/pip.log Something went wrong! Sending 'venv' back in time, so make knows it's invalid. '''.format(get_python_version(), tmpdir) ) == rest assert_venv_marked_invalid(tmpdir.join('venv'))
def test_editable_egg_conflict(tmpdir): conflicting_package = tmpdir / 'tmp/conflicting_package' many_versions_package_2 = tmpdir / 'tmp/many_versions_package_2' from shutil import copytree copytree( str(T.TOP / 'tests/testing/packages/conflicting_package'), str(conflicting_package), ) copytree( str(T.TOP / 'tests/testing/packages/many_versions_package_2'), str(many_versions_package_2), ) with many_versions_package_2.as_cwd(): from sys import executable as python T.run(python, 'setup.py', 'bdist_egg', '--dist-dir', str(conflicting_package)) with tmpdir.as_cwd(): T.requirements('-r %s/requirements.d/coverage.txt' % T.TOP) T.venv_update() T.requirements('-e %s' % conflicting_package) with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) assert err == '' out = T.uncolor(out) expected = '\nSuccessfully installed many-versions-package conflicting-package\n' assert expected in out rest = out.rsplit(expected, 1)[-1] if True: # :pragma:nocover:pylint:disable=using-constant-test # Debian de-vendorizes the version of pip it ships try: from sysconfig import get_python_version except ImportError: # <= python2.6 from distutils.sysconfig import get_python_version assert ( '''\ Cleaning up... Error: version conflict: many-versions-package 2 (tmp/conflicting_package/many_versions_package-2-py{0}.egg)''' ''' <-> many-versions-package<2 (from conflicting-package==1->-r requirements.txt (line 1)) Storing debug log for failure in {1}/home/.pip/pip.log Something went wrong! Sending 'venv' back in time, so make knows it's invalid. '''.format(get_python_version(), tmpdir)) == rest assert_venv_marked_invalid(tmpdir.join('venv'))
def it_gives_proper_error_without_requirements(tmpdir): venv = tmpdir.join('venv') install_coverage(venv) pip = venv.join('bin/pip').strpath run(pip, 'install', 'venv-update==' + __version__) out, err = run(str(venv.join('bin/pip-faster')), 'install') out = uncolor(out) assert out.startswith('You must give at least one requirement to install') assert err == ''
def test_arguments_version(tmpdir): """Show that we can pass arguments through to virtualenv""" tmpdir.chdir() enable_coverage() # should show virtualenv version, successfully out, err = venv_update('venv=', '--version') err = strip_pip_warnings(err) assert err == '' out = uncolor(out) lines = out.splitlines() assert lines[-2] == '> virtualenv --version', repr(lines)
def test_arguments_version(tmpdir): """Show that we can pass arguments through to virtualenv""" tmpdir.chdir() # should show virtualenv version, successfully out, err = venv_update('--version') assert err == '' out = uncolor(out) lines = out.splitlines() # 13:py27 14:py35 15:pypy assert len(lines) in (13, 14, 15), repr(lines) assert lines[-2] == '> virtualenv --version', repr(lines)
def test_wrong_wheel(tmpdir): tmpdir.chdir() requirements('pure_python_package==0.1.0') venv_update('venv=', 'venv1') # A different python # Before fixing, this would install argparse using the `py2-none-any` # wheel, even on py3 other_python = OtherPython() ret2out, _ = venv_update('venv=', 'venv2', '-p' + other_python.interpreter, 'install=', '-vv', '-r', 'requirements.txt') assert ''' No wheel found locally for pinned requirement pure_python_package==0.1.0 (from -r requirements.txt (line 1)) ''' in uncolor(ret2out)
def test_wrong_wheel(tmpdir): tmpdir.chdir() requirements('pure_python_package==0.1.0') venv_update('venv1') # A different python # Before fixing, this would install argparse using the `py2-none-any` # wheel, even on py3 other_python = OtherPython() ret2out, _ = venv_update('venv2', '-p' + other_python.interpreter, '--', '-vv', '-r', 'requirements.txt') assert ''' No wheel found locally for pinned requirement pure-python-package==0.1.0 (from -r requirements.txt (line 1)) ''' in uncolor(ret2out)
def test_install_whl_over_http(pypi_server): whl_url = pypi_server + '/packages/wheeled_package-0.2.0-py2.py3-none-any.whl' venv = make_venv() out, err = run(str(venv.join('bin/pip-faster')), 'install', whl_url) err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out == '''\ Collecting wheeled-package==0.2.0 from {server}/packages/wheeled_package-0.2.0-py2.py3-none-any.whl Downloading {server}/packages/wheeled_package-0.2.0-py2.py3-none-any.whl Installing collected packages: wheeled-package Successfully installed wheeled-package-0.2.0 '''.format(server=pypi_server)
def test_install_whl_over_http(pypi_server): whl_url = pypi_server + '/packages/wheeled_package-0.2.0-py2.py3-none-any.whl' venv = make_venv() out, err = run(str(venv.join('bin/pip-faster')), 'install', whl_url) err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out == '''\ Looking in indexes: {server}/simple Collecting wheeled-package==0.2.0 from {server}/packages/wheeled_package-0.2.0-py2.py3-none-any.whl Downloading {server}/packages/wheeled_package-0.2.0-py2.py3-none-any.whl Installing collected packages: wheeled-package Successfully installed wheeled-package-0.2.0 '''.format(server=pypi_server)
def test_update_invalidated_missing_activate(tmpdir): with tmpdir.as_cwd(): enable_coverage() requirements('') venv_update() tmpdir.join('venv/bin/activate').remove() out, err = venv_update() err = strip_pip_warnings(err) assert err == "sh: 1: .: Can't open venv/bin/activate\n" out = uncolor(out) assert out.startswith('''\ > virtualenv venv Removing invalidated virtualenv. (could not inspect metadata) ''')
def test_update_while_active(tmpdir): tmpdir.chdir() requirements('virtualenv<2') venv_update() assert 'project-with-c' not in pip_freeze() # An arbitrary small package: project_with_c requirements('project_with_c') venv_update_symlink_pwd() out, err = run('sh', '-c', '. venv/bin/activate && python venv_update.py') out = uncolor(out) assert err == '' assert out.startswith('> virtualenv\nKeeping valid virtualenv from previous run.\n') assert 'project-with-c' in pip_freeze()
def test_multiple_issues(tmpdir): # Make it a bit worse. The output should show all three issues. tmpdir.chdir() T.enable_coverage() T.requirements('dependant_package\n-r %s/requirements.d/coverage.txt' % T.TOP) T.venv_update() T.run('./venv/bin/pip', 'uninstall', '--yes', 'implicit_dependency') T.requirements(''' dependant_package conflicting_package pure_python_package==0.1.0 ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) err = err.splitlines() # pip outputs conflict lines in a non-consistent order assert set(err[:3]) == { "conflicting-package 1 has requirement many-versions-package<2, but you'll have many-versions-package 3 which is incompatible.", # noqa "dependant-package 1 has requirement pure-python-package>=0.2.1, but you'll have pure-python-package 0.1.0 which is incompatible.", # noqa 'Error: version conflict: pure-python-package 0.1.0 (venv/{lib}) <-> pure-python-package>=0.2.1 (from dependant_package->-r requirements.txt (line 2))'.format( # noqa lib=PYTHON_LIB, ), } # TODO: do we still need to append our own error? assert '\n'.join(err[3:]) == ( 'Error: version conflict: many-versions-package 3 ' '(venv/{lib}) <-> many-versions-package<2 ' '(from conflicting_package->-r requirements.txt (line 3))'.format( lib=PYTHON_LIB, ) ) out = T.uncolor(out) assert_something_went_wrong(out) assert_venv_marked_invalid(tmpdir.join('venv'))
def test_multiple_issues(tmpdir): # Make it a bit worse. The output should show all three issues. tmpdir.chdir() T.enable_coverage() T.requirements('dependant_package\n-r %s/requirements.d/coverage.txt' % T.TOP) T.venv_update() T.run('./venv/bin/pip', 'uninstall', '--yes', 'implicit_dependency') T.requirements(''' dependant_package conflicting_package pure_python_package==0.1.0 ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) err = err.splitlines() # pip outputs conflict lines in a non-consistent order assert set(err[:3]) == { 'dependant-package 1 requires implicit-dependency, which is not installed.', "dependant-package 1 has requirement pure-python-package>=0.2.1, but you'll have pure-python-package 0.1.0 which is incompatible.", # noqa "conflicting-package 1 has requirement many-versions-package<2, but you'll have many-versions-package 3 which is incompatible.", # noqa } # TODO: do we still need to append our own error? assert '\n'.join(err[3:]) == ( 'Error: version conflict: pure-python-package 0.1.0 ' '(venv/{lib}) <-> pure-python-package>=0.2.1 ' '(from dependant_package->-r requirements.txt (line 2))\n' 'Error: version conflict: many-versions-package 3 ' '(venv/{lib}) <-> many-versions-package<2 ' '(from conflicting_package->-r requirements.txt (line 3))'.format( lib=PYTHON_LIB, )) out = T.uncolor(out) assert_something_went_wrong(out) assert_venv_marked_invalid(tmpdir.join('venv'))
def test_update_while_active(tmpdir): tmpdir.chdir() requirements('virtualenv<2') venv_update() assert 'project-with-c' not in pip_freeze() # An arbitrary small package: project_with_c requirements('project_with_c') venv_update_symlink_pwd() out, err = run('sh', '-c', '. venv/bin/activate && python venv_update.py') out = uncolor(out) assert err == '' assert out.startswith( '> virtualenv\nKeeping valid virtualenv from previous run.\n') assert 'project-with-c' in pip_freeze()
def test_cant_wheel_package(tmpdir): with tmpdir.as_cwd(): enable_coverage() install_coverage() requirements('cant-wheel-package\npure-python-package') out, err = venv_update() err = strip_pip_warnings(err) assert err == ' Failed building wheel for cant-wheel-package\n' out = uncolor(out) assert '''\ Installing collected packages: cant-wheel-package, pure-python-package Running setup.py install for cant-wheel-package ... done Successfully installed cant-wheel-package-0.1.0 pure-python-package-0.2.1 ''' in out # noqa assert pip_freeze().startswith('cant-wheel-package==0.1.0\n')
def test_arguments_version(tmpdir): """Show that we can pass arguments through to virtualenv""" tmpdir.chdir() from subprocess import CalledProcessError with pytest.raises(CalledProcessError) as excinfo: # should show virtualenv version, then crash venv_update('--version') assert excinfo.value.returncode == 1 out, err = excinfo.value.result lasterr = err.rsplit('\n', 2)[-2] assert lasterr.startswith('virtualenv executable not found: /'), err assert lasterr.endswith('/virtualenv_run/bin/python'), err lines = [uncolor(line) for line in out.split('\n')] assert len(lines) == 3, lines assert lines[0].endswith(' -m virtualenv virtualenv_run --version'), repr( lines[0])
def test_arguments_version(tmpdir): """Show that we can pass arguments through to virtualenv""" tmpdir.chdir() from subprocess import CalledProcessError with pytest.raises(CalledProcessError) as excinfo: # should show virtualenv version, then crash venv_update('--version') assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = strip_coverage_warnings(err) lasterr = err.rsplit('\n', 2)[-2] assert lasterr.startswith('virtualenv executable not found: /'), err assert lasterr.endswith('/virtualenv_run/bin/python'), err lines = [uncolor(line) for line in out.split('\n')] assert len(lines) == 3, lines assert lines[0].endswith(' -m virtualenv virtualenv_run --version'), repr(lines[0])
def test_editable_egg_conflict(tmpdir): conflicting_package = tmpdir / 'tmp/conflicting_package' many_versions_package_2 = tmpdir / 'tmp/many_versions_package_2' from shutil import copytree copytree( str(T.TOP / 'tests/testing/packages/conflicting_package'), str(conflicting_package), ) copytree( str(T.TOP / 'tests/testing/packages/many_versions_package_2'), str(many_versions_package_2), ) with many_versions_package_2.as_cwd(): from sys import executable as python T.run(python, 'setup.py', 'bdist_egg', '--dist-dir', str(conflicting_package)) with tmpdir.as_cwd(): T.enable_coverage() T.requirements('-e %s' % conflicting_package) with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) assert err == ( 'Error: version conflict: many-versions-package 2 ' '(tmp/conflicting_package/many_versions_package-2-py{}.egg) ' '<-> many_versions_package<2 ' '(from conflicting-package==1->-r requirements.txt (line 1))\n'.format( get_python_version(), ) ) out = T.uncolor(out) assert_something_went_wrong(out) assert_venv_marked_invalid(tmpdir.join('venv'))
def test_editable_egg_conflict(tmpdir): conflicting_package = tmpdir / 'tmp/conflicting_package' many_versions_package_2 = tmpdir / 'tmp/many_versions_package_2' from shutil import copytree copytree( str(T.TOP / 'tests/testing/packages/conflicting_package'), str(conflicting_package), ) copytree( str(T.TOP / 'tests/testing/packages/many_versions_package_2'), str(many_versions_package_2), ) with many_versions_package_2.as_cwd(): from sys import executable as python T.run(python, 'setup.py', 'bdist_egg', '--dist-dir', str(conflicting_package)) with tmpdir.as_cwd(): T.enable_coverage() T.requirements('-e %s' % conflicting_package) with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) err = T.strip_pip_warnings(err) assert err.strip() == ( 'Error: version conflict: many-versions-package 2 ' '(tmp/conflicting_package/many_versions_package-2-py{}.egg) ' '<-> many_versions_package<2 ' '(from conflicting-package==1->-r requirements.txt (line 1))'.format( get_python_version(), ) ) out = T.uncolor(out) assert_something_went_wrong(out) assert_venv_marked_invalid(tmpdir.join('venv'))
def test_cant_wheel_package(tmpdir): with tmpdir.as_cwd(): enable_coverage() install_coverage() requirements('cant-wheel-package\npure-python-package') out, err = venv_update() err = strip_pip_warnings(err) assert err == ' Failed building wheel for cant-wheel-package\n' out = uncolor(out) assert '''\ Installing collected packages: cant-wheel-package, pure-python-package Running setup.py install for cant-wheel-package ... done Successfully installed cant-wheel-package-0.1.0 pure-python-package-0.2.1 ''' in out # noqa assert pip_freeze().startswith( 'cant-wheel-package==0.1.0\n' )
def test_update_invalidated_while_active(tmpdir): tmpdir.chdir() requirements('virtualenv<2') venv_update() assert 'project-with-c' not in pip_freeze() # An arbitrary small package: project_with_c requirements('project-with-c') venv_update_symlink_pwd() out, err = run('sh', '-c', '. venv/bin/activate && python venv_update.py --system-site-packages') err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out.startswith('''\ > virtualenv --system-site-packages Removing invalidated virtualenv. ''') assert 'project-with-c' in pip_freeze()
def test_update_while_active(tmpdir): tmpdir.chdir() enable_coverage() requirements('') venv_update() assert 'project-with-c' not in pip_freeze() # An arbitrary small package: project_with_c requirements('project_with_c') venv_update_symlink_pwd() out, err = run('sh', '-c', '. venv/bin/activate && python venv_update.py venv= venv --python=venv/bin/python') out = uncolor(out) err = strip_pip_warnings(err) assert err == '' assert out.startswith('''\ > virtualenv venv --python=venv/bin/python Keeping valid virtualenv from previous run. ''') assert 'project-with-c' in pip_freeze()
def test_touch_on_error(tmpdir): from sys import executable tmpdir.chdir() requirements('') from os import mkdir mkdir('myvenv') from subprocess import CalledProcessError with pytest.raises(CalledProcessError) as excinfo: stage2(executable, tmpdir) assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = strip_coverage_warnings(err) lasterr = err.rsplit('\n', 2)[-2] assert lasterr == 'AssertionError: Executable not in venv: %s != %s/myvenv/bin/python' % (executable, tmpdir.strpath) out = uncolor(out) assert out.startswith('\nSomething went wrong! ') assert out.count('\n> touch myvenv ') == 1
def test_multiple_issues(tmpdir): # Make it a bit worse. The output should show all three issues. tmpdir.chdir() T.requirements('dependant_package\n-r %s/requirements.d/coverage.txt' % T.TOP) T.venv_update() T.run('./venv/bin/pip', 'uninstall', '--yes', 'implicit_dependency') T.requirements(''' dependant_package conflicting_package pure_python_package==0.1.0 ''') with pytest.raises(CalledProcessError) as excinfo: T.venv_update() assert excinfo.value.returncode == 1 out, err = excinfo.value.result err = T.strip_coverage_warnings(err) assert err == '' out = T.uncolor(out) assert ( ''' Cleaning up... Error: unmet dependency: implicit-dependency (from dependant-package->-r requirements.txt (line 2)) Error: version conflict: many-versions-package 1 (venv/%s)''' ''' <-> many-versions-package>=2,<4 (from dependant-package->-r requirements.txt (line 2)) Error: version conflict: pure-python-package 0.1.0 (venv/%s)''' ''' <-> pure-python-package>=0.2.0 (from dependant-package->-r requirements.txt (line 2)) Storing debug log for failure in %s/home/.pip/pip.log Something went wrong! Sending 'venv' back in time, so make knows it's invalid. ''' % (PYTHON_LIB, PYTHON_LIB, tmpdir) ) in out assert_venv_marked_invalid(tmpdir.join('venv'))
def test_args_backward(tmpdir): tmpdir.chdir() enable_coverage() requirements('') with pytest.raises(CalledProcessError) as excinfo: venv_update('venv=', 'requirements.txt') assert excinfo.value.returncode == 3 out, err = excinfo.value.result err = strip_coverage_warnings(err) err = strip_pip_warnings(err) assert err == '' out = uncolor(out) assert out.rsplit('\n', 4)[-4:] == [ '> virtualenv requirements.txt', 'ERROR: File already exists and is not a directory.', 'Please provide a different path or delete the file.', '', ] assert Path('requirements.txt').isfile() assert Path('requirements.txt').read() == '' assert not Path('myvenv').exists()