I want to check an arbitrary (defined in data) set of rules expressed in text and eval() does the job nicely.
e.g. to define a rule to check that A and B are both valid:
Rule = "A and B"
print eval(Rule)
So how do I dynamically assign values to an arbitrary set of items?
I have a list of named Options and a list of Selections. Everthing in the Selections is considered valid (True) and everything in the Options, but not in the Selections is considered invalid (False).
So this code works but I don't like it because I am setting values within the local name space and I can't prevent an option name clashing with my local variables.
def CheckConstraints(self, Selections):
'Validate the stored constraints'
Good = True
## Undefined options default to False
for i in self.Options:
exec(i+" = False") ## Bad - can I use setattr?
## Set defined Options to True
for i in Selections:
exec(i+" = True") ## Bad - can I use setattr?
for i in self.Constraints:
if not eval( i ):
Good = False
print "Constraint Check Failure:", i, Selections
else:
print "Constraint Check OK:", i, Selections
return Good
I have tried to use setattr, but it is not clear what setattr is setting and eval doesn't seem to be able to use the values set.
I'm on python 2.7x
Any suggestion welcome?
eval
can take a dictionary as its second argument which contains a new environment. Create a dictionary env
and set your new variables within there, which ensures it won't clash with your local namespace:
def CheckConstraints(self, Selections):
'Validate the stored constraints'
Good = True
env = {}
## Undefined options default to False
for i in self.Options:
env[i] = False
## Set defined Options to True
for i in Selections:
env[i] = True
for i in self.Constraints:
if not eval(i, env):
Good = False
print "Constraint Check Failure:", i, Selections
else:
print "Constraint Check OK:", i, Selections
return Good