ϪfddZddlmZddlmZmZmZddlmZddl m Z ddl m Z m Z ddlmZmZmZddlmZGd d e j(ZGd d eZGd deZeeGdde j0ZeeGdde j0ZGdde j(ZGddeZGddeZGddeZGddeZGddeZ Gdd eZ!eee e!Gd!d"e j0Z"eeGd#d$Z#Gd%d&Z$Gd'd(ejJe$Z&Gd)d*ejJZ'Gd+d,eZ(ee(Gd-d.e j0Z)ee(Gd/d0e j0Z*Gd1d2Z+Gd3d4e j(Z,ee(Gd5d6e j0Z-Gd7d8eZ.Gd9d:eZ/ee.Gd;d<Z0e Gd=d>Z1Gd?d@e$ejJZ2GdAdBe$ejJZ3GdCdDeZ4GdEdFe4Z5ee4GdGdHZ6ee5GdIdJZ7GdKdLeZ8GdMdNZ9GdOdPejJZ:yQ)Rz0 Test cases for Twisted component architecture. )wraps) Attribute Interface implementer)AdapterRegistry) components)cmp comparable)_addHook _removeHookproxyForInterface)unittestceZdZdZdZy)ComporcB|jdz|_|jSNnumselfs E/usr/lib/python3/dist-packages/twisted/python/test/test_components.pyincz Compo.incs88a<xxN)__name__ __module__ __qualname__rrrrrrs CrrceZdZdZy)IAdeptctN)NotImplementedErrorrrr adaptorFunczIAdept.adaptorFuncs !##rN)rrrr$rrrr r s$rr ceZdZdZy)IElapsedcy)z 1! Nrrrr elapsedFunczIElapsed.elapsedFunc#rNrrrr(rrrr&r&"s rr&ceZdZdZdZy)Adeptc ||_d|_yNroriginalrrorigs r__init__zAdept.__init__+s rcv|jdz|_|j|jjfSr)rr0rrs rr$zAdept.adaptorFunc/s-88a<xx**,,,rN)rrrr3r$rrrr,r,)s -rr,ceZdZdZy)Elapsedcyrrrs rr(zElapsed.elapsedFunc6srNr*rrrr6r64srr6c eZdZy)ACompNrrrrrrr9r9:rr9c eZdZy)BCompNr:rrrr=r=>r;rr=c eZdZy)CCompNr:rrrr?r?Br;rr?c eZdZy)ITestNr:rrrrArAFr;rrAc eZdZy)ITest2Nr:rrrrCrCJr;rrCc eZdZy)ITest3Nr:rrrrErENr;rrEc eZdZy)ITest4Nr:rrrrGrGRr;rrGceZdZdZy)Testcyr"rr1s rr3z Test.__init__X rNrrrr3rrrrIrIVs rrIceZdZdZdZy)Test2rcyr"rr1s rr3zTest2.__init__`rKrN)rrrtemporaryAdapterr3rrrrNrN\s  rrNceZdZdZdZy)RegistryUsingMixinzH Mixin for test cases which modify the global registry somehow. ct}|jtd|t|}|j t |y)z Configure L{twisted.python.components.registerAdapter} to mutate an alternate registry to improve test isolation. globalRegistryN)rpatchrr addCleanupr )rscratchRegistryhooks rsetUpzRegistryUsingMixin.setUpis7*+ :/A(  T*rN)rrr__doc__rYrrrrRrRds  +rrRcLeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z y ) ComponentizedTestsz8 Simple test case for caching in Componentized. ctj|tjtt t tjtt ttjtt tyr") rRrYrregisterAdapterrIr9rArErNrCrs rrYzComponentizedTests.setUp~sF  &""46""47""5%8rctjttttjt tt t}|jtjdk(sJ|jtjdk(sJt t |jdk(sJy)N)rr)r`r) rr^r,rr r6r& getComponentr$r(rcs rtestComponentizedz$ComponentizedTests.testComponentizeds""5%8""7E8< G~~f%113v===~~f%113v===q "..0A555rcft}|jt}|jt}|jt}|jt}||usJ||usJ|j ||jt}|jt}||usJ||usJyr")r?rarArCremoveComponent)rrcco1co2co3co4co5co6s rtestInheritanceAdaptationz,ComponentizedTests.testInheritanceAdaptations GnnU#nnU#nnV$nnV$czz#~~ #nnU#nnU#czz#~~rct}|jt}|jt}|jt}|j ||j ||yr")r?rarArErG assertIsNoneassertIs)rrcrgrirjs rtestMultiAdapterz#ComponentizedTests.testMultiAdaptersO GnnU#nnV$nnV$ # c3rc$tj}t}|j|j t |||j|j t |||j|j t dy)z Test that a default value specified to Componentized.getComponent if there is no component for the requested interface. )defaultN)r ComponentizedobjectrprarA)r componentizedrss rtest_getComponentDefaultsz,ComponentizedTests.test_getComponentDefaultssk #002 ( m00@'J m000H'R m007>rctj}|jtt|j t}|j |j||j|ty)z C{Componentized.setAdapter} sets a component for an interface by wrapping the instance with the given adapter class. N) rrt setAdapterr r,ra assertEqualr0assertIsInstancerrv components rtest_setAdapterz"ComponentizedTests.test_setAdaptersX #002   /!..v6  ++]; i/rctj}|jtd|j t }|j |j||j|ty)z C{Componentized.setAdapter} adapts the instance by wrapping it with given adapter class, then stores it using C{addComponent}. T) ignoreClassN) rrt addAdapterr,rar rzr0r{r|s rtest_addAdapterz"ComponentizedTests.test_addAdapters[ #002   D 9!..v6  ++]; i/rctj}t}|jt||j |j t|y)zx C{Componentized.setComponent} stores the given component using the given interface as the key. N)rrtru setComponentrArprarrvobjs rtest_setComponentz$ComponentizedTests.test_setComponentsB #002 h""5#. m007=rctj}t}|jt||j t|j |jty)zm C{Componentized.setComponent} removes the cached component for the given interface. N)rrtrurrAunsetComponentrorars rtest_unsetComponentz&ComponentizedTests.test_unsetComponentsP #002 h""5#.$$U+ -44U; ='rr\ceZdZdZdZy) AdapterTestszTest adapters.ct}t|}|jtjt ||j t |dyr")rur, assertRaisesr CannotAdaptrAro)roas rtestAdapterGetComponentz$AdapterTests.testAdapterGetComponents> H !H *00%; %4.)rN)rrrrZrrrrrrs *rrc eZdZy)IMetaNr:rrrrrr;rrceZdZdZy) MetaAdderc4|jj|zSr"r/rrs raddz MetaAdder.add}}  3&&rNrrrrrrrrr'rrceZdZdZy)BackwardsAdderc4|jj|z Sr"r/rs rrzBackwardsAdder.addrrNrrrrrrrrrceZdZdZdZy) MetaNumberz9 Integer wrapper for Interface adaptation tests. c||_yr"rrs rr3zMetaNumber.__init__s rN)rrrrZr3rrrrrs rrceZdZdZy)ComponentNumbercPd|_tjj|yr.)rrrtr3rs rr3zComponentNumber.__init__ s  ))$/rNrLrrrrrs0rrceZdZdZdZdZy)ComponentAdderz0 Adder for componentized adapter tests. cztjj|||jj|_yr")rAdapterr3r0rrr0s rr3zComponentAdder.__init__s)##D(3==$$rcD|xj|z c_|jSr"rrs rrzComponentAdder.adds CxxrN)rrrrZr3rrrrrrs%rrceZdZdZdZy)IAttrXz= Base interface for test of adapter with C{__cmp__}. cy)z! Return a value. NrrrrxzIAttrX.x"r)rNrrrrZrrrrrr  rrceZdZdZdZy)IAttrXXz@ Adapted interface for test of adapter with C{__cmp__}. cy)z+ Return a tuple of values. Nrrrrxxz IAttrXX.xx-r)rN)rrrrZrrrrrr(rrrceZdZdZdZy)XcellentzG L{IAttrX} implementation for test of adapter with C{__cmp__}. cy)z; Return a value. @return: a value x!rrs rrz Xcellent.x9s rNrrrrrr3s rrc&eZdZdZdZdZdZdZy)DoubleXAdapterz Adapter with __cmp__. *c||_yr")r0rs rr3zDoubleXAdapter.__init__Js   rcj|jj|jjfSr")r0rrs rrzDoubleXAdapter.xxMs# !4==??#455rcBt|j|jSr")r r)rothers r__cmp__zDoubleXAdapter.__cmp__Ps488UYY''rN)rrrrZrr3rrrrrrrBs C!6(rrceZdZdZdZdZy)MetaInterfaceTestsctjttttd}|j t |j ddy)zS Registered adapters can be used to adapt classes to an interface. rr`N)rr^rrrrzr)rns r test_basiczMetaInterfaceTests.test_basicUs; ""9j%@ qM qa!,rctjtttt}t |j dt |j d|j t |j ddy)Nr)rr^rrrrrzrbs rtestComponentizedInteractionz/MetaInterfaceTests.testComponentizedInteraction]sV"">?EJ   a Q a Q qa!,rctjtttt t }|j d|jy)N)rr)rr^rrrrrzr)rrs rtestAdapterWithCmpz%MetaInterfaceTests.testAdapterWithCmpds6"">67C XZ  ruuw/rN)rrrrrrrrrrrTs--0rrcjeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZy)RegistrationTestsz) Tests for adapter registration. cd}tj||t|jtj|td|y)z Register an adapter with L{components.registerAdapter} for the given class or interface and verify that the adapter can be looked up with L{components.getAdapterFactory}. cyr"rrs rzGRegistrationTests._registerAdapterForClassOrInterface..vr)rNrr^rArpgetAdapterFactoryrr0adapters r#_registerAdapterForClassOrInterfacez5RegistrationTests._registerAdapterForClassOrInterfaceps8 !""7He< j228UDI7Src8Gdd}|j|S)za Test that an adapter from a class can be registered and then looked up. c eZdZy)CRegistrationTests.test_registerAdapterForClass..TheOriginalNr:rrr TheOriginalr rr)rrrs rtest_registerAdapterForClassz.RegistrationTests.test_registerAdapterForClasszs   77 DDrc,|jtS)zf Test that an adapter from an interface can be registered and then looked up. )rrCrs r test_registerAdapterForInterfacez2RegistrationTests.test_registerAdapterForInterfaces 77??rcd}d}tj||t|jttj||t|j tj |td|y)z Verify that L{components.registerAdapter} raises L{ValueError} if the from-type/interface and to-interface pair is not unique. cyNFrrs rrzHRegistrationTests._duplicateAdapterForClassOrInterface..r)rcyNTrrs rrzHRegistrationTests._duplicateAdapterForClassOrInterface..r)rN)rr^rAr ValueErrorrpr)rr0 firstAdapter secondAdapters r$_duplicateAdapterForClassOrInterfacez6RegistrationTests._duplicateAdapterForClassOrInterfaces^ ' & ""<5A   22M8U  j228UDI<Xrc8Gdd}|j|S)zz Test that attempting to register a second adapter from a class raises the appropriate exception. c eZdZy)DRegistrationTests.test_duplicateAdapterForClass..TheOriginalNr:rrrrrrrr)rrs rtest_duplicateAdapterForClassz/RegistrationTests.test_duplicateAdapterForClasss   88EErc,|jtS)z Test that attempting to register a second adapter from an interface raises the appropriate exception. )rrCrs r!test_duplicateAdapterForInterfacez3RegistrationTests.test_duplicateAdapterForInterfaces 88@@rcd}d}Gddt}tj|||dt_ tj||||j tj ||d|dt_|j ttj||||j tj ||d|y#dt_wxYw)z Verify that when C{components.ALLOW_DUPLICATES} is set to C{True}, new adapter registrations for a particular from-type/interface and to-interface pair replace older registrations. cyrrrs rrzORegistrationTests._duplicateAdapterForClassOrInterfaceAllowed..r)rcyrrrs rrzORegistrationTests._duplicateAdapterForClassOrInterfaceAllowed..r)rc eZdZy)SRegistrationTests._duplicateAdapterForClassOrInterfaceAllowed..TheInterfaceNr:rrr TheInterfacerrrrTNF)rrr^ALLOW_DUPLICATESrprrr)rr0rrrs r+_duplicateAdapterForClassOrInterfaceAllowedz=RegistrationTests._duplicateAdapterForClassOrInterfaceAlloweds ' &  9  ""<<H&* # 0  & &}h M MM,,X|TJ  +0J '   22L(L   ( (< F  +0J 's >C Cc8Gdd}|j|S)z Test that when L{components.ALLOW_DUPLICATES} is set to a true value, duplicate registrations from classes are allowed to override the original registration. c eZdZy)KRegistrationTests.test_duplicateAdapterForClassAllowed..TheOriginalNr:rrrrrrrr)rrs r$test_duplicateAdapterForClassAllowedz6RegistrationTests.test_duplicateAdapterForClassAlloweds  ?? LLrcBGddt}|j|S)z Test that when L{components.ALLOW_DUPLICATES} is set to a true value, duplicate registrations from interfaces are allowed to override the original registration. c eZdZy)ORegistrationTests.test_duplicateAdapterForInterfaceAllowed..TheOriginalNr:rrrrrrrr)rrrs r(test_duplicateAdapterForInterfaceAllowedz:RegistrationTests.test_duplicateAdapterForInterfaceAlloweds! ) ?? LLrcd}tj||tt|j tj |td||j tj |td|y)zh Verify that an adapter can be registered for multiple to-interfaces at a time. cyr"rrs rrzJRegistrationTests._multipleInterfacesForClassOrInterface..r)rN)rr^rArCrprrs r&_multipleInterfacesForClassOrInterfacez8RegistrationTests._multipleInterfacesForClassOrInterfacesW !""7HeVD j228UDI7S j228VTJGTrc8Gdd}|j|S)zi Test the registration of an adapter from a class to several interfaces at once. c eZdZy)FRegistrationTests.test_multipleInterfacesForClass..TheOriginalNr:rrrrr rrr)r rs rtest_multipleInterfacesForClassz1RegistrationTests.test_multipleInterfacesForClasss   ::;GGrc,|jtS)zn Test the registration of an adapter from an interface to several interfaces at once. )r rErs r#test_multipleInterfacesForInterfacez5RegistrationTests.test_multipleInterfacesForInterfaces ::6BBrc>d}d}Gdd|}tj||ttj||t|jtj|td||jtj|td|y)a  Verify that a new adapter can be registered for a particular to-interface from a subclass of a type or interface which already has an adapter registered to that interface and that the subclass adapter takes precedence over the base class adapter. cyrrrs rrzSRegistrationTests._subclassAdapterRegistrationForClassOrInterface..r)rcyrrrs rrzSRegistrationTests._subclassAdapterRegistrationForClassOrInterface..r)rc eZdZy)VRegistrationTests._subclassAdapterRegistrationForClassOrInterface..TheSubclassNr:rrr TheSubclassr rrrNr)rr0rrrs r/_subclassAdapterRegistrationForClassOrInterfacezARegistrationTests._subclassAdapterRegistrationForClassOrInterfaces}& '  (  ""<5A""=+uE j228UDI<X  ( (eT BM rc8Gdd}|j|S)z~ Test that an adapter to a particular interface can be registered from both a class and its subclass. c eZdZy)ORegistrationTests.test_subclassAdapterRegistrationForClass..TheOriginalNr:rrrrrrrr)rrs r(test_subclassAdapterRegistrationForClassz:RegistrationTests.test_subclassAdapterRegistrationForClasss   CCKPPrc,|jtS)z Test that an adapter to a particular interface can be registered from both an interface and its subclass. )rrCrs r,test_subclassAdapterRegistrationForInterfacez>RegistrationTests.test_subclassAdapterRegistrationForInterfaces CCFKKrN)rrrrZrrrrrrrrrr r rrrrrrrrrks`T E@ Y FA @ M MU HC ( QLrrc&eZdZdZedZdZy)IProxiedInterfacez= An interface class for use by L{proxyForInterface}. z@ An example declared attribute, which should be proxied.cy)z: A sample method which should be proxied. Nr)rkws ryayzIProxiedInterface.yay1r)rN)rrrrZrifaceAttributer!rrrrr's CN  rrceZdZdZdZy)IProxiedSubInterfacezS An interface that derives from another for use with L{proxyForInterface}. cy)zD A different sample method which should be proxied. NrrrrboozIProxiedSubInterface.boo<r)rNrrrrZr&rrrr$r$7rrr$ceZdZdZdZdZy)Yayablez A provider of L{IProxiedInterface} which increments a counter for every call to C{yay}. @ivar yays: The number of times C{yay} has been called. c d|_g|_yr.)yaysyayArgsrs rr3zYayable.__init__Ms  rc~|xjdz c_|jj||f|jS)z) Increment C{self.yays}. r)r+r,appendrrr s rr!z Yayable.yayQs1 Q  QG$yyrN)rrrrZr3r!rrrr)r)Bsrr)c$eZdZdZdZdZdZdZy)Booablez3 An implementation of IProxiedSubInterface Fcd|_y)z; Mark the fact that 'yay' has been called. TN)yayedr/s rr!z Booable.yaye  rcd|_y)z< Mark the fact that 'boo' has been called.1 TN)booedrs rr&z Booable.bookr4rN)rrrrZr3r6r!r&rrrr1r1Zs E E rr1ceZdZdZdZdZy)IMultipleMethodsz- An interface with multiple methods. cy)z4 The first method. Should return 1. Nrrrr methodOnezIMultipleMethods.methodOnewr)rcy)z5 The second method. Should return 2. Nrrrr methodTwozIMultipleMethods.methodTwo|r)rNrrrrZr:r<rrrr8r8rs  rr8ceZdZdZdZdZy)MultipleMethodImplementorz: A precise implementation of L{IMultipleMethods}. cy)z @return: 1 rrrs rr:z#MultipleMethodImplementor.methodOnercy)z @return: 2 r`rrs rr<z#MultipleMethodImplementor.methodTworArNr=rrrr?r?s rr?cdeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZy)ProxyForInterfaceTestsz) Tests for L{proxyForInterface}. czt}tt|}|j|j|y)z Proxy objects should have an C{original} attribute which refers to the original object passed to the constructor. N)rur rrpr0)rr0proxys r test_originalz$ProxyForInterfaceTests.test_originals0 84!"34X> ennh/rctt}t}||}|j|j |jd|j |j dy)z The class created from L{proxyForInterface} passes methods on an interface to the object which is passed to its constructor. r`Nr rr)r!rzr+)rklassyayablerFs rtest_proxyMethodz'ProxyForInterfaceTests.test_proxyMethodsR ""34)g  a( q)rcttGfdd}t}||}|j|j d|j y)z Methods of the class created from L{proxyForInterface} can be used with the decorator-helper L{functools.wraps}. cDeZdZeWjfdZy)?ProxyForInterfaceTests.test_decoratedProxyMethod..klasscd|jxjdz c_j|Sr)r0r+r!)rbases rr!zCProxyForInterfaceTests.test_decoratedProxyMethod..klass.yays& ""a'"xx~%rN)rrrrr!)rQsrrJrOs 488_ & &rrJr`NrI)rrJr0rKrQs @rtest_decoratedProxyMethodz0ProxyForInterfaceTests.test_decoratedProxyMethodsK !!23 &D & 9/  HMM*rct}t|_tt||j j|j|j tfdy)zc Proxy objects should proxy declared attributes, but not other attributes. cjSr")r+)rFsrrz.s %**rN)r)rur"r rrprAttributeErrorrrKrFs @rtest_proxyAttributez*ProxyForInterfaceTests.test_proxyAttributesT )!'4!"34W= e**G,B,BC .*<=rct}tt|}t}||_|j |j|y)zv The attributes that proxy objects proxy should be assignable and affect the original object. N)r)r rrur"rprrKrFthingys rtest_proxySetAttributez-ProxyForInterfaceTests.test_proxySetAttributesA )4!"34W=% g,,f5rct}d|_tt|}|`|j t |dy)zu The attributes that proxy objects proxy should be deletable and affect the original object. Nr")r)r"r r assertFalsehasattrrVs rtest_proxyDeleteAttributez0ProxyForInterfaceTests.test_proxyDeleteAttributesB )!%4!"34W=   *:;.SpecializedProxyzU A specialized proxy which can decrement the number of yays. cB|jxjdzc_y)z? Decrement the number of yays. rN)r0r+rs rr&zEProxyForInterfaceTests.test_subclassing..SpecializedProxy.boos ""a'"rNr'rrrSpecializedProxyres   (rrgrN)r rr)rzr+r&)rrgrKspecials rtest_subclassingz'ProxyForInterfaceTests.test_subclassingsY (01BC ()"7+ q)  r*rcZtt}|j|jdy)zQ The name of a proxy class indicates which interface it proxies. zA(Proxy for twisted.python.test.test_components.IProxiedInterface)N)r rrzrrrFs rtest_proxyNamez%ProxyForInterfaceTests.test_proxyNames'""34  NN R rcjtt}|jtj|y)zO The resulting proxy implements the interface that it proxies. N)r r assertTrue implementedByrls rtest_implementsz&ProxyForInterfaceTests.test_implements s'""34 )77>?rc,Gdd}|}|}||_tjdd}|j|j ||j |j d}|||j |jy)a\ _ProxyDescriptor's __get__ method should return the appropriate attribute of its argument's 'original' attribute if it is invoked with an object. If it is invoked with None, it should return a false class-method emulator instead. For some reason, Python's documentation recommends to define descriptors' __get__ methods with the 'type' parameter as optional, despite the fact that Python itself never actually calls the descriptor that way. This is probably do to support 'foo.__get__(bar)' as an idiom. Let's make sure that the behavior is correct. Since we don't actually use the 'type' argument at all, this test calls it the idiomatic way to ensure that signature works; test_proxyInheritance verifies the how-Python-actually-calls-it signature. ceZdZdZdZy)>ProxyForInterfaceTests.test_proxyDescriptorGet..SampleFcd|_yr)calledrs rrzDProxyForInterfaceTests.test_proxyDescriptorGet..Sample.hello&s " rN)rrrrvrrrrSamplert#s F #rrwrr0N)r0r_ProxyDescriptorrz__get__rrorv)rrw fakeProxy testObjectpdfakeClassMethods rtest_proxyDescriptorGetz.ProxyForInterfaceTests.test_proxyDescriptorGets}" # # H X '   ( (* = I. 0@0@A**T* "  ))*rcGddttGfdd}t}||}|j|j dddd d |j|j d t dd fgy ) z Subclasses of the class returned from L{proxyForInterface} should be able to upcall methods by reference to their superclass, as any normal Python class can. ceZdZdZy)DProxyForInterfaceTests.test_proxyInheritance..YayableWrapperzI This class does not override any functionality. N)rrrrZrrrYayableWrapperr9s rrc eZdZdZdZfdZy)EProxyForInterfaceTests.test_proxyInheritance..EnhancedWrapperz@ This class overrides the 'yay' method. rc`|xjdz c_j|g|i|dzS)Nr) wrappedYaysr!)rrkrs rr!zIProxyForInterfaceTests.test_proxyInheritance..EnhancedWrapper.yayEs6  A% )~))$88a81<s K =rrr)ry)rrN)r rr)rzr!r,dict)rrrKwrapperrs @rtest_proxyInheritancez,ProxyForInterfaceTests.test_proxyInheritance2sx ./@A  =n =)!'* QQ!4a8 FD1N+C*DErctt}t}||}|j|j |j |j |j |jy)z Proxies of subinterfaces generated with proxyForInterface should allow access to attributes of both the child and the base interfaces. N)r r$r1r!r&ror3r6)r proxyClassbooablerFs rtest_interfaceInheritancez0ProxyForInterfaceTests.test_interfaceInheritanceNsR '';< )7#    &  &rct}t|_ttd|}|j |j ||j|jd|j |j|jt}||_|j |j||`|jt|dy)a The original attribute name can be customized via the C{originalAttribute} argument of L{proxyForInterface}: the attribute should change, but the methods of the original object should still be callable, and the attributes still accessible. foo)originalAttributerr"N) r)rur"r rrprrzr!r]r^rYs rtest_attributeCustomizationz2ProxyForInterfaceTests.test_attributeCustomization[s)!'M!"3uMgV eii) a( e**G,B,BC% g,,f5   *:; 6 =/+, @+@F8 '=rrDN);rZ functoolsrzope.interfacerrrzope.interface.adapterrtwisted.pythonrtwisted.python.compatr r twisted.python.componentsr r r twisted.trialrrtrr r&rr,r6r9r=r?rArCrErGrIrNrRSynchronousTestCaser\rrrrrrrrrrrrrrr$r)r1r8r?rDrrrrs   <<2%1NN"J $ $$Y$  y  V-J  -- Xj    J $ $  E  E  I  Y  Y  Y  UFF# :   $  V   ++*i'557Ii'X*8//* I  U' ""''  U'Z'''' 0j..0  U Z''   Y  i  V    (( ("0+X-I-I0.yL*H,H,HyLx    ,   . !"#.  y  $Z=X99Z=r