1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
From 64446a63a0e31bad2f6927f2213710dfcc50b3ab Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Wed, 3 Dec 2014 11:18:11 -0600
Subject: Prevent pip from removing system packages.
Adjust is_local() to consider OS-owned paths non-local. Fix the error
message for is_local() in the non-virtualenv case.
Author: Geoffrey Thomas <geofft@ldpreload.com>
Bug-Debian: http://bugs.debian.org/771794
Origin: https://github.com/geofft/pip.git
Forwarded: not-needed
Reviewed-By: Donald Stufft <donald@stufft.io>
Reviewed-By: Scott Kitterman <scott@kitterman.com>
Last-Update: 2014-12-04
Patch-Name: hands-off-system-packages.patch
---
pip/utils/__init__.py | 36 +++++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/pip/utils/__init__.py b/pip/utils/__init__.py
index 815bd33..0d25d91 100644
--- a/pip/utils/__init__.py
+++ b/pip/utils/__init__.py
@@ -276,22 +276,40 @@ def renames(old, new):
def is_local(path):
"""
- Return True if path is within sys.prefix, if we're running in a virtualenv.
+ Return True if this is a path pip is allowed to modify.
- If we're not in a virtualenv, all paths are considered "local."
+ If we're in a virtualenv, sys.prefix points to the virtualenv's
+ prefix; only sys.prefix is considered local.
+
+ If we're not in a virtualenv, in general we can modify anything.
+ However, if the OS vendor has configured distutils to install
+ somewhere other than sys.prefix (which could be a subdirectory of
+ sys.prefix, e.g. /usr/local), we consider sys.prefix itself nonlocal
+ and the domain of the OS vendor. (In other words, everything _other
+ than_ sys.prefix is considered local.)
"""
- if not running_under_virtualenv():
- return True
- return normalize_path(path).startswith(normalize_path(sys.prefix))
+
+ path = normalize_path(path)
+ prefix = normalize_path(sys.prefix)
+
+ if running_under_virtualenv():
+ return path.startswith(normalize_path(sys.prefix))
+ else:
+ from pip.locations import distutils_scheme
+ if path.startswith(prefix):
+ for local_path in distutils_scheme("").values():
+ if path.startswith(normalize_path(local_path)):
+ return True
+ return False
+ else:
+ return True
def dist_is_local(dist):
"""
- Return True if given Distribution object is installed locally
- (i.e. within current virtualenv).
-
- Always True if we're not in a virtualenv.
+ Return True if given Distribution object is installed somewhere pip
+ is allowed to modify.
"""
return is_local(dist_location(dist))
|