
    BPc`E                         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ZddlmZm	Z	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ZdZ G d	 d
          Z G d d          Z G d d          Z G d de          ZdS )a,  
Any mocking utilities required by testing. Mocking is when you need the test
to exercise a piece of code, but that code may or does call on something
outside of the target code that either takes too long to run, isn't available
during the test running process or simply shouldn't be running at all.
    N)ListTupleAny)MIMEApplication)MIMEMultipart)MIMEText)Parserz--CALLDATA--//--CALLDATA--c                   &    e Zd ZdZddZd Zd ZdS )	CapturezECapture stdout or stderr. Used as `with Capture('stdout') as stream:`stdoutTc                     || _         t          t          |          | _        t	          j                    | _        || _        d S N)io_namegetattrsysoriginalioStringIOstreamswap)selfr   r   s      3/usr/share/inkscape/extensions/inkex/tester/mock.py__init__zCapture.__init__1   s2    W--kmm			    c                 ^    | j         r t          t          | j        | j                   | j        S r   )r   setattrr   r   r   r   s    r   	__enter__zCapture.__enter__7   s*    9 	4Ct{333{r   c                     |8| j         r1| j                            | j                                                   t          t          | j        | j                   d S r   )r   r   writer   getvaluer   r   r   )r   excvalue	tracebacks       r   __exit__zCapture.__exit__<   sM    ?ty?M 4 4 6 6777T\4=11111r   N)r   T)__name__
__module____qualname____doc__r   r   r%    r   r   r   r   .   sL        OO     
2 2 2 2 2r   r   c                   D    e Zd ZdZ ed           ZddZ	 d	dZeZeZ	dS )
ManualVerbosityz/Change the verbosity of the test suite manuallyc                     | j         j        S r   )test_current_resultr   s    r   <lambda>zManualVerbosity.<lambda>F   s    49#< r   TFc                 0    || _         || _        || _        d S r   )r.   okaydots)r   r.   r2   r3   s       r   r   zManualVerbosity.__init__H   s    					r   Nc                     | j         j        | j        c| _        | j         _        | j         j        | j        c| _        | j         _        dS )z+Swap the stored verbosity with the originalN)resultshowAllr2   r3   )r   exc_typeexc_valexc_tbs       r   flipzManualVerbosity.flipM   s>     *.)<di&	4;&&*k&6	#	4;###r   )TF)NNN)
r&   r'   r(   r)   propertyr5   r   r:   r   r%   r*   r   r   r,   r,   C   sd        99X<<==F    37B B B B IHHHr   r,   c                   <     e Zd ZdZg Zd Z fdZ fdZd Z xZ	S )	MockMixina  
    Add mocking ability to any test base class, will set up mock on setUp
    and remove it on tearDown.

    Mocks are stored in an array attached to the test class (not instance!) which
    ensures that mocks can only ever be setUp once and can never be reset over
    themselves. (just in case this looks weird at first glance)

    class SomeTest(MockingMixin, TestBase):
        mocks = [(sys, 'exit', NoSystemExit("Nope!")]
    c                    t          ||          }t          t                    r t          |           rt          |           t          t                    rfd}t          |||           nX.t          t          t          t          t          t          f          rfd}t          |||           nt          ||           |||dfS )zGSetup the mock here, taking name and function and returning (name, old)c                  N     t                    t                              r   )typestr)args2kw2news     r   _error_functionz,MockMixin.setUpMock.<locals>._error_functiono   s    d3iiC)))r   Nc                      S r   r*   )argskwrD   s     r   _value_functionz,MockMixin.setUpMock.<locals>._value_functionu   s    
r   F)
r   
isinstancerA   hasattr	Exceptionr   intfloatlisttuple)r   ownernamerD   oldrE   rI   s      `   r   	setUpMockzMockMixin.setUpMockg   s    eT""c3 	)tS!! )dC((c9%% 	&* * * * * E41111[JsS#udE,JKK[     E41111E4%%% tS%((r   c                     t                                                       t          | j                  D ]?\  }}t	          |          dk    rt          j        d           - | j        | | j        |<   @dS )z9For each mock instruction, set it up and store the return   z9Mock was already set up, so it wasn't cleared previously!N)supersetUp	enumeratemockslenloggingerrorrT   )r   xmock	__class__s      r   rX   zMockMixin.setUp   s|     ,, 	2 	2GAt4yyA~~O   *DND1DJqMM	2 	2r   c                 *   t                                                       	 t          | j                  D ]6\  }\  }}}}||t	          ||          f| j        |<   t          |||           7dS # t          $ r t          j        d           Y dS w xY w)zCFor each returned stored, tear it down and restore mock instructionz)Was never mocked, did something go wrong?N)	rW   tearDownrY   rZ   r   r   
ValueErrorr\   warning)r   r^   rQ   rR   rS   _r`   s         r   rb   zMockMixin.tearDown   s    	I,5dj,A,A * *((E4a!&geT.B.B C
1tS))))* *  	I 	I 	IOGHHHHHH	Is   AA0 0BBc                 H    | j         D ]}|d         |k    r
|d         c S d S )zGet the original caller      c                      d S r   r*   r*   r   r   r0   z$MockMixin.old_call.<locals>.<lambda>   s    t r   )rZ   )r   rR   args      r   old_callzMockMixin.old_call   s:    : 	 	C1v~~1v |r   )
r&   r'   r(   r)   rZ   rT   rX   rb   rk   __classcell__r`   s   @r   r=   r=   X   s        
 
 E) ) )0	2 	2 	2 	2 	2I I I I I      r   r=   c                        e Zd ZdZej        ddfeddfgZg Z fdZ	e
d             Zd Zd	 Zd
 Zd Zd Zd Zd ZddZed             ZddZd Z	 ddZddZ xZS )MockCommandMixinz
    Replace all the command functions with testable replacements.

    This stops the pipeline and people without the programs, running into problems.
    _call	mock_callmkdtemprecord_tempdirc                     t                                                       ddlm} |                                 |_        d S )Nrg   TestCase)rW   rX    rv   datadir_mockdatadir)r   rv   r`   s     r   rX   zMockCommandMixin.setUp   s>     	 $r   c                 X    ddl m} t          j                            |j        d          S )z6Returns the location of all the mocked command resultsrg   ru   cmd)rw   rv   ospathjoinry   )clsrv   s     r   cmddirzMockCommandMixin.cmddir   s/     	w||H15999r   c                      |                      d          |i |}| j                            t          j                            |                     |S )z$Record any attempts to make tempdirsrr   )rk   recorded_tempdirsappendr|   r}   realpath)r   rG   kwargsnewdirs       r   rs   zMockCommandMixin.record_tempdir   sN    )y))4:6::%%bg&6&6v&>&>???r   c                     d }	 | j         D ]} |||d          } |||d          }|D ],} |||t          j                            |                    }-n# t          t
          f$ r Y nw xY w|S )z'Clean a string of any files or tempdirsc                     t          | t                    r|                               } nfd| D             } | S )Nc                 <    g | ]}|                               S r*   )replace).0ireplacedreplacements     r   
<listcomp>zAMockCommandMixin.clean_paths.<locals>.replace.<locals>.<listcomp>   s'    KKKq!))Hk::KKKr   )rJ   rA   r   )indatar   r   s    ``r   r   z-MockCommandMixin.clean_paths.<locals>.replace   sM    &#&& L+>>KKKKKFKKKMr   .)r   r|   r}   basenameUnicodeDecodeError	TypeError)r   datafilesr   fdirfnames         r   clean_pathszMockCommandMixin.clean_paths   s    	 	 		. 2 2wtT3//tS11 E EwtUBG,<,<U,C,CDDE"I. 	 	 	D	s   AA A-,A-c           	      `   t          g           }| j        D ]}t          j                            |          s"t          j        |          D ]_}|dv rt          j                            ||          }|                    |dt          j                            |           z              `|S )z=Returns a set() of all files currently in any of the tempdirs)r   z..;)	setr   r|   r}   isdirlistdirr~   addgetmtime)r   retr   r   r}   s        r   get_all_tempfilesz"MockCommandMixin.get_all_tempfiles   s    "gg* 		= 		=D7==&& D)) = =K''w||D%00 ;27#3#3D#9#9;;;<<<<= 
r   c                 P    | r#|r!|rt           j                            d          S dS )z"Return true if the mock is ignoredNO_MOCK_COMMANDSF)r|   environget)r   programarglsts      r   ignore_command_mockz$MockCommandMixin.ignore_command_mock   s2     	6G 	6 	6:>>"4555ur   c                 j   |                     dd          }t          |          }t          t                    }t                              |          |d<   |                     |||          \  }}t          j        j	        |g|R i |dd         }| 
                    |||z             }d                    |          }	|	                                |d<   |e| 
                    |||z                                 dd	                              d
d          }
|                    t          |
dd                     |                                }|                    dd	          }|                    dd	          }|                    dd          }d|v r|                    dd          }t#          j        |                    d                                                    }|                     ||          r|||d<   |                                 } |                     d          |g|R i |}|t          |                                 |z
            z  }d |D             }t          t                    }t                              |          |d<   |	|d<   |                     |||||           |                     |||d           |S 	 |                     |||          S # t6          $ r:}|                     |||d           t7          d| d| d| d|	 d	          |d}~ww xY w)z
        Replacement for the inkex.command.call() function, instead of calling
        an external program, will compile all arguments into a hash and use the
        hash to find a command result.
        stdinN)boundaryProgramrg    	Arguments

.\./plainutf-8z

z
 verbz; r   rp   c                 F    g | ]}|                     d d          d         S )r   rg   r   )rsplit)r   outs     r   r   z.MockCommandMixin.mock_call.<locals>.<listcomp>  s+    @@@szz#q))!,@@@r   keyzbad-keyzProblem loading call: /z~ use the environment variable NO_MOCK_COMMANDS=1 to call out to the external program and generate the mock call file for call r   )poprO   r   FIXED_BOUNDARYro   get_program_nameadd_call_filesinkexcommandto_args_sortedr   r~   stripr   attachr   	as_stringhashlibmd5encode	hexdigestr   r   rk   	save_callsave_key	load_callIOError)r   r   rG   r   r   msginputsoutputsr   argstrcleaninkeystrr   beforer   replyerrs                    r   rq   zMockCommandMixin.mock_call   ss    

7D))Dzz ^444)::7CCI --c4@@-gGGGGGGK!!&&7*:;;&!!!<<>>K   (899&&%% 
 JJx'::;;;----s++V^^D#..Fk&--0011;;==##GV44 	  "'w++--F+T]]7++GEdEEEfEEFtD2244v=>>>G@@@@@G
 ">:::E/@@IIE)!'E+NN7C%@@@MM'3666M	>>'3888 	 	 	MM'3	:::C C C3 C C/6C C9?C C C  		s   K. .
L285L--L2c                 R   t          |                                d           }g }|D ]V}t          |t          t          f          r|                    |           4|                    t          |                     W|D ]s\  }}t          |t          t          f          r,|D ](}	|	dur"|                    t          |	                     )M|dur"|                    t          |                     tg g g}
|D ]}t          j        	                    |          r2|
d                             |           | 
                    ||           St          j                            t          j                            |                    r|
d                             |           |
S )z
        Gather all files, adding input files to the msg (for hashing) and
        output files to the returned files list (for outputting in debug)
        c                     | d         S )Nr   r*   )r   s    r   r0   z1MockCommandMixin.add_call_files.<locals>.<lambda>;  s
    ad r   r   Tr   rg   )sorteditemsrJ   rP   rO   r   rA   r|   r}   isfileadd_call_filer   dirname)r   r   rG   r   loargsvaluesrj   re   r#   valr   s              r   r   zMockCommandMixin.add_call_files5  s    NN;;; 	( 	(C#t}-- (c""""c#hh''''  	* 	*JQ%%// *  0 0C$c#hh///0 d""c%jj))) R 	' 	'Ew~~e$$ 'a&&&""3....rwu5566 'a&&&r   c                    t           j                            |          }t          |d          5 }|                    d          r<|                     |                                                    d          g           }n:|                                }	 |                                }n# t          $ r Y nw xY wt          |t                    r*|                    dd                              dd          }t          ||          }d	d	d	           n# 1 swxY w Y   d
|d<   ||d<   |                    |           d	S )z+Add a single file to the given mime messagerbz.svgutf8r   r   r   r   )NameN
attachmentContent-DispositionFilename)r|   r}   r   openendswithr   readdecoder   rJ   rA   r   r   r   )r   r   filenamer   fhlr#   parts          r   r   zMockCommandMixin.add_call_fileV  st     **(D!! 	6S  (( (():):6)B)BBGG

!LLNNEE)   D%%% Ifd33;;E4HH"5u555D	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 '3"# Z

4s7   A&DB,+D,
B96D8B99ADDDFc                     |                      ||          }t          j                            ||dz             }|s1t          j                            |          st          d|           |S )zD
        Get the filename for the call testing information.
        createz.msgz!Attempted to find call test data )get_call_pathr|   r}   r~   r   r   )r   r   r   r   r}   r   s         r   get_call_filenamez"MockCommandMixin.get_call_filenamej  sp     !!'&!99T3<00 	EbgnnU33 	ECcCCDDDr   c                 4    | t           j        j        k    rdS | S )z*Takes a program and returns a program nameinkscape)r   r   INKSCAPE_EXECUTABLE_NAME)r   s    r   r   z!MockCommandMixin.get_program_namet  s     em<<<:r   Tc                 0   t           j                            |                                 t                              |                    }t           j                            |          s,|rt          j        |           nt          d| d|           |S )z1Get where this program would store it's test dataz;A test is attempting to use an external program in a test: zb; but there is not a command data directory which should contain the results of the command here: )	r|   r}   r~   r   ro   r   r   makedirsr   )r   r   r   command_dirs       r   r   zMockCommandMixin.get_call_path{  s    gllKKMM+<<WEE
 
 w}}[)) 	 K((((UU UGRU U  
 r   c                    |                      ||d          }t          |d          5 }t                                          |                                                    d                    }ddd           n# 1 swxY w Y   d}|                                D ][}d|                    dd          v r|d	         }	|D ]j}
|
                    |	          rSt          |
d
          5 }|	                    |
                    d                     d}ddd           n# 1 swxY w Y   k|| j        D ]}t          j                            |          rot          t          j                            ||	          d
          5 }|	                    |
                    d                     ddd           n# 1 swxY w Y   -|                                dk    r|
                    d          }]|S )z%
        Load the given call
        Fr   r   r   Nr   r   rw   r   wbT)r   z
text/plain)r   r   EmailParserparsestrr   r   walkr   r   r    get_payloadr   r|   r}   r   r~   get_content_type)r   r   r   r   r   r   r   r   r   	base_nameout_filer   s               r   r   zMockCommandMixin.load_call  s    &&wE&BB% 	E#--(():):7)C)CDDC	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E HHJJ 	7 	7Dtxx(=rBBBB ,	 % ( (H((33 (!(D11 (SIId&6&6d&6&C&CDDD#'D( ( ( ( ( ( ( ( ( ( ( ( ( ( ( # !% 6 I I7==.. I!%bgll4&C&CT!J!J Ic #		$*:*:$*:*G*G H H HI I I I I I I I I I I I I I I&&((L88)))66s6   AA<<B B *,D""D&)D&*F<<G G outputc                    |K|                                 r7|                    t          |                    d          dd                     t	          |          D ]}t
          j                            |          r|                     ||           8t          ddd          }|	                    dt
          j        
                    |                     |                    |           |                     ||d          dz   |z   }t          |d	          5 }	|	                    |                                                    d                     ddd           dS # 1 swxY w Y   dS )
z
        Saves the results from the call into a debug output file, the resulting files
        should be a Mime msg file format with each attachment being one of the input
        files as well as any stdin and arguments used in the call.
        Nr   r   zMissing Filer   Tr   r   r   )r   r   r   r   r   r|   r}   r   r   
add_headerr   r   r   r    r   r   )
r   r   r   r   r   r   extr   r   r   s
             r   r   zMockCommandMixin.save_call  s    &,,..JJxg 6 6IIJJJZZ 	! 	!Ew~~e$$ !""3....AA
BG,<,<U,C,CDDD

4    &&wD&AACG#M% 	7#IIcmmoo,,W55666	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7s   ;E%%E),E)r   c                 &   t           j                            d          rq|                     ||d          dz   |z   }t	          |d          5 }|                    |                    d                     ddd           dS # 1 swxY w Y   dS dS )z2Save the key file if we are debugging the key data	DEBUG_KEYTr   r   r   r   N)r|   r   r   r   r   r    r   )r   r   r   r   r  r   r   s          r   r   zMockCommandMixin.save_key  s    :>>+&& 	2**7C*EEKcQEeT"" 2c		&--001112 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2	2 	2s   )BBB)F)T)r  r   )r&   r'   r(   r)   r   r   tempfilerZ   r   rX   classmethodr   rs   r   r   r   rq   r   r   r   staticmethodr   r   r   r   r   rl   rm   s   @r   ro   ro      sr         
-	9./E / / / / / : : [:    (     J J JX  B  (      \      > 5=7 7 7 722 2 2 2 2 2 2 2r   ro   )r)   r   r|   r   r\   r   r
  typingr   r   r   email.mime.applicationr   email.mime.multipartr   email.mime.textr   email.parserr	   r   inkex.commandr   r   r   r,   r=   ro   r*   r   r   <module>r     s  (  
			 				 



    # # # # # # # # # # 2 2 2 2 2 2 . . . . . . $ $ $ $ $ $ . . . . . .     .2 2 2 2 2 2 2 2*       *A A A A A A A AHk2 k2 k2 k2 k2y k2 k2 k2 k2 k2r   