diff --git a/asteval/astutils.py b/asteval/astutils.py index 4c57d12..7942c01 100644 --- a/asteval/astutils.py +++ b/asteval/astutils.py @@ -310,10 +310,10 @@ def get_field(self, field_name, args, kwargs): else: obj = obj[i] return obj, first - + def safe_format(_string, raise_exc, node, *args, **kwargs): formatter = SafeFormatter(raise_exc, node) - return formatter.vformat(_string, args, kwargs) + return formatter.vformat(_string, args, kwargs) def valid_symbol_name(name): """Determine whether the input symbol name is a valid name. @@ -364,13 +364,24 @@ def __repr__(self): class ExceptionHolder: """Basic exception handler.""" - def __init__(self, node, exc=None, msg='', expr=None, lineno=None): + def __init__(self, node, exc=None, msg='', expr=None, + text=None, lineno=None): """TODO: docstring in public method.""" self.node = node self.expr = expr self.msg = msg self.exc = exc + self.text = text self.lineno = lineno + self.end_lineno = lineno + self.col_offset = 0 + if lineno is None: + try: + self.lineno = node.lineno + self.end_lineno = node.end_lineno + self.col_offset = node.col_offset + except: + pass self.exc_info = exc_info() if self.exc is None and self.exc_info[0] is not None: self.exc = self.exc_info[0] @@ -379,12 +390,6 @@ def __init__(self, node, exc=None, msg='', expr=None, lineno=None): def get_error(self): """Retrieve error data.""" - col_offset = -1 - if self.node is not None: - try: - col_offset = self.node.col_offset - except AttributeError: - pass try: exc_name = self.exc.__name__ except AttributeError: @@ -392,9 +397,15 @@ def get_error(self): if exc_name in (None, 'None'): exc_name = 'UnknownError' - out = [f" {self.expr}"] - if col_offset > 0: - out.append(f" {col_offset*' '}^^^^") + out = [] + try: + lines = self.text.split('\n') + line = '\n'.join(lines[self.lineno-1:self.end_lineno]) + out.append(f"{line}") + except: + out.append(f"{self.expr}") + if self.col_offset > 0: + out.append(f"{self.col_offset*' '}^^^^") out.append(f"{exc_name}: {self.msg}") return (exc_name, '\n'.join(out)) @@ -546,7 +557,7 @@ class Procedure: """ - def __init__(self, name, interp, doc=None, lineno=0, + def __init__(self, name, interp, doc=None, lineno=None, body=None, args=None, kwargs=None, vararg=None, varkws=None): """TODO: docstring in public method.""" @@ -562,6 +573,7 @@ def __init__(self, name, interp, doc=None, lineno=0, self.__vararg__ = vararg self.__varkws__ = varkws self.lineno = lineno + self.__text__ = ast.unparse(self.__body__) self.__ininit__ = False def __setattr__(self, attr, val): @@ -703,8 +715,9 @@ def __call__(self, *args, **kwargs): retval = None # evaluate script of function + self.__asteval__.code_text.append(self.__text__) for node in self.__body__: - self.__asteval__.run(node, expr='<>', lineno=self.lineno) + self.__asteval__.run(node, lineno=node.lineno) if len(self.__asteval__.error) > 0: break if self.__asteval__.retval is not None: @@ -715,6 +728,7 @@ def __call__(self, *args, **kwargs): break self.__asteval__.symtable = save_symtable + self.__asteval__.code_text.pop() self.__asteval__._calldepth -= 1 symlocals = None return retval