o
    hg                     @   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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mZ ddlmZmZ dd	 ZG d
d dZG dd dZG d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dS )z)
Tests for L{pyflakes.scripts.pyflakes}.
    N)PYPY)UnusedImport)Reporter)maincheck	checkPathcheckRecursiveiterSourceCode)TestCaseskipIfc                 O   s.   t j| }t _z||i |W |t _S |t _w )z?
    Call C{f} with C{sys.stderr} redirected to C{stderr}.
    )sysstderr)r   fargskwargsouter r   L/var/www/html/ai/venv/lib/python3.10/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   %       r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	SysStreamCapturingzContext manager capturing sys.stdin, sys.stdout and sys.stderr.

    The file handles are replaced with a StringIO object.
    c                 C   s   t j|pdtjd| _d S )N newline)ioStringIOoslinesep_stdin)r   stdinr   r   r   r   4   s   zSysStreamCapturing.__init__c                 C   sP   t j| _t j| _t j| _| jt _tj	t
jd t _| _tj	t
jd t _| _| S )Nr"   )r   r)   _orig_stdinstdout_orig_stdoutr   _orig_stderrr(   r$   r%   r&   r'   _stdout_stringio_stderr_stringior   r   r   r   	__enter__7   s   zSysStreamCapturing.__enter__c                 G   s4   | j  | _| j | _| jt_| jt_	| j
t_d S r   )r.   getvalueoutputr/   errorr*   r   r)   r,   r+   r-   r   )r   r   r   r   r   __exit__B   s
   zSysStreamCapturing.__exit__N)r   r   r   r   r   r1   r5   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   r7   r   r   r   r   P   s   
zLoggingReporter.__init__c                 C   s   | j dt|f d S )Nflake)r7   appendstr)r   messager   r   r   r8   X   s   zLoggingReporter.flakec                 C   s   | j d||f d S )NunexpectedErrorr7   r9   )r   filenamer;   r   r   r   r<   [   s   zLoggingReporter.unexpectedErrorc                 C   s   | j d|||||f d S )NsyntaxErrorr=   )r   r>   msgr   offsetliner   r   r   r?   ^   s   zLoggingReporter.syntaxErrorN)r   r   r   r   r   r8   r<   r?   r   r   r   r   r6   K   s    r6   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 r   )tempfilemkdtemptempdirr0   r   r   r   setUpg   s   zTestIterSourceCode.setUpc                 C      t | j d S r   shutilrmtreerF   r0   r   r   r   tearDownj      zTestIterSourceCode.tearDownc                 G   s0   |sJ t jj| jg|R  }t|d  |S )Na)r&   pathjoinrF   openclose)r   partsfpathr   r   r   makeEmptyFilem   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   r0   r   r   r   test_emptyDirectorys   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.
        foo.pyNrU   rV   rW   r	   rF   )r   	childpathr   r   r   test_singleFiley   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.pycNrZ   r0   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.
        fooa.pyza.py~barb.pyzc.pyN)	r&   mkdirrO   rP   rF   rU   rV   sortedr	   )r   apathbpathcpathr   r   r   test_recurses   s   
z TestIterSourceCode.test_recursesc           	   
   C   sT  t j| jd}t|d}|d W d   n1 sw   Y  | d tt j| jdd}|d W d   n1 sBw   Y  t j| jd}t|d}|d	 W d   n1 sdw   Y  t j| jd
}t|d}|d W d   n1 sw   Y  t j| jd}t|d}|d W d   n1 sw   Y  t j| jd}t|d}|d W d   n1 sw   Y  t j| jd}t|d}|d W d   n1 sw   Y  t j| jd}t|d}|d W d   n	1 sw   Y  | tt	| jgt||||||g dS )zd
        Find Python files that don't end with `.py`, but contain a Python
        shebang.
        rN   wz#!/usr/bin/env python
Nbczhello
world
ez#!/usr/bin/env python3
r   z#!/usr/bin/env pythonw
gz#!/usr/bin/python3 -u
iz#!/usr/local/bin/python3d
jz#! /usr/bin/env python3.8m
lz#!/bin/sh
#!/usr/bin/python
)
r&   rO   rP   rF   rQ   writerU   rV   rc   r	   )	r   pythonfdpython3pythonwpython3argspython3d	python38mnotfirstr   r   r   test_shebang   sN   

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.
        r^   r`   r_   ra   N)	r&   rO   rP   rF   rb   rU   rV   rc   r	   )r   foopathbarpathrd   re   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)rU   rV   rW   r	   )r   epathr   r   r   test_explicitFiles   s   
z%TestIterSourceCode.test_explicitFilesN)r   r   r   r   rG   rL   rU   rX   r\   r]   rg   ry   r|   r~   r   r   r   r   rC   b   s    .rC   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S )TestReporterz 
    Tests for L{Reporter}.
    c                 C   s8   t  }td|}|ddd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.
        NrY   	a problem      bad line of sourcez2foo.py:3:8: a problem
bad line of source
       ^
r$   r%   r   r?   rV   r2   r   errreporterr   r   r   test_syntaxError   s   
zTestReporter.test_syntaxErrorc                 C   s8   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}.
        NrY   r   r   r   z'foo.py:3: a problem
bad line of source
r   r   r   r   r   test_syntaxErrorNoOffset   s   
z%TestReporter.test_syntaxErrorNoOffsetc                 C   s8   t  }td|}|ddddd | d|  dS )z
        C{syntaxError} doesn't include text or nonsensical offsets if C{text} is C{None}.

        This typically happens when reporting syntax errors from stdin.
        N<stdin>r   r   z<stdin>:1:1: a problem
r   r   r   r   r   test_syntaxErrorNoText  s   
z#TestReporter.test_syntaxErrorNoTextc              	   C   sf   t  }ddg}td|}|dddt|d 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.
        r   zmore bad lines of sourceNrY   r   r   r      
zfoo.py:3:25: a problem
z                        ^
)r$   r%   r   r?   lenrP   rV   r2   )r   r   linesr   r   r   r   test_multiLineSyntaxError  s(   
z&TestReporter.test_multiLineSyntaxErrorc                 C   s2   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   r<   rV   r2   r   r   r   r   test_unexpectedError   s   
z!TestReporter.test_unexpectedErrorc                 C   sF   t  }t|d}tdtdd}|| | | | d dS )z
        C{flake} reports a code warning from Pyflakes.  It is exactly the
        str() of a L{pyflakes.messages.Message}.
        NrY   *   r`   r   )r$   r%   r   r   r   r8   rV   r2   )r   outr   r;   r   r   r   
test_flake)  s
   

zTestReporter.test_flakeN)
r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s    	r   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*d+ Zd,S )-
CheckTestszL
    Tests for L{check} and L{checkPath} which check a file for flakes.
    c              	   c   s|    t  \}}z0t|d}t|ds|d}|| W d   n1 s(w   Y  |V  W t| dS t| w )zV
        Make a temporary file containing C{content} and return a path to it.
        wbdecodeasciiN)rD   mkstempr&   fdopenhasattrencoderp   remove)r   contentrr   namer   r   r   r   makeTempFile:  s   

zCheckTests.makeTempFilec                 C   s:   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   r   rV   r2   r   rP   )r   rO   	errorListr   countr   r   r   assertHasErrorsI  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.
        )r6   r   )r   rO   r7   r   r   r   r   r   	getErrorsU  s   	
zCheckTests.getErrorsc                 C   s   ddl m} | |jt d S )Nr   )pyflakes)pyflakes.scriptsr   assertIsr   )r   script_pyflakesr   r   r   test_legacyScriptc  s   zCheckTests.test_legacyScriptc                 C   <   |  d}| |g  W d   dS 1 sw   Y  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   fNamer   r   r   test_missingTrailingNewlineg  s   "z&CheckTests.test_missingTrailingNewlinec                 C   s,   |  d\}}| |d | |dg dS )z:
        L{checkPath} handles non-existing files.
        extremo   )r<   r   zNo such file or directoryN)r   rV   )r   r   errorsr   r   r   test_checkPathNonExistingp  s   z$CheckTests.test_checkPathNonExistingc                 C   s   d}dd }z|| W n$ t y0 } zts&tjdk r&| |jddk W Y d}~n	d}~ww |   | |5}tr@d}n
tjdkrHd	}nd
}tsQtjdkrTd}nd}| 	|d|||d|d  f g W d   dS 1 srw   Y  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 r   )exec)sourcer   r   r   evaluate  s   z6CheckTests.test_multilineSyntaxError.<locals>.evaluater   
   r   r   Nz=end of file (EOF) while scanning triple-quoted string literalz>unterminated triple-quoted string literal (detected at line 8)zinvalid syntax   r   z%s:8:%d: %s
    '''quux'''
%s^
 )
SyntaxErrorr   r   version_info
assertTruetextr   failr   r   )r   r   r   rk   
sourcePathr;   columnr   r   r   test_multilineSyntaxErrorz  s4   
"z$CheckTests.test_multilineSyntaxErrorc                 C   s   |  d9}trd}n
tjdkrd}nd}tstjdkrd}nd}d|d	  }d
||||}| ||g W d   dS 1 sAw   Y  dS )
        The error reported for source files which end prematurely causing a
        syntax error reflects the cause for the syntax error.
        zdef foo(zparenthesis is never closedr   z'(' was never closedzunexpected EOF while parsingr   	   r   r   z{}:1:{}: {}
def foo(
{}^
N)r   r   r   r   formatr   )r   r   r@   r   spacesexpectedr   r   r   test_eofSyntaxError  s   
"zCheckTests.test_eofSyntaxErrorc                 C   sD   |  d}| || dg W d   dS 1 sw   Y  dS )r   zif True:
	foo =z$:2:7: invalid syntax
	foo =
	     ^
Nr   r   r   r   r   r   test_eofSyntaxErrorWithTab  s   "z%CheckTests.test_eofSyntaxErrorWithTabc                 C   s   d}|  |N}tjdkrd}nd}trtjdkrd}ntr!d}ntjdkr)d}n
tjdkr1d	}nd
}d|d  d }| || d| d| d| g W d   dS 1 sXw   Y  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   r   z<parameter without a default follows parameter with a defaultz-non-default argument follows default argumentr   r      r   r      r   r   r   r   z:1:z: z
def foo(bar=baz, bax):
N)r   r   r   r   r   )r   r   r   r@   r   	last_liner   r   r   (test_nonDefaultFollowsDefaultSyntaxError  s6   


"z3CheckTests.test_nonDefaultFollowsDefaultSyntaxErrorc              
   C   s   d}|  |3}tjdkrd}ntsd}nd}d|d  d }d	| }d
}| |d||||g W d   dS 1 s=w   Y  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            r   r   r   z%d:z,positional argument follows keyword argumentz{}:1:{} {}
foo(bar=baz, bax)
{}N)r   r   r   r   r   r   )r   r   r   r   r   	columnstrr;   r   r   r   &test_nonKeywordAfterKeywordSyntaxError  s"   
"z1CheckTests.test_nonKeywordAfterKeywordSyntaxErrorc                 C   s   |  dC}d}trtjdkrd}ntrd}ndtj  kr"dk r'n nd}nd}dd	|d   }d
||||f }| ||g W d   dS 1 sKw   Y  dS )zI
        The invalid escape syntax raises ValueError in Python 2
        zfoo = '\xyz'r   r   r      r   r   z%s^
r   zy%s:1:%d: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-%d: truncated \xXX escape
foo = '\xyz'
%sN)r   r   r   r   r   )r   r   position_endr   r   decoding_errorr   r   r   test_invalidEscape  s"   
"zCheckTests.test_invalidEscapewin32zunsupported on Windowsc                 C   s   t  dkr| d | d&}t |d | |\}}| |d | |d|dfg W d   dS 1 s9w   Y  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!   r   r<   zPermission deniedN)r&   getuidskipTestr   chmodr   rV   r   r   r   r   r   r   r   test_permissionDenied,  s   

"z CheckTests.test_permissionDeniedc              
   C   sl   |  d'}| |\}}| |d | |dtt|tddfg W d   dS 1 s/w   Y  dS )zc
        If the source file has a pyflakes warning, this is reported as a
        'flake'.
        z
import foor   r8   r^   N)r   r   rV   r:   r   r   r   r   r   r   test_pyflakesWarning=  s   "zCheckTests.test_pyflakesWarningc                 C   sR   t d}d| d}| |}| |g  W d   dS 1 s"w   Y  dS )zU
        If source file declares the correct encoding, no error is reported.
        &  z# coding: utf-8
x = "%s"
utf-8Nchrr   r   r   r   SNOWMANr   r   r   r   r   test_encodedFileUTF8H  s   "zCheckTests.test_encodedFileUTF8c                 C   r   )zW
        Source files with Windows CR LF line endings are parsed successfully.
        zx = 42
Nr   r   r   r   r   test_CRLFLineEndingsT  s   "zCheckTests.test_CRLFLineEndingsc                 C   sZ   t d}d| d}| |}| || dg W d   dS 1 s&w   Y  dS )n
        If a source file contains bytes which cannot be decoded, this is
        reported on stderr.
        r   # coding: ascii
x = "%s"
r   zU:1:1: 'ascii' codec can't decode byte 0xe2 in position 21: ordinal not in range(128)
Nr   r   r   r   r   test_misencodedFileUTF8[  s   
"z"CheckTests.test_misencodedFileUTF8c                 C   st   t d}d| d}| | }tjdk r| d}n| d}| ||g W d   dS 1 s3w   Y  dS )r   r   r   zutf-16)r         z: problem decoding source
z1:1: source code string cannot contain null bytes
N)r   r   r   r   r   r   )r   r   r   r   r   r   r   r   test_misencodedFileUTF16j  s   

"z#CheckTests.test_misencodedFileUTF16c                 C   s$  t  }zttj|d tj|dd}t|d}|d W d   n1 s,w   Y  tj|d}t|d}|d W d   n1 sMw   Y  g }t|}t	|g|}| 
|d | 
t|td	tt|td
dfd	tt|td
dfg W t| dS t| w )zv
        L{checkRecursive} descends into each directory, finding Python files
        and reporting problems.
        r^   zbar.pyr   s   import baz
Nzbaz.pys   import contraband   r8   r   baz
contraband)rD   rE   r&   rb   rO   rP   rQ   rp   r6   r   rV   rc   r:   r   r   rJ   rK   )r   rF   file1rr   file2r7   r   warningsr   r   r   test_checkRecursive|  s0   zCheckTests.test_checkRecursivec                 C   st   d}t  }t|t|d}| |d | ddd }tjdkr(g d}n
t	r/g d	}nd
g}| || dS )z;
        L{check} reports syntax errors from stdin
        z-max(1 for i in range(10), key=lambda x: x+1)
r   r   r   Nr   r   )7<stdin>:1:5: Generator expression must be parenthesized,max(1 for i in range(10), key=lambda x: x+1)z    ^)zL<stdin>:1:4: Generator expression must be parenthesized if not sole argumentr   z   ^r   )
r$   r%   r   r   rV   r2   splitr   r   r   )r   r   r   r   errlinesexpected_errorr   r   r   test_stdinReportsErrors  s   


z"CheckTests.test_stdinReportsErrorsN)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   r   5  s0    
	
1#
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 )Ntemp)rD   rE   rF   r&   rO   rP   tempfilepathr0   r   r   r   rG     s   
zIntegrationTests.setUpc                 C   rH   r   rI   r0   r   r   r   rL     rM   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&   rO   dirname__file__rP   )r   r   package_dirr   r   r   getPyflakesBinary  s   z"IntegrationTests.getPyflakesBinaryNc           	      C   s   t tj}tjtj|d< tj|  g}|	| |r4t
j||t
jt
jt
jd}||d\}}nt
j||t
jt
jd}| \}}| }|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.
        
PYTHONPATH)envr)   r+   r   r   )r  r+   r   r   )dictr&   environpathseprP   r   rO   
executabler  extend
subprocessPopenPIPEcommunicater   waitr   )	r   pathsr)   r  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.
        rN   )r!   r!   r   N)rQ   r  rR   r  rV   )r   dr   r   r   test_goodFile  s   zIntegrationTests.test_goodFilec                 C   sv   t | jd}|d W d   n1 sw   Y  | | jg}t| jtdd}| || tj 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   s   import contraband
Nr   r   r!   )	rQ   r  rp   r  r   r   rV   r&   r'   )r   rr   r  r   r   r   r   test_fileWithFlakes  s    z$IntegrationTests.test_fileWithFlakesc                 C   s4   |  | jg}d| jtj}| |d|df dS )
        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{}: No such file or directory{}r!   r   N)r  r  r   r&   r'   rV   )r   r  	error_msgr   r   r   test_errors_io  s
   zIntegrationTests.test_errors_ioc                 C   sj   t | jd}|d W d   n1 sw   Y  | | jg}d| jtj}| |d|df dS )r  r   s   importNz-{0}:1:7: invalid syntax{1}import{1}      ^{1}r!   r   )rQ   r  rp   r  r   r&   r'   rV   )r   rr   r  r  r   r   r   test_errors_syntax   s   z#IntegrationTests.test_errors_syntaxc                 C   s>   | j g dd}tdtdd}| || tj ddf dS )zU
        If no arguments are passed to C{pyflakes} then it reads from stdin.
        zimport contraband)r)   r   r   r   r!   N)r  r   r   rV   r&   r'   )r   r  r   r   r   r   test_readFromStdin  s    z#IntegrationTests.test_readFromStdinr   )r   r   r   r   rG   rL   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   s   z#t |}t|d W d    n1 sw   Y  W t	dW t	d tyH } z| |jt t|j}|j|j|fW  Y d }~S d }~ww )N)r   zSystemExit not raised)
r    r   
SystemExitassertIsInstancecodeboolintr3   r4   RuntimeError)r   r  r)   capturerk   r  r   r   r   r    s   

zTestMain.runPyflakesr   )r   r   r   r   r  r   r   r   r   r     r   r   ) r   r   r$   r&   r   rJ   r  rD   pyflakes.checkerr   pyflakes.messagesr   pyflakes.reporterr   pyflakes.apir   r   r   r   r	   pyflakes.test.harnessr
   r   r   r   r    r6   rC   r   r   r   r   r   r   r   r   <module>   s2    	|W   b