mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #21157 -- Fixed problems with ResolverMatch
- Fixed bug in get_callable() that caused resolve() to put a string in ResolverMatch.func. - Made ResolverMatch.url_name match the actual url name (or None). - Updated tests that used the string value in ResolverMatch.func, and added regression tests for this bug. - Corrected test urls whose dummy view paths caused failures (behavior that was previously masked by this bug).
This commit is contained in:
committed by
Tim Graham
parent
0aa4c6c391
commit
91afc00513
@@ -25,41 +25,41 @@ from .views import empty_view
|
||||
|
||||
|
||||
resolve_test_data = (
|
||||
# These entries are in the format: (path, url_name, app_name, namespace, view_func, args, kwargs)
|
||||
# These entries are in the format: (path, url_name, app_name, namespace, view_name, func, args, kwargs)
|
||||
# Simple case
|
||||
('/normal/42/37/', 'normal-view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/view_class/42/37/', 'view-class', None, '', views.view_class_instance, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/normal/42/37/', 'inc-normal-view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/view_class/42/37/', 'inc-view-class', None, '', views.view_class_instance, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/normal/42/37/', 'normal-view', None, '', 'normal-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/view_class/42/37/', 'view-class', None, '', 'view-class', views.view_class_instance, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/normal/42/37/', 'inc-normal-view', None, '', 'inc-normal-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/view_class/42/37/', 'inc-view-class', None, '', 'inc-view-class', views.view_class_instance, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
|
||||
# Unnamed args are dropped if you have *any* kwargs in a pattern
|
||||
('/mixed_args/42/37/', 'mixed-args', None, '', views.empty_view, tuple(), {'arg2': '37'}),
|
||||
('/included/mixed_args/42/37/', 'inc-mixed-args', None, '', views.empty_view, tuple(), {'arg2': '37'}),
|
||||
('/mixed_args/42/37/', 'mixed-args', None, '', 'mixed-args', views.empty_view, tuple(), {'arg2': '37'}),
|
||||
('/included/mixed_args/42/37/', 'inc-mixed-args', None, '', 'inc-mixed-args', views.empty_view, tuple(), {'arg2': '37'}),
|
||||
|
||||
# Unnamed views will be resolved to the function/class name
|
||||
('/unnamed/normal/42/37/', 'urlpatterns_reverse.views.empty_view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/unnamed/view_class/42/37/', 'urlpatterns_reverse.views.ViewClass', None, '', views.view_class_instance, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
# Unnamed views should have None as the url_name. Regression data for #21157.
|
||||
('/unnamed/normal/42/37/', None, None, '', 'urlpatterns_reverse.views.empty_view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/unnamed/view_class/42/37/', None, None, '', 'urlpatterns_reverse.views.ViewClass', views.view_class_instance, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
|
||||
# If you have no kwargs, you get an args list.
|
||||
('/no_kwargs/42/37/', 'no-kwargs', None, '', views.empty_view, ('42', '37'), {}),
|
||||
('/included/no_kwargs/42/37/', 'inc-no-kwargs', None, '', views.empty_view, ('42', '37'), {}),
|
||||
('/no_kwargs/42/37/', 'no-kwargs', None, '', 'no-kwargs', views.empty_view, ('42', '37'), {}),
|
||||
('/included/no_kwargs/42/37/', 'inc-no-kwargs', None, '', 'inc-no-kwargs', views.empty_view, ('42', '37'), {}),
|
||||
|
||||
# Namespaces
|
||||
('/test1/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns1', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/ns-included1/normal/42/37/', 'inc-normal-view', None, 'inc-ns1', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/default/inner/42/37/', 'urlobject-view', 'testapp', 'testapp', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/other2/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns2', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/other1/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns1', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/test1/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns1', 'test-ns1:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'test-ns3:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/ns-included1/normal/42/37/', 'inc-normal-view', None, 'inc-ns1', 'inc-ns1:inc-normal-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'test-ns3:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/default/inner/42/37/', 'urlobject-view', 'testapp', 'testapp', 'testapp:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/other2/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns2', 'other-ns2:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/other1/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns1', 'other-ns1:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
|
||||
# Nested namespaces
|
||||
('/ns-included1/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/ns-included1/ns-included4/ns-included2/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:inc-ns4:inc-ns2:test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/ns-included1/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:test-ns3', 'inc-ns1:test-ns3:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
('/ns-included1/ns-included4/ns-included2/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:inc-ns4:inc-ns2:test-ns3', 'inc-ns1:inc-ns4:inc-ns2:test-ns3:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}),
|
||||
|
||||
# Namespaces capturing variables
|
||||
('/inc70/', 'inner-nothing', None, 'inc-ns5', views.empty_view, tuple(), {'outer': '70'}),
|
||||
('/inc78/extra/foobar/', 'inner-extra', None, 'inc-ns5', views.empty_view, tuple(), {'outer': '78', 'extra': 'foobar'}),
|
||||
('/inc70/', 'inner-nothing', None, 'inc-ns5', 'inc-ns5:inner-nothing', views.empty_view, tuple(), {'outer': '70'}),
|
||||
('/inc78/extra/foobar/', 'inner-extra', None, 'inc-ns5', 'inc-ns5:inner-extra', views.empty_view, tuple(), {'outer': '78', 'extra': 'foobar'}),
|
||||
)
|
||||
|
||||
test_data = (
|
||||
@@ -141,8 +141,6 @@ test_data = (
|
||||
# once with an explicit argument, and once using the default value on
|
||||
# the method. This is potentially ambiguous, as you have to pick the
|
||||
# correct view for the arguments provided.
|
||||
('kwargs_view', '/arg_view/', [], {}),
|
||||
('kwargs_view', '/arg_view/10/', [], {'arg1': 10}),
|
||||
('urlpatterns_reverse.views.absolute_kwargs_view', '/absolute_arg_view/', [], {}),
|
||||
('urlpatterns_reverse.views.absolute_kwargs_view', '/absolute_arg_view/10/', [], {'arg1': 10}),
|
||||
('non_path_include', '/includes/non_path_include/', [], {}),
|
||||
@@ -603,7 +601,6 @@ class ErrorHandlerResolutionTests(TestCase):
|
||||
"""Tests for handler400, handler404 and handler500"""
|
||||
|
||||
def setUp(self):
|
||||
from django.core.urlresolvers import RegexURLResolver
|
||||
urlconf = 'urlpatterns_reverse.urls_error_handlers'
|
||||
urlconf_callables = 'urlpatterns_reverse.urls_error_handlers_callables'
|
||||
self.resolver = RegexURLResolver(r'^$', urlconf)
|
||||
@@ -651,7 +648,7 @@ class NoRootUrlConfTests(TestCase):
|
||||
class ResolverMatchTests(TestCase):
|
||||
|
||||
def test_urlpattern_resolve(self):
|
||||
for path, name, app_name, namespace, func, args, kwargs in resolve_test_data:
|
||||
for path, url_name, app_name, namespace, view_name, func, args, kwargs in resolve_test_data:
|
||||
# Test legacy support for extracting "function, args, kwargs"
|
||||
match_func, match_args, match_kwargs = resolve(path)
|
||||
self.assertEqual(match_func, func)
|
||||
@@ -661,12 +658,13 @@ class ResolverMatchTests(TestCase):
|
||||
# Test ResolverMatch capabilities.
|
||||
match = resolve(path)
|
||||
self.assertEqual(match.__class__, ResolverMatch)
|
||||
self.assertEqual(match.url_name, name)
|
||||
self.assertEqual(match.args, args)
|
||||
self.assertEqual(match.kwargs, kwargs)
|
||||
self.assertEqual(match.url_name, url_name)
|
||||
self.assertEqual(match.app_name, app_name)
|
||||
self.assertEqual(match.namespace, namespace)
|
||||
self.assertEqual(match.view_name, view_name)
|
||||
self.assertEqual(match.func, func)
|
||||
self.assertEqual(match.args, args)
|
||||
self.assertEqual(match.kwargs, kwargs)
|
||||
|
||||
# ... and for legacy purposes:
|
||||
self.assertEqual(match[0], func)
|
||||
@@ -693,6 +691,9 @@ class ErroneousViewTests(TestCase):
|
||||
self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_outer/')
|
||||
self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable/')
|
||||
|
||||
# Regression test for #21157
|
||||
self.assertRaises(ImportError, self.client.get, '/erroneous_unqualified/')
|
||||
|
||||
def test_erroneous_reverse(self):
|
||||
"""
|
||||
Ensure that a useful exception is raised when a regex is invalid in the
|
||||
|
||||
Reference in New Issue
Block a user