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 | +
|
---|