B
    \7                 @   s  d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	m
Z
mZ ddlmZ yddlmZ dZW n ek
r   dZY nX 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 ddlmZ  ddlm!Z! ej"dkre!j#ne j$Z%e%dd Z&dd Z'de'_(dd Z)dd Z*d7ddZ+d8ddZ,d9d d!Z-G d"d# d#e.Z/d$Z0d%d& Z1eZ2e3e4dZ5d'Z6G d(d) d)e.Z7d*Z8G d+d, d,e7Z9ed-d. Z:ed/d0 Z;d1d2 Z<d:d3d4Z=d;d5d6Z>dS )<zWGeneric testing tools.

Authors
-------
- Fernando Perez <Fernando.Perez@berkeley.edu>
    N)contextmanager)StringIO)PopenPIPE)patchTF)Config)get_output_error_code)list_strings)temp_pyfileTee)	py3compat   )
decorators)skipdoctestZwin32c                s*   t |}tj| d   fdd|D S )aP  Make full paths for all the listed files, based on startPath.

    Only the base part of startPath is kept, since this routine is typically
    used with a script's ``__file__`` variable as startPath. The base of startPath
    is then prepended to all the listed files, forming the output list.

    Parameters
    ----------
    startPath : string
      Initial path to use as the base for the results.  This path is split
      using os.path.split() and only its first component is kept.

    files : string or list
      One or more files.

    Examples
    --------

    >>> full_path('/foo/bar.py',['a.txt','b.txt'])
    ['/foo/a.txt', '/foo/b.txt']

    >>> full_path('/foo',['a.txt','b.txt'])
    ['/a.txt', '/b.txt']

    If a single file is given, the output is still a list::

        >>> full_path('/foo','a.txt')
        ['/a.txt']
    r   c                s   g | ]}t j |qS  )ospathjoin).0f)baser   4lib/python3.7/site-packages/IPython/testing/tools.py
<listcomp>O   s    zfull_path.<locals>.<listcomp>)r	   r   r   split)Z	startPathfilesr   )r   r   	full_path-   s     r   c             C   s   t d| t j}|r.t|d}d}||fS t d| t j}|r\d}t|d}||fS t d| t j}|rt|d}t|d}||fS dS )a  Parse the output of a test run and return errors, failures.

    Parameters
    ----------
    txt : str
      Text output of a test run, assumed to contain a line of one of the
      following forms::

        'FAILED (errors=1)'
        'FAILED (failures=1)'
        'FAILED (errors=1, failures=1)'

    Returns
    -------
    nerr, nfail
      number of errors and failures.
    z^FAILED \(errors=(\d+)\)r   r   z^FAILED \(failures=(\d+)\)z(^FAILED \(errors=(\d+), failures=(\d+)\)   )r   r   )research	MULTILINEintgroup)ZtxtZerr_mZnerrZnfailZfail_mZboth_mr   r   r   parse_test_outputR   s"    r"   c               C   s   dddddgS )zEReturn a valid default argv for creating testing instances of ipythonz--quickz--colors=NoColorz--no-term-titlez--no-bannerz--autocall=0r   r   r   r   r   default_argv   s    r#   c              C   sJ   t  } d| j_d| j_d| j_tjddd}|j| j	_
|  d| j	_| S )z6Return a config object with good defaults for testing.ZNoColor)Fr   ztest_hist.sqliteF)suffixdeletei'  )r   ZTerminalInteractiveShellZcolorsZ TerminalTerminalInteractiveShellZ
term_titleZautocalltempfileZNamedTemporaryFilenameZHistoryManagerZ	hist_filecloseZdb_cache_size)Zconfigr   r   r   r   default_config   s    
r)   c             C   s   t jddg}| rd|}|S )aW  
    Return appropriate IPython command line name. By default, this will return
    a list that can be used with subprocess.Popen, for example, but passing
    `as_string=True` allows for returning the IPython command as a string.

    Parameters
    ----------
    as_string: bool
        Flag to allow to return the command as a string.
    z-mZIPython )sys
executabler   )Z	as_stringipython_cmdr   r   r   get_ipython_cmd   s    
r.   r   c             C   s   |dkrg }t  | }tjt}t }tj|| }|| |g }tj }d|d< x(|	 D ]\}	}
t
|
ts`t|	|
 q`W t|ttt|d}|jtd|pdd\}}t|t| }}|rtdd|}||fS )	a  Utility to call 'ipython filename'.

    Starts IPython with a minimal and safe configuration to make startup as fast
    as possible.

    Note that this starts IPython in a subprocess!

    Parameters
    ----------
    fname : str
      Name of file to be executed (should have .py or .ipy extension).

    options : optional, list
      Extra command-line flags to be passed to IPython.

    commands : optional, list
      Commands to send in on stdin

    Returns
    -------
    ``(stdout, stderr)`` of ipython subprocess.
    NignoreZPYTHONWARNINGS)stdoutstderrstdinenv
)inputz\x1b\[[^h]+h )r#   r   r   dirname__file__r.   r   environcopyitems
isinstancestrprintr   r   Zcommunicater   encodedecoder   sub)fnameoptionscommandsZcmdargsZtest_dirr-   Z
full_fnameZfull_cmdr3   kvpouterrr   r   r   ipexec   s$     


 rJ   r6   c             C   s   ddl m} t| ||\}}|r^|rN|d|  d|   ntd| |f |d|  d|   dS )a3  Utility to call 'ipython filename' and validate output/error.

    This function raises an AssertionError if the validation fails.

    Note that this starts IPython in a subprocess!

    Parameters
    ----------
    fname : str
      Name of the file to be executed (should have .py or .ipy extension).

    expected_out : str
      Expected stdout of the process.

    expected_err : optional, str
      Expected stderr of the process.

    options : optional, list
      Extra command-line flags to be passed to IPython.

    Returns
    -------
    None
    r   Nr4   z"Running file %r produced error: %r)
nose.toolstoolsrJ   assert_equalr   strip
splitlines
ValueError)rB   Zexpected_outZexpected_errrC   rD   ntrH   rI   r   r   r   ipexec_validate   s    *rR   c               @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )TempFileMixinzcUtility class to create temporary Python/IPython files.

    Meant as a mixin class for test cases..pyc             C   s8   t ||\}}t| dsg | _| j||f || _dS )zMake a valid python temp file.tmpsN)r
   hasattrrU   appendrB   )selfsrcZextrB   r   r   r   r   mktmp  s
    
zTempFileMixin.mktmpc             C   sF   t | drBx6| jD ],\}}|  yt| W q   Y qX qW d S )NrU   )rV   rU   r(   r   unlink)rX   r   rB   r   r   r   tearDown  s    
zTempFileMixin.tearDownc             C   s   | S )Nr   )rX   r   r   r   	__enter__%  s    zTempFileMixin.__enter__c             C   s   |    d S )N)r\   )rX   exc_type	exc_value	tracebackr   r   r   __exit__(  s    zTempFileMixin.__exit__N)rT   )__name__
__module____qualname____doc__rZ   r\   r]   ra   r   r   r   r   rS   	  s
   
rS   z8Testing {0}

In:
  {1!r}
Expected:
  {2!r}
Got:
  {3!r}
c             C   sN   t | dt | dd}x4|D ],\}}| |}||kstt||||qW dS )a  Utility function for the common case of checking a function with a
    sequence of input/output pairs.

    Parameters
    ----------
    func : callable
      The function to be tested. Should accept a single argument.
    pairs : iterable
      A list of (input, expected_output) tuples.

    Returns
    -------
    None. Raises an AssertionError if any output does not match the expected
    value.
    Z	func_namerb   z	<unknown>N)getattrAssertionErrorpair_fail_msgformat)funcZpairsr'   ZinpZexpectedrH   r   r   r   check_pairs3  s    rk   zEDid not find {0!r} in printed output (on {1}):
-------
{2!s}
-------
c               @   s*   e Zd ZdZdddZdd Zdd	 Zd
S )AssertPrintszContext manager for testing that code prints certain text.

    Examples
    --------
    >>> with AssertPrints("abc", suppress=False):
    ...     print("abcd")
    ...     print("def")
    ...
    abcd
    def
    r0   Tc             C   s0   || _ t| j ttfr | j g| _ || _|| _d S )N)sr<   r=   _re_typechannelsuppress)rX   rm   ro   rp   r   r   r   __init___  s
    
zAssertPrints.__init__c             C   sH   t t| j| _t | _t| j| jd| _tt| j| j	r<| jn| j d S )N)ro   )
rf   r+   ro   orig_stream
MyStringIObufferr   teesetattrrp   )rX   r   r   r   r]   f  s    zAssertPrints.__enter__c             C   s   z|d k	rdS | j   tt| j| j | j }xV| jD ]L}t	|t
rj||stt|j| j|q:||ks:tt|| j|q:W dS | j   X d S )NF)ru   flushrv   r+   ro   rr   rt   getvaluerm   r<   rn   r   rg   notprinted_msgri   patternr(   )rX   etypevaluer`   printedrm   r   r   r   ra   l  s    


" zAssertPrints.__exit__N)r0   T)rb   rc   rd   re   rq   r]   ra   r   r   r   r   rl   S  s   
rl   z>Found {0!r} in printed output (on {1}):
-------
{2!s}
-------
c               @   s   e Zd ZdZdd ZdS )AssertNotPrintszcContext manager for checking that certain output *isn't* produced.

    Counterpart of AssertPrintsc             C   s   z|d k	r| j   dS | j   tt| j| j | j }xV| j	D ]L}t
|trt||rtt|j| j|qD||ksDtt|| j|qDW dS | j   X d S )NF)ru   r(   rw   rv   r+   ro   rr   rt   rx   rm   r<   rn   r   rg   printed_msgri   rz   )rX   r{   r|   r`   r}   rm   r   r   r   ra     s    



zAssertNotPrints.__exit__N)rb   rc   rd   re   ra   r   r   r   r   r~     s   r~   c              c   s4   ddl m}  | j}dd | _z
d V  W d || _X d S )Nr   )warnc              _   s   d S )Nr   )akwr   r   r   <lambda>  s    zmute_warn.<locals>.<lambda>)IPython.utilsr   )r   Z	save_warnr   r   r   	mute_warn  s    

r   c          	   c   s*   t | d  z
dV  W dt|  X dS )zM Create an empty, named, temporary file for the duration of the context.
    wN)openr(   r   r[   )r'   r   r   r   make_tempfile  s    
r   c                s    t |  d fdd	}td|S )a  Temporarily replace the input() function to return the given values

    Use as a context manager:

    with fake_input(['result1', 'result2']):
        ...

    Values are returned in order. If input() is called again after the last value
    was used, EOFError is raised.
    r6   c                s*   yt  S  tk
r$   tdY nX d S )NzNo more inputs given)nextStopIterationEOFError)prompt)itr   r   
mock_input  s    zfake_input.<locals>.mock_inputzbuiltins.input)r6   )iterr   )Zinputsr   r   )r   r   
fake_input  s    r   c             C   sV   t  | dg }t|\}}}t|d| td| td| td| ||fS )z)test that `ipython [subcommand] -h` worksz-hr   	TracebackOptionsz
--help-all)r.   r   rQ   rM   assert_not_in	assert_in)
subcommandcmdrH   rI   rcr   r   r   help_output_test  s    r   c             C   sV   t  | dg }t|\}}}t|d| td| td| td| ||fS )z1test that `ipython [subcommand] --help-all` worksz
--help-allr   r   r   ZClass)r.   r   rQ   rM   r   r   )r   r   rH   rI   r   r   r   r   help_all_output_test  s    r   )F)Nr   )r6   Nr   )r6   )r6   )?re   r   r   r+   r&   
contextlibr   ior   
subprocessr   r   Zunittest.mockr   rK   rL   rQ   Zhas_noseImportErrorZtraitlets.config.loaderr   ZIPython.utils.processr   ZIPython.utils.textr	   ZIPython.utils.ior
   r   r   r   r6   r   Zdecr   platformZskip_doctestZ	null_decoZdoctest_decor   r"   Z__test__r#   r)   r.   rJ   rR   objectrS   rh   rk   rs   typecompilern   ry   rl   r   r~   r   r   r   r   r   r   r   r   r   <module>   sX   
%+	

5 
+#.


