U
    1ei.                     @   s   d Z ddlZddlZddlZddlmZ eeZG dd dej	Z	G dd dej
ZG dd	 d	ejZG d
d dejZedZG dd dejeZdS )a  Nose Plugin that supports IPython doctests.

Limitations:

- When generating examples for use as doctests, make sure that you have
  pretty-printing OFF.  This can be done either by setting the
  ``PlainTextFormatter.pprint`` option in your configuration file to  False, or
  by interactively disabling it with  %Pprint.  This is required so that IPython
  output matches that of normal Python, which is used by doctest for internal
  execution.

- Do not rely on specific prompt numbers for results (such as using
  '_34==True', for example).  For IPython tests run via an external process the
  prompt numbers may be different, and IPython tests run as normal python code
  won't even have these special _NN variables set at all.
    N)modified_envc                       s   e Zd Z fddZ  ZS )DocTestFinderc                    sH   t  |||||}tt|ddrD|d k	rD|jD ]}d|jtj< q2|S )NZ__skip_doctest__FT)super	_get_testboolgetattrZexamplesoptionsdoctestSKIP)selfobjnamemoduleZglobssource_linestestZexample	__class__ D/tmp/pip-unpacked-wheel-3hxk2k58/IPython/testing/plugin/ipdoctest.pyr   )   s
    
zDocTestFinder._get_test)__name__
__module____qualname__r   __classcell__r   r   r   r   r   (   s   r   c                   @   s"   e Zd ZdZedZdd ZdS )IPDoctestOutputCheckerzSecond-chance checker with support for random tests.

    If the default comparison doesn't pass, this checker looks in the expected
    output string for flags that tell us to ignore the output.
    z#\s*random\s+c                 C   s*   t j| |||}|s&| j|r&dS |S )zCheck output, accepting special markers embedded in the output.

        If the output didn't pass the default validation but the special string
        '#random' is included, we accept it.T)r	   OutputCheckercheck_output	random_research)r   wantgotZoptionflagsretr   r   r   r   <   s    z#IPDoctestOutputChecker.check_outputN)r   r   r   __doc__recompiler   r   r   r   r   r   r   3   s   
r   c                   @   s   e Zd ZdS )	IPExampleN)r   r   r   r   r   r   r   r$   O   s    r$   c                   @   s   e Zd ZdZdZdZdZdZdZe	
eeeeef e	je	jB Ze	
eeeeef e	je	jB Ze	
dZdd	 ZdddZdddZdd ZdS )IPDocTestParserz
    A class used to parse strings containing doctest examples.

    Note: This is a version modified to properly recognize IPython input and
    convert any IPython examples into valid Python ones.
    z>>>z\.\.\.zIn\ \[\d+\]:z\ \ \ \.\.\.+:a]  
        # Source consists of a PS1 line followed by zero or more PS2 lines.
        (?P<source>
            (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*)    # PS1 line
            (?:\n           [ ]*  (?P<ps2> %s) .*)*)  # PS2 lines
        \n? # a newline
        # Want consists of any non-blank lines that do not start with PS1.
        (?P<want> (?:(?![ ]*$)    # Not a blank line
                     (?![ ]*%s)   # Not a line starting with PS1
                     (?![ ]*%s)   # Not a line starting with PS2
                     .*$\n?       # But any other line
                  )*)
                  z#\s*all-random\s+c                 C   s.   t j|}t| dkr&t |S |S dS )z/Convert input IPython source into valid Python.   N)_ipZinput_transformer_managerZtransform_celllen
splitlinesZ	prefilter)r   sourceblockr   r   r   ip2py   s    
zIPDocTestParser.ip2py<string>c                    sT  |  }| |  dkr8d fdd|dD }g }d\}}| j|rVd}nd}d}t| j|}|rzt	j
}	nt| j|}t}	d	}|D ]}
||||
   ||d||
 7 }| |
|||\}}}}||7 }| |s||	|||| t|
d
 |d ||d|
 |
 7 }|
 }q|||d  |S )a=  
        Divide the given string into examples and intervening text,
        and return them as a list of alternating Examples and strings.
        Line numbers for the Examples are 0-based.  The optional
        argument `name` is a name identifying this string, and is only
        used for error messages.
        r   
c                    s   g | ]}| d  qS Nr   ).0lZ
min_indentr   r   
<listcomp>   s     z)IPDocTestParser.parse.<locals>.<listcomp>)r   r   z	
# random FTindent)linenor5   r   N)
expandtabsZ_min_indentjoinsplit_RANDOM_TESTr   list_EXAMPLE_RE_PYfinditerr	   Example_EXAMPLE_RE_IPr$   appendstartcount_parse_exampleZ_IS_BLANK_OR_COMMENTr(   groupend)r   stringr   outputZcharnor6   Zrandom_markerr,   Ztermsr>   mr*   r   r   exc_msgr   r2   r   parse   s@    


zIPDocTestParser.parseFc                    sT  t |d |dd}|d}|d}t || | || |rp| |dd d  | || d fd	d
|D }|r| |}|d}	|	d}
t |
dkrtd|
d r|
d= | |
d  ||t |  t	dd|
d |
d< d fdd
|
D }	| j
|	}|r6|d}nd}| |||}|||	|fS )a7  
        Given a regular expression match from `_EXAMPLE_RE` (`m`),
        return a pair `(source, want)`, where `source` is the matched
        example's source code (with prompts and indentation stripped);
        and `want` is the example's expected output (with indentation
        stripped).

        `name` is the string's name, and `lineno` is the line number
        where the example starts; both are used for error messages.

        Optional:
        `ip2py`: if true, filter the input via IPython to convert the syntax
        into valid python.
        r5   r*   r.   ps1ps2r&   N c                    s    g | ]}|  d  d qS )r&   Nr   )r0   slr5   ps1_lenr   r   r3      s     z2IPDocTestParser._parse_example.<locals>.<listcomp>r   z *$zOut\[\d+\]: \s*?\n?r4   r   c                    s   g | ]}| d  qS r/   r   )r0   Zwl)r5   r   r   r3      s     msg)r(   rD   r9   _check_prompt_blankZ_check_prefixr8   r,   r"   matchsubZ_EXCEPTION_REZ_find_options)r   rH   r   r6   r,   r   rK   rL   r*   r   Z
want_linesrI   r   r   rO   r   rC      s4    

 



zIPDocTestParser._parse_examplec           
      C   sb   || }|d }t |D ]D\}}	t|	|kr|	| dkrtd|| d ||	|| |	f qdS )a  
        Given the lines of a source string (including prompts and
        leading indentation), check to make sure that every prompt is
        followed by a space character.  If any line is not followed by
        a space character, then raise ValueError.

        Note: IPython-modified version which takes the input prompt length as a
        parameter, so that prompts of variable length can be dealt with.
        r&   rM   z8line %r of the docstring for %s lacks blank after %s: %rN)	enumerater(   
ValueError)
r   linesr5   r   r6   rP   Z	space_idxZmin_leniliner   r   r   rS     s    

 z#IPDocTestParser._check_prompt_blankN)r-   )F)r   r   r   r!   Z_PS1_PYZ_PS2_PYZ_PS1_IPZ_PS2_IPZ_RE_TPLr"   r#   	MULTILINEVERBOSEr<   r?   r:   r,   rJ   rC   rS   r   r   r   r   r%   R   s"   



D
Ar%   r
   c                       s"   e Zd ZdZd fdd	Z  ZS )IPDocTestRunnerzKTest runner that synchronizes the IPython namespace with test globals.
    NTc              
      s<   t ddd$ tt| ||||W  5 Q R  S Q R X d S )N80Z24)COLUMNSLINES)r   r   r]   run)r   r   ZcompileflagsoutZclear_globsr   r   r   ra   '  s      zIPDocTestRunner.run)NNT)r   r   r   r!   ra   r   r   r   r   r   r]   #  s   r]   )r!   r	   loggingr"   Ztestpathr   	getLoggerr   logr   r   r   r>   r$   ZDocTestParserr%   Zregister_optionflagr
   ZDocTestRunnerobjectr]   r   r   r   r   <module>   s   
 O
