Skip to content

Commit e4e0dd9

Browse files
committed
Add unit tests for user install decision
1 parent b5f4a91 commit e4e0dd9

File tree

3 files changed

+98
-61
lines changed

3 files changed

+98
-61
lines changed

src/pip/_internal/commands/install.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ def site_packages_writable(**kwargs):
536536

537537

538538
def decide_user_install(
539-
use_user_site, # type: Optional[bool]
539+
use_user_site=None, # type: Optional[bool]
540540
prefix_path=None, # type: Optional[str]
541541
target_dir=None, # type: Optional[str]
542542
root_path=None, # type: Optional[str]
@@ -577,12 +577,19 @@ def decide_user_install(
577577
return False
578578

579579
if use_user_site is not None:
580+
use_user_site = bool(use_user_site)
580581
logger.debug("{} install by explicit request".format(
581582
"User" if use_user_site else "Non-user"))
582-
use_user_site = bool(use_user_site)
583-
elif site.ENABLE_USER_SITE is False: # This never seems to be reached.
584-
logger.debug("Non-user install due to disabled user site-packages by "
585-
"user request (with 'python -s' or PYTHONNOUSERSITE)")
583+
if use_user_site is True and site.ENABLE_USER_SITE is None:
584+
raise InstallationError("User site-packages are disabled for "
585+
"security reasons or by an administrator.")
586+
elif site.ENABLE_USER_SITE is None:
587+
logger.debug("Non-user install since user site-packages are disabled "
588+
"for security reasons or by an administrator.")
589+
use_user_site = False
590+
elif site.ENABLE_USER_SITE is False:
591+
logger.debug("Non-user install since user site-packages are disabled "
592+
"by user request (with 'python -s' or PYTHONNOUSERSITE)")
586593
use_user_site = False
587594
elif root_path:
588595
logger.debug(
@@ -596,14 +603,13 @@ def decide_user_install(
596603
"normal site-packages is not writeable")
597604
use_user_site = True
598605

599-
if use_user_site:
600-
if site.ENABLE_USER_SITE is None:
601-
raise InstallationError("User site-packages are disabled for "
602-
"security reasons or by an administrator.")
606+
if use_user_site is True:
603607
if virtualenv_no_global():
604-
raise InstallationError("User site-packages are not visible "
605-
"in this virtualenv.")
608+
raise InstallationError(
609+
"Can not perform a '--user' install. "
610+
"User site-packages are not visible in this virtualenv.")
606611
else:
612+
assert use_user_site is False
607613
if not site_packages_writable(root=root_path, isolated=isolated_mode):
608614
raise InstallationError("Cannot write to global site-packages.")
609615
return use_user_site

tests/functional/test_install.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -847,27 +847,6 @@ def test_install_package_with_target(script):
847847
assert singlemodule_py in result.files_updated, str(result)
848848

849849

850-
def test_install_package_to_usersite_with_target_must_fail(script):
851-
"""
852-
Test that installing package to usersite with target
853-
must raise error
854-
"""
855-
target_dir = script.scratch_path / 'target'
856-
result = script.pip_install_local(
857-
'--user', '-t', target_dir, "simple==1.0", expect_error=True
858-
)
859-
assert "Can not combine '--user' and '--target'" in result.stderr, (
860-
str(result)
861-
)
862-
863-
result = script.pip_install_local(
864-
'--user', '--target', target_dir, "simple==1.0", expect_error=True
865-
)
866-
assert "Can not combine '--user' and '--target'" in result.stderr, (
867-
str(result)
868-
)
869-
870-
871850
def test_install_nonlocal_compatible_wheel(script, data):
872851
target_dir = script.scratch_path / 'target'
873852

tests/unit/test_command_install.py

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import errno
2+
from itertools import product
23

34
import pytest
45
from mock import patch
@@ -9,39 +10,90 @@
910
decide_user_install,
1011
warn_deprecated_install_options,
1112
)
13+
from pip._internal.exceptions import CommandError, InstallationError
1214
from pip._internal.req.req_install import InstallRequirement
1315

16+
ENABLE_USER_SITE = 'site.ENABLE_USER_SITE'
17+
WRITABLE = 'pip._internal.commands.install.test_writable_dir'
18+
ISDIR = 'pip._internal.commands.install.os.path.isdir'
19+
EXISTS = 'pip._internal.commands.install.os.path.exists'
1420

21+
22+
def false(*args, **kwargs):
23+
"""Return False."""
24+
return False
25+
26+
27+
def true(*args, **kwargs):
28+
"""Return True."""
29+
return True
30+
31+
32+
# virtualenv_no_global is tested by functional test
33+
@patch('pip._internal.commands.install.virtualenv_no_global', false)
1534
class TestDecideUserInstall:
16-
@patch('site.ENABLE_USER_SITE', True)
17-
@patch('pip._internal.commands.install.site_packages_writable')
18-
def test_prefix_and_target(self, sp_writable):
19-
sp_writable.return_value = False
20-
21-
assert decide_user_install(
22-
use_user_site=None, prefix_path='foo'
23-
) is False
24-
25-
assert decide_user_install(
26-
use_user_site=None, target_dir='bar'
27-
) is False
28-
29-
@pytest.mark.parametrize(
30-
"enable_user_site,site_packages_writable,result", [
31-
(True, True, False),
32-
(True, False, True),
33-
(False, True, False),
34-
(False, False, False),
35-
])
36-
def test_most_cases(
37-
self, enable_user_site, site_packages_writable, result, monkeypatch,
38-
):
39-
monkeypatch.setattr('site.ENABLE_USER_SITE', enable_user_site)
40-
monkeypatch.setattr(
41-
'pip._internal.commands.install.site_packages_writable',
42-
lambda **kw: site_packages_writable
43-
)
44-
assert decide_user_install(use_user_site=None) is result
35+
@pytest.mark.parametrize('use_user_site,prefix_path,target_dir,root_path',
36+
filter(lambda args: sum(map(bool, args)) > 1,
37+
product((False, True), (None, 'foo'),
38+
(None, 'bar'), (None, 'baz'))))
39+
def test_conflicts(self, use_user_site,
40+
prefix_path, target_dir, root_path):
41+
with pytest.raises(CommandError):
42+
decide_user_install(
43+
use_user_site=use_user_site, prefix_path=prefix_path,
44+
target_dir=target_dir, root_path=root_path)
45+
46+
def test_target_dir(self):
47+
with patch(WRITABLE, true):
48+
with patch(EXISTS, true), patch(ISDIR, false):
49+
with pytest.raises(InstallationError):
50+
decide_user_install(target_dir='bar')
51+
for exists, isdir in (false, false), (false, true), (true, true):
52+
with patch(EXISTS, exists), patch(ISDIR, isdir):
53+
assert decide_user_install(target_dir='bar') is False
54+
55+
def test_target_writable(self):
56+
with patch(EXISTS, false):
57+
with patch(WRITABLE, false), pytest.raises(InstallationError):
58+
decide_user_install(target_dir='bar')
59+
with patch(WRITABLE, true):
60+
assert decide_user_install(target_dir='bar') is False
61+
62+
def test_prefix_writable(self):
63+
with patch(WRITABLE, false), pytest.raises(InstallationError):
64+
decide_user_install(prefix_path='foo')
65+
with patch(WRITABLE, true):
66+
assert decide_user_install(prefix_path='foo') is False
67+
68+
def test_global_site_writable(self):
69+
with patch(ENABLE_USER_SITE, True):
70+
with patch(WRITABLE, false):
71+
with pytest.raises(InstallationError):
72+
decide_user_install(use_user_site=False)
73+
with pytest.raises(InstallationError):
74+
decide_user_install(root_path='baz')
75+
assert decide_user_install() is True
76+
with patch(WRITABLE, true):
77+
assert decide_user_install(use_user_site=True) is True
78+
assert decide_user_install(root_path='baz') is False
79+
assert decide_user_install() is False
80+
81+
def test_enable_user_site(self):
82+
with patch(WRITABLE, true):
83+
with patch(ENABLE_USER_SITE, None):
84+
assert decide_user_install() is False
85+
assert decide_user_install(use_user_site=False) is False
86+
with pytest.raises(InstallationError):
87+
decide_user_install(use_user_site=True)
88+
with patch(ENABLE_USER_SITE, False):
89+
assert decide_user_install() is False
90+
assert decide_user_install(use_user_site=False) is False
91+
assert decide_user_install(use_user_site=True) is True
92+
with patch(ENABLE_USER_SITE, True):
93+
assert decide_user_install(use_user_site=False) is False
94+
assert decide_user_install(use_user_site=True) is True
95+
with patch(WRITABLE, false), patch(ENABLE_USER_SITE, True):
96+
assert decide_user_install() is True
4597

4698

4799
def test_deprecation_notice_for_pip_install_options(recwarn):

0 commit comments

Comments
 (0)