Fix integration tests on Windows (#4769)

This commit is contained in:
Benoit Pierre 2017-10-06 21:51:42 +02:00 committed by Paul Moore
parent 6af0a836f3
commit 961737ab98
18 changed files with 231 additions and 119 deletions

View File

@ -1,16 +1,36 @@
environment:
matrix:
# Unit and integration tests.
- PYTHON: "C:\\Python27"
- PYTHON: "C:\\Python33"
- PYTHON: "C:\\Python34"
- PYTHON: "C:\\Python35"
RUN_INTEGRATION_TESTS: "True"
- PYTHON: "C:\\Python36-x64"
RUN_INTEGRATION_TESTS: "True"
# Unit tests only.
- PYTHON: "C:\\Python27-x64"
- PYTHON: "C:\\Python33"
- PYTHON: "C:\\Python33-x64"
- PYTHON: "C:\\Python34"
- PYTHON: "C:\\Python34-x64"
- PYTHON: "C:\\Python35"
- PYTHON: "C:\\Python35-x64"
- PYTHON: "C:\\Python36"
install:
cmd: "%PYTHON%\\python.exe -m pip install tox"
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- "python --version"
- "pip install certifi tox"
# Fix git SSL errors.
- "python -m certifi >cacert.txt"
- "set /p GIT_SSL_CAINFO=<cacert.txt"
- "set GIT_SSL_CAINFO"
build: off
test_script:
- "%PYTHON%\\Scripts\\tox.exe -e py -- -m unit -n 8"
# Shorten paths, workaround https://bugs.python.org/issue18199
- "subst T: %TEMP%"
- "set TEMP=T:\\"
- "set TMP=T:\\"
- "tox -e py -- -m unit -n 3"
- "if \"%RUN_INTEGRATION_TESTS%\" == \"True\" (
tox -e py -- -m integration -n 3 --duration=5 )"

View File

@ -945,7 +945,7 @@ class InstallRequirement(object):
def get_dist(self):
"""Return a pkg_resources.Distribution built from self.egg_info_path"""
egg_info = self.egg_info_path('').rstrip('/')
egg_info = self.egg_info_path('').rstrip(os.path.sep)
base_dir = os.path.dirname(egg_info)
metadata = pkg_resources.PathMetadata(base_dir, egg_info)
dist_name = os.path.splitext(os.path.basename(egg_info))[0]

View File

@ -77,8 +77,6 @@ def isolate(tmpdir):
We use an autouse function scoped fixture because we want to ensure that
every test has it's own isolated home directory.
"""
# TODO: Ensure Windows will respect $HOME, including for the cache
# directory
# TODO: Figure out how to isolate from *system* level configuration files
# as well as user level configuration files.
@ -91,21 +89,36 @@ def isolate(tmpdir):
fake_root = os.path.join(str(tmpdir), "fake-root")
os.makedirs(fake_root)
# Set our home directory to our temporary directory, this should force all
# of our relative configuration files to be read from here instead of the
# user's actual $HOME directory.
os.environ["HOME"] = home_dir
# Isolate ourselves from XDG directories
os.environ["XDG_DATA_HOME"] = os.path.join(home_dir, ".local", "share")
os.environ["XDG_CONFIG_HOME"] = os.path.join(home_dir, ".config")
os.environ["XDG_CACHE_HOME"] = os.path.join(home_dir, ".cache")
os.environ["XDG_RUNTIME_DIR"] = os.path.join(home_dir, ".runtime")
os.environ["XDG_DATA_DIRS"] = ":".join([
os.path.join(fake_root, "usr", "local", "share"),
os.path.join(fake_root, "usr", "share"),
])
os.environ["XDG_CONFIG_DIRS"] = os.path.join(fake_root, "etc", "xdg")
if sys.platform == 'win32':
# Note: this will only take effect in subprocesses...
home_drive, home_path = os.path.splitdrive(home_dir)
os.environ.update({
'USERPROFILE': home_dir,
'HOMEDRIVE': home_drive,
'HOMEPATH': home_path,
})
for env_var, sub_path in (
('APPDATA', 'AppData/Roaming'),
('LOCALAPPDATA', 'AppData/Local'),
):
path = os.path.join(home_dir, *sub_path.split('/'))
os.environ[env_var] = path
os.makedirs(path)
else:
# Set our home directory to our temporary directory, this should force
# all of our relative configuration files to be read from here instead
# of the user's actual $HOME directory.
os.environ["HOME"] = home_dir
# Isolate ourselves from XDG directories
os.environ["XDG_DATA_HOME"] = os.path.join(home_dir, ".local", "share")
os.environ["XDG_CONFIG_HOME"] = os.path.join(home_dir, ".config")
os.environ["XDG_CACHE_HOME"] = os.path.join(home_dir, ".cache")
os.environ["XDG_RUNTIME_DIR"] = os.path.join(home_dir, ".runtime")
os.environ["XDG_DATA_DIRS"] = ":".join([
os.path.join(fake_root, "usr", "local", "share"),
os.path.join(fake_root, "usr", "share"),
])
os.environ["XDG_CONFIG_DIRS"] = os.path.join(fake_root, "etc", "xdg")
# Configure git, because without an author name/email git will complain
# and cause test failures.
@ -116,6 +129,7 @@ def isolate(tmpdir):
# We want to disable the version check from running in the tests
os.environ["PIP_DISABLE_PIP_VERSION_CHECK"] = "true"
# FIXME: Windows...
os.makedirs(os.path.join(home_dir, ".config", "git"))
with open(os.path.join(home_dir, ".config", "git", "config"), "wb") as fp:
fp.write(
@ -143,6 +157,15 @@ def virtualenv_template(tmpdir_factory):
pip_source_dir=pip_src,
relocatable=True,
)
if sys.platform == 'win32':
# Work around setuptools' easy_install.exe
# not working properly after relocation.
for exe in os.listdir(venv.bin):
if exe.startswith('easy_install'):
(venv.bin / exe).remove()
with open(venv.bin / 'easy_install.bat', 'w') as fp:
fp.write('python.exe -m easy_install %*\n')
# Rename original virtualenv directory to make sure
# it's not reused by mistake from one of the copies.
venv_template = tmpdir / "venv_template"

View File

@ -93,7 +93,7 @@ def test_download_wheel_archive(script, data):
It should download a wheel archive path
"""
wheel_filename = 'colander-0.9.9-py2.py3-none-any.whl'
wheel_path = os.path.join(data.find_links, wheel_filename)
wheel_path = '/'.join((data.find_links, wheel_filename))
result = script.pip(
'download', wheel_path,
'-d', '.', '--no-deps'
@ -107,7 +107,7 @@ def test_download_should_download_wheel_deps(script, data):
"""
wheel_filename = 'colander-0.9.9-py2.py3-none-any.whl'
dep_filename = 'translationstring-1.1.tar.gz'
wheel_path = os.path.join(data.find_links, wheel_filename)
wheel_path = '/'.join((data.find_links, wheel_filename))
result = script.pip(
'download', wheel_path,
'-d', '.', '--find-links', data.find_links, '--no-index'

View File

@ -6,7 +6,10 @@ from doctest import ELLIPSIS, OutputChecker
import pytest
from tests.lib import _create_test_package, _create_test_package_with_srcdir
from tests.lib import (
_create_test_package, _create_test_package_with_srcdir, need_bzr,
need_mercurial
)
distribute_re = re.compile('^distribute==[0-9.]+\n', re.MULTILINE)
@ -319,7 +322,7 @@ def test_freeze_git_remote(script, tmpdir):
_check_output(result.stdout, expected)
@pytest.mark.mercurial
@need_mercurial
def test_freeze_mercurial_clone(script, tmpdir):
"""
Test freezing a Mercurial clone.
@ -361,7 +364,7 @@ def test_freeze_mercurial_clone(script, tmpdir):
_check_output(result.stdout, expected)
@pytest.mark.bzr
@need_bzr
def test_freeze_bazaar_clone(script, tmpdir):
"""
Test freezing a Bazaar clone.
@ -478,7 +481,7 @@ def test_freeze_with_requirement_option_multiple(script):
simple2==1.0
""")
expected += "## The following requirements were added by pip freeze:"
expected += os.linesep + textwrap.dedent("""\
expected += '\n' + textwrap.dedent("""\
...meta==1.0...
""")
_check_output(result.stdout, expected)

View File

@ -1,3 +1,4 @@
import distutils
import glob
import os
import sys
@ -8,11 +9,11 @@ import pytest
from pip._internal import pep425tags
from pip._internal.status_codes import ERROR
from pip._internal.utils import appdirs
from pip._internal.utils.misc import rmtree
from tests.lib import (
_create_svn_repo, _create_test_package, create_test_package_with_setup,
path_to_url, pyversion, pyversion_tuple, requirements_file
need_bzr, need_mercurial, path_to_url, pyversion, pyversion_tuple,
requirements_file
)
from tests.lib.local_repos import local_checkout
from tests.lib.path import Path
@ -217,6 +218,7 @@ def test_install_editable_uninstalls_existing_from_path(script, data):
assert simple_folder in result.files_deleted, str(result.stdout)
@need_mercurial
def test_install_editable_from_hg(script, tmpdir):
"""Test cloning from Mercurial."""
pkg_path = _create_test_package(script, name='testpackage', vcs='hg')
@ -225,6 +227,7 @@ def test_install_editable_from_hg(script, tmpdir):
result.assert_installed('testpackage', with_files=['.hg'])
@need_mercurial
def test_vcs_url_final_slash_normalization(script, tmpdir):
"""
Test that presence or absence of final slash in VCS URL is normalized.
@ -235,7 +238,7 @@ def test_vcs_url_final_slash_normalization(script, tmpdir):
result.assert_installed('testpackage', with_files=['.hg'])
@pytest.mark.bzr
@need_bzr
def test_install_editable_from_bazaar(script, tmpdir):
"""Test checking out from Bazaar."""
pkg_path = _create_test_package(script, name='testpackage', vcs='bazaar')
@ -245,7 +248,7 @@ def test_install_editable_from_bazaar(script, tmpdir):
@pytest.mark.network
@pytest.mark.bzr
@need_bzr
def test_vcs_url_urlquote_normalization(script, tmpdir):
"""
Test that urlquoted characters are normalized for repo URL comparison.
@ -289,13 +292,14 @@ def test_install_relative_directory(script, data):
# Compute relative install path to FSPkg from scratch path.
full_rel_path = data.packages.join('FSPkg') - script.scratch_path
full_rel_url = (
'file:' + full_rel_path.replace(os.path.sep, '/') + '#egg=FSPkg'
)
embedded_rel_path = script.scratch_path.join(full_rel_path)
# For each relative path, install as either editable or not using either
# URLs with egg links or not.
for req_path in (full_rel_path,
'file:' + full_rel_path + '#egg=FSPkg',
embedded_rel_path):
for req_path in (full_rel_path, full_rel_url, embedded_rel_path):
# Regular install.
result = script.pip('install', req_path,
cwd=script.scratch_path)
@ -498,6 +502,7 @@ def test_install_using_install_option_and_editable(script, tmpdir):
@pytest.mark.network
@need_mercurial
def test_install_global_option_using_editable(script, tmpdir):
"""
Test using global distutils options, but in an editable installation
@ -653,12 +658,10 @@ def test_install_package_with_prefix(script, data):
'--no-binary', 'simple', '--no-index', 'simple==1.0',
)
if hasattr(sys, "pypy_version_info"):
path = script.scratch / 'prefix'
else:
path = script.scratch / 'prefix' / 'lib' / 'python{0}'.format(pyversion) # noqa
rel_prefix_path = script.scratch / 'prefix'
install_path = (
path / 'site-packages' / 'simple-1.0-py{0}.egg-info'.format(pyversion)
distutils.sysconfig.get_python_lib(prefix=rel_prefix_path) /
'simple-1.0-py{0}.egg-info'.format(pyversion)
)
assert install_path in result.files_created, str(result)
@ -673,8 +676,11 @@ def test_install_editable_with_prefix(script):
version='0.1')
"""))
site_packages = os.path.join(
'prefix', 'lib', 'python{0}'.format(pyversion), 'site-packages')
if hasattr(sys, "pypy_version_info"):
site_packages = os.path.join(
'prefix', 'lib', 'python{0}'.format(pyversion), 'site-packages')
else:
site_packages = distutils.sysconfig.get_python_lib(prefix='prefix')
# make sure target path is in PYTHONPATH
pythonpath = script.scratch_path / site_packages
@ -745,7 +751,7 @@ def test_url_req_case_mismatch_no_index(script, data):
tests/data/packages contains Upper-1.0.tar.gz and Upper-2.0.tar.gz
'requiresupper' has install_requires = ['upper']
"""
Upper = os.path.join(data.find_links, 'Upper-1.0.tar.gz')
Upper = '/'.join((data.find_links, 'Upper-1.0.tar.gz'))
result = script.pip(
'install', '--no-index', '-f', data.find_links, Upper, 'requiresupper'
)
@ -772,7 +778,7 @@ def test_url_req_case_mismatch_file_index(script, data):
set of packages as it requires a prepared index.html file and
subdirectory-per-package structure.
"""
Dinner = os.path.join(data.find_links3, 'dinner', 'Dinner-1.0.tar.gz')
Dinner = '/'.join((data.find_links3, 'dinner', 'Dinner-1.0.tar.gz'))
result = script.pip(
'install', '--index-url', data.find_links3, Dinner, 'requiredinner'
)
@ -964,6 +970,12 @@ def test_cleanup_after_failed_wheel(script, data, common_wheels):
@pytest.mark.network
def test_install_builds_wheels(script, data, common_wheels):
# We need to use a subprocess to get the right value on Windows.
res = script.run('python', '-c', (
'from pip._internal.utils import appdirs; '
'print(appdirs.user_cache_dir("pip"))'
))
wheels_cache = os.path.join(res.stdout.rstrip('\n'), 'wheels')
# NB This incidentally tests a local tree + tarball inputs
# see test_install_editable_from_git_autobuild_wheel for editable
# vcs coverage.
@ -976,9 +988,8 @@ def test_install_builds_wheels(script, data, common_wheels):
" upper-2.0 wheelbroken-0.1")
# Must have installed it all
assert expected in str(res), str(res)
root = appdirs.user_cache_dir('pip')
wheels = []
for top, dirs, files in os.walk(os.path.join(root, "wheels")):
for top, dirs, files in os.walk(wheels_cache):
wheels.extend(files)
# and built wheels for upper and wheelbroken
assert "Running setup.py bdist_wheel for upper" in str(res), str(res)
@ -1085,7 +1096,9 @@ def test_double_install(script):
"""
Test double install passing with two same version requirements
"""
result = script.pip('install', 'pip', 'pip', expect_error=False)
result = script.pip('install', 'pip', 'pip',
use_module=True,
expect_error=False)
msg = "Double requirement given: pip (already in pip, name='pip')"
assert msg not in result.stderr
@ -1115,7 +1128,7 @@ def test_install_incompatible_python_requires(script, common_wheels):
)
result = script.pip('install', pkga_path, expect_error=True)
assert ("pkga requires Python '<1.0' "
"but the running Python is ") in result.stderr
"but the running Python is ") in result.stderr, str(result)
def test_install_incompatible_python_requires_editable(script, common_wheels):
@ -1134,7 +1147,7 @@ def test_install_incompatible_python_requires_editable(script, common_wheels):
result = script.pip(
'install', '--editable=%s' % pkga_path, expect_error=True)
assert ("pkga requires Python '<1.0' "
"but the running Python is ") in result.stderr
"but the running Python is ") in result.stderr, str(result)
@pytest.mark.network

View File

@ -5,6 +5,7 @@ import pytest
from pip._internal.locations import write_delete_marker_file
from pip._internal.status_codes import PREVIOUS_BUILD_DIR_ERROR
from tests.lib import need_mercurial
from tests.lib.local_repos import local_checkout
@ -36,6 +37,7 @@ def test_no_clean_option_blocks_cleaning_after_install(script, data):
@pytest.mark.network
@need_mercurial
def test_cleanup_after_install_editable_from_hg(script, tmpdir):
"""
Test clean up after cloning from Mercurial.

View File

@ -203,16 +203,19 @@ def test_options_from_venv_config(script, virtualenv):
def test_install_no_binary_via_config_disables_cached_wheels(
script, data, common_wheels):
script.pip('install', 'wheel', '--no-index', '-f', common_wheels)
config_file = tempfile.NamedTemporaryFile(mode='wt')
script.environ['PIP_CONFIG_FILE'] = config_file.name
config_file.write(textwrap.dedent("""\
[global]
no-binary = :all:
"""))
config_file.flush()
res = script.pip(
'install', '--no-index', '-f', data.find_links,
'upper', expect_stderr=True)
config_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
try:
script.environ['PIP_CONFIG_FILE'] = config_file.name
config_file.write(textwrap.dedent("""\
[global]
no-binary = :all:
"""))
config_file.close()
res = script.pip(
'install', '--no-index', '-f', data.find_links,
'upper', expect_stderr=True)
finally:
os.unlink(config_file.name)
assert "Successfully installed upper-2.0" in str(res), str(res)
# No wheel building for upper, which was blacklisted
assert "Running setup.py bdist_wheel for upper" not in str(res), str(res)

View File

@ -70,7 +70,7 @@ def test_nonexistent_extra_warns_user_no_wheel(script, data):
assert (
"simple 3.0 does not provide the extra 'nonexistent'"
in result.stderr
)
), str(result)
def test_nonexistent_extra_warns_user_with_wheel(script, data):

View File

@ -1,3 +1,4 @@
import os
import textwrap
from pip._vendor.six.moves.urllib import parse as urllib_parse
@ -29,7 +30,7 @@ def test_find_links_requirements_file_relative_path(script, data):
--no-index
--find-links=%s
parent==0.1
""" % data.packages))
""" % data.packages.replace(os.path.sep, '/')))
result = script.pip(
'install',
'-r',

View File

@ -1,10 +1,11 @@
import os.path
import os
import textwrap
import pytest
from tests.lib import (
_create_test_package_with_subdirectory, pyversion, requirements_file
_create_test_package_with_subdirectory, path_to_url, pyversion,
requirements_file
)
from tests.lib.local_repos import local_checkout
@ -68,13 +69,13 @@ def test_relative_requirements_file(script, data):
# Compute relative install path to FSPkg from scratch path.
full_rel_path = data.packages.join('FSPkg') - script.scratch_path
full_rel_url = 'file:' + full_rel_path + '#egg=FSPkg'
embedded_rel_path = script.scratch_path.join(full_rel_path)
# For each relative path, install as either editable or not using either
# URLs with egg links or not.
for req_path in (full_rel_path,
'file:' + full_rel_path + '#egg=FSPkg',
embedded_rel_path):
for req_path in (full_rel_path, full_rel_url, embedded_rel_path):
req_path = req_path.replace(os.path.sep, '/')
# Regular install.
with requirements_file(req_path + '\n',
script.scratch_path) as reqs_file:
@ -203,7 +204,7 @@ def test_install_local_editable_with_subdirectory(script):
result = script.pip(
'install', '-e',
'%s#egg=version_subpkg&subdirectory=version_subdir' %
('git+file://%s' % version_pkg_path,)
('git+%s' % path_to_url(version_pkg_path),)
)
result.assert_installed('version-subpkg', sub_dir='version_subdir')
@ -216,7 +217,7 @@ def test_install_local_with_subdirectory(script):
result = script.pip(
'install',
'%s#egg=version_subpkg&subdirectory=version_subdir' %
('git+file://%s' % version_pkg_path,)
('git+' + path_to_url(version_pkg_path),)
)
result.assert_installed('version_subpkg.py', editable=False)
@ -228,9 +229,13 @@ def test_wheel_user_with_prefix_in_pydistutils_cfg(
# Make sure wheel is available in the virtualenv
script.pip('install', 'wheel', '--no-index', '-f', common_wheels)
virtualenv.system_site_packages = True
homedir = script.environ["HOME"]
if os.name == 'posix':
user_filename = ".pydistutils.cfg"
else:
user_filename = "pydistutils.cfg"
user_cfg = os.path.join(os.path.expanduser('~'), user_filename)
script.scratch_path.join("bin").mkdir()
with open(os.path.join(homedir, ".pydistutils.cfg"), "w") as cfg:
with open(user_cfg, "w") as cfg:
cfg.write(textwrap.dedent("""
[install]
prefix=%s""" % script.scratch_path))
@ -310,7 +315,7 @@ def test_constraints_local_install_causes_error(script, data):
def test_constraints_constrain_to_local_editable(script, data):
to_install = data.src.join("singlemodule")
script.scratch_path.join("constraints.txt").write(
"-e file://%s#egg=singlemodule" % to_install
"-e %s#egg=singlemodule" % path_to_url(to_install)
)
result = script.pip(
'install', '--no-index', '-f', data.find_links, '-c',
@ -321,7 +326,7 @@ def test_constraints_constrain_to_local_editable(script, data):
def test_constraints_constrain_to_local(script, data):
to_install = data.src.join("singlemodule")
script.scratch_path.join("constraints.txt").write(
"file://%s#egg=singlemodule" % to_install
"%s#egg=singlemodule" % path_to_url(to_install)
)
result = script.pip(
'install', '--no-index', '-f', data.find_links, '-c',
@ -331,13 +336,13 @@ def test_constraints_constrain_to_local(script, data):
def test_constrained_to_url_install_same_url(script, data):
to_install = data.src.join("singlemodule")
script.scratch_path.join("constraints.txt").write(
"file://%s#egg=singlemodule" % to_install
)
constraints = path_to_url(to_install) + "#egg=singlemodule"
script.scratch_path.join("constraints.txt").write(constraints)
result = script.pip(
'install', '--no-index', '-f', data.find_links, '-c',
script.scratch_path / 'constraints.txt', to_install)
assert 'Running setup.py install for singlemodule' in result.stdout
assert ('Running setup.py install for singlemodule'
in result.stdout), str(result)
@pytest.mark.network
@ -377,7 +382,7 @@ def test_double_install_spurious_hash_mismatch(
def test_install_with_extras_from_constraints(script, data):
to_install = data.packages.join("LocalExtras")
script.scratch_path.join("constraints.txt").write(
"file://%s#egg=LocalExtras[bar]" % to_install
"%s#egg=LocalExtras[bar]" % path_to_url(to_install)
)
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras')
@ -387,7 +392,7 @@ def test_install_with_extras_from_constraints(script, data):
def test_install_with_extras_from_install(script, data):
to_install = data.packages.join("LocalExtras")
script.scratch_path.join("constraints.txt").write(
"file://%s#egg=LocalExtras" % to_install
"%s#egg=LocalExtras" % path_to_url(to_install)
)
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]')
@ -397,7 +402,7 @@ def test_install_with_extras_from_install(script, data):
def test_install_with_extras_joined(script, data):
to_install = data.packages.join("LocalExtras")
script.scratch_path.join("constraints.txt").write(
"file://%s#egg=LocalExtras[bar]" % to_install
"%s#egg=LocalExtras[bar]" % path_to_url(to_install)
)
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]'
@ -409,7 +414,7 @@ def test_install_with_extras_joined(script, data):
def test_install_with_extras_editable_joined(script, data):
to_install = data.packages.join("LocalExtras")
script.scratch_path.join("constraints.txt").write(
"-e file://%s#egg=LocalExtras[bar]" % to_install
"-e %s#egg=LocalExtras[bar]" % path_to_url(to_install)
)
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]')

View File

@ -1,3 +1,4 @@
import distutils
import glob
import os
import sys
@ -187,11 +188,8 @@ def test_install_wheel_with_prefix(script, data):
'install', 'simple.dist==0.1', '--prefix', prefix_dir,
'--no-index', '--find-links=' + data.find_links,
)
if hasattr(sys, "pypy_version_info"):
lib = Path('scratch') / 'prefix' / 'site-packages'
else:
lib = Path('scratch') / 'prefix' / 'lib'
assert lib in result.files_created
lib = distutils.sysconfig.get_python_lib(prefix=Path('scratch') / 'prefix')
assert lib in result.files_created, str(result)
def test_install_from_wheel_installs_deps(script, data):
@ -234,7 +232,7 @@ def test_install_user_wheel(script, virtualenv, data, common_wheels):
egg_info_folder = script.user_site / 'has.script-1.0.dist-info'
assert egg_info_folder in result.files_created, str(result)
script_file = script.user_bin / 'script.py'
assert script_file in result.files_created
assert script_file in result.files_created, str(result)
def test_install_from_wheel_gen_entrypoint(script, data):

View File

@ -180,6 +180,8 @@ def test_uninstall_entry_point(script, console_scripts):
}
)
script_name = script.bin_path.join(console_scripts.split('=')[0].strip())
if sys.platform == 'win32':
script_name += '.exe'
result = script.pip('install', pkg_path)
assert script_name.exists
result = script.pip('list', '--format=json')
@ -204,6 +206,8 @@ def test_uninstall_gui_scripts(script):
entry_points={"gui_scripts": ["test_ = distutils_install", ], }
)
script_name = script.bin_path.join('test_')
if sys.platform == 'win32':
script_name += '.exe'
script.pip('install', pkg_path)
assert script_name.exists
script.pip('uninstall', pkg_name, '-y')
@ -424,8 +428,8 @@ def test_uninstall_setuptools_develop_install(script, data):
script.run('python', 'setup.py', 'install',
expect_stderr=True, cwd=pkg_path)
list_result = script.pip('list', '--format=json')
assert {"name": "FSPkg", "version": "0.1.dev0"} \
in json.loads(list_result.stdout)
assert {"name": os.path.normcase("FSPkg"), "version": "0.1.dev0"} \
in json.loads(list_result.stdout), str(list_result)
# Uninstall both develop and install
uninstall = script.pip('uninstall', 'FSPkg', '-y')
assert any(filename.endswith('.egg')

View File

@ -1,7 +1,7 @@
"""
tests specific to uninstalling --user installs
"""
from os.path import isdir, isfile
from os.path import isdir, isfile, normcase
import pytest
@ -49,8 +49,8 @@ class Tests_UninstallUserSite:
result3 = script.pip('uninstall', '-vy', 'pip-test-package')
# uninstall console is mentioning user scripts, but not global scripts
assert script.user_bin_path in result3.stdout
assert script.bin_path not in result3.stdout
assert normcase(script.user_bin_path) in result3.stdout, str(result3)
assert normcase(script.bin_path) not in result3.stdout, str(result3)
# uninstall worked
assert_all_changes(result2, result3, [script.venv / 'build', 'cache'])

View File

@ -7,7 +7,9 @@ import re
import textwrap
import site
import shutil
import subprocess
import pytest
import scripttest
import six
import virtualenv
@ -32,7 +34,9 @@ def path_to_url(path):
filepath = path.split(os.path.sep)
url = '/'.join(filepath)
if drive:
return 'file:///' + drive + url
# Note: match urllib.request.pathname2url's
# behavior: uppercase the drive letter.
return 'file:///' + drive.upper() + url
return 'file://' + url
@ -197,10 +201,11 @@ class TestPipResult(object):
)
egg_link_file = self.files_created[egg_link_path]
egg_link_contents = egg_link_file.bytes.replace(os.linesep, '\n')
# FIXME: I don't understand why there's a trailing . here
if not (egg_link_file.bytes.endswith('\n.') and
egg_link_file.bytes[:-2].endswith(pkg_dir)):
if not (egg_link_contents.endswith('\n.') and
egg_link_contents[:-2].endswith(pkg_dir)):
raise TestFailure(textwrap.dedent(u'''\
Incorrect egg_link file %r
Expected ending: %r
@ -209,7 +214,7 @@ class TestPipResult(object):
-------------------------------''' % (
egg_link_file,
pkg_dir + '\n.',
repr(egg_link_file.bytes))
repr(egg_link_contents))
))
if use_user_site:
@ -283,13 +288,20 @@ class PipTestEnvironment(scripttest.TestFileEnvironment):
self.site_packages_path = self.lib_path.join("site-packages")
self.user_base_path = self.venv_path.join("user")
self.user_bin_path = self.user_base_path.join(
self.bin_path - self.venv_path
)
self.user_site_path = self.venv_path.join(
"user",
site.USER_SITE[len(site.USER_BASE) + 1:],
)
if sys.platform == 'win32':
if sys.version_info >= (3, 5):
scripts_base = self.user_site_path.join('..').normpath
else:
scripts_base = self.user_base_path
self.user_bin_path = scripts_base.join('Scripts')
else:
self.user_bin_path = self.user_base_path.join(
self.bin_path - self.venv_path
)
# Create a Directory to use as a scratch pad
self.scratch_path = base_path.join("scratch").mkdir()
@ -308,6 +320,8 @@ class PipTestEnvironment(scripttest.TestFileEnvironment):
environ["PYTHONUSERBASE"] = self.user_base_path
# Writing bytecode can mess up updated file detection
environ["PYTHONDONTWRITEBYTECODE"] = "1"
# Make sure we get UTF-8 on output, even on Windows...
environ["PYTHONIOENCODING"] = "UTF-8"
kwargs["environ"] = environ
# Call the TestFileEnvironment __init__
@ -343,6 +357,9 @@ class PipTestEnvironment(scripttest.TestFileEnvironment):
run_from = kw.pop('run_from', None)
assert not cwd or not run_from, "Don't use run_from; it's going away"
cwd = cwd or run_from or self.cwd
if sys.platform == 'win32':
# Partial fix for ScriptTest.run using `shell=True` on Windows.
args = [str(a).replace('^', '^^').replace('&', '^&') for a in args]
return TestPipResult(
super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw),
verbose=self.verbose,
@ -358,8 +375,12 @@ class PipTestEnvironment(scripttest.TestFileEnvironment):
# Python 3.3 is deprecated and we emit a warning on it.
if pyversion_tuple[:2] == (3, 3):
kwargs['expect_stderr'] = True
return self.run("pip", *args, **kwargs)
if kwargs.pop('use_module', False):
exe = 'python'
args = ('-m', 'pip') + args
else:
exe = 'pip'
return self.run(exe, *args, **kwargs)
def pip_install_local(self, *args, **kwargs):
return self.pip(
@ -730,3 +751,25 @@ def create_basic_wheel_for_package(script, name, version, depends, extras):
script.temp_path.mkdir()
return retval
def need_executable(name, check_cmd):
def wrapper(fn):
try:
subprocess.check_output(check_cmd)
except OSError:
return pytest.mark.skip(reason='%s is not available' % name)(fn)
return fn
return wrapper
def need_bzr(fn):
return pytest.mark.bzr(need_executable(
'Bazaar', ('bzr', 'version', '--short')
)(fn))
def need_mercurial(fn):
return pytest.mark.mercurial(need_executable(
'Mercurial', ('hg', 'version')
)(fn))

View File

@ -39,7 +39,7 @@ class TestUserCacheDir:
def test_user_cache_dir_linux(self, monkeypatch):
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
monkeypatch.delenv("XDG_CACHE_HOME")
monkeypatch.delenv("XDG_CACHE_HOME", raising=False)
monkeypatch.setenv("HOME", "/home/test")
monkeypatch.setattr(sys, "platform", "linux2")
@ -58,7 +58,7 @@ class TestUserCacheDir:
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
# Verify that we are not affected by http://bugs.python.org/issue14768
monkeypatch.delenv("XDG_CACHE_HOME")
monkeypatch.delenv("XDG_CACHE_HOME", raising=False)
monkeypatch.setenv("HOME", "/")
monkeypatch.setattr(sys, "platform", "linux2")
@ -115,7 +115,7 @@ class TestSiteConfigDirs:
def test_site_config_dirs_linux(self, monkeypatch):
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
monkeypatch.delenv("XDG_CONFIG_DIRS")
monkeypatch.delenv("XDG_CONFIG_DIRS", raising=False)
monkeypatch.setattr(sys, "platform", "linux2")
assert appdirs.site_config_dirs("pip") == [
@ -194,7 +194,7 @@ class TestUserDataDir:
def test_user_data_dir_linux(self, monkeypatch):
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
monkeypatch.delenv("XDG_DATA_HOME")
monkeypatch.delenv("XDG_DATA_HOME", raising=False)
monkeypatch.setenv("HOME", "/home/test")
monkeypatch.setattr(sys, "platform", "linux2")
@ -213,7 +213,7 @@ class TestUserDataDir:
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
# Verify that we are not affected by http://bugs.python.org/issue14768
monkeypatch.delenv("XDG_DATA_HOME")
monkeypatch.delenv("XDG_DATA_HOME", raising=False)
monkeypatch.setenv("HOME", "/")
monkeypatch.setattr(sys, "platform", "linux2")
@ -276,7 +276,7 @@ class TestUserConfigDir:
def test_user_config_dir_linux(self, monkeypatch):
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
monkeypatch.delenv("XDG_CONFIG_HOME")
monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
monkeypatch.setenv("HOME", "/home/test")
monkeypatch.setattr(sys, "platform", "linux2")
@ -295,7 +295,7 @@ class TestUserConfigDir:
monkeypatch.setattr(appdirs, "WINDOWS", False)
monkeypatch.setattr(os, "path", posixpath)
# Verify that we are not affected by http://bugs.python.org/issue14768
monkeypatch.delenv("XDG_CONFIG_HOME")
monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
monkeypatch.setenv("HOME", "/")
monkeypatch.setattr(sys, "platform", "linux2")

View File

@ -385,22 +385,18 @@ class TestInstallRequirement(object):
req = InstallRequirement.from_editable(url)
assert req.link.url == url
def test_get_dist(self):
req = InstallRequirement.from_line('foo')
req.egg_info_path = Mock(return_value='/path/to/foo.egg-info')
dist = req.get_dist()
assert isinstance(dist, pkg_resources.Distribution)
assert dist.project_name == 'foo'
assert dist.location == '/path/to'
def test_get_dist_trailing_slash(self):
@pytest.mark.parametrize('path', (
'/path/to/foo.egg-info'.replace('/', os.path.sep),
# Tests issue fixed by https://github.com/pypa/pip/pull/2530
'/path/to/foo.egg-info/'.replace('/', os.path.sep),
))
def test_get_dist(self, path):
req = InstallRequirement.from_line('foo')
req.egg_info_path = Mock(return_value='/path/to/foo.egg-info/')
req.egg_info_path = Mock(return_value=path)
dist = req.get_dist()
assert isinstance(dist, pkg_resources.Distribution)
assert dist.project_name == 'foo'
assert dist.location == '/path/to'
assert dist.location == '/path/to'.replace('/', os.path.sep)
def test_markers(self):
for line in (

View File

@ -4,6 +4,7 @@ envlist =
py27, py33, py34, py35, py36, py37, pypy
[testenv]
passenv = GIT_SSL_CAINFO
setenv =
# This is required in order to get UTF-8 output inside of the subprocesses
# that our tests use.