From 9a70e62b8d545c8de7e3728e544cebe289a39254 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 21 Sep 2011 03:47:36 +0200 Subject: [PATCH] No longer swallow important import errors. This implements a simple but elegant method to find out if an import error can be swallowed to try the next module or if the import error is important and must be reraised. --- flask/ext/__init__.py | 20 ++++++++++++++++++-- scripts/flaskext_compat.py | 18 +++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/flask/ext/__init__.py b/flask/ext/__init__.py index 14c8d8d4..d030336f 100644 --- a/flask/ext/__init__.py +++ b/flask/ext/__init__.py @@ -47,7 +47,7 @@ class _ExtensionImporter(object): return self def load_module(self, fullname): - from sys import modules + from sys import modules, exc_info if fullname in modules: return modules[fullname] modname = fullname.split('.', self.prefix_cutoff)[self.prefix_cutoff] @@ -56,12 +56,28 @@ class _ExtensionImporter(object): try: __import__(realname) except ImportError: + exc_type, exc_value, tb = exc_info() + if self.is_important_traceback(realname, tb): + raise exc_type, exc_value, tb continue module = modules[fullname] = modules[realname] if '.' not in modname: setattr(modules[__name__], modname, module) return module - raise ImportError(fullname) + raise ImportError('No module named %s' % fullname) + + 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: + if tb.tb_frame.f_globals.get('__name__') == important_module: + return True + tb = tb.tb_next + return False _ExtensionImporter() diff --git a/scripts/flaskext_compat.py b/scripts/flaskext_compat.py index 03601a1a..f0b1739d 100644 --- a/scripts/flaskext_compat.py +++ b/scripts/flaskext_compat.py @@ -44,12 +44,28 @@ class _ExtensionImporter(object): try: __import__(realname) except ImportError: + exc_type, exc_value, tb = sys.exc_info() + if self.is_important_traceback(realname, tb): + raise exc_type, exc_value, tb continue module = sys.modules[fullname] = sys.modules[realname] if '.' not in modname: setattr(ext_module, modname, module) return module - raise ImportError(fullname) + raise ImportError('No module named %s' % fullname) + + 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: + if tb.tb_frame.f_globals.get('__name__') == important_module: + return True + tb = tb.tb_next + return False def activate():