Ticket #8809: django8809-urlerror.2.diff

File django8809-urlerror.2.diff, 8.2 KB (added by Bas Peschier, 13 years ago)
  • django/core/urlresolvers.py

     
    162162            return self._callback
    163163        try:
    164164            self._callback = get_callable(self._callback_str)
    165         except ImportError, e:
    166             mod_name, _ = get_mod_func(self._callback_str)
    167             raise ViewDoesNotExist("Could not import %s. Error was: %s" % (mod_name, str(e)))
    168         except AttributeError, e:
     165        except (ImportError, AttributeError), e:
    169166            mod_name, func_name = get_mod_func(self._callback_str)
    170             raise ViewDoesNotExist("Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e)))
     167            debug_info = ''
     168            if settings.DEBUG:
     169                if hasattr(self, '_origin_line'): # extra debug info available
     170                    debug_info = ' from line "%s" at %s:%s' % self._origin_line
     171                elif hasattr(self, '_origin_module'):
     172                    debug_info = ' from pattern "%s" in %s' % ((self.regex.pattern,) + self._origin_module)
     173            if isinstance(e, ImportError):
     174                raise ViewDoesNotExist("Could not import %s%s. Error was: %s" % (mod_name, debug_info, str(e)))
     175            elif isinstance(e, AttributeError):
     176                raise ViewDoesNotExist("Tried %s in module %s%s. Error was: %s" % (func_name, mod_name, debug_info, str(e)))
    171177        return self._callback
    172178    callback = property(_get_callback)
    173179
  • django/conf/urls/defaults.py

     
     1from django.conf import settings
    12from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
    23from django.core.exceptions import ImproperlyConfigured
    34
     
    1718        urlconf_module = arg
    1819    return (urlconf_module, app_name, namespace)
    1920
     21def _get_pattern_origin(urlobj):
     22    """ Finds out which module called this pattern/url for debug purposes. """
     23    import inspect
     24    import os.path
     25    current_frame = inspect.currentframe()
     26    if current_frame: # currentframe not always supported
     27        calling_frames = inspect.getouterframes(current_frame)
     28        index = 0
     29        while calling_frames[index][3] != '<module>': # find the module
     30            index = index + 1
     31        calling_frame = calling_frames[index]
     32        if index == 2: # direct call from url(), get line details
     33            urlobj._origin_line = (calling_frame[4], os.path.normpath(calling_frame[1]), calling_frame[2], )
     34        else: # url() created by patterns(), only show module
     35            urlobj._origin_module = (os.path.normpath(calling_frame[1]), )
     36
    2037def patterns(prefix, *args):
    2138    pattern_list = []
    2239    for t in args:
     
    3148    if isinstance(view, (list,tuple)):
    3249        # For include(...) processing.
    3350        urlconf_module, app_name, namespace = view
    34         return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
     51        urlobj = RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
    3552    else:
    3653        if isinstance(view, basestring):
    3754            if not view:
    3855                raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
    3956            if prefix:
    4057                view = prefix + '.' + view
    41         return RegexURLPattern(regex, view, kwargs, name)
     58        urlobj = RegexURLPattern(regex, view, kwargs, name)
    4259
     60    if settings.DEBUG: # attach debug information to object
     61        _get_pattern_origin(urlobj)
     62    return urlobj
     63
  • tests/regressiontests/urlpatterns_errors/tests.py

     
     1from django.conf import settings
     2from django.core.urlresolvers import RegexURLResolver, ViewDoesNotExist
     3from django.test import TestCase
     4
     5class URLPatternErrorsTestsNonSpecific(TestCase):
     6    urls = 'regressiontests.urlpatterns_errors.urls'
     7
     8    def assertRaisesErrorWithStart(self, error, message, callable,
     9        *args, **kwargs):
     10        self.assertRaises(error, callable, *args, **kwargs)
     11        try:
     12            callable(*args, **kwargs)
     13        except error, e: # check start of message only
     14            self.assertEqual(message, str(e)[:len(message)])
     15
     16    def test_resolve_errors_nonspecific(self):
     17        """
     18        Resolver should raise exceptions pointing only divulging
     19        basic information
     20        """
     21       
     22        olddebug = settings.DEBUG
     23        settings.DEBUG = False
     24
     25        resolver = RegexURLResolver(r'^', self.urls)
     26
     27        # Import errors
     28        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     29            "Could not import nonexistent. Error was:", resolver.resolve,
     30            'first-urled/')
     31        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     32            "Could not import nonexistent. Error was:", resolver.resolve,
     33            'second-nonurled/')
     34
     35        # Attribute errors
     36        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     37            "Tried nonexistent in module regressiontests.urlpatterns_errors.views.",
     38            resolver.resolve, 'third-urled/')
     39        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     40            "Tried nonexistent in module regressiontests.urlpatterns_errors.views.",
     41            resolver.resolve, 'fourth-nonurled/')
     42
     43        settings.DEBUG = olddebug
     44
     45class URLPatternErrorsSpecificTests(TestCase):
     46    urls = 'regressiontests.urlpatterns_errors.urls'
     47
     48    def assertRaisesErrorWithStart(self, error, message, callable,
     49        *args, **kwargs):
     50        self.assertRaises(error, callable, *args, **kwargs)
     51        try:
     52            callable(*args, **kwargs)
     53        except error, e: # check start of message only
     54            self.assertEqual(message, str(e)[:len(message)])
     55
     56    def test_resolve_errors_specific(self):
     57        """
     58        Resolver should raise exceptions pointing to the urls module
     59        if that information is available
     60        """
     61       
     62        olddebug = settings.DEBUG
     63        settings.DEBUG = True
     64
     65        resolver = RegexURLResolver(r'^', self.urls)
     66
     67        # Import errors
     68        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     69            "Could not import nonexistent from line", resolver.resolve,
     70            'first-urled/')
     71        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     72            "Could not import nonexistent from pattern", resolver.resolve,
     73            'second-nonurled/')
     74
     75        # Attribute errors
     76        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     77            "Tried nonexistent in module regressiontests.urlpatterns_errors.views from line",
     78            resolver.resolve, 'third-urled/')
     79        self.assertRaisesErrorWithStart(ViewDoesNotExist,
     80            "Tried nonexistent in module regressiontests.urlpatterns_errors.views from pattern",
     81            resolver.resolve, 'fourth-nonurled/')
     82
     83        settings.DEBUG = olddebug
  • tests/regressiontests/urlpatterns_errors/urls.py

     
     1from django.conf.urls.defaults import url, patterns
     2
     3urlpatterns = patterns('',
     4    url(r'^first-urled/$', 'nonexistent.view'),
     5    (r'^second-nonurled/$', 'nonexistent.view'),
     6    url(r'^third-urled/$', 'regressiontests.urlpatterns_errors.views.nonexistent'),
     7    (r'^fourth-nonurled/$', 'regressiontests.urlpatterns_errors.views.nonexistent'),
     8)
Back to Top