Ticket #11696: 20091107.diff

File 20091107.diff, 3.5 KB (added by Luc Saffre, 15 years ago)
  • django/db/models/loading.py

     
    88import sys
    99import os
    1010import threading
     11import imp
     12import traceback
    1113
    1214__all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
    1315        'load_app', 'app_cache_ready')
    1416
     17def module_exists(full_name,path=None):
     18    """
     19    tests whether the module exists but does not import it.
     20    see http://www.python.org/doc/current/library/imp.html#module-imp
     21    """
     22    a = full_name.split('.',1)
     23    if len(a) == 1:
     24        # simple module name without package
     25        try:
     26            (file, pathname, description) = imp.find_module(full_name,path)
     27            if file is not None: file.close()
     28        except ImportError,e:
     29            return False
     30        return True
     31    assert len(a) == 2
     32    (file, pathname, description) = imp.find_module(a[0],path)
     33    if description[-1] != imp.PKG_DIRECTORY:
     34        return False
     35    pkg = imp.load_module(a[0],file,pathname,description)
     36    if file is not None: file.close()
     37    return module_exists(a[1],pkg.__path__)
     38
     39
     40
     41
    1542class AppCache(object):
    1643    """
    1744    A cache that stores installed applications and their models. Used to
     
    5784                    continue
    5885                self.load_app(app_name, True)
    5986            if not self.nesting_level:
    60                 for app_name in self.postponed:
     87                postponed = self.postponed
     88                self.postponed = []
     89                for app_name,tb in postponed:
    6190                    self.load_app(app_name)
    6291                self.loaded = True
     92            if len(self.postponed):
     93                msg = ''.join(["%s:\n%s" % i for i in self.postponed])
     94                raise ImproperlyConfigured(
     95                    "Failed to import %d applications:\n%s" % (
     96                        len(self.postponed),msg))
    6397        finally:
    6498            self.write_lock.release()
    65 
     99           
    66100    def load_app(self, app_name, can_postpone=False):
    67101        """
    68102        Loads the app with the provided fully qualified name, and returns the
    69103        model module.
    70104        """
    71105        self.handled[app_name] = None
     106        if not module_exists(app_name + ".models"):
     107            # silently ignore applications without models
     108            #print "[DEBUG] application %s has no models" % app_name
     109            return None
    72110        self.nesting_level += 1
    73111        try:
    74112            models = import_module('.models', app_name)
    75         except ImportError:
     113        except ImportError,e:
    76114            self.nesting_level -= 1
     115            self.postponed.append( (app_name,traceback.format_exc(e)) )
    77116            if can_postpone:
    78                 # Either the app has no models, or the package is still being
     117                # The package is maybe still being
    79118                # imported by Python and the model module isn't available yet.
    80119                # We will check again once all the recursion has finished (in
    81120                # populate).
    82                 self.postponed.append(app_name)
    83             return None
     121                #print "[DEBUG] Postponing application %s:" % app_name
     122                #traceback.print_exc(e)
     123                return None
     124            traceback.print_exc(e)
     125            raise
    84126        self.nesting_level -= 1
    85127        if models not in self.app_store:
    86128            self.app_store[models] = len(self.app_store)
Back to Top