PKh=Jcg]]iologger/__init__.py""" Decorator which logs the wrapped function/method. The following are logged: 1. name of the function called 2. arg(s) passed for the function called (if any) 3. kwarg(s) passed for the function called (if any) 4. execution time of the function called (in seconds) * also catches and logs any exceptions raised gracefully. """ import time from functools import wraps from logbook import Logger __version__ = "1.0.5" def iologger(function): """ Decorator which logs the wrapped function/method. The following are logged: 1. name of the function called 2. arg(s) passed for the function called (if any) 3. kwarg(s) passed for the function called (if any) 4. execution time of the function called (in seconds) * also catches and logs any exceptions raised gracefully. :param function: func to run and all its args/kwargs. :return: returns func(*args, **kwargs) """ logger = Logger("IOL - {}".format(function.__name__)) @wraps(function) def wrapper(*args, **kwargs) -> None: with logger.catch_exceptions(): logger.debug("Starting...") arg_dict = dict() arg_dict['args'] = args arg_dict['kwargs'] = kwargs logger.debug("passed args/kwargs = {}".format(arg_dict)) start = time.time() result = function(*args, **kwargs) end = time.time() logger.debug("returned: '{}'".format(result)) logger.info("...Finished ({:1.2} seconds)".format(end - start)) return result return wrapper PKd=Jiologger/module_test.pyfrom io import StringIO import pytest from hypothesis import given from hypothesis.strategies import integers, permutations, text from logbook import StreamHandler from iologger import * @iologger def logged_function(a_string: str, an_int: int) -> str: """ Returns a str made from static text, a passed str, and a passed int. :param a_string: a str to be used in the returned string :param an_int: an int to be used in the returned string :return: a str which includes both a_string and an_int values """ return "Your str was '{}' and your int was '{}'.".format(a_string, an_int) @iologger def logged_exception() -> None: """ This function just raises an exception. :return: None """ raise PermissionError @pytest.fixture() def setup_logging(): logger = Logger('test_logger') return logger @given(t_str=text(alphabet='azbef'), t_int=integers()) def test_iologger_runs(t_str, t_int): assert logged_function(a_string=t_str, an_int=t_int) @given(t_str=permutations('azbef'), t_int=integers()) @pytest.mark.usefixtures('setup_logging') def test_args_logging(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile) stdout_handler.push_application() t_str = ''.join(t_str) logged_function(a_string=t_str, an_int=t_int) assert t_str in logfile.getvalue() assert str(t_int) in logfile.getvalue() stdout_handler.pop_application() @given(t_str=text(alphabet='azbef'), t_int=integers()) @pytest.mark.usefixtures('setup_logging') def test_iologger_debug_level(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile) stdout_handler.push_application() t_str = ''.join(t_str) logged_function(a_string=t_str, an_int=t_int) assert "Starting" in logfile.getvalue() assert "args/kwargs" in logfile.getvalue() assert "Finished" in logfile.getvalue() assert logfile.getvalue() assert len(logfile.getvalue().splitlines()) == 4 stdout_handler.pop_application() @given(t_str=text(alphabet='azbef'), t_int=integers()) @pytest.mark.usefixtures('setup_logging') def test_iologger_info_level(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile, level="INFO") stdout_handler.push_application() t_str = ''.join(t_str) logged_function(a_string=t_str, an_int=t_int) assert "Starting" not in logfile.getvalue() assert "args/kwargs" not in logfile.getvalue() assert "Finished" in logfile.getvalue() assert logfile.getvalue() assert len(logfile.getvalue().splitlines()) == 1 stdout_handler.pop_application() @given(t_str=text(alphabet='azbef'), t_int=integers()) @pytest.mark.usefixtures('setup_logging') def test_iologger_notice_level(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile, level="NOTICE") stdout_handler.push_application() t_str = ''.join(t_str) logged_function(a_string=t_str, an_int=t_int) assert "Starting" not in logfile.getvalue() assert "args/kwargs" not in logfile.getvalue() assert "Finished" not in logfile.getvalue() assert logfile.getvalue() == "" stdout_handler.pop_application() @given(t_str=text(alphabet='azbef'), t_int=integers()) @pytest.mark.usefixtures('setup_logging') def test_iologger_notice_level(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile, level="NOTICE") stdout_handler.push_application() t_str = ''.join(t_str) logged_function(a_string=t_str, an_int=t_int) assert "Starting" not in logfile.getvalue() assert "args/kwargs" not in logfile.getvalue() assert "Finished" not in logfile.getvalue() assert logfile.getvalue() == "" stdout_handler.pop_application() @pytest.mark.usefixtures('setup_logging') def test_iologger_exception_catching(): with StringIO() as logfile: stdout_handler = StreamHandler(logfile) stdout_handler.push_application() logged_exception() assert "Starting" in logfile.getvalue() assert "args/kwargs" in logfile.getvalue() assert "PermissionError" in logfile.getvalue() stdout_handler.pop_application() @given(t_str=text(alphabet='azbef'), t_int=integers()) @pytest.mark.usefixtures('setup_logging') def test_iologger_exception_catching_graceful(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile) stdout_handler.push_application() logged_exception() t_str = ''.join(t_str) logged_function(a_string=t_str, an_int=t_int) assert "Starting" in logfile.getvalue() assert "args/kwargs" in logfile.getvalue() assert "PermissionError" in logfile.getvalue() assert "Finished" in logfile.getvalue() stdout_handler.pop_application() if __name__ == "__main__": pytest.main(['-v']) PK!H|&Ubiologger-1.0.5.dist-info/WHEEL HM K-*ϳR03rOK-J,/RH,Q034 /, (-JLR()*M ILR(4KM̫#DPK!HT)!iologger-1.0.5.dist-info/METADATAM0sl#mEbTy8c!Ϳg݅}C(<1*F'ER$ 2y.l*7go,Ѷ n,zc)$/pX*BVkI9+/LʂQ9W.r77Ԋ6B;l?mw߶]MV6DRuS}:Bd&iO${]UY>EhTZw1[O`o7znhUcJ-!sd7#h+C+tY5G foahZml:n>CT!?`.u#kvLY+ ,,Q^8? 2gQP!W/o?=LӵV@i23t`[07 :^`"3@N/%Cq!/&)58ڑNeP9Ct\dEՙ0,-rJ!PK!Hܺ3niologger-1.0.5.dist-info/RECORDuKr0нg ,\ ?`74 nyB֒sO)P]"k) deq'sG^ތG9h٫[1L :1b<Ռ*6[pw&k^at޼X=א 0qE)q8W:k$2e;Z$ NB!n3W&CW[s([sҖWlIBV]"e[,z4jSIsz.5J=MPKh=Jcg]]iologger/__init__.pyPKd=Jiologger/module_test.pyPK!H|&Ubiologger-1.0.5.dist-info/WHEELPK!HT)!Uiologger-1.0.5.dist-info/METADATAPK!Hܺ3nziologger-1.0.5.dist-info/RECORDPKo