提交 ae867db0 编写于 作者: P Paul Nasrat

Merge pull request #574 from qwcode/userscheme_pt4

--user fixes part 4,  issue #440
"""Stuff that differs in different Python versions"""
import sys
import site
__all__ = ['WindowsError']
......@@ -84,6 +85,8 @@ else:
from distutils.sysconfig import get_python_lib, get_python_version
#site.USER_SITE was created in py2.6
user_site = getattr(site,'USER_SITE',None)
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
......
......@@ -217,7 +217,8 @@ class InstallCommand(Command):
as_egg=options.as_egg,
ignore_installed=options.ignore_installed,
ignore_dependencies=options.ignore_dependencies,
force_reinstall=options.force_reinstall)
force_reinstall=options.force_reinstall,
use_user_site=options.use_user_site)
for name in args:
requirement_set.add_requirement(
InstallRequirement.from_line(name, None))
......
......@@ -15,7 +15,7 @@ from pip.vcs import vcs
from pip.log import logger
from pip.util import display_path, rmtree
from pip.util import ask, ask_path_exists, backup_dir
from pip.util import is_installable_dir, is_local, dist_is_local
from pip.util import is_installable_dir, is_local, dist_is_local, dist_in_usersite
from pip.util import renames, normalize_path, egg_link_path
from pip.util import make_path_relative
from pip.util import call_subprocess
......@@ -62,6 +62,7 @@ class InstallRequirement(object):
self.install_succeeded = None
# UninstallPathSet of uninstalled distribution (for possible rollback)
self.uninstalled = None
self.use_user_site = False
@classmethod
def from_editable(cls, editable_req, comes_from=None, default_vcs=None):
......@@ -564,7 +565,7 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
if self.editable:
self.install_editable(install_options, global_options)
return
temp_location = tempfile.mkdtemp('-record', 'pip-')
record_filename = os.path.join(temp_location, 'install-record.txt')
try:
......@@ -680,7 +681,12 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
except pkg_resources.DistributionNotFound:
return False
except pkg_resources.VersionConflict:
self.conflicts_with = pkg_resources.get_distribution(self.req.project_name)
existing_dist = pkg_resources.get_distribution(self.req.project_name)
if self.use_user_site:
if dist_in_usersite(existing_dist):
self.conflicts_with = existing_dist
else:
self.conflicts_with = existing_dist
return True
@property
......@@ -798,7 +804,7 @@ class RequirementSet(object):
def __init__(self, build_dir, src_dir, download_dir, download_cache=None,
upgrade=False, ignore_installed=False, as_egg=False,
ignore_dependencies=False, force_reinstall=False):
ignore_dependencies=False, force_reinstall=False, use_user_site=False):
self.build_dir = build_dir
self.src_dir = src_dir
self.download_dir = download_dir
......@@ -815,6 +821,7 @@ class RequirementSet(object):
self.successfully_installed = []
self.reqs_to_cleanup = []
self.as_egg = as_egg
self.use_user_site = use_user_site
def __str__(self):
reqs = [req for req in self.requirements.values()
......@@ -825,6 +832,7 @@ class RequirementSet(object):
def add_requirement(self, install_req):
name = install_req.name
install_req.as_egg = self.as_egg
install_req.use_user_site = self.use_user_site
if not name:
self.unnamed_requirements.append(install_req)
else:
......
......@@ -9,7 +9,7 @@ import zipfile
import tarfile
import subprocess
from pip.exceptions import InstallationError, BadCommand
from pip.backwardcompat import WindowsError, string_types, raw_input, console_to_str
from pip.backwardcompat import WindowsError, string_types, raw_input, console_to_str, user_site
from pip.locations import site_packages, running_under_virtualenv
from pip.log import logger
......@@ -294,6 +294,16 @@ def dist_is_local(dist):
return is_local(dist_location(dist))
def dist_in_usersite(dist):
"""
Return True if given Distribution is installed in user site.
"""
if user_site:
return normalize_path(dist_location(dist)).startswith(normalize_path(user_site))
else:
return False
def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'python')):
"""
Return a list of installed Distribution objects.
......
......@@ -94,3 +94,75 @@ class Tests_UserSite:
result = run_pip('install', '--user', curdir, cwd=run_from, expect_error=True)
assert "Can not perform a '--user' install. User site-packages are not visible in this virtualenv." in result.stdout
def test_install_user_conflict_in_usersite(self):
"""
Test user install with conflict in usersite updates usersite.
"""
env = reset_env(system_site_packages=True)
result1 = run_pip('install', '--user', 'INITools==0.3')
result2 = run_pip('install', '--user', 'INITools==0.1')
#usersite has 0.1
egg_info_folder = env.user_site / 'INITools-0.1-py%s.egg-info' % pyversion
initools_v3_file = env.root_path / env.user_site / 'initools' / 'configparser.py' #file only in 0.3
assert egg_info_folder in result2.files_created, str(result2)
assert not isfile(initools_v3_file), initools_v3_file
def test_install_user_conflict_in_site(self):
"""
Test user install with conflict in site ignores site and installs to usersite
"""
#the test framework only supports testing using virtualenvs
#this test will use a --system_site_packages virtualenv to achieve the conflict scenario.
env = reset_env(system_site_packages=True)
result1 = run_pip('install', 'INITools==0.2')
result2 = run_pip('install', '--user', 'INITools==0.1')
#usersite has 0.1
egg_info_folder = env.user_site / 'INITools-0.1-py%s.egg-info' % pyversion
initools_folder = env.user_site / 'initools'
assert egg_info_folder in result2.files_created, str(result2)
assert initools_folder in result2.files_created, str(result2)
#site still has 0.2 (can't look in result1; have to check)
egg_info_folder = env.root_path / env.site_packages / 'INITools-0.2-py%s.egg-info' % pyversion
initools_folder = env.root_path / env.site_packages / 'initools'
assert isdir(egg_info_folder)
assert isdir(initools_folder)
def test_install_user_conflict_in_globalsite_and_usersite(self):
"""
Test user install with conflict in globalsite and usersite ignores global site and updates usersite.
"""
#the test framework only supports testing using virtualenvs
#this test will use a --system_site_packages virtualenv to achieve the conflict scenario.
env = reset_env(system_site_packages=True)
# the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv site, usersite, global site
# given this ordering you *can't* use it to simulate the scenario for this test.
# this test will add the usersite to PYTHONPATH to simulate the desired ordering
env.environ["PYTHONPATH"] = env.root_path / env.user_site
result1 = run_pip('install', 'INITools==0.2')
result2 = run_pip('install', '--user', 'INITools==0.3')
result3 = run_pip('install', '--user', 'INITools==0.1')
#usersite has 0.1
egg_info_folder = env.user_site / 'INITools-0.1-py%s.egg-info' % pyversion
initools_v3_file = env.root_path / env.user_site / 'initools' / 'configparser.py' #file only in 0.3
assert egg_info_folder in result3.files_created, str(result3)
assert not isfile(initools_v3_file), initools_v3_file
#site still has 0.2 (can't just look in result1; have to check)
egg_info_folder = env.root_path / env.site_packages / 'INITools-0.2-py%s.egg-info' % pyversion
initools_folder = env.root_path / env.site_packages / 'initools'
assert isdir(egg_info_folder)
assert isdir(initools_folder)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册