Commit 2df0f02c by Peter Baratta

Fix behavior of UndefinedVariable

Prior to this, the code would:
1. Only display the intersection of bad variables and functions (instead
   of the union, like it should)
2. Display the lowercase version of everything, when it should be
   preserving the case.
parent 48d20baf
...@@ -282,35 +282,22 @@ class ParseAugmenter(object): ...@@ -282,35 +282,22 @@ class ParseAugmenter(object):
self.variables_used = set() self.variables_used = set()
self.functions_used = set() self.functions_used = set()
def make_variable_parse_action(self):
"""
Create a wrapper to store variables as they are parsed.
"""
def vpa(tokens): def vpa(tokens):
""" """
When a variable is recognized, store its correct form in `variables_used`. When a variable is recognized, store it in `variables_used`.
""" """
if self.case_sensitive: varname = tokens[0][0]
varname = tokens[0][0]
else:
varname = tokens[0][0].lower()
self.variables_used.add(varname) self.variables_used.add(varname)
return vpa
def make_function_parse_action(self):
"""
Create a wrapper to store functions as they are parsed.
"""
def fpa(tokens): def fpa(tokens):
""" """
When a function is recognized, store its correct form in `variables_used`. When a function is recognized, store it in `functions_used`.
""" """
if self.case_sensitive: varname = tokens[0][0]
varname = tokens[0][0]
else:
varname = tokens[0][0].lower()
self.functions_used.add(varname) self.functions_used.add(varname)
return fpa
self.variable_parse_action = vpa
self.function_parse_action = fpa
def parse_algebra(self): def parse_algebra(self):
""" """
...@@ -350,11 +337,11 @@ class ParseAugmenter(object): ...@@ -350,11 +337,11 @@ class ParseAugmenter(object):
# and may contain numbers afterward. # and may contain numbers afterward.
inner_varname = Word(alphas + "_", alphanums + "_") inner_varname = Word(alphas + "_", alphanums + "_")
varname = Group(inner_varname)("variable") varname = Group(inner_varname)("variable")
varname.setParseAction(self.make_variable_parse_action()) varname.setParseAction(self.variable_parse_action)
# Same thing for functions. # Same thing for functions.
function = Group(inner_varname + Suppress("(") + expr + Suppress(")"))("function") function = Group(inner_varname + Suppress("(") + expr + Suppress(")"))("function")
function.setParseAction(self.make_function_parse_action()) function.setParseAction(self.function_parse_action)
atom = number | function | varname | "(" + expr + ")" atom = number | function | varname | "(" + expr + ")"
atom = Group(atom)("atom") atom = Group(atom)("atom")
...@@ -420,9 +407,16 @@ class ParseAugmenter(object): ...@@ -420,9 +407,16 @@ class ParseAugmenter(object):
Otherwise, raise an UndefinedVariable containing all bad variables. Otherwise, raise an UndefinedVariable containing all bad variables.
""" """
# Test that `used_vars` is a subset of `all_vars`; also do functions. if self.case_sensitive:
if not (self.variables_used.issubset(valid_variables) and casify = lambda x: x
self.functions_used.issubset(valid_functions)): else:
bad_vars = self.variables_used.difference(valid_variables) casify = lambda x: x.lower() # Lowercase for case insens.
bad_vars &= self.functions_used.difference(valid_functions)
raise UndefinedVariable(' '.join(bad_vars)) # Test if casify(X) is valid, but return the actual bad input (i.e. X)
bad_vars = set(var for var in self.variables_used
if casify(var) not in valid_variables)
bad_vars.update(func for func in self.functions_used
if casify(func) not in valid_functions)
if bad_vars:
raise UndefinedVariable(' '.join(sorted(bad_vars)))
...@@ -536,9 +536,9 @@ class EvaluatorTest(unittest.TestCase): ...@@ -536,9 +536,9 @@ class EvaluatorTest(unittest.TestCase):
""" """
variables = {'R1': 2.0, 'R3': 4.0} variables = {'R1': 2.0, 'R3': 4.0}
with self.assertRaises(calc.UndefinedVariable): with self.assertRaisesRegexp(calc.UndefinedVariable, 'QWSEKO'):
calc.evaluator({}, {}, "5+7*QWSEKO") calc.evaluator({}, {}, "5+7*QWSEKO")
with self.assertRaises(calc.UndefinedVariable): with self.assertRaisesRegexp(calc.UndefinedVariable, 'r2'):
calc.evaluator({'r1': 5}, {}, "r1+r2") calc.evaluator({'r1': 5}, {}, "r1+r2")
with self.assertRaises(calc.UndefinedVariable): with self.assertRaisesRegexp(calc.UndefinedVariable, 'r1 r3'):
calc.evaluator(variables, {}, "r1*r3", case_sensitive=True) calc.evaluator(variables, {}, "r1*r3", case_sensitive=True)
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