summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2015-08-17 13:45:07 -0400
committerTim Graham <timograham@gmail.com>2015-09-23 19:31:09 -0400
commit785cc71d5b3300e2702b0b2fc7316e58ca70b563 (patch)
treedc526b6b3df79c0da82694f0879713f33c0dee3c
parentd79122f40ba2016b1a943e2e1ba46984b2ef99ad (diff)
Refs #22384 -- Removed the ability to reverse URLs by dotted path per deprecation timeline.
-rw-r--r--django/conf/urls/__init__.py4
-rw-r--r--django/core/urlresolvers.py124
-rw-r--r--docs/ref/templates/builtins.txt7
-rw-r--r--docs/ref/urlresolvers.txt23
-rw-r--r--tests/gis_tests/geoapp/test_sitemaps.py12
-rw-r--r--tests/resolve_url/tests.py14
-rw-r--r--tests/sitemaps_tests/test_http.py24
-rw-r--r--tests/sitemaps_tests/test_https.py17
-rw-r--r--tests/template_tests/syntax_tests/test_url.py69
-rw-r--r--tests/template_tests/urls.py8
-rw-r--r--tests/urlpatterns_reverse/erroneous_urls.py29
-rw-r--r--tests/urlpatterns_reverse/erroneous_views_module.py5
-rw-r--r--tests/urlpatterns_reverse/tests.py45
-rw-r--r--tests/urlpatterns_reverse/urls.py6
-rw-r--r--tests/urlpatterns_reverse/views.py4
15 files changed, 93 insertions, 298 deletions
diff --git a/django/conf/urls/__init__.py b/django/conf/urls/__init__.py
index f9cd305ece..512d6f79e0 100644
--- a/django/conf/urls/__init__.py
+++ b/django/conf/urls/__init__.py
@@ -79,5 +79,7 @@ def url(regex, view, kwargs=None, name=None):
# For include(...) processing.
urlconf_module, app_name, namespace = view
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
- else:
+ elif callable(view):
return RegexURLPattern(regex, view, kwargs, name)
+ else:
+ raise TypeError('view must be a callable or a list/tuple in the case of include().')
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index 81aa9bb7ca..303901048a 100644
--- a/django/core/urlresolvers.py
+++ b/django/core/urlresolvers.py
@@ -9,7 +9,6 @@ from __future__ import unicode_literals
import functools
import re
-import warnings
from importlib import import_module
from threading import local
@@ -17,7 +16,6 @@ from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.http import Http404
from django.utils import lru_cache, six
from django.utils.datastructures import MultiValueDict
-from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_str, force_text, iri_to_uri
from django.utils.functional import cached_property, lazy
from django.utils.http import RFC3986_SUBDELIMS, urlquote
@@ -80,67 +78,50 @@ class NoReverseMatch(Exception):
@lru_cache.lru_cache(maxsize=None)
-def get_callable(lookup_view, can_fail=False):
+def get_callable(lookup_view):
"""
- Return a callable corresponding to lookup_view. This function is used
- by both resolve() and reverse(), so can_fail allows the caller to choose
- between returning the input as is and raising an exception when the input
- string can't be interpreted as an import path.
+ Return a callable corresponding to lookup_view.
- If lookup_view is already a callable, return it.
- If lookup_view is a string import path that can be resolved to a callable,
- import that callable and return it.
- If lookup_view is some other kind of string and can_fail is True, the string
- is returned as is. If can_fail is False, an exception is raised (either
- ImportError or ViewDoesNotExist).
+ * If lookup_view is already a callable, return it.
+ * If lookup_view is a string import path that can be resolved to a callable,
+ import that callable and return it, otherwise raise an exception
+ (ImportError or ViewDoesNotExist).
"""
if callable(lookup_view):
return lookup_view
if not isinstance(lookup_view, six.string_types):
- raise ViewDoesNotExist(
- "'%s' is not a callable or a dot-notation path" % lookup_view
- )
+ raise ViewDoesNotExist("'%s' is not a callable or a dot-notation path" % lookup_view)
mod_name, func_name = get_mod_func(lookup_view)
if not func_name: # No '.' in lookup_view
- if can_fail:
- return lookup_view
- else:
- raise ImportError(
- "Could not import '%s'. The path must be fully qualified." %
- lookup_view)
+ raise ImportError("Could not import '%s'. The path must be fully qualified." % lookup_view)
try:
mod = import_module(mod_name)
except ImportError:
- if can_fail:
- return lookup_view
+ parentmod, submod = get_mod_func(mod_name)
+ if submod and not module_has_submodule(import_module(parentmod), submod):
+ raise ViewDoesNotExist(
+ "Could not import '%s'. Parent module %s does not exist." %
+ (lookup_view, mod_name)
+ )
else:
- parentmod, submod = get_mod_func(mod_name)
- if submod and not module_has_submodule(import_module(parentmod), submod):
- raise ViewDoesNotExist(
- "Could not import '%s'. Parent module %s does not exist." %
- (lookup_view, mod_name))
- else:
- raise
+ raise
else:
try:
view_func = getattr(mod, func_name)
except AttributeError:
- if can_fail:
- return lookup_view
- else:
- raise ViewDoesNotExist(
- "Could not import '%s'. View does not exist in module %s." %
- (lookup_view, mod_name))
+ raise ViewDoesNotExist(
+ "Could not import '%s'. View does not exist in module %s." %
+ (lookup_view, mod_name)
+ )
else:
if not callable(view_func):
- # For backwards compatibility this is raised regardless of can_fail
raise ViewDoesNotExist(
"Could not import '%s.%s'. View is not callable." %
- (mod_name, func_name))
-
+ (mod_name, func_name)
+ )
return view_func
@@ -209,14 +190,7 @@ class LocaleRegexProvider(object):
class RegexURLPattern(LocaleRegexProvider):
def __init__(self, regex, callback, default_args=None, name=None):
LocaleRegexProvider.__init__(self, regex)
- # callback is either a string like 'foo.views.news.stories.story_detail'
- # which represents the path to a module and a view function name, or a
- # callable object (view).
- if callable(callback):
- self._callback = callback
- else:
- self._callback = None
- self._callback_str = callback
+ self.callback = callback # the view
self.default_args = default_args or {}
self.name = name
@@ -239,13 +213,19 @@ class RegexURLPattern(LocaleRegexProvider):
return ResolverMatch(self.callback, args, kwargs, self.name)
- @property
- def callback(self):
- if self._callback is not None:
- return self._callback
-
- self._callback = get_callable(self._callback_str)
- return self._callback
+ @cached_property
+ def lookup_str(self):
+ """
+ A string that identifies the view (e.g. 'path.to.view_function' or
+ 'path.to.ClassBasedView').
+ """
+ callback = self.callback
+ if isinstance(callback, functools.partial):
+ callback = callback.func
+ if not hasattr(callback, '__name__'):
+ return callback.__module__ + "." + callback.__class__.__name__
+ else:
+ return callback.__module__ + "." + callback.__name__
class RegexURLResolver(LocaleRegexProvider):
@@ -283,18 +263,8 @@ class RegexURLResolver(LocaleRegexProvider):
apps = {}
language_code = get_language()
for pattern in reversed(self.url_patterns):
- if hasattr(pattern, '_callback_str'):
- self._callback_strs.add(pattern._callback_str)
- elif hasattr(pattern, '_callback'):
- callback = pattern._callback
- if isinstance(callback, functools.partial):
- callback = callback.func
-
- if not hasattr(callback, '__name__'):
- lookup_str = callback.__module__ + "." + callback.__class__.__name__
- else:
- lookup_str = callback.__module__ + "." + callback.__name__
- self._callback_strs.add(lookup_str)
+ if isinstance(pattern, RegexURLPattern):
+ self._callback_strs.add(pattern.lookup_str)
p_pattern = pattern.regex.pattern
if p_pattern.startswith('^'):
p_pattern = p_pattern[1:]
@@ -427,9 +397,6 @@ class RegexURLResolver(LocaleRegexProvider):
callback = getattr(urls, 'handler%s' % view_type)
return get_callable(callback), {}
- def reverse(self, lookup_view, *args, **kwargs):
- return self._reverse_with_prefix(lookup_view, '', *args, **kwargs)
-
def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
if args and kwargs:
raise ValueError("Don't mix *args and **kwargs in call to reverse()!")
@@ -439,18 +406,6 @@ class RegexURLResolver(LocaleRegexProvider):
if not self._populated:
self._populate()
- original_lookup = lookup_view
- try:
- if self._is_callback(lookup_view):
- lookup_view = get_callable(lookup_view, True)
- except (ImportError, AttributeError) as e:
- raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e))
- else:
- if not callable(original_lookup) and callable(lookup_view):
- warnings.warn(
- 'Reversing by dotted path is deprecated (%s).' % original_lookup,
- RemovedInDjango110Warning, stacklevel=3
- )
possibilities = self.reverse_dict.getlist(lookup_view)
for possibility, pattern, defaults in possibilities:
@@ -484,9 +439,8 @@ class RegexURLResolver(LocaleRegexProvider):
if url.startswith('//'):
url = '/%%2F%s' % url[2:]
return url
- # lookup_view can be URL label, or dotted path, or callable, Any of
- # these can be passed in at the top, but callables are not friendly in
- # error messages.
+ # lookup_view can be URL name or callable, but callables are not
+ # friendly in error messages.
m = getattr(lookup_view, '__module__', None)
n = getattr(lookup_view, '__name__', None)
if m is not None and n is not None:
diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
index a21dd75caf..9bf22e4740 100644
--- a/docs/ref/templates/builtins.txt
+++ b/docs/ref/templates/builtins.txt
@@ -1051,13 +1051,6 @@ This will follow the normal :ref:`namespaced URL resolution strategy
<topics-http-reversing-url-namespaces>`, including using any hints provided
by the context as to the current application.
-.. deprecated:: 1.8
-
- You can also pass a dotted Python path to a view function, but this syntax
- is deprecated and will be removed in Django 1.10::
-
- {% url 'path.to.some_view' v1 v2 %}
-
.. warning::
Don't forget to put quotes around the :func:`~django.conf.urls.url`
diff --git a/docs/ref/urlresolvers.txt b/docs/ref/urlresolvers.txt
index 8e9634c31d..116aa4fcd0 100644
--- a/docs/ref/urlresolvers.txt
+++ b/docs/ref/urlresolvers.txt
@@ -12,9 +12,8 @@ your code, Django provides the following function:
.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
-``viewname`` can be a string containing the Python path to the view object, a
-:ref:`URL pattern name <naming-url-patterns>`, or the callable view object.
-For example, given the following ``url``::
+``viewname`` can be a :ref:`URL pattern name <naming-url-patterns>` or the
+callable view object. For example, given the following ``url``::
from news import views
@@ -63,24 +62,6 @@ namespaces into URLs on specific application instances, according to the
The ``urlconf`` argument is the URLconf module containing the url patterns to
use for reversing. By default, the root URLconf for the current thread is used.
-.. deprecated:: 1.8
-
- The ability to reverse using the Python path, e.g.
- ``reverse('news.views.archive')``, has been deprecated.
-
-.. admonition:: Make sure your views are all correct.
-
- As part of working out which URL names map to which patterns, the
- ``reverse()`` function has to import all of your URLconf files and examine
- the name of each view. This involves importing each view function. If
- there are *any* errors whilst importing any of your view functions, it
- will cause ``reverse()`` to raise an error, even if that view function is
- not the one you are trying to reverse.
-
- Make sure that any views you reference in your URLconf files exist and can
- be imported correctly. Do not include lines that reference views you
- haven't written yet, because those views will not be importable.
-
.. note::
The string returned by ``reverse()`` is already
diff --git a/tests/gis_tests/geoapp/test_sitemaps.py b/tests/gis_tests/geoapp/test_sitemaps.py
index 5162b11c77..e17a48a624 100644
--- a/tests/gis_tests/geoapp/test_sitemaps.py
+++ b/tests/gis_tests/geoapp/test_sitemaps.py
@@ -7,10 +7,8 @@ from xml.dom import minidom
from django.conf import settings
from django.contrib.sites.models import Site
from django.test import (
- TestCase, ignore_warnings, modify_settings, override_settings,
- skipUnlessDBFeature,
+ TestCase, modify_settings, override_settings, skipUnlessDBFeature,
)
-from django.utils.deprecation import RemovedInDjango110Warning
from .models import City, Country
@@ -30,17 +28,9 @@ class GeoSitemapTest(TestCase):
expected = set(expected)
self.assertEqual(actual, expected)
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_geositemap_kml(self):
"Tests KML/KMZ geographic sitemaps."
for kml_type in ('kml', 'kmz'):
- # The URL for the sitemaps in urls.py have been updated
- # with a name but since reversing by Python path is tried first
- # before reversing by name and works since we're giving
- # name='django.contrib.gis.sitemaps.views.(kml|kmz)', we need
- # to silence the erroneous warning until reversing by dotted
- # path is removed. The test will work without modification when
- # it's removed.
doc = minidom.parseString(self.client.get('/sitemaps/%s.xml' % kml_type).content)
# Ensuring the right sitemaps namespace is present.
diff --git a/tests/resolve_url/tests.py b/tests/resolve_url/tests.py
index d0c9d74abe..52e800a8c0 100644
--- a/tests/resolve_url/tests.py
+++ b/tests/resolve_url/tests.py
@@ -3,9 +3,8 @@ from __future__ import unicode_literals
from django.contrib.auth.views import logout
from django.core.urlresolvers import NoReverseMatch, reverse_lazy
from django.shortcuts import resolve_url
-from django.test import SimpleTestCase, ignore_warnings, override_settings
+from django.test import SimpleTestCase, override_settings
from django.utils import six
-from django.utils.deprecation import RemovedInDjango110Warning
from .models import UnimportantThing
@@ -51,8 +50,8 @@ class ResolveUrlTests(SimpleTestCase):
def test_view_function(self):
"""
- Tests that passing a view name to ``resolve_url`` will result in the
- URL path mapping to that view name.
+ Tests that passing a view function to ``resolve_url`` will result in
+ the URL path mapping to that view name.
"""
resolved_url = resolve_url(logout)
self.assertEqual('/accounts/logout/', resolved_url)
@@ -66,13 +65,12 @@ class ResolveUrlTests(SimpleTestCase):
self.assertIsInstance(resolved_url, six.text_type)
self.assertEqual('/accounts/logout/', resolved_url)
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_valid_view_name(self):
"""
- Tests that passing a view function to ``resolve_url`` will result in
- the URL path mapping to that view.
+ Tests that passing a view name to ``resolve_url`` will result in the
+ URL path mapping to that view.
"""
- resolved_url = resolve_url('django.contrib.auth.views.logout')
+ resolved_url = resolve_url('logout')
self.assertEqual('/accounts/logout/', resolved_url)
def test_domain(self):
diff --git a/tests/sitemaps_tests/test_http.py b/tests/sitemaps_tests/test_http.py
index a6bc46e03a..399cd35ae6 100644
--- a/tests/sitemaps_tests/test_http.py
+++ b/tests/sitemaps_tests/test_http.py
@@ -9,9 +9,8 @@ from django.conf import settings
from django.contrib.sitemaps import GenericSitemap, Sitemap
from django.contrib.sites.models import Site
from django.core.exceptions import ImproperlyConfigured
-from django.test import ignore_warnings, modify_settings, override_settings
+from django.test import modify_settings, override_settings
from django.utils._os import upath
-from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.formats import localize
from django.utils.translation import activate, deactivate
@@ -21,15 +20,8 @@ from .models import TestModel
class HTTPSitemapTests(SitemapTestsBase):
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_simple_sitemap_index(self):
"A simple sitemap index can be rendered"
- # The URL for views.sitemap in tests/urls/http.py has been updated
- # with a name but since reversing by Python path is tried first
- # before reversing by name and works since we're giving
- # name='django.contrib.sitemaps.views.sitemap', we need to silence
- # the erroneous warning until reversing by dotted path is removed.
- # The test will work without modification when it's removed.
response = self.client.get('/simple/index.xml')
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
@@ -38,19 +30,12 @@ class HTTPSitemapTests(SitemapTestsBase):
""" % self.base_url
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
- @ignore_warnings(category=RemovedInDjango110Warning)
@override_settings(TEMPLATES=[{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
}])
def test_simple_sitemap_custom_index(self):
"A simple sitemap index can be rendered with a custom template"
- # The URL for views.sitemap in tests/urls/http.py has been updated
- # with a name but since reversing by Python path is tried first
- # before reversing by name and works since we're giving
- # name='django.contrib.sitemaps.views.sitemap', we need to silence
- # the erroneous warning until reversing by dotted path is removed.
- # The test will work without modification when it's removed.
response = self.client.get('/simple/custom-index.xml')
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
<!-- This is a customised template -->
@@ -194,14 +179,7 @@ class HTTPSitemapTests(SitemapTestsBase):
""" % self.base_url
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_x_robots_sitemap(self):
- # The URL for views.sitemap in tests/urls/http.py has been updated
- # with a name but since reversing by Python path is tried first
- # before reversing by name and works since we're giving
- # name='django.contrib.sitemaps.views.sitemap', we need to silence
- # the erroneous warning until reversing by dotted path is removed.
- # The test will work without modification when it's removed.
response = self.client.get('/simple/index.xml')
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')
diff --git a/tests/sitemaps_tests/test_https.py b/tests/sitemaps_tests/test_https.py
index b3bcdc172b..3b68baac43 100644
--- a/tests/sitemaps_tests/test_https.py
+++ b/tests/sitemaps_tests/test_https.py
@@ -2,8 +2,7 @@ from __future__ import unicode_literals
from datetime import date
-from django.test import ignore_warnings, override_settings
-from django.utils.deprecation import RemovedInDjango110Warning
+from django.test import override_settings
from .base import SitemapTestsBase
@@ -12,15 +11,8 @@ from .base import SitemapTestsBase
class HTTPSSitemapTests(SitemapTestsBase):
protocol = 'https'
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_secure_sitemap_index(self):
"A secure sitemap index can be rendered"
- # The URL for views.sitemap in tests/urls/https.py has been updated
- # with a name but since reversing by Python path is tried first
- # before reversing by name and works since we're giving
- # name='django.contrib.sitemaps.views.sitemap', we need to silence
- # the erroneous warning until reversing by dotted path is removed.
- # The test will work without modification when it's removed.
response = self.client.get('/secure/index.xml')
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
@@ -44,15 +36,8 @@ class HTTPSSitemapTests(SitemapTestsBase):
class HTTPSDetectionSitemapTests(SitemapTestsBase):
extra = {'wsgi.url_scheme': 'https'}
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_sitemap_index_with_https_request(self):
"A sitemap index requested in HTTPS is rendered with HTTPS links"
- # The URL for views.sitemap in tests/urls/https.py has been updated
- # with a name but since reversing by Python path is tried first
- # before reversing by name and works since we're giving
- # name='django.contrib.sitemaps.views.sitemap', we need to silence
- # the erroneous warning until reversing by dotted path is removed.
- # The test will work without modification when it's removed.
response = self.client.get('/simple/index.xml', **self.extra)
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
diff --git a/tests/template_tests/syntax_tests/test_url.py b/tests/template_tests/syntax_tests/test_url.py
index 0877a316f1..689ffc8c08 100644
--- a/tests/template_tests/syntax_tests/test_url.py
+++ b/tests/template_tests/syntax_tests/test_url.py
@@ -1,10 +1,7 @@
# coding: utf-8
from django.core.urlresolvers import NoReverseMatch, resolve
from django.template import RequestContext, TemplateSyntaxError
-from django.test import (
- RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
-)
-from django.utils.deprecation import RemovedInDjango110Warning
+from django.test import RequestFactory, SimpleTestCase, override_settings
from ..utils import setup
@@ -13,38 +10,32 @@ from ..utils import setup
class UrlTagTests(SimpleTestCase):
# Successes
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url01': '{% url "template_tests.views.client" client.id %}'})
+ @setup({'url01': '{% url "client" client.id %}'})
def test_url01(self):
output = self.engine.render_to_string('url01', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url02': '{% url "template_tests.views.client_action" id=client.id action="update" %}'})
+ @setup({'url02': '{% url "client_action" id=client.id action="update" %}'})
def test_url02(self):
output = self.engine.render_to_string('url02', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/update/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url02a': '{% url "template_tests.views.client_action" client.id "update" %}'})
+ @setup({'url02a': '{% url "client_action" client.id "update" %}'})
def test_url02a(self):
output = self.engine.render_to_string('url02a', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/update/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url02b': "{% url 'template_tests.views.client_action' id=client.id action='update' %}"})
+ @setup({'url02b': "{% url 'client_action' id=client.id action='update' %}"})
def test_url02b(self):
output = self.engine.render_to_string('url02b', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/update/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url02c': "{% url 'template_tests.views.client_action' client.id 'update' %}"})
+ @setup({'url02c': "{% url 'client_action' client.id 'update' %}"})
def test_url02c(self):
output = self.engine.render_to_string('url02c', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/update/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url03': '{% url "template_tests.views.index" %}'})
+ @setup({'url03': '{% url "index" %}'})
def test_url03(self):
output = self.engine.render_to_string('url03')
self.assertEqual(output, '/')
@@ -64,12 +55,6 @@ class UrlTagTests(SimpleTestCase):
output = self.engine.render_to_string('url06', {'v': 'Ω'})
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url07': '{% url "template_tests.views.client2" tag=v %}'})
- def test_url07(self):
- output = self.engine.render_to_string('url07', {'v': 'Ω'})
- self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
-
@setup({'url08': '{% url "метка_оператора" v %}'})
def test_url08(self):
output = self.engine.render_to_string('url08', {'v': 'Ω'})
@@ -80,55 +65,45 @@ class UrlTagTests(SimpleTestCase):
output = self.engine.render_to_string('url09', {'v': 'Ω'})
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url10': '{% url "template_tests.views.client_action" id=client.id action="two words" %}'})
+ @setup({'url10': '{% url "client_action" id=client.id action="two words" %}'})
def test_url10(self):
output = self.engine.render_to_string('url10', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/two%20words/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url11': '{% url "template_tests.views.client_action" id=client.id action="==" %}'})
+ @setup({'url11': '{% url "client_action" id=client.id action="==" %}'})
def test_url11(self):
output = self.engine.render_to_string('url11', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/==/')
- @setup({'url12': '{% url "template_tests.views.client_action" '
- 'id=client.id action="!$&\'()*+,;=~:@," %}'})
- @ignore_warnings(category=RemovedInDjango110Warning)
+ @setup({'url12': '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'})
def test_url12(self):
output = self.engine.render_to_string('url12', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/!$&amp;&#39;()*+,;=~:@,/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url13': '{% url "template_tests.views.client_action" '
- 'id=client.id action=arg|join:"-" %}'})
+ @setup({'url13': '{% url "client_action" id=client.id action=arg|join:"-" %}'})
def test_url13(self):
output = self.engine.render_to_string('url13', {'client': {'id': 1}, 'arg': ['a', 'b']})
self.assertEqual(output, '/client/1/a-b/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url14': '{% url "template_tests.views.client_action" client.id arg|join:"-" %}'})
+ @setup({'url14': '{% url "client_action" client.id arg|join:"-" %}'})
def test_url14(self):
output = self.engine.render_to_string('url14', {'client': {'id': 1}, 'arg': ['a', 'b']})
self.assertEqual(output, '/client/1/a-b/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url15': '{% url "template_tests.views.client_action" 12 "test" %}'})
+ @setup({'url15': '{% url "client_action" 12 "test" %}'})
def test_url15(self):
output = self.engine.render_to_string('url15')
self.assertEqual(output, '/client/12/test/')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url18': '{% url "template_tests.views.client" "1,2" %}'})
+ @setup({'url18': '{% url "client" "1,2" %}'})
def test_url18(self):
output = self.engine.render_to_string('url18')
self.assertEqual(output, '/client/1,2/')
- @ignore_warnings(category=RemovedInDjango110Warning)
@setup({'url19': '{% url named_url client.id %}'})
def test_url19(self):
output = self.engine.render_to_string(
- 'url19', {'client': {'id': 1}, 'named_url': 'template_tests.views.client'}
+ 'url19', {'client': {'id': 1}, 'named_url': 'client'}
)
self.assertEqual(output, '/client/1/')
@@ -138,10 +113,8 @@ class UrlTagTests(SimpleTestCase):
self.assertEqual(output, '/named-client/1/')
@setup({'url21': '{% autoescape off %}'
- '{% url "template_tests.views.client_action" '
- 'id=client.id action="!$&\'()*+,;=~:@," %}'
+ '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'
'{% endautoescape %}'})
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_url21(self):
output = self.engine.render_to_string('url21', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/!$&\'()*+,;=~:@,/')
@@ -157,8 +130,7 @@ class UrlTagTests(SimpleTestCase):
with self.assertRaises(NoReverseMatch):
self.engine.render_to_string('url-fail02')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url-fail03': '{% url "template_tests.views.client" %}'})
+ @setup({'url-fail03': '{% url "client" %}'})
def test_url_fail03(self):
with self.assertRaises(NoReverseMatch):
self.engine.render_to_string('url-fail03')
@@ -203,7 +175,6 @@ class UrlTagTests(SimpleTestCase):
with self.assertRaises(NoReverseMatch):
self.engine.render_to_string('url-fail12', {'named_url': 'no_such_view'})
- @ignore_warnings(category=RemovedInDjango110Warning)
@setup({'url-fail13': '{% url named_url %}'})
def test_url_fail13(self):
with self.assertRaises(NoReverseMatch):
@@ -240,14 +211,12 @@ class UrlTagTests(SimpleTestCase):
self.engine.render_to_string('url-fail19', {'named_url': 'view'})
# {% url ... as var %}
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url-asvar01': '{% url "template_tests.views.index" as url %}'})
+ @setup({'url-asvar01': '{% url "index" as url %}'})
def test_url_asvar01(self):
output = self.engine.render_to_string('url-asvar01')
self.assertEqual(output, '')
- @ignore_warnings(category=RemovedInDjango110Warning)
- @setup({'url-asvar02': '{% url "template_tests.views.index" as url %}{{ url }}'})
+ @setup({'url-asvar02': '{% url "index" as url %}{{ url }}'})
def test_url_asvar02(self):
output = self.engine.render_to_string('url-asvar02')
self.assertEqual(output, '/')
diff --git a/tests/template_tests/urls.py b/tests/template_tests/urls.py
index e7a9d39a69..b0304e1c54 100644
--- a/tests/template_tests/urls.py
+++ b/tests/template_tests/urls.py
@@ -7,10 +7,10 @@ from . import views
ns_patterns = [
# Test urls for testing reverse lookups
- url(r'^$', views.index),
- url(r'^client/([0-9,]+)/$', views.client),
- url(r'^client/(?P<id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
- url(r'^client/(?P<client_id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
+ url(r'^$', views.index, name='index'),
+ url(r'^client/([0-9,]+)/$', views.client, name='client'),
+ url(r'^client/(?P<id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action, name='client_action'),
+ url(r'^client/(?P<client_id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action, name='client_action'),
url(r'^named-client/([0-9]+)/$', views.client2, name="named.client"),
]
diff --git a/tests/urlpatterns_reverse/erroneous_urls.py b/tests/urlpatterns_reverse/erroneous_urls.py
index 281d2bfa5b..4d75b49e8f 100644
--- a/tests/urlpatterns_reverse/erroneous_urls.py
+++ b/tests/urlpatterns_reverse/erroneous_urls.py
@@ -1,30 +1,7 @@
-import warnings
-
from django.conf.urls import url
-from django.utils.deprecation import RemovedInDjango110Warning
from . import views
-# Test deprecated behavior of passing strings as view to url().
-# Some of these can be removed in Django 1.10 as they aren't convertable to
-# callables.
-with warnings.catch_warnings():
- warnings.filterwarnings('ignore', category=RemovedInDjango110Warning)
- urlpatterns = [
- # View has erroneous import
- url(r'erroneous_inner/$', views.erroneous_view),
- # Module has erroneous import
- url(r'erroneous_outer/$', 'urlpatterns_reverse.erroneous_views_module.erroneous_view'),
- # Module is an unqualified string
- url(r'erroneous_unqualified/$', 'unqualified_view'),
- # View does not exist
- url(r'missing_inner/$', 'urlpatterns_reverse.views.missing_view'),
- # View is not a callable (string import; arbitrary Python object)
- url(r'uncallable-dotted/$', 'urlpatterns_reverse.views.uncallable'),
- # View is not a callable (explicit import; arbitrary Python object)
- url(r'uncallable-object/$', views.uncallable),
- # Module does not exist
- url(r'missing_outer/$', 'urlpatterns_reverse.missing_module.missing_view'),
- # Regex contains an error (refs #6170)
- url(r'(regex_error/$', views.empty_view),
- ]
+urlpatterns = [
+ url(r'(regex_error/$', views.empty_view),
+]
diff --git a/tests/urlpatterns_reverse/erroneous_views_module.py b/tests/urlpatterns_reverse/erroneous_views_module.py
deleted file mode 100644
index 3f7f5b2ac7..0000000000
--- a/tests/urlpatterns_reverse/erroneous_views_module.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import non_existent # NOQA
-
-
-def erroneous_view(request):
- pass
diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py
index 292b981907..0fe61bedaa 100644
--- a/tests/urlpatterns_reverse/tests.py
+++ b/tests/urlpatterns_reverse/tests.py
@@ -26,9 +26,7 @@ from django.test import (
)
from django.test.utils import override_script_prefix
from django.utils import six
-from django.utils.deprecation import (
- RemovedInDjango20Warning, RemovedInDjango110Warning,
-)
+from django.utils.deprecation import RemovedInDjango20Warning
from . import middleware, urlconf_outer, views
from .views import empty_view
@@ -231,13 +229,6 @@ test_data = (
('nested-namedcapture', NoReverseMatch, [], {'outer': 'opt/', 'inner': 'opt'}),
('nested-namedcapture', NoReverseMatch, [], {'inner': 'opt'}),
- # Regression for #9038
- # These views are resolved by method name. Each method is deployed twice -
- # 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.
- ('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/', [], {}),
# Tests for #13154
@@ -292,7 +283,6 @@ class NoURLPatternsTests(SimpleTestCase):
@override_settings(ROOT_URLCONF='urlpatterns_reverse.urls')
class URLPatternReverse(SimpleTestCase):
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_urlpattern_reverse(self):
for name, expected, args, kwargs in test_data:
try:
@@ -544,11 +534,10 @@ class ReverseShortcutTests(SimpleTestCase):
redirect("urlpatterns_reverse.nonimported_module.view")
self.assertNotIn("urlpatterns_reverse.nonimported_module", sys.modules)
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_reverse_by_path_nested(self):
- # Views that are added to urlpatterns using include() should be
- # reversible by dotted path.
- self.assertEqual(reverse('urlpatterns_reverse.views.nested_view'), '/includes/nested_path/')
+ # Views added to urlpatterns using include() should be reversible.
+ from .views import nested_view
+ self.assertEqual(reverse(nested_view), '/includes/nested_path/')
def test_redirect_view_object(self):
from .views import absolute_kwargs_view
@@ -982,24 +971,16 @@ class ResolverMatchTests(SimpleTestCase):
@override_settings(ROOT_URLCONF='urlpatterns_reverse.erroneous_urls')
class ErroneousViewTests(SimpleTestCase):
- def test_erroneous_resolve(self):
- self.assertRaises(ImportError, self.client.get, '/erroneous_inner/')
- self.assertRaises(ImportError, self.client.get, '/erroneous_outer/')
- self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_inner/')
- self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_outer/')
- self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable-dotted/')
- self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable-object/')
-
- # Regression test for #21157
- self.assertRaises(ImportError, self.client.get, '/erroneous_unqualified/')
+ def test_noncallable_view(self):
+ # View is not a callable (explicit import; arbitrary Python object)
+ with self.assertRaisesMessage(TypeError, 'view must be a callable'):
+ url(r'uncallable-object/$', views.uncallable)
- def test_erroneous_reverse(self):
- """
- Ensure that a useful exception is raised when a regex is invalid in the
- URLConf (#6170).
- """
- # The regex error will be hit before NoReverseMatch can be raised
- self.assertRaises(ImproperlyConfigured, reverse, 'whatever blah blah')
+ def test_invalid_regex(self):
+ # Regex contains an error (refs #6170)
+ msg = '(regex_error/$" is not a valid regular expression'
+ with self.assertRaisesMessage(ImproperlyConfigured, msg):
+ reverse(views.empty_view)
class ViewLoadingTests(SimpleTestCase):
diff --git a/tests/urlpatterns_reverse/urls.py b/tests/urlpatterns_reverse/urls.py
index 4672f1800d..0ede20da3b 100644
--- a/tests/urlpatterns_reverse/urls.py
+++ b/tests/urlpatterns_reverse/urls.py
@@ -2,7 +2,7 @@ from django.conf.urls import include, url
from .views import (
absolute_kwargs_view, defaults_view, empty_view, empty_view_partial,
- empty_view_wrapped, kwargs_view, nested_view,
+ empty_view_wrapped, nested_view,
)
other_patterns = [
@@ -67,10 +67,6 @@ urlpatterns = [
# This is non-reversible, but we shouldn't blow up when parsing it.
url(r'^(?:foo|bar)(\w+)/$', empty_view, name="disjunction"),
- # Regression views for #9038. See tests for more details
- url(r'arg_view/$', kwargs_view),
- url(r'arg_view/(?P<arg1>[0-9]+)/$', kwargs_view),
- url(r'absolute_arg_view/(?P<arg1>[0-9]+)/$', absolute_kwargs_view),
url(r'absolute_arg_view/$', absolute_kwargs_view),
# Tests for #13154. Mixed syntax to test both ways of defining URLs.
diff --git a/tests/urlpatterns_reverse/views.py b/tests/urlpatterns_reverse/views.py
index e13d28777e..6fd1c53a00 100644
--- a/tests/urlpatterns_reverse/views.py
+++ b/tests/urlpatterns_reverse/views.py
@@ -10,10 +10,6 @@ def empty_view(request, *args, **kwargs):
return HttpResponse('')
-def kwargs_view(request, arg1=1, arg2=2):
- return HttpResponse('')
-
-
def absolute_kwargs_view(request, arg1=1, arg2=2):
return HttpResponse('')