import time
import logging
from contextlib import contextmanager
import sys
import warnings

if not sys.warnoptions:
    warnings.simplefilter("ignore")


def log_time_decorator(func):
    """
    logs func execution time
    :param func:
    :return:
    """
    def timed(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        logging.error('TIMER {}: {}'.format(func.__name__, round(time.time() - start, 3)))
        return res

    return timed


@contextmanager
def log_time_context(tag='', longer=0):
    """

    :param tag: log time preceeded with this tag
    :param longer: log only if execution took longer than this (float)
    :return:
    """
    start = time.time()
    yield
    end = time.time()
    if end - start > longer:
        logging.error('CONTEXT TIMER {}: {}'.format(tag, round(end - start, 3)))


class memoized_property(object):
    """
    Дискриптор, который используется как декоратор для методов класса,
    добавляет инстансу одноименный атрибут и
    сохраняет в нем значение вычисления метода
    """
    def __init__(self, method):
        self._method = method

    def __get__(self, instance, owner):
        if instance is None:
            return None
        value = self._method(instance)
        setattr(instance, self._method.__name__, value)
        return value

__all__ = ['log_time_decorator', 'log_time_context', 'memoized_property']