I find myself writing assertions like these:
if f(x, y) != z:
print(repr(x))
print(repr(y))
print(repr(z))
raise MyException('Expected: f(x, y) == z')
I was wondering if there's a way to write a function that would accept a valid Python expression and an exception class as an input, evaluate the expression, and if it finds it to be false, print out the representation of each of the lowest-level terms in the expression and raise the given exception?
# validate is the mystery function
validate('f(x, y) == z', MyException)
Here's an implementation:
import inspect, keyword, pprint, sys, tokenize
def value_in_frame(name, frame):
try:
return frame.f_locals[name]
except KeyError:
try:
return frame.f_globals[name]
except KeyError:
raise ValueError("Couldn't find value for %s" % name)
def validate(expr, exc_class=AssertionError):
"""Evaluate `expr` in the caller's frame, raise `exc_class` if false."""
frame = inspect.stack()[1][0]
val = eval(expr, frame.f_globals, frame.f_locals)
if not val:
rl = iter([expr]).next
for typ, tok, _, _, _ in tokenize.generate_tokens(rl):
if typ == tokenize.NAME and not keyword.iskeyword(tok):
try:
val = value_in_frame(tok, frame)
except ValueError:
val = '???'
else:
val = repr(val)
print " %s: %s" % (tok, val)
raise exc_class("Failed to validate: %s" % expr)
if __name__ == '__main__':
a = b = 3
validate("a + b == 5")
What about assertions ?
assert f(x, y) != z, 'Expected: f(%r, %r) == %r'%(x,y,z)
Edit
to add %r to print repr's - thanks for the comment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With