浏览代码

Refs #24046 -- Removed mark_for_escaping() per deprecation timeline.

Tim Graham 8 年之前
父节点
当前提交
60ca37d2e5

+ 2 - 21
django/template/base.py

@@ -54,22 +54,18 @@ from __future__ import unicode_literals
 import inspect
 import logging
 import re
-import warnings
 
 from django.template.context import (  # NOQA: imported for backwards compatibility
     BaseContext, Context, ContextPopException, RequestContext,
 )
 from django.utils import six
-from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.encoding import (
     force_str, force_text, python_2_unicode_compatible,
 )
 from django.utils.formats import localize
 from django.utils.html import conditional_escape, escape
 from django.utils.inspect import getargspec
-from django.utils.safestring import (
-    EscapeData, SafeData, mark_for_escaping, mark_safe,
-)
+from django.utils.safestring import SafeData, mark_safe
 from django.utils.text import (
     get_text_list, smart_split, unescape_string_literal,
 )
@@ -713,7 +709,6 @@ class FilterExpression(object):
                         obj = string_if_invalid
         else:
             obj = self.var
-        escape_isnt_last_filter = True
         for func, args in self.filters:
             arg_vals = []
             for lookup, arg in args:
@@ -729,22 +724,8 @@ class FilterExpression(object):
                 new_obj = func(obj, *arg_vals)
             if getattr(func, 'is_safe', False) and isinstance(obj, SafeData):
                 obj = mark_safe(new_obj)
-            elif isinstance(obj, EscapeData):
-                with warnings.catch_warnings():
-                    # Ignore mark_for_escaping deprecation as this will be
-                    # removed in Django 2.0.
-                    warnings.simplefilter('ignore', category=RemovedInDjango20Warning)
-                    obj = mark_for_escaping(new_obj)
-                    escape_isnt_last_filter = False
             else:
                 obj = new_obj
-        if not escape_isnt_last_filter:
-            warnings.warn(
-                "escape isn't the last filter in %s and will be applied "
-                "immediately in Django 2.0 so the output may change."
-                % [func.__name__ for func, _ in self.filters],
-                RemovedInDjango20Warning, stacklevel=2
-            )
         return obj
 
     def args_check(name, func, provided):
@@ -1015,7 +996,7 @@ def render_value_in_context(value, context):
     value = template_localtime(value, use_tz=context.use_tz)
     value = localize(value, use_l10n=context.use_l10n)
     value = force_text(value)
-    if context.autoescape or isinstance(value, EscapeData):
+    if context.autoescape:
         return conditional_escape(value)
     else:
         return value

+ 2 - 8
django/template/defaultfilters.py

@@ -3,7 +3,6 @@ from __future__ import unicode_literals
 
 import random as random_module
 import re
-import warnings
 from decimal import ROUND_HALF_UP, Context, Decimal, InvalidOperation
 from functools import wraps
 from operator import itemgetter
@@ -11,14 +10,13 @@ from pprint import pformat
 
 from django.utils import formats, six
 from django.utils.dateformat import format, time_format
-from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.encoding import force_text, iri_to_uri
 from django.utils.html import (
     avoid_wrapping, conditional_escape, escape, escapejs, linebreaks,
     strip_tags, urlize as _urlize,
 )
 from django.utils.http import urlquote
-from django.utils.safestring import SafeData, mark_for_escaping, mark_safe
+from django.utils.safestring import SafeData, mark_safe
 from django.utils.text import (
     Truncator, normalize_newlines, phone2numeric, slugify as _slugify, wrap,
 )
@@ -442,11 +440,7 @@ def escape_filter(value):
     """
     Marks the value as a string that should be auto-escaped.
     """
-    with warnings.catch_warnings():
-        # Ignore mark_for_escaping deprecation -- this will use
-        # conditional_escape() in Django 2.0.
-        warnings.simplefilter('ignore', category=RemovedInDjango20Warning)
-        return mark_for_escaping(value)
+    return conditional_escape(value)
 
 
 @register.filter(is_safe=True)

+ 0 - 46
django/utils/safestring.py

@@ -4,39 +4,11 @@ without further escaping in HTML. Marking something as a "safe string" means
 that the producer of the string has already turned characters that should not
 be interpreted by the HTML engine (e.g. '<') into the appropriate entities.
 """
-import warnings
 
 from django.utils import six
-from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.functional import Promise, curry, wraps
 
 
-class EscapeData(object):
-    pass
-
-
-class EscapeBytes(bytes, EscapeData):
-    """
-    A byte string that should be HTML-escaped when output.
-    """
-    pass
-
-
-class EscapeText(six.text_type, EscapeData):
-    """
-    A unicode string object that should be HTML-escaped when output.
-    """
-    pass
-
-
-if six.PY3:
-    EscapeString = EscapeText
-else:
-    EscapeString = EscapeBytes
-    # backwards compatibility for Python 2
-    EscapeUnicode = EscapeText
-
-
 class SafeData(object):
     def __html__(self):
         """
@@ -144,21 +116,3 @@ def mark_safe(s):
     if callable(s):
         return _safety_decorator(mark_safe, s)
     return SafeString(str(s))
-
-
-def mark_for_escaping(s):
-    """
-    Explicitly mark a string as requiring HTML escaping upon output. Has no
-    effect on SafeData subclasses.
-
-    Can be called multiple times on a single string (the resulting escaping is
-    only applied once).
-    """
-    warnings.warn('mark_for_escaping() is deprecated.', RemovedInDjango20Warning)
-    if hasattr(s, '__html__') or isinstance(s, EscapeData):
-        return s
-    if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
-        return EscapeBytes(s)
-    if isinstance(s, (six.text_type, Promise)):
-        return EscapeText(s)
-    return EscapeString(str(s))

+ 0 - 11
docs/ref/templates/builtins.txt

@@ -1636,11 +1636,6 @@ Escapes a string's HTML. Specifically, it makes these replacements:
 * ``"`` (double quote) is converted to ``&quot;``
 * ``&`` is converted to ``&amp;``
 
-The escaping is only applied when the string is output, so it does not matter
-where in a chained sequence of filters you put ``escape``: it will always be
-applied as though it were the last filter. If you want escaping to be applied
-immediately, use the :tfilter:`force_escape` filter.
-
 Applying ``escape`` to a variable that would normally have auto-escaping
 applied to the result will only result in one round of escaping being done. So
 it is safe to use this function even in auto-escaping environments. If you want
@@ -1652,12 +1647,6 @@ For example, you can apply ``escape`` to fields when :ttag:`autoescape` is off::
         {{ title|escape }}
     {% endautoescape %}
 
-.. deprecated:: 1.10
-
-    The "lazy" behavior of the ``escape`` filter is deprecated. It will change
-    to immediately apply :func:`~django.utils.html.conditional_escape` in
-    Django 2.0.
-
 .. templatefilter:: escapejs
 
 ``escapejs``

+ 0 - 10
docs/ref/utils.txt

@@ -841,16 +841,6 @@ appropriate entities.
 
         Added support for decorator usage.
 
-.. function:: mark_for_escaping(s)
-
-    .. deprecated:: 1.10
-
-    Explicitly mark a string as requiring HTML escaping upon output. Has no
-    effect on ``SafeData`` subclasses.
-
-    Can be called multiple times on a single string (the resulting escaping is
-    only applied once).
-
 ``django.utils.text``
 =====================
 

+ 6 - 0
docs/releases/2.0.txt

@@ -378,3 +378,9 @@ these features.
 
 * ``FileField`` methods ``get_directory_name()`` and ``get_filename()`` are
   removed.
+
+* The ``mark_for_escaping()`` function and the classes it uses: ``EscapeData``,
+  ``EscapeBytes``, ``EscapeText``, ``EscapeString``, and ``EscapeUnicode`` are
+  removed.
+
+* The ``escape`` filter now uses ``django.utils.html.conditional_escape()``.

+ 4 - 8
docs/topics/python3.txt

@@ -112,22 +112,18 @@ For forwards compatibility, the new names work as of Django 1.4.2.
     information.
 
 :mod:`django.utils.safestring` is mostly used via the
-:func:`~django.utils.safestring.mark_safe` and
-:func:`~django.utils.safestring.mark_for_escaping` functions, which didn't
-change. In case you're using the internals, here are the name changes:
+:func:`~django.utils.safestring.mark_safe` function, which didn't change. In
+case you're using the internals, here are the name changes:
 
 ==================  ==================
 Old name            New name
 ==================  ==================
-``EscapeString``    ``EscapeBytes``
-``EscapeUnicode``   ``EscapeText``
 ``SafeString``      ``SafeBytes``
 ``SafeUnicode``     ``SafeText``
 ==================  ==================
 
-For backwards compatibility, the old names still work on Python 2. Under
-Python 3, ``EscapeString`` and ``SafeString`` are aliases for ``EscapeText``
-and ``SafeText`` respectively.
+For backwards compatibility, the old names still work on Python 2. On Python 3,
+``SafeString`` is an alias for ``SafeText``.
 
 For forwards compatibility, the new names work as of Django 1.4.2.
 

+ 4 - 19
tests/template_tests/filter_tests/test_chaining.py

@@ -1,8 +1,4 @@
-import warnings
-
-from django.test import SimpleTestCase, ignore_warnings
-from django.test.utils import reset_warning_registry
-from django.utils.deprecation import RemovedInDjango20Warning
+from django.test import SimpleTestCase
 from django.utils.safestring import mark_safe
 
 from ..utils import setup
@@ -42,20 +38,9 @@ class ChainingTests(SimpleTestCase):
     # Using a filter that forces safeness does not lead to double-escaping
     @setup({'chaining05': '{{ a|escape|capfirst }}'})
     def test_chaining05(self):
-        reset_warning_registry()
-        with warnings.catch_warnings(record=True) as warns:
-            warnings.simplefilter('always')
-            output = self.engine.render_to_string('chaining05', {'a': 'a < b'})
-            self.assertEqual(output, 'A &lt; b')
-
-        self.assertEqual(len(warns), 1)
-        self.assertEqual(
-            str(warns[0].message),
-            "escape isn't the last filter in ['escape_filter', 'capfirst'] and "
-            "will be applied immediately in Django 2.0 so the output may change."
-        )
-
-    @ignore_warnings(category=RemovedInDjango20Warning)
+        output = self.engine.render_to_string('chaining05', {'a': 'a < b'})
+        self.assertEqual(output, 'A &lt; b')
+
     @setup({'chaining06': '{% autoescape off %}{{ a|escape|capfirst }}{% endautoescape %}'})
     def test_chaining06(self):
         output = self.engine.render_to_string('chaining06', {'a': 'a < b'})

+ 1 - 6
tests/template_tests/filter_tests/test_escape.py

@@ -1,7 +1,6 @@
 from django.template.defaultfilters import escape
-from django.test import SimpleTestCase, ignore_warnings
+from django.test import SimpleTestCase
 from django.utils import six
-from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.functional import Promise, lazy
 from django.utils.safestring import mark_safe
 
@@ -24,15 +23,11 @@ class EscapeTests(SimpleTestCase):
         output = self.engine.render_to_string('escape02', {"a": "x&y", "b": mark_safe("x&y")})
         self.assertEqual(output, "x&amp;y x&y")
 
-    # It is only applied once, regardless of the number of times it
-    # appears in a chain (to be changed in Django 2.0).
-    @ignore_warnings(category=RemovedInDjango20Warning)
     @setup({'escape03': '{% autoescape off %}{{ a|escape|escape }}{% endautoescape %}'})
     def test_escape03(self):
         output = self.engine.render_to_string('escape03', {"a": "x&y"})
         self.assertEqual(output, "x&amp;y")
 
-    @ignore_warnings(category=RemovedInDjango20Warning)
     @setup({'escape04': '{{ a|escape|escape }}'})
     def test_escape04(self):
         output = self.engine.render_to_string('escape04', {"a": "x&y"})

+ 4 - 8
tests/template_tests/filter_tests/test_force_escape.py

@@ -2,8 +2,7 @@
 from __future__ import unicode_literals
 
 from django.template.defaultfilters import force_escape
-from django.test import SimpleTestCase, ignore_warnings
-from django.utils.deprecation import RemovedInDjango20Warning
+from django.test import SimpleTestCase
 from django.utils.safestring import SafeData
 
 from ..utils import setup
@@ -36,8 +35,7 @@ class ForceEscapeTests(SimpleTestCase):
         self.assertEqual(output, "x&amp;amp;y")
 
     # Because the result of force_escape is "safe", an additional
-    # escape filter has no effect (to be changed in Django 2.0).
-    @ignore_warnings(category=RemovedInDjango20Warning)
+    # escape filter has no effect.
     @setup({'force-escape05': '{% autoescape off %}{{ a|force_escape|escape }}{% endautoescape %}'})
     def test_force_escape05(self):
         output = self.engine.render_to_string('force-escape05', {"a": "x&y"})
@@ -48,17 +46,15 @@ class ForceEscapeTests(SimpleTestCase):
         output = self.engine.render_to_string('force-escape06', {"a": "x&y"})
         self.assertEqual(output, "x&amp;y")
 
-    @ignore_warnings(category=RemovedInDjango20Warning)
     @setup({'force-escape07': '{% autoescape off %}{{ a|escape|force_escape }}{% endautoescape %}'})
     def test_force_escape07(self):
         output = self.engine.render_to_string('force-escape07', {"a": "x&y"})
-        self.assertEqual(output, "x&amp;y")
+        self.assertEqual(output, "x&amp;amp;y")
 
-    @ignore_warnings(category=RemovedInDjango20Warning)
     @setup({'force-escape08': '{{ a|escape|force_escape }}'})
     def test_force_escape08(self):
         output = self.engine.render_to_string('force-escape08', {"a": "x&y"})
-        self.assertEqual(output, "x&amp;y")
+        self.assertEqual(output, "x&amp;amp;y")
 
 
 class FunctionTests(SimpleTestCase):

+ 2 - 39
tests/utils_tests/test_safestring.py

@@ -1,14 +1,11 @@
 from __future__ import unicode_literals
 
 from django.template import Context, Template
-from django.test import SimpleTestCase, ignore_warnings
+from django.test import SimpleTestCase
 from django.utils import html, six, text
-from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.encoding import force_bytes
 from django.utils.functional import lazy, lazystr
-from django.utils.safestring import (
-    EscapeData, SafeData, mark_for_escaping, mark_safe,
-)
+from django.utils.safestring import SafeData, mark_safe
 
 lazybytes = lazy(force_bytes, bytes)
 
@@ -63,40 +60,6 @@ class SafeStringTest(SimpleTestCase):
     def test_mark_safe_lazy_result_implements_dunder_html(self):
         self.assertEqual(mark_safe(lazystr('a&b')).__html__(), 'a&b')
 
-    @ignore_warnings(category=RemovedInDjango20Warning)
-    def test_mark_for_escaping(self):
-        s = mark_for_escaping('a&b')
-        self.assertRenderEqual('{{ s }}', 'a&amp;b', s=s)
-        self.assertRenderEqual('{{ s }}', 'a&amp;b', s=mark_for_escaping(s))
-
-    @ignore_warnings(category=RemovedInDjango20Warning)
-    def test_mark_for_escaping_object_implementing_dunder_html(self):
-        e = customescape('<a&b>')
-        s = mark_for_escaping(e)
-        self.assertIs(s, e)
-
-        self.assertRenderEqual('{{ s }}', '<<a&b>>', s=s)
-        self.assertRenderEqual('{{ s|force_escape }}', '&lt;a&amp;b&gt;', s=s)
-
-    @ignore_warnings(category=RemovedInDjango20Warning)
-    def test_mark_for_escaping_lazy(self):
-        s = lazystr('a&b')
-        b = lazybytes(b'a&b')
-
-        self.assertIsInstance(mark_for_escaping(s), EscapeData)
-        self.assertIsInstance(mark_for_escaping(b), EscapeData)
-        self.assertRenderEqual('{% autoescape off %}{{ s }}{% endautoescape %}', 'a&amp;b', s=mark_for_escaping(s))
-
-    @ignore_warnings(category=RemovedInDjango20Warning)
-    def test_mark_for_escaping_object_implementing_dunder_str(self):
-        class Obj(object):
-            def __str__(self):
-                return '<obj>'
-
-        s = mark_for_escaping(Obj())
-
-        self.assertRenderEqual('{{ s }}', '&lt;obj&gt;', s=s)
-
     def test_add_lazy_safe_text_and_safe_text(self):
         s = html.escape(lazystr('a'))
         s += mark_safe('&b')