summaryrefslogtreecommitdiff
path: root/pkg_resources
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2016-01-16 17:04:13 -0500
committerJason R. Coombs <jaraco@jaraco.com>2016-01-16 17:04:13 -0500
commit8a304f31a541944339fed6fe931dd5024d3f0897 (patch)
treec8bb161ac6503c06b948f787c244c25e11c9e242 /pkg_resources
parent70697b3a8c795a25de56a30d41cca76ad18d78fb (diff)
parentebc54982b1085b05054a75dbcdd16008ac20a60e (diff)
downloadpython-setuptools-git-8a304f31a541944339fed6fe931dd5024d3f0897.tar.gz
Merged in embray/setuptools (pull request #167)
Possible fix for #207
Diffstat (limited to 'pkg_resources')
-rw-r--r--pkg_resources/__init__.py25
-rw-r--r--pkg_resources/tests/test_resources.py60
2 files changed, 72 insertions, 13 deletions
diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py
index 8382571e..50b86cdb 100644
--- a/pkg_resources/__init__.py
+++ b/pkg_resources/__init__.py
@@ -755,7 +755,7 @@ class WorkingSet(object):
will be called.
"""
if insert:
- dist.insert_on(self.entries, entry)
+ dist.insert_on(self.entries, entry, replace=replace)
if entry is None:
entry = dist.location
@@ -2182,9 +2182,17 @@ def _handle_ns(packageName, path_item):
path = module.__path__
path.append(subpath)
loader.load_module(packageName)
- for path_item in path:
- if path_item not in module.__path__:
- module.__path__.append(path_item)
+
+ # Rebuild mod.__path__ ensuring that all entries are ordered
+ # corresponding to their sys.path order
+ sys_path= [(p and _normalize_cached(p) or p) for p in sys.path]
+ def sort_key(p):
+ parts = p.split(os.sep)
+ parts = parts[:-(packageName.count('.') + 1)]
+ return sys_path.index(_normalize_cached(os.sep.join(parts)))
+
+ path.sort(key=sort_key)
+ module.__path__[:] = [_normalize_cached(p) for p in path]
return subpath
def declare_namespace(packageName):
@@ -2639,7 +2647,7 @@ class Distribution(object):
"""Ensure distribution is importable on `path` (default=sys.path)"""
if path is None:
path = sys.path
- self.insert_on(path)
+ self.insert_on(path, replace=True)
if path is sys.path:
fixup_namespace_packages(self.location)
for pkg in self._get_metadata('namespace_packages.txt'):
@@ -2716,7 +2724,7 @@ 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):
+ def insert_on(self, path, loc=None, replace=False):
"""Insert self.location in path before its nearest parent directory"""
loc = loc or self.location
@@ -2740,7 +2748,10 @@ class Distribution(object):
else:
if path is sys.path:
self.check_version_conflict()
- path.append(loc)
+ if replace:
+ path.insert(0, loc)
+ else:
+ path.append(loc)
return
# p is the spot where we found or inserted loc; now remove duplicates
diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py
index 84133a32..6f68bf77 100644
--- a/pkg_resources/tests/test_resources.py
+++ b/pkg_resources/tests/test_resources.py
@@ -612,18 +612,32 @@ class TestNamespaces:
def setup_method(self, method):
self._ns_pkgs = pkg_resources._namespace_packages.copy()
- self._tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-")
+
+ # Further, test case where the temp dir is a symlink, where applicable
+ # See #231
+ if hasattr(os, 'symlink'):
+ real_tmpdir = tempfile.mkdtemp(prefix="real-tests-setuptools-")
+ tmpdir_base, tmpdir_name = os.path.split(real_tmpdir)
+ tmpdir = os.path.join(tmpdir_base, tmpdir_name[5:])
+ os.symlink(real_tmpdir, tmpdir)
+ self._real_tmpdir = real_tmpdir
+ self._tmpdir = tmpdir
+ else:
+ tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-")
+ self._real_tmpdir = self._tmpdir = tmpdir
+
os.makedirs(os.path.join(self._tmpdir, "site-pkgs"))
self._prev_sys_path = sys.path[:]
sys.path.append(os.path.join(self._tmpdir, "site-pkgs"))
def teardown_method(self, method):
- shutil.rmtree(self._tmpdir)
+ shutil.rmtree(self._real_tmpdir)
+ if os.path.islink(self._tmpdir):
+ os.unlink(self._tmpdir)
+
pkg_resources._namespace_packages = self._ns_pkgs.copy()
sys.path = self._prev_sys_path[:]
- @pytest.mark.skipif(os.path.islink(tempfile.gettempdir()),
- reason="Test fails when /tmp is a symlink. See #231")
def test_two_levels_deep(self):
"""
Test nested namespace packages
@@ -655,7 +669,41 @@ class TestNamespaces:
assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"]
# check the __path__ attribute contains both paths
expected = [
- os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"),
- os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"),
+ os.path.join(self._real_tmpdir, "site-pkgs", "pkg1", "pkg2"),
+ os.path.join(self._real_tmpdir, "site-pkgs2", "pkg1", "pkg2"),
]
assert pkg1.pkg2.__path__ == expected
+
+ def test_path_order(self):
+ """
+ Test that if multiple versions of the same namespace package subpackage
+ are on different sys.path entries, that only the one earliest on
+ sys.path is imported, and that the namespace package's __path__ is in
+ the correct order.
+
+ Regression test for https://bitbucket.org/pypa/setuptools/issues/207
+ """
+
+ site_pkgs = ["site-pkgs", "site-pkgs2", "site-pkgs3"]
+
+ ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
+ vers_str = "__version__ = %r"
+
+ for idx, site in enumerate(site_pkgs):
+ if idx > 0:
+ sys.path.append(os.path.join(self._tmpdir, site))
+ os.makedirs(os.path.join(self._tmpdir, site, "nspkg", "subpkg"))
+ with open(os.path.join(self._tmpdir, site, "nspkg",
+ "__init__.py"), "w") as f:
+ f.write(ns_str)
+
+ with open(os.path.join(self._tmpdir, site, "nspkg", "subpkg",
+ "__init__.py"), "w") as f:
+ f.write(vers_str % (idx + 1))
+
+ import nspkg.subpkg
+ import nspkg
+ assert nspkg.__path__ == [os.path.join(self._real_tmpdir, site,
+ "nspkg")
+ for site in site_pkgs]
+ assert nspkg.subpkg.__version__ == 1