resolves issue #59
resolves issue #48 Have the path.pyimport() helper raise an EnvironmentError if an import of a given file returns a module that does not appear to be coming from the actual path. E.g. for a directory layout like this: a / test_whatever.py b / test_whatever.py calling py.path.local("b/test_whatever.py").pyimport() will fail if the other globally scoped test_whatever module was loaded already. --HG-- branch : trunk
This commit is contained in:
parent
1f01fafec7
commit
86fc12dd15
|
@ -516,7 +516,16 @@ class LocalPath(FSBase):
|
|||
self._prependsyspath(self.dirpath())
|
||||
modname = self.purebasename
|
||||
mod = __import__(modname, None, None, ['__doc__'])
|
||||
#self._module = mod
|
||||
modfile = mod.__file__
|
||||
if modfile[-4:] in ('.pyc', '.pyo'):
|
||||
modfile = modfile[:-1]
|
||||
elif modfile.endswith('$py.class'):
|
||||
modfile = modfile[:-9] + '.py'
|
||||
if not self.samefile(modfile):
|
||||
raise EnvironmentError("mismatch:\n"
|
||||
"imported module %r\n"
|
||||
"does not stem from %r\n"
|
||||
"maybe __init__.py files are missing?" % (mod, str(self)))
|
||||
return mod
|
||||
else:
|
||||
try:
|
||||
|
|
|
@ -70,6 +70,12 @@ class TmpTestdir:
|
|||
py.std.sys.path.remove(p)
|
||||
if hasattr(self, '_olddir'):
|
||||
self._olddir.chdir()
|
||||
# delete modules that have been loaded from tmpdir
|
||||
for name, mod in list(sys.modules.items()):
|
||||
if mod:
|
||||
fn = getattr(mod, '__file__', None)
|
||||
if fn and fn.startswith(str(self.tmpdir)):
|
||||
del sys.modules[name]
|
||||
|
||||
def getreportrecorder(self, obj):
|
||||
if isinstance(obj, py._com.Registry):
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
Changes between 1.0.2 and '1.1.0b1'
|
||||
=====================================
|
||||
|
||||
* fix issue48 and issue59: raise an Error if the module
|
||||
from an imported test file does not seem to come from
|
||||
the filepath - avoids "same-name" confusion that has
|
||||
been reported repeatedly
|
||||
|
||||
* merged Ronny's nose-compatibility hacks: now
|
||||
nose-style setup_module() and setup() functions are
|
||||
supported
|
||||
|
|
|
@ -336,6 +336,27 @@ class TestImport:
|
|||
from xxxpackage import module1
|
||||
assert module1 is mod1
|
||||
|
||||
def test_pyimport_check_filepath_consistency(self, monkeypatch, tmpdir):
|
||||
name = 'pointsback123'
|
||||
ModuleType = type(py.std.sys)
|
||||
p = tmpdir.ensure(name + '.py')
|
||||
for ending in ('.pyc', '$py.class', '.pyo'):
|
||||
mod = ModuleType(name)
|
||||
pseudopath = tmpdir.ensure(name+ending)
|
||||
mod.__file__ = str(pseudopath)
|
||||
monkeypatch.setitem(sys.modules, name, mod)
|
||||
newmod = p.pyimport()
|
||||
assert mod == newmod
|
||||
monkeypatch.undo()
|
||||
mod = ModuleType(name)
|
||||
pseudopath = tmpdir.ensure(name+"123.py")
|
||||
mod.__file__ = str(pseudopath)
|
||||
monkeypatch.setitem(sys.modules, name, mod)
|
||||
excinfo = py.test.raises(EnvironmentError, "p.pyimport()")
|
||||
s = str(excinfo.value)
|
||||
assert "mismatch" in s
|
||||
assert name+"123" in s
|
||||
|
||||
def test_pypkgdir(tmpdir):
|
||||
pkg = tmpdir.ensure('pkg1', dir=1)
|
||||
pkg.ensure("__init__.py")
|
||||
|
|
|
@ -16,6 +16,18 @@ class TestModule:
|
|||
py.test.raises(ImportError, modcol.collect)
|
||||
py.test.raises(ImportError, modcol.run)
|
||||
|
||||
def test_import_duplicate(self, testdir):
|
||||
a = testdir.mkdir("a")
|
||||
b = testdir.mkdir("b")
|
||||
p = a.ensure("test_whatever.py")
|
||||
p.pyimport()
|
||||
del py.std.sys.modules['test_whatever']
|
||||
b.ensure("test_whatever.py")
|
||||
result = testdir.runpytest()
|
||||
s = result.stdout.str()
|
||||
assert 'mismatch' in s
|
||||
assert 'test_whatever' in s
|
||||
|
||||
def test_syntax_error_in_module(self, testdir):
|
||||
modcol = testdir.getmodulecol("this is a syntax error")
|
||||
py.test.raises(SyntaxError, modcol.collect)
|
||||
|
|
Loading…
Reference in New Issue