diff --git a/news/4208.bugfix b/news/4208.bugfix new file mode 100644 index 00000000000..9325da32c7f --- /dev/null +++ b/news/4208.bugfix @@ -0,0 +1,3 @@ +Fix a bug where `SETUPTOOLS_SHIM` got called incorrectly for relative path +requirements by converting relative paths to absolute paths prior to calling +the shim. diff --git a/pip/req/req_install.py b/pip/req/req_install.py index 0f935ffaf66..6c7fe4f7514 100644 --- a/pip/req/req_install.py +++ b/pip/req/req_install.py @@ -77,7 +77,10 @@ def __init__(self, req, comes_from, source_dir=None, editable=False, self.req = req self.comes_from = comes_from self.constraint = constraint - self.source_dir = source_dir + if source_dir is not None: + self.source_dir = os.path.normpath(os.path.abspath(source_dir)) + else: + self.source_dir = None self.editable = editable self._wheel_cache = wheel_cache @@ -388,7 +391,7 @@ def _correct_build_location(self): shutil.move(old_location, new_location) self._temp_build_dir = new_location self._ideal_build_dir = None - self.source_dir = new_location + self.source_dir = os.path.normpath(os.path.abspath(new_location)) self._egg_info_path = None @property diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index 700db586d40..ab22617a4e6 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -271,6 +271,41 @@ def test_install_from_local_directory(script, data): assert egg_info_folder in result.files_created, str(result) +def test_install_relative_directory(script, data): + """ + Test installing a requirement using a relative path. + """ + egg_info_file = ( + script.site_packages / 'FSPkg-0.1.dev0-py%s.egg-info' % pyversion + ) + egg_link_file = ( + script.site_packages / 'FSPkg.egg-link' + ) + package_folder = script.site_packages / 'fspkg' + + # Compute relative install path to FSPkg from scratch path. + full_rel_path = data.packages.join('FSPkg') - script.scratch_path + 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): + # Regular install. + result = script.pip('install', req_path, + cwd=script.scratch_path) + assert egg_info_file in result.files_created, str(result) + assert package_folder in result.files_created, str(result) + script.pip('uninstall', '-y', 'fspkg') + + # Editable install. + result = script.pip('install', '-e' + req_path, + cwd=script.scratch_path) + assert egg_link_file in result.files_created, str(result) + script.pip('uninstall', '-y', 'fspkg') + + def test_install_quiet(script, data): """ Test that install -q is actually quiet. diff --git a/tests/functional/test_install_reqs.py b/tests/functional/test_install_reqs.py index f3b4cfbeede..9526a3ba456 100644 --- a/tests/functional/test_install_reqs.py +++ b/tests/functional/test_install_reqs.py @@ -3,7 +3,7 @@ import pytest -from tests.lib import (pyversion, path_to_url, requirements_file, +from tests.lib import (pyversion, requirements_file, _create_test_package_with_subdirectory) from tests.lib.local_repos import local_checkout @@ -53,25 +53,43 @@ def test_schema_check_in_requirements_file(script): def test_relative_requirements_file(script, data): """ - Test installing from a requirements file with a relative path with an - egg= definition.. + Test installing from a requirements file with a relative path. For path + URLs, use an egg= definition. """ - url = path_to_url( - os.path.join(data.root, "packages", "..", "packages", "FSPkg") - ) + '#egg=FSPkg' - script.scratch_path.join("file-egg-req.txt").write(textwrap.dedent("""\ - %s - """ % url)) - result = script.pip( - 'install', '-vvv', '-r', script.scratch_path / 'file-egg-req.txt' - ) - assert ( + egg_info_file = ( script.site_packages / 'FSPkg-0.1.dev0-py%s.egg-info' % pyversion - ) in result.files_created, str(result) - assert (script.site_packages / 'fspkg') in result.files_created, ( - str(result.stdout) ) + egg_link_file = ( + script.site_packages / 'FSPkg.egg-link' + ) + package_folder = script.site_packages / 'fspkg' + + # Compute relative install path to FSPkg from scratch path. + full_rel_path = data.packages.join('FSPkg') - script.scratch_path + 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): + # Regular install. + with requirements_file(req_path + '\n', + script.scratch_path) as reqs_file: + result = script.pip('install', '-vvv', '-r', reqs_file.name, + cwd=script.scratch_path) + assert egg_info_file in result.files_created, str(result) + assert package_folder in result.files_created, str(result) + script.pip('uninstall', '-y', 'fspkg') + + # Editable install. + with requirements_file('-e ' + req_path + '\n', + script.scratch_path) as reqs_file: + result = script.pip('install', '-vvv', '-r', reqs_file.name, + cwd=script.scratch_path) + assert egg_link_file in result.files_created, str(result) + script.pip('uninstall', '-y', 'fspkg') @pytest.mark.network