from itertools import chain, islice


def _unpack_translation_error(func_lines, args, before=2, after=5):
    """Unpacks TranslationError *args* data and reconstructs the contained exception.

    Translation errors are used to attach source localtion (line number / column offset)
    and shuttle them out of AST traversal where they can be formatted and rethrown.

    :param args: TranslationError.args with (error type, line number and error message)
    :param before: number of lines to show before the offending one.
    :param after: number of lines to show after the offending one.

    """

    def draw_gutter(snippet, line_index):
        for i, line in enumerate(snippet):
            prefix = "  >>> " if i == line_index else "      "
            yield prefix + line

    error_type, line_number, message = args
    line_i = line_number - 1

    padded = draw_gutter(func_lines.split("\n"), line_i)
    snippet = islice(padded, max(0, line_i - before), line_i + after)

    return error_type("\n".join(chain((message, "  Traceback:"), snippet)))