diff --git a/pip/commands/install.py b/pip/commands/install.py index 227c5264a0d..2cb3f756f3a 100644 --- a/pip/commands/install.py +++ b/pip/commands/install.py @@ -256,6 +256,16 @@ def run(self, options, args): temp_target_dir = None if options.target_dir: + if options.prefix_path: + raise CommandError( + "Can not combine '--target' and '--prefix' as they imply " + "different installation locations" + ) + if options.use_user_site: + raise CommandError( + "Can not combine '--target' and '--user' as they imply " + "different installation locations" + ) options.ignore_installed = True temp_target_dir = tempfile.mkdtemp() options.target_dir = os.path.abspath(options.target_dir) @@ -266,6 +276,7 @@ def run(self, options, args): "continue." ) install_options.append('--home=' + temp_target_dir) + install_options.append('--prefix=') global_options = options.global_options or [] diff --git a/pip/download.py b/pip/download.py index 54d3131dfba..8f5850b493e 100644 --- a/pip/download.py +++ b/pip/download.py @@ -388,7 +388,12 @@ def request(self, method, url, *args, **kwargs): def get_file_content(url, comes_from=None, session=None): """Gets the content of a file; it may be a filename, file: URL, or - http: URL. Returns (location, content). Content is unicode.""" + http: URL. Returns (location, content). Content is unicode. + + :param url: File path or url. + :param comes_from: Origin description of requirements. + :param session: Instance of pip.download.PipSession. + """ if session is None: raise TypeError( "get_file_content() missing 1 required keyword argument: 'session'" diff --git a/pip/locations.py b/pip/locations.py index e598ef105a4..97d1f064683 100644 --- a/pip/locations.py +++ b/pip/locations.py @@ -144,9 +144,11 @@ def distutils_scheme(dist_name, user=False, home=None, root=None, # or user base for installations during finalize_options() # ideally, we'd prefer a scheme class that has no side-effects. assert not (user and prefix), "user={0} prefix={1}".format(user, prefix) - i.user = user or i.user - if user: + assert not (home and prefix), "home={0} prefix={1}".format(home, prefix) + assert not (home and user), "home={0} user={1}".format(home, user) + if user or home: i.prefix = "" + i.user = user or i.user i.prefix = prefix or i.prefix i.home = home or i.home i.root = root or i.root diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index 4ebc1b7b35c..4fe9211d132 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -690,6 +690,37 @@ def test_install_package_conflict_prefix_and_user(script, data): ) +def test_install_package_conflict_prefix_and_target(script, data): + """ + Test installing a package using pip install --prefix --user errors out + """ + prefix_path = script.scratch_path / 'prefix' + target_path = script.scratch_path / 'target' + result = script.pip( + 'install', '-f', data.find_links, '--no-index', '--target', target_path, + '--prefix', prefix_path, 'simple==1.0', + expect_error=True, quiet=True, + ) + assert ( + "Can not combine '--target' and '--prefix'" in result.stderr + ) + + +def test_install_package_conflict_target_and_user(script, data): + """ + Test installing a package using pip install --prefix --user errors out + """ + target_path = script.scratch_path / 'target' + result = script.pip( + 'install', '-f', data.find_links, '--no-index', '--user', + '--target', target_path, 'simple==1.0', + expect_error=True, quiet=True, + ) + assert ( + "Can not combine '--target' and '--user'" in result.stderr + ) + + # skip on win/py3 for now, see issue #782 @pytest.mark.skipif("sys.platform == 'win32' and sys.version_info >= (3,)") def test_install_package_that_emits_unicode(script, data): diff --git a/tests/functional/test_install_reqs.py b/tests/functional/test_install_reqs.py index c78a21786ea..0e21b9bec0b 100644 --- a/tests/functional/test_install_reqs.py +++ b/tests/functional/test_install_reqs.py @@ -241,6 +241,45 @@ def test_nowheel_user_with_prefix_in_pydistutils_cfg(script, data, virtualenv): ) in result.stderr +@pytest.mark.network +def test_wheel_target_with_prefix_in_pydistutils_cfg(script, data, virtualenv): + # Make sure wheel is available in the virtualenv + script.pip('install', 'wheel') + virtualenv.system_site_packages = True + homedir = script.environ["HOME"] + script.scratch_path.join("bin").mkdir() + with open(os.path.join(homedir, ".pydistutils.cfg"), "w") as cfg: + cfg.write(textwrap.dedent(""" + [install] + prefix=%s""" % script.scratch_path)) + + target_path = script.scratch_path / 'target' + result = script.pip('install', '--target', target_path, '--no-index', '-f', + data.find_links, 'requiresupper') + # Check that we are really installing a wheel + assert 'Running setup.py install for requiresupper' not in result.stdout + assert 'installed requiresupper' in result.stdout + + +def test_nowheel_target_with_prefix_in_pydistutils_cfg(script, data, virtualenv): + virtualenv.system_site_packages = True + homedir = script.environ["HOME"] + script.scratch_path.join("bin").mkdir() + with open(os.path.join(homedir, ".pydistutils.cfg"), "w") as cfg: + cfg.write(textwrap.dedent(""" + [install] + prefix=%s""" % script.scratch_path)) + + target_path = script.scratch_path / 'target' + result = script.pip('install', '--no-use-wheel', '--target', target_path, + '--no-index', '-f', data.find_links, 'requiresupper', + expect_stderr=True) + assert 'installed requiresupper' in result.stdout + assert ('DEPRECATION: --no-use-wheel is deprecated and will be removed ' + 'in the future. Please use --no-binary :all: instead.\n' + ) in result.stderr + + def test_install_option_in_requirements_file(script, data, virtualenv): """ Test --install-option in requirements file overrides same option in cli