Commit 367bfaa5 authored by Florian Apolloner's avatar Florian Apolloner
Browse files

Don't swallow AttributeError in core.urlresolvers.get_callable.

parent 37c93187
Loading
Loading
Loading
Loading
+16 −11
Original line number Diff line number Diff line
@@ -89,18 +89,11 @@ def get_callable(lookup_view, can_fail=False):
    """
    if not callable(lookup_view):
        mod_name, func_name = get_mod_func(lookup_view)
        if func_name == '':
            return lookup_view

        try:
            if func_name != '':
                lookup_view = getattr(import_module(mod_name), func_name)
                if not callable(lookup_view):
                    raise ViewDoesNotExist(
                        "Could not import %s.%s. View is not callable." %
                        (mod_name, func_name))
        except AttributeError:
            if not can_fail:
                raise ViewDoesNotExist(
                    "Could not import %s. View does not exist in module %s." %
                    (lookup_view, mod_name))
            mod = import_module(mod_name)
        except ImportError:
            parentmod, submod = get_mod_func(mod_name)
            if (not can_fail and submod != '' and
@@ -110,6 +103,18 @@ def get_callable(lookup_view, can_fail=False):
                    (lookup_view, mod_name))
            if not can_fail:
                raise
        else:
            try:
                lookup_view = getattr(mod, func_name)
                if not callable(lookup_view):
                    raise ViewDoesNotExist(
                        "Could not import %s.%s. View is not callable." %
                        (mod_name, func_name))
            except AttributeError:
                if not can_fail:
                    raise ViewDoesNotExist(
                        "Could not import %s. View does not exist in module %s." %
                        (lookup_view, mod_name))
    return lookup_view
get_callable = memoize(get_callable, _callable_cache, 1)

+16 −2
Original line number Diff line number Diff line
@@ -5,8 +5,9 @@ from __future__ import absolute_import, unicode_literals

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.core.urlresolvers import (reverse, resolve, NoReverseMatch,
    Resolver404, ResolverMatch, RegexURLResolver, RegexURLPattern)
from django.core.urlresolvers import (reverse, resolve, get_callable,
    NoReverseMatch, Resolver404, ResolverMatch, RegexURLResolver,
    RegexURLPattern)
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
from django.shortcuts import redirect
from django.test import TestCase
@@ -519,3 +520,16 @@ class ErroneousViewTests(TestCase):
        """
        # The regex error will be hit before NoReverseMatch can be raised
        self.assertRaises(ImproperlyConfigured, reverse, 'whatever blah blah')

class ViewLoadingTests(TestCase):
    def test_view_loading(self):
        # A missing view (identified by an AttributeError) should raise
        # ViewDoesNotExist, ...
        self.assertRaisesRegexp(ViewDoesNotExist, ".*View does not exist in.*",
            get_callable,
            'regressiontests.urlpatterns_reverse.views.i_should_not_exist')
        # ... but if the AttributeError is caused by something else don't
        # swallow it.
        self.assertRaises(AttributeError, get_callable,
            'regressiontests.urlpatterns_reverse.views_broken.i_am_broken')
+2 −0
Original line number Diff line number Diff line
# I just raise an AttributeError to confuse the view loading mechanism
raise AttributeError('I am here to confuse django.core.urlresolvers.get_callable')