Browse Source

Deprecated django.utils.text.javascript_quote.

Refs #21725.
Baptiste Mispelon 11 years ago
parent
commit
926e18d7d1

+ 6 - 0
django/utils/text.py

@@ -4,6 +4,7 @@ import re
 import unicodedata
 from gzip import GzipFile
 from io import BytesIO
+import warnings
 
 from django.utils.encoding import force_text
 from django.utils.functional import allow_lazy, SimpleLazyObject
@@ -327,6 +328,11 @@ ustring_re = re.compile("([\u0080-\uffff])")
 
 
 def javascript_quote(s, quote_double_quotes=False):
+    msg = (
+        "django.utils.text.javascript_quote() is deprecated. "
+        "Use django.utils.html.escapejs() instead."
+    )
+    warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
 
     def fix(match):
         return "\\u%04x" % ord(match.group(1))

+ 2 - 0
docs/internals/deprecation.txt

@@ -119,6 +119,8 @@ details on these changes.
 * ``ssi`` and ``url`` template tags will be removed from the ``future`` template
   tag library (used during the 1.3/1.4 deprecation period).
 
+* ``django.utils.text.javascript_quote`` will be removed.
+
 .. _deprecation-removed-in-1.8:
 
 1.8

+ 12 - 0
docs/releases/1.7.txt

@@ -1374,3 +1374,15 @@ Django 1.3 introduced ``{% load ssi from future %}`` and
 :ttag:`ssi` and :ttag:`url` template tags. This syntax is now deprecated and
 will be removed in Django 1.9. You can simply remove the
 ``{% load ... from future %}`` tags.
+
+``django.utils.text.javascript_quote``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``javascript_quote()`` was an undocumented function present in ``django.utils.text``.
+It was used internally in the :ref:`javascript_catalog view <javascript_catalog-view>`
+whose implementation was changed to make use of ``json.dumps()`` instead.
+If you were relying on this function to provide safe output from untrusted
+strings, you should use ``django.utils.html.escapejs`` or the
+:tfilter:`escapejs` template filter.
+If all you need is to generate valid javascript strings, you can simply use
+``json.dumps()``.

+ 17 - 6
tests/utils_tests/test_text.py

@@ -2,6 +2,7 @@
 from __future__ import unicode_literals
 
 from unittest import skipUnless
+import warnings
 
 from django.test import SimpleTestCase
 from django.utils import six, text
@@ -152,16 +153,26 @@ class TestUtilsText(SimpleTestCase):
     def test_javascript_quote(self):
         input = "<script>alert('Hello \\xff.\n Welcome\there\r');</script>"
         output = r"<script>alert(\'Hello \\xff.\n Welcome\there\r\');<\/script>"
-        self.assertEqual(text.javascript_quote(input), output)
+        with warnings.catch_warnings():
+            self.assertEqual(text.javascript_quote(input), output)
 
         # Exercising quote_double_quotes keyword argument
         input = '"Text"'
-        self.assertEqual(text.javascript_quote(input), '"Text"')
-        self.assertEqual(text.javascript_quote(input, quote_double_quotes=True),
-                         '&quot;Text&quot;')
+        with warnings.catch_warnings():
+            self.assertEqual(text.javascript_quote(input), '"Text"')
+            self.assertEqual(text.javascript_quote(input, quote_double_quotes=True),
+                             '&quot;Text&quot;')
 
-    @skipUnless(IS_WIDE_BUILD)
+    @skipUnless(IS_WIDE_BUILD, 'Not running in a wide build of Python')
     def test_javascript_quote_unicode(self):
         input = "<script>alert('Hello \\xff.\n Wel𝕃come\there\r');</script>"
         output = r"<script>alert(\'Hello \\xff.\n Wel𝕃come\there\r\');<\/script>"
-        self.assertEqual(text.javascript_quote(input), output)
+        with warnings.catch_warnings():
+            self.assertEqual(text.javascript_quote(input), output)
+
+    def test_deprecation(self):
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter("always")
+            text.javascript_quote('thingy')
+            self.assertEqual(len(w), 1)
+            self.assertIn('escapejs()', repr(w[0].message))

+ 7 - 7
tests/view_tests/tests/test_i18n.py

@@ -1,5 +1,6 @@
 # -*- coding:utf-8 -*-
 import gettext
+import json
 import os
 from os import path
 import unittest
@@ -11,7 +12,6 @@ from django.test import (
 from django.utils import six
 from django.utils._os import upath
 from django.utils.translation import override
-from django.utils.text import javascript_quote
 
 try:
     from selenium.webdriver.firefox import webdriver as firefox
@@ -63,8 +63,8 @@ class I18NTests(TestCase):
                 response = self.client.get('/jsi18n/')
                 # response content must include a line like:
                 # "this is to be translated": <value of trans_txt Python variable>
-                # javascript_quote is used to be able to check unicode strings
-                self.assertContains(response, javascript_quote(trans_txt), 1)
+                # json.dumps() is used to be able to check unicode strings
+                self.assertContains(response, json.dumps(trans_txt), 1)
                 if lang_code == 'fr':
                     # Message with context (msgctxt)
                     self.assertContains(response, r'"month name\u0004May": "mai"', 1)
@@ -120,7 +120,7 @@ class JsI18NTests(TestCase):
         """
         with self.settings(LANGUAGE_CODE='fr'), override('en-us'):
             response = self.client.get('/jsi18n_english_translation/')
-            self.assertContains(response, javascript_quote('this app0 string is to be translated'))
+            self.assertContains(response, 'this app0 string is to be translated')
 
     def testI18NLanguageNonEnglishFallback(self):
         """
@@ -165,7 +165,7 @@ class JsI18NTestsMultiPackage(TestCase):
         """
         with self.settings(LANGUAGE_CODE='en-us'), override('fr'):
             response = self.client.get('/jsi18n_multi_packages1/')
-            self.assertContains(response, javascript_quote('il faut traduire cette chaîne de caractères de app1'))
+            self.assertContains(response, 'il faut traduire cette cha\\u00eene de caract\\u00e8res de app1')
 
     @modify_settings(INSTALLED_APPS={'append': ['view_tests.app3', 'view_tests.app4']})
     def testI18NDifferentNonEnLangs(self):
@@ -175,7 +175,7 @@ class JsI18NTestsMultiPackage(TestCase):
         """
         with self.settings(LANGUAGE_CODE='fr'), override('es-ar'):
             response = self.client.get('/jsi18n_multi_packages2/')
-            self.assertContains(response, javascript_quote('este texto de app3 debe ser traducido'))
+            self.assertContains(response, 'este texto de app3 debe ser traducido')
 
     def testI18NWithLocalePaths(self):
         extended_locale_paths = settings.LOCALE_PATHS + (
@@ -185,7 +185,7 @@ class JsI18NTestsMultiPackage(TestCase):
             with override('es-ar'):
                 response = self.client.get('/jsi18n/')
                 self.assertContains(response,
-                    javascript_quote('este texto de app3 debe ser traducido'))
+                    'este texto de app3 debe ser traducido')
 
 
 skip_selenium = not os.environ.get('DJANGO_SELENIUM_TESTS', False)