diff --git a/django/conf/urls/__init__.py b/django/conf/urls/__init__.py index 03879bccd4..45af3a10d2 100644 --- a/django/conf/urls/__init__.py +++ b/django/conf/urls/__init__.py @@ -1,4 +1,3 @@ -import warnings from importlib import import_module from django.core.exceptions import ImproperlyConfigured @@ -6,7 +5,6 @@ from django.urls import ( LocaleRegexURLResolver, RegexURLPattern, RegexURLResolver, ) from django.utils import six -from django.utils.deprecation import RemovedInDjango20Warning __all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'url'] @@ -16,16 +14,8 @@ handler404 = 'django.views.defaults.page_not_found' handler500 = 'django.views.defaults.server_error' -def include(arg, namespace=None, app_name=None): - if app_name and not namespace: - raise ValueError('Must specify a namespace if specifying app_name.') - if app_name: - warnings.warn( - 'The app_name argument to django.conf.urls.include() is deprecated. ' - 'Set the app_name in the included URLconf instead.', - RemovedInDjango20Warning, stacklevel=2 - ) - +def include(arg, namespace=None): + app_name = None if isinstance(arg, tuple): # callable returning a namespace hint try: @@ -35,13 +25,11 @@ def include(arg, namespace=None, app_name=None): raise ImproperlyConfigured( 'Cannot override the namespace for a dynamic module that provides a namespace' ) - warnings.warn( - 'Passing a 3-tuple to django.conf.urls.include() is deprecated. ' + raise ImproperlyConfigured( + 'Passing a 3-tuple to django.conf.urls.include() is not supported. ' 'Pass a 2-tuple containing the list of patterns and app_name, ' 'and provide the namespace argument to include() instead.', - RemovedInDjango20Warning, stacklevel=2 ) - urlconf_module, app_name, namespace = arg else: # No namespace hint - use manually provided namespace urlconf_module = arg @@ -51,12 +39,11 @@ def include(arg, namespace=None, app_name=None): patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module) app_name = getattr(urlconf_module, 'app_name', app_name) if namespace and not app_name: - warnings.warn( + raise ImproperlyConfigured( 'Specifying a namespace in django.conf.urls.include() without ' - 'providing an app_name is deprecated. Set the app_name attribute ' + 'providing an app_name is not supported. Set the app_name attribute ' 'in the included module, or pass a 2-tuple containing the list of ' 'patterns and app_name instead.', - RemovedInDjango20Warning, stacklevel=2 ) namespace = namespace or app_name diff --git a/docs/ref/urls.txt b/docs/ref/urls.txt index d1464da66d..505295ede4 100644 --- a/docs/ref/urls.txt +++ b/docs/ref/urls.txt @@ -53,10 +53,9 @@ parameter is useful. ``include()`` ============= -.. function:: include(module, namespace=None, app_name=None) +.. function:: include(module, namespace=None) include(pattern_list) include((pattern_list, app_namespace), namespace=None) - include((pattern_list, app_namespace, instance_namespace)) A function that takes a full Python import path to another URLconf module that should be "included" in this place. Optionally, the :term:`application @@ -68,15 +67,12 @@ parameter is useful. can be used to set a different instance namespace. ``include()`` also accepts as an argument either an iterable that returns - URL patterns, a 2-tuple containing such iterable plus the names of the - application namespaces, or a 3-tuple containing the iterable and the names - of both the application and instance namespace. + URL patterns or a 2-tuple containing such iterable plus the names of the + application namespaces. :arg module: URLconf module (or module name) :arg namespace: Instance namespace for the URL entries being included :type namespace: string - :arg app_name: Application namespace for the URL entries being included - :type app_name: string :arg pattern_list: Iterable of :func:`django.conf.urls.url` instances :arg app_namespace: Application namespace for the URL entries being included :type app_namespace: string @@ -85,20 +81,6 @@ parameter is useful. See :ref:`including-other-urlconfs` and :ref:`namespaces-and-include`. -.. deprecated:: 1.9 - - Support for the ``app_name`` argument is deprecated and will be removed in - Django 2.0. Specify the ``app_name`` as explained in - :ref:`namespaces-and-include` instead. - - Support for passing a 3-tuple is also deprecated and will be removed in - Django 2.0. Pass a 2-tuple containing the pattern list and application - namespace, and use the ``namespace`` argument instead. - - Lastly, support for an instance namespace without an application namespace - has been deprecated and will be removed in Django 2.0. Specify the - application namespace or remove the instance namespace. - ``handler400`` ============== diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt index 348572a75f..0ae25a8295 100644 --- a/docs/releases/2.0.txt +++ b/docs/releases/2.0.txt @@ -291,3 +291,11 @@ these features. * The ``mime_type`` attribute of ``django.utils.feedgenerator.Atom1Feed`` and ``django.utils.feedgenerator.RssFeed`` is removed. + +* The ``app_name`` argument to ``include()`` is removed. + +* Support for passing a 3-tuple as the first argument to ``include()`` is + removed. + +* Support for setting a URL instance namespace without an application namespace + is removed. diff --git a/tests/urlpatterns_reverse/included_namespace_urls.py b/tests/urlpatterns_reverse/included_namespace_urls.py index 4f68e4c602..75b0bf1971 100644 --- a/tests/urlpatterns_reverse/included_namespace_urls.py +++ b/tests/urlpatterns_reverse/included_namespace_urls.py @@ -6,6 +6,7 @@ from .views import empty_view, view_class_instance testobj3 = URLObject('testapp', 'test-ns3') testobj4 = URLObject('testapp', 'test-ns4') +app_name = 'included_namespace_urls' urlpatterns = [ url(r'^normal/$', empty_view, name='inc-normal-view'), url(r'^normal/(?P[0-9]+)/(?P[0-9]+)/$', empty_view, name='inc-normal-view'), @@ -17,8 +18,8 @@ urlpatterns = [ url(r'^view_class/(?P[0-9]+)/(?P[0-9]+)/$', view_class_instance, name='inc-view-class'), - url(r'^test3/', include(testobj3.urls)), - url(r'^test4/', include(testobj4.urls)), - url(r'^ns-included3/', include('urlpatterns_reverse.included_urls', namespace='inc-ns3')), + url(r'^test3/', include(*testobj3.urls)), + url(r'^test4/', include(*testobj4.urls)), + url(r'^ns-included3/', include(('urlpatterns_reverse.included_urls', 'included_urls'), namespace='inc-ns3')), url(r'^ns-included4/', include('urlpatterns_reverse.namespace_urls', namespace='inc-ns4')), ] diff --git a/tests/urlpatterns_reverse/namespace_urls.py b/tests/urlpatterns_reverse/namespace_urls.py index fa6359dec2..a92df2716a 100644 --- a/tests/urlpatterns_reverse/namespace_urls.py +++ b/tests/urlpatterns_reverse/namespace_urls.py @@ -12,6 +12,7 @@ otherobj2 = URLObject('nodefault', 'other-ns2') newappobj1 = URLObject('newapp') +app_name = 'namespace_urls' urlpatterns = [ url(r'^normal/$', views.empty_view, name='normal-view'), url(r'^normal/(?P[0-9]+)/(?P[0-9]+)/$', views.empty_view, name='normal-view'), @@ -27,12 +28,12 @@ urlpatterns = [ url(r'^unnamed/normal/(?P[0-9]+)/(?P[0-9]+)/$', views.empty_view), url(r'^unnamed/view_class/(?P[0-9]+)/(?P[0-9]+)/$', views.view_class_instance), - url(r'^test1/', include(testobj1.urls)), - url(r'^test2/', include(testobj2.urls)), - url(r'^default/', include(default_testobj.urls)), + url(r'^test1/', include(*testobj1.urls)), + url(r'^test2/', include(*testobj2.urls)), + url(r'^default/', include(*default_testobj.urls)), - url(r'^other1/', include(otherobj1.urls)), - url(r'^other[246]/', include(otherobj2.urls)), + url(r'^other1/', include(*otherobj1.urls)), + url(r'^other[246]/', include(*otherobj2.urls)), url(r'^newapp1/', include(newappobj1.app_urls, 'new-ns1')), url(r'^new-default/', include(newappobj1.app_urls)), @@ -43,10 +44,12 @@ urlpatterns = [ url(r'^ns-included[135]/', include('urlpatterns_reverse.included_namespace_urls', namespace='inc-ns1')), url(r'^ns-included2/', include('urlpatterns_reverse.included_namespace_urls', namespace='inc-ns2')), - url(r'^app-included/', include('urlpatterns_reverse.included_namespace_urls', 'inc-app', 'inc-app')), + url(r'^app-included/', include('urlpatterns_reverse.included_namespace_urls', 'inc-app')), url(r'^included/', include('urlpatterns_reverse.included_namespace_urls')), - url(r'^inc(?P[0-9]+)/', include('urlpatterns_reverse.included_urls', namespace='inc-ns5')), + url( + r'^inc(?P[0-9]+)/', include(('urlpatterns_reverse.included_urls', 'included_urls'), namespace='inc-ns5') + ), url(r'^included/([0-9]+)/', include('urlpatterns_reverse.included_namespace_urls')), url( diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py index b332ac4f7e..5f824469fa 100644 --- a/tests/urlpatterns_reverse/tests.py +++ b/tests/urlpatterns_reverse/tests.py @@ -18,16 +18,13 @@ from django.http import ( HttpRequest, HttpResponsePermanentRedirect, HttpResponseRedirect, ) from django.shortcuts import redirect -from django.test import ( - SimpleTestCase, TestCase, ignore_warnings, override_settings, -) +from django.test import SimpleTestCase, TestCase, override_settings from django.test.utils import override_script_prefix from django.urls import ( NoReverseMatch, RegexURLPattern, RegexURLResolver, Resolver404, ResolverMatch, get_callable, get_resolver, resolve, reverse, reverse_lazy, ) from django.utils import six -from django.utils.deprecation import RemovedInDjango20Warning from . import middleware, urlconf_outer, views from .utils import URLObject @@ -42,23 +39,27 @@ resolve_test_data = ( {'arg1': '42', 'arg2': '37'} ), ( - '/included/normal/42/37/', 'inc-normal-view', '', '', 'inc-normal-view', views.empty_view, tuple(), - {'arg1': '42', 'arg2': '37'} + '/included/normal/42/37/', 'inc-normal-view', 'included_namespace_urls', + 'included_namespace_urls', 'included_namespace_urls:inc-normal-view', + views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'} ), ( - '/included/view_class/42/37/', 'inc-view-class', '', '', 'inc-view-class', views.view_class_instance, tuple(), - {'arg1': '42', 'arg2': '37'} + '/included/view_class/42/37/', 'inc-view-class', 'included_namespace_urls', + 'included_namespace_urls', 'included_namespace_urls: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', '', '', 'mixed-args', views.empty_view, tuple(), {'arg2': '37'}), ( - '/included/mixed_args/42/37/', 'inc-mixed-args', '', '', 'inc-mixed-args', views.empty_view, tuple(), - {'arg2': '37'} + '/included/mixed_args/42/37/', 'inc-mixed-args', 'included_namespace_urls', + 'included_namespace_urls', 'included_namespace_urls:inc-mixed-args', + views.empty_view, tuple(), {'arg2': '37'} ), ( - '/included/12/mixed_args/42/37/', 'inc-mixed-args', '', '', 'inc-mixed-args', views.empty_view, tuple(), - {'arg2': '37'} + '/included/12/mixed_args/42/37/', 'inc-mixed-args', 'included_namespace_urls', + 'included_namespace_urls', 'included_namespace_urls:inc-mixed-args', + views.empty_view, tuple(), {'arg2': '37'} ), # Unnamed views should have None as the url_name. Regression data for #21157. @@ -73,10 +74,15 @@ resolve_test_data = ( # If you have no kwargs, you get an args list. ('/no_kwargs/42/37/', 'no-kwargs', '', '', 'no-kwargs', views.empty_view, ('42', '37'), {}), - ('/included/no_kwargs/42/37/', 'inc-no-kwargs', '', '', 'inc-no-kwargs', views.empty_view, ('42', '37'), {}), ( - '/included/12/no_kwargs/42/37/', 'inc-no-kwargs', '', '', 'inc-no-kwargs', views.empty_view, - ('12', '42', '37'), {} + '/included/no_kwargs/42/37/', 'inc-no-kwargs', 'included_namespace_urls', + 'included_namespace_urls', 'included_namespace_urls:inc-no-kwargs', + views.empty_view, ('42', '37'), {} + ), + ( + '/included/12/no_kwargs/42/37/', 'inc-no-kwargs', 'included_namespace_urls', + 'included_namespace_urls', 'included_namespace_urls:inc-no-kwargs', + views.empty_view, ('12', '42', '37'), {} ), # Namespaces @@ -85,20 +91,23 @@ resolve_test_data = ( views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'} ), ( - '/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'test-ns3:urlobject-view', + '/included/test3/inner/42/37/', 'urlobject-view', 'included_namespace_urls:testapp', + 'included_namespace_urls:test-ns3', 'included_namespace_urls:test-ns3:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'} ), ( - '/ns-included1/normal/42/37/', 'inc-normal-view', '', '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', + '/ns-included1/normal/42/37/', 'inc-normal-view', 'included_namespace_urls', + 'inc-ns1', 'inc-ns1:inc-normal-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'} + '/included/test3/inner/42/37/', 'urlobject-view', 'included_namespace_urls:testapp', + 'included_namespace_urls:test-ns3', 'included_namespace_urls: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', @@ -111,29 +120,37 @@ resolve_test_data = ( # Nested namespaces ( - '/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/test3/inner/42/37/', 'urlobject-view', 'included_namespace_urls: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'} + '/ns-included1/ns-included4/ns-included2/test3/inner/42/37/', 'urlobject-view', + 'included_namespace_urls:namespace_urls:included_namespace_urls: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'} ), ( - '/app-included/test3/inner/42/37/', 'urlobject-view', 'inc-app:testapp', 'inc-app:test-ns3', + '/app-included/test3/inner/42/37/', 'urlobject-view', 'included_namespace_urls:testapp', 'inc-app:test-ns3', 'inc-app:test-ns3:urlobject-view', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'} ), ( - '/app-included/ns-included4/ns-included2/test3/inner/42/37/', 'urlobject-view', 'inc-app:testapp', - 'inc-app:inc-ns4:inc-ns2:test-ns3', 'inc-app:inc-ns4:inc-ns2:test-ns3:urlobject-view', views.empty_view, - tuple(), {'arg1': '42', 'arg2': '37'} + '/app-included/ns-included4/ns-included2/test3/inner/42/37/', 'urlobject-view', + 'included_namespace_urls:namespace_urls:included_namespace_urls:testapp', + 'inc-app:inc-ns4:inc-ns2:test-ns3', + 'inc-app:inc-ns4:inc-ns2:test-ns3:urlobject-view', + views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'} ), # Namespaces capturing variables - ('/inc70/', 'inner-nothing', '', 'inc-ns5', 'inc-ns5:inner-nothing', views.empty_view, tuple(), {'outer': '70'}), ( - '/inc78/extra/foobar/', 'inner-extra', '', 'inc-ns5', 'inc-ns5:inner-extra', views.empty_view, tuple(), - {'outer': '78', 'extra': 'foobar'} + '/inc70/', 'inner-nothing', 'included_urls', 'inc-ns5', 'inc-ns5:inner-nothing', + views.empty_view, tuple(), {'outer': '70'} + ), + ( + '/inc78/extra/foobar/', 'inner-extra', 'included_urls', 'inc-ns5', 'inc-ns5:inner-extra', + views.empty_view, tuple(), {'outer': '78', 'extra': 'foobar'} ), ) @@ -355,7 +372,6 @@ class URLPatternReverse(SimpleTestCase): class ResolverTests(SimpleTestCase): - @ignore_warnings(category=RemovedInDjango20Warning) def test_resolver_repr(self): """ Test repr of RegexURLResolver, especially when urlconf_name is a list @@ -576,7 +592,6 @@ class ReverseShortcutTests(SimpleTestCase): @override_settings(ROOT_URLCONF='urlpatterns_reverse.namespace_urls') -@ignore_warnings(category=RemovedInDjango20Warning) class NamespaceTests(SimpleTestCase): def test_ambiguous_object(self): @@ -613,10 +628,13 @@ class NamespaceTests(SimpleTestCase): def test_simple_included_name(self): "Normal lookups work on names included from other patterns" - self.assertEqual('/included/normal/', reverse('inc-normal-view')) - self.assertEqual('/included/normal/37/42/', reverse('inc-normal-view', args=[37, 42])) - self.assertEqual('/included/normal/42/37/', reverse('inc-normal-view', kwargs={'arg1': 42, 'arg2': 37})) - self.assertEqual('/included/+%5C$*/', reverse('inc-special-view')) + self.assertEqual('/included/normal/', reverse('included_namespace_urls:inc-normal-view')) + self.assertEqual('/included/normal/37/42/', reverse('included_namespace_urls:inc-normal-view', args=[37, 42])) + self.assertEqual( + '/included/normal/42/37/', + reverse('included_namespace_urls:inc-normal-view', kwargs={'arg1': 42, 'arg2': 37}) + ) + self.assertEqual('/included/+%5C$*/', reverse('included_namespace_urls:inc-special-view')) def test_namespace_object(self): "Dynamic URL objects can be found using a namespace" @@ -643,12 +661,17 @@ class NamespaceTests(SimpleTestCase): def test_embedded_namespace_object(self): "Namespaces can be installed anywhere in the URL pattern tree" - self.assertEqual('/included/test3/inner/', reverse('test-ns3:urlobject-view')) - self.assertEqual('/included/test3/inner/37/42/', reverse('test-ns3:urlobject-view', args=[37, 42])) + self.assertEqual('/included/test3/inner/', reverse('included_namespace_urls:test-ns3:urlobject-view')) self.assertEqual( - '/included/test3/inner/42/37/', reverse('test-ns3:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}) + '/included/test3/inner/37/42/', reverse('included_namespace_urls:test-ns3:urlobject-view', args=[37, 42]) + ) + self.assertEqual( + '/included/test3/inner/42/37/', + reverse('included_namespace_urls:test-ns3:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}) + ) + self.assertEqual( + '/included/test3/inner/+%5C$*/', reverse('included_namespace_urls:test-ns3:urlobject-special-view') ) - self.assertEqual('/included/test3/inner/+%5C$*/', reverse('test-ns3:urlobject-special-view')) def test_namespace_pattern(self): "Namespaces can be applied to include()'d urlpatterns" @@ -718,17 +741,17 @@ class NamespaceTests(SimpleTestCase): def test_app_lookup_object_with_default(self): "A default application namespace is sensitive to the 'current' app can be used for lookup" - self.assertEqual('/included/test3/inner/', reverse('testapp:urlobject-view', current_app='test-ns3')) + self.assertEqual('/default/inner/', reverse('testapp:urlobject-view', current_app='test-ns3')) self.assertEqual( - '/included/test3/inner/37/42/', + '/default/inner/37/42/', reverse('testapp:urlobject-view', args=[37, 42], current_app='test-ns3') ) self.assertEqual( - '/included/test3/inner/42/37/', + '/default/inner/42/37/', reverse('testapp:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}, current_app='test-ns3') ) self.assertEqual( - '/included/test3/inner/+%5C$*/', reverse('testapp:urlobject-special-view', current_app='test-ns3') + '/default/inner/+%5C$*/', reverse('testapp:urlobject-special-view', current_app='test-ns3') ) def test_app_lookup_object_without_default(self): @@ -749,13 +772,16 @@ class NamespaceTests(SimpleTestCase): self.assertEqual('/other1/inner/+%5C$*/', reverse('nodefault:urlobject-special-view', current_app='other-ns1')) def test_special_chars_namespace(self): - self.assertEqual('/+%5C$*/included/normal/', reverse('special:inc-normal-view')) - self.assertEqual('/+%5C$*/included/normal/37/42/', reverse('special:inc-normal-view', args=[37, 42])) + self.assertEqual('/+%5C$*/included/normal/', reverse('special:included_namespace_urls:inc-normal-view')) + self.assertEqual( + '/+%5C$*/included/normal/37/42/', + reverse('special:included_namespace_urls:inc-normal-view', args=[37, 42]) + ) self.assertEqual( '/+%5C$*/included/normal/42/37/', - reverse('special:inc-normal-view', kwargs={'arg1': 42, 'arg2': 37}) + reverse('special:included_namespace_urls:inc-normal-view', kwargs={'arg1': 42, 'arg2': 37}) ) - self.assertEqual('/+%5C$*/included/+%5C$*/', reverse('special:inc-special-view')) + self.assertEqual('/+%5C$*/included/+%5C$*/', reverse('special:included_namespace_urls:inc-special-view')) def test_namespaces_with_variables(self): "Namespace prefixes can capture variables: see #15900" @@ -965,7 +991,6 @@ class NoRootUrlConfTests(SimpleTestCase): @override_settings(ROOT_URLCONF='urlpatterns_reverse.namespace_urls') class ResolverMatchTests(SimpleTestCase): - @ignore_warnings(category=RemovedInDjango20Warning) def test_urlpattern_resolve(self): for path, url_name, app_name, namespace, view_name, func, args, kwargs in resolve_test_data: # Test legacy support for extracting "function, args, kwargs" @@ -990,7 +1015,6 @@ class ResolverMatchTests(SimpleTestCase): self.assertEqual(match[1], args) self.assertEqual(match[2], kwargs) - @ignore_warnings(category=RemovedInDjango20Warning) def test_resolver_match_on_request(self): response = self.client.get('/resolver_match/') resolver_match = response.resolver_match @@ -1042,34 +1066,21 @@ class IncludeTests(SimpleTestCase): ] app_urls = URLObject('inc-app') - def test_include_app_name_but_no_namespace(self): - msg = "Must specify a namespace if specifying app_name." - with self.assertRaisesMessage(ValueError, msg): - include(self.url_patterns, app_name='bar') - def test_include_urls(self): self.assertEqual(include(self.url_patterns), (self.url_patterns, None, None)) - @ignore_warnings(category=RemovedInDjango20Warning) def test_include_namespace(self): - # no app_name -> deprecated - self.assertEqual(include(self.url_patterns, 'namespace'), (self.url_patterns, None, 'namespace')) - - @ignore_warnings(category=RemovedInDjango20Warning) - def test_include_namespace_app_name(self): - # app_name argument to include -> deprecated - self.assertEqual( - include(self.url_patterns, 'namespace', 'app_name'), - (self.url_patterns, 'app_name', 'namespace') + msg = ( + "Specifying a namespace in django.conf.urls.include() without " + "providing an app_name is not supported." ) + with self.assertRaisesMessage(ImproperlyConfigured, msg): + include(self.url_patterns, 'namespace') - @ignore_warnings(category=RemovedInDjango20Warning) def test_include_3_tuple(self): - # 3-tuple -> deprecated - self.assertEqual( - include((self.url_patterns, 'app_name', 'namespace')), - (self.url_patterns, 'app_name', 'namespace') - ) + msg = 'Passing a 3-tuple to django.conf.urls.include() is not supported.' + with self.assertRaisesMessage(ImproperlyConfigured, msg): + include((self.url_patterns, 'app_name', 'namespace')) def test_include_2_tuple(self): self.assertEqual( diff --git a/tests/urlpatterns_reverse/utils.py b/tests/urlpatterns_reverse/utils.py index 6c3fe8a31d..adcb310fa5 100644 --- a/tests/urlpatterns_reverse/utils.py +++ b/tests/urlpatterns_reverse/utils.py @@ -18,7 +18,7 @@ class URLObject(object): @property def urls(self): - return self.urlpatterns, self.app_name, self.namespace + return (self.urlpatterns, self.app_name), self.namespace @property def app_urls(self):