summaryrefslogtreecommitdiff
path: root/pkg_resources.py
diff options
context:
space:
mode:
authorpje <pje@6015fed2-1504-0410-9fe1-9d1591cc4771>2005-10-17 02:26:39 +0000
committerpje <pje@6015fed2-1504-0410-9fe1-9d1591cc4771>2005-10-17 02:26:39 +0000
commitc70724954e8f3d74adbf14dfae5d294cfd3a712c (patch)
treee931e6f30fe51eb6ee968a008e9ac4c439249ea8 /pkg_resources.py
parent64091da29d13967a2bce9f44b30e5beda0bc1ab8 (diff)
downloadpython-setuptools-c70724954e8f3d74adbf14dfae5d294cfd3a712c.tar.gz
Significantly enhanced support and docs for "non-root" installation,
including both "virtual" and PYTHONPATH-based installs. The activation precedence of distributions has also changed so that PYTHONPATH-based non-root installs can include eggs that override system-defined packages (whether managed or unmanaged). This version should eliminate most common installation complaints from non-root Python users. Note: this version includes a hacked 'site.py' to support processing .pth files in directories that come *before* site-packages on sys.path. However, because of its placement, it should only come into play when a user puts the setuptools .egg file *directly* on PYTHONPATH, so it doesn't affect "virtual" or "root" installations. It's strictly to provide support for luddites who refuse to give up their existing non-root PYTHONPATH setup unless you pry it from their cold, dead hands. :) git-svn-id: http://svn.python.org/projects/sandbox/trunk/setuptools@41262 6015fed2-1504-0410-9fe1-9d1591cc4771
Diffstat (limited to 'pkg_resources.py')
-rw-r--r--pkg_resources.py61
1 files changed, 51 insertions, 10 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index f946fc4..6717c2a 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -356,7 +356,7 @@ class WorkingSet(object):
self.entry_keys.setdefault(entry, [])
self.entries.append(entry)
for dist in find_distributions(entry, True):
- self.add(dist, entry)
+ self.add(dist, entry, False)
def __contains__(self,dist):
@@ -421,7 +421,7 @@ class WorkingSet(object):
seen[key]=1
yield self.by_key[key]
- def add(self, dist, entry=None):
+ def add(self, dist, entry=None, insert=True):
"""Add `dist` to working set, associated with `entry`
If `entry` is unspecified, it defaults to the ``.location`` of `dist`.
@@ -432,23 +432,23 @@ class WorkingSet(object):
doesn't already have a distribution in the set. If it's added, any
callbacks registered with the ``subscribe()`` method will be called.
"""
+ if insert:
+ dist.insert_on(self.entries, entry)
+
if entry is None:
entry = dist.location
-
- if entry not in self.entry_keys:
- self.entries.append(entry)
- self.entry_keys[entry] = []
+ keys = self.entry_keys.setdefault(entry,[])
if dist.key in self.by_key:
return # ignore hidden distros
self.by_key[dist.key] = dist
- keys = self.entry_keys[entry]
if dist.key not in keys:
keys.append(dist.key)
self._added_new(dist)
+
def resolve(self, requirements, env=None, installer=None):
"""List all distributions needed to (recursively) meet `requirements`
@@ -1837,12 +1837,12 @@ class Distribution(object):
def activate(self,path=None):
"""Ensure distribution is importable on `path` (default=sys.path)"""
if path is None: path = sys.path
- if self.location not in path:
- path.append(self.location)
+ self.insert_on(path)
if path is sys.path:
fixup_namespace_packages(self.location)
map(declare_namespace, self._get_metadata('namespace_packages.txt'))
+
def egg_name(self):
"""Return what this distribution's standard .egg filename should be"""
filename = "%s-%s-py%s" % (
@@ -1907,6 +1907,47 @@ class Distribution(object):
"""Return the EntryPoint object for `group`+`name`, or ``None``"""
return self.get_entry_map(group).get(name)
+ def insert_on(self, path, loc = None):
+ """Insert self.location in path before its nearest parent directory"""
+ loc = loc or self.location
+ if not loc: return
+ if path is sys.path:
+ self.check_version_conflict()
+ best, pos = 0, -1
+ for p,item in enumerate(path):
+ if loc.startswith(item) and len(item)>best and loc<>item:
+ best, pos = len(item), p
+ if pos==-1:
+ if loc not in path: path.append(loc)
+ elif loc not in path[:pos+1]:
+ while loc in path: path.remove(loc)
+ path.insert(pos,loc)
+
+
+
+ def check_version_conflict(self):
+ if self.key=='setuptools':
+ return # ignore the inevitable setuptools self-conflicts :(
+
+ nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt'))
+
+ for modname in self._get_metadata('top_level.txt'):
+ if modname not in sys.modules or modname in nsp:
+ continue
+
+ fn = getattr(sys.modules[modname], '__file__', None)
+ if fn and fn.startswith(self.location):
+ continue
+
+ from warnings import warn
+ warn(
+ "Module %s was already imported from %s, but %s is being added"
+ " to sys.path" % (modname, fn, self.location)
+ )
+
+
+
+
@@ -2165,9 +2206,9 @@ iter_entry_points = working_set.iter_entry_points
add_activation_listener = working_set.subscribe
run_script = working_set.run_script
run_main = run_script # backward compatibility
-
# Activate all distributions already on sys.path, and ensure that
# all distributions added to the working set in the future (e.g. by
# calling ``require()``) will get activated as well.
add_activation_listener(lambda dist: dist.activate())
+working_set.entries=[]; map(working_set.add_entry,sys.path) # match order