diff --git a/VERSION b/VERSION index 15e51e7f..42bb24cb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 14:16:37) dev +Version 2.1.0 (2012-10-14 14:20:09) dev diff --git a/gluon/custom_import.py b/gluon/custom_import.py index 4ba79f26..b924ae83 100644 --- a/gluon/custom_import.py +++ b/gluon/custom_import.py @@ -9,11 +9,11 @@ import threading import traceback from gluon import current -NAIVE_IMPORTER = __builtin__.__import__ +NATIVE_IMPORTER = __builtin__.__import__ TRACK_CHANGES = False INVALID_MODULES = set(sys.modules.keys()).union(('','gluon','applications','custom_import')) -# backward compatibility API +# backward compatibility API def custom_import_install(): __builtin__.__import__ = custom_importer @@ -22,14 +22,17 @@ def track_changes(track=True): global TRACK_CHANGES TRACK_CHANGES = track -def is_tracking_changes(): +def is_tracking_changes(): return TRACK_CHANGES +class CustomImportException(ImportError): + pass + def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): """ The web2py custom importer. Like the standard Python importer but it tries to transform import statements as something like - "import applications.app_name.modules.x". + "import applications.app_name.modules.x". If the import failed, fall back on naive_importer """ @@ -37,13 +40,14 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): locals = locals or {} fromlist = fromlist or [] - base_importer = TRACK_IMPORTER if TRACK_CHANGES else NAIVE_IMPORTER + base_importer = TRACK_IMPORTER if TRACK_CHANGES else NATIVE_IMPORTER # if not relative and not from applications: if hasattr(current,'request') \ and level<=0 \ and not name.split('.')[0] in INVALID_MODULES \ - and isinstance(globals, dict): + and isinstance(globals, dict): + import_tb = None try: items = current.request.folder.split(os.path.sep) if not items[-1]: items = items[:-1] @@ -52,23 +56,27 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): # import like "import x" or "import x.y" result = None for itemname in name.split("."): - new_mod = base_importer( - modules_prefix, globals,locals, [itemname], level) - try: - result = result or new_mod.__dict__[itemname] - except KeyError, e: - raise ImportError, 'Cannot import module %s' % str(e) modules_prefix += "." + itemname + base_importer( + modules_prefix, globals,locals, [], level) return result else: # import like "from x import a, b, ..." pname = modules_prefix + "." + name return base_importer(pname, globals, locals, fromlist, level) except ImportError, e1: - pass # the module does not exist + import_tb = sys.exc_info()[2] + try: + return NATIVE_IMPORTER(name,globals,locals,fromlist,level) + except ImportError, e3: + raise ImportError, e1, import_tb.tb_next # there an import error in the module except Exception, e2: raise e2 # there is an error in the module - return NAIVE_IMPORTER(name,globals,locals,fromlist,level) + finally: + if import_tb: + import_tb = None + + return NATIVE_IMPORTER(name,globals,locals,fromlist,level) class TrackImporter(object): @@ -96,7 +104,7 @@ class TrackImporter(object): # Check the date and reload if needed: self._update_dates(name, globals, locals, fromlist, level) # Try to load the module and update the dates if it works: - result = NAIVE_IMPORTER(name, globals, locals, fromlist, level) + result = NATIVE_IMPORTER(name, globals, locals, fromlist, level) # Module maybe loaded for the 1st time so we need to set the date self._update_dates(name, globals, locals, fromlist, level) return result @@ -152,7 +160,7 @@ class TrackImporter(object): mod_name = module.__name__ del sys.modules[mod_name] # Delete the module # Reload the module: - NAIVE_IMPORTER(mod_name, globals, locals, [], level) + NATIVE_IMPORTER(mod_name, globals, locals, [], level) else: reload(module) self.THREAD_LOCAL._modules_loaded.add(module)