Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python: automatically printing representation of each component in an expression

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)
like image 481
max Avatar asked Jan 23 '11 23:01

max


2 Answers

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")
like image 93
Ned Batchelder Avatar answered Oct 16 '22 07:10

Ned Batchelder


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.

like image 31
Manuel Salvadores Avatar answered Oct 16 '22 07:10

Manuel Salvadores