forked from orbit-oss/flask
Deal with partially setup packages in the redirect hook.
This commit is contained in:
parent
ee9b401632
commit
9691b7f0bf
6 changed files with 49 additions and 7 deletions
|
|
@ -57,6 +57,17 @@ class _ExtensionImporter(object):
|
||||||
__import__(realname)
|
__import__(realname)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
exc_type, exc_value, tb = exc_info()
|
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):
|
if self.is_important_traceback(realname, tb):
|
||||||
raise exc_type, exc_value, tb
|
raise exc_type, exc_value, tb
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,32 @@ class FlaskTestCase(unittest.TestCase):
|
||||||
def assert_equal(self, x, y):
|
def assert_equal(self, x, y):
|
||||||
return self.assertEqual(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):
|
class BetterLoader(unittest.TestLoader):
|
||||||
"""A nicer loader that solves two problems. First of all we are setting
|
"""A nicer loader that solves two problems. First of all we are setting
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
:copyright: (c) 2011 by Armin Ronacher.
|
:copyright: (c) 2011 by Armin Ronacher.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from flask.testsuite import FlaskTestCase
|
from flask.testsuite import FlaskTestCase
|
||||||
|
|
@ -92,6 +94,11 @@ class ExtImportHookTestCase(FlaskTestCase):
|
||||||
from flask.ext.oldext_package.submodule import test_function
|
from flask.ext.oldext_package.submodule import test_function
|
||||||
self.assert_equal(test_function(), 42)
|
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():
|
def suite():
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
|
|
|
||||||
2
flask/testsuite/test_apps/flask_broken/__init__.py
Normal file
2
flask/testsuite/test_apps/flask_broken/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
import flask.ext.broken.b
|
||||||
|
import missing_module
|
||||||
0
flask/testsuite/test_apps/flask_broken/b.py
Normal file
0
flask/testsuite/test_apps/flask_broken/b.py
Normal file
|
|
@ -25,7 +25,8 @@ ext_module.__package__ = ext_module.__name__
|
||||||
|
|
||||||
class _ExtensionImporter(object):
|
class _ExtensionImporter(object):
|
||||||
"""This importer redirects imports from the flask.ext module to other
|
"""This importer redirects imports from the flask.ext module to other
|
||||||
locations.
|
locations. For implementation details see the code in Flask 0.8
|
||||||
|
that does the same.
|
||||||
"""
|
"""
|
||||||
_module_choices = ['flask_%s', 'flaskext.%s']
|
_module_choices = ['flask_%s', 'flaskext.%s']
|
||||||
prefix = ext_module.__name__ + '.'
|
prefix = ext_module.__name__ + '.'
|
||||||
|
|
@ -45,6 +46,7 @@ class _ExtensionImporter(object):
|
||||||
__import__(realname)
|
__import__(realname)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
exc_type, exc_value, tb = sys.exc_info()
|
exc_type, exc_value, tb = sys.exc_info()
|
||||||
|
sys.modules.pop(fullname, None)
|
||||||
if self.is_important_traceback(realname, tb):
|
if self.is_important_traceback(realname, tb):
|
||||||
raise exc_type, exc_value, tb
|
raise exc_type, exc_value, tb
|
||||||
continue
|
continue
|
||||||
|
|
@ -55,12 +57,6 @@ class _ExtensionImporter(object):
|
||||||
raise ImportError('No module named %s' % fullname)
|
raise ImportError('No module named %s' % fullname)
|
||||||
|
|
||||||
def is_important_traceback(self, important_module, tb):
|
def is_important_traceback(self, important_module, tb):
|
||||||
"""Walks a traceback's frames and checks if any of the frames
|
|
||||||
originated in the given important module. If that is the case
|
|
||||||
then we were able to import the module itself but apparently
|
|
||||||
something went wrong when the module was imported. (Eg: import
|
|
||||||
of an import failed).
|
|
||||||
"""
|
|
||||||
while tb is not None:
|
while tb is not None:
|
||||||
if tb.tb_frame.f_globals.get('__name__') == important_module:
|
if tb.tb_frame.f_globals.get('__name__') == important_module:
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue