import ast def quote_text(text): return '\n'.join([f' {t}' for t in text.split('\n')]) class CustomError(Exception): def __init__(self, msg, node = None): self.msg = msg if node is not None: self.at(node) def at(self, node): self.msg = f'Error at {node.lineno}:{node.col_offset+1}-' \ f'{node.end_lineno}:{node.end_col_offset+1} ' \ f'\n{quote_text(ast.unparse(node))}\n{self.msg}' return self def stringify_subst(subst): if isinstance(subst, str): return subst elements = [f"{key}: {str(value)}" for key, value in subst.items()] return "{" + ', '.join(elements) + "}"