From f5b0050cd54b887b9dab13872a58ce100edde332 Mon Sep 17 00:00:00 2001 From: Tim Vieira Date: Sat, 13 Jul 2013 11:24:26 -0400 Subject: [PATCH] minor cleanup. --- src/Dyna/Backend/Python/errors.py | 60 +++++++++++++++++++++++++- src/Dyna/Backend/Python/interpreter.py | 57 +++++------------------- src/Dyna/Backend/Python/term.py | 1 - 3 files changed, 69 insertions(+), 49 deletions(-) diff --git a/src/Dyna/Backend/Python/errors.py b/src/Dyna/Backend/Python/errors.py index 424b24b..dfc5f9b 100644 --- a/src/Dyna/Backend/Python/errors.py +++ b/src/Dyna/Backend/Python/errors.py @@ -64,5 +64,61 @@ def show_traceback(einfo=None): h(etype, evalue, tb) -def notimplemented(*_,**__): - raise NotImplementedError +def rule_error_context(): + """ + Inspect the stack frame to extract local variable bindings of an update + handler, rule initializer or backward chaining routine. + + >>> def f(x): + ... y = 3 + ... return g(x) + + >>> def g(x): + ... return _(x) + + >>> def _(x): # target frame + ... y = x + 1 + ... z = 3 * 4 + ... errorizer() + + >>> def errorizer(): + ... a = 1 + ... b = 0 + ... c = a / b # divide by zero error. + ... d = 3 # will be undefined, along with c + ... return 10 + + >>> try: + ... print f(3) + ... except ZeroDivisionError: + ... print rule_error_context() + {'y': 4, 'x': 3, 'z': 12} + + """ + + # Move to the frame where the exception occurred, which is often not the + # same frame where the exception was caught. + tb = sys.exc_info()[2] + if tb is not None: + while 1: + if not tb.tb_next: + break + tb = tb.tb_next + f = tb.tb_frame + else: # no exception occurred + f = sys._getframe() + + # get the stack frames + stack = [] + while f: + stack.append(f) + f = f.f_back + + rule_frame = None + for frame in stack: + if frame.f_code.co_name == '_': # find frame which looks like an update handler (it's name is at least '_') + rule_frame = frame + + if rule_frame is not None: + return dict(rule_frame.f_locals) + return {} diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 9a6a702..d61575c 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -86,52 +86,10 @@ from utils import ip, red, green, blue, magenta, yellow, parse_attrs, \ from prioritydict import prioritydict from config import dotdynadir -from errors import crash_handler, AggregatorError, DynaCompilerError +from errors import crash_handler, rule_error_context, AggregatorError, DynaCompilerError from stdlib import todyna -def rule_error_context(): - # Move to the frame where the exception occurred, which is often not the - # same frame where the exception was caught. - tb = sys.exc_info()[2] - if tb is not None: - while 1: - if not tb.tb_next: - break - tb = tb.tb_next - f = tb.tb_frame - else: # no exception occurred - f = sys._getframe() - - # get the stack frames - stack = [] - while f: - stack.append(f) - f = f.f_back - - rule_frame = None - for frame in stack: - if frame.f_code.co_name == '_': # find frame which looks like an update handler (it's name is at least '_') - rule_frame = frame - - if False: - print 'Frame %s in %s at line %s' % (frame.f_code.co_name, frame.f_code.co_filename, frame.f_lineno) - for key, value in frame.f_locals.iteritems(): - print '%20s = %r' % (key, value) - print '\n' - - if rule_frame is not None: - return dict(rule_frame.f_locals.items()) - return {} - - -def render_rule_context(rule, ctx, indent=''): - # TODO: highlight expression which caused the error. - from post.trace import Crux - c = Crux(head=None, rule=rule, body=None, vs = ctx) - return '\n'.join(indent + line for line in c.format()) - - class Rule(object): def __init__(self, index): @@ -160,6 +118,13 @@ class Rule(object): def __repr__(self): return 'Rule(%s, %r)' % (self.index, self.src) + def render_ctx(self, ctx, indent=''): + # TODO: highlight expression which caused the error. + from post.trace import Crux + c = Crux(head=None, rule=self, body=None, vs = ctx) + return '\n'.join(indent + line for line in c.format()) + + # TODO: yuck, hopefully temporary measure to support pickling the Interpreter's # state @@ -306,7 +271,7 @@ class Interpreter(object): print >> out, ' %s' % (e) print >> out - print >> out, render_rule_context(r, e.exception_frame, indent=' ') + print >> out, r.render_ctx(e.exception_frame, indent=' ') print >> out # uninitialized rules @@ -318,7 +283,7 @@ class Interpreter(object): rule = self.rules[r] print >> out, ' ', rule.src print >> out, ' due to `%s`' % e - print >> out, render_rule_context(rule, e.exception_frame, indent=' ') + print >> out, rule.render_ctx(e.exception_frame, indent=' ') print >> out print >> out @@ -430,7 +395,7 @@ class Interpreter(object): item.value = now continue - except (ZeroDivisionError, TypeError, KeyboardInterrupt, NotImplementedError) as e: + except (ZeroDivisionError, TypeError, KeyboardInterrupt) as e: error[item] = (None, [(e, None)]) now = self.build('$error/0') # XXX: should go an agenda or run delete? diff --git a/src/Dyna/Backend/Python/term.py b/src/Dyna/Backend/Python/term.py index 3ac67fd..ff80a46 100644 --- a/src/Dyna/Backend/Python/term.py +++ b/src/Dyna/Backend/Python/term.py @@ -1,4 +1,3 @@ -from errors import notimplemented from utils import _repr, true, false from aggregator import NoAggregator -- 2.50.1