B
    >¶†\_e  ã               @   s–  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 ddl	m
Z
 ddlmZ ddlmZmZmZmZ ddlmZmZ ejdk r˜dd	lmZ ndd	lmZ eZyej d
ZW n ek
rÎ   dZY nX ye d
ZW n e k
rô   dZY nX ejdkpe Z!Z"dd„ Z#G dd„ de$ƒZ%G dd„ de$ƒZ&G dd„ de$ƒZ'G dd„ deƒZ(G dd„ deƒZ)G dd„ deƒZ*G dd„ deƒZ+G dd„ de+ƒZ,dS )z)
Tests for L{pyflakes.scripts.pyflakes}.
é    N)ÚPY2)ÚUnusedImport)ÚReporter)ÚmainÚ	checkPathÚcheckRecursiveÚiterSourceCode)ÚTestCaseÚskipIf)é   )ÚStringIOTF)r   é   c             O   s&   t j|  }t _z
|||ŽS |t _X dS )z?
    Call C{f} with C{sys.stderr} redirected to C{stderr}.
    N)ÚsysÚstderr)r   ÚfÚargsÚkwargsZouter© r   ú5lib/python3.7/site-packages/pyflakes/test/test_api.pyÚwithStderrTo,   s    
r   c               @   s   e Zd ZdZddd„ZdS )ÚNodez
    Mock an AST node.
    r   c             C   s   || _ || _d S )N)ÚlinenoÚ
col_offset)Úselfr   r   r   r   r   Ú__init__;   s    zNode.__init__N)r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   7   s   r   c               @   s2   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ ZdS )ÚSysStreamCapturinga/  
    Context manager capturing sys.stdin, sys.stdout and sys.stderr.

    The file handles are replaced with a StringIO object.
    On environments that support it, the StringIO object uses newlines
    set to os.linesep.  Otherwise newlines are converted from \n to
    os.linesep during __exit__.
    Nc             C   sD   yt |tjdS  tk
r>   d| _|d kr2t ƒ S t |ƒS Y nX d S )N)ÚnewlineT)r   ÚosÚlinesepÚ	TypeErrorÚ_newline)r   Úbufferr   r   r   Ú_create_StringIOK   s    z#SysStreamCapturing._create_StringIOc             C   s   d| _ |  |pd¡| _d S )NFÚ )r$   r&   Ú_stdin)r   Ústdinr   r   r   r   W   s    zSysStreamCapturing.__init__c             C   sD   t j| _t j| _t j| _| jt _|  ¡  t _| _	|  ¡  t _| _
| S )N)r   r)   Ú_orig_stdinÚstdoutÚ_orig_stdoutr   Ú_orig_stderrr(   r&   Ú_stdout_stringioÚ_stderr_stringio)r   r   r   r   Ú	__enter__[   s    zSysStreamCapturing.__enter__c             G   sh   | j  ¡ | _| j ¡ | _| jrLtjdkrL| j dtj¡| _| j dtj¡| _| j	t
_| jt
_| jt
_d S )NÚ
)r.   ÚgetvalueÚoutputr/   Úerrorr$   r!   r"   Úreplacer*   r   r)   r,   r+   r-   r   )r   r   r   r   r   Ú__exit__f   s    zSysStreamCapturing.__exit__)N)r   r   r   r   r&   r   r0   r6   r   r   r   r   r   @   s
   	
r   c               @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚLoggingReporterzK
    Implementation of Reporter that just appends any error to a list.
    c             C   s
   || _ dS )zh
        Construct a C{LoggingReporter}.

        @param log: A list to append log messages to.
        N)Úlog)r   r8   r   r   r   r   x   s    zLoggingReporter.__init__c             C   s   | j  dt|ƒf¡ d S )NÚflake)r8   ÚappendÚstr)r   Úmessager   r   r   r9   €   s    zLoggingReporter.flakec             C   s   | j  d||f¡ d S )NÚunexpectedError)r8   r:   )r   Úfilenamer<   r   r   r   r=   ƒ   s    zLoggingReporter.unexpectedErrorc             C   s   | j  d|||||f¡ d S )NÚsyntaxError)r8   r:   )r   r>   Úmsgr   ÚoffsetÚliner   r   r   r?   †   s    zLoggingReporter.syntaxErrorN)r   r   r   r   r   r9   r=   r?   r   r   r   r   r7   s   s
   r7   c               @   s`   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚTestIterSourceCodez&
    Tests for L{iterSourceCode}.
    c             C   s   t  ¡ | _d S )N)ÚtempfileÚmkdtempÚtempdir)r   r   r   r   ÚsetUp   s    zTestIterSourceCode.setUpc             C   s   t  | j¡ d S )N)ÚshutilÚrmtreerF   )r   r   r   r   ÚtearDown’   s    zTestIterSourceCode.tearDownc             G   s.   |st ‚tjj| jf|žŽ }t|dƒ ¡  |S )NÚa)ÚAssertionErrorr!   ÚpathÚjoinrF   ÚopenÚclose)r   ÚpartsZfpathr   r   r   ÚmakeEmptyFile•   s    z TestIterSourceCode.makeEmptyFilec             C   s   |   tt| jgƒƒg ¡ dS )zB
        There are no Python files in an empty directory.
        N)ÚassertEqualÚlistr   rF   )r   r   r   r   Útest_emptyDirectory›   s    z&TestIterSourceCode.test_emptyDirectoryc             C   s(   |   d¡}|  tt| jgƒƒ|g¡ dS )zd
        If the directory contains one Python file, C{iterSourceCode} will find
        it.
        zfoo.pyN)rR   rS   rT   r   rF   )r   Z	childpathr   r   r   Útest_singleFile¡   s    
z"TestIterSourceCode.test_singleFilec             C   s&   |   d¡ |  tt| jgƒƒg ¡ dS )zJ
        Files that are not Python source files are not included.
        zfoo.pycN)rR   rS   rT   r   rF   )r   r   r   r   Útest_onlyPythonSource©   s    
z(TestIterSourceCode.test_onlyPythonSourcec             C   s€   t  t j | jd¡¡ |  dd¡}|  dd¡ t  t j | jd¡¡ |  dd¡}|  d¡}|  tt| jgƒƒt|||gƒ¡ dS )zk
        If the Python files are hidden deep down in child directories, we will
        find them.
        Úfooza.pyza.py~Úbarzb.pyzc.pyN)	r!   ÚmkdirrM   rN   rF   rR   rS   Úsortedr   )r   ÚapathÚbpathZcpathr   r   r   Útest_recurses°   s    
z TestIterSourceCode.test_recursesc          	   C   s  t j | jd¡}t|dƒ}| d¡ W dQ R X |  d¡ tt j | jd¡dƒ}| d¡ W dQ R X t j | jd¡}t|dƒ}| d	¡ W dQ R X t j | jd
¡}t|dƒ}| d¡ W dQ R X t j | jd¡}t|dƒ}| d¡ W dQ R X |  tt	| jgƒƒt||||gƒ¡ dS )zd
        Find Python files that don't end with `.py`, but contain a Python
        shebang.
        rK   Úwz#!/usr/bin/env python
NÚbÚczhello
world
Údz#!/usr/bin/env python2
Úez#!/usr/bin/env python3
r   z#!/usr/bin/env pythonw
)
r!   rM   rN   rF   rO   ÚwriterR   rS   r[   r   )r   ZpythonÚfdZpython2Zpython3Zpythonwr   r   r   Útest_shebang¿   s$    
zTestIterSourceCode.test_shebangc             C   sp   t j | jd¡}t j | jd¡}t  |¡ |  dd¡}t  |¡ |  dd¡}|  tt||gƒƒt||gƒ¡ dS )zr
        L{iterSourceCode} can be given multiple directories.  It will recurse
        into each of them.
        rX   rY   za.pyzb.pyN)	r!   rM   rN   rF   rZ   rR   rS   r[   r   )r   ZfoopathZbarpathr\   r]   r   r   r   Útest_multipleDirectoriesÝ   s    

z+TestIterSourceCode.test_multipleDirectoriesc             C   s&   |   d¡}|  tt|gƒƒ|g¡ dS )z‹
        If one of the paths given to L{iterSourceCode} is not a directory but
        a file, it will include that in its output.
        ze.pyN)rR   rS   rT   r   )r   Zepathr   r   r   Útest_explicitFilesì   s    
z%TestIterSourceCode.test_explicitFilesN)r   r   r   r   rG   rJ   rR   rU   rV   rW   r^   rf   rg   rh   r   r   r   r   rC   Š   s   rC   c               @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )ÚTestReporterz 
    Tests for L{Reporter}.
    c             C   sD   t ƒ }td|ƒ}| dddtjdkr(dndd¡ |  d	| ¡ ¡ dS )
a  
        C{syntaxError} reports that there was a syntax error in the source
        file.  It reports to the error stream and includes the filename, line
        number, error message, actual line of source and a caret pointing to
        where the error is.
        Nzfoo.pyz	a problemr   )r   é   rj   é   zbad line of sourcez2foo.py:3:8: a problem
bad line of source
       ^
)r   r   r?   r   Úversion_inforS   r2   )r   ÚerrÚreporterr   r   r   Útest_syntaxErrorû   s    

zTestReporter.test_syntaxErrorc             C   s6   t ƒ }td|ƒ}| ddddd¡ |  d| ¡ ¡ dS )zy
        C{syntaxError} doesn't include a caret pointing to the error if
        C{offset} is passed as C{None}.
        Nzfoo.pyz	a problemr   zbad line of sourcez'foo.py:3: a problem
bad line of source
)r   r   r?   rS   r2   )r   rm   rn   r   r   r   Útest_syntaxErrorNoOffset  s    
z%TestReporter.test_syntaxErrorNoOffsetc          	   C   s‚   t ƒ }ddg}td|ƒ}| dddt|d ƒd d	 |¡¡ tjd
krJdnd}|  d| |d  d	 d|d   d | ¡ ¡ dS )z¸
        If there's a multi-line syntax error, then we only report the last
        line.  The offset is adjusted so that it is relative to the start of
        the last line.
        zbad line of sourcezmore bad lines of sourceNzfoo.pyz	a problemr   r   rk   r1   )r   rj   é   zfoo.py:3:%d: a problem
éÿÿÿÿú é   z^
)	r   r   r?   ÚlenrN   r   rl   rS   r2   )r   rm   Úlinesrn   Úcolumnr   r   r   Útest_multiLineSyntaxError  s    
"z&TestReporter.test_multiLineSyntaxErrorc             C   s0   t ƒ }td|ƒ}| dd¡ |  d| ¡ ¡ dS )zO
        C{unexpectedError} reports an error processing a source file.
        Nz	source.pyzerror messagezsource.py: error message
)r   r   r=   rS   r2   )r   rm   rn   r   r   r   Útest_unexpectedError0  s    
z!TestReporter.test_unexpectedErrorc             C   sD   t ƒ }t|dƒ}tdtdƒdƒ}| |¡ |  | ¡ d|f ¡ dS )z„
        C{flake} reports a code warning from Pyflakes.  It is exactly the
        str() of a L{pyflakes.messages.Message}.
        Nzfoo.pyé*   rY   z%s
)r   r   r   r   r9   rS   r2   )r   Úoutrn   r<   r   r   r   Ú
test_flake9  s
    

zTestReporter.test_flakeN)	r   r   r   r   ro   rp   rx   ry   r|   r   r   r   r   ri   ö   s   	ri   c               @   s¾   e Zd ZdZejdd„ ƒZdd„ Zdd„ Zdd	„ Z	d
d„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zeejdkdƒdd„ ƒZdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*S )+Ú
CheckTestszL
    Tests for L{check} and L{checkPath} which check a file for flakes.
    c          	   c   s^   t  ¡ \}}z@t |d¡$}t|dƒs0| d¡}| |¡ W dQ R X |V  W dt |¡ X dS )zV
        Make a temporary file containing C{content} and return a path to it.
        ÚwbÚdecodeÚasciiN)rD   Zmkstempr!   ÚfdopenÚhasattrÚencoderd   Úremove)r   Zcontentre   Únamer   r   r   r   ÚmakeTempFileJ  s    


zCheckTests.makeTempFilec             C   s8   t ƒ }t|t|ƒ}|  || ¡ ft|ƒd |¡f¡ dS )z²
        Assert that C{path} causes errors.

        @param path: A path to a file to check.
        @param errorList: A list of errors expected to be printed to stderr.
        r'   N)r   r   r   rS   r2   ru   rN   )r   rM   Z	errorListrm   Úcountr   r   r   ÚassertHasErrorsY  s    zCheckTests.assertHasErrorsc             C   s   g }t |ƒ}t||ƒ}||fS )a‘  
        Get any warnings or errors reported by pyflakes for the file at C{path}.

        @param path: The path to a Python file on disk that pyflakes will check.
        @return: C{(count, log)}, where C{count} is the number of warnings or
            errors generated, and log is a list of those warnings, presented
            as structured data.  See L{LoggingReporter} for more details.
        )r7   r   )r   rM   r8   rn   r‡   r   r   r   Ú	getErrorse  s    	
zCheckTests.getErrorsc             C   s   ddl m} |  |jt¡ d S )Nr   )Úpyflakes)Zpyflakes.scriptsrŠ   ZassertIsr   )r   Zscript_pyflakesr   r   r   Útest_legacyScripts  s    zCheckTests.test_legacyScriptc          	   C   s&   |   d¡}|  |g ¡ W dQ R X dS )z§
        Source which doesn't end with a newline shouldn't cause any
        exception to be raised nor an error indicator to be returned by
        L{check}.
        zdef foo():
	pass
	N)r†   rˆ   )r   ZfNamer   r   r   Útest_missingTrailingNewlinew  s    z&CheckTests.test_missingTrailingNewlinec             C   s,   |   d¡\}}|  |d¡ |  |dg¡ dS )z:
        L{checkPath} handles non-existing files.
        Úextremort   )r=   r   zNo such file or directoryN)r‰   rS   )r   r‡   Úerrorsr   r   r   Útest_checkPathNonExisting€  s
    z$CheckTests.test_checkPathNonExistingc             C   s¸   d}dd„ }y||ƒ W n: t k
rR   t ¡ d }tsN|  |j d¡dk¡ Y n
X |  ¡  |  |¡H}trrd}nd}tj	dkr„d	nd
}|  
|d|||d|d  f g¡ W dQ R X dS )zÏ
        Source which includes a syntax error which results in the raised
        L{SyntaxError.text} containing multiple lines of source are reported
        with only the last line of that source.
        zCdef foo():
    '''

def bar():
    pass

def baz():
    '''quux'''
c             S   s   t | ƒ d S )N)Úexec)Úsourcer   r   r   Úevaluate  s    z6CheckTests.test_multilineSyntaxError.<locals>.evaluatert   r1   z/EOF while scanning triple-quoted string literalzinvalid syntax)r   rj   rj   é   z%s:8:%d: %s
    '''quux'''
%s^
rs   N)ÚSyntaxErrorr   Úexc_infoÚPYPYZ
assertTrueÚtextr‡   Zfailr†   rl   rˆ   )r   r‘   r’   rc   Ú
sourcePathr<   rw   r   r   r   Útest_multilineSyntaxErrorŠ  s"    z$CheckTests.test_multilineSyntaxErrorc          	   C   sB   |   d¡.}trd|f }n
d|f }|  ||g¡ W dQ R X dS )z“
        The error reported for source files which end prematurely causing a
        syntax error reflects the cause for the syntax error.
        zdef foo(z5%s:1:7: parenthesis is never closed
def foo(
      ^
z8%s:1:9: unexpected EOF while parsing
def foo(
        ^
N)r†   r–   rˆ   )r   r˜   Úresultr   r   r   Útest_eofSyntaxError·  s    
zCheckTests.test_eofSyntaxErrorc          	   C   sJ   |   d¡6}trdnd}tr dnd}|  |d|||f g¡ W dQ R X dS )z“
        The error reported for source files which end prematurely causing a
        syntax error reflects the cause for the syntax error.
        zif True:
	foo =é   rk   z	   ^z	     ^z"%s:2:%s: invalid syntax
	foo =
%s
N)r†   r–   rˆ   )r   r˜   rw   Ú	last_liner   r   r   Útest_eofSyntaxErrorWithTabÎ  s    z%CheckTests.test_eofSyntaxErrorWithTabc          	   C   sn   d}|   |¡V}tr@tjdkr"dnd}d|d  d }d| }nd	 }}|  |d
|||f g¡ W dQ R X dS )zÎ
        Source which has a non-default argument following a default argument
        should include the line number of the syntax error.  However these
        exceptions do not include an offset.
        z def foo(bar=baz, bax):
    pass
)r   rj   é	   rj   rs   rt   z^
z%d:r'   zO%s:1:%s non-default argument follows default argument
def foo(bar=baz, bax):
%sN)r†   ÚERROR_HAS_LAST_LINEr   rl   rˆ   )r   r‘   r˜   rw   r   Ú	columnstrr   r   r   Ú(test_nonDefaultFollowsDefaultSyntaxErrorß  s    	
z3CheckTests.test_nonDefaultFollowsDefaultSyntaxErrorc          	   C   s„   d}|   |¡l}tr@tjdkr"dnd}d|d  d }d| }nd	 }}tjd
krXd}nd}|  |d||||f g¡ W dQ R X dS )zÊ
        Source which has a non-keyword argument after a keyword argument should
        include the line number of the syntax error.  However these exceptions
        do not include an offset.
        zfoo(bar=baz, bax)
)r   rj   é   é   rs   rt   z^
z%d:r'   )r   rœ   z,positional argument follows keyword argumentz!non-keyword arg after keyword argz%s:1:%s %s
foo(bar=baz, bax)
%sN)r†   r    r   rl   rˆ   )r   r‘   r˜   rw   r   r¡   r<   r   r   r   Ú&test_nonKeywordAfterKeywordSyntaxError÷  s    

z1CheckTests.test_nonKeywordAfterKeywordSyntaxErrorc          	   C   sš   t j}|  d¡€}|dk r&d|f }nXd}tr4d}n d}|dk sP|dd	… d
krTd}trjdd|d   }nd}d||||f }|  ||g¡ W dQ R X dS )zI
        The invalid escape syntax raises ValueError in Python 2
        zfoo = '\xyz')r   z%s: problem decoding source
rt   é   rk   )r   r   é   Nr   )r   r   r   r   z%s^
rs   r'   zy%s:1:%d: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-%d: truncated \xXX escape
foo = '\xyz'
%s)r   rl   r†   r–   r    rˆ   )r   Zverr˜   Zdecoding_errorZposition_endrw   r   r   r   r   Útest_invalidEscape  s     zCheckTests.test_invalidEscapeZwin32zunsupported on Windowsc          	   C   sj   t  ¡ dkr|  d¡ |  d¡@}t  |d¡ |  |¡\}}|  |d¡ |  |d|dfg¡ W dQ R X dS )za
        If the source file is not readable, this is reported on standard
        error.
        r   z8root user can access all files regardless of permissionsr'   rt   r=   zPermission deniedN)r!   ÚgetuidZskipTestr†   Úchmodr‰   rS   )r   r˜   r‡   rŽ   r   r   r   Útest_permissionDenied5  s    
z CheckTests.test_permissionDeniedc          
   C   sV   |   d¡B}|  |¡\}}|  |d¡ |  |dtt|tdƒdƒƒfg¡ W dQ R X dS )zc
        If the source file has a pyflakes warning, this is reported as a
        'flake'.
        z
import foort   r9   rX   N)r†   r‰   rS   r;   r   r   )r   r˜   r‡   rŽ   r   r   r   Útest_pyflakesWarningF  s
    zCheckTests.test_pyflakesWarningc          	   C   s<   t dƒ}d|  d¡}|  |¡}|  |g ¡ W dQ R X dS )zU
        If source file declares the correct encoding, no error is reported.
        i&  z# coding: utf-8
x = "%s"
zutf-8N)Úunichrrƒ   r†   rˆ   )r   ÚSNOWMANr‘   r˜   r   r   r   Útest_encodedFileUTF8Q  s    zCheckTests.test_encodedFileUTF8c          	   C   s&   |   d¡}|  |g ¡ W dQ R X dS )zW
        Source files with Windows CR LF line endings are parsed successfully.
        zx = 42
N)r†   rˆ   )r   r˜   r   r   r   Útest_CRLFLineEndings]  s    zCheckTests.test_CRLFLineEndingsc          	   C   sl   t dƒ}d|  d¡}|  |¡B}trBtjdk rBd}d||f }nd}d|f }|  ||g¡ W d	Q R X d	S )
zn
        If a source file contains bytes which cannot be decoded, this is
        reported on stderr.
        i&  z# coding: ascii
x = "%s"
zutf-8)r   zN'ascii' codec can't decode byte 0xe2 in position 21: ordinal not in range(128)u"   %s:0:0: %s
x = "Ã¢Â˜Âƒ"
        ^
zproblem decoding sourcez%s: problem decoding source
N)r­   rƒ   r†   r–   r   rl   rˆ   )r   r®   r‘   r˜   r<   rš   r   r   r   Útest_misencodedFileUTF8d  s    
z"CheckTests.test_misencodedFileUTF8c          	   C   sD   t dƒ}d|  d¡}|  |¡}|  |d|f g¡ W dQ R X dS )zn
        If a source file contains bytes which cannot be decoded, this is
        reported on stderr.
        i&  z# coding: ascii
x = "%s"
zutf-16z%s: problem decoding source
N)r­   rƒ   r†   rˆ   )r   r®   r‘   r˜   r   r   r   Útest_misencodedFileUTF16~  s
    z#CheckTests.test_misencodedFileUTF16c             C   s   t  ¡ }zæt tj |d¡¡ tj |dd¡}t|dƒ}| d d¡¡ W dQ R X tj |d¡}t|dƒ}| d d¡¡ W dQ R X g }t	|ƒ}t
|g|ƒ}|  |d	¡ |  t|ƒtd
tt|tdƒdƒƒfd
tt|tdƒdƒƒfgƒ¡ W dt |¡ X dS )zv
        L{checkRecursive} descends into each directory, finding Python files
        and reporting problems.
        rX   zbar.pyr~   zimport baz
r€   Nzbaz.pyzimport contrabandr   r9   rt   ZbazÚ
contraband)rD   rE   r!   rZ   rM   rN   rO   rd   rƒ   r7   r   rS   r[   r;   r   r   rH   rI   )r   rF   Zfile1re   Zfile2r8   rn   Úwarningsr   r   r   Útest_checkRecursiveŒ  s&     zCheckTests.test_checkRecursiveN)r   r   r   r   Ú
contextlibÚcontextmanagerr†   rˆ   r‰   r‹   rŒ   r   r™   r›   rž   r¢   r¥   r¨   r
   r   Úplatformr«   r¬   r¯   r°   r±   r²   rµ   r   r   r   r   r}   E  s(   	
-!r}   c               @   sZ   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	d
„Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )ÚIntegrationTestszF
    Tests of the pyflakes script that actually spawn the script.
    c             C   s    t  ¡ | _tj | jd¡| _d S )NZtemp)rD   rE   rF   r!   rM   rN   Útempfilepath)r   r   r   r   rG   ¬  s    
zIntegrationTests.setUpc             C   s   t  | j¡ d S )N)rH   rI   rF   )r   r   r   r   rJ   °  s    zIntegrationTests.tearDownc             C   s(   ddl }tj |j¡}tj |ddd¡S )z9
        Return the path to the pyflakes binary.
        r   Nz..ÚbinrŠ   )rŠ   r!   rM   ÚdirnameÚ__file__rN   )r   rŠ   Zpackage_dirr   r   r   ÚgetPyflakesBinary³  s    z"IntegrationTests.getPyflakesBinaryNc       	      C   sÒ   t tjƒ}tj tj¡|d< tj|  ¡ g}| 	|¡ |rht
j||t
jt
jt
jd}| | d¡¡\}}n"t
j||t
jt
jd}| ¡ \}}| ¡ }tjdkr°| d¡}| d¡}trÈtrÈtrÈ| dd¡}|||fS )	a	  
        Launch a subprocess running C{pyflakes}.

        @param paths: Command-line arguments to pass to pyflakes.
        @param stdin: Text to use as stdin.
        @return: C{(returncode, stdout, stderr)} of the completed pyflakes
            process.
        Z
PYTHONPATH)Úenvr)   r+   r   r€   )r¿   r+   r   )r   zutf-8z
z
)Údictr!   ÚenvironÚpathseprN   r   rM   Ú
executabler¾   ÚextendÚ
subprocessÚPopenÚPIPEZcommunicaterƒ   Úwaitrl   r   r–   r   ÚWINr5   )	r   Úpathsr)   r¿   ZcommandÚpr+   r   Úrvr   r   r   ÚrunPyflakes»  s$    	




zIntegrationTests.runPyflakesc             C   s.   t | jdƒ ¡  |  | jg¡}|  |d¡ dS )z
        When a Python source file is all good, the return code is zero and no
        messages are printed to either stdout or stderr.
        rK   )r'   r'   r   N)rO   rº   rP   rÍ   rS   )r   rb   r   r   r   Útest_goodFileÙ  s    zIntegrationTests.test_goodFilec          	   C   sh   t | jdƒ}| d d¡¡ W dQ R X |  | jg¡}t| jtdƒdƒ}|  |d|tj	f ddf¡ dS )	z…
        When a Python source file has warnings, the return code is non-zero
        and the warnings are printed to stdout.
        r~   zimport contraband
r€   Nrt   r³   z%s%sr'   )
rO   rº   rd   rƒ   rÍ   r   r   rS   r!   r"   )r   re   rb   Úexpectedr   r   r   Útest_fileWithFlakesâ  s
    z$IntegrationTests.test_fileWithFlakesc             C   s4   |   | jg¡}d| jtjf }|  |d|df¡ dS )zº
        When pyflakes finds errors with the files it's given, (if they don't
        exist, say), then the return code is non-zero and the errors are
        printed to stderr.
        z%s: No such file or directory%sr'   rt   N)rÍ   rº   r!   r"   rS   )r   rb   Ú	error_msgr   r   r   Útest_errors_ioí  s    
zIntegrationTests.test_errors_ioc          	   C   sp   t | jdƒ}| d d¡¡ W dQ R X |  | jg¡}d | jtjtrJdndtrTdnd	¡}|  	|d|d
f¡ dS )zº
        When pyflakes finds errors with the files it's given, (if they don't
        exist, say), then the return code is non-zero and the errors are
        printed to stderr.
        r~   Úimportr€   Nz0{0}:1:{2}: invalid syntax{1}import{1}    {3}^{1}rœ   rk   r'   z  rt   )
rO   rº   rd   rƒ   rÍ   Úformatr!   r"   r–   rS   )r   re   rb   rÑ   r   r   r   Útest_errors_syntaxø  s     z#IntegrationTests.test_errors_syntaxc             C   s>   | j g dd}tdtdƒdƒ}|  |d|tjf ddf¡ dS )	zU
        If no arguments are passed to C{pyflakes} then it reads from stdin.
        zimport contraband)r)   z<stdin>rt   r³   z%s%sr'   N)rÍ   r   r   rS   r!   r"   )r   rb   rÏ   r   r   r   Útest_readFromStdin  s    z#IntegrationTests.test_readFromStdin)N)r   r   r   r   rG   rJ   r¾   rÍ   rÎ   rÐ   rÒ   rÕ   rÖ   r   r   r   r   r¹   §  s   
	r¹   c               @   s   e Zd ZdZddd„ZdS )ÚTestMainz.
    Tests of the pyflakes main function.
    Nc          
   C   st   y"t |ƒ}t|d W d Q R X W nD tk
rf } z&|  |jt¡ t|jƒ}|j|j|fS d }~X Y n
X t	dƒ‚d S )N)r   zSystemExit not raised)
r   r   Ú
SystemExitZassertIsInstanceÚcodeÚboolÚintr3   r4   ÚRuntimeError)r   rÊ   r)   Zcapturerc   rÌ   r   r   r   rÍ     s    

zTestMain.runPyflakes)N)r   r   r   r   rÍ   r   r   r   r   r×     s   r×   )-r   r¶   r!   r   rH   rÅ   rD   Zpyflakes.checkerr   Zpyflakes.messagesr   Zpyflakes.reporterr   Zpyflakes.apir   r   r   r   Zpyflakes.test.harnessr	   r
   rl   Z	cStringIOr   ÚioÚchrr­   Zpypy_version_infor–   ÚAttributeErrorZWindowsErrorrÉ   Ú	NameErrorZERROR_HAS_COL_NUMr    r   Úobjectr   r   r7   rC   ri   r}   r¹   r×   r   r   r   r   Ú<module>   sJ   


	3lO  dg