Browse Source

Assumed iri_to_uri always returns a string

Thanks Tim Graham for the review.
Claude Paroz 8 years ago
parent
commit
d2e7d15b4c

+ 1 - 1
django/template/defaultfilters.py

@@ -164,7 +164,7 @@ def floatformat(text, arg=-1):
 @stringfilter
 def iriencode(value):
     """Escapes an IRI value for use in a URL."""
-    return force_text(iri_to_uri(value))
+    return iri_to_uri(value)
 
 
 @register.filter(is_safe=True, needs_autoescape=True)

+ 2 - 2
django/urls/base.py

@@ -1,7 +1,7 @@
 from threading import local
 from urllib.parse import urlsplit, urlunsplit
 
-from django.utils.encoding import force_text, iri_to_uri
+from django.utils.encoding import iri_to_uri
 from django.utils.functional import lazy
 from django.utils.translation import override
 
@@ -85,7 +85,7 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
         if ns_pattern:
             resolver = get_ns_resolver(ns_pattern, resolver)
 
-    return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
+    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
 
 
 reverse_lazy = lazy(reverse, str)

+ 9 - 7
django/utils/encoding.py

@@ -151,13 +151,13 @@ def iri_to_uri(iri):
     Convert an Internationalized Resource Identifier (IRI) portion to a URI
     portion that is suitable for inclusion in a URL.
 
-    This is the algorithm from section 3.1 of RFC 3987.  However, since we are
-    assuming input is either UTF-8 or unicode already, we can simplify things a
-    little from the full method.
+    This is the algorithm from section 3.1 of RFC 3987, slightly simplified
+    since the input is assumed to be a string rather than an arbitrary byte
+    stream.
 
-    Takes an IRI in UTF-8 bytes (e.g. '/I \xe2\x99\xa5 Django/') or unicode
-    (e.g. '/I ♥ Django/') and returns ASCII bytes containing the encoded result
-    (e.g. '/I%20%E2%99%A5%20Django/').
+    Take an IRI (string or UTF-8 bytes, e.g. '/I ♥ Django/' or
+    b'/I \xe2\x99\xa5 Django/') and return a string containing the encoded
+    result with ASCII chars only (e.g. '/I%20%E2%99%A5%20Django/').
     """
     # The list of safe characters here is constructed from the "reserved" and
     # "unreserved" characters specified in sections 2.2 and 2.3 of RFC 3986:
@@ -173,7 +173,9 @@ def iri_to_uri(iri):
     # converted.
     if iri is None:
         return iri
-    return quote(force_bytes(iri), safe=b"/#%[]=:;$&()+,!?*@'~")
+    elif isinstance(iri, Promise):
+        iri = str(iri)
+    return quote(iri, safe="/#%[]=:;$&()+,!?*@'~")
 
 
 def uri_to_iri(uri):

+ 1 - 2
docs/ref/models/instances.txt

@@ -733,8 +733,7 @@ in ``get_absolute_url()`` and have all your other code call that one place.
     Code and templates calling ``get_absolute_url()`` should be able to use the
     result directly without any further processing. You may wish to use the
     ``django.utils.encoding.iri_to_uri()`` function to help with this if you
-    are using unicode strings containing characters outside the ASCII range at
-    all.
+    are using strings containing characters outside the ASCII range.
 
 Extra instance methods
 ======================

+ 5 - 5
docs/ref/utils.txt

@@ -262,12 +262,12 @@ The functions defined in this module share the following properties:
     Convert an Internationalized Resource Identifier (IRI) portion to a URI
     portion that is suitable for inclusion in a URL.
 
-    This is the algorithm from section 3.1 of :rfc:`3987#section-3.1`. However,
-    since we are assuming input is either UTF-8 or unicode already, we can
-    simplify things a little from the full method.
+    This is the algorithm from section 3.1 of :rfc:`3987#section-3.1`, slightly
+    simplified since the input is assumed to be a string rather than an
+    arbitrary byte stream.
 
-    Takes an IRI in UTF-8 bytes and returns ASCII bytes containing the encoded
-    result.
+    Takes an IRI (string or UTF-8 bytes) and returns a string containing the
+    encoded result.
 
 .. function:: uri_to_iri(uri)