Commit f58903a5 by zubair-arbi

Merge pull request #2097 from zubair-arbi/zub/bugfix/std893-optionresponse

escape single quotes in optioninput (optionresponse) tags
parents 9075dcef 1990a412
......@@ -309,6 +309,9 @@ class OptionInput(InputTypeBase):
Given options string, convert it into an ordered list of (option_id, option_description) tuples, where
id==description for now. TODO: make it possible to specify different id and descriptions.
"""
# convert single quotes inside option values to html encoded string
options = re.sub(r"([a-zA-Z])('|\\')([a-zA-Z])", r"\1'\3", options)
options = re.sub(r"\\'", r"'", options) # replace already escaped single quotes
# parse the set of possible options
lexer = shlex.shlex(options[1:-1].encode('utf8'))
lexer.quotes = "'"
......@@ -316,7 +319,8 @@ class OptionInput(InputTypeBase):
lexer.whitespace = ", "
# remove quotes
tokens = [x[1:-1].decode('utf8') for x in lexer]
# convert escaped single quotes (html encoded string) back to single quotes
tokens = [x[1:-1].decode('utf8').replace("'", "'") for x in lexer]
# make list of (option_id, option_description), with description=id
return [(t, t) for t in tokens]
......
......@@ -41,7 +41,7 @@ class OptionInputTest(unittest.TestCase):
'''
def test_rendering(self):
xml_str = """<optioninput options="('Up','Down')" id="sky_input" correct="Up"/>"""
xml_str = """<optioninput options="('Up','Down','Don't know')" id="sky_input" correct="Up"/>"""
element = etree.fromstring(xml_str)
state = {'value': 'Down',
......@@ -54,7 +54,7 @@ class OptionInputTest(unittest.TestCase):
expected = {
'STATIC_URL': '/dummy-static/',
'value': 'Down',
'options': [('Up', 'Up'), ('Down', 'Down')],
'options': [('Up', 'Up'), ('Down', 'Down'), ('Don\'t know', 'Don\'t know')],
'status': 'answered',
'msg': '',
'inline': False,
......@@ -80,6 +80,10 @@ class OptionInputTest(unittest.TestCase):
check(u"('б в','в')", [u'б в', u'в'])
check(u"('Мой \"кавыки\"место','в')", [u'Мой \"кавыки\"место', u'в'])
# check that escaping single quotes with leading backslash (\') properly works
# note: actual input by user will be hasn\'t but json parses it as hasn\\'t
check(u"('hasnt','hasn't')", [u'hasnt', u'hasn\'t'])
class ChoiceGroupTest(unittest.TestCase):
'''
......
......@@ -344,6 +344,17 @@ class OptionResponseTest(ResponseTest):
# Options not in the list should be marked incorrect
self.assert_grade(problem, "invalid_option", "incorrect")
def test_quote_option(self):
# Test that option response properly escapes quotes inside options strings
problem = self.build_problem(options=["hasnot", "hasn't", "has'nt"],
correct_option="hasn't")
# Assert that correct option with a quote inside is marked correctly
self.assert_grade(problem, "hasnot", "incorrect")
self.assert_grade(problem, "hasn't", "correct")
self.assert_grade(problem, "hasn\'t", "correct")
self.assert_grade(problem, "has'nt", "incorrect")
class FormulaResponseTest(ResponseTest):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment