Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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

  • Loading branch information...
commit 367bfaa5226eaae3278989e63f16063d5cc46cd8 1 parent 37c9318
@apollo13 apollo13 authored
View
27 django/core/urlresolvers.py
@@ -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)
View
18 tests/regressiontests/urlpatterns_reverse/tests.py
@@ -5,8 +5,9 @@
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 @@ def test_erroneous_reverse(self):
"""
# 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')
+
View
2  tests/regressiontests/urlpatterns_reverse/views_broken.py
@@ -0,0 +1,2 @@
+# I just raise an AttributeError to confuse the view loading mechanism
+raise AttributeError('I am here to confuse django.core.urlresolvers.get_callable')
Please sign in to comment.
Something went wrong with that request. Please try again.