Merge pull request #4980 from blueyed/fixup_namespace_packages
monkeypatch.syspath_prepend: call fixup_namespace_packages
This commit is contained in:
		
						commit
						51f64c2920
					
				|  | @ -0,0 +1 @@ | ||||||
|  | Namespace packages are handled better with ``monkeypatch.syspath_prepend`` and ``testdir.syspathinsert`` (via ``pkg_resources.fixup_namespace_packages``). | ||||||
|  | @ -262,10 +262,15 @@ class MonkeyPatch(object): | ||||||
| 
 | 
 | ||||||
|     def syspath_prepend(self, path): |     def syspath_prepend(self, path): | ||||||
|         """ Prepend ``path`` to ``sys.path`` list of import locations. """ |         """ Prepend ``path`` to ``sys.path`` list of import locations. """ | ||||||
|  |         from pkg_resources import fixup_namespace_packages | ||||||
|  | 
 | ||||||
|         if self._savesyspath is None: |         if self._savesyspath is None: | ||||||
|             self._savesyspath = sys.path[:] |             self._savesyspath = sys.path[:] | ||||||
|         sys.path.insert(0, str(path)) |         sys.path.insert(0, str(path)) | ||||||
| 
 | 
 | ||||||
|  |         # https://github.com/pypa/setuptools/blob/d8b901bc/docs/pkg_resources.txt#L162-L171 | ||||||
|  |         fixup_namespace_packages(str(path)) | ||||||
|  | 
 | ||||||
|     def chdir(self, path): |     def chdir(self, path): | ||||||
|         """ Change the current working directory to the specified path. |         """ Change the current working directory to the specified path. | ||||||
|         Path can be a string or a py.path.local object. |         Path can be a string or a py.path.local object. | ||||||
|  |  | ||||||
|  | @ -593,11 +593,16 @@ class Testdir(object): | ||||||
| 
 | 
 | ||||||
|         This is undone automatically when this object dies at the end of each |         This is undone automatically when this object dies at the end of each | ||||||
|         test. |         test. | ||||||
| 
 |  | ||||||
|         """ |         """ | ||||||
|  |         from pkg_resources import fixup_namespace_packages | ||||||
|  | 
 | ||||||
|         if path is None: |         if path is None: | ||||||
|             path = self.tmpdir |             path = self.tmpdir | ||||||
|         sys.path.insert(0, str(path)) | 
 | ||||||
|  |         dirname = str(path) | ||||||
|  |         sys.path.insert(0, dirname) | ||||||
|  |         fixup_namespace_packages(dirname) | ||||||
|  | 
 | ||||||
|         # a call to syspathinsert() usually means that the caller wants to |         # a call to syspathinsert() usually means that the caller wants to | ||||||
|         # import some dynamically created files, thus with python3 we |         # import some dynamically created files, thus with python3 we | ||||||
|         # invalidate its import caches |         # invalidate its import caches | ||||||
|  | @ -606,12 +611,10 @@ class Testdir(object): | ||||||
|     def _possibly_invalidate_import_caches(self): |     def _possibly_invalidate_import_caches(self): | ||||||
|         # invalidate caches if we can (py33 and above) |         # invalidate caches if we can (py33 and above) | ||||||
|         try: |         try: | ||||||
|             import importlib |             from importlib import invalidate_caches | ||||||
|         except ImportError: |         except ImportError: | ||||||
|             pass |             return | ||||||
|         else: |         invalidate_caches() | ||||||
|             if hasattr(importlib, "invalidate_caches"): |  | ||||||
|                 importlib.invalidate_caches() |  | ||||||
| 
 | 
 | ||||||
|     def mkdir(self, name): |     def mkdir(self, name): | ||||||
|         """Create a new (sub)directory.""" |         """Create a new (sub)directory.""" | ||||||
|  |  | ||||||
|  | @ -34,8 +34,6 @@ class TestModule(object): | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def test_import_prepend_append(self, testdir, monkeypatch): |     def test_import_prepend_append(self, testdir, monkeypatch): | ||||||
|         syspath = list(sys.path) |  | ||||||
|         monkeypatch.setattr(sys, "path", syspath) |  | ||||||
|         root1 = testdir.mkdir("root1") |         root1 = testdir.mkdir("root1") | ||||||
|         root2 = testdir.mkdir("root2") |         root2 = testdir.mkdir("root2") | ||||||
|         root1.ensure("x456.py") |         root1.ensure("x456.py") | ||||||
|  |  | ||||||
|  | @ -1335,7 +1335,7 @@ class TestEarlyRewriteBailout(object): | ||||||
|         # Setup conditions for py's fspath trying to import pathlib on py34 |         # Setup conditions for py's fspath trying to import pathlib on py34 | ||||||
|         # always (previously triggered via xdist only). |         # always (previously triggered via xdist only). | ||||||
|         # Ref: https://github.com/pytest-dev/py/pull/207 |         # Ref: https://github.com/pytest-dev/py/pull/207 | ||||||
|         monkeypatch.setattr(sys, "path", [""] + sys.path) |         monkeypatch.syspath_prepend("") | ||||||
|         monkeypatch.delitem(sys.modules, "pathlib", raising=False) |         monkeypatch.delitem(sys.modules, "pathlib", raising=False) | ||||||
| 
 | 
 | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|  |  | ||||||
|  | @ -437,3 +437,28 @@ def test_context(): | ||||||
|         m.setattr(functools, "partial", 3) |         m.setattr(functools, "partial", 3) | ||||||
|         assert not inspect.isclass(functools.partial) |         assert not inspect.isclass(functools.partial) | ||||||
|     assert inspect.isclass(functools.partial) |     assert inspect.isclass(functools.partial) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_syspath_prepend_with_namespace_packages(testdir, monkeypatch): | ||||||
|  |     for dirname in "hello", "world": | ||||||
|  |         d = testdir.mkdir(dirname) | ||||||
|  |         ns = d.mkdir("ns_pkg") | ||||||
|  |         ns.join("__init__.py").write( | ||||||
|  |             "__import__('pkg_resources').declare_namespace(__name__)" | ||||||
|  |         ) | ||||||
|  |         lib = ns.mkdir(dirname) | ||||||
|  |         lib.join("__init__.py").write("def check(): return %r" % dirname) | ||||||
|  | 
 | ||||||
|  |     monkeypatch.syspath_prepend("hello") | ||||||
|  |     import ns_pkg.hello | ||||||
|  | 
 | ||||||
|  |     assert ns_pkg.hello.check() == "hello" | ||||||
|  | 
 | ||||||
|  |     with pytest.raises(ImportError): | ||||||
|  |         import ns_pkg.world | ||||||
|  | 
 | ||||||
|  |     # Prepending should call fixup_namespace_packages. | ||||||
|  |     monkeypatch.syspath_prepend("world") | ||||||
|  |     import ns_pkg.world | ||||||
|  | 
 | ||||||
|  |     assert ns_pkg.world.check() == "world" | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ from __future__ import division | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
| 
 | 
 | ||||||
| import os | import os | ||||||
| import re |  | ||||||
| import sys | import sys | ||||||
| import types | import types | ||||||
| 
 | 
 | ||||||
|  | @ -165,10 +164,10 @@ def test_importplugin_error_message(testdir, pytestpm): | ||||||
|     with pytest.raises(ImportError) as excinfo: |     with pytest.raises(ImportError) as excinfo: | ||||||
|         pytestpm.import_plugin("qwe") |         pytestpm.import_plugin("qwe") | ||||||
| 
 | 
 | ||||||
|     expected_message = '.*Error importing plugin "qwe": Not possible to import: .' |     assert str(excinfo.value).endswith( | ||||||
|     expected_traceback = ".*in test_traceback" |         'Error importing plugin "qwe": Not possible to import: ☺' | ||||||
|     assert re.match(expected_message, str(excinfo.value)) |     ) | ||||||
|     assert re.match(expected_traceback, str(excinfo.traceback[-1])) |     assert "in test_traceback" in str(excinfo.traceback[-1]) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TestPytestPluginManager(object): | class TestPytestPluginManager(object): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue