+
    Qi3V                     j   ^ RI t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHtHt R t	 ! R R]4      t
]! ]	! 4       '       * R4       ! R R]
4      4       t]! ]	! 4       '       * R4       ! R	 R
]
4      4       t]! ]	! 4       '       * R4       ! R R]4      4       t]! ]	! 4       '       * R4       ! R R]
4      4       tR# )    N)skipIfTestCasec                  B     \        R 4       R#   \         d     R# i ; i)twistedTF)
__import__ImportError     =/usr/lib/python3/dist-packages/automat/_test/test_discover.pyisTwistedInstalledr   
   s(    9   s    c                   f   a a ] tR t^t oRtV 3R ltV 3R ltR tR tR t	R t
R tR	 tR
tVtV ;t# )_WritesPythonModulesz?
A helper that enables generating Python module test fixtures.
c                f  < \         \        V `  4        ^ RIHpHp ^ RIHp Wn        W n        W0n        \        \        P                  P                  4       4      V n        \        P                  R,          V n        \        P                   ! 4       V n        V P%                  V P"                  4       R# )r   )	getModule
PythonPath)FilePathNNNN)superr   setUptwisted.python.modulesr   r   twisted.python.filepathr   setsysmoduleskeysoriginalSysModulespathsavedSysPathtempfilemkdtemppathDirmakeImportable)selfr   r   r   	__class__s   &   r   r   _WritesPythonModules.setUp   sr    "D/1@4"$ "%ckk&6&6&8"9HHQK'')DLL)r
   c                8  < \         \        V `  4        V P                  \        P
                  R &   \        P                  P                  4       V P                  ,
          pV F  p\        P                  V K  	  \        P                  ! V P                  4       R# )r   N)r   r   tearDownr   r   r   r   r   r   shutilrmtreer!   )r#   modulesToDeletemoduler$   s   &  r   r'   _WritesPythonModules.tearDown(   si    "D24''++**,t/F/FF%FF# & 	dll#r
   c                D    \         P                  P                  V4       R # N)r   r   append)r#   r   s   &&r   r"   #_WritesPythonModules.makeImportable2   s    r
   c                <   V P                  V4      pVP                  V4      p\        VP                  R 4      ;_uu_ 4       pVP	                  \
        P                  ! V4      4       RRR4       V P                  VP                  .4      #   + '       g   i     L,; i)wN)r   childopenr   writetextwrapdedentr   )r#   sourcer   
moduleName	directoryr+   fs   &&&&   r   writeSourceInto$_WritesPythonModules.writeSourceInto5   sn    MM$'	, &++s##qGGHOOF+, $ 	/00 $#s   &BB	c                v    \         P                  P                  V4      w  rEV P                  WV4      V,          # r.   )osr   splitextr<   )r#   r8   r   r9   pythonModuleName_s   &&&&  r   
makeModule_WritesPythonModules.makeModule@   s3     gg..z:##F*=>NOOr
   c                `    VP                  4        Uu/ uF  q"P                  VbK  	  up# u upi r.   )iterAttributesname)r#   hasIterAttributesattrs   && r   attributesAsDict%_WritesPythonModules.attributesAsDictD   s+    ,=,L,L,NO,ND		4,NOOOs   +c                D    VP                  4        V P                  V4      # r.   )loadrJ   )r#   r+   s   &&r   loadModuleAsDict%_WritesPythonModules.loadModuleAsDictG   s    $$V,,r
   c                D    V P                  V P                  WV4      4      # r.   )rN   rC   )r#   r8   r   rG   s   &&&&r   makeModuleAsDict%_WritesPythonModules.makeModuleAsDictK   s    $$T__V4%HIIr
   )r   r   r   r   r!   r   )__name__
__module____qualname____firstlineno____doc__r   r'   r"   r<   rC   rJ   rN   rQ   __static_attributes____classdictcell____classcell__r$   __classdict__s   @@r   r   r      s;     * $	1PP-J Jr
   r   zTwisted is not installed.c                   H   a a ] tR t^Ot oRtV 3R ltR tR tR tRt	Vt
V ;t# )OriginalLocationTestsax  
Tests that L{isOriginalLocation} detects when a
L{PythonAttribute}'s FQPN refers to an object inside the module
where it was defined.

For example: A L{twisted.python.modules.PythonAttribute} with a
name of 'foo.bar' that refers to a 'bar' object defined in module
'baz' does *not* refer to bar's original location, while a
L{PythonAttribute} with a name of 'baz.bar' does.

c                D   < \         \        V `  4        ^RIHp Wn        R# )   isOriginalLocationN)r   r^   r   	_discoverrb   )r#   rb   r$   s   & r   r   OriginalLocationTests.setUp]   s    #T022"4r
   c                    RpV P                  WP                  R4      pV P                  V P                  VR,          4      4       R# )zv
L{isOriginalLocation} returns False when the attribute refers to an
object whose source module cannot be determined.
z~        class Fake(object):
            pass
        hasEmptyModule = Fake()
        hasEmptyModule.__module__ = None
        zempty_module_attr.pyz empty_module_attr.hasEmptyModuleN)rQ   r!   assertFalserb   )r#   r8   
moduleDicts   &  r   test_failsWithNoModule,OriginalLocationTests.test_failsWithNoModulec   sD    
 **6<<AWX
##J/Q$RS	
r
   c                   RpRpV P                  WP                  R4       V P                  W P                  R4      pV P                  V P	                  VR,          4      4       V P                  V P	                  VR,          4      4       VR,          pV P                  V4      pVR,          pV P                  V P	                  V4      4       R	# )
z
L{isOriginalLocation} returns False when the attribute refers to
an object outside of the module where that object was defined.
z        class ImportThisClass(object):
            pass
        importThisObject = ImportThisClass()
        importThisNestingObject = ImportThisClass()
        importThisNestingObject.nestedObject = ImportThisClass()
        z        from original import (ImportThisClass,
                              importThisObject,
                              importThisNestingObject)
        original.pyimporting.pyzimporting.ImportThisClasszimporting.importThisObjectz!importing.importThisNestingObjectz.importing.importThisNestingObject.nestedObjectN)rC   r!   rQ   rf   rb   rJ   )r#   originalSourceimportingSourceimportingDictnestingObjectnestingObjectDictnestedObjects   &      r   test_failsWithDifferentModule3OriginalLocationTests.test_failsWithDifferentModuleu   s    
 	mD--\\>
 	##M2M$NO	
 	##M2N$OP	
 &&IJ 11-@(<
 	00>?r
   c                   \         P                  ! R4      pV P                  WP                  R4      pV P	                  V P                  VR,          4      4       V P	                  V P                  VR,          4      4       VR,          pV P                  V4      pVR,          pV P	                  V P                  V4      4       R# )z|
L{isOriginalLocation} returns True when the attribute refers to an
object inside the module where that object was defined.
z
        class ThisClassWasDefinedHere(object):
            pass
        anObject = ThisClassWasDefinedHere()
        aNestingObject = ThisClassWasDefinedHere()
        aNestingObject.nestedObject = ThisClassWasDefinedHere()
        zm.pyzm.ThisClassWasDefinedHerezm.aNestingObjectzm.aNestingObject.nestedObjectN)r6   r7   rQ   r!   
assertTruerb   rJ   )r#   mSourcemDictrp   rq   rr   s   &     r   test_succeedsWithSameModule1OriginalLocationTests.test_succeedsWithSameModule   s    
 //
 %%g||VD//6Q0RST//6H0IJK01 11-@()HI//=>r
   ra   )rS   rT   rU   rV   rW   r   rh   rs   ry   rX   rY   rZ   r[   s   @@r   r^   r^   O   s%     
5
$$@L? ?r
   r^   c                   ~   a a ] tR t^t oRtV 3R ltR tV3R lR ltR tR t	R t
R	 tR
 tR tR tR tRtVtV ;t# )FindMachinesViaWrapperTestsz
L{findMachinesViaWrapper} recursively yields FQPN,
L{MethodicalMachine} pairs in and under a given
L{twisted.python.modules.PythonModule} or
L{twisted.python.modules.PythonAttribute}.
c                D   < \         \        V `  4        ^RIHp Wn        R# )r`   findMachinesViaWrapperN)r   r|   r   rc   r   )r#   r   r$   s   & r   r   !FindMachinesViaWrapperTests.setUp   s    )4686&<#r
   c                    RpV P                  WP                  R4      pVR,          pV P                  RVP                  4       3\	        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonAttribute} that refers
directly to a L{MethodicalMachine}, L{findMachinesViaWrapper}
yields that machine and its FQPN.
a        from automat import MethodicalMachine

        rootMachine = MethodicalMachine()
        root.pyroot.rootMachineNrQ   r!   assertInrM   listr   r#   r8   rg   rootMachines   &   r   test_yieldsMachine.FindMachinesViaWrapperTests.test_yieldsMachine   s\     **6<<K
 !34!1!1!34,,[9:	
r
   c                   < V ^8  d   QhRR/# )r`   returnNr	   )formatr\   s   "r   __annotate__(FindMachinesViaWrapperTests.__annotate__   s     
 
 
r
   c                    RpV P                  WP                  R4      pVR,          pV P                  RVP                  4       3\	        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonAttribute} that refers
directly to a L{TypeMachine}, L{findMachinesViaWrapper} yields that
machine and its FQPN.
ae          from automat import TypeMachineBuilder
        from typing import Protocol, Callable
        class P(Protocol):
            def method(self) -> None: ...
        class C:...
        def buildBuilder() -> Callable[[C], P]:
            builder = TypeMachineBuilder(P, C)
            return builder.build()
        rootMachine = buildBuilder()
        r   r   Nr   r   s   &   r   test_yieldsTypeMachine2FindMachinesViaWrapperTests.test_yieldsTypeMachine   s\    
 **6<<K
 !34!1!1!34,,[9:	
r
   c                    RpV P                  WP                  R4      pVR,          pV P                  RVP                  4       P                  3\        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonAttribute} that refers
to a class that contains a L{MethodicalMachine} as a class
variable, L{findMachinesViaWrapper} yields that machine and
its FQPN.
        from automat import MethodicalMachine

        class PythonClass(object):
            _classMachine = MethodicalMachine()
        	clsmod.pyclsmod.PythonClass clsmod.PythonClass._classMachineN)rQ   r!   r   rM   _classMachiner   r   r#   r8   rg   PythonClasss   &   r   test_yieldsMachineInClass5FindMachinesViaWrapperTests.test_yieldsMachineInClass   sb     **6<<M
 !56/1A1A1C1Q1QR,,[9:	
r
   c                    RpV P                  WP                  R4      pVR,          pV P                  RVP                  4       P                  P
                  3\        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonAttribute} that refers
to a nested class that contains a L{MethodicalMachine} as a
class variable, L{findMachinesViaWrapper} yields that machine
and its FQPN.
        from automat import MethodicalMachine

        class PythonClass(object):
            class NestedClass(object):
                _classMachine = MethodicalMachine()
        nestedcls.pynestedcls.PythonClass/nestedcls.PythonClass.NestedClass._classMachineN)rQ   r!   r   rM   NestedClassr   r   r   r   s   &   r   test_yieldsMachineInNestedClass;FindMachinesViaWrapperTests.test_yieldsMachineInNestedClass  sm     **6<<P
 !89A  "..<< ,,[9:	
r
   c                    RpV P                  WP                  R4      pV P                  V4      R,          P                  4       pV P	                  RV3\        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonModule} that refers to
a module that contains a L{MethodicalMachine},
L{findMachinesViaWrapper} yields that machine and its FQPN.
r   r   r   N)rC   r!   rN   rM   r   r   r   )r#   r8   r+   r   s   &   r   test_yieldsMachineInModule6FindMachinesViaWrapperTests.test_yieldsMachineInModule  se    
 yA++F34FGLLN-tD4O4OPV4W/X	
r
   c                    RpV P                  WP                  R4      pV P                  V4      R,          P                  4       pV P	                  RVP
                  3\        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonModule} that refers to
the original module of a class containing a
L{MethodicalMachine}, L{findMachinesViaWrapper} yields that
machine and its FQPN.
r   r   r   r   N)rC   r!   rN   rM   r   r   r   r   r#   r8   r+   r   s   &   r   !test_yieldsMachineInClassInModule=FindMachinesViaWrapperTests.test_yieldsMachineInClassInModule-  sk     {C++F34HINNP/1J1JK,,V45	
r
   c                   RpV P                  WP                  R4      pV P                  V4      R,          P                  4       pV P	                  RVP
                  P                  3\        V P                  V4      4      4       R# )z
When given a L{twisted.python.modules.PythonModule} that refers to
the original module of a nested class containing a
L{MethodicalMachine}, L{findMachinesViaWrapper} yields that
machine and its FQPN.
r   r   r   r   N)	rC   r!   rN   rM   r   r   r   r   r   r   s   &   r   'test_yieldsMachineInNestedClassInModuleCFindMachinesViaWrapperTests.test_yieldsMachineInNestedClassInModuleA  sv     ~F++F34KLQQSA''55 ,,V45	
r
   c                    RpRpV P                  WP                  R4       V P                  W P                  R4      pV P                  \        V P	                  V4      4      4       R# )a  
When given a L{twisted.python.modules.PythonAttribute} that refers
to a class imported from another module, any
L{MethodicalMachine}s on that class are ignored.

This behavior ensures that a machine is only discovered on a
class when visiting the module where that class was defined.
z
        from automat import MethodicalMachine

        class PythonClass(object):
            _classMachine = MethodicalMachine()
        z2
        from original import PythonClass
        rk   rl   NrC   r!   rf   r   r   )r#   rm   rn   importingModules   &   r   test_ignoresImportedClass5FindMachinesViaWrapperTests.test_ignoresImportedClassZ  sV     	mD///<<Xd99/JKLr
   c                   V P                  V P                  .4      pV P                  V P                  4      P                  R4      pVP	                  4        VP                  R4      P                  4        RpV P                  W2P                  R4       VR,          p\        V P                  V4      \        P                  ! ^ 4      R7      pV P                  VR,          4      pVR,          P                  4       pVR,          P                  4       p\        RV3R	VP                  3.\        P                  ! ^ 4      R7      p	V P                  W4       R
# )zH
L{findMachinesViaWrapper} descends into packages to discover
machines.
test_package__init__.pyz
        from automat import MethodicalMachine


        class PythonClass(object):
            _classMachine = MethodicalMachine()


        rootMachine = MethodicalMachine()
        	module.pykeyr+   ztest_package.module.rootMachineztest_package.module.PythonClassz-test_package.module.PythonClass._classMachineN)r   r!   r   r3   makedirstouchrC   r   sortedr   operator
itemgetterrN   rM   r   assertEqual)
r#   
pythonPathpackager8   r   machinesrg   r   r   expectedMachiness
   &         r   test_descendsIntoPackages5FindMachinesViaWrapperTests.test_descendsIntoPackagess  s)   
 __dll^4
---33NCm$**,	 	k:!.1''58;N;Nq;Q
 **<+AB
 !BCHHJ !BCHHJ!2K@C-- ##A&	
 	)4r
   c                    RpV P                  WP                  R4      pV P                  \        V P	                  V4      4      4       R# )zi
L{findMachinesViaWrapper} ignores infinite loops.

Note this test can't fail - it can only run forever!
zh
        class InfiniteLoop(object):
            pass

        InfiniteLoop.loop = InfiniteLoop
        zloop.pyNr   )r#   r8   r+   s   &  r   test_infiniteLoop-FindMachinesViaWrapperTests.test_infiniteLoop  s=     yAd99&ABCr
   r~   )rS   rT   rU   rV   rW   r   r   r   r   r   r   r   r   r   r   r   rX   rY   rZ   r[   s   @@r   r|   r|      sO     =
&
 
2
(
2
"
(
2M2*5XD Dr
   r|   c                   r   a  ] tR tRt o RtR tR tR tR tR t	R t
R	 tR
 tR tR tR tR tR tRtV tR# )WrapFQPNTestsi  z
Tests that ensure L{wrapFQPN} loads the
L{twisted.python.modules.PythonModule} or
L{twisted.python.modules.PythonAttribute} for a given FQPN.
c                v    ^ RI HpHp ^RIHpHpHpHp Wn        W n        W0n        W@n        WPn        W`n        R# )r   )PythonModulePythonAttribute)wrapFQPNInvalidFQPNNoModuleNoObjectN)r   r   r   rc   r   r   r   r   )r#   r   r   r   r   r   r   s   &      r   r   WrapFQPNTests.setUp  s,    HII(. &  r
   c                    V P                  WP                  4       V P                  VP                  VP                  4       V P                  VP                  4       V4       R# )z\
Assert that a L{twisted.python.modules.PythonModule} refers to a
particular Python module.
N)assertIsInstancer   r   rG   rS   assertIsrM   )r#   moduleWrapperr+   s   &&&r   assertModuleWrapperRefersTo)WrapFQPNTests.assertModuleWrapperRefersTo  sI    
 	m->->?++V__=m((*F3r
   c                    V P                  WP                  4       V P                  VP                  V4       V P	                  VP                  4       V4       R# )z_
Assert that a L{twisted.python.modules.PythonAttribute} refers to a
particular Python object.
N)r   r   r   rG   r   rM   )r#   attributeWrapperfqpnobjs   &&&&r   assertAttributeWrapperRefersTo,WrapFQPNTests.assertAttributeWrapperRefersTo  sH    
 	.0D0DE)..5&++-s3r
   c                    V P                  V P                  4      ;_uu_ 4        V P                  R4       RRR4       R#   + '       g   i     R# ; i)z?
L{wrapFQPN} raises L{InvalidFQPN} when given an empty string.
 NassertRaisesr   r   r#   s   &r   test_failsWithEmptyFQPN%WrapFQPNTests.test_failsWithEmptyFQPN  s6     t//00MM" 1000   A  A	c                    R F@  pV P                  V P                  4      ;_uu_ 4        V P                  V4       RRR4       KB  	  R#   + '       g   i     KW  ; i)zS"
L{wrapFQPN} raises L{InvalidFQPN} when given a badly-dotted
FQPN.  (e.g., x..y).
N)z.failszfails.zthis..failsr   r#   bads   & r   test_failsWithBadDotting&WrapFQPNTests.test_failsWithBadDotting  sC    
 7C""4#3#344c" 54 7444   A		Ac                    ^ RI pV P                  R4      pV P                  W P                  4       V P	                  VP                  4       V4       R# )zw
L{wrapFQPN} returns a L{twisted.python.modules.PythonModule}
referring to the single module a dotless FQPN describes.
Nr?   )r?   r   r   r   r   rM   )r#   r?   r   s   &  r   test_singleModuleWrapFQPNTests.test_singleModule  s@    
 	d+m->->?m((*B/r
   c                    V P                  V P                  4      ;_uu_ 4        V P                  R4       RRR4       R#   + '       g   i     R# ; i)zf
L{wrapFQPN} raises L{NoModule} when given a dotless FQPN that does
not refer to a module or package.
zthis is not an acceptable name!N)r   r   r   r   s   &r   *test_failsWithMissingSingleModuleOrPackage8WrapFQPNTests.test_failsWithMissingSingleModuleOrPackage  s5    
 t}}--MM;< .---r   c                P    ^ RI pV P                  V P                  R4      V4       R# )zx
L{wrapFQPN} returns a L{twisted.python.modules.PythonModule}
referring to the single package a dotless FQPN describes.
Nxml)r   r   r   r#   r   s   & r   test_singlePackage WrapFQPNTests.test_singlePackage  s     
 	((u)=sCr
   c                d    ^ RI pV P                  V P                  R4      VP                  4       R# )zy
L{wrapFQPN} returns a L{twisted.python.modules.PythonModule}
referring to the deepest package described by dotted FQPN.
Nz	xml.etree)	xml.etreer   r   etreer   s   & r   test_multiplePackages#WrapFQPNTests.test_multiplePackages  s$    
 	(({)CSYYOr
   c                x    ^ RI pV P                  V P                  R4      VP                  P                  4       R# )zx
L{wrapFQPN} returns a L{twisted.python.modules.PythonModule}
referring to the deepest module described by dotted FQPN.
Nzxml.etree.ElementTree)xml.etree.ElementTreer   r   r   ElementTreer   s   & r    test_multiplePackagesFinalModule.WrapFQPNTests.test_multiplePackagesFinalModule
  s.    
 	%((MM12CII4I4I	
r
   c                f    ^ RI pV P                  V P                  R4      RVP                  4       R# )z
L{wrapFQPN} returns a L{twisted.python.modules.PythonAttribute}
referring to the deepest object an FQPN names, traversing one module.
Nzos.path)r?   r   r   r   )r#   r?   s   & r   test_singleModuleObject%WrapFQPNTests.test_singleModuleObject  s)    
 	++MM)$i	
r
   c                    ^ RI p^ RIpRVP                  P                  P                  3RVP
                  P                  33 F&  w  r4V P                  V P                  V4      W44       K(  	  R# )z
L{wrapFQPN} returns a L{twisted.python.modules.PythonAttribute}
referring to the deepest object described by an FQPN,
descending through several packages.
Nz xml.etree.ElementTree.fromstringz!automat.MethodicalMachine.__doc__)	r   automatr   r   
fromstringMethodicalMachinerW   r   r   )r#   r   r  r   r   s   &    r   test_multiplePackagesObject)WrapFQPNTests.test_multiplePackagesObject   sa     	% 01F1F1Q1QR0'2K2K2S2ST
ID //d0CTO	
r
   c                    R F@  pV P                  V P                  4      ;_uu_ 4        V P                  V4       RRR4       KB  	  R#   + '       g   i     KW  ; i)zj
L{wrapFQPN} raises L{NoObject} when given an FQPN that contains a
missing attribute, module, or package.
N)zxml.etree.nope!z*xml.etree.nope!.but.the.rest.is.believable)r   r   r   r   s   & r   4test_failsWithMultiplePackagesMissingModuleOrPackageBWrapFQPNTests.test_failsWithMultiplePackagesMissingModuleOrPackage/  sC    
 UC""4==11c" 21 U111r   )r   r   r   r   r   r   N)rS   rT   rU   rV   rW   r   r   r   r   r   r   r   r   r   r  r  r
  r  rX   rY   )r\   s   @r   r   r     sS     	!44#
0=DP	
	
P# #r
   r   c                   @   a a ] tR tRt oRtRtV 3R ltR tRtVt	V ;t
# )FindMachinesIntegrationTestsi9  zg
Integration tests to check that L{findMachines} yields all
machines discoverable at or below an FQPN.
z
    from automat import MethodicalMachine

    class PythonClass(object):
        _machine = MethodicalMachine()
        ignored = "i am ignored"

    rootLevel = MethodicalMachine()

    ignored = "i am ignored"
    c                  < \         \        V `  4        ^RIHp Wn        V P                  V P                  4      P                  R4      pVP                  4        V P                  V P                  .4      V n
        V P                  V P                  VP                  R4       VP                  R4      pVP                  4        VP                  R4      P                  4        V P                  V P                  VP                  R4       V P!                  V P                  R,          4      V n        V P!                  V P                  R,          R,          R,          4      V n        R# )r`   )findMachinesr   r   
subpackager   r+   N)r   r  r   rc   r  r   r!   r3   r   r   r   r<   SOURCEr   r   rC   rN   packageDictrg   )r#   r  
packageDirsubPackageDirr$   s   &   r   r   "FindMachinesIntegrationTests.setUpL  s   *D79,(]]4<<066~F
//4<<.9T[[*//=I"((6 M*002]%7%7E001PQ//OON+L9(C
r
   c                   \        V P                  R4      \        P                  ! ^ 4      R7      pV P                  R,          P                  4       pV P                  R,          P                  4       pV P                  R,          pVP                  4       pV P                  R,          pVP                  4       p\        RV3RVP                  3RV3RVP                  3.\        P                  ! ^ 4      R7      pV P                  W4       R	# )
zo
Given a top-level package FQPN, L{findMachines} discovers all
L{MethodicalMachine} instances in and below it.
r   r   ztest_package.rootLevelztest_package.PythonClassz(test_package.subpackage.module.rootLevelz*test_package.subpackage.module.PythonClassz!test_package.PythonClass._machinez3test_package.subpackage.module.PythonClass._machineN)	r   r  r   r   r  rM   rg   _machiner   )	r#   r   tpRootLeveltpPythonClassmRLAttr
mRootLevelmPCAttrmPythonClassr   s	   &        r   test_discoverAll-FindMachinesIntegrationTests.test_discoverAllb  s    
 $++N;ATATUVAWX&&'?@EEG(()CDIIK//"LM\\^
//"NO||~!);74m6L6LM;ZHI ))	 ##A&
 	)4r
   )r  rg   r  r   )rS   rT   rU   rV   rW   r  r   r!  rX   rY   rZ   r[   s   @@r   r  r  9  s      

F
,5 5r
   r  )r   r?   r(   r   r6   r   unittestr   r   r   r   r^   r|   r   r  r	   r
   r   <module>r$     s     	  
   %9J8 9Jx   "=>a?0 a? ?a?H   "=>wD"6 wD ?wDt   "=>F#H F# ?F#R   "=>D5#7 D5 ?D5r
   