diff --git a/django/utils/http.py b/django/utils/http.py index af44ff498c..f47b58979c 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -31,7 +31,6 @@ def urlquote(url, safe='/'): without double-quoting occurring. """ return force_unicode(urllib.quote(smart_str(url), smart_str(safe))) - urlquote = allow_lazy(urlquote, unicode) def urlquote_plus(url, safe=''): @@ -44,6 +43,22 @@ def urlquote_plus(url, safe=''): return force_unicode(urllib.quote_plus(smart_str(url), smart_str(safe))) urlquote_plus = allow_lazy(urlquote_plus, unicode) +def urlunquote(quoted_url): + """ + A wrapper for Python's urllib.unquote() function that can operate on + the result of django.utils.http.urlquote(). + """ + return force_unicode(urllib.unquote(smart_str(quoted_url))) +urlunquote = allow_lazy(urlunquote, unicode) + +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(). + """ + return force_unicode(urllib.unquote_plus(smart_str(quoted_url))) +urlunquote_plus = allow_lazy(urlunquote_plus, unicode) + def urlencode(query, doseq=0): """ A version of Python's urllib.urlencode() function that can operate on diff --git a/tests/regressiontests/text/tests.py b/tests/regressiontests/text/tests.py index ac10a0162e..2bbd8efe37 100644 --- a/tests/regressiontests/text/tests.py +++ b/tests/regressiontests/text/tests.py @@ -3,7 +3,8 @@ from __future__ import with_statement from django.test import TestCase from django.utils.encoding import iri_to_uri -from django.utils.http import urlquote, urlquote_plus, cookie_date, http_date +from django.utils.http import (cookie_date, http_date, + urlquote, urlquote_plus, urlunquote, urlunquote_plus) from django.utils.text import get_text_list, smart_split from django.utils.translation import override @@ -60,15 +61,26 @@ class TextTests(TestCase): [u"cut:','|cut:' '"]) def test_urlquote(self): - self.assertEqual(urlquote(u'Paris & Orl\xe9ans'), u'Paris%20%26%20Orl%C3%A9ans') self.assertEqual(urlquote(u'Paris & Orl\xe9ans', safe="&"), u'Paris%20&%20Orl%C3%A9ans') + self.assertEqual( + urlunquote(u'Paris%20%26%20Orl%C3%A9ans'), + u'Paris & Orl\xe9ans') + self.assertEqual( + urlunquote(u'Paris%20&%20Orl%C3%A9ans'), + u'Paris & Orl\xe9ans') self.assertEqual(urlquote_plus(u'Paris & Orl\xe9ans'), u'Paris+%26+Orl%C3%A9ans') self.assertEqual(urlquote_plus(u'Paris & Orl\xe9ans', safe="&"), u'Paris+&+Orl%C3%A9ans') + self.assertEqual( + urlunquote_plus(u'Paris+%26+Orl%C3%A9ans'), + u'Paris & Orl\xe9ans') + self.assertEqual( + urlunquote_plus(u'Paris+&+Orl%C3%A9ans'), + u'Paris & Orl\xe9ans') def test_cookie_date(self): t = 1167616461.0