def __str__(self): from vyper import ast as vy_ast from vyper.utils import annotate_source_code if not hasattr(self, "source_code"): if self.lineno is not None and self.col_offset is not None: return f"line {self.lineno}:{self.col_offset} {self.message}" else: return self.message msg = f"{self.message}\n" for node in self.nodes: try: source_annotation = annotate_source_code( self.source_code, node.lineno, node.col_offset, context_lines=VYPER_ERROR_CONTEXT_LINES, line_numbers=VYPER_ERROR_LINE_NUMBERS, ) except Exception: # necessary for certian types of syntax exceptions return msg if isinstance(node, vy_ast.VyperNode): fn_node = node.get_ancestor(vy_ast.FunctionDef) if fn_node: msg += f"function '{fn_node.name}', " col_offset_str = "" if node.col_offset is None else str( node.col_offset) msg += f"line {node.lineno}:{col_offset_str} \n{source_annotation}\n" return msg
def _annotated_source(self): # return source with context / line/col info return annotate_source_code( self.full_source_code, self.lineno, self.col_offset, context_lines=VYPER_ERROR_CONTEXT_LINES, line_numbers=VYPER_ERROR_LINE_NUMBERS, )
def __repr__(self): cls = type(self) class_repr = f"{cls.__module__}.{cls.__qualname__}" source_annotation = annotate_source_code( self.full_source_code, self.lineno, self.col_offset, context_lines=VYPER_ERROR_CONTEXT_LINES, line_numbers=VYPER_ERROR_LINE_NUMBERS, ) return f"{class_repr}:\n{source_annotation}"
def __str__(self): from vyper import ast as vy_ast from vyper.utils import annotate_source_code if not hasattr(self, "annotations"): if self.lineno is not None and self.col_offset is not None: return f"line {self.lineno}:{self.col_offset} {self.message}" else: return self.message annotation_list = [] for value in self.annotations: node = value[1] if isinstance(value, tuple) else value node_msg = "" try: source_annotation = annotate_source_code( # add trailing space because EOF exceptions point one char beyond the length f"{node.full_source_code} ", node.lineno, node.col_offset, context_lines=VYPER_ERROR_CONTEXT_LINES, line_numbers=VYPER_ERROR_LINE_NUMBERS, ) except Exception: # necessary for certain types of syntax exceptions return self.message if isinstance(node, vy_ast.VyperNode): module_node = node.get_ancestor(vy_ast.Module) if module_node.get("name") not in (None, "<unknown>"): node_msg = f'{node_msg}contract "{module_node.name}", ' fn_node = node.get_ancestor(vy_ast.FunctionDef) if fn_node: node_msg = f'{node_msg}function "{fn_node.name}", ' col_offset_str = "" if node.col_offset is None else str( node.col_offset) node_msg = f"{node_msg}line {node.lineno}:{col_offset_str} \n{source_annotation}\n" if isinstance(value, tuple): # if annotation includes a message, apply it at the start and further indent node_msg = textwrap.indent(node_msg, " ") node_msg = f"{value[0]}\n{node_msg}" node_msg = textwrap.indent(node_msg, " ") annotation_list.append(node_msg) annotation_msg = "\n".join(annotation_list) return f"{self.message}\n{annotation_msg}"
def __str__(self): lineno, col_offset = self.lineno, self.col_offset if lineno is not None and hasattr(self, 'source_code'): from vyper.utils import annotate_source_code source_annotation = annotate_source_code( self.source_code, lineno, col_offset, context_lines=VYPER_ERROR_CONTEXT_LINES, line_numbers=VYPER_ERROR_LINE_NUMBERS, ) col_offset_str = '' if col_offset is None else str(col_offset) return f'line {lineno}:{col_offset_str} {self.message}\n{source_annotation}' elif lineno is not None and col_offset is not None: return f'line {lineno}:{col_offset} {self.message}' return self.message
def test_annotate_source_code_marks_positions_in_source_code(): annotation = annotate_source_code(TEST_SOURCE_CODE, 22, col_offset=16, context_lines=0, line_numbers=False) assert (annotation == r""" def __str__(self): ----------------^ """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 22, col_offset=15, context_lines=1, line_numbers=False) assert (annotation == r""" def __str__(self): ---------------^ output = self.message """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 22, col_offset=20, context_lines=2, line_numbers=False) assert (annotation == r""" self.col_offset = col_offset def __str__(self): --------------------^ output = self.message """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 1, col_offset=5, context_lines=3, line_numbers=True) assert (annotation == r""" ---> 1 # Attempts to display the line and column of violating code. ------------^ 2 class ParserException(Exception): 3 def __init__(self, message='Error Message not found.', item=None): 4 self.message = message """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 36, col_offset=8, context_lines=4, line_numbers=True) assert (annotation == r""" 32 33 elif self.lineno is not None and self.col_offset is not None: 34 output = f'line {self.lineno}:{self.col_offset} {output}' 35 ---> 36 return output ----------------^ """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 15, col_offset=8, context_lines=11, line_numbers=True) assert (annotation == r""" 4 self.message = message 5 self.lineno = None 6 self.col_offset = None 7 8 if isinstance(item, tuple): # is a position. 9 self.lineno, self.col_offset = item 10 elif item and hasattr(item, 'lineno'): 11 self.set_err_pos(item.lineno, item.col_offset) 12 if hasattr(item, 'source_code'): 13 self.source_code = item.source_code.splitlines() 14 ---> 15 def set_err_pos(self, lineno, col_offset): ----------------^ 16 if not self.lineno: 17 self.lineno = lineno 18 19 if not self.col_offset: 20 self.col_offset = col_offset 21 22 def __str__(self): 23 output = self.message 24 25 if self.lineno and hasattr(self, 'source_code'): 26 """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 15, col_offset=None, context_lines=3, line_numbers=True) assert (annotation == r""" 12 if hasattr(item, 'source_code'): 13 self.source_code = item.source_code.splitlines() 14 ---> 15 def set_err_pos(self, lineno, col_offset): 16 if not self.lineno: 17 self.lineno = lineno 18 """[1:-1]) annotation = annotate_source_code(TEST_SOURCE_CODE, 15, col_offset=None, context_lines=2, line_numbers=False) assert (annotation == r""" self.source_code = item.source_code.splitlines() def set_err_pos(self, lineno, col_offset): if not self.lineno: self.lineno = lineno """[1:-1])
def test_annotate_source_code_raises_value_errors(bad_lineno): with pytest.raises(ValueError, match="Line number is out of range"): annotate_source_code(TEST_SOURCE_CODE, bad_lineno)