Index: tests/regressiontests/forms/widgets.py
===================================================================
--- tests/regressiontests/forms/widgets.py	(revision 6710)
+++ tests/regressiontests/forms/widgets.py	(working copy)
@@ -2,6 +2,7 @@
 tests = r"""
 >>> from django.newforms import *
 >>> from django.newforms.widgets import RadioFieldRenderer
+>>> from django.utils.safestring import mark_safe
 >>> import datetime
 >>> import time
 >>> import re
@@ -205,6 +206,8 @@
 u'<textarea rows="10" cols="40" name="msg">value</textarea>'
 >>> w.render('msg', 'some "quoted" & ampersanded value')
 u'<textarea rows="10" cols="40" name="msg">some &quot;quoted&quot; &amp; ampersanded value</textarea>'
+>>> w.render('msg', mark_safe('pre &quot;quoted&quot; value'))
+u'<textarea rows="10" cols="40" name="msg">pre &quot;quoted&quot; value</textarea>'
 >>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20})
 u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>'
 
@@ -375,6 +378,17 @@
 <option value="5">5</option>
 </select>
 
+# Choices are escaped correctly
+>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
+<select name="escape">
+<option value="1">1</option>
+<option value="2">2</option>
+<option value="3">3</option>
+<option value="bad">you &amp; me</option>
+<option value="good">you &gt; me</option>
+</select>
+
+# Unicode choices are correctly rendered as HTML
 >>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
 u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
 
@@ -538,6 +552,17 @@
 <option value="5">5</option>
 </select>
 
+# Choices are escaped correctly
+>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
+<select multiple="multiple" name="escape">
+<option value="1">1</option>
+<option value="2">2</option>
+<option value="3">3</option>
+<option value="bad">you &amp; me</option>
+<option value="good">you &gt; me</option>
+</select>
+
+# Unicode choices are correctly rendered as HTML
 >>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
 u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
 
@@ -682,6 +707,14 @@
 ...
 IndexError: list index out of range
 
+# Choices are escaped correctly
+>>> w = RadioSelect()
+>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
+<ul>
+<li><label><input type="radio" name="escape" value="bad" /> you &amp; me</label></li>
+<li><label><input type="radio" name="escape" value="good" /> you &gt; me</label></li>
+</ul>
+
 # Unicode choices are correctly rendered as HTML
 >>> w = RadioSelect()
 >>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]))
@@ -811,6 +844,17 @@
 <li><label><input type="checkbox" name="nums" value="5" /> 5</label></li>
 </ul>
 
+# Choices are escaped correctly
+>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
+<ul>
+<li><label><input type="checkbox" name="escape" value="1" /> 1</label></li>
+<li><label><input type="checkbox" name="escape" value="2" /> 2</label></li>
+<li><label><input type="checkbox" name="escape" value="3" /> 3</label></li>
+<li><label><input type="checkbox" name="escape" value="bad" /> you &amp; me</label></li>
+<li><label><input type="checkbox" name="escape" value="good" /> you &gt; me</label></li>
+</ul>
+
+# Unicode choices are correctly rendered as HTML
 >>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
 u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'
 
Index: django/newforms/widgets.py
===================================================================
--- django/newforms/widgets.py	(revision 6710)
+++ django/newforms/widgets.py	(working copy)
@@ -11,7 +11,7 @@
 from itertools import chain
 
 from django.utils.datastructures import MultiValueDict
-from django.utils.html import escape
+from django.utils.html import escape, conditional_escape
 from django.utils.translation import ugettext
 from django.utils.encoding import StrAndUnicode, force_unicode
 from django.utils.safestring import mark_safe
@@ -155,7 +155,7 @@
         value = force_unicode(value)
         final_attrs = self.build_attrs(attrs, name=name)
         return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
-                escape(value)))
+                conditional_escape(force_unicode(value))))
 
 class DateTimeInput(Input):
     input_type = 'text'
@@ -217,7 +217,9 @@
         for option_value, option_label in chain(self.choices, choices):
             option_value = force_unicode(option_value)
             selected_html = (option_value == str_value) and u' selected="selected"' or ''
-            output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(force_unicode(option_label))))
+            output.append(u'<option value="%s"%s>%s</option>' % (
+                    escape(option_value), selected_html,
+                    conditional_escape(force_unicode(option_label))))
         output.append(u'</select>')
         return mark_safe(u'\n'.join(output))
 
@@ -254,7 +256,9 @@
         for option_value, option_label in chain(self.choices, choices):
             option_value = force_unicode(option_value)
             selected_html = (option_value in str_values) and ' selected="selected"' or ''
-            output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(force_unicode(option_label))))
+            output.append(u'<option value="%s"%s>%s</option>' % (
+                    escape(option_value), selected_html,
+                    conditional_escape(force_unicode(option_label))))
         output.append(u'</select>')
         return mark_safe(u'\n'.join(output))
 
@@ -278,7 +282,7 @@
 
     def __unicode__(self):
         return mark_safe(u'<label>%s %s</label>' % (self.tag(),
-                self.choice_label))
+                conditional_escape(force_unicode(self.choice_label))))
 
     def is_checked(self):
         return self.value == self.choice_value
@@ -361,7 +365,8 @@
             cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
             option_value = force_unicode(option_value)
             rendered_cb = cb.render(name, option_value)
-            output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(force_unicode(option_label))))
+            output.append(u'<li><label>%s %s</label></li>' % (rendered_cb,
+                    conditional_escape(force_unicode(option_label))))
         output.append(u'</ul>')
         return mark_safe(u'\n'.join(output))
 
