PKzJiologger/__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.7" class FunctionExecutionError(BaseException): pass def iologger(function=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 function: func to run and all its args/kwargs. :return: returns func(*args, **kwargs) """ if function is None: return partial(iologger, catch_exceptions=catch_exceptions) logger = Logger(function.__name__) @wraps(function) def wrapper(*args, **kwargs) -> None: def run_function(func): arg_dict = OrderedDict() arg_dict['args'] = args arg_dict['kwargs'] = kwargs result = None start = time.time() try: result = func(*args, **kwargs) arg_dict['returned'] = str(result) except Exception as e: result = "Exception: {}".format(e) arg_dict['returned'] = str(result) arg_dict['exception'] = str(e) raise Exception finally: end = time.time() arg_dict['exec_time'] = "{:f} seconds".format(end - start) logger.info(str(arg_dict)) return result if catch_exceptions: with logger.catch_exceptions(): return run_function(function) else: return run_function(function) return wrapper PKqJE5NNiologger/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 "Starting" in logfile.getvalue() # assert "args/kwargs" 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_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" in logfile.getvalue() # assert "Finished" not 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_graceful(): # logged_exception_graceful() # # # @pytest.mark.usefixtures('setup_logging') # def test_iologger_exception_catching_ungraceful(): # with pytest.raises(FunctionExecutionError): # 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 "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_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']) PKkt;JC"iologger/.cache/v/cache/lastfailed{}PKXf;J:|z!!?iologger/.hypothesis/examples/d11ab8b6baef3077/01ec548baccbe696PKPf;J/!!?iologger/.hypothesis/examples/d11ab8b6baef3077/20070074de316402ŀPKPf;Jk<7\!!?iologger/.hypothesis/examples/d11ab8b6baef3077/31bf9e18d6132942PKPf;JYQ !!?iologger/.hypothesis/examples/d11ab8b6baef3077/363af9b65c099c60PKPf;J!!?iologger/.hypothesis/examples/d11ab8b6baef3077/3b3bd7f3f5fe614bPKPf;J/f!!?iologger/.hypothesis/examples/d11ab8b6baef3077/55fb667caede5e32PKPf;J!!?iologger/.hypothesis/examples/d11ab8b6baef3077/5d5a3d8c9ff6583cPKPf;J+''?iologger/.hypothesis/examples/d11ab8b6baef3077/5fa4fa5f4dbe5909ŀPKPf;J%!!?iologger/.hypothesis/examples/d11ab8b6baef3077/6f70561bd02b37f0PKPf;J`!!?iologger/.hypothesis/examples/d11ab8b6baef3077/748ea665e48eca7cPKPf;JϺr0!!?iologger/.hypothesis/examples/d11ab8b6baef3077/799e1b536e553f23PKPf;JKeL!!?iologger/.hypothesis/examples/d11ab8b6baef3077/8e05ec1399bc61edPKPf;J|a<a<8iologger/.hypothesis/unicodedata/8.0.0/charmap.pickle.gztmp9rckc40mM |T̜ df3$ "*#}ֿk]R++L*U.mV[w%k}0g<=yt:X?-}U|#b쥋 K.],]pۥ-Ve*eKPY%uCvPsVSnNr^Ύ"|<(_m|Y+X|?\SXW.9rx37#8ތ26=#82CPQ;\383qgFp3G"##8H؛ ^o$Z]kkjuZ+{ umPg:+O c|֐{ a6<`P4LP/l.y0qEÄavrP>:L a>\(G v(yp[H^7ܖ_ /V&oaKFpaeA(l,cM#`s<m `enP6,yH[He#Lf2hc)6ܵv#Oj鍶C-#i5&d[5_dW6"&[BdȕMV&n|~-$?krԢb{-|֐_[V5h`Qֲ̬AY<8+`+^{, Ϧ1l6ypB>g_Y_9߆uVO6[l~rS[ٲu:{fɓ6MMV& ذk!ẉހ:6 7K7ɧ6rpɦA2P;(' |A*D|oߌq+~cq_ ^v:!x~&&/o?' +އG'Ɋ/8D>mH/W Zj}|Sw_ݗ??uR-+> >_~?Zy0%|v}$>}"d|lK?p/?TL_uq_p߅t=VkZnyp;׸op߄ݷl3kr/&/t oor× /9+^׺ގǹO'O't >}_|Cݏv?~:p?k-+~b}Q+ݟM 򖆊%#},)f :MuQ5Dz }6|؊V=fz8s\sݏOt_q^vy<>Y=ߝ_//x|9Pŏguh/t_~~-xyZN4W3{BO(})~[Kxmm??8{K\_xϸoo$|4|{{^|Y^z^'v]ůzM~k~Rx'YuxC>xϹGoo>>$||W{{g>~0~ㇻ~4~⧺~~B|7Kooq77xHXerU*Z/{򺏽cO_į4?[ܟy^v?K޷/+^v|k >`|"+uk_t/}r}}|}gs?$v{7^v:z+5_q7'b8xWŗT`.Qɥ /s D @pOeu XKk**B9<{@(lk^3@(GBM G kP #ܻ@('B}  l'rR X rj dPk`,B 7ܓB_ X kb`*5@(@@(kUPk P<3ʟByn X (Mg#`$WP^MPv X /~@(@=Hl%d X ρ` ܻ@v&=m 'kJI@(廁7@(? ām$? kS`11{@F*.₺ *.₺ *.₺ *.₺ *.₺ *.₺ *.LN 26^\( ֆz %.Uܖ''6! <'a$k {\ɗ|5!X#M0<'9!8 yNsBpO5&ʳm(PPnCA݆ u 6(8PP}P~P(ByA(x B^(xF /C CA=gT` 5%CA}kO(Xu 4CZ(x |CZg(P ?U5P(}!a5PBAm |(/ PC &P0nB &P0nB &P0nBs(`P/Bx "P/~􋤠_$")IAH ER/~􋤠_$")IAH ER/~􋤠_$")IAH ERPIjmYLl+ó㷲3ɳ g$8Hp8#qF 3g$8Hp8#qF 3g$8Hp8#qF b$苑` P F5H7#3H ւ#A}4HG#AH0H0H0H0)Hп"A+Hп"A+Hп"A9Hп"A+C"<$"H"A-H"AFrI$_E W$_E W$_E W$_E W$x EDgB$Dg̑k$x X$cE> X$cE> X$cE> X$cE> X$cE> X$cE>Y]}ֶ$sYk##9=ksv9/kǒ vٝkriJMޛGD'jrm^ _:$k_dK2*juVA} U0i]șO`OAv8 )oǐ? qy~iy; /. "/. "/.~^p yu?/n &/n &/n &/n &/n &/n &/n &/n &/n;gyA=׵ۆgmC}(EA_/ zQ׋^}(EA_/ zQ׋^`}(EA_/ zQ׋^`(wE+ ]Q0qW`(wE+ ]Qp- %X\wKnIuYq䄒z[\oK:- %$ޖ$8/%y) KIp^JR༔$8/%y) KIp^JR༔$8/%y) KIp^JRz[􋒝E$/ %+ _IpJWח{qJUMIpJT􇒠?$%A( CIJ/ $x^~;ghrA$cV3@Zy<笳9*}Ve?Gib=}}X p}G}xK%/5>}|_s| _}>s_/r8?U>qh[G[2nϓoqAW v$3!j_%}T{gCsvn"0T(*A3T0ګWZ_+yQ/ j)}M%-v;[qe`4oe+ɓs f9<7owMதK0]貛olr̎LQH6,K,( VJW5B^W>է>#) VʶjΓ)/y¶dG  r rU`9T>mL'dʦqvYIU6<^ _*@nor`.8D( [;dlmٟ>$ɰvf4R-;V U)M^RmWCUrj WT k&&7Vd2e)ץv)"ǧl}v wJA);<<%x);$e?#/SCl9yg"I䊔༤UɯSח VOOhru6>m;(msvyrZp I ^gڮ$N5/+ڴ]Gސ-![ȞrmZ:3aomaMn]2󚱃y;$cWWg!2vyO Wd63)cog2YcX=9&5Ǝ Rc Kju5vyW=DO=IE_k鵶;yA]H^\+&䕵Tj7䵵~OZ+r㮵~Z[NYkw+j'ߨdNzlr:;ή"c]uZm?z;<^0gcȓmyz]@^]/8\o{w03r0۟&?o/[mʽkU~M."a;^{\aOOus{|JVu ׍.5K0lY8`qv5t=Hnge26ail{WK*ko/ح*[_,]Ɛ'_hVYJ` dN=$Xw=v*yaE~c_=#XSmjwLr^K^kwo;?zmX>ϾG36'OlyGٽ}\'>nAg ߪET[-~Am[rtuo9{]Ξ$v"_lWɭk6nv w)خn69`w/ .wlɍm\0hA{7~#J{>c%ވOpލ _4{^~SܻǸGs^/s_=^m}33/t5577cq/uJgݗ='?uxp|vxx|໸͞e?q jng3__wsÜpcl=eʾ~_>XN~fnw;'`LSOr:{&w_lߕ~= 9codܝ׺اً7,Ēxֽmx{;>}"ÿ^^nl}~~\|܏r??3u??߽7wurY/XI>Mg/V,^?iG`ƁfY[ēfm ٓeY` #+O_}(Pp +#CA;P vP V H(#>$}$)#IAI HRG>$}$)#IAI HRG>$}$)#IAI HRGO.'XA\]/8??nWvE 3g$8Hp8#qF 3g$8Hp8#qF 3g$8Hp8#A2C"<$D> V"I$X1n#JQ$X95H_#AH0H0H0H0+Hп"A+Hп"A+Hп"A+Hп"A+EI$.DB$oE [$oE Y$_E W$_E W$_E W$_E W$XH3#'#H"A},H"A},H"A},H"A},H"A},H"A},HPYddֶ"Ggm,S֦{fȃYnMV06?kOeO+Y{gM~2*Xm:mՆ[ vV֭oVAݷZGeE&S[m{`UyyA=(ؼ`7H^$/ )y.M^C^PyA=C^PyA=C^p y>/K^P/yAK^P/yAK^P/yA^z %/^z %/8yAK^P/yAK^0^z %/^z vS): vQз]`\}(EA. vQз]o}(EA. YQ0Ί]^](_E* WQ0U`|(_E* WQ0jIP_%A}UWIp]- %$ӒoӒzZeIp^JR༔$8/%y) KIp^JR༔$8/%y) KIp^JR༔$8/%y) %.$/dwIpJV`_I$8O%y* OIp~JSIP%A_IP%A_%$؅_I'1Rmj3Z5%:)N^"N ^LӖ`ԴrӂIҶ7y@ZuҶ|4m$LS3i3.-x{Cv Œ]D>\a28:cOdOK{XSkl:9$g5[ckjy[O~RcV~Mc/:zs3^M!Qv"yQ]L^VoW\o76 W7SFۖ6jqFۉll&"$8&ސ&&;u՟no/sGE-r"~9V<+*kTM9{=;䂢R6UËBI[ʤ%I{\ܭTY- U6\P%V*{G>$3DPClYb OC}CmPk#ۇZyP;P'U f[ՂZm{V-K_m?# jUՂwN)s-|ݔ}#e{oJp);<=%wRv!pJ ruʞ"M ҂/-xiAZZЋӂIۑi#-i]_F36=Y3rO(cGd7#8,#س2w2AZؑ35{|FpZDQkw za=@>TkOڳ:kZ}{1Oq|.&/ȟok|Guq_o;;$rzJXob`Op}v7y_O>g+Gs>O O}Jàձ.7hc67J|=ho3;;)x{s > .{#NLw??c.H>ƽ~*~{7~#v|eW&wwt_w;{yI)tc৹~.+1ρndMX@s /އ=~ yl1~&'~1~ekJ&}ZR<&m󹞿 1m \W߫ Z;Z{Y{e?~z|R?l\?6ګ}Mv&lџ7ۋ~;"sEkWs^oWɍ59l췯+ekdUf)2*s u;v#42_q?wU]}̽Ū3>0Y͜?a?.dV%Xovr.DW E*yw]钻zr=ﭺpץ LJ p%+ߡ3)I7dOگ!F sll 5 >/'l;gWsZm.wEืlme6eq+v[;?y6w%m%c3ߟܯ6WxF{u ;~߳%|^vf0}/x۟Rh~#_;w/tŗob k)O|>#ho3?>;GO|ˆ=G<~&Wӡ|ۡy;40;M<0'Xu\mf?Q`teR0H * hs%_SSpi靂]q%Xxm<՟AOi) yX k#.'x,"5݄M\`ޒzJ FxRI3,&Se5ds`TY B68(8AnAI5h{srAxP0~x2([,2U,[Tf2[9,xQ]y*&%hf-}>k5߿f1,& %3i49DB|F Lȵ {00}} K2~̒NU%)P'8u0Bps XN&'X3 v Q(Xk666A- fmi@mi p36ZO9Q`Ϳ]#=]O]|]]#]w?ץ]#wn7P-tU v +Oat#x7 氃+dYPw_z5׫W=}²2}p>_]Pq{]zݸ0.ƭLlv "+xGg|3kܜA.J6]W@sأ- fesS>oMDєT}

_8_P>QC㗅/Y%MU6s3#'X \ʜ]ElVAZV[L^jדK[K*x**ػ**/H`j򮌲V:ǹ(|cM޷હ꺍 fm8auKnl2k kmF VގocMF6hǐ`Z<,eQz}$>-Ylo>>~~{/Fsg0. 3 n< 1iWWvWYU*$"ؑZ-i9m_҂g\\_ ꬁl,9Np7U':y=A?:{ޖT۵}7 ^#8檧5۹j.jUV&hVk VEn*lV\UplV3V3rvZZZV[Bj#oi[RF.kgɵp wwwy ~3s013l܏Op*v1Q(vwy+z^e|$q"~E}cmtt_~Q|$vw__߽Q>}{kO?~Woxo1~?ǩ9cz|9Aܯo#stW}+'hU/Pˉwwai-=BP?9K1ks?Lg{PK!H|&Ubiologger-1.1.7.dist-info/WHEEL HM K-*ϳR03rOK-J,/RH,Q034 /, (-JLR()*M ILR(4KM̫#DPK!H$9q!iologger-1.1.7.dist-info/METADATAMs0= cgIPO{IZP-$*b}c;iV7'1EWa4:̓-"isa7,Ѷ <n,zc)$/pX*BVkI9-/LʂQ9W.Ns77ԊM7>B;l?mw߶}MV6W|{fywי:'3)H{6$ʚT/}?m^.QK+\ OzJup.fK6 FFN#Xb؂DVFfV,0414uH}B~\h/.# i-z#Q^872cAc!5M?8FGRu:0{s.v"2i 8=4݉hz@`8*%+6g$o܄s]BeD72\084]2G_$G3ҩ*g񜖔~pP:`QvE.Z6PK!H3 iologger-1.1.7.dist-info/RECORDYϲ8,P^̅o(b," ~L&73ɘ46&ŵ"~$O_"ڮg>qn1g{ɏJSS'V\n(b~~淼5dQ  f5tctcfjU]*@7 HJ&$ɕwnj >rUqJH7}s,I$+aRD %AQ~(7ž/I뢝y.^ڠ%y46\! ]I(kɌKɂV ڥ0ygz%|ckcpx}J! XxԢwVi*Jhiz5XK7*H)qc5wwa<a<8K)iologger/.hypothesis/unicodedata/8.0.0/charmap.pickle.gzPK!H|&Ubfiologger-1.1.7.dist-info/WHEELPK!H$9q!fiologger-1.1.7.dist-info/METADATAPK!H3 hiologger-1.1.7.dist-info/RECORDPK< >n