From: Tim Vieira Date: Sat, 29 Jun 2013 01:51:15 +0000 (-0400) Subject: Tweaks to error messages. X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=ec87c7ce6b867108a035abbc831c0e453bf2b45f;p=dyna2 Tweaks to error messages. Improved documentation for loaders and post-processors. --- diff --git a/src/Dyna/Backend/Python/errors.py b/src/Dyna/Backend/Python/errors.py index 70a9728..973f3bd 100644 --- a/src/Dyna/Backend/Python/errors.py +++ b/src/Dyna/Backend/Python/errors.py @@ -8,19 +8,21 @@ class DynaCompilerError(Exception): pass -#class AggregatorConflict(Exception): -# def __init__(self, key, expected, got): -# msg = "Aggregator conflict %r was %r trying to set to %r." \ -# % (key, expected, got) -# super(AggregatorConflict, self).__init__(msg) - - class DynaInitializerException(Exception): def __init__(self, exception, init): - msg = '%r in ininitializer for rule\n %s\n %s' % \ - (exception, - parse_attrs(init)['Span'], - parse_attrs(init)['rule']) + rule = parse_attrs(init)['rule'] + span = parse_attrs(init)['Span'] + + if span.startswith(dotdynadir / 'tmp'): + # don't show users tmp files create by the repl. + msg = '%r in ininitializer for rule\n %s' % \ + (exception, rule) + + else: + msg = '%r in ininitializer for rule\n %s\n %s' % \ + (exception, + span, + rule) super(DynaInitializerException, self).__init__(msg) @@ -43,17 +45,22 @@ def exception_handler(etype, evalue, tb): # chart -- because it might be too big to email); input to repl. # This should all go into a tarball. + if crash_handler.interp is not None: + crash_handler.interp() + print 'FATAL ERROR (%s): %s' % (etype.__name__, evalue) - print 'Please report this error by emailing bugs@dyna.org. ' \ - 'Please attach the following file %s' % crashreport.name + print 'Crash log available %s' % crashreport.name -def enable_crash_handler(): +def crash_handler(): """ Use our custom exception handler for handling uncaught exceptions. """ sys.excepthook = exception_handler +# XXX: global state... +crash_handler.interp = None + def show_traceback(einfo=None): if not einfo: diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 7e0f8c2..7fbd358 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -204,10 +204,7 @@ from utils import ip, red, green, blue, magenta, yellow, parse_attrs, \ from prioritydict import prioritydict from config import dotdynadir -from errors import notimplemented, enable_crash_handler, \ - DynaInitializerException, DynaCompilerError - -from stdlib import * +from errors import crash_handler, DynaInitializerException class Rule(object): @@ -258,6 +255,8 @@ class Interpreter(object): self.rules = ddict(Rule) self.error = {} + self.files = [] + def __getstate__(self): return ((self.chart, self.agenda, @@ -580,6 +579,11 @@ class Interpreter(object): return self.go() + def dynac(self, filename, out=None): + self.files.append(filename) + out = dynac(filename, out) + self.files.append(out) + def dynac_code(self, code): """ Compile a string of dyna code. @@ -599,7 +603,7 @@ class Interpreter(object): f.write(self.parser_state) # include parser state if any. f.write(code) - dynac(dyna, out) # might raise compiler error + self.dynac(dyna, out) # might raise compiler error return out @@ -646,7 +650,23 @@ def main(): interp = Interpreter() - enable_crash_handler() + crash_handler() + + +# def pickle_interp(): +# import subprocess +# +# crash = dotdynadir / 'crash' +# crash.rmtree(ignore_errors=False) +# crash.mkdir_p() +# +# for f in [dotdynadir / 'crash.log'] + interp.files: +# path(f).copy(crash) +# +# subprocess.Popen(['tar', 'czf', dotdynadir / 'crash.tar.gz', crash]) +# +# crash_handler.interp = pickle_interp + if args.source: @@ -658,7 +678,7 @@ def main(): plan = args.source else: plan = args.source + '.plan.py' - dynac(args.source, plan) + interp.dynac(args.source, plan) if args.profile: # When profiling, its common practice to disable the garbage collector. diff --git a/src/Dyna/Backend/Python/load/__init__.py b/src/Dyna/Backend/Python/load/__init__.py index 462a3b4..a733071 100644 --- a/src/Dyna/Backend/Python/load/__init__.py +++ b/src/Dyna/Backend/Python/load/__init__.py @@ -1,16 +1,11 @@ -#from sexpr import sexpr -#from tsv import tsv -#from matrix import matrix -#from pickled import pickled - -import re as _re +import re from utils import get_module available = 'sexpr', 'tsv', 'matrix' def run(interp, line): try: - [(name, module, args)] = _re.findall('^([a-z][a-zA-Z_0-9]*) = ([a-z][a-zA-Z_0-9]*)\((.*)\)', line) + [(name, module, args)] = re.findall('^([a-z][a-zA-Z_0-9]*) = ([a-z][a-zA-Z_0-9]*)\((.*)\)', line) except ValueError: print 'Error: failed to parse post command.' print ' %s' % line diff --git a/src/Dyna/Backend/Python/load/matrix.py b/src/Dyna/Backend/Python/load/matrix.py index de827a6..a3e3171 100644 --- a/src/Dyna/Backend/Python/load/matrix.py +++ b/src/Dyna/Backend/Python/load/matrix.py @@ -1,24 +1,52 @@ -""" -mat - Load a text file as a (jagged) matrix. +import re -For example +class matrix(object): + """ + Load a text file as a (jagged) matrix. -1 2 3 -4 5 + For example -6 7 + $ echo 1 2 3 > /tmp/foo + $ echo 4 5 >> /tmp/foo + $ echo >> /tmp/foo + $ echo 6 7 >> /tmp/foo + :- load m = matrix("/tmp/foo") + :- sol -m(0,0) := 1. m(0,1) := 2. m(0,2) := 3 -m(1,0) := 4. m(1,1) := 5. + Solution + ======== + m/2 + === + m(0,0) := 1.0 + m(0,1) := 2.0 + m(0,2) := 3.0 + m(1,0) := 4.0 + m(1,1) := 5.0 + m(3,0) := 6.0 + m(3,1) := 7.0 -m(3,0) := 6. m(3,1) := 7. -""" + As you can see, by default values are interpreted as floats, to specify a + different type simple passing a function which will convert strings to the + appropriate time (e.g. str, int, float). -import re + :- load m = matrix("/tmp/foo", astype=str) + :- sol -class matrix(object): + Solution + ======== + m/2 + === + m(0,0) := "1" + m(0,1) := "2" + m(0,2) := "3" + m(1,0) := "4" + m(1,1) := "5" + m(3,0) := "6" + m(3,1) := "7" + + """ def __init__(self, interp, name): self.interp = interp diff --git a/src/Dyna/Backend/Python/load/sexpr.py b/src/Dyna/Backend/Python/load/sexpr.py index a4e0d66..7983791 100644 --- a/src/Dyna/Backend/Python/load/sexpr.py +++ b/src/Dyna/Backend/Python/load/sexpr.py @@ -1,12 +1,24 @@ -""" -Read lisp-style S-Expressions from a file. -""" - from cStringIO import StringIO from utils import parse_sexpr class sexpr(object): + """ + Read lisp-style S-Expressions from a file. + + $ echo '(a (b c) (d e)) (a b (c))' > /tmp/foo + $ ./dyna + :- load trees = sexpr("/tmp/foo") + :- sol + + Solution + ======== + trees/1 + ======= + trees(0) := node("a", node("b", "c"), node("d", "e")) + trees(1) := node("a", "b", "c") + + """ def __init__(self, interp, name): self.interp = interp diff --git a/src/Dyna/Backend/Python/load/tsv.py b/src/Dyna/Backend/Python/load/tsv.py index be67a79..7d0a51e 100644 --- a/src/Dyna/Backend/Python/load/tsv.py +++ b/src/Dyna/Backend/Python/load/tsv.py @@ -1,12 +1,27 @@ +""" +TODO: option for stripping comments +TODO: option for strict number of columns. +""" + import re class tsv(object): - """ Load tab-delimited files. - TODO: option for stripping comments - TODO: option for strict number of columns. + :- load row = tsv("test/repl/english.gr") + :- sol + row/4 + ===== + row(0,"0","S","NP VP") := true + row(1,"1.58","ROOT","S .") := true + row(2,"1.58","ROOT","S !") := true + row(3,"1.58","ROOT","VP !") := true + row(4,"3.81","VP","V") := true + row(5,"3.81","VP","V NP") := true + row(6,"1.49","VP","V VP") := true + ... + """ def __init__(self, interp, name): diff --git a/src/Dyna/Backend/Python/repl.py b/src/Dyna/Backend/Python/repl.py index 1ebc77b..f5dfb2e 100644 --- a/src/Dyna/Backend/Python/repl.py +++ b/src/Dyna/Backend/Python/repl.py @@ -139,7 +139,7 @@ class REPL(cmd.Cmd, object): """ try: - changed = self.interp.do(dynac(filename)) + changed = self.interp.do(self.interp.dynac(filename)) except DynaCompilerError as e: print e else: diff --git a/src/Dyna/Backend/Python/utils.py b/src/Dyna/Backend/Python/utils.py index 602f0f3..c5b482b 100644 --- a/src/Dyna/Backend/Python/utils.py +++ b/src/Dyna/Backend/Python/utils.py @@ -3,8 +3,6 @@ from path import path from subprocess import Popen, PIPE from IPython.frontend.terminal.embed import InteractiveShellEmbed from config import dynahome, dotdynadir -import signal -from contextlib import contextmanager from collections import namedtuple @@ -106,24 +104,26 @@ def subst(term, v): return ''.join((_repr(v[x]) if x in v else x) for x in lexer(term)) - -@contextmanager -def interrupt_after(): - - def handler(signum, frame): - sys.stderr.write('^C') - handler.interrupted = True - return signal.SIG_IGN - - handler.interrupted = False - signal.signal(signal.SIGINT, handler) - - yield - - signal.signal(signal.SIGINT, signal.default_int_handler) - - if handler.interrupted: - raise KeyboardInterrupt +#import signal +#from contextlib import contextmanager +# +#@contextmanager +#def interrupt_after(): +# +# def handler(signum, frame): +# sys.stderr.write('^C') +# handler.interrupted = True +# return signal.SIG_IGN +# +# handler.interrupted = False +# signal.signal(signal.SIGINT, handler) +# +# yield +# +# signal.signal(signal.SIGINT, signal.default_int_handler) +# +# if handler.interrupted: +# raise KeyboardInterrupt class ddict(dict):