Skip to content

Commit 51f64c2

Browse files
authored
Merge pull request #4980 from blueyed/fixup_namespace_packages
monkeypatch.syspath_prepend: call fixup_namespace_packages
2 parents 2df9d05 + fd64fa1 commit 51f64c2

File tree

7 files changed

+46
-15
lines changed

7 files changed

+46
-15
lines changed

changelog/4980.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Namespace packages are handled better with ``monkeypatch.syspath_prepend`` and ``testdir.syspathinsert`` (via ``pkg_resources.fixup_namespace_packages``).

src/_pytest/monkeypatch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,15 @@ def delenv(self, name, raising=True):
262262

263263
def syspath_prepend(self, path):
264264
""" Prepend ``path`` to ``sys.path`` list of import locations. """
265+
from pkg_resources import fixup_namespace_packages
266+
265267
if self._savesyspath is None:
266268
self._savesyspath = sys.path[:]
267269
sys.path.insert(0, str(path))
268270

271+
# https://github.com/pypa/setuptools/blob/d8b901bc/docs/pkg_resources.txt#L162-L171
272+
fixup_namespace_packages(str(path))
273+
269274
def chdir(self, path):
270275
""" Change the current working directory to the specified path.
271276
Path can be a string or a py.path.local object.

src/_pytest/pytester.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,11 +593,16 @@ def syspathinsert(self, path=None):
593593
594594
This is undone automatically when this object dies at the end of each
595595
test.
596-
597596
"""
597+
from pkg_resources import fixup_namespace_packages
598+
598599
if path is None:
599600
path = self.tmpdir
600-
sys.path.insert(0, str(path))
601+
602+
dirname = str(path)
603+
sys.path.insert(0, dirname)
604+
fixup_namespace_packages(dirname)
605+
601606
# a call to syspathinsert() usually means that the caller wants to
602607
# import some dynamically created files, thus with python3 we
603608
# invalidate its import caches
@@ -606,12 +611,10 @@ def syspathinsert(self, path=None):
606611
def _possibly_invalidate_import_caches(self):
607612
# invalidate caches if we can (py33 and above)
608613
try:
609-
import importlib
614+
from importlib import invalidate_caches
610615
except ImportError:
611-
pass
612-
else:
613-
if hasattr(importlib, "invalidate_caches"):
614-
importlib.invalidate_caches()
616+
return
617+
invalidate_caches()
615618

616619
def mkdir(self, name):
617620
"""Create a new (sub)directory."""

testing/python/collect.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ def test_import_duplicate(self, testdir):
3434
)
3535

3636
def test_import_prepend_append(self, testdir, monkeypatch):
37-
syspath = list(sys.path)
38-
monkeypatch.setattr(sys, "path", syspath)
3937
root1 = testdir.mkdir("root1")
4038
root2 = testdir.mkdir("root2")
4139
root1.ensure("x456.py")

testing/test_assertrewrite.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ def test_cwd_changed(self, testdir, monkeypatch):
13351335
# Setup conditions for py's fspath trying to import pathlib on py34
13361336
# always (previously triggered via xdist only).
13371337
# Ref: https://github.com/pytest-dev/py/pull/207
1338-
monkeypatch.setattr(sys, "path", [""] + sys.path)
1338+
monkeypatch.syspath_prepend("")
13391339
monkeypatch.delitem(sys.modules, "pathlib", raising=False)
13401340

13411341
testdir.makepyfile(

testing/test_monkeypatch.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,28 @@ def test_context():
437437
m.setattr(functools, "partial", 3)
438438
assert not inspect.isclass(functools.partial)
439439
assert inspect.isclass(functools.partial)
440+
441+
442+
def test_syspath_prepend_with_namespace_packages(testdir, monkeypatch):
443+
for dirname in "hello", "world":
444+
d = testdir.mkdir(dirname)
445+
ns = d.mkdir("ns_pkg")
446+
ns.join("__init__.py").write(
447+
"__import__('pkg_resources').declare_namespace(__name__)"
448+
)
449+
lib = ns.mkdir(dirname)
450+
lib.join("__init__.py").write("def check(): return %r" % dirname)
451+
452+
monkeypatch.syspath_prepend("hello")
453+
import ns_pkg.hello
454+
455+
assert ns_pkg.hello.check() == "hello"
456+
457+
with pytest.raises(ImportError):
458+
import ns_pkg.world
459+
460+
# Prepending should call fixup_namespace_packages.
461+
monkeypatch.syspath_prepend("world")
462+
import ns_pkg.world
463+
464+
assert ns_pkg.world.check() == "world"

testing/test_pluginmanager.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from __future__ import print_function
55

66
import os
7-
import re
87
import sys
98
import types
109

@@ -165,10 +164,10 @@ def test_traceback():
165164
with pytest.raises(ImportError) as excinfo:
166165
pytestpm.import_plugin("qwe")
167166

168-
expected_message = '.*Error importing plugin "qwe": Not possible to import: .'
169-
expected_traceback = ".*in test_traceback"
170-
assert re.match(expected_message, str(excinfo.value))
171-
assert re.match(expected_traceback, str(excinfo.traceback[-1]))
167+
assert str(excinfo.value).endswith(
168+
'Error importing plugin "qwe": Not possible to import: ☺'
169+
)
170+
assert "in test_traceback" in str(excinfo.traceback[-1])
172171

173172

174173
class TestPytestPluginManager(object):

0 commit comments

Comments
 (0)