diff options
| author | Jason R. Coombs <jaraco@jaraco.com> | 2016-01-16 17:04:13 -0500 |
|---|---|---|
| committer | Jason R. Coombs <jaraco@jaraco.com> | 2016-01-16 17:04:13 -0500 |
| commit | 8a304f31a541944339fed6fe931dd5024d3f0897 (patch) | |
| tree | c8bb161ac6503c06b948f787c244c25e11c9e242 /pkg_resources | |
| parent | 70697b3a8c795a25de56a30d41cca76ad18d78fb (diff) | |
| parent | ebc54982b1085b05054a75dbcdd16008ac20a60e (diff) | |
| download | python-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__.py | 25 | ||||
| -rw-r--r-- | pkg_resources/tests/test_resources.py | 60 |
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 |
