o
    NEg"                     @   sF   d Z ddlZddlZddlmZ ddlmZmZ G dd dejZ	dS )ac  Machinery for running and validating transcripts.

If the user wants to run a transcript (see docs/transcript.rst),
we need a mechanism to run each command in the transcript as
a unit test, comparing the expected output to the actual output.

This file contains the class necessary to make that work. This
class is used in cmd2.py::run_transcript_tests()
    N)Tuple   )ansiutilsc                   @   s   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zde	fddZ
de	de	fddZede	de	dededee	eef f
ddZdS )Cmd2TestCasezA unittest class used for transcript testing.

    Subclass this, setting CmdApp, to make a unittest.TestCase class
    that will execute the commands in a transcript file and expect the
    results shown.

    See example.py
    Nc                 C   s2   | j r|   | j j| _t| j j| j _d S d S N)cmdapp_fetchTranscriptsstdout_orig_stdoutr   StdSimself r   i/var/www/eduai.edurigo.com/doc_train/edurigo_ai/Puru/venv/lib/python3.10/site-packages/cmd2/transcript.pysetUp#   s
   
zCmd2TestCase.setUpc                 C   s   | j r
| j| j _d S d S r   )r   r   r
   r   r   r   r   tearDown+   s   zCmd2TestCase.tearDownc                 C   s6   | j rt| j }|D ]\}}| || qd S d S r   )r   sortedtranscriptsitems_test_transcript)r   itsfname
transcriptr   r   r   runTest0   s   zCmd2TestCase.runTestc                 C   s:   i | _ | jjD ]}t|}t| | j |< |  qd S r   )r   r   	testfilesopeniter	readlinesclose)r   r   tfiler   r   r   r	   6   s   
zCmd2TestCase._fetchTranscriptsr   c              
   C   s`  d}d}t t|}|d7 }|s.|| jjs9z	t t|}W n ty-   d}Y nw |d7 }|| jjr|t| jjd  g}zt|}W n tyU   d}Y nw |d7 }|| jjr|	|t| jjd   zt|}W n ty } zd
||d }t||d }~ww |d7 }|| jjsad|}| j|}	| jj }
d}t || jjrd
||||
}| |
  | | |	| qg }t || jjs|	| zt|}W n ty   d}Y nw |d7 }t || jjr|	r| || d|}| |}d	
|||||
}| t||
tjtjB | |rd S d S )
Nr   Fr   T zGTranscript broke off while reading command beginning at line {} with
{}zJCommand indicated application should quit, but more commands in transcriptz>
File {}, line {}
Command was:
{}
Expected: (nothing)
Got:
{}
z7
File {}, line {}
Command was:
{}
Expected:
{}
Got:
{}
)r   strip_stylenext
startswithr   visible_promptStopIterationlencontinuation_promptappendformatjoinonecmd_plus_hooksr
   read
assertTruestripassertFalse_transform_transcript_expectedrematch	MULTILINEDOTALL)r   r   r   line_numfinishedlinecommandexcmsgstopresultstop_msgmessageexpectedr   r   r   r   =   s   

	
	


zCmd2TestCase._test_transcriptsreturnc                 C   s   d}d}	 |  |||d\}}}|dkr"|t||d 7 }	 |S |t||| 7 }|d }|  |||d\}}}|dkrM|||| 7 }|d }n|t||d d 7 }	 |S q)a  Parse the string with slashed regexes into a valid regex.

        Given a string like:

            Match a 10 digit phone number: /\d{3}-\d{3}-\d{4}/

        Turn it into a valid regular expression which matches the literal text
        of the string and the regular expression. We have to remove the slashes
        because they differentiate between plain text and a regular expression.
        Unless the slashes are escaped, in which case they are interpreted as
        plain text, or there is only one slash, which is treated as plain text
        also.

        Check the tests in tests/test_transcript.py to see all the edge
        cases.
        r!   r   TFNr   )_escaped_findr2   escape)r   rA   regexstartfirst_slash_possecond_slash_posr   r   r   r1   }   s$   
z+Cmd2TestCase._transform_transcript_expectedrF   rG   in_regexc                 C   s   	 | d|}|dkrn?|dkrn:||d | dkrI|r.| |||d  7 } | || 7 } n| t|||d  7 } | t|| 7 } |d }nnq| ||fS )a  Find the next slash in {s} after {start} that is not preceded by a backslash.

        If we find an escaped slash, add everything up to and including it to regex,
        updating {start}. {start} therefore serves two purposes, tells us where to start
        looking for the next thing, and also tells us where in {s} we have already
        added things to {regex}

        {in_regex} specifies whether we are currently searching in a regex, we behave
        differently if we are or if we aren't.
        T/rC   r   r   \)findr2   rE   )rF   rA   rG   rJ   posr   r   r   rD      s    

!zCmd2TestCase._escaped_find)__name__
__module____qualname____doc__r   r   r   r   r	   strr   r1   staticmethodintboolr   rD   r   r   r   r   r      s    @/.r   )
rR   r2   unittesttypingr   r!   r   r   TestCaser   r   r   r   r   <module>   s   	