Pārlūkot izejas kodu

Refs #23919 -- Replaced usage of django.utils.http utilities with Python equivalents

Thanks Tim Graham for the review.
Claude Paroz 8 gadi atpakaļ
vecāks
revīzija
fee42fd99e

+ 2 - 1
django/contrib/admin/options.py

@@ -3,6 +3,7 @@ import json
 import operator
 import operator
 from collections import OrderedDict
 from collections import OrderedDict
 from functools import partial, reduce, update_wrapper
 from functools import partial, reduce, update_wrapper
+from urllib.parse import quote as urlquote
 
 
 from django import forms
 from django import forms
 from django.conf import settings
 from django.conf import settings
@@ -39,7 +40,7 @@ from django.urls import reverse
 from django.utils.decorators import method_decorator
 from django.utils.decorators import method_decorator
 from django.utils.encoding import force_text
 from django.utils.encoding import force_text
 from django.utils.html import format_html
 from django.utils.html import format_html
-from django.utils.http import urlencode, urlquote
+from django.utils.http import urlencode
 from django.utils.safestring import mark_safe
 from django.utils.safestring import mark_safe
 from django.utils.text import capfirst, format_lazy, get_text_list
 from django.utils.text import capfirst, format_lazy, get_text_list
 from django.utils.translation import ugettext as _, ungettext
 from django.utils.translation import ugettext as _, ungettext

+ 2 - 2
django/core/cache/utils.py

@@ -1,7 +1,7 @@
 import hashlib
 import hashlib
+from urllib.parse import quote
 
 
 from django.utils.encoding import force_bytes
 from django.utils.encoding import force_bytes
-from django.utils.http import urlquote
 
 
 TEMPLATE_FRAGMENT_KEY_TEMPLATE = 'template.cache.%s.%s'
 TEMPLATE_FRAGMENT_KEY_TEMPLATE = 'template.cache.%s.%s'
 
 
@@ -9,6 +9,6 @@ TEMPLATE_FRAGMENT_KEY_TEMPLATE = 'template.cache.%s.%s'
 def make_template_fragment_key(fragment_name, vary_on=None):
 def make_template_fragment_key(fragment_name, vary_on=None):
     if vary_on is None:
     if vary_on is None:
         vary_on = ()
         vary_on = ()
-    key = ':'.join(urlquote(var) for var in vary_on)
+    key = ':'.join(quote(str(var)) for var in vary_on)
     args = hashlib.md5(force_bytes(key))
     args = hashlib.md5(force_bytes(key))
     return TEMPLATE_FRAGMENT_KEY_TEMPLATE % (fragment_name, args.hexdigest())
     return TEMPLATE_FRAGMENT_KEY_TEMPLATE % (fragment_name, args.hexdigest())

+ 3 - 3
django/template/defaultfilters.py

@@ -5,6 +5,7 @@ from decimal import ROUND_HALF_UP, Context, Decimal, InvalidOperation
 from functools import wraps
 from functools import wraps
 from operator import itemgetter
 from operator import itemgetter
 from pprint import pformat
 from pprint import pformat
+from urllib.parse import quote
 
 
 from django.utils import formats
 from django.utils import formats
 from django.utils.dateformat import format, time_format
 from django.utils.dateformat import format, time_format
@@ -13,7 +14,6 @@ from django.utils.html import (
     avoid_wrapping, conditional_escape, escape, escapejs, linebreaks,
     avoid_wrapping, conditional_escape, escape, escapejs, linebreaks,
     strip_tags, urlize as _urlize,
     strip_tags, urlize as _urlize,
 )
 )
-from django.utils.http import urlquote
 from django.utils.safestring import SafeData, mark_safe
 from django.utils.safestring import SafeData, mark_safe
 from django.utils.text import (
 from django.utils.text import (
     Truncator, normalize_newlines, phone2numeric, slugify as _slugify, wrap,
     Truncator, normalize_newlines, phone2numeric, slugify as _slugify, wrap,
@@ -318,14 +318,14 @@ def urlencode(value, safe=None):
     Escapes a value for use in a URL.
     Escapes a value for use in a URL.
 
 
     Takes an optional ``safe`` parameter used to determine the characters which
     Takes an optional ``safe`` parameter used to determine the characters which
-    should not be escaped by Django's ``urlquote`` method. If not provided, the
+    should not be escaped by Python's quote() function. If not provided, the
     default safe characters will be used (but an empty string can be provided
     default safe characters will be used (but an empty string can be provided
     when *all* characters should be escaped).
     when *all* characters should be escaped).
     """
     """
     kwargs = {}
     kwargs = {}
     if safe is not None:
     if safe is not None:
         kwargs['safe'] = safe
         kwargs['safe'] = safe
-    return urlquote(value, **kwargs)
+    return quote(value, **kwargs)
 
 
 
 
 @register.filter(is_safe=True, needs_autoescape=True)
 @register.filter(is_safe=True, needs_autoescape=True)

+ 3 - 2
django/urls/resolvers.py

@@ -9,6 +9,7 @@ import functools
 import re
 import re
 import threading
 import threading
 from importlib import import_module
 from importlib import import_module
+from urllib.parse import quote
 
 
 from django.conf import settings
 from django.conf import settings
 from django.core.checks import Warning
 from django.core.checks import Warning
@@ -17,7 +18,7 @@ from django.core.exceptions import ImproperlyConfigured
 from django.utils.datastructures import MultiValueDict
 from django.utils.datastructures import MultiValueDict
 from django.utils.encoding import force_text
 from django.utils.encoding import force_text
 from django.utils.functional import cached_property
 from django.utils.functional import cached_property
-from django.utils.http import RFC3986_SUBDELIMS, urlquote
+from django.utils.http import RFC3986_SUBDELIMS
 from django.utils.regex_helper import normalize
 from django.utils.regex_helper import normalize
 from django.utils.translation import get_language
 from django.utils.translation import get_language
 
 
@@ -455,7 +456,7 @@ class RegexURLResolver(LocaleRegexProvider):
                 candidate_pat = _prefix.replace('%', '%%') + result
                 candidate_pat = _prefix.replace('%', '%%') + result
                 if re.search('^%s%s' % (re.escape(_prefix), pattern), candidate_pat % candidate_subs):
                 if re.search('^%s%s' % (re.escape(_prefix), pattern), candidate_pat % candidate_subs):
                     # safe characters from `pchar` definition of RFC 3986
                     # safe characters from `pchar` definition of RFC 3986
-                    url = urlquote(candidate_pat % candidate_subs, safe=RFC3986_SUBDELIMS + str('/~:@'))
+                    url = quote(candidate_pat % candidate_subs, safe=RFC3986_SUBDELIMS + '/~:@')
                     # Don't allow construction of scheme relative urls.
                     # Don't allow construction of scheme relative urls.
                     if url.startswith('//'):
                     if url.startswith('//'):
                         url = '/%%2F%s' % url[2:]
                         url = '/%%2F%s' % url[2:]

+ 20 - 25
django/utils/http.py

@@ -14,7 +14,7 @@ from urllib.parse import (
 from django.core.exceptions import TooManyFieldsSent
 from django.core.exceptions import TooManyFieldsSent
 from django.utils.datastructures import MultiValueDict
 from django.utils.datastructures import MultiValueDict
 from django.utils.deprecation import RemovedInDjango21Warning
 from django.utils.deprecation import RemovedInDjango21Warning
-from django.utils.encoding import force_bytes, force_str, force_text
+from django.utils.encoding import force_bytes
 from django.utils.functional import keep_lazy_text
 from django.utils.functional import keep_lazy_text
 
 
 # based on RFC 7232, Appendix C
 # based on RFC 7232, Appendix C
@@ -47,58 +47,53 @@ FIELDS_MATCH = re.compile('[&;]')
 @keep_lazy_text
 @keep_lazy_text
 def urlquote(url, safe='/'):
 def urlquote(url, safe='/'):
     """
     """
-    A version of Python's urllib.quote() function that can operate on unicode
-    strings. The url is first UTF-8 encoded before quoting. The returned string
-    can safely be used as part of an argument to a subsequent iri_to_uri() call
-    without double-quoting occurring.
+    A legacy compatibility wrapper to Python's urllib.parse.quote() function.
+    (was used for unicode handling on Python 2)
     """
     """
-    return force_text(quote(force_str(url), force_str(safe)))
+    return quote(url, safe)
 
 
 
 
 @keep_lazy_text
 @keep_lazy_text
 def urlquote_plus(url, safe=''):
 def urlquote_plus(url, safe=''):
     """
     """
-    A version of Python's urllib.quote_plus() function that can operate on
-    unicode strings. The url is first UTF-8 encoded before quoting. The
-    returned string can safely be used as part of an argument to a subsequent
-    iri_to_uri() call without double-quoting occurring.
+    A legacy compatibility wrapper to Python's urllib.parse.quote_plus()
+    function. (was used for unicode handling on Python 2)
     """
     """
-    return force_text(quote_plus(force_str(url), force_str(safe)))
+    return quote_plus(url, safe)
 
 
 
 
 @keep_lazy_text
 @keep_lazy_text
 def urlunquote(quoted_url):
 def urlunquote(quoted_url):
     """
     """
-    A wrapper for Python's urllib.unquote() function that can operate on
-    the result of django.utils.http.urlquote().
+    A legacy compatibility wrapper to Python's urllib.parse.unquote() function.
+    (was used for unicode handling on Python 2)
     """
     """
-    return force_text(unquote(force_str(quoted_url)))
+    return unquote(quoted_url)
 
 
 
 
 @keep_lazy_text
 @keep_lazy_text
 def urlunquote_plus(quoted_url):
 def urlunquote_plus(quoted_url):
     """
     """
-    A wrapper for Python's urllib.unquote_plus() function that can operate on
-    the result of django.utils.http.urlquote_plus().
+    A legacy compatibility wrapper to Python's urllib.parse.unquote_plus()
+    function. (was used for unicode handling on Python 2)
     """
     """
-    return force_text(unquote_plus(force_str(quoted_url)))
+    return unquote_plus(quoted_url)
 
 
 
 
-def urlencode(query, doseq=0):
+def urlencode(query, doseq=False):
     """
     """
-    A version of Python's urllib.urlencode() function that can operate on
-    unicode strings. The parameters are first cast to UTF-8 encoded strings and
-    then encoded as per normal.
+    A version of Python's urllib.parse.urlencode() function that can operate on
+    MultiValueDict and non-string values.
     """
     """
     if isinstance(query, MultiValueDict):
     if isinstance(query, MultiValueDict):
         query = query.lists()
         query = query.lists()
     elif hasattr(query, 'items'):
     elif hasattr(query, 'items'):
         query = query.items()
         query = query.items()
     return original_urlencode(
     return original_urlencode(
-        [(force_str(k),
-         [force_str(i) for i in v] if isinstance(v, (list, tuple)) else force_str(v))
-            for k, v in query],
-        doseq)
+        [(k, [str(i) for i in v] if isinstance(v, (list, tuple)) else str(v))
+         for k, v in query],
+        doseq
+    )
 
 
 
 
 def cookie_date(epoch_seconds=None):
 def cookie_date(epoch_seconds=None):

+ 3 - 2
django/views/i18n.py

@@ -1,6 +1,7 @@
 import itertools
 import itertools
 import json
 import json
 import os
 import os
+from urllib.parse import unquote
 
 
 from django import http
 from django import http
 from django.apps import apps
 from django.apps import apps
@@ -9,7 +10,7 @@ from django.template import Context, Engine
 from django.urls import translate_url
 from django.urls import translate_url
 from django.utils.encoding import force_text
 from django.utils.encoding import force_text
 from django.utils.formats import get_format
 from django.utils.formats import get_format
-from django.utils.http import is_safe_url, urlunquote
+from django.utils.http import is_safe_url
 from django.utils.translation import (
 from django.utils.translation import (
     LANGUAGE_SESSION_KEY, check_for_language, get_language,
     LANGUAGE_SESSION_KEY, check_for_language, get_language,
 )
 )
@@ -35,7 +36,7 @@ def set_language(request):
             not is_safe_url(url=next, allowed_hosts={request.get_host()}, require_https=request.is_secure())):
             not is_safe_url(url=next, allowed_hosts={request.get_host()}, require_https=request.is_secure())):
         next = request.META.get('HTTP_REFERER')
         next = request.META.get('HTTP_REFERER')
         if next:
         if next:
-            next = urlunquote(next)  # HTTP_REFERER may be encoded.
+            next = unquote(next)  # HTTP_REFERER may be encoded.
         if not is_safe_url(url=next, allowed_hosts={request.get_host()}, require_https=request.is_secure()):
         if not is_safe_url(url=next, allowed_hosts={request.get_host()}, require_https=request.is_secure()):
             next = '/'
             next = '/'
     response = http.HttpResponseRedirect(next) if next else http.HttpResponse(status=204)
     response = http.HttpResponseRedirect(next) if next else http.HttpResponse(status=204)

+ 2 - 2
docs/ref/unicode.txt

@@ -156,8 +156,8 @@ Django provides some assistance.
 * The function :func:`django.utils.encoding.iri_to_uri()` implements the
 * The function :func:`django.utils.encoding.iri_to_uri()` implements the
   conversion from IRI to URI as required by the specification (:rfc:`3987#section-3.1`).
   conversion from IRI to URI as required by the specification (:rfc:`3987#section-3.1`).
 
 
-* The functions :func:`django.utils.http.urlquote()` and
-  :func:`django.utils.http.urlquote_plus()` are versions of Python's standard
+* The functions ``django.utils.http.urlquote()`` and
+  ``django.utils.http.urlquote_plus()`` are versions of Python's standard
   ``urllib.quote()`` and ``urllib.quote_plus()`` that work with non-ASCII
   ``urllib.quote()`` and ``urllib.quote_plus()`` that work with non-ASCII
   characters. (The data is converted to UTF-8 prior to encoding.)
   characters. (The data is converted to UTF-8 prior to encoding.)
 
 

+ 2 - 3
docs/ref/urlresolvers.txt

@@ -70,9 +70,8 @@ use for reversing. By default, the root URLconf for the current thread is used.
         >>> reverse('cities', args=['Orléans'])
         >>> reverse('cities', args=['Orléans'])
         '.../Orl%C3%A9ans/'
         '.../Orl%C3%A9ans/'
 
 
-    Applying further encoding (such as :meth:`~django.utils.http.urlquote` or
-    ``urllib.quote``) to the output of ``reverse()`` may produce undesirable
-    results.
+    Applying further encoding (such as :func:`urllib.parse.quote`) to the output
+    of ``reverse()`` may produce undesirable results.
 
 
 ``reverse_lazy()``
 ``reverse_lazy()``
 ==================
 ==================

+ 2 - 19
docs/ref/utils.txt

@@ -684,27 +684,10 @@ escaping HTML.
 .. module:: django.utils.http
 .. module:: django.utils.http
    :synopsis: HTTP helper functions. (URL encoding, cookie handling, ...)
    :synopsis: HTTP helper functions. (URL encoding, cookie handling, ...)
 
 
-.. function:: urlquote(url, safe='/')
-
-    A version of Python's ``urllib.quote()`` function that can operate on
-    unicode strings. The url is first UTF-8 encoded before quoting. The
-    returned string can safely be used as part of an argument to a subsequent
-    ``iri_to_uri()`` call without double-quoting occurring. Employs lazy
-    execution.
-
-.. function:: urlquote_plus(url, safe='')
-
-    A version of Python's urllib.quote_plus() function that can operate on
-    unicode strings. The url is first UTF-8 encoded before quoting. The
-    returned string can safely be used as part of an argument to a subsequent
-    ``iri_to_uri()`` call without double-quoting occurring. Employs lazy
-    execution.
-
 .. function:: urlencode(query, doseq=0)
 .. function:: urlencode(query, doseq=0)
 
 
-    A version of Python's urllib.urlencode() function that can operate on
-    unicode strings. The parameters are first cast to UTF-8 encoded strings
-    and then encoded as per normal.
+    A version of Python's :func:`urllib.parse.urlencode` function that can
+    operate on ``MultiValueDict`` and non-string values.
 
 
 .. function:: cookie_date(epoch_seconds=None)
 .. function:: cookie_date(epoch_seconds=None)
 
 

+ 1 - 1
docs/releases/1.6.txt

@@ -585,7 +585,7 @@ be at the end of a line. If they are not, the comments are ignored and
 Quoting in ``reverse()``
 Quoting in ``reverse()``
 ------------------------
 ------------------------
 
 
-When reversing URLs, Django didn't apply :func:`~django.utils.http.urlquote`
+When reversing URLs, Django didn't apply ``django.utils.http.urlquote``
 to arguments before interpolating them in URL patterns. This bug is fixed in
 to arguments before interpolating them in URL patterns. This bug is fixed in
 Django 1.6. If you worked around this bug by applying URL quoting before
 Django 1.6. If you worked around this bug by applying URL quoting before
 passing arguments to ``reverse()``, this may result in double-quoting. If this
 passing arguments to ``reverse()``, this may result in double-quoting. If this

+ 10 - 11
tests/auth_tests/test_views.py

@@ -3,7 +3,7 @@ import itertools
 import os
 import os
 import re
 import re
 from importlib import import_module
 from importlib import import_module
-from urllib.parse import ParseResult, urlparse
+from urllib.parse import ParseResult, quote, urlparse
 
 
 from django.apps import apps
 from django.apps import apps
 from django.conf import settings
 from django.conf import settings
@@ -28,7 +28,6 @@ from django.test.utils import patch_logger
 from django.urls import NoReverseMatch, reverse, reverse_lazy
 from django.urls import NoReverseMatch, reverse, reverse_lazy
 from django.utils.deprecation import RemovedInDjango21Warning
 from django.utils.deprecation import RemovedInDjango21Warning
 from django.utils.encoding import force_text
 from django.utils.encoding import force_text
-from django.utils.http import urlquote
 from django.utils.translation import LANGUAGE_SESSION_KEY
 from django.utils.translation import LANGUAGE_SESSION_KEY
 
 
 from .client import PasswordResetConfirmClient
 from .client import PasswordResetConfirmClient
@@ -546,7 +545,7 @@ class LoginTest(AuthViewsTestCase):
             nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
             nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
                 'url': login_url,
                 'url': login_url,
                 'next': REDIRECT_FIELD_NAME,
                 'next': REDIRECT_FIELD_NAME,
-                'bad_url': urlquote(bad_url),
+                'bad_url': quote(bad_url),
             }
             }
             response = self.client.post(nasty_url, {
             response = self.client.post(nasty_url, {
                 'username': 'testclient',
                 'username': 'testclient',
@@ -568,7 +567,7 @@ class LoginTest(AuthViewsTestCase):
             safe_url = '%(url)s?%(next)s=%(good_url)s' % {
             safe_url = '%(url)s?%(next)s=%(good_url)s' % {
                 'url': login_url,
                 'url': login_url,
                 'next': REDIRECT_FIELD_NAME,
                 'next': REDIRECT_FIELD_NAME,
-                'good_url': urlquote(good_url),
+                'good_url': quote(good_url),
             }
             }
             response = self.client.post(safe_url, {
             response = self.client.post(safe_url, {
                 'username': 'testclient',
                 'username': 'testclient',
@@ -583,7 +582,7 @@ class LoginTest(AuthViewsTestCase):
         not_secured_url = '%(url)s?%(next)s=%(next_url)s' % {
         not_secured_url = '%(url)s?%(next)s=%(next_url)s' % {
             'url': login_url,
             'url': login_url,
             'next': REDIRECT_FIELD_NAME,
             'next': REDIRECT_FIELD_NAME,
-            'next_url': urlquote(non_https_next_url),
+            'next_url': quote(non_https_next_url),
         }
         }
         post_data = {
         post_data = {
             'username': 'testclient',
             'username': 'testclient',
@@ -701,13 +700,13 @@ class LoginURLSettings(AuthViewsTestCase):
 
 
     @override_settings(LOGIN_URL='http://remote.example.com/login')
     @override_settings(LOGIN_URL='http://remote.example.com/login')
     def test_remote_login_url(self):
     def test_remote_login_url(self):
-        quoted_next = urlquote('http://testserver/login_required/')
+        quoted_next = quote('http://testserver/login_required/')
         expected = 'http://remote.example.com/login?next=%s' % quoted_next
         expected = 'http://remote.example.com/login?next=%s' % quoted_next
         self.assertLoginURLEquals(expected)
         self.assertLoginURLEquals(expected)
 
 
     @override_settings(LOGIN_URL='https:///login/')
     @override_settings(LOGIN_URL='https:///login/')
     def test_https_login_url(self):
     def test_https_login_url(self):
-        quoted_next = urlquote('http://testserver/login_required/')
+        quoted_next = quote('http://testserver/login_required/')
         expected = 'https:///login/?next=%s' % quoted_next
         expected = 'https:///login/?next=%s' % quoted_next
         self.assertLoginURLEquals(expected)
         self.assertLoginURLEquals(expected)
 
 
@@ -717,7 +716,7 @@ class LoginURLSettings(AuthViewsTestCase):
 
 
     @override_settings(LOGIN_URL='http://remote.example.com/login/?next=/default/')
     @override_settings(LOGIN_URL='http://remote.example.com/login/?next=/default/')
     def test_remote_login_url_with_next_querystring(self):
     def test_remote_login_url_with_next_querystring(self):
-        quoted_next = urlquote('http://testserver/login_required/')
+        quoted_next = quote('http://testserver/login_required/')
         expected = 'http://remote.example.com/login/?next=%s' % quoted_next
         expected = 'http://remote.example.com/login/?next=%s' % quoted_next
         self.assertLoginURLEquals(expected)
         self.assertLoginURLEquals(expected)
 
 
@@ -973,7 +972,7 @@ class LogoutTest(AuthViewsTestCase):
             nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
             nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
                 'url': logout_url,
                 'url': logout_url,
                 'next': REDIRECT_FIELD_NAME,
                 'next': REDIRECT_FIELD_NAME,
-                'bad_url': urlquote(bad_url),
+                'bad_url': quote(bad_url),
             }
             }
             self.login()
             self.login()
             response = self.client.get(nasty_url)
             response = self.client.get(nasty_url)
@@ -994,7 +993,7 @@ class LogoutTest(AuthViewsTestCase):
             safe_url = '%(url)s?%(next)s=%(good_url)s' % {
             safe_url = '%(url)s?%(next)s=%(good_url)s' % {
                 'url': logout_url,
                 'url': logout_url,
                 'next': REDIRECT_FIELD_NAME,
                 'next': REDIRECT_FIELD_NAME,
-                'good_url': urlquote(good_url),
+                'good_url': quote(good_url),
             }
             }
             self.login()
             self.login()
             response = self.client.get(safe_url)
             response = self.client.get(safe_url)
@@ -1008,7 +1007,7 @@ class LogoutTest(AuthViewsTestCase):
         url = '%(url)s?%(next)s=%(next_url)s' % {
         url = '%(url)s?%(next)s=%(next_url)s' % {
             'url': logout_url,
             'url': logout_url,
             'next': REDIRECT_FIELD_NAME,
             'next': REDIRECT_FIELD_NAME,
-            'next_url': urlquote(non_https_next_url),
+            'next_url': quote(non_https_next_url),
         }
         }
         self.login()
         self.login()
         response = self.client.get(url, secure=True)
         response = self.client.get(url, secure=True)

+ 4 - 3
tests/contenttypes_tests/models.py

@@ -1,10 +1,11 @@
+from urllib.parse import quote
+
 from django.contrib.contenttypes.fields import (
 from django.contrib.contenttypes.fields import (
     GenericForeignKey, GenericRelation,
     GenericForeignKey, GenericRelation,
 )
 )
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.sites.models import SiteManager
 from django.contrib.sites.models import SiteManager
 from django.db import models
 from django.db import models
-from django.utils.http import urlquote
 
 
 
 
 class Site(models.Model):
 class Site(models.Model):
@@ -72,7 +73,7 @@ class FooWithUrl(FooWithoutUrl):
     """
     """
 
 
     def get_absolute_url(self):
     def get_absolute_url(self):
-        return "/users/%s/" % urlquote(self.name)
+        return "/users/%s/" % quote(self.name)
 
 
 
 
 class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
 class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
@@ -126,4 +127,4 @@ class ModelWithNullFKToSite(models.Model):
         return self.title
         return self.title
 
 
     def get_absolute_url(self):
     def get_absolute_url(self):
-        return '/title/%s/' % urlquote(self.title)
+        return '/title/%s/' % quote(self.title)

+ 3 - 3
tests/file_uploads/tests.py

@@ -7,13 +7,13 @@ import sys
 import tempfile as sys_tempfile
 import tempfile as sys_tempfile
 import unittest
 import unittest
 from io import BytesIO, StringIO
 from io import BytesIO, StringIO
+from urllib.parse import quote
 
 
 from django.core.files import temp as tempfile
 from django.core.files import temp as tempfile
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.http.multipartparser import MultiPartParser, parse_header
 from django.http.multipartparser import MultiPartParser, parse_header
 from django.test import SimpleTestCase, TestCase, client, override_settings
 from django.test import SimpleTestCase, TestCase, client, override_settings
 from django.utils.encoding import force_bytes
 from django.utils.encoding import force_bytes
-from django.utils.http import urlquote
 
 
 from . import uploadhandler
 from . import uploadhandler
 from .models import FileModel
 from .models import FileModel
@@ -127,7 +127,7 @@ class FileUploadTests(TestCase):
         payload = client.FakePayload()
         payload = client.FakePayload()
         payload.write('\r\n'.join([
         payload.write('\r\n'.join([
             '--' + client.BOUNDARY,
             '--' + client.BOUNDARY,
-            'Content-Disposition: form-data; name="file_unicode"; filename*=UTF-8\'\'%s' % urlquote(UNICODE_FILENAME),
+            'Content-Disposition: form-data; name="file_unicode"; filename*=UTF-8\'\'%s' % quote(UNICODE_FILENAME),
             'Content-Type: application/octet-stream',
             'Content-Type: application/octet-stream',
             '',
             '',
             'You got pwnd.\r\n',
             'You got pwnd.\r\n',
@@ -153,7 +153,7 @@ class FileUploadTests(TestCase):
         payload.write(
         payload.write(
             '\r\n'.join([
             '\r\n'.join([
                 '--' + client.BOUNDARY,
                 '--' + client.BOUNDARY,
-                'Content-Disposition: form-data; name*=UTF-8\'\'file_unicode; filename*=UTF-8\'\'%s' % urlquote(
+                'Content-Disposition: form-data; name*=UTF-8\'\'file_unicode; filename*=UTF-8\'\'%s' % quote(
                     UNICODE_FILENAME
                     UNICODE_FILENAME
                 ),
                 ),
                 'Content-Type: application/octet-stream',
                 'Content-Type: application/octet-stream',

+ 3 - 3
tests/requests/tests.py

@@ -3,7 +3,7 @@ from datetime import datetime, timedelta
 from http import cookies
 from http import cookies
 from io import BytesIO
 from io import BytesIO
 from itertools import chain
 from itertools import chain
-from urllib.parse import urlencode as original_urlencode
+from urllib.parse import urlencode
 
 
 from django.core.exceptions import SuspiciousOperation
 from django.core.exceptions import SuspiciousOperation
 from django.core.handlers.wsgi import LimitedStream, WSGIRequest
 from django.core.handlers.wsgi import LimitedStream, WSGIRequest
@@ -14,7 +14,7 @@ from django.http.request import split_domain_port
 from django.test import RequestFactory, SimpleTestCase, override_settings
 from django.test import RequestFactory, SimpleTestCase, override_settings
 from django.test.client import FakePayload
 from django.test.client import FakePayload
 from django.test.utils import freeze_time
 from django.test.utils import freeze_time
-from django.utils.http import cookie_date, urlencode
+from django.utils.http import cookie_date
 from django.utils.timezone import utc
 from django.utils.timezone import utc
 
 
 
 
@@ -379,7 +379,7 @@ class RequestsTests(SimpleTestCase):
         """
         """
         Test a POST with non-utf-8 payload encoding.
         Test a POST with non-utf-8 payload encoding.
         """
         """
-        payload = FakePayload(original_urlencode({'key': 'España'.encode('latin-1')}))
+        payload = FakePayload(urlencode({'key': 'España'.encode('latin-1')}))
         request = WSGIRequest({
         request = WSGIRequest({
             'REQUEST_METHOD': 'POST',
             'REQUEST_METHOD': 'POST',
             'CONTENT_LENGTH': len(payload),
             'CONTENT_LENGTH': len(payload),

+ 1 - 1
tests/servers/tests.py

@@ -5,10 +5,10 @@ import errno
 import os
 import os
 import socket
 import socket
 from urllib.error import HTTPError
 from urllib.error import HTTPError
+from urllib.parse import urlencode
 from urllib.request import urlopen
 from urllib.request import urlopen
 
 
 from django.test import LiveServerTestCase, override_settings
 from django.test import LiveServerTestCase, override_settings
-from django.utils.http import urlencode
 
 
 from .models import Person
 from .models import Person
 
 

+ 2 - 2
tests/utils_tests/test_encoding.py

@@ -1,12 +1,12 @@
 import datetime
 import datetime
 import unittest
 import unittest
+from urllib.parse import quote_plus
 
 
 from django.utils.encoding import (
 from django.utils.encoding import (
     escape_uri_path, filepath_to_uri, force_bytes, force_text, iri_to_uri,
     escape_uri_path, filepath_to_uri, force_bytes, force_text, iri_to_uri,
     smart_text, uri_to_iri,
     smart_text, uri_to_iri,
 )
 )
 from django.utils.functional import SimpleLazyObject
 from django.utils.functional import SimpleLazyObject
-from django.utils.http import urlquote_plus
 
 
 
 
 class TestEncodingUtils(unittest.TestCase):
 class TestEncodingUtils(unittest.TestCase):
@@ -72,7 +72,7 @@ class TestRFC3987IEncodingUtils(unittest.TestCase):
             # Valid UTF-8 sequences are encoded.
             # Valid UTF-8 sequences are encoded.
             ('red%09rosé#red', 'red%09ros%C3%A9#red'),
             ('red%09rosé#red', 'red%09ros%C3%A9#red'),
             ('/blog/for/Jürgen Münster/', '/blog/for/J%C3%BCrgen%20M%C3%BCnster/'),
             ('/blog/for/Jürgen Münster/', '/blog/for/J%C3%BCrgen%20M%C3%BCnster/'),
-            ('locations/%s' % urlquote_plus('Paris & Orléans'), 'locations/Paris+%26+Orl%C3%A9ans'),
+            ('locations/%s' % quote_plus('Paris & Orléans'), 'locations/Paris+%26+Orl%C3%A9ans'),
 
 
             # Reserved chars remain unescaped.
             # Reserved chars remain unescaped.
             ('%&', '%&'),
             ('%&', '%&'),