import functools import logging from functools import wraps import time logging.basicConfig( level=logging.DEBUG, format="[%(asctime)s] [%(levelname)s] %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S %z", ) logger = logging.getLogger(__name__) def timerun(func): """Calculate the execution time of a method and return it back""" @functools.wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) duration = time.time() - start logger.debug(f"Duration of {func.__name__} function was {duration}") return result return wrapper def yommi_logger( *, logging_type ): # I prefer keyword-only arugments for decorators, but that is your call... def decorator(func): @wraps(func) def debug(*args, **kwargs): logger.debug(f"Calling : {func.__name__}") logger.debug(f"args, kwargs: {args, kwargs}") start = time.time() result = func(*args, **kwargs) duration = time.time() - start logger.debug(f"{func.__name__} function was {duration}") return result @wraps(func) def another_option(*args, **kwargs): print("another option") return func(*args, **kwargs) options = {"debug": debug, "another_option": another_option} return options[logging_type] return decorator class LoggerYommiOld: def __init__(self, logging_type: str = "debug"): self.logging_function = getattr(self, logging_type) def __call__(self, decorated_function: callable): def f(*args, **kwargs): return self.logging_function(decorated_function, *args, **kwargs) return f def debug(self, decorated_function, *args, **kwargs): print("starting function") output = decorated_function(*args, **kwargs) print("Completing Function") return output