# -*- coding: utf-8 -*-

"""
Исключения, по которым можно узнать, что случилось.
"""

__author__ = "Zasimov Alexey"
__email__ = "zasimov-a@yandex-team.ru"


import sys, traceback


class S3Exception(Exception):
    """
    Базовый класс для исключений, после которых невозможно восстановление.
    Информация об этих исключениях пишется в лог.
    """
    STAGE = "!!UNKNOWN!!"

    def __init__(self, native_exception, block):
        """
        @param native_exception: Исключение, которое в действительности
                                появилось.
        @param block: Объект, из которого исключение прилетело.
        """
        self.nativeException = native_exception
        self.block = block
        self.exc_info = None

    def get_stage(self):
        """
        Возвращает имя этапа, на котором произошла ошибка. Это имя выводится в
        лог.
        """
        return self.STAGE

    def __str__(self):
        return str(self.nativeException)

class throw_only:
    """
    Используется как декотратор, которые нужно заставить генерировать
    исключение строго определенного вида.

    Сделано это для того, чтобы определить, что сломалось.

    Реализовано так: обертываемая функция генерирует исключение, которое
    обертывается заданным классом и новое исключение проталкивается дальше.
    """
    def __init__(self, exc_class):
        self.exc_class = exc_class

    def __call__(self, f):
        wrapper = self
        def throwed_only_function(self, *args):
            try:
                return f(self, *args)
            except KeyboardInterrupt:
                print('Interrupted by user')
                sys.exit(-1)
            except Exception as e:
                exc_info = sys.exc_info()
                e = wrapper.exc_class(e, self)
                e.exc_info = exc_info
                raise e
        throwed_only_function.__name__ = f.__name__
        return throwed_only_function

