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:
holger krekel 2009-10-28 19:51:20 +01:00
parent 1f01fafec7
commit 86fc12dd15
5 changed files with 54 additions and 1 deletions

View File

@ -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:

View File

@ -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):

View File

@ -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

View File

@ -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")

View File

@ -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)