diff --git a/common/lib/capa/capa/chem/chemcalc.py b/common/lib/capa/capa/chem/chemcalc.py
index a58a3ac85d..389e688cf4 100644
--- a/common/lib/capa/capa/chem/chemcalc.py
+++ b/common/lib/capa/capa/chem/chemcalc.py
@@ -218,6 +218,9 @@ def render_to_html(eq):
return u'\u2192'
if arrow == '<->':
return u'\u2194'
+
+ # this won't be reached unless we add more arrow types, but keep it to avoid explosions when
+ # that happens.
return arrow
def render_expression(ex):
@@ -391,36 +394,40 @@ def chemical_equations_equal(eq1, eq2, exact=False):
chemical_equations_equal('H2 + O2 -> H2O2', '2 H2 + 2 O2 -> 2 H2O2', exact=True) -> False
- If there's a syntax error, we raise pyparsing.ParseException.
+ If there's a syntax error, we return False.
"""
left1, arrow1, right1 = split_on_arrow(eq1)
left2, arrow2, right2 = split_on_arrow(eq2)
if arrow1 == '' or arrow2 == '':
- raise ParseException("Could not find arrow. Legal arrows: {0}".format(ARROWS))
+ return False
# TODO: may want to be able to give student helpful feedback about why things didn't work.
if arrow1 != arrow2:
# arrows don't match
return False
- factor_left = divide_chemical_expression(left1, left2)
- if not factor_left:
- # left sides don't match
- return False
+ try:
+ factor_left = divide_chemical_expression(left1, left2)
+ if not factor_left:
+ # left sides don't match
+ return False
- factor_right = divide_chemical_expression(right1, right2)
- if not factor_right:
- # right sides don't match
- return False
+ factor_right = divide_chemical_expression(right1, right2)
+ if not factor_right:
+ # right sides don't match
+ return False
- if factor_left != factor_right:
- # factors don't match (molecule counts to add up)
- return False
+ if factor_left != factor_right:
+ # factors don't match (molecule counts to add up)
+ return False
- if exact and factor_left != 1:
- # want an exact match.
- return False
+ if exact and factor_left != 1:
+ # want an exact match.
+ return False
- return True
+ return True
+ except ParseException:
+ # Don't want external users to have to deal with parsing exceptions. Just return False.
+ return False
diff --git a/common/lib/capa/capa/chem/tests.py b/common/lib/capa/capa/chem/tests.py
index 9d415ad402..34d903ec1d 100644
--- a/common/lib/capa/capa/chem/tests.py
+++ b/common/lib/capa/capa/chem/tests.py
@@ -1,3 +1,4 @@
+import codecs
from fractions import Fraction
from pyparsing import ParseException
import unittest
@@ -55,15 +56,17 @@ class Test_Compare_Equations(unittest.TestCase):
self.assertTrue(chemical_equations_equal('H2 + O2 -> H2O2',
'O2 + H2 -> H2O2', exact=True))
-
- def test_syntax_errors(self):
- self.assertRaises(ParseException, chemical_equations_equal,
- 'H2 + O2 a-> H2O2',
- '2O2 + 2H2 -> 2H2O2')
- self.assertRaises(ParseException, chemical_equations_equal,
- 'H2 + O2 ==> H2O2', # strange arrow
- '2O2 + 2H2 -> 2H2O2')
+ def test_syntax_errors(self):
+ self.assertFalse(chemical_equations_equal('H2 + O2 a-> H2O2',
+ '2O2 + 2H2 -> 2H2O2'))
+
+ self.assertFalse(chemical_equations_equal('H2O( -> H2O2',
+ 'H2O -> H2O2'))
+
+
+ self.assertFalse(chemical_equations_equal('H2 + O2 ==> H2O2', # strange arrow
+ '2O2 + 2H2 -> 2H2O2'))
class Test_Compare_Expressions(unittest.TestCase):
@@ -294,6 +297,29 @@ class Test_Render_Equations(unittest.TestCase):
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
+ def test_render_eq1(self):
+ s = "H^+ + OH^- -> H2O"
+ out = render_to_html(s)
+ correct = u'H++OH-\u2192H2O'
+ log(out + ' ------- ' + correct, 'html')
+ self.assertEqual(out, correct)
+
+ def test_render_eq2(self):
+ s = "H^+ + OH^- <-> H2O"
+ out = render_to_html(s)
+ correct = u'H++OH-\u2194H2O'
+ log(out + ' ------- ' + correct, 'html')
+ self.assertEqual(out, correct)
+
+
+ def test_render_eq3(self):
+ s = "H^+ + OH^- <= H2O" # unsupported arrow
+ out = render_to_html(s)
+ correct = u'H^+ + OH^- <= H2O'
+ log(out + ' ------- ' + correct, 'html')
+ self.assertEqual(out, correct)
+
+
def suite():
@@ -305,6 +331,6 @@ def suite():
if __name__ == "__main__":
local_debug = True
- with open('render.html', 'w') as f:
+ with codecs.open('render.html', 'w', encoding='utf-8') as f:
unittest.TextTestRunner(verbosity=2).run(suite())
# open render.html to look at rendered equations