ÿØÿà JFIF    ÿÛ „ !.%+&8&+/1555$;@;4?.451 4,$,44444444444414444444444444444444444444444444444444ÿÀ  á á" ÿÄ     ÿÄ ?    !1AQaq"2‘¡±ÁðBRbrÑá#‚’¢²3S CñÿÄ   ÿÄ !    !1QAa‘2ÿÚ   ? 5˜Z¯V¦cø)›t/? z¨±>Õ5€¶‹Á¤·¼z¼Ü¬+ñ®v¤¨_ˆR­BFn©—˜ý®ç̝P8gýt·ÉSTŦˆìät?þé¼íìN/Þa)ì–í6ô… Ï¿øÃj´¿KÇü]ÿ ªô¹-eKànëÕHTx}ýSÜ›ÿ ”7Ø×&µ<¦  ¥ÑO¶[Ù¯ä¨ÞÃÿ PZ-¬;#õ|•oaÿ ©CìÞz3˜öː/¤­ñTûIØ}š^ mÓ%ªxˆ¥ÉŸu=Z+ISe¿45™¼u;ú&WØ÷€æßQ™®{|íx*TC“#ZŠìZ§²‹ 6pv…³¿¡äª*áZÐ%ÒOáˆo"x«OHk w±æ+¬V(kMúŸ5Vö«$ ÁrÏbàb57/luR ¸ÑÛj Òµì`Мq­û žICÀÊ•©4€Âcà¨Ï€O´<èÐ:›ù(Ë^L8þ‘ÍÌ#¸Ð_Ì©ÙK(Öz 4¬û+¸;ü’V’84‘¬ÃŽ:[â‡ÔÌáõp¢~§ªlæ£ö{®G>J¼"°‡7¯ÆÉèßû ‹É‹§ÁòÃýâßî ^ƾÙõ‹×óH#«LP½ïX=xÑÍ$|W?•~• îëÔ©ª‹ {ÝT…Kÿ ”hûâá)J*ö˜–ÔU;iÇ€/ ÆþjóZ\ýwØ=Ìm ºèËL9 ýèÆð/¨’¥öo=nË.%Îì ŽÕ¯È|{Oj²ƒE6e/ßdÄõ²Ìâ1O®ò×TsəԸhOMýíMˆ¿¼H˜l²,7Â¥#MF/Úf°Ö½± ¸–dr‹NýÊ íjqx{œÉ ä-È ¦ øÄër¨q°ð †nцýÑÄÆ’mä…n<0È™;ÁÝá¯ÁZƒ7FÀmì­ É&9ˆîéi¶ùN§Y• ÃZãAâ?•‡©‰ , ó¾IŸŠc1 4â&y­&pŠ­6;M À 0¹qç»p.á …ŸÅáK@%6·y6ƒ‰3?”úºŽ‰éX5ªPT §µ!=Mž«Ú½‹ÅgÂSâÉaþÓoö–¯ÁÔìR>5éÿ üs¶ÆUcÌ kÇR ]ÿ ù¬¼«VŽ;Â|‡~¢¦”ÏŰæ {L™Õ°Óv¹ò¸írޡעCÃ!íVÕ {¶»sŒNPg/ "uÕbkm²“$ďå¿é¹§°½æz¯6 †s¿!s–wÚÝ“™Œ °.ûj>·+™Òa…©Œ&rÝÎtÛë긪Ît’LAVp%c Úý[ÄzJ¾ÇàXXç@˜ó<êL]·T˜¾¥1Ó©V‡g´æ½¦Ý@¹óø!_@´ÞâSÁ —S3™•& ]@JHÚý©ZŽ €×æÔr»Áf!‡yÞ4Mv*èÓã_{‘åóUuљØ«Oïé*®EvÑ Œ÷‡U \"㪒ÍK+À 4“M¡ï:0¥5í!'<@î´”>Ç»&Z–ïCCV˜Ì5Šo&îhè.žû |ÓK©h$s6KìŒëã)¹hI¦GïOåóI;ììü#É$Š0…Ææ¥TØ.5­¾gn´ “ÂÖ\:hœ89G)J@„}œ:’Ò{/Š"¦_Æ×7Æ3VÇŠÊa]ÚŒÙ€Ä–=®uÁßâACZƒ§§£ Qnâ:«,×{tyø¬iÛcœÜÄ€H½ÄÍCk´÷šß .W'b¤Íåh]÷€=,Žv×cÚEÚHXJX¶îo¨FÒtèöŸ>ªª6[J®Fµ£sGÁeqõfe\íjÒÐïÄÐGˆe1Ø‹.Ø”‘Ëuø Y­ˆÜ ŽG|zùªüMpDnQWÄ”%JŠ™)â*p@Örš«ÕT2Ð%ˆG#ª„ ·¤!°ŸOTÂT¸aÚ%4&h™LµšØüÐ.F¿²ÐÞ_Ç‚¾ÅÃaÜ÷09Æ q€öy˜v‡85õN÷]¬äѼóS{°_MެúÔ#°Ç¸0åÞè2ëôPcvÆw9®ií1Ä8F™˜à‰´+‰Ik1òÝ7“Ñ×ÒsÝ\x‚h`ÞÑ`ó"|µEcý£n˜h`}GÞ !±ù²Ápü²ß6 0ïi󜵩SÈÇ7˜-ÕURO˜¦´f$ªž-Í6(œ}<„ éc øs]ŽŽ„*—¾ ìdŽ„)méª\¿êÎIg¾ØÞ~I#C/¼¼´EÁÈŽi8“©õådô·>euä ƒ'Ê×लR1ÉJE1ÐAát`t;ÇР%Ý<‡¥„ÍÆ`×Oyó)õiI€ñQaŸ4Ûù\áàaÃÔ¹HÃu¹*k€¦<„e S‡&õÏ B!ŽhüÞ`yj}mªf×\¿ Ç~æ­9‡û\՞Ǖg²1Žû5V7 !àöšm° c`ܬøÇìµÒ'P"?…´Ö,"§^•õލsÔ)6˜sæéÍR¼ ò|Sl”‹7 nPW Gòú÷½§O¯‡„l¡kSÞŒr½PÊ@æ¢pŽ-mÿ #Ÿ˜Àº¶Áä¦;ïÔæ$1££`“Õ>„—·ž)ßð³ñ#Ï Ô$¶œ‰ÊE‹À;÷º ¯«P:Ñ”8–IÊtpÞ3ª“>ê“þës4ò2OÏÕ­±zô†Õ§‰.÷ä¸;¿˜“'œ›žª}«Œ{ª±Ì 9ÔóÞÕ‡0 $íWV3Üì¬ —@kÝ4@¿r¼±½¬™›?øØæ´'Áé®CË3-g$˜ö‡×auÚi´Žp/êÛ æF›Ú2v‹ã¿¿,nB1̨ƃqÞa5͝@&Æû“él÷ \C²½UÍc ¯k×¢U ÖéQå™—-r wô ÞÏ<Ò=&=ÿ Ôê Òêˈt,i—;LîÜ á¸*ÚÃ1$êL•LÍ <É)ýÐà’ ;F™{ƒ™˜€&'}‚ãÄK`¡ÞT@I;®žZóè‚s’7®°›+§O­Åq©é»²9<Ô J ¼9O’HL»Ùïì¸rk¼Ž_ý‘TŸu[²ßÚŒ·ü÷B%¯E ŸÔX5êO´ Ç•€’I0 ÉJX` ñ¹õ%;µŸD‘«´€àwÒ™U ûئžÖö\×®×´8 ½‡ºÐÆÓ§?Àkmœ=;d5*@-ì0F Rªýš[Ü6âö̃ڸr*KA9· u*µæ£?U¸Âêí†8@¦X4 e-ò„0s{ HâUpU?¼mñRa°®a%Ð'tÉ×’\¾ÊÉ]t›h>·(Ë@R¼¡Ãt h}’O÷au<+nT…Ö…MӐ??Óe95 q>í/;&JSû °¯ÊéÞ øƒ*Ã2½Ài&:nôUl=¾¿5eˆ3”ñc|Ú2V”>„»&eE;«ÚäC p¢Û úy 9š[ŒÌx¼擼A&DåÒ¯ˆ¤ÀÌ;"˜ ÏQä¸åhÊ}Ûq«Û0WžÒ|»€ø®öCm5•\ÇÀ§Pe3£]0ÃàLDÉ‰1øªxjgwT‚÷¿LΨK‹›ùs—xˆÜ±µ kæ¸f‰‰ÜGk/LÛØ6d9ò¶ùA{ƒA3š/¬D¬khÓk‰`˜"㯒r¿±Óã jx‡°e}<Ñø\3y:'À•/h½Í€Ç4~g ?Û(¼]v‘ªlKÎâ~?O‚W%{Ì:“'©úNq¾›úo(X’¥¯ˆ nFê{Ç€ü?º'ë ø‹ì Þ09ŒÌç9Æ —ËC`j@ÓÄ(+a‹un¸#ÂꟋ{K`‘ÑÍÍ'à´»/Û,KW;Þ4²þð ï Nm|~fGÏ(…³Ã)«1ö­Õ ¥‡¨©ƒÃ™ü-s=à=U66Ï«Ýc蓦W¹íž®›nÔ%êÇìŒ<#Ü×84ån®Ð ÒåOC` ñânÑs‡¢ç 1õ%Îhì½Ã½® e:ݼUZo™`  ÅZŸŒÊ«ê1ÏÄo$q¹Þ€©ˆhÐÉä¯ñ[!…Ú˜àJ:x2$Íß&PåT£6ç— ‡Í*4Ýšçjÿ ‰É nófÐ ó(L5C•åÆ\rMÒ@ò }y-W}™üýVù—ú¢=Ù”c®‘< M ž ´Phr ¦©TD ‘ù.$´÷O‡‘V2Æò.=IUŒ=ž‡â¬i™aþÓåÙ?òUø'ØÖ•.~* šTŒ!•-×áºTâ®ä#õü'´ eýlYÅÓeÕKÂrT"CÚ@u!Óxƒ{š3€}1¿(r}%«nËamjÑ%ÑNEò v ˜à  σöK³,*º.àzù¨™Ó ÚçâU¦*¿ 9{%Ö¹ njûdaXöb) kÛÆ±ûÓ\°M7ˆÂ=û›ç¿Ã‚­V»Cg–8ÙêE- j)k$º`Ã-ùEýeBÆÇ]c¡°ñty&Òd0nõ'¡W+ƒ*|–øµFa\GQªEAÔp5\Ǽ·¼Ç8·õ -â§Ú[ ‡ uZeÖ 3}×d'+¹:ð+K†Û®s!Ï$úe€<Û”x)1»a­¡LC]¸µík…ÚàA»AYº{†ªS[¦5HÒ7ù --,ísòDØ€èk ÞÀîÜ ò@â( ËNˆë›4ô½•/¦o‡€Û7 ê•ÆêòðÜy'Án½µ á˜ݦ ndeo…[ì¶Ê,¥R³Ä=À±—–ß;£™´ñSâ*g§”ïaið‘Jå~™ÓÞ ß³Õ¢»8x埒²52>AÊb&-÷\7´éÄù€T˜,w;3{ï˜k…à¹ÄqÀ«œ{€\ ˆ¾[´¨јr &Úé„Ívˆ±8†¿]|¬ņ4I×pÞS1ÈÖz‰#Ìv‡G!YNògñ:màTz¢Ý1ô©^O=~ë|5Bã™ç•¼µõ•bÆ@úÕS¬ÈŒ#¬zünrŸ û” Z²•èðV"ÁHÚý©wÝ €7¼Ìu1hÑa3Éä û f$o¿É ™Ú›ÝçnpÒ3äÌ3†Í§,Äï]$‰/pê †«À¼¸e9­Æê_C]žƒ·ý·frÁN«, E=›Çq -‰öŒ:aÏ¿±í&£Í:-} 84‘ÿ eƒQÑeëSsuiA ³g㟥ú£?ÿ ʼn*”“÷aühe:ÊWa@ÒÞk±eØ] F Ô—r.åä˜ @ö¥ªZoÐýYL·¥S²G/‡ñ <~*ZÆ´è>JlòàÛÆ½ÿ 窘ìGN¢:I®KšJp/`íIÁÀõ#Ä-€ö­šµŒoF4|ÆQØÆ@Ì|£Ô…¢À{9˜è½Üó›€ôYÒÎYsið;ís¤€à²ˆ‚4qÉVŒI$ ‰"° æµ8cXGjœˏ¡Aâý•ËÜ¢ûï e·çLx']á"oÅÎê3¯Ç—¹”ó0nå‚âg{Œñ> S´˜îè°g238‚ãköÝfÚd´6Ò€;ò÷±¢™¼›º ¢Æ'¥Ðx'e¬ç ]bÈÆV¢ó‹kýBO ðÊâ$Ÿ!×T 3Mýמ žìٍàÌü‘8÷€àæØ8æ©6‰©L´«…oãpð„~Çk‰!ñ;‹”ÛžÍ àž±z Ÿôû øŸÝužÏ;ÿ #|u6™Þ¬ÚˆÐõA4¶â|ôl|Ê2ŽÇ¤ÝÅÇY.<#Aí.k§hóF‚”Y; M½Ö4hŸ4&›­¿tès´%FìL¥£Ãk‰ÇT¤haÁ¤ÚxfÉ`ÑìË›>i 3t‚:,–+^÷´–{Û–Nxi"x‘Ûg î¨>¥Õ܁ùZH,2Û“:8xÊ¢Çí9.É-Ìâã-=çjwµS˜dütžçwýGòú®®ûº_ˆýx$–¡ãøO EÚÛÏ÷R„×w+3£Á£öUMyR²¹âŒ°š›¸Ñãò9§Ó_Dl+Ùßc›úšGÅÌc†Ž!Ko=¶.‘Îÿ c²(2®V mª.ÿ ¹B›¹å ù„öŸSV>™ü¯$y:G¢Z×àøúdî¹û­·ýÇ´:•c LÍõi_‹ö+ÎæGÊè>OŠ•äž´§Þ{X}¨1ÚTc›»Qþ•êô°t¿OP?eæ~É{5]•ÙR£r5†nZ\ã@ &îJõ ¾àC°þV>fé¥/ü5ñÊIº_é5 ;e­h<@ Ä&æÃëE%;X,ÒãÆÞ`Oò¦kŸm#˜!ÀyÄ¢| óLšò¥Ä` ¶R=|ÈCâh5ò3DˆïF†ðÒ#ÅìÛœ?¸yhBãœí ZxßÎÄhºRK„`Þödvײ™ÀÈÑÒgŒuY w³%†ƒÓzõ ÖÏp‚dH®¦A´ù§»ÓÇMæ~)ˆð‡û:ù&Ä •vGD´À n ݇¼Ö8Fö óáà£~Ë¥x`oK|Ä?fxiØü%pìR>éò+Û±éÎ>núlFŤ'tq8LZÏvÃ?„¡ß±È⽆¯³íü@x|PöUäèØã¡ð‚ŒAìÏ"vÍwóŸÍ{ ý0.z È•Ö{,N¡£¡ŸKÕÙž>Ýœþ ÍÀ°<×EA!Å‚D™IúOÍ¡>ôG}Â` ÍßkÜL™Ž Þð™ {IøF²¹òQ3&!ÃÂÞz.d&Ï-sH¸,Ôõ˜ŽP€ 77ˆÝ¼ÊëÜw =cÕ Ú,ØÐ5ÎYÐ)ì´öœgŒ[¤ßv㙑8心>h]§µháYš£²ºÑ.{Ï7Sð•?´~×SÃKýJÛ˜ ™Íäiúu<µX¶1õ^kâçIÑ£sZ4h>j*ÔšD:4­¿_ ÷¸ Õxæÿ ¸?Mù _•­ÊÐ ä ÷ý ÑwL œ­ïnTkÛUÍN©ë:¦fV ¶ÜÔÜMªÅâA½–¿R×TXš-%iTÊT•‡Ù‚JôϐZxWÑè‰f‰òG º ×Õû2aZ7OU3[“×AT–ÞŒ…-‘¤”Ì ì&(ˆ¿­•ƒkï’:ðY¦W‘ Å)“†‘˜³Åtcø˜ñTÂwÚÇ4|üLÇªí–v- qˆèU qPE.†â‘˜µ Æ,ÐÅs]8¾„oúÑ i>ÜxxÈó)ƒ ´æÁâØ$À‰vžŸf$Ž |ãw;ÀÁIJ»b` {¦Ó¤Ú$©YÀ‘n@Óïž«9J¼êG m¤ ܯ¹ÌW4€ÐÒÅÛ‡#褕Ÿn-?í|с¥÷Ú¹¬'´ÞÜ9ÓK `hê£SÄSà?7—Wí_´…óB›»:=Ãïq`<8ñÓŒÑlú2d¬ê³£hÖ[l|$vÝro~'R®‰§°ñmY ͧäP |PUª¹·:3Œ[Û{Xÿ ºâ@‚W–Äé u‚ ¯´*=íή.pûÒdt @G‰¬ s¸ ëÉücr ÞæÑ¨Ê@>¤¢Ö±. Þ'¯°ÌME[YéïĵÂCå½ Ué©Áû'Ê9%eÔðNU”ë‘ÌsD3/®+UI˜9h.WC”빓$#:pz:YÓ ¿xž* ³$Í +$kñAŠ‹†¢ Uê>¸)_š¬÷©ßAÂÔb9ÇU ¯¾á•9¯ÏÏ÷O÷¼¼Fähal1‰3Ì[Ïr•´UCksNÐ] R‘¸¥H+§Šé†c©vÖÞ0iÓ76s†î!§=ß ¼~Ô'°Ãmäoäš³ªøi1úÉ)³yV8 CLÄØÁ‘WYïi€H6ÖÑiámø^ÈY´°Ñ7¥Û*—Ñ©L«Qƒï—Ùrÿ ›£Ð*š¸ˆL©ˆ$ˆ ÷¾D§9È®«qbqC)–ˆïv´çñsÑVT­Ø, <àïºÀO«Jý·õ àfPìð .wFšir´þ’2_Y *Æ€x\« ì€9š@ Ž|F⇥ˆkZ@hÖÄ0t¿-<“‹qµ¾*ZL¤Ú)&BJpÓF5=$„at*Zš$’ÑtdûÝRI1 2މ$€$I$#‰SÞ’Hë¬ï;Á$¡t$’`<(ñÇt)$‡Ð.Êf¢X’Kt=Éé$‚ˆªè¢oÝëòI%Rgcª÷ŠyI%¡‰ÿ !ñ)´õ $¤ Ô’IIGÿÙ b ddlZddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z m Z ddl m Z ddlmZmZmZddlmZddlmZddlmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%dd l&m'Z'dd l(m)Z)m*Z*m+Z+ ddl,Z,d Z-n #e.$rd Z-YnwxYwe/ej0iZ1e-r+e2e,d rde1e,j3<de1e,j4<n de1e,j5<e6e17Z8e*rGddl9Z9ee9j:Z;e;edkZd Z?e=sd Z?dZ@dZAdZBdZCdZDeEZFdZGdZHdZIdZJGddZKGddZLGdd ZMGd!d"eLZNGd#d$eLZOe*reOZPneNZPGd%d&ZQGd'd(eQZRGd)d*eQZSd+ZTd,ZUeVeWeWeUeUeXeVeVeUd- ZYd.ZZGd/d0Z[Gd1d2e[Z\dS)3N)chain)EmptyFull LifoQueue)time)parse_qsunquoteurlparse)Version) NoBackoff)AuthenticationError$AuthenticationWrongNumberOfArgsErrorBusyLoadingErrorChildDeadlockedErrorConnectionError DataErrorExecAbortErrorInvalidResponse ModuleErrorNoPermissionError NoScriptError ReadOnlyError RedisError ResponseError TimeoutError)Retry)CRYPTOGRAPHY_AVAILABLEHIREDIS_AVAILABLE str_if_bytesTFSSLWantReadErrorz0.1.3z0.1.4z1.0.0*$s zConnection closed by server.z:Error loading the extension. Please check the server logs.z5Error unloading module: no such module with that namez/Error unloading module: operation not possible.z[Error unloading module: the module exports one or more module-side data types, can't unloadc&eZdZdZdZdZddZdS)Encoderz=Encode strings to bytes-like and decode bytes-like to stringsc0||_||_||_dSNencodingencoding_errorsdecode_responses)selfr*r+r,s 2/usr/lib/python3/dist-packages/redis/connection.py__init__zEncoder.__init__Xs  . 0r$ct|ttfr|St|trt dt|t t fr"t|}n>D --)) " 3t99$ ?d0 0 0 JJLLLCRCyr$c|jd|jd|_d|_dSrc)rirstruncaterjrkrns r.rzSocketBuffer.purges? ! r$c ||jn#t$rYnwxYwd|_d|_dSr()rriclose Exceptionrdrns r.rzSocketBuffer.close sa  JJLLL L       D    s -0 ==) r;rCrDr/propertyrortrrrrrrrFr$r.raras44X4(,XPT'5'5'5'5R   "&     r$rac8eZdZdZdZdZdZdZdZd dZ d S) PythonParserzPlain Python parsing classc>||_d|_d|_d|_dSr()reencoderrdrir-res r.r/zPythonParser.__init__s# 0   r$cR |dS#t$rYdSwxYwr( on_disconnectrrns r.__del__zPythonParser.__del__$A         DD   &&c|j|_t|j|j|j|_|j|_dS)zCalled when the socket connectsN)rdrarerfrirr- connections r. on_connectzPythonParser.on_connect*s<% # J-z/H   ") r$cpd|_|j |jd|_d|_dS)z"Called when the socket disconnectsN)rdrirrrns r.rzPythonParser.on_disconnect2s7 < # L   DL r$cD|jo|j|Sr()rirrs r.rzPythonParser.can_read:s|> 5 5g > >>r$Fcj}|stt|dd|dd}}|dvrt d||dkrE|dd}|}t|tr||S|dkrn|d krt|}nq|d kr2t|}|d krdSj |}n9|d kr3t|}|d krdSfd t|D}t|trdurj |}|S)NrR)-+:r#r"zProtocol Error: rutf-8replace)errorsrrr#rrr"c<g|]}S)disable_decoding) read_response).0irr-s r. z.PythonParser.read_response..es;""4D"EEr$F) rirrrwrr@r[r1r5rranger2r)r-rrawbyterXerrorros`` r.rzPythonParser.read_response=sl##%% B!"@AA ARaR#abb'h 5 5 5!"|j|_|jdur||dSdS)NFrT)rrrwrgetsread_from_socketrs r.rzHiredisParser.can_readsl| B!"@AA A  % ' '"&,"3"3"5"5D "e++,,Wu,UUUtr$Tc|j}|tu} |r||tr[|j|j}|dkrt t|j |jd|nu|j |j }t|trt|dkrt t|j | |r||jdSdS#t j$r3|rt%dY|r||jdSdSt&$rm}t(|jd}|s/|j|kr$Yd}~|r||jdSdSt d|jd}~wwxYw#|r||jwwxYwrq)rdrtrur recv_intorirrwrfeedrvrer1r2rUrrlryrrzr{rWr|r}r~) r-ryrrrbufflenbufferrrs r.rzHiredisParser.read_from_socketsJz 0 6 )(((& **..t|<<a<<)*HIII !!$,7;;;;)>??!&%00JCKK14D4D)*HIII !!&))) 6 455555 6 6~    B"#@AAA 6 455555 6 6& Q Q Q :==blBOOG# G(;(;uuu 6 455555 6 6""Obg"O"OPP P Q 6 45555 6s<C.D!! GG" G+-GG<GGGG:FcP|jstt|jdur|j}d|_|S|r|jd}n|j}|durN||r|jd}n|j}|duNt st|tr!| |j d}n[t|trF|rDt|dtr)| |dj d|d<t|tr|t|tr%|r#t|dtr|d|S)NFr) rrrwrrrrr1rr[r~list)r-rrXs r.rzHiredisParser.read_responses| B!"@AA A  e + +*H"'D O  +|((//HH|((**H%  ! ! # # # /<,,U33<,,.. %0 D(M22 D++HM!,<==8T** D Dx{M:: D #..x{/?/BCC  h 0 0 N x & &  8A;88  1+ r$NrB) r;rCrDrEr/rrrrrtrrrFr$r.rrns00777 $$$ $$$ (0$#6#6#6#6J++++++r$rceZdZdZddddddddddeddded dddddfd Zd Zd Zd Z dZ dZ dZ dZ dZdZdZdZdZdZdZd dZdZd!dZd"dZdZdZdS)# Connectionz4Manages TCP communication to and from a Redis server localhostirNFrstrictc tj|_||_t ||_||_||_||_||_ ||_ |p||_ ||_ |pi|_ | |_| |_| t urg} | r| t$| |_| rX|"t)t+d|_nt/j||_|j| n!t)t+d|_||_d|_||_t;| | ||_d|_||_ |!|g|_"d|_#dS)a2 Initialize a new Connection. To specify a retry policy for specific errors, first set `retry_on_error` to a list of the error/s to retry on, then set `retry` to a valid `Retry` object. To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. NrRrp)$osgetpidpidhostr5portdbusername client_namepasswordrfsocket_connect_timeoutsocket_keepalivesocket_keepalive_options socket_typeretry_on_timeoutrtappendrretry_on_errorrr retrycopydeepcopyupdate_supported_errorshealth_check_intervalnext_health_checkredis_connect_funcr&rrd_socket_read_size set_parser_connect_callbacks_buffer_cutoff)r-rrrrrfrrrrrrr*r+r, parser_classrerrrrrs r.r/zConnection.__init__sx>9;; II   &  ,&<&N# 0(@(FB%& 0 X % %N  0  ! !, / / /,  /}"9;;22 "]511 J . .~ > > > >y{{A..DJ%:"!""4x:JKK  !1  %%%"$"r$cdd|D}|jjd|dS)N,c"g|] \}}|d| S)=rF)rkvs r.rz'Connection.__repr__..As&HHHTQjjQjjHHHr$<>)join repr_piecesr|r;)r- repr_argss r.__repr__zConnection.__repr__@sJHHHHT5E5E5G5GHHHII .)88I8888r$cd|jfd|jfd|jfg}|jr|d|jf|S)Nrrrr)rrrrrr-piecess r.rzConnection.repr_piecesDsL49% ':T47OL   = MM=$*:; < < < r$cR |dS#t$rYdSwxYwr() disconnectrrns r.rzConnection.__del__Js?  OO         DD rc^|jtj|dSr()rrweakref WeakMethod)r-callbacks r.register_connect_callbackz$Connection.register_connect_callbackPs* &&w'9('C'CDDDDDr$cg|_dSr()rrns r.clear_connect_callbacksz"Connection.clear_connect_callbacksSs"$r$c2||j|_dS)z Creates a new instance of parser_class with socket size: _socket_read_size and assigns it to the parser for the connection :param parser_class: The required parser class )reN)r_parser)r-rs r.rzConnection.set_parserVs $|T5KLLL r$cjrdS jfdfd}nQ#tj$rt dt $r'}t|d}~wwxYw|_ j  n n##t$r wxYwj D]}|}|r |dS)z5Connects to the Redis server if not already connectedNc,Sr()_connectrnsr.z$Connection.connect..ds r$c.|Sr(r )rr-s r.rz$Connection.connect..dstu7M7Mr$zTimeout connecting to server)rdrcall_with_retryrlryrOSErrorr_error_messagerrrr r)r-rerefrs` r.connectzConnection.connect^sV :  F ::--'''')M)M)M)MDD~ ? ? ?=>> > : : :!$"5"5a"8"899 9 :  &.!!!!''---    OO     *  CsuuH   s!!.'A<"A77A<1B99 Ccd}tj|j|j|jtjD]<}|\}}}}}d} tj|||}|tjtjd|j rk|tj tj d|j D]&\} } |tj| | '||j||||j|cS#t$$r#} | }||Yd} ~ 6d} ~ wwxYw||t%d)zCreate a TCP socket connectionNrRz)socket.getaddrinfo returned an empty list)rl getaddrinforrr SOCK_STREAM setsockopt IPPROTO_TCP TCP_NODELAYr SOL_SOCKET SO_KEEPALIVEritemsrurr"rfrr) r-errresfamilysocktypeproto canonnamesocket_addressrrr_s r.rzConnection._connects % Ity$"2F4F   ! !CBE >FHeYD !}VXu== 2F4FJJJ(BOOF$5v7JANNN $ = C C E EBB1(:AqAAAA ;<<< ^,,, 3444  ! ! !#JJLLL ! ?IABBBsC=E E. E))E.c Vt|jdkrB d|jd|jd|jddS#t$rd|jdcYSwxYw d|jdd |jd|jd |jdd S#t$rd|jdcYSwxYw) NrRzError connecting to :z. r.zConnection Error: Error z connecting to . )rUr~rrAttributeErrorr- exceptions r.rzConnection._error_messages8 y~  ! # # @.di..$).."*....! @ @ @?IN1,=????? @ @EY^A.EEyEE#'9EE09q0AEEE" @ @ @?IN1,=????? @s! ;AA.B B('B(c|j||js|jr|jr|j|jpdf}n|jf}|jdg|Rddi |}nA#t $r4|d|jd|}YnwxYwt|dkrtd|j rP|dd |j t|dkrtd |j rO|d |j t|dkrtd d Sd S)z=Initialize the connection, authenticate and select a databaseAUTH check_healthFr?OKzInvalid Username or PasswordCLIENTSETNAMEzError setting client nameSELECTzInvalid DatabaseN) rrrr send_commandrrrr rrr)r- auth_args auth_responses r.rzConnection.on_connects %%% = JDM J} -!]DM,?R@ !],  D f Ey E E Eu E E E 5 $ 2 2 4 4 7 5 5 5 !!&$-e!LLL $ 2 2 4 4  5M**d22)*HIII   C   h 43C D D DD..0011T99%&ABBB 7 :   h 0 0 0D..0011T99%&8999 : :99sA00;B.-B.cR|j|jdStj|jkr6 |jtjn#t$rYnwxYw |j n#t$rYnwxYwd|_dS)z!Disconnects from the Redis serverN) rrrdrrrshutdownrl SHUT_RDWRrr)r-r~s r.r zConnection.disconnects ""$$$ :  F 9;;$( " "  ##F$45555      J          D  s$$A%% A21A26B BBc|ddt|dkrtddS)z Send PING, expect PONG in returnPINGFr@PONGz#Bad response from PING health checkN)rErrrrns r. _send_pingzConnection._send_pingsQ &u555 **,, - - 7 7!"GHH H 8 7r$c.|dS)z Function to call when PING failsNr)r-rs r. _ping_failedzConnection._ping_faileds r$c|jr>t|jkr)|j|j|jdSdSdS)z3Check the health of the connection with a PING/PONGN)rrrrrrNrPrns r.r?zConnection.check_healthsT  % K$&&43I*I*I J & &t8I J J J J J K K*I*Ir$Tcr|js||r| t|tr|g}|D]}|j|dS#t j$r$|tdt$rq}|t|j dkrd|j d}}n|j d}|j d}td|d|dd}~wt$r|wxYw) z2Send an already packed command to the Redis serverzTimeout writing to socketrRUNKNOWNrr7z while writing to socket. r6N)rdr"r?r1r9sendallrlryr rrrUr~r BaseException)r-commandr?itemr r}errmsgs r.send_packed_commandzConnection.send_packed_commandsiz  LLNNN        '3'' $") ) ) ""4(((( ) )~ < < < OO   :;; ; W W W OO   16{{a )16!9vq !"U5"U"UF"U"U"UVV V    OO     s7A,,;D6'A,D#D6cl||j||dddS)z+Pack and send a command to the Redis serverr?Tr@N)rY pack_commandrW)r-r~rs r.rEzConnection.send_commandsF   D t $6::nd3S3S !     r$c  |j}|s| |j|S#t$r@}|t d|jd|jd|j d}~wwxYw)z8Poll the socket to see if there's data that can be read.Error while reading from r5z: N) rdr"rrrr rrrr~)r-ryrr s r.rzConnection.can_read#sz  LLNNN <((11 1    OO   !MDIMM MMQVMM  s9 B;A>>Bc  |jd|j}n#t$rd}YnwxYw |j|}n#t j$r'|td|t$r3}|td|d|j d}~wt$r|wxYw|j rt|j z|_t!|t"r||S)z0Read the response from a previously sent commandr5rrzTimeout reading from r]z : N)rrr9rrrlryr rrrr~rUrrrr1r)r-rhosterrrXr s r.rzConnection.read_response0sX #00TY00GG # # #"GGG # |11CS1TTHH~ B B B OO   @w@@AA A X X X OO   !"Vg"V"Vaf"V"VWW W    OO       % I%)VVd.H%HD " h . . Ns# ##A>C.B//#Cc fg}t|dtrEt|d|ddz}n)>)@)@(KLL+ t|*D11  CSJD M)) --c:...!~~:s:'='='?'?J d### c""" ~~"J..00      d r$cg}g}d}|j}|D]}|j|D]}t|}||ks||kst|tr1|t |d}g}||kst|tr||||||z }|r-|t ||S)z.Pack multiple commands into the Redis protocolr)rr[rUr1r3rrcr) r-commandsrgr  buffer_lengthricmdchunkchunklens r. pack_commandszConnection.pack_commandsws +  . .C**C0 . .u::!M11-//!%440MM).."8"8999$%MFm++z%/L/L+MM%((((MM%(((!X-MM ."  2 MM)..00 1 1 1 r$T)rrB)r;rCrDrErt DefaultParserr/rrrrrrr"rrrr rNrPr?rYrErrr[rrrFr$r.rrs::  #!% "-D#D#D#D#L999  EEE%%%MMMB'C'C'CR@@@$%:%:%:N$III KKK 6      4+++Zr$rcFeZdZdZ dfd ZfdZxZS) SSLConnectionzManages SSL connections to and from the Redis server(s). This class extends the Connection class, adding SSL functionality, and making use of ssl.SSLContext (https://docs.python.org/3/library/ssl.html#ssl.SSLContext) NrequiredFc  tstdtjdi| ||_||_| t j}nWt|trBt jt j t j d}||vrtd|||}||_ ||_ ||_||_||_||_| |_| |_| |_| |_dS)aeConstructor Args: ssl_keyfile: Path to an ssl private key. Defaults to None. ssl_certfile: Path to an ssl certificate. Defaults to None. ssl_cert_reqs: The string value for the SSLContext.verify_mode (none, optional, required). Defaults to "required". ssl_ca_certs: The path to a file of concatenated CA certificates in PEM format. Defaults to None. ssl_ca_data: Either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded certificates. ssl_check_hostname: If set, match the hostname during the SSL handshake. Defaults to False. ssl_ca_path: The path to a directory containing several CA certificates in PEM format. Defaults to None. ssl_password: Password for unlocking an encrypted private key. Defaults to None. ssl_validate_ocsp: If set, perform a full ocsp validation (i.e not a stapled verification) ssl_validate_ocsp_stapled: If set, perform a validation on a stapled ocsp response ssl_ocsp_context: A fully initialized OpenSSL.SSL.Context object to be used in verifying the ssl_ocsp_expected_cert ssl_ocsp_expected_cert: A PEM armoured string containing the expected certificate to be returned from the ocsp verification service. Raises: RedisError z$Python wasn't built with SSL supportN)noneoptionalrwz+Invalid SSL Certificate Requirements Flag: rF) ssl_availablersuperr/keyfilecertfilessl CERT_NONEr1r9 CERT_OPTIONAL CERT_REQUIRED cert_reqsca_certsca_dataca_pathcheck_hostnamecertificate_passwordssl_validate_ocspssl_validate_ocsp_stapledssl_ocsp_contextssl_ocsp_expected_cert)r- ssl_keyfile ssl_certfile ssl_cert_reqs ssl_ca_certs ssl_ca_datassl_check_hostname ssl_ca_path ssl_passwordrrrrr CERT_REQSr|s r.r/zSSLConnection.__init__sH ECDD D""6"""" $  MMM  s + + 5 --I I-- Q-QQ&m4M&$ " " 0$0!!2)B& 0&<###r$c"t}tj}|j|_|j|_|js|jr'| |j|j|j |j |j |j '||j |j |j |||j}|jdurt$durt'd|jr|jrt'd|jrd dl}d d lm}|jY|j|jj}||j||jn|j}|||j|j |tCj!}|"|#|j|j$f|%|&|S|jdurOt$rHd d lm'}|||j|j$|j } | (r|StSd |S)z Wrap the socket with SSL support)r~r}rN)cafilecapathcadata)server_hostnameTFzcryptography is not installed.zKEither an OCSP staple or pure OCSP connection must be validated - not both.rrR)ocsp_staple_verifier) OCSPVerifierzocsp validation error)*r|rrcreate_default_contextrr verify_moder~r}load_cert_chainrrrrload_verify_locations wrap_socketrrrrrOpenSSLocsprrSSLContext SSLv23_METHODuse_certificate_fileuse_privatekey_fileset_ocsp_client_callbackrrrl request_ocspr"r do_handshakerIris_validr) r-rcontextsslsockrr staple_ctxconror|s r.rzSSLConnection._connectsww!!,..!%!4"n = DL   # # 2 $    M %|'|'  ) )}T\$, *   %%dDI%FF  !T ) ).D.M.M=>> >  ) d.D    )  NNN 2 2 2 2 2 2$,$[001JKK // >>>..t|<<<<!2  / /$d&A    +((V]__EEC       KKDI. / / /       LLNNNN  !T ) ).D ) * * * * * * WdiDMJJAzz|| ?%&=>>>r$) NNrwNNFNNFFNN)r;rCrDrEr/r __classcell__r|s@r.rvrvs  "'#A=A=A=A=A=A=FAAAAAAAAAr$rvcHeZdZdddddddddeedddddfdZd Zd Zd ZdS) UnixDomainSocketConnectionr=rNrrFrctj|_||_||_||_||_||_||_| |_ | turg} | r| t| |_ |j rX|"ttd|_nt#j||_|j| n!ttd|_| |_d|_||_t/||||_d|_| |_|| g|_d|_dS)aB Initialize a new UnixDomainSocketConnection. To specify a retry policy for specific errors, first set `retry_on_error` to a list of the error/s to retry on, then set `retry` to a valid `Retry` object. To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. NrRrr)rrrpathrrrrrfrrtrrrrr rrrrrrrr&rrdrrrr)r-rrrrrfr*r+r,rrrrerrrrs r.r/z#UnixDomainSocketConnection.__init__#sD49;;   &  , 0 X % %N  0  ! !, / / /,   /}"9;;22 "]511 J . .~ > > > >y{{A..DJ%:"!""4x:JKK  !1  %%%"$"r$cpd|jfd|jfg}|jr|d|jf|S)Nrrr)rrrrr s r.rz&UnixDomainSocketConnection.repr_pieces_sC49%dg7   = MM=$*:; < < < r$ctjtjtj}||j||j|S)z&Create a Unix domain socket connection)rlAF_UNIXr%rurfr"r)r-rs r.rz#UnixDomainSocketConnection._connectesF}V^V-?@@ +,,, TY r$ct|jdkrd|jd|jddSd|jdd|jd|jddS)NrRz!Error connecting to unix socket: r8rr6r7z connecting to unix socket: )rUr~rr:s r.rz)UnixDomainSocketConnection._error_messagels y~  ! # #XtyXXINSTDUXXX X5*55955 )q 1555 r$) r;rCrDrtrtr/rrrrFr$r.rr"s  "#:#:#:#:#x      r$r)0FFALSENNOc||dkrdSt|tr|tvrdSt |S)Nr=F)r1r9upper FALSE_STRINGSr4)r<s r.to_boolr{sI } t%%++--="@"@u ;;r$) rrfrrrrmax_connectionsrrct|}i}t|jD]\}}|rt |dkrnt |d}t |}|r8 ||||<[#ttf$rtd|dwxYw|||<|j rt |j |d<|j rt |j |d<|j dkr)|j rt |j |d<t|d<n|j d vr|jrt |j|d <|jrt#|j|d <|j rUd |vrQ t#t |j d d|d <n#t&tf$rYnwxYw|j dkr t(|d<ntd|S)NrzInvalid value for `z` in connection URL.rrunixrconnection_class)redisredissrrr/r=rzRRedis URL must specify one of the following schemes (redis://, rediss://, unix://))r rqueryr+rUr URL_QUERY_ARGUMENT_PARSERSrW TypeError ValueErrorrrschemerrhostnamerr5rr9rv)urlrnamer<parsers r. parse_urlrsB 3--C F **0022 % % e  %SZZ!^^E!H%%E/33D99F %W#)6%==F4LL!:.WWW$%U4%U%U%UVVVW %t  |3$S\22z |3$S\22z zV 8 /$SX..F6N%?!"" * * * < 3$S\22F6N 8 + ]]F6N 8 F** "738#4#4#<# - `rediss://` creates a SSL wrapped TCP socket connection. See more at: - ``unix://``: creates a Unix Domain Socket connection. The username, password, hostname, path and all querystring values are passed through urllib.parse.unquote in order to replace any percent-encoded values with their corresponding characters. There are several ways to specify a database number. The first value found will be used: 1. A ``db`` querystring option, e.g. redis://localhost?db=0 2. If using the redis:// or rediss:// schemes, the path argument of the url, e.g. redis://localhost/0 3. A ``db`` keyword argument to this function. If none of these options are specified, the default db=0 is used. All querystring options are cast to their appropriate Python types. Boolean arguments can be specified with string values "True"/"False" or "Yes"/"No". Values that cannot be properly cast cause a ``ValueError`` to be raised. Once parsed, the querystring arguments and keyword arguments are passed to the ``ConnectionPool``'s class initializer. In the case of conflicting arguments, querystring arguments always win. rrF)rupdate)clsrr url_optionss r.from_urlzConnectionPool.from_urlsPR nn  ' '.45G.HK* + k"""s}}V}}r$Nc |pd}t|tr|dkrtd||_||_||_t j|_| dS)Nlrz,"max_connections" must be a positive integer) r1r5rrconnection_kwargsr threadingLock _fork_lockreset)r-rrrs r.r/zConnectionPool.__init__st*2U/3// M?Q3F3FKLL L 0!2.$.** r$c pt|jdt|jdi|jdS)NrrrF)r:r;r7rrrns r.rzConnectionPool.__repr__sSDzz" I I*T*DDT-CDDEE I I I r$ctj|_d|_g|_t |_tj|_ dSrc) rr_lock_created_connections_available_connectionsset_in_use_connectionsrrrrns r.rzConnectionPool.resets@^%% $%!&(##&55 9;;r$cZ|jtjkr|jd}|st  |jtjkr||jdS#|jwxYwdS)N)ry)rrrracquirerrrelease)r-acquireds r. _checkpidzConnectionPool._checkpid0sF 8ry{{ " "..q.99H +** *8ry{{**JJLLL'')))))'')))) # "s 0B B(c||j5 |j}n$#t$r|}YnwxYw|j|dddn #1swxYwY | | rtdnb#ttf$rN| || rtdYnwxYwn$#t$r||wxYw|S)zGet a connection from the poolNConnection has dataConnection not ready)rrrpop IndexErrormake_connectionraddr"rrrr rUrr- command_namekeysoptionsrs r.get_connectionzConnectionPool.get_connection_s  Z 5 5 4!8<<>>  4 4 4!1133  4  $ ( ( 4 4 4  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5      B&&((A)*?@@@A#W- B B B%%'''""$$$&&((B)*@AAABB B     LL $ $ $    sbB8BABABB BD*##CD*AD&#D*%D&&D**!E c|j}t|dd|dd|ddS)z,Return an encoder based on encoding settingsr*rr+rr,Fr))rr&rW)r-rs r. get_encoderzConnectionPool.get_encodersV'ZZ G44"JJ'8(CC#ZZ(:EBB    r$c|j|jkrtd|xjdz c_|jdi|jS)zCreate a new connectionzToo many connectionsrRrF)rrrrrrns r.rzConnectionPool.make_connectionsR  $(< < <!"899 9 !!Q&!!$t$>>t'=>>>r$c||j5 |j|n#t$rYnwxYw||r|j|n2|xjdzc_|  ddddS ddddS#1swxYwYdS)z(Releases the connection back to the poolrRN) rrrremoveKeyErrorowns_connectionrrrr rs r.rzConnectionPool.releasesI  Z   (// ;;;;     ##J// +22:>>>> ))Q.))%%'''!        ?                  s2B99B9 AB9AAB99B=B=c"|j|jkSr()rrs r.rzConnectionPool.owns_connections~))r$Tc||j5|rt|j|j}n|j}|D]}| ddddS#1swxYwYdS)z Disconnects connections in the pool If ``inuse_connections`` is True, disconnect connections that are current in use, potentially by other threads. Otherwise only disconnect connections that are idle in the pool. N)rrrrrr )r-inuse_connections connectionsrs r.r zConnectionPool.disconnects  Z ( (  :#/1I #9 ) ( ( %%'''' ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (s>A((A,/A,rs)r;rCrDrE classmethodrrr/rrrrrrrrr rFr$r.rrs  ..[.b *4,   "-*-*-*^B   ???****((((((r$rcJeZdZdZddeeffd ZdZdZdZ dZ d Z xZ S) BlockingConnectionPoola Thread-safe blocking connection pool:: >>> from redis.client import Redis >>> client = Redis(connection_pool=BlockingConnectionPool()) It performs the same function as the default :py:class:`~redis.ConnectionPool` implementation, in that, it maintains a pool of reusable connections that can be shared by multiple redis clients (safely across threads if required). The difference is that, in the event that a client tries to get a connection from the pool when all of connections are in use, rather than raising a :py:class:`~redis.ConnectionError` (as the default :py:class:`~redis.ConnectionPool` implementation does), it makes the client wait ("blocks") for a specified number of seconds until a connection becomes available. Use ``max_connections`` to increase / decrease the pool size:: >>> pool = BlockingConnectionPool(max_connections=10) Use ``timeout`` to tell it either how many seconds to wait for a connection to become available, or to block forever: >>> # Block forever. >>> pool = BlockingConnectionPool(timeout=None) >>> # Raise a ``ConnectionError`` after five seconds if a connection is >>> # not available. >>> pool = BlockingConnectionPool(timeout=5) 2c \||_||_tjd||d|dS)N)rrrF) queue_classryr|r/)r-rryrr rr|s r.r/zBlockingConnectionPool.__init__sS'  -+        r$c||j|_ |jdn#t$rYnwxYw-g|_t j|_dSr() r rpool put_nowaitr _connectionsrrrrns r.rzBlockingConnectionPool.resets$$T%9::    $$T****     9;;s= A  A c^|jdi|j}|j||S)zMake a fresh connection.rF)rrrrrs r.rz&BlockingConnectionPool.make_connections:*T*DDT-CDD    ,,,r$c`|d} |jd|j}n#t$rt dwxYw||} | |rt dnb#t tf$rN| ||rt dYnwxYwn$#t$r| |wxYw|S)a7 Get a connection, blocking for ``self.timeout`` until a connection is available from the pool. If the connection returned is ``None`` then creates a new connection. Because we use a last-in first-out queue, the existing connections (having been returned to the pool after the initial ``None`` values were added) will be returned before ``None`` values. This means we only create new connections when we need to, i.e.: the actual number of connections will only increase in response to demand. NT)blockryzNo connection available.rr) rrrWryrrrr"rrr rUrrs r.rz%BlockingConnectionPool.get_connectionsz   >T4<HHJJ > > >""<== = >  --//J      B&&((A)*?@@@A#W- B B B%%'''""$$$&&((B)*@AAABB B     LL $ $ $   s:!:A.D #B'&D 'ADD DD !D+c|||s0||jddS |j|dS#t $rYdSwxYw)z)Releases the connection back to the pool.N)rrr rrrrs r.rzBlockingConnectionPool.releaseBs ##J//   ! ! # # # I  & & & F  I  , , , , ,    DD sA77 BBcj||jD]}|dS)z(Disconnects all connections in the pool.N)rrr rs r.r z!BlockingConnectionPool.disconnectWsC + $ $J  ! ! # # # # $ $r$) r;rCrDrErrr/rrrrr rrs@r.r r sF#       "0 222h*$$$$$$$r$r )]rr}rgrrlrr itertoolsrqueuerrrr urllib.parserr r packaging.versionr redis.backoffr redis.exceptionsr rrrrrrrrrrrrrr redis.retryr redis.utilsrrrrr{ ImportErrorBlockingIOError EWOULDBLOCKr{hasattrr SSLWantWriteErrorSSLErrorrbrrzr __version__hiredis_versionrHIREDIS_SUPPORTS_BYTE_BUFFERrrrdrfrrcrwobjectrtr\r^r_r]r&rHrarrrtrrvrrrr5r6rrrrr rFr$r.r)sb ((((((((((4444444444%%%%%%######"OOOOOOOOOOJJJMMMMM(78I&J#>ws&''>DE+C,@AEF+C,ABB<=+CL9BGGIIJJ (NNNgg122O'6''':J:J'J$#2ggg6F6F#F '6''':J:J'J$" '("'     !? 688SN#W  &&&&&&&&R$'$'$'$'$'$'$'$'NsssssssslPPPPP:PPPf@@@@@J@@@F!!MM M[[[[[[[[| JJJJJJJJJZSSSSSSSSl/  # !  111hv(v(v(v(v(v(v(v(r^$^$^$^$^$^^$^$^$^$^$s<BB  B