mirror of https://github.com/pypa/pip
Default to --user install in certain conditions
This commit is contained in:
parent
90aeec97f1
commit
042d4844e8
|
@ -13,6 +13,7 @@ import logging
|
|||
import operator
|
||||
import os
|
||||
import shutil
|
||||
import site
|
||||
from optparse import SUPPRESS_HELP
|
||||
|
||||
from pip._vendor import pkg_resources
|
||||
|
@ -28,11 +29,11 @@ from pip._internal.exceptions import (
|
|||
InstallationError,
|
||||
PreviousBuildDirError,
|
||||
)
|
||||
from pip._internal.locations import distutils_scheme
|
||||
from pip._internal.locations import distutils_scheme, site_packages
|
||||
from pip._internal.operations.check import check_install_conflicts
|
||||
from pip._internal.req import RequirementSet, install_given_reqs
|
||||
from pip._internal.req.req_tracker import RequirementTracker
|
||||
from pip._internal.utils.filesystem import check_path_owner
|
||||
from pip._internal.utils.filesystem import check_path_owner, test_writable_dir
|
||||
from pip._internal.utils.misc import (
|
||||
ensure_dir,
|
||||
get_installed_version,
|
||||
|
@ -305,6 +306,17 @@ class InstallCommand(RequirementCommand):
|
|||
install_options.append('--user')
|
||||
install_options.append('--prefix=')
|
||||
|
||||
elif options.use_user_site is None:
|
||||
if options.prefix_path or options.target_dir:
|
||||
options.use_user_site = False
|
||||
elif site_packages_writable(
|
||||
root=options.root_path,
|
||||
isolated=options.isolated_mode
|
||||
):
|
||||
options.use_user_site = False
|
||||
elif site.ENABLE_USER_SITE:
|
||||
options.use_user_site = True
|
||||
|
||||
target_temp_dir = None # type: Optional[TempDirectory]
|
||||
target_temp_dir_path = None # type: Optional[str]
|
||||
if options.target_dir:
|
||||
|
@ -594,6 +606,10 @@ def get_lib_location_guesses(*args, **kwargs):
|
|||
return [scheme['purelib'], scheme['platlib']]
|
||||
|
||||
|
||||
def site_packages_writable(**kwargs):
|
||||
return all(test_writable_dir(d) for d in get_lib_location_guesses(**kwargs))
|
||||
|
||||
|
||||
def create_env_error_message(error, show_traceback, using_user_site):
|
||||
"""Format an error message for an EnvironmentError
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import os.path
|
||||
import random
|
||||
import shutil
|
||||
import stat
|
||||
from contextlib import contextmanager
|
||||
|
@ -113,3 +114,42 @@ if PY2:
|
|||
|
||||
else:
|
||||
replace = _replace_retry(os.replace)
|
||||
|
||||
|
||||
# test_writable_dir and _test_writable_dir_win are copied from Flit,
|
||||
# with the author's agreement to also place them under pip's license.
|
||||
def test_writable_dir(path):
|
||||
"""Check if a directory is writable.
|
||||
|
||||
Uses os.access() on POSIX, tries creating files on Windows.
|
||||
"""
|
||||
if os.name == 'posix':
|
||||
return os.access(path, os.W_OK)
|
||||
|
||||
return _test_writable_dir_win(path)
|
||||
|
||||
|
||||
def _test_writable_dir_win(path):
|
||||
# os.access doesn't work on Windows: http://bugs.python.org/issue2528
|
||||
# and we can't use tempfile: http://bugs.python.org/issue22107
|
||||
basename = 'accesstest_deleteme_fishfingers_custard_'
|
||||
alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'
|
||||
for i in range(10):
|
||||
name = basename + ''.join(random.choice(alphabet) for _ in range(6))
|
||||
file = os.path.join(path, name)
|
||||
try:
|
||||
with open(file, mode='xb'):
|
||||
pass
|
||||
except FileExistsError:
|
||||
continue
|
||||
except PermissionError:
|
||||
# This could be because there's a directory with the same name.
|
||||
# But it's highly unlikely there's a directory called that,
|
||||
# so we'll assume it's because the parent directory is not writable.
|
||||
return False
|
||||
else:
|
||||
os.unlink(file)
|
||||
return True
|
||||
|
||||
# This should never be reached
|
||||
raise EnvironmentError('Unexpected condition testing for writable directory')
|
||||
|
|
Loading…
Reference in New Issue