Deal with partially setup packages in the redirect hook.

This commit is contained in:
Armin Ronacher 2011-09-21 21:34:47 +02:00
parent ee9b401632
commit 9691b7f0bf
6 changed files with 49 additions and 7 deletions

View file

@ -57,6 +57,17 @@ class _ExtensionImporter(object):
__import__(realname)
except ImportError:
exc_type, exc_value, tb = exc_info()
# since we only establish the entry in sys.modules at the
# very this seems to be redundant, but if recursive imports
# happen we will call into the move import a second time.
# On the second invocation we still don't have an entry for
# fullname in sys.modules, but we will end up with the same
# fake module name and that import will succeed since this
# one already has a temporary entry in the modules dict.
# Since this one "succeeded" temporarily that second
# invocation now will have created a fullname entry in
# sys.modules which we have to kill.
modules.pop(fullname, None)
if self.is_important_traceback(realname, tb):
raise exc_type, exc_value, tb
continue

View file

@ -134,6 +134,32 @@ class FlaskTestCase(unittest.TestCase):
def assert_equal(self, x, y):
return self.assertEqual(x, y)
def assert_raises(self, exc_type, callable=None, *args, **kwargs):
catcher = _ExceptionCatcher(self, exc_type)
if callable is None:
return catcher
with catcher:
callable(*args, **kwargs)
class _ExceptionCatcher(object):
def __init__(self, test_case, exc_type):
self.test_case = test_case
self.exc_type = exc_type
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, tb):
exception_name = self.exc_type.__name__
if exc_type is None:
self.test_case.fail('Expected exception of type %r' %
exception_name)
elif not issubclass(exc_type, self.exc_type):
raise exc_type, exc_value, tb
return True
class BetterLoader(unittest.TestLoader):
"""A nicer loader that solves two problems. First of all we are setting

View file

@ -8,6 +8,8 @@
:copyright: (c) 2011 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from __future__ import with_statement
import sys
import unittest
from flask.testsuite import FlaskTestCase
@ -92,6 +94,11 @@ class ExtImportHookTestCase(FlaskTestCase):
from flask.ext.oldext_package.submodule import test_function
self.assert_equal(test_function(), 42)
def test_flaskext_broken_package_no_module_caching(self):
for x in xrange(2):
with self.assert_raises(ImportError):
import flask.ext.broken
def suite():
suite = unittest.TestSuite()

View file

@ -0,0 +1,2 @@
import flask.ext.broken.b
import missing_module