From b43055063756fc482d35f179ab5f2f393d83a294 Mon Sep 17 00:00:00 2001 From: Daniel H Date: Wed, 9 Nov 2016 17:15:47 +0100 Subject: [PATCH 1/6] Also set --prefix to empty when specifying --home. --- pip/commands/install.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pip/commands/install.py b/pip/commands/install.py index 227c5264a0d..f6210f246a7 100644 --- a/pip/commands/install.py +++ b/pip/commands/install.py @@ -266,6 +266,7 @@ def run(self, options, args): "continue." ) install_options.append('--home=' + temp_target_dir) + install_options.append('--prefix=') global_options = options.global_options or [] From 8b373493946ca7f733022c640908eb4a18a2b4a5 Mon Sep 17 00:00:00 2001 From: Daniel H Date: Wed, 9 Nov 2016 17:25:38 +0100 Subject: [PATCH 2/6] Avoid setting home and prefix simultaneously. --- pip/locations.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pip/locations.py b/pip/locations.py index e598ef105a4..d3013d1e0ec 100644 --- a/pip/locations.py +++ b/pip/locations.py @@ -144,9 +144,10 @@ 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), "user={0} prefix={1}".format(home, prefix) + 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 From 3aa1101704827ca6ba34d311d3f553bed17bab4b Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Wed, 9 Nov 2016 16:25:40 +0300 Subject: [PATCH 3/6] Document get_file_content() parameters --- pip/download.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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'" From 2306675d63d28149c1f0e7931e78d07610989723 Mon Sep 17 00:00:00 2001 From: Daniel H Date: Wed, 9 Nov 2016 17:15:47 +0100 Subject: [PATCH 4/6] Make --target, --user, and --prefix mutually exclusive. Also override defaults set somewhere (e.g. .pydistutils.cfg) when command line switches are given. --- pip/commands/install.py | 11 +++++++++++ pip/locations.py | 6 ++++-- 2 files changed, 15 insertions(+), 2 deletions(-) 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/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 From b586148f56600cc01a1894cb20997509d9615395 Mon Sep 17 00:00:00 2001 From: Daniel Halmschlager Date: Thu, 10 Nov 2016 17:39:06 +0100 Subject: [PATCH 5/6] Add tests for mutual exclusivity of --target, --user, and --prefix. Also check if prefix from .pydistutils.cfg is overriden. --- tests/functional/test_install.py | 31 +++++++++++++++++++++ tests/functional/test_install_reqs.py | 39 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) 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 From f023a34db59107759a5de0a436c34b0cf82438c7 Mon Sep 17 00:00:00 2001 From: Daniel Halmschlager Date: Thu, 10 Nov 2016 20:05:08 +0100 Subject: [PATCH 6/6] Fix conflicts. --- pip/locations.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pip/locations.py b/pip/locations.py index bab11742f0a..97d1f064683 100644 --- a/pip/locations.py +++ b/pip/locations.py @@ -144,12 +144,8 @@ 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) -<<<<<<< HEAD assert not (home and prefix), "home={0} prefix={1}".format(home, prefix) assert not (home and user), "home={0} user={1}".format(home, user) -======= - assert not (home and prefix), "user={0} prefix={1}".format(home, prefix) ->>>>>>> 8b373493946ca7f733022c640908eb4a18a2b4a5 if user or home: i.prefix = "" i.user = user or i.user