Code

Ticket #17135: 17135.3.patch

File 17135.3.patch, 30.0 KB (added by aaugustin, 2 years ago)
  • docs/internals/deprecation.txt

     
    251251  :mod:`django.core.management`. This also means that the old (pre-1.4) 
    252252  style of :file:`manage.py` file will no longer work. 
    253253 
     254* Setting the ``is_safe`` and ``needs_autoescape`` flags as attributes of 
     255  template filter functions will no longer be supported. 
     256 
    2542572.0 
    255258--- 
    256259 
  • docs/howto/custom-template-tags.txt

     
    2062061. Your filter does not introduce any HTML-unsafe characters (``<``, ``>``, 
    207207   ``'``, ``"`` or ``&``) into the result that were not already present. In 
    208208   this case, you can let Django take care of all the auto-escaping 
    209    handling for you. All you need to do is put the ``is_safe`` attribute on 
    210    your filter function and set it to ``True``, like so: 
     209   handling for you. All you need to do is set the ``is_safe`` flag to ``True`` 
     210   when you register your filter function, like so: 
    211211 
    212212   .. code-block:: python 
    213213 
    214        @register.filter 
     214       @register.filter(is_safe=True) 
    215215       def myfilter(value): 
    216216           return value 
    217        myfilter.is_safe = True 
    218217 
    219218   This attribute tells Django that if a "safe" string is passed into your 
    220219   filter, the result will still be "safe" and if a non-safe string is 
     
    236235 
    237236   .. code-block:: python 
    238237 
    239        @register.filter 
     238       @register.filter(is_safe=True) 
    240239       def add_xx(value): 
    241240           return '%sxx' % value 
    242        add_xx.is_safe = True 
    243241 
    244242   When this filter is used in a template where auto-escaping is enabled, 
    245243   Django will escape the output whenever the input is not already marked 
    246244   as "safe". 
    247245 
    248    By default, ``is_safe`` defaults to ``False``, and you can omit it from 
    249    any filters where it isn't required. 
     246   By default, ``is_safe`` is ``False``, and you can omit it from any filters 
     247   where it isn't required. 
    250248 
    251249   Be careful when deciding if your filter really does leave safe strings 
    252250   as safe. If you're *removing* characters, you might inadvertently leave 
     
    279277   can operate in templates where auto-escaping is either on or off in 
    280278   order to make things easier for your template authors. 
    281279 
    282    In order for your filter to know the current auto-escaping state, set 
    283    the ``needs_autoescape`` attribute to ``True`` on your function. (If you 
    284    don't specify this attribute, it defaults to ``False``). This attribute 
    285    tells Django that your filter function wants to be passed an extra 
    286    keyword argument, called ``autoescape``, that is ``True`` if 
    287    auto-escaping is in effect and ``False`` otherwise. 
     280   In order for your filter to know the current auto-escaping state, set the 
     281   ``needs_autoescape`` flag to ``True`` when you register your filter function. 
     282   (If you don't specify this flag, it defaults to ``False``). This flag tells 
     283   Django that your filter function wants to be passed an extra keyword 
     284   argument, called ``autoescape``, that is ``True`` if auto-escaping is in 
     285   effect and ``False`` otherwise. 
    288286 
    289287   For example, let's write a filter that emphasizes the first character of 
    290288   a string: 
     
    294292       from django.utils.html import conditional_escape 
    295293       from django.utils.safestring import mark_safe 
    296294 
     295       @register.filter(needs_autoescape=True) 
    297296       def initial_letter_filter(text, autoescape=None): 
    298297           first, other = text[0], text[1:] 
    299298           if autoescape: 
     
    302301               esc = lambda x: x 
    303302           result = '<strong>%s</strong>%s' % (esc(first), esc(other)) 
    304303           return mark_safe(result) 
    305        initial_letter_filter.needs_autoescape = True 
    306304 
    307    The ``needs_autoescape`` attribute on the filter function and the 
    308    ``autoescape`` keyword argument mean that our function will know whether 
    309    automatic escaping is in effect when the filter is called. We use 
    310    ``autoescape`` to decide whether the input data needs to be passed 
    311    through ``django.utils.html.conditional_escape`` or not. (In the latter 
    312    case, we just use the identity function as the "escape" function.) The 
    313    ``conditional_escape()`` function is like ``escape()`` except it only 
    314    escapes input that is **not** a ``SafeData`` instance. If a ``SafeData`` 
    315    instance is passed to ``conditional_escape()``, the data is returned 
    316    unchanged. 
     305   The ``needs_autoescape`` flag and the ``autoescape`` keyword argument mean 
     306   that our function will know whether automatic escaping is in effect when the 
     307   filter is called. We use ``autoescape`` to decide whether the input data 
     308   needs to be passed through ``django.utils.html.conditional_escape`` or not. 
     309   (In the latter case, we just use the identity function as the "escape" 
     310   function.) The ``conditional_escape()`` function is like ``escape()`` except 
     311   it only escapes input that is **not** a ``SafeData`` instance. If a 
     312   ``SafeData`` instance is passed to ``conditional_escape()``, the data is 
     313   returned unchanged. 
    317314 
    318315   Finally, in the above example, we remember to mark the result as safe 
    319316   so that our HTML is inserted directly into the template without further 
     
    324321   handle the auto-escaping issues and return a safe string, the 
    325322   ``is_safe`` attribute won't change anything either way. 
    326323 
     324.. versionchanged:: 1.4 
     325 
     326``is_safe`` and ``needs_autoescape`` used to be attributes of the filter 
     327function: 
     328 
     329.. code-block:: python 
     330 
     331    @register.filter 
     332    def myfilter(value): 
     333        return value 
     334    myfilter.is_safe = True 
     335 
     336.. code-block:: python 
     337 
     338    @register.filter 
     339    def initial_letter_filter(text, autoescape=None): 
     340        # ... 
     341        return mark_safe(result) 
     342    initial_letter_filter.needs_autoescape = True 
     343 
     344This syntax is deprecated. 
     345 
    327346Writing custom template tags 
    328347---------------------------- 
    329348 
  • tests/regressiontests/templates/templatetags/custom.py

     
    66 
    77register = template.Library() 
    88 
     9@register.filter 
     10@stringfilter 
    911def trim(value, num): 
    1012    return value[:num] 
    11 trim = stringfilter(trim) 
    1213 
    13 register.filter(trim) 
    14  
    1514@register.simple_tag 
    1615def no_params(): 
    1716    """Expected no_params __doc__""" 
  • django/templatetags/l10n.py

     
    55 
    66register = Library() 
    77 
    8 @register.filter 
     8@register.filter(is_safe=False) 
    99def localize(value): 
    1010    """ 
    1111    Forces a value to be rendered as a localized value, 
    1212    regardless of the value of ``settings.USE_L10N``. 
    1313    """ 
    1414    return force_unicode(formats.localize(value, use_l10n=True)) 
    15 localize.is_safe = False 
    1615 
    17 @register.filter 
     16@register.filter(is_safe=False) 
    1817def unlocalize(value): 
    1918    """ 
    2019    Forces a value to be rendered as a non-localized value, 
    2120    regardless of the value of ``settings.USE_L10N``. 
    2221    """ 
    2322    return force_unicode(value) 
    24 unlocalize.is_safe = False 
    2523 
    2624class LocalizeNode(Node): 
    2725    def __init__(self, nodelist, use_l10n): 
  • django/contrib/humanize/templatetags/humanize.py

     
    1111 
    1212register = template.Library() 
    1313 
    14 @register.filter 
     14@register.filter(is_safe=True) 
    1515def ordinal(value): 
    1616    """ 
    1717    Converts an integer to its ordinal as a string. 1 is '1st', 2 is '2nd', 
     
    2525    if value % 100 in (11, 12, 13): # special case 
    2626        return u"%d%s" % (value, suffixes[0]) 
    2727    return u"%d%s" % (value, suffixes[value % 10]) 
    28 ordinal.is_safe = True 
    2928 
    30 @register.filter 
     29@register.filter(is_safe=True) 
    3130def intcomma(value, use_l10n=True): 
    3231    """ 
    3332    Converts an integer to a string containing commas every three digits. 
     
    4746        return new 
    4847    else: 
    4948        return intcomma(new, use_l10n) 
    50 intcomma.is_safe = True 
    5149 
    5250# A tuple of standard large number to their converters 
    5351intword_converters = ( 
     
    9795    )), 
    9896) 
    9997 
    100 @register.filter 
     98@register.filter(is_safe=False) 
    10199def intword(value): 
    102100    """ 
    103101    Converts a large integer to a friendly text representation. Works best 
     
    129127            new_value = value / float(large_number) 
    130128            return _check_for_i18n(new_value, *converters(new_value)) 
    131129    return value 
    132 intword.is_safe = False 
    133130 
    134 @register.filter 
     131@register.filter(is_safe=True) 
    135132def apnumber(value): 
    136133    """ 
    137134    For numbers 1-9, returns the number spelled out. Otherwise, returns the 
     
    144141    if not 0 < value < 10: 
    145142        return value 
    146143    return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1] 
    147 apnumber.is_safe = True 
    148144 
    149145@register.filter 
    150146def naturalday(value, arg=None): 
  • django/contrib/markup/templatetags/markup.py

     
    1818 
    1919register = template.Library() 
    2020 
    21 @register.filter 
     21@register.filter(is_safe=True) 
    2222def textile(value): 
    2323    try: 
    2424        import textile 
     
    2828        return force_unicode(value) 
    2929    else: 
    3030        return mark_safe(force_unicode(textile.textile(smart_str(value), encoding='utf-8', output='utf-8'))) 
    31 textile.is_safe = True 
    3231 
    33 @register.filter 
     32@register.filter(is_safe=True) 
    3433def markdown(value, arg=''): 
    3534    """ 
    3635    Runs Markdown over a given value, optionally using various 
     
    7372                return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode)) 
    7473        else: 
    7574            return mark_safe(force_unicode(markdown.markdown(smart_str(value)))) 
    76 markdown.is_safe = True 
    7775 
    78 @register.filter 
     76@register.filter(is_safe=True) 
    7977def restructuredtext(value): 
    8078    try: 
    8179        from docutils.core import publish_parts 
     
    8785        docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {}) 
    8886        parts = publish_parts(source=smart_str(value), writer_name="html4css1", settings_overrides=docutils_settings) 
    8987        return mark_safe(force_unicode(parts["fragment"])) 
    90 restructuredtext.is_safe = True 
    91  
  • django/template/base.py

     
    10571057        self.tags[getattr(func, "_decorated_function", func).__name__] = func 
    10581058        return func 
    10591059 
    1060     def filter(self, name=None, filter_func=None): 
     1060    def filter(self, name=None, filter_func=None, **flags): 
    10611061        if name is None and filter_func is None: 
    10621062            # @register.filter() 
    1063             return self.filter_function 
    1064         elif filter_func is None: 
     1063            def dec(func): 
     1064                return self.filter_function(func, **flags) 
     1065            return dec 
     1066 
     1067        elif name is not None and filter_func is None: 
    10651068            if callable(name): 
    10661069                # @register.filter 
    1067                 return self.filter_function(name) 
     1070                return self.filter_function(name, **flags) 
    10681071            else: 
    10691072                # @register.filter('somename') or @register.filter(name='somename') 
    10701073                def dec(func): 
    1071                     return self.filter(name, func) 
     1074                    return self.filter(name, func, **flags) 
    10721075                return dec 
     1076 
    10731077        elif name is not None and filter_func is not None: 
    10741078            # register.filter('somename', somefunc) 
    10751079            self.filters[name] = filter_func 
     1080            for attr in ('is_safe', 'needs_autoescape'): 
     1081                if attr in flags: 
     1082                    value = flags[attr] 
     1083                    setattr(filter_func, attr, value) 
     1084                    if hasattr(filter_func, "_decorated_function"): 
     1085                        setattr(filter_func._decorated_function, attr, value) 
    10761086            return filter_func 
    10771087        else: 
    10781088            raise InvalidTemplateLibrary("Unsupported arguments to " 
    10791089                "Library.filter: (%r, %r)", (name, filter_func)) 
    10801090 
    1081     def filter_function(self, func): 
    1082         self.filters[getattr(func, "_decorated_function", func).__name__] = func 
    1083         return func 
     1091    def filter_function(self, func, **flags): 
     1092        name = getattr(func, "_decorated_function", func).__name__ 
     1093        return self.filter(name, func, **flags) 
    10841094 
    10851095    def simple_tag(self, func=None, takes_context=None, name=None): 
    10861096        def dec(func): 
  • django/template/defaultfilters.py

     
    3737        if args: 
    3838            args = list(args) 
    3939            args[0] = force_unicode(args[0]) 
    40             if isinstance(args[0], SafeData) and getattr(func, 'is_safe', False): 
     40            if (isinstance(args[0], SafeData) and 
     41                getattr(_dec._decorated_function, 'is_safe', False)): 
    4142                return mark_safe(func(*args, **kwargs)) 
    4243        return func(*args, **kwargs) 
    4344 
     
    4647    _dec._decorated_function = getattr(func, '_decorated_function', func) 
    4748    for attr in ('is_safe', 'needs_autoescape'): 
    4849        if hasattr(func, attr): 
     50            import warnings 
     51            warnings.warn("Setting the %s attribute of a template filter " 
     52                          "function is deprecated; use @register.filter(%s=%s) " 
     53                          "instead" % (attr, attr, getattr(func, attr)), 
     54                          PendingDeprecationWarning) 
    4955            setattr(_dec, attr, getattr(func, attr)) 
    5056    return wraps(func)(_dec) 
    5157 
     
    5359# STRINGS         # 
    5460################### 
    5561 
    56 @register.filter 
     62@register.filter(is_safe=True) 
    5763@stringfilter 
    5864def addslashes(value): 
    5965    """ 
     
    6268    filter instead. 
    6369    """ 
    6470    return value.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'") 
    65 addslashes.is_safe = True 
    6671 
    67 @register.filter 
     72@register.filter(is_safe=True) 
    6873@stringfilter 
    6974def capfirst(value): 
    7075    """Capitalizes the first character of the value.""" 
    7176    return value and value[0].upper() + value[1:] 
    72 capfirst.is_safe = True 
    7377 
    7478@register.filter("escapejs") 
    7579@stringfilter 
     
    7781    """Hex encodes characters for use in JavaScript strings.""" 
    7882    return escapejs(value) 
    7983 
    80 @register.filter("fix_ampersands") 
     84@register.filter("fix_ampersands", is_safe=True) 
    8185@stringfilter 
    8286def fix_ampersands_filter(value): 
    8387    """Replaces ampersands with ``&amp;`` entities.""" 
    8488    return fix_ampersands(value) 
    85 fix_ampersands_filter.is_safe = True 
    8689 
    8790# Values for testing floatformat input against infinity and NaN representations, 
    8891# which differ across platforms and Python versions.  Some (i.e. old Windows 
     
    9699nan = (1e200 * 1e200) // (1e200 * 1e200) 
    97100special_floats = [str(pos_inf), str(neg_inf), str(nan)] 
    98101 
    99 @register.filter 
     102@register.filter(is_safe=True) 
    100103def floatformat(text, arg=-1): 
    101104    """ 
    102105    Displays a float to a specified number of decimal places. 
     
    172175        return mark_safe(formats.number_format(number, abs(p))) 
    173176    except InvalidOperation: 
    174177        return input_val 
    175 floatformat.is_safe = True 
    176178 
    177 @register.filter 
     179@register.filter(is_safe=True) 
    178180@stringfilter 
    179181def iriencode(value): 
    180182    """Escapes an IRI value for use in a URL.""" 
    181183    return force_unicode(iri_to_uri(value)) 
    182 iriencode.is_safe = True 
    183184 
    184 @register.filter 
     185@register.filter(is_safe=True, needs_autoescape=True) 
    185186@stringfilter 
    186187def linenumbers(value, autoescape=None): 
    187188    """Displays text with line numbers.""" 
     
    196197        for i, line in enumerate(lines): 
    197198            lines[i] = (u"%0" + width  + u"d. %s") % (i + 1, escape(line)) 
    198199    return mark_safe(u'\n'.join(lines)) 
    199 linenumbers.is_safe = True 
    200 linenumbers.needs_autoescape = True 
    201200 
    202 @register.filter 
     201@register.filter(is_safe=True) 
    203202@stringfilter 
    204203def lower(value): 
    205204    """Converts a string into all lowercase.""" 
    206205    return value.lower() 
    207 lower.is_safe = True 
    208206 
    209 @register.filter 
     207@register.filter(is_safe=False) 
    210208@stringfilter 
    211209def make_list(value): 
    212210    """ 
     
    216214    For a string, it's a list of characters. 
    217215    """ 
    218216    return list(value) 
    219 make_list.is_safe = False 
    220217 
    221 @register.filter 
     218@register.filter(is_safe=True) 
    222219@stringfilter 
    223220def slugify(value): 
    224221    """ 
     
    228225    value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') 
    229226    value = unicode(re.sub('[^\w\s-]', '', value).strip().lower()) 
    230227    return mark_safe(re.sub('[-\s]+', '-', value)) 
    231 slugify.is_safe = True 
    232228 
    233 @register.filter 
     229@register.filter(is_safe=True) 
    234230def stringformat(value, arg): 
    235231    """ 
    236232    Formats the variable according to the arg, a string formatting specifier. 
     
    245241        return (u"%" + unicode(arg)) % value 
    246242    except (ValueError, TypeError): 
    247243        return u"" 
    248 stringformat.is_safe = True 
    249244 
    250 @register.filter 
     245@register.filter(is_safe=True) 
    251246@stringfilter 
    252247def title(value): 
    253248    """Converts a string into titlecase.""" 
    254249    t = re.sub("([a-z])'([A-Z])", lambda m: m.group(0).lower(), value.title()) 
    255250    return re.sub("\d([A-Z])", lambda m: m.group(0).lower(), t) 
    256 title.is_safe = True 
    257251 
    258 @register.filter 
     252@register.filter(is_safe=True) 
    259253@stringfilter 
    260254def truncatechars(value, arg): 
    261255    """ 
     
    268262    except ValueError: # Invalid literal for int(). 
    269263        return value # Fail silently. 
    270264    return Truncator(value).chars(length) 
    271 truncatechars.is_safe = True 
    272265 
    273 @register.filter 
     266@register.filter(is_safe=True) 
    274267@stringfilter 
    275268def truncatewords(value, arg): 
    276269    """ 
     
    285278    except ValueError: # Invalid literal for int(). 
    286279        return value # Fail silently. 
    287280    return Truncator(value).words(length, truncate=' ...') 
    288 truncatewords.is_safe = True 
    289281 
    290 @register.filter 
     282@register.filter(is_safe=True) 
    291283@stringfilter 
    292284def truncatewords_html(value, arg): 
    293285    """ 
     
    302294    except ValueError: # invalid literal for int() 
    303295        return value # Fail silently. 
    304296    return Truncator(value).words(length, html=True, truncate=' ...') 
    305 truncatewords_html.is_safe = True 
    306297 
    307 @register.filter 
     298@register.filter(is_safe=False) 
    308299@stringfilter 
    309300def upper(value): 
    310301    """Converts a string into all uppercase.""" 
    311302    return value.upper() 
    312 upper.is_safe = False 
    313303 
    314 @register.filter 
     304@register.filter(is_safe=False) 
    315305@stringfilter 
    316306def urlencode(value, safe=None): 
    317307    """ 
     
    326316    if safe is not None: 
    327317        kwargs['safe'] = safe 
    328318    return urlquote(value, **kwargs) 
    329 urlencode.is_safe = False 
    330319 
    331 @register.filter 
     320@register.filter(is_safe=True, needs_autoescape=True) 
    332321@stringfilter 
    333322def urlize(value, autoescape=None): 
    334323    """Converts URLs in plain text into clickable links.""" 
    335324    return mark_safe(urlize_impl(value, nofollow=True, autoescape=autoescape)) 
    336 urlize.is_safe = True 
    337 urlize.needs_autoescape = True 
    338325 
    339 @register.filter 
     326@register.filter(is_safe=True, needs_autoescape=True) 
    340327@stringfilter 
    341328def urlizetrunc(value, limit, autoescape=None): 
    342329    """ 
     
    347334    """ 
    348335    return mark_safe(urlize_impl(value, trim_url_limit=int(limit), nofollow=True, 
    349336                            autoescape=autoescape)) 
    350 urlizetrunc.is_safe = True 
    351 urlizetrunc.needs_autoescape = True 
    352337 
    353 @register.filter 
     338@register.filter(is_safe=False) 
    354339@stringfilter 
    355340def wordcount(value): 
    356341    """Returns the number of words.""" 
    357342    return len(value.split()) 
    358 wordcount.is_safe = False 
    359343 
    360 @register.filter 
     344@register.filter(is_safe=True) 
    361345@stringfilter 
    362346def wordwrap(value, arg): 
    363347    """ 
     
    366350    Argument: number of characters to wrap the text at. 
    367351    """ 
    368352    return wrap(value, int(arg)) 
    369 wordwrap.is_safe = True 
    370353 
    371 @register.filter 
     354@register.filter(is_safe=True) 
    372355@stringfilter 
    373356def ljust(value, arg): 
    374357    """ 
     
    377360    Argument: field size. 
    378361    """ 
    379362    return value.ljust(int(arg)) 
    380 ljust.is_safe = True 
    381363 
    382 @register.filter 
     364@register.filter(is_safe=True) 
    383365@stringfilter 
    384366def rjust(value, arg): 
    385367    """ 
     
    388370    Argument: field size. 
    389371    """ 
    390372    return value.rjust(int(arg)) 
    391 rjust.is_safe = True 
    392373 
    393 @register.filter 
     374@register.filter(is_safe=True) 
    394375@stringfilter 
    395376def center(value, arg): 
    396377    """Centers the value in a field of a given width.""" 
    397378    return value.center(int(arg)) 
    398 center.is_safe = True 
    399379 
    400380@register.filter 
    401381@stringfilter 
     
    413393# HTML STRINGS    # 
    414394################### 
    415395 
    416 @register.filter("escape") 
     396@register.filter("escape", is_safe=True) 
    417397@stringfilter 
    418398def escape_filter(value): 
    419399    """ 
    420400    Marks the value as a string that should not be auto-escaped. 
    421401    """ 
    422402    return mark_for_escaping(value) 
    423 escape_filter.is_safe = True 
    424403 
    425 @register.filter 
     404@register.filter(is_safe=True) 
    426405@stringfilter 
    427406def force_escape(value): 
    428407    """ 
     
    431410    possible escaping). 
    432411    """ 
    433412    return mark_safe(escape(value)) 
    434 force_escape.is_safe = True 
    435413 
    436 @register.filter("linebreaks") 
     414@register.filter("linebreaks", is_safe=True, needs_autoescape=True) 
    437415@stringfilter 
    438416def linebreaks_filter(value, autoescape=None): 
    439417    """ 
     
    443421    """ 
    444422    autoescape = autoescape and not isinstance(value, SafeData) 
    445423    return mark_safe(linebreaks(value, autoescape)) 
    446 linebreaks_filter.is_safe = True 
    447 linebreaks_filter.needs_autoescape = True 
    448424 
    449 @register.filter 
     425@register.filter(is_safe=True, needs_autoescape=True) 
    450426@stringfilter 
    451427def linebreaksbr(value, autoescape=None): 
    452428    """ 
     
    458434    if autoescape: 
    459435        value = escape(value) 
    460436    return mark_safe(value.replace('\n', '<br />')) 
    461 linebreaksbr.is_safe = True 
    462 linebreaksbr.needs_autoescape = True 
    463437 
    464 @register.filter 
     438@register.filter(is_safe=True) 
    465439@stringfilter 
    466440def safe(value): 
    467441    """ 
    468442    Marks the value as a string that should not be auto-escaped. 
    469443    """ 
    470444    return mark_safe(value) 
    471 safe.is_safe = True 
    472445 
    473 @register.filter 
     446@register.filter(is_safe=True) 
    474447def safeseq(value): 
    475448    """ 
    476449    A "safe" filter for sequences. Marks each element in the sequence, 
     
    478451    with the results. 
    479452    """ 
    480453    return [mark_safe(force_unicode(obj)) for obj in value] 
    481 safeseq.is_safe = True 
    482454 
    483 @register.filter 
     455@register.filter(is_safe=True) 
    484456@stringfilter 
    485457def removetags(value, tags): 
    486458    """Removes a space separated list of [X]HTML tags from the output.""" 
     
    491463    value = starttag_re.sub(u'', value) 
    492464    value = endtag_re.sub(u'', value) 
    493465    return value 
    494 removetags.is_safe = True 
    495466 
    496 @register.filter 
     467@register.filter(is_safe=True) 
    497468@stringfilter 
    498469def striptags(value): 
    499470    """Strips all [X]HTML tags.""" 
    500471    return strip_tags(value) 
    501 striptags.is_safe = True 
    502472 
    503473################### 
    504474# LISTS           # 
    505475################### 
    506476 
    507 @register.filter 
     477@register.filter(is_safe=False) 
    508478def dictsort(value, arg): 
    509479    """ 
    510480    Takes a list of dicts, returns that list sorted by the property given in 
    511481    the argument. 
    512482    """ 
    513483    return sorted(value, key=Variable(arg).resolve) 
    514 dictsort.is_safe = False 
    515484 
    516 @register.filter 
     485@register.filter(is_safe=False) 
    517486def dictsortreversed(value, arg): 
    518487    """ 
    519488    Takes a list of dicts, returns that list sorted in reverse order by the 
    520489    property given in the argument. 
    521490    """ 
    522491    return sorted(value, key=Variable(arg).resolve, reverse=True) 
    523 dictsortreversed.is_safe = False 
    524492 
    525 @register.filter 
     493@register.filter(is_safe=False) 
    526494def first(value): 
    527495    """Returns the first item in a list.""" 
    528496    try: 
    529497        return value[0] 
    530498    except IndexError: 
    531499        return u'' 
    532 first.is_safe = False 
    533500 
    534 @register.filter 
     501@register.filter(is_safe=True, needs_autoescape=True) 
    535502def join(value, arg, autoescape=None): 
    536503    """ 
    537504    Joins a list with a string, like Python's ``str.join(list)``. 
     
    544511    except AttributeError: # fail silently but nicely 
    545512        return value 
    546513    return mark_safe(data) 
    547 join.is_safe = True 
    548 join.needs_autoescape = True 
    549514 
    550 @register.filter 
     515@register.filter(is_safe=True) 
    551516def last(value): 
    552517    "Returns the last item in a list" 
    553518    try: 
    554519        return value[-1] 
    555520    except IndexError: 
    556521        return u'' 
    557 last.is_safe = True 
    558522 
    559 @register.filter 
     523@register.filter(is_safe=True) 
    560524def length(value): 
    561525    """Returns the length of the value - useful for lists.""" 
    562526    try: 
    563527        return len(value) 
    564528    except (ValueError, TypeError): 
    565529        return '' 
    566 length.is_safe = True 
    567530 
    568 @register.filter 
     531@register.filter(is_safe=False) 
    569532def length_is(value, arg): 
    570533    """Returns a boolean of whether the value's length is the argument.""" 
    571534    try: 
    572535        return len(value) == int(arg) 
    573536    except (ValueError, TypeError): 
    574537        return '' 
    575 length_is.is_safe = False 
    576538 
    577 @register.filter 
     539@register.filter(is_safe=True) 
    578540def random(value): 
    579541    """Returns a random item from the list.""" 
    580542    return random_module.choice(value) 
    581 random.is_safe = True 
    582543 
    583 @register.filter("slice") 
     544@register.filter("slice", is_safe=True) 
    584545def slice_filter(value, arg): 
    585546    """ 
    586547    Returns a slice of the list. 
     
    600561 
    601562    except (ValueError, TypeError): 
    602563        return value # Fail silently. 
    603 slice_filter.is_safe = True 
    604564 
    605 @register.filter 
     565@register.filter(is_safe=True, needs_autoescape=True) 
    606566def unordered_list(value, autoescape=None): 
    607567    """ 
    608568    Recursively takes a self-nested list and returns an HTML unordered list -- 
     
    688648        return '\n'.join(output) 
    689649    value, converted = convert_old_style_list(value) 
    690650    return mark_safe(_helper(value)) 
    691 unordered_list.is_safe = True 
    692 unordered_list.needs_autoescape = True 
    693651 
    694652################### 
    695653# INTEGERS        # 
    696654################### 
    697655 
    698 @register.filter 
     656@register.filter(is_safe=False) 
    699657def add(value, arg): 
    700658    """Adds the arg to the value.""" 
    701659    try: 
     
    705663            return value + arg 
    706664        except Exception: 
    707665            return '' 
    708 add.is_safe = False 
    709666 
    710 @register.filter 
     667@register.filter(is_safe=False) 
    711668def get_digit(value, arg): 
    712669    """ 
    713670    Given a whole number, returns the requested digit of it, where 1 is the 
     
    726683        return int(str(value)[-arg]) 
    727684    except IndexError: 
    728685        return 0 
    729 get_digit.is_safe = False 
    730686 
    731687################### 
    732688# DATES           # 
    733689################### 
    734690 
    735 @register.filter 
     691@register.filter(is_safe=False) 
    736692def date(value, arg=None): 
    737693    """Formats a date according to the given format.""" 
    738694    if not value: 
     
    746702            return format(value, arg) 
    747703        except AttributeError: 
    748704            return '' 
    749 date.is_safe = False 
    750705 
    751 @register.filter 
     706@register.filter(is_safe=False) 
    752707def time(value, arg=None): 
    753708    """Formats a time according to the given format.""" 
    754709    if value in (None, u''): 
     
    762717            return time_format(value, arg) 
    763718        except AttributeError: 
    764719            return '' 
    765 time.is_safe = False 
    766720 
    767 @register.filter("timesince") 
     721@register.filter("timesince", is_safe=False) 
    768722def timesince_filter(value, arg=None): 
    769723    """Formats a date as the time since that date (i.e. "4 days, 6 hours").""" 
    770724    if not value: 
     
    775729        return timesince(value) 
    776730    except (ValueError, TypeError): 
    777731        return u'' 
    778 timesince_filter.is_safe = False 
    779732 
    780 @register.filter("timeuntil") 
     733@register.filter("timeuntil", is_safe=False) 
    781734def timeuntil_filter(value, arg=None): 
    782735    """Formats a date as the time until that date (i.e. "4 days, 6 hours").""" 
    783736    if not value: 
     
    786739        return timeuntil(value, arg) 
    787740    except (ValueError, TypeError): 
    788741        return u'' 
    789 timeuntil_filter.is_safe = False 
    790742 
    791743################### 
    792744# LOGIC           # 
    793745################### 
    794746 
    795 @register.filter 
     747@register.filter(is_safe=False) 
    796748def default(value, arg): 
    797749    """If value is unavailable, use given default.""" 
    798750    return value or arg 
    799 default.is_safe = False 
    800751 
    801 @register.filter 
     752@register.filter(is_safe=False) 
    802753def default_if_none(value, arg): 
    803754    """If value is None, use given default.""" 
    804755    if value is None: 
    805756        return arg 
    806757    return value 
    807 default_if_none.is_safe = False 
    808758 
    809 @register.filter 
     759@register.filter(is_safe=False) 
    810760def divisibleby(value, arg): 
    811761    """Returns True if the value is devisible by the argument.""" 
    812762    return int(value) % int(arg) == 0 
    813 divisibleby.is_safe = False 
    814763 
    815 @register.filter 
     764@register.filter(is_safe=False) 
    816765def yesno(value, arg=None): 
    817766    """ 
    818767    Given a string mapping values for true, false and (optionally) None, 
     
    843792    if value: 
    844793        return yes 
    845794    return no 
    846 yesno.is_safe = False 
    847795 
    848796################### 
    849797# MISC            # 
    850798################### 
    851799 
    852 @register.filter 
     800@register.filter(is_safe=True) 
    853801def filesizeformat(bytes): 
    854802    """ 
    855803    Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 
     
    873821    if bytes < 1024 * 1024 * 1024 * 1024 * 1024: 
    874822        return ugettext("%s TB") % filesize_number_format(bytes / (1024 * 1024 * 1024 * 1024)) 
    875823    return ugettext("%s PB") % filesize_number_format(bytes / (1024 * 1024 * 1024 * 1024 * 1024)) 
    876 filesizeformat.is_safe = True 
    877824 
    878 @register.filter 
     825@register.filter(is_safe=False) 
    879826def pluralize(value, arg=u's'): 
    880827    """ 
    881828    Returns a plural suffix if the value is not 1. By default, 's' is used as 
     
    918865        except TypeError: # len() of unsized object. 
    919866            pass 
    920867    return singular_suffix 
    921 pluralize.is_safe = False 
    922868 
    923 @register.filter("phone2numeric") 
     869@register.filter("phone2numeric", is_safe=True) 
    924870def phone2numeric_filter(value): 
    925871    """Takes a phone number and converts it in to its numerical equivalent.""" 
    926872    return phone2numeric(value) 
    927 phone2numeric_filter.is_safe = True 
    928873 
    929 @register.filter 
     874@register.filter(is_safe=True) 
    930875def pprint(value): 
    931876    """A wrapper around pprint.pprint -- for debugging, really.""" 
    932877    try: 
    933878        return pformat(value) 
    934879    except Exception, e: 
    935880        return u"Error in formatting: %s" % force_unicode(e, errors="replace") 
    936 pprint.is_safe = True