
    tfH                        d Z ddlZddlZddlZddlZddlZddlmZm	Z	m
Z
mZ ddlmZ 	 ddlZddlZeZeZn# e$ r dZdZY nw xY wddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlm Z  ddl!m"Z" ddl#m$Z$m%Z% ddl&m'Z(  e ej)                  *                                Z+ G d de%          Z, G d de%          Z- G d de%          Z. e e/edd           d           G d de%                      Z0 G d de%          Z1 G d de%          Z2 G d de%          Z3 G d d e          Z4 e ej5        e           d!           G d" d#e%                      Z6 G d$ d%e%          Z7 G d& d'e%          Z8 G d( d)ej9                  Z: G d* d+ej9                  Z; G d, d-e:          Z< G d. d/          Z= G d0 d1          Z> G d2 d3e%          Z? e e/ed4d           d5           G d6 d7e%                      Z@ eejA         d8           G d9 d:e%                      ZB G d; d<e%          ZC G d= d>e%          ZD G d? d@e%          ZE G dA dBe%          ZFdS )Cz#
Tests for L{twisted.python.util}.
    N)IterableMappingMutableMappingSequence)skipIf)reactor)Deferred)ProcessDone)IReactorProcess)ProcessProtocol)util)FilePath)MockOS)FailTestTestCase)suppressc                       e Zd Zd Zd Zd Z eedu d          d             Zd Z	 ee
du d          d	             ZdS )
	UtilTestsc                 b    g d}|                      t          j        |          g d           d S )N)a   abr         r      r   r      )r   r   r   r   r   r   r   )assertEqualr   uniquify)selflistWithDupess     \/var/www/surfInsights/venv3-11/lib/python3.11/site-packages/twisted/python/test/test_util.pytestUniqzUtilTests.testUniq+   s:    @@@}557Q7Q7QRRRRR    c                 V   |                      t          j        t          t          dd                     |                     t          j        t          t          dd                     	 t          j        t          t          dd           t          d          # t          $ r Y d S w xY w)Nr   r   z,util.raises didn't raise when it should have)
assertTruer   raisesZeroDivisionErrordivmodassertFalse	TypeErrorr   r   s    r!   
testRaiseszUtilTests.testRaises/   s    $5vq!DDEEE%61EEFFF	KK	61a000 IJJJ ! 	 	 	DD	s   *!B 
B('B(c                 V    |                      t          j        d          d           dS )
        When L{uidFromString} is called with a base-ten string representation
        of an integer, it returns the integer.
        100d   N)r   r   uidFromStringr+   s    r!   test_uidFromNumericStringz#UtilTests.test_uidFromNumericString:   +    
 	+E22C88888r#   Nz0Username/UID conversion requires the pwd module.c                     t                               t          j                              }|                     t          j        |j                  |j                   dS )r.   N)	pwdgetpwuidosgetuidr   r   r1   pw_namepw_uid)r   pwents     r!   test_uidFromUsernameStringz$UtilTests.test_uidFromUsernameStringA   F     RY[[))+EM::ELIIIIIr#   c                 V    |                      t          j        d          d           dS )
        When L{gidFromString} is called with a base-ten string representation
        of an integer, it returns the integer.
        r/   r0   N)r   r   gidFromStringr+   s    r!   test_gidFromNumericStringz#UtilTests.test_gidFromNumericStringJ   r3   r#   z2Group Name/GID conversion requires the grp module.c                     t                               t          j                              }|                     t          j        |j                  |j                   dS )r?   N)	grpgetgrgidr7   getgidr   r   r@   gr_namegr_gid)r   grents     r!   test_gidFromGroupnameStringz%UtilTests.test_gidFromGroupnameStringQ   r=   r#   )__name__
__module____qualname__r"   r,   r2   r   r5   r<   rA   rC   rI    r#   r!   r   r   *   s        S S S	K 	K 	K9 9 9 VC4KKLLJ J MLJ9 9 9 VC4KMNNJ J ONJ J Jr#   r   c                       e Zd ZdZd ZdS )NameToLabelTestsz#
    Tests for L{nameToLabel}.
    c                     g d}|D ]9\  }}t          j        |          }|                     ||d|d|d|           :dS )zK
        Test the various kinds of inputs L{nameToLabel} supports.
        ))fF)foFo)fooFoo)fooBarzFoo Bar)	fooBarBazzFoo Bar BazznameToLabel(z) == z != N)r   nameToLabelr   )r   nameDatainpoutgots        r!   test_nameToLabelz!NameToLabelTests.test_nameToLabel`   sz    
 
 
 ! 	V 	VHC"3''CS#'Tc'T'T#'T'TS'T'TUUUU	V 	Vr#   N)rJ   rK   rL   __doc__r^   rM   r#   r!   rO   rO   [   s2         V V V V Vr#   rO   c                       e Zd ZdZd ZdS )UntilConcludesTestsz:
    Tests for L{untilConcludes}, an C{EINTR} helper.
    c                 z     fd}dg _         d _                             t          j        |dd          d                                 j        d           dt
          t          g _         d _                             t          j        |dd          d                                 j        d           dS )a  
        L{untilConcludes} calls the function passed to it until the function
        does not raise either L{OSError} or L{IOError} with C{errno} of
        C{EINTR}.  It otherwise completes with the same result as the function
        passed to it.
        c                     xj         dz  c_         j                                        }| |t          j        d          | |z   S )Nr   zInterrupted system call!)calls
exceptionspoperrnoEINTR)r   bexcr   s      r!   rQ   z3UntilConcludesTests.test_uninterruptably.<locals>.f}   sH    JJ!OJJ/%%''Cc%+'ABBBq5Lr#   Nr   r   r   r      )re   rd   r   r   untilConcludesOSErrorIOError)r   rQ   s   ` r!   test_uninterruptablyz(UntilConcludesTests.test_uninterruptablyu   s    	 	 	 	 	  &
,Q155q999Q''''2
,Q155q999Q'''''r#   N)rJ   rK   rL   r_   ro   rM   r#   r!   ra   ra   p   s-         ( ( ( ( (r#   ra   r8   zgetuid/setuid not availablec                   6    e Zd ZdZd Zd Zd Zd Zd Zd Z	dS )	SwitchUIDTestsz&
    Tests for L{util.switchUID}.
    c                     t                      | _        |                     t          d| j                   |                     t          d| j                   g | _        d S )Nr7   
initgroups)r   mockospatchr   rs   initgroupsCallsr+   s    r!   setUpzSwitchUIDTests.setUp   sK    hh

4t{+++

4t777!r#   c                 >    | j                             ||f           dS )zK
        Save L{util.initgroups} calls in C{self.initgroupsCalls}.
        N)rv   append)r   uidgids      r!   rs   zSwitchUIDTests.initgroups   s%     	##S#J/////r#   c                     t          j        dd           |                     | j        dg           |                     | j        j        dg           dS )zn
        L{util.switchUID} calls L{util.initgroups} and then C{os.setuid} with
        the given uid.
        .  Nr}   N)setuidr}   )r   	switchUIDr   rv   rt   actionsr+   s    r!   test_uidzSwitchUIDTests.test_uid   sV    
 	ud###-???,/@.ABBBBBr#   c                     t          j        ddd           |                     | j        dg           |                     | j        j        dg           dS )z
        L{util.switchUID} calls L{util.initgroups} and then C{os.seteuid} with
        the given uid if the C{euid} parameter is set to C{True}.
        r}   NTr~   )r   r   r   rv   rt   seteuidCallsr+   s    r!   	test_euidzSwitchUIDTests.test_euid   sV    
 	udD)))-???1E7;;;;;r#   c                    | j                                         }t          j        |d           |                     | j        g            |                     | j         j        g            |                     t          j        g          }|                     t          |          d           | 	                    d|z  |d         d                    | 	                    d|z  |d         d                    dS )z
        If the current uid is the same as the uid passed to L{util.switchUID},
        then initgroups does not get called, but a warning is issued.
        Nr   z&tried to drop privileges and setuid %ir   messagezbut uid is already %i)
rt   r8   r   r   r   rv   r   flushWarningslenassertIn)r   rz   currentWarningss      r!   test_currentUIDzSwitchUIDTests.test_currentUID   s    
 k  ""sD!!!-r222,b111,,dn-=>>_--q1114s:Ay)	
 	
 	
 	-3_Q5G	5RSSSSSr#   c                    | j                                         }t          j        |dd           |                     | j        g            |                     | j         j        g            |                     t          j        g          }|                     t          |          d           | 	                    d|z  |d         d                    | 	                    d|z  |d         d                    dS )z
        If the current euid is the same as the euid passed to L{util.switchUID},
        then initgroups does not get called, but a warning is issued.
        NTr   z'tried to drop privileges and seteuid %ir   r   zbut euid is already %i)
rt   geteuidr   r   r   rv   r   r   r   r   )r   euidr   s      r!   test_currentEUIDzSwitchUIDTests.test_currentEUID   s    
 {""$$tT4(((-r22212666,,dn-=>>_--q1115<Ay)	
 	
 	
 	.5q7I)7TUUUUUr#   N)
rJ   rK   rL   r_   rw   rs   r   r   r   r   rM   r#   r!   rq   rq      s         " " "0 0 0C C C< < <T T T"V V V V Vr#   rq   c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )MergeFunctionMetadataTestsz-
    Tests for L{mergeFunctionMetadata}.
    c                     t                      t                      fd}d	fd	}t          j        ||          }|                      |dddd                     dS )
zt
        After merging C{foo}'s data into C{bar}, the returned function behaves
        as if it is C{bar}.
        c                       S NrM   )
foo_objects   r!   rU   zQMergeFunctionMetadataTests.test_mergedFunctionBehavesLikeMergeTarget.<locals>.foo   s	    r#   
   c                     |\  }}S r   rM   )	xyr   cder   ri   
bar_objects	           r!   barzQMergeFunctionMetadataTests.test_mergedFunctionBehavesLikeMergeTarget.<locals>.bar   s    FQr#   r   r   )r   r   )quuxN)r   )objectr   mergeFunctionMetadataassertIs)r   rU   r   bazr   r   s       @@r!   )test_mergedFunctionBehavesLikeMergeTargetzDMergeFunctionMetadataTests.test_mergedFunctionBehavesLikeMergeTarget   s    
 XX
XX
	 	 	 	 		 	 	 	 	 	 (c22cc!QR000*=====r#   c                     d }d }d|_         t          j        ||          }|                     |j         |j                    dS )zd
        Merging C{foo} into C{bar} returns a function with C{foo}'s
        C{__module__}.
        c                      d S r   rM   rM   r#   r!   rU   z;MergeFunctionMetadataTests.test_moduleIsMerged.<locals>.foo       Dr#   c                      d S r   rM   rM   r#   r!   r   z;MergeFunctionMetadataTests.test_moduleIsMerged.<locals>.bar   r   r#   zsomewhere.elseN)rK   r   r   r   r   rU   r   r   s       r!   test_moduleIsMergedz.MergeFunctionMetadataTests.test_moduleIsMerged   s[    	 	 		 	 	 *(c2288888r#   c                 |    d }d }t          j        ||          }|                     |j        |j                   dS )zX
        Merging C{foo} into C{bar} returns a function with C{foo}'s docstring.
        c                      dS )z&
            This is foo.
            NrM   rM   r#   r!   rU   z>MergeFunctionMetadataTests.test_docstringIsMerged.<locals>.foo        r#   c                      dS )z&
            This is bar.
            NrM   rM   r#   r!   r   z>MergeFunctionMetadataTests.test_docstringIsMerged.<locals>.bar  r   r#   N)r   r   r   r_   r   s       r!   test_docstringIsMergedz1MergeFunctionMetadataTests.test_docstringIsMerged   sT    
	 	 	
	 	 	
 (c22ck22222r#   c                 |    d }d }t          j        ||          }|                     |j        |j                   dS )zS
        Merging C{foo} into C{bar} returns a function with C{foo}'s name.
        c                      d S r   rM   rM   r#   r!   rU   z9MergeFunctionMetadataTests.test_nameIsMerged.<locals>.foo  r   r#   c                      d S r   rM   rM   r#   r!   r   z9MergeFunctionMetadataTests.test_nameIsMerged.<locals>.bar  r   r#   N)r   r   r   rJ   r   s       r!   test_nameIsMergedz,MergeFunctionMetadataTests.test_nameIsMerged  sT    
	 	 		 	 	 (c22s|44444r#   c                 4   d }d|_         d|_        d }d|_        d|_        t          j        ||          }|                     |j         |j                    |                     |j        |j                   |                     |j        |j                   dS )zv
        Merging C{foo} into C{bar} returns a function with C{bar}'s
        dictionary, updated by C{foo}'s.
        c                      d S r   rM   rM   r#   r!   rU   zGMergeFunctionMetadataTests.test_instanceDictionaryIsMerged.<locals>.foo$  r   r#   r   r   c                      d S r   rM   rM   r#   r!   r   zGMergeFunctionMetadataTests.test_instanceDictionaryIsMerged.<locals>.bar*  r   r#   r   r   N)r   ri   r   r   r   r   r   s       r!   test_instanceDictionaryIsMergedz:MergeFunctionMetadataTests.test_instanceDictionaryIsMerged  s    	 	 	 	 	 	 (c22&&&&&&&&&&&r#   N)	rJ   rK   rL   r_   r   r   r   r   r   rM   r#   r!   r   r      si         > > >$9 9 9"3 3 3$5 5 5' ' ' ' 'r#   r   c                       e Zd ZdZd ZdS )OrderedDictTestsz(
    Tests for L{util.OrderedDict}.
    c                 &   ddl m} | |                     | j        g          }|                     |d         d         d           |                     |d         d         t
                     |                     t          |          d           dS )	z4
        L{util.OrderedDict} is deprecated.
        r   )OrderedDictoffendingFunctionsr   zftwisted.python.util.OrderedDict was deprecated in Twisted 15.5.0: Use collections.OrderedDict instead.categoryr   N)twisted.python.utilr   r   test_deprecatedr   DeprecationWarningr   )r   r   r   s      r!   r   z OrderedDictTests.test_deprecated;  s     	433333,,AU@V,WWAy);	
 	
 	

 	+J79KLLL_--q11111r#   N)rJ   rK   rL   r_   r   rM   r#   r!   r   r   6  s-         2 2 2 2 2r#   r   c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )InsensitiveDictTestsz,
    Tests for L{util.InsensitiveDict}.
    c                 l   t          j                    }|                     t          |t                               |                     t          |t
                               |                     t          |t                               |                     t          |t                               dS )zN
        L{util.InsensitiveDict} implements L{typing.MutableMapping}.
        N)	r   InsensitiveDictr%   
isinstancer   r   r   r)   r   )r   dcts     r!   test_abczInsensitiveDictTests.test_abcR  s     "$$
311222
300111
377888C2233333r#   c                    t          j        ddddidd          }|                     |d         ddi           |                     |d         d           |                     |                                |           |                     |d         |                    d                     |                     d|           |                     d|           t          t          |          |t           j        d	          }|                     ||           g d
}|D ]Z}|                     ||                                           |                     |||         f|	                                           [|                     t          |          t          |                     |d= |d= |                     |                                dg           dS )zr
        L{util.InsensitiveDict} preserves the case of keys if constructed with
        C{preserve=True}.
        r   r   r   rV   r   fnzpreserver   rU   rV   )r   r   )rV   r   r   N)r   r   r   copygetr   evalreprkeysitemsr   )r   r   resultr   r   s        r!   test_preservez"InsensitiveDictTests.test_preserve\  s   
 "5Q1v#F#FQRSSSUaV,,,UU+++S)))USWWU^^444aeS!!!II#'#7 
 
 	%%%    	4 	4AMM!SXXZZ(((MM1c!f+syy{{3333TCHH---FJeW-----r#   c                    t          j        ddddidd          }g d}|D ]Z}|                     ||                                           |                     |||         f|                                           [|                     t          |          t          |                     |d= |d= |                     |                                d	g           d
S )z|
        L{util.InsensitiveDict} does not preserves the case of keys if
        constructed with C{preserve=False}.
        r   r   r   r   r   r   )rU   r   r   rU   r   N)r   r   r   r   r   r   r   )r   r   r   r   s       r!   test_noPreservez$InsensitiveDictTests.test_noPreserve{  s    
 "5Q1v#F#FQRSSS    	4 	4AMM!SXXZZ(((MM1c!f+syy{{3333TCHH---FJeW-----r#   c                     t          j        d          }d|d<   |                     |d         d           |                     |                                dg           dS )z4
        Unicode keys are case insensitive.
        Fr   r   rV   FOOrU   Nr   r   r   r   r   r   s     r!   test_unicodez!InsensitiveDictTests.test_unicode  s`      %000%51%%%E7+++++r#   c                     t          j        d          }d|d<   |                     |d         d           |                     |                                dg           dS )z2
        Bytes keys are case insensitive.
        Fr   r   s   Foos   FOOs   fooNr   r   s     r!   
test_byteszInsensitiveDictTests.test_bytes  s`      %000&	6A&&&F8,,,,,r#   N)	rJ   rK   rL   r_   r   r   r   r   r   rM   r#   r!   r   r   M  si         4 4 4. . .>. . ., , ,- - - - -r#   r   c                   $    e Zd ZdZd Zd Zd ZdS )PasswordTestingProcessProtocolz
    Write the string C{"secret\n"} to a subprocess and then collect all of
    its output and fire a Deferred with it when the process ends.
    c                 H    g | _         | j                            d           d S )Ns   secret
)output	transportwriter+   s    r!   connectionMadez-PasswordTestingProcessProtocol.connectionMade  s%    [)))))r#   c                 >    | j                             ||f           d S r   )r   ry   )r   fdr   s      r!   childDataReceivedz0PasswordTestingProcessProtocol.childDataReceived  s"    B<(((((r#   c                 H    | j                             || j        f           d S r   )finishedcallbackr   )r   reasons     r!   processEndedz+PasswordTestingProcessProtocol.processEnded  s%    455555r#   N)rJ   rK   rL   r_   r   r   r   rM   r#   r!   r   r     sK         
* * *) ) )6 6 6 6 6r#   r   z,Process support required to test getPasswordc                       e Zd Zd ZdS )GetPasswordTestsc           	      F    t                      }t                      |_        t          j        |t
          t
          ddgdt          j                            t          j
                                      d          i            fd}|j                            |          S )a.  
        Making sure getPassword accepts a password from standard input by
        running a child process which uses getPassword to read in a string
        which it then writes it out again.  Write a string to the child
        process and then read one and make sure it is the right string.
        s   -csj   import sys
from twisted.python.util import getPassword
sys.stdout.write(getPassword())
sys.stdout.flush()
s
   PYTHONPATHutf8)envc                 r    | \  }}|                     t                                         d|           d S )N)r   s   secret)trapr
   r   )r   r   r   r   s      r!   processFinishedz4GetPasswordTests.test_stdin.<locals>.processFinished  s9    %VVKK$$$MM.&11111r#   )r   r	   r   r   spawnProcesspyExer7   pathsepjoinsyspathencodeaddCallback)r   pr   s   `  r!   
test_stdinzGetPasswordTests.test_stdin  s     +,,ZZ
,		 
 9 9 @ @ H HI	
 	
 	
 	
 	2 	2 	2 	2 	2
 z%%o666r#   N)rJ   rK   rL   r   rM   r#   r!   r   r     s#        
7 7 7 7 7r#   r   c                       e Zd Zd ZdS )SearchUpwardsTestsc                    t          j        d           t          dd                                           t          dd                                           t          dd                                           t          j        d           t          j        d           t          j        d           t          j        d	           t          j        dd
gddg          }t           j                            d          t           j	        z   }| 
                    ||           t          j        d           t          j        dd
gddg          }d }| 
                    ||           d S )Nzsearchupwards/a/b/czsearchupwards/foo.txtwzsearchupwards/a/foo.txtzsearchupwards/a/b/c/foo.txtzsearchupwards/barzsearchupwards/bamzsearchupwards/a/barzsearchupwards/a/b/bamzfoo.txtr   bam)filesdirssearchupwards)r7   makedirsopenclosemkdirr   r  r   abspathsepr   shutilrmtree)r   actualexpecteds      r!   testSearchupwardsz$SearchUpwardsTests.testSearchupwards  s[   
)***$c**00222&,,22444*C0066888
$%%%
$%%%
&'''
()))#!)E5>
 
 
 7???33bf<***o&&&#!)E5>
 
 
 *****r#   N)rJ   rK   rL   r  rM   r#   r!   r  r    s#        + + + + +r#   r  c                   2    e Zd Zd Zd Zd Zd Zd Zd ZdS )IntervalDifferentialTestsc                     t          t          j        g d                    }t          d          D ]%}|                     t          |          d           &d S )Nr   r0   r   Niterr   IntervalDifferentialranger   nextr   r   is      r!   testDefaultz%IntervalDifferentialTests.testDefault  sZ    *2r2233s 	2 	2AT!WWj1111	2 	2r#   c                     t          t          j        dgd                    }t          d          D ]%}|                     t          |          d           &d S )Nrk   r   r0   rk   r   r  r  s      r!   
testSinglez$IntervalDifferentialTests.testSingle  s\    *A33344s 	. 	.AT!WWf----	. 	.r#   c                    t          t          j        ddgd                    }t          d          D ]}|                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d	           |                     t          |          d           |                     t          |          d
           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           d S )Nrk      r   r0   r!  r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r  r  s      r!   testPairz"IntervalDifferentialTests.testPair  s   *Aq626677s 	. 	.AT!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf----	. 	.r#   c                    t          t          j        g dd                    }t          d          D ]}|                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           |                     t          |          d           d S )	N)r   r   rk   r   r0   r*  r+  )r   r   r'  )r   r   r  r  s      r!   
testTriplez$IntervalDifferentialTests.testTriple  sV   *999b99::s 	. 	.AT!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf---T!WWf----'	. 	.r#   c                    t          t          j        g d                    }|                     t	          |          d           |                    d           |                     t	          |          d           |                     t	          |          d           |                    d           |                     t	          |          d           |                     t	          |          d           |                     t	          |          d           |                     t	          |          d           |                     t	          |          d           |                     t	          |          d           d S )Nr   r  r   r&  r   r+  )r  r   r  r   r  addIntervalr   s     r!   
testInsertz$IntervalDifferentialTests.testInsert  sB   *2r2233a*---	aa&)))a&)))	aa&)))a&)))a&)))a&)))a&)))a&)))))r#   c                    t          t          j        ddgd                    }|                     t	          |          d           |                     t	          |          d           |                     t	          |          d           |                    d           |                     t	          |          d           |                     t	          |          d           |                    d           |                     t	          |          d	           |                     t          |j        d           d S )
Nr   rk   r   r&  r%  r'  r)  r!  r  )r  r   r  r   r  removeIntervalassertRaises
ValueErrorr   s     r!   
testRemovez$IntervalDifferentialTests.testRemove+  s   *Aq626677a&)))a&)))a&)))	a&)))a&)))	a*---*a&6;;;;;r#   N)	rJ   rK   rL   r  r"  r,  r.  r1  r6  rM   r#   r!   r  r    sn        2 2 2
. . .
. . . . . ..* * *
< 
< 
< 
< 
<r#   r  c                       e Zd ZdZdZd ZdS )Recordz8
    Trivial user of L{FancyEqMixin} used by tests.
    r   ri   c                 "    || _         || _        d S r   r9  r   r   ri   s      r!   __init__zRecord.__init__?      r#   NrJ   rK   rL   r_   compareAttributesr<  rM   r#   r!   r8  r8  8  5          #    r#   r8  c                       e Zd ZdZdZd ZdS )DifferentRecordzL
    Trivial user of L{FancyEqMixin} which is not related to L{Record}.
    r9  c                 "    || _         || _        d S r   r9  r;  s      r!   r<  zDifferentRecord.__init__K  r=  r#   Nr>  rM   r#   r!   rB  rB  D  r@  r#   rB  c                       e Zd ZdZdS )DerivedRecordz@
    A class with an inheritance relationship to L{Record}.
    N)rJ   rK   rL   r_   rM   r#   r!   rE  rE  P  s           r#   rE  c                   "    e Zd ZdZdedefdZdS )EqualToEverythingzQ
    A class the instances of which consider themselves equal to everything.
    otherreturnc                     dS )NTrM   r   rH  s     r!   __eq__zEqualToEverything.__eq__[  s    tr#   NrJ   rK   rL   r_   r   boolrL  rM   r#   r!   rG  rG  V  s@         F t      r#   rG  c                   "    e Zd ZdZdedefdZdS )EqualToNothingzN
    A class the instances of which consider themselves equal to nothing.
    rH  rI  c                     dS )NFrM   rK  s     r!   rL  zEqualToNothing.__eq__d  s    ur#   NrM  rM   r#   r!   rP  rP  _  s@         F t      r#   rP  c                   H    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 ZdS )EqualityTestsz$
    Tests for L{FancyEqMixin}.
    c                 R    G d dt           j                  }|                      |             |            k               |                      |             |            k                |            }|                     ||k               |                     ||k               dS )z
        Instances of a class which mixes in L{FancyEqMixin} but which
        defines no comparison attributes compare by identity.
        c                       e Zd ZdS )*EqualityTests.test_identity.<locals>.EmptyN)rJ   rK   rL   rM   r#   r!   EmptyrV  s  s        Dr#   rW  N)r   FancyEqMixinr)   r%   )r   rW  emptys      r!   test_identityzEqualityTests.test_identitym  s    	 	 	 	 	D% 	 	 	 	EEGG+,,,5577*+++'''%(((((r#   c                    |                      t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               dS )z
        Instances of a class which mixes in L{FancyEqMixin} should compare
        equal if all of their attributes compare equal.  They should not
        compare equal if any of their attributes do not compare equal.
        r   r   r   r   N)r%   r8  r)   r+   s    r!   test_equalityzEqualityTests.test_equality|  s     	q!q!455511566611566611566666r#   c                    |                      t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               dS )z
        Inequality between instances of a particular L{record} should be
        defined as the negation of equality.
        r   r   r   r   N)r)   r8  r%   r+   s    r!   test_unequalityzEqualityTests.test_unequality  s    
 	115666q!q!4555q!q!4555q!q!455555r#   c                 p    |                      t          dd          t          dd          k               dS )zo
        Instances of different classes which mix in L{FancyEqMixin} should not
        compare equal.
        r   r   N)r)   r8  rB  r+   s    r!   test_differentClassesEqualityz+EqualityTests.test_differentClassesEquality  s5    
 	1A)>)>>?????r#   c                 p    |                      t          dd          t          dd          k               dS )zm
        Instances of different classes which mix in L{FancyEqMixin} should
        compare unequal.
        r   r   N)r%   r8  rB  r+   s    r!   test_differentClassesInequalityz-EqualityTests.test_differentClassesInequality  s3    
 	q!1(=(==>>>>>r#   c                    |                      t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               dS )z
        An instance of a class which derives from a class which mixes in
        L{FancyEqMixin} should compare equal to an instance of the base class
        if and only if all of their attributes compare equal.
        r   r   r   r   N)r%   r8  rE  r)   r+   s    r!   test_inheritedClassesEqualityz+EqualityTests.test_inheritedClassesEquality  s     	q!a(;(;;<<<1q!)<)<<===1q!)<)<<===1q!)<)<<=====r#   c                    |                      t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               |                     t          dd          t          dd          k               dS )z
        An instance of a class which derives from a class which mixes in
        L{FancyEqMixin} should compare unequal to an instance of the base
        class if any of their attributes compare unequal.
        r   r   r   r   N)r)   r8  rE  r%   r+   s    r!   test_inheritedClassesInequalityz-EqualityTests.test_inheritedClassesInequality  s     	1q!)<)<<===q!a(;(;;<<<q!a(;(;;<<<q!a(;(;;<<<<<r#   c                     |                      t          dd          t                      k               |                     t          dd          t	                      k               dS )z
        The right-hand argument to the equality operator is given a chance
        to determine the result of the operation if it is of a type
        unrelated to the L{FancyEqMixin}-based instance on the left-hand
        side.
        r   r   N)r%   r8  rG  r)   rP  r+   s    r!   (test_rightHandArgumentImplementsEqualityz6EqualityTests.test_rightHandArgumentImplementsEquality  sW     	q!(9(;(;;<<<1)9)99:::::r#   c                     |                      t          dd          t                      k               |                     t          dd          t	                      k               dS )z
        The right-hand argument to the non-equality operator is given a
        chance to determine the result of the operation if it is of a type
        unrelated to the L{FancyEqMixin}-based instance on the left-hand
        side.
        r   r   N)r)   r8  rG  r%   rP  r+   s    r!   *test_rightHandArgumentImplementsUnequalityz8EqualityTests.test_rightHandArgumentImplementsUnequality  sW     	1):)<)<<===q!(8(8899999r#   N)rJ   rK   rL   r_   rZ  r\  r^  r`  rb  rd  rf  rh  rj  rM   r#   r!   rS  rS  h  s         ) ) )	7 	7 	76 6 6@ @ @? ? ?	> 	> 	>	= 	= 	=; ; ;: : : : :r#   rS  r   zgeteuid/seteuid not availablec                   N    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd ZdS )RunAsEffectiveUserTestsz;
    Test for the L{util.runAsEffectiveUser} function.
    c                 \   t                      | _        |                     t          d| j        j                   |                     t          d| j        j                   |                     t          d| j        j                   |                     t          d| j        j                   d S )Nr   getegidseteuidsetegid)r   rt   ru   r7   r   rn  ro  rp  r+   s    r!   rw   zRunAsEffectiveUserTests.setUp  s    hh

2y$+"5666

2y$+"5666

2y$+"5666

2y$+"566666r#   c                     |                      ||k    p|| j        j        d         k               |                      ||k    p|| j        j        d         k               dS )zF
        Check if wanted UID/GID matched start or saved ones.
        N)r%   rt   r   setegidCalls)r   startUIDstartGIDwantUIDwantGIDs        r!   _securedFunctionz(RunAsEffectiveUserTests._securedFunction  sb     	8+Vw$+:RSU:V/VWWW8+Vw$+:RSU:V/VWWWWWr#   c                 `    t          j        ddd           }|                     |d           dS )zo
        L{util.runAsEffectiveUser} forwards the result obtained by calling the
        given function
        r   c                      dS )Nr   rM   rM   r#   r!   <lambda>z<RunAsEffectiveUserTests.test_forwardResult.<locals>.<lambda>  s    q r#   r   Nr   runAsEffectiveUserr   r   r   s     r!   test_forwardResultz*RunAsEffectiveUserTests.test_forwardResult  s6    
 (Ayy99#####r#   c                 b    t          j        ddd d          }|                     |d           dS )ze
        L{util.runAsEffectiveUser} pass the given parameters to the given
        function.
        r   c                     d| z  S )Nr   rM   )r   s    r!   r{  z=RunAsEffectiveUserTests.test_takeParameters.<locals>.<lambda>  s
    Q r#   r   r   Nr|  r~  s     r!   test_takeParametersz+RunAsEffectiveUserTests.test_takeParameters  s8    
 (ABB#####r#   c                 h    t          j        ddd	ddd          }|                     |d           dS )
zg
        L{util.runAsEffectiveUser} pass the keyword parameters to the given
        function.
        r   r   c                     | |z  |z  S r   rM   )r   r   zs      r!   r{  zDRunAsEffectiveUserTests.test_takesKeyworkArguments.<locals>.<lambda>  s    1q519 r#   r   r   )r  r   Nr(  r|  r~  s     r!   test_takesKeyworkArgumentsz2RunAsEffectiveUserTests.test_takesKeyworkArguments  sC    
 (A/L/L/LaSTUUU#####r#   c           	      $   || j         _        || j         _        t          j        ||| j        ||||           |                     | j         j        |           |                     | j         j        |           g | j         _        g | j         _        dS )z
        Helper method checking the calls to C{os.seteuid} and C{os.setegid}
        made by L{util.runAsEffectiveUser}, when switching from startUID to
        wantUID and from startGID to wantGID.
        N)	rt   r   egidr   r}  rx  r   r   rs  )r   rt  ru  rv  rw  expectedUIDSwitchesexpectedGIDSwitchess          r!   _testUIDGIDSwitchz)RunAsEffectiveUserTests._testUIDGIDSwitch  s     $#!	
 	
 	
 	13FGGG13FGGG#% #%   r#   c           	          |                      ddddg g            |                      ddddddgg            |                      ddddg ddg           |                      ddddddgddg           dS )zL
        Check UID/GID switches when current effective UID is root.
        r   r   Nr  r+   s    r!   	test_rootz!RunAsEffectiveUserTests.test_root  s     	q!Q2r222q!QAq62666q!Q21v666q!QAq6Aq6:::::r#   c           	          |                      ddddddgg            |                      ddddg g            |                      ddddg dddg           |                      ddddg dddg           dS )zP
        Check UID/GID switches when current effective UID is non-root.
        r   r   r   r   r   r   r   r   r   r   r   Nr  r+   s    r!   test_UIDz RunAsEffectiveUserTests.test_UID  s     	q!QAq62666q!Q2r222q!Q<<<!Q@@@q!Q<<<!Q@@@@@r#   c           	          |                      ddddg ddg           |                      ddddg g            |                      ddddddgg            |                      ddddddgddg           dS )zP
        Check UID/GID switches when current effective GID is non-root.
        r   r   r   Nr  r+   s    r!   test_GIDz RunAsEffectiveUserTests.test_GID&  s     	q!Q21v666q!Q2r222q!QAq62666q!QAq6Aq6:::::r#   c           	         |                      ddddddgddg           |                      ddddddgg            |                      ddddg dddg           |                      ddddg g            |                      ddddg dg            |                      ddddg dddg           |                      ddddg dddg           dS )zT
        Check UID/GID switches when current effective UID/GID is non-root.
        r   r   r  r   r  Nr  r+   s    r!   test_UIDGIDz#RunAsEffectiveUserTests.test_UIDGID/  s    	q!QAq6Aq6:::q!QAq62666q!Q<<<!Q@@@q!Q2r222q!Q<<<<<<q!Q<<<!Q@@@q!Q<<<!Q@@@@@r#   N)rJ   rK   rL   r_   rw   rx  r  r  r  r  r  r  r  r  rM   r#   r!   rl  rl    s         7 7 7X X X$ $ $$ $ $$ $ $& & &<; ; ;A A A; ; ;
A 
A 
A 
A 
Ar#   rl  z.stdlib support for initgroups is not availablec                       e Zd ZdZd Zd ZdS )InitGroupsTestsz'
    Tests for L{util.initgroups}.
    c                    g fd}|                      t          d|           g }|                      t          d|j                   t          j        t	          j                    d           |                     t                              t	          j                              j	        dfg           | 
                    |           dS )zc
        Calling L{util.initgroups} will call the underlying stdlib
        implmentation.
        c                 6                         | |f           d S r   )ry   )r   r   rd   s     r!   mockInitgroupsz?InitGroupsTests.test_initgroupsInStdlib.<locals>.mockInitgroupsI  s    LL!Q     r#   _initgroups	setgroupsr   N)ru   r   ry   rs   r7   r8   r   r5   r6   r9   r)   )r   r  setgroupsCallsrd   s      @r!   test_initgroupsInStdlibz'InitGroupsTests.test_initgroupsInStdlibB  s    
 	! 	! 	! 	! 	! 	

4777

4n&;<<<	Q'''#,,ry{{";";"CQ!G HIII(((((r#   c                 v    |                      t          t          j        t	          j                    d           dS )zN
        Calling L{util.initgroups} with None for gid gives an error.
        N)r4  r*   r   rs   r7   r8   r+   s    r!   test_initgroupsNoneGidz&InitGroupsTests.test_initgroupsNoneGidT  s,     	)T_bikk4HHHHHr#   N)rJ   rK   rL   r_   r  r  rM   r#   r!   r  r  <  sA         ) ) )$I I I I Ir#   r  c                   D    e Zd ZdZd Zd Z eed          ge_        dS )DeprecationTestsz;
    Tests for deprecations in C{twisted.python.util}.
    c                 <   t          j                     |                     | j        g          }|                     |d         d         d           |                     |d         d         t
                     |                     t          |          d           dS )z6
        L{util.getPluginDirs} is deprecated.
        r   r   r   zCtwisted.python.util.getPluginDirs is deprecated since Twisted 12.2.r   r   N)r   getPluginDirsr   test_getPluginDirsr   r   r   r   r   s     r!   r  z#DeprecationTests.test_getPluginDirs`  s     	,, $ 78 - 
 
 	Ay)T	
 	
 	
 	+J79KLLL_--q11111r#   c                 <   t          j                     |                     | j        g          }|                     |d         d         d           |                     |d         d         t
                     |                     t          |          d           dS )z5
        L{util.addPluginDir} is deprecated.
        r   r   r   zBtwisted.python.util.addPluginDir is deprecated since Twisted 12.2.r   r   N)r   addPluginDirr   test_addPluginDirr   r   r   r  s     r!   r  z"DeprecationTests.test_addPluginDiro  s     	,, $ 67 - 
 
 	Ay)S	
 	
 	
 	+J79KLLL_--q11111r#   z/twisted.python.util.getPluginDirs is deprecated)r   r   N)	rJ   rK   rL   r_   r  r  SUPPRESSr   r   rM   r#   r!   r  r  [  s_         2 2 22 2 2  	'E	
 	
 	
"r#   r  c                   J    e Zd ZdZ eej                  Zd Zd Zd Z	d Z
dS )SuppressedWarningsTestsz6
    Tests for L{util.runWithWarningsSuppressed}.
    c                     di fdi fg}|                      |t          j        d           |                      |t          j        d           |                     g |                                            dS )z
        Warnings from the function called by C{runWithWarningsSuppressed} are
        suppressed if they match the passed in filter.
        ignorez.*foo.*r  z.*bar.*
ignore fooz
ignore barNrunWithWarningsSuppressedwarningswarnr   r   r   filterss     r!   &test_runWithWarningsSuppressedFilteredz>SuppressedWarningsTests.test_runWithWarningsSuppressedFiltered  su    
 *2.1F0KL&&w|LLL&&w|LLLT//1122222r#   c                     di fdi fg}|                      |t          j        d           |                     dgd |                                 D                        dS )z
        Warnings from the function called by C{runWithWarningsSuppressed} are
        not suppressed if they do not match the passed in filter.
        r  r  zdon't ignorec                     g | ]
}|d          S r   rM   .0r  s     r!   
<listcomp>zTSuppressedWarningsTests.test_runWithWarningsSuppressedUnfiltered.<locals>.<listcomp>  s    +W+W+WQAiL+W+W+Wr#   Nr  r  s     r!   (test_runWithWarningsSuppressedUnfilteredz@SuppressedWarningsTests.test_runWithWarningsSuppressedUnfiltered  sm    
 *2.1F0KL&&w~NNN.)+W+W$BTBTBVBV+W+W+WXXXXXr#   c                 \    |                      |                     g d           d           dS )zd
        C{runWithWarningsSuppressed} returns the result of the function it
        called.
        c                      dS )Nr   rM   rM   r#   r!   r{  z:SuppressedWarningsTests.test_passThrough.<locals>.<lambda>  s    A r#   r   N)r   r  r+   s    r!   test_passThroughz(SuppressedWarningsTests.test_passThrough  s2    
 	77IIFFJJJJJr#   c                     di fdi fg}|                      |d            t          j        d           |                     dgd |                                 D                        dS )zk
        Once C{runWithWarningsSuppressed} has returned, it no longer
        suppresses warnings.
        r  r  c                      d S r   rM   rM   r#   r!   r{  z<SuppressedWarningsTests.test_noSideEffects.<locals>.<lambda>  s     r#   r  c                     g | ]
}|d          S r  rM   r  s     r!   r  z>SuppressedWarningsTests.test_noSideEffects.<locals>.<listcomp>  s    )U)U)U1!I,)U)U)Ur#   Nr  r  s     r!   test_noSideEffectsz*SuppressedWarningsTests.test_noSideEffects  sz    
 *2.1F0KL&&w===l###,)U)U@R@R@T@T)U)U)UVVVVVr#   N)rJ   rK   rL   r_   staticmethodr   r  r  r  r  r  rM   r#   r!   r  r    sz          !-T-K L L3 3 3Y Y YK K KW W W W Wr#   r  c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )FancyStrMixinTestsz*
    Tests for L{util.FancyStrMixin}.
    c                      G d dt           j                  }|                     t           |                      d           dS )z
        If C{showAttributes} is set to a sequence of strings, C{__str__}
        renders using those by looking them up as attributes on the object.
        c                       e Zd ZdZdZdZdS )6FancyStrMixinTests.test_sequenceOfStrings.<locals>.Foofirstsecondr   helloNrJ   rK   rL   showAttributesr  r  rM   r#   r!   rV   r            0NEFFFr#   rV   z<Foo first=1 second='hello'>Nr   FancyStrMixinr   strr   rV   s     r!   test_sequenceOfStringsz)FancyStrMixinTests.test_sequenceOfStrings  sZ    	 	 	 	 	$$ 	 	 	
 	SSUU%CDDDDDr#   c                      G d dt           j                  }|                     dt           |                                 dS )a  
        If C{showAttributes} has an item that is a 2-tuple, C{__str__} renders
        the first item in the tuple as a key and the result of calling the
        second item with the value of the attribute named by the first item as
        the value.
        c                   $    e Zd Zddd ffZdZdZdS ).FancyStrMixinTests.test_formatter.<locals>.Foor  r  c                 2    t          | d d d                   S )Nrr  )r   )values    r!   r{  z7FancyStrMixinTests.test_formatter.<locals>.Foo.<lambda>  s    U44R4[@Q@Q r#   r  worldNr  rM   r#   r!   rV   r    s+        %2Q2Q'RSNEFFFr#   rV   z"<Foo first='hello' second='dlrow'>Nr  r  s     r!   test_formatterz!FancyStrMixinTests.test_formatter  sZ    	 	 	 	 	$$ 	 	 	
 	=s3355zzJJJJJr#   c                      G d dt           j                  }|                     t           |                      d           dS )a&  
        If C{showAttributes} has an item that is a 3-tuple, C{__str__} renders
        the second item in the tuple as a key, and the contents of the
        attribute named in the first item are rendered as the value. The value
        is formatted using the third item in the tuple.
        c                       e Zd ZdZdZdZdS )-FancyStrMixinTests.test_override.<locals>.Foo)r  )r  2ndz%.1fr   gS @Nr  rM   r#   r!   rV   r    s        ANEFFFr#   rV   z<Foo first=1 2nd=2.1>Nr  r  s     r!   test_overridez FancyStrMixinTests.test_override  sZ    	 	 	 	 	$$ 	 	 	
 	SSUU%<=====r#   c                      G d dt           j                  }|                     t           |                      d           dS )z_
        If C{fancybasename} is present, C{__str__} uses it instead of the class name.
        c                       e Zd ZdZdS )2FancyStrMixinTests.test_fancybasename.<locals>.FooBarN)rJ   rK   rL   fancybasenamerM   r#   r!   rV   r    s        !MMMr#   rV   z<Bar>Nr  r  s     r!   test_fancybasenamez%FancyStrMixinTests.test_fancybasename  sY    
	" 	" 	" 	" 	"$$ 	" 	" 	" 	SSUUW-----r#   c                      G d dt           j                  } |            }|                     t          |          t	          |                     dS )zE
        C{__repr__} outputs the same content as C{__str__}.
        c                       e Zd ZdZdZdZdS ))FancyStrMixinTests.test_repr.<locals>.Foor  r   r  Nr  rM   r#   r!   rV   r    r  r#   rV   N)r   r  r   r  r   )r   rV   objs      r!   	test_reprzFancyStrMixinTests.test_repr  sd    
	 	 	 	 	$$ 	 	 	
 ceeS499-----r#   N)	rJ   rK   rL   r_   r  r  r  r  r  rM   r#   r!   r  r    so         E E EK K K> > >. . .. . . . .r#   r  c                   <    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	S )

PadToTestsz"
    Tests for L{util.padTo}.
    c                 d    t          j        dg           }|                     dgdz  |           dS )ze
        L{None} values can be added to a list to cause it to have a certain
        length.
        r   Nr   padTor   r   paddeds     r!   test_defaultzPadToTests.test_default  s7    
 Ar""$!V,,,,,r#   c                 f    t          j        dg d          }|                     dgdz  |           dS )zg
        A specific value can be added to a list to cause it to have a certain
        length.
        r   r   Nr  r  s     r!   test_specificDefaultValuez$PadToTests.test_specificDefaultValue  s9    
 Ar3''#F+++++r#   c                 f    t          j        dddgd          }|                     g d|           dS )zl
        A list which already has some items has the padding value added after
        those items.
        r   r   r   r  )r   r   r  Nr  r  s     r!   test_padNonEmptyListzPadToTests.test_padNonEmptyList  s;    
 A1vs++f-----r#   c                 X    |                      t          t          j        dddg           dS )z{
        L{util.padTo} can't pad a list if the size requested is smaller than
        the size of the list to pad.
        r   r   N)r4  r5  r   r  r+   s    r!   test_padToSmallerSizez PadToTests.test_padToSmallerSize  s*    
 	*dj!aV<<<<<r#   c                 ~    ddg}t          j        t          |          |          }|                     ||           dS )z
        If the list is already the length indicated by the padding argument
        then a list with the same value is returned.
        r   r   N)r   r  r   r   r   r   r  s      r!   test_alreadyPaddedzPadToTests.test_alreadyPadded  s@    
 ACJJ..'''''r#   c                 ~    ddg}t          j        t          |          |          }|                     ||           dS )z
        If the list is already the length indicated by the padding argument
        then the return value is a copy of the input.
        r   r   N)r   r  r   assertIsNotr   s      r!   test_alreadyPaddedCopiesz#PadToTests.test_alreadyPaddedCopies'  s@    
 ACJJ..'''''r#   c                 `    g }t          j        d|           |                     g |           dS )zO
        L{util.padTo} doesn't modify the input list but makes a copy.
        r   Nr  )r   r   s     r!   test_makeCopyzPadToTests.test_makeCopy0  s7     
1eU#####r#   N)rJ   rK   rL   r_   r  r  r  r  r  r  r  rM   r#   r!   r  r    s         - - -, , ,. . .= = =( ( (( ( ($ $ $ $ $r#   r  )Gr_   rg   os.pathr7   r  r   r  typingr   r   r   r   unittestr   rC   _grpr5   _pwdImportErrortwisted.internetr   twisted.internet.deferr	   twisted.internet.errorr
   twisted.internet.interfacesr   twisted.internet.protocolr   twisted.pythonr   twisted.python.filepathr   twisted.test.test_processr   twisted.trial.unittestr   r   twisted.trial.utilr   r  
executable_asBytesPathr   r   rO   ra   getattrrq   r   r   r   r   
providedByr   r  r  rX  r8  rB  rE  rG  rP  rS  rl  r  r  r  r  r  r  rM   r#   r!   <module>r     s  
 
    



  > > > > > > > > > > > >      
 C
CC    
C
CCC % $ $ $ $ $ + + + + + + . . . . . . 7 7 7 7 7 7 5 5 5 5 5 5       , , , , , , , , , , , , 5 5 5 5 5 5 5 5 3 3 3 3 3 3  --//.J .J .J .J .J .J .J .JbV V V V Vx V V V*( ( ( ( (( ( ( (> GGB$''')FGGCV CV CV CV CVX CV CV HGCVL]' ]' ]' ]' ]' ]' ]' ]'@2 2 2 2 2x 2 2 2.M- M- M- M- M-8 M- M- M-`6 6 6 6 6_ 6 6 6" ""7+++2 7 7 7 7 7x 7 7	 7D+ + + + + + + +.J< J< J< J< J< J< J< J<Z	 	 	 	 	T 	 	 		 	 	 	 	d' 	 	 	    F                 _: _: _: _: _:H _: _: _:D GGB	4(((*IJJnA nA nA nA nAh nA nA KJnAb DNOOI I I I Ih I I POI<( ( ( ( (x ( ( (V)W )W )W )W )Wh )W )W )WXE. E. E. E. E. E. E. E.P<$ <$ <$ <$ <$ <$ <$ <$ <$ <$s   7 	AA