| 1 | Index: django/utils/safestring.py
|
|---|
| 2 | ===================================================================
|
|---|
| 3 | --- django/utils/safestring.py (revision 9781)
|
|---|
| 4 | +++ django/utils/safestring.py (working copy)
|
|---|
| 5 | @@ -4,7 +4,7 @@
|
|---|
| 6 | that the producer of the string has already turned characters that should not
|
|---|
| 7 | be interpreted by the HTML engine (e.g. '<') into the appropriate entities.
|
|---|
| 8 | """
|
|---|
| 9 | -from django.utils.functional import curry, Promise
|
|---|
| 10 | +from django.utils.functional import curry, wraps, Promise
|
|---|
| 11 |
|
|---|
| 12 | class EscapeData(object):
|
|---|
| 13 | pass
|
|---|
| 14 | @@ -86,13 +86,24 @@
|
|---|
| 15 |
|
|---|
| 16 | encode = curry(_proxy_method, method = unicode.encode)
|
|---|
| 17 |
|
|---|
| 18 | -def mark_safe(s):
|
|---|
| 19 | +def _safety_decorator(safety_marker, func):
|
|---|
| 20 | + @wraps(func)
|
|---|
| 21 | + def wrapped(*args, **kwargs):
|
|---|
| 22 | + return safety_marker(func(*args, **kwargs))
|
|---|
| 23 | + return wrapped
|
|---|
| 24 | +
|
|---|
| 25 | +
|
|---|
| 26 | +def mark_safe(s=None):
|
|---|
| 27 | """
|
|---|
| 28 | Explicitly mark a string as safe for (HTML) output purposes. The returned
|
|---|
| 29 | object can be used everywhere a string or unicode object is appropriate.
|
|---|
| 30 |
|
|---|
| 31 | Can be called multiple times on a single string.
|
|---|
| 32 | """
|
|---|
| 33 | + if s is None: # Used like: @mark_safe()
|
|---|
| 34 | + return curry(_safety_decorator, mark_safe)
|
|---|
| 35 | + if callable(s): # Used like: @mark_safe
|
|---|
| 36 | + return _safety_decorator(mark_safe, s)
|
|---|
| 37 | if isinstance(s, SafeData):
|
|---|
| 38 | return s
|
|---|
| 39 | if isinstance(s, str) or (isinstance(s, Promise) and s._delegate_str):
|
|---|
| 40 | @@ -101,7 +112,7 @@
|
|---|
| 41 | return SafeUnicode(s)
|
|---|
| 42 | return SafeString(str(s))
|
|---|
| 43 |
|
|---|
| 44 | -def mark_for_escaping(s):
|
|---|
| 45 | +def mark_for_escaping(s=None):
|
|---|
| 46 | """
|
|---|
| 47 | Explicitly mark a string as requiring HTML escaping upon output. Has no
|
|---|
| 48 | effect on SafeData subclasses.
|
|---|
| 49 | @@ -109,6 +120,11 @@
|
|---|
| 50 | Can be called multiple times on a single string (the resulting escaping is
|
|---|
| 51 | only applied once).
|
|---|
| 52 | """
|
|---|
| 53 | +
|
|---|
| 54 | + if s is None:
|
|---|
| 55 | + return curry(_safety_decorator, mark_for_escaping)
|
|---|
| 56 | + if callable(s):
|
|---|
| 57 | + return _safety_decorator(mark_for_escaping, s)
|
|---|
| 58 | if isinstance(s, (SafeData, EscapeData)):
|
|---|
| 59 | return s
|
|---|
| 60 | if isinstance(s, str) or (isinstance(s, Promise) and s._delegate_str):
|
|---|
| 61 | Index: tests/regressiontests/decorators/tests.py
|
|---|
| 62 | ===================================================================
|
|---|
| 63 | --- tests/regressiontests/decorators/tests.py (revision 9781)
|
|---|
| 64 | +++ tests/regressiontests/decorators/tests.py (working copy)
|
|---|
| 65 | @@ -3,6 +3,7 @@
|
|---|
| 66 |
|
|---|
| 67 | from django.http import HttpResponse
|
|---|
| 68 | from django.utils.functional import allow_lazy, lazy, memoize
|
|---|
| 69 | +from django.utils.safestring import mark_safe, mark_for_escaping
|
|---|
| 70 | from django.views.decorators.http import require_http_methods, require_GET, require_POST
|
|---|
| 71 | from django.views.decorators.vary import vary_on_headers, vary_on_cookie
|
|---|
| 72 | from django.views.decorators.cache import cache_page, never_cache, cache_control
|
|---|
| 73 | @@ -14,6 +15,7 @@
|
|---|
| 74 | return HttpResponse('<html><body>dummy</body></html>')
|
|---|
| 75 | fully_decorated.anything = "Expected __dict__"
|
|---|
| 76 |
|
|---|
| 77 | +
|
|---|
| 78 | # django.views.decorators.http
|
|---|
| 79 | fully_decorated = require_http_methods(["GET"])(fully_decorated)
|
|---|
| 80 | fully_decorated = require_GET(fully_decorated)
|
|---|
| 81 | @@ -41,8 +43,11 @@
|
|---|
| 82 | fully_decorated = allow_lazy(fully_decorated)
|
|---|
| 83 | fully_decorated = lazy(fully_decorated)
|
|---|
| 84 |
|
|---|
| 85 | +# django.utils.safestring
|
|---|
| 86 | +fully_decorated = mark_safe(fully_decorated)
|
|---|
| 87 | +fully_decorated = mark_for_escaping(fully_decorated)
|
|---|
| 88 | +
|
|---|
| 89 | class DecoratorsTest(TestCase):
|
|---|
| 90 | -
|
|---|
| 91 | def test_attributes(self):
|
|---|
| 92 | """
|
|---|
| 93 | Tests that django decorators set certain attributes of the wrapped
|
|---|
| 94 | @@ -54,3 +59,37 @@
|
|---|
| 95 | self.assertEquals(fully_decorated.__name__, 'fully_decorated')
|
|---|
| 96 | self.assertEquals(fully_decorated.__doc__, 'Expected __doc__')
|
|---|
| 97 | self.assertEquals(fully_decorated.__dict__['anything'], 'Expected __dict__')
|
|---|
| 98 | +
|
|---|
| 99 | + def test_escaping(self):
|
|---|
| 100 | + """
|
|---|
| 101 | + Tests that safety markers from django.utils.safestring
|
|---|
| 102 | + return the proper str or unicode subclass for use in templates.
|
|---|
| 103 | +
|
|---|
| 104 | + Tests are done by comparing directly a sample rendered Template instance
|
|---|
| 105 | + with the unicode content it should contain.
|
|---|
| 106 | + """
|
|---|
| 107 | + from django.template import Template, Context
|
|---|
| 108 | + template = Template("{{ data }}")
|
|---|
| 109 | +
|
|---|
| 110 | + rendered = { 'safe': u'<html><body>dummy</body></html>',
|
|---|
| 111 | + 'escaped': u'<html><body>dummy</body></html>' }
|
|---|
| 112 | + def clean_unicode_provider():
|
|---|
| 113 | + return u'<html><body>dummy</body></html>'
|
|---|
| 114 | +
|
|---|
| 115 | + def clean_string_provider():
|
|---|
| 116 | + return '<html><body>dummy</body></html>'
|
|---|
| 117 | +
|
|---|
| 118 | + escaped_unicode = mark_for_escaping(clean_unicode_provider)()
|
|---|
| 119 | + safe_unicode = mark_safe(clean_unicode_provider)()
|
|---|
| 120 | + escaped_str = mark_for_escaping(clean_string_provider)()
|
|---|
| 121 | + safe_str = mark_safe(clean_string_provider)()
|
|---|
| 122 | +
|
|---|
| 123 | + self.assertEquals(template.render(Context({'data': escaped_unicode})),
|
|---|
| 124 | + rendered['escaped'])
|
|---|
| 125 | + self.assertEquals(template.render(Context({'data': safe_unicode})),
|
|---|
| 126 | + rendered['safe'])
|
|---|
| 127 | + self.assertEquals(template.render(Context({'data': escaped_str})),
|
|---|
| 128 | + rendered['escaped'])
|
|---|
| 129 | + self.assertEquals(template.render(Context({'data': safe_str})),
|
|---|
| 130 | + rendered['safe'])
|
|---|
| 131 | +
|
|---|