PK̥JBZQM M 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 collections import OrderedDict from functools import partial, wraps from logbook import Logger __version__ = "1.1.4" def iologger(func=None, catch_exceptions=True): """ 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 catch_exceptions: will catch exceptions gracefully if true. :param func: func to run and all its args/kwargs. :return: returns func(*args, **kwargs) """ if func is None: return partial(iologger, catch_exceptions=catch_exceptions) logger = Logger("IOL - {}".format(func.__name__)) @wraps(func) def wrapper(*args, **kwargs) -> None: def run_function(func): func_dict = OrderedDict() func_dict.keys = [ 'passed_args', 'passed_kwargs', 'returned', 'exec_time', 'exception' ] try: func_dict['passed_args'] = args func_dict['passed_kwargs'] = kwargs start = time.time() result = func(*args, **kwargs) end = time.time() func_dict['returned'] = result func_dict['exec_time'] = "{:f}".format(end - start) return result except Exception as e: func_dict['exception'] = e raise e finally: logger.info(func_dict) if catch_exceptions: try: with logger.catch_exceptions(): return run_function(func) except Exception as e: return e else: return run_function(func) return wrapper PKJoNNiologger/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_graceful() -> None: """ This function just raises an exception. :return: None """ raise PermissionError @iologger(catch_exceptions=False) def logged_exception_ungraceful() -> 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 "passed_args" in logfile.getvalue() assert "passed_kwargs" in logfile.getvalue() assert "returned" 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 "passed_args" in logfile.getvalue() assert "passed_kwargs" in logfile.getvalue() assert "returned" 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 "passed_args" in logfile.getvalue() assert "passed_kwargs" in logfile.getvalue() assert "returned" 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 "passed_args" not in logfile.getvalue() assert "passed_kwargs" not in logfile.getvalue() assert "returned" not in logfile.getvalue() assert logfile.getvalue() == "" stdout_handler.pop_application() @pytest.mark.usefixtures('setup_logging') def test_iologger_exception_catching_graceful(): logged_exception_graceful() @pytest.mark.usefixtures('setup_logging') def test_iologger_exception_catching_ungraceful(): with pytest.raises(PermissionError): logged_exception_ungraceful() @pytest.mark.usefixtures('setup_logging') def test_iologger_exception_catching_logging(): with StringIO() as logfile: stdout_handler = StreamHandler(logfile) stdout_handler.push_application() logged_exception_graceful() assert "passed_args" in logfile.getvalue() assert "passed_kwargs" in logfile.getvalue() # assert "returned" 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_logging(t_str, t_int): with StringIO() as logfile: stdout_handler = StreamHandler(logfile) stdout_handler.push_application() logged_exception_graceful() 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']) PKJC"iologger/.cache/v/cache/lastfailed{}PKJ:|z!!?iologger/.hypothesis/examples/25079bac2819120b/01ec548baccbe696PKJ0:!!?iologger/.hypothesis/examples/25079bac2819120b/672e2508db53d291 PKJJH//?iologger/.hypothesis/examples/25079bac2819120b/9cd6668ed7bfd7c1 PKJ,J2!!?iologger/.hypothesis/examples/25079bac2819120b/c3adf95b70f9d727 PKJPܑ!!?iologger/.hypothesis/examples/25079bac2819120b/c714a24af0cee0d8 PK!H|&Ubiologger-1.1.4.dist-info/WHEEL HM K-*ϳR03rOK-J,/RH,Q034 /, (-JLR()*M ILR(4KM̫#DPK!Hqq!iologger-1.1.4.dist-info/METADATAn0 ~ V$H Vk`3#˶Y$y~t6,~I=F_ubXQ&υ b D& 荅B@cD YY)|aR|4*IrlKpϸ)gPV4n=%ei k H(U83SϻN<9IAgQH=oྪI>EhTZwwdOFy{GNZ,ClnDV,t$dkfo̡od6D}7R_0:?!kv;$ˬHBZ>}AZ/ 䱯M֚wj4NT} ޜK@煈(entN$MpwbwJ-7?\WzIu;f.]1G_ۤL <ҩ*g񜖔8a(\T C("YTPK!Hv)}Siologger-1.1.4.dist-info/RECORDMo@} ( 3 0t6.I}rS6NRI2j)?1 g:Em>,g;^Ӥҹhue g{q`~sIu=A7"))u"j?t19z?R0@N)az#.k2|Cڒ#=75cIg)H2$ScE2c@tu82!n;[ҵ{u8WKEC@?(4%X~G{,ݣgFB`î]y{̰nbWb뺎h"SU@B9Zs|1fEX#kT%JXˠT17hvR|wmOŤ-Z֠f!w_J@M P*詢ho¸tOݽ8ܹQXj'ݮsېUEy$Q^V.Gi>}VOwiEuld=0>Ęg7ܨN6xF Bt|#tMɌYVeߜ|C^PK̥JBZQM M iologger/__init__.pyPKJoNN iologger/module_test.pyPKJC" iologger/.cache/v/cache/lastfailedPKJ:|z!!?D iologger/.hypothesis/examples/25079bac2819120b/01ec548baccbe696PKJ0:!!? iologger/.hypothesis/examples/25079bac2819120b/672e2508db53d291PKJJH//?@!iologger/.hypothesis/examples/25079bac2819120b/9cd6668ed7bfd7c1PKJ,J2!!?!iologger/.hypothesis/examples/25079bac2819120b/c3adf95b70f9d727PKJPܑ!!?J"iologger/.hypothesis/examples/25079bac2819120b/c714a24af0cee0d8PK!H|&Ub"iologger-1.1.4.dist-info/WHEELPK!Hqq!Y#iologger-1.1.4.dist-info/METADATAPK!Hv)}S%iologger-1.1.4.dist-info/RECORDPK $(