K ijd@dZddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z ddlmZmZmZmZmZddlmZmZdZGd d ZGd d ZGd dZGddeZGddeZGddeZGddeZGddeZy)z) Tests for L{pyflakes.scripts.pyflakes}. N)PYPY) UnusedImport)Reporter)maincheck checkPathcheckRecursiveiterSourceCode)TestCaseskipIfctj|c}t_ ||i||t_S#|t_wxYw)z? Call C{f} with C{sys.stderr} redirected to C{stderr}. )sysstderr)rfargskwargsouters \/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/pyflakes/test/test_api.py withStderrTors7::vUCJ$!&! U s1 >ceZdZdZddZy)Nodez Mock an AST node. c ||_||_yN)lineno col_offset)selfrrs r__init__z Node.__init__)s $N)r)__name__ __module__ __qualname____doc__rrrrr%s %rrc"eZdZdZdZdZdZy)SysStreamCapturingzContext manager capturing sys.stdin, sys.stdout and sys.stderr. The file handles are replaced with a StringIO object. c`tj|xsdtj|_y)Nnewline)ioStringIOoslinesep_stdin)rstdins rrzSysStreamCapturing.__init__4skk%+2rzzB rc~tj|_tj|_tj |_|jt_tjtjxt_|_ tjtjxt_|_ |S)Nr()rr/ _orig_stdinstdout _orig_stdoutr _orig_stderrr.r*r+r,r-_stdout_stringio_stderr_stringiors r __enter__zSysStreamCapturing.__enter__7sn99JJJJKK -/[[-LL T*-/[[-LL T* rc|jj|_|jj|_|j t _|jt _ |jt _ yr) r5getvalueoutputr6errorr1rr/r3r2r4r)rrs r__exit__zSysStreamCapturing.__exit__BsU++446 **335 $$ && && rN)rr r!r"rr8r=r#rrr%r%.s C 'rr%c(eZdZdZdZdZdZdZy)LoggingReporterzK Implementation of Reporter that just appends any error to a list. c||_y)zh Construct a C{LoggingReporter}. @param log: A list to append log messages to. N)log)rrAs rrzLoggingReporter.__init__Ps rcP|jjdt|fy)Nflake)rAappendstr)rmessages rrCzLoggingReporter.flakeXs #g,/0rc@|jjd||fy)NunexpectedErrorrArD)rfilenamerFs rrHzLoggingReporter.unexpectedError[s *Hg>?rcF|jjd|||||fy)N syntaxErrorrI)rrJmsgroffsetlines rrLzLoggingReporter.syntaxError^s #vvtLMrN)rr r!r"rrCrHrLr#rrr?r?Ks1@Nrr?cLeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z y ) TestIterSourceCodez& Tests for L{iterSourceCode}. c6tj|_yr)tempfilemkdtemptempdirr7s rsetUpzTestIterSourceCode.setUpgs'') rcBtj|jyrshutilrmtreerUr7s rtearDownzTestIterSourceCode.tearDownj dll#rc|sJtjj|jg|}t |dj |S)Na)r,pathjoinrUopenclose)rpartsfpaths r makeEmptyFilez TestIterSourceCode.makeEmptyFilems< u T\\2E2 UC  rcb|jtt|jggy)zB There are no Python files in an empty directory. N) assertEquallistr rUr7s rtest_emptyDirectoryz&TestIterSourceCode.test_emptyDirectoryss$ ndll^<=rBrc|jd}|jtt|jg|gy)zd If the directory contains one Python file, C{iterSourceCode} will find it. foo.pyNrergrhr rU)r childpaths rtest_singleFilez"TestIterSourceCode.test_singleFileys6 &&x0  ndll^<= {Krc|jd|jtt|jggy)zJ Files that are not Python source files are not included. zfoo.pycNrlr7s rtest_onlyPythonSourcez(TestIterSourceCode.test_onlyPythonSources2 9% ndll^<=rBrctjtjj|jd|j dd}|j ddtjtjj|jd|j dd}|j d}|j tt|jgt|||gy)zk If the Python files are hidden deep down in child directories, we will find them. fooa.pyza.py~barb.pyzc.pyN) r,mkdirr_r`rUrergsortedr )rapathbpathcpaths r test_recursesz TestIterSourceCode.test_recursess dllE23""5&1 5'* dllE23""5&1""6*  >4<<.1 2 E5%( ) +rc jtjj|jd}t |d5}|j dddd|j dt tjj|jdd5}|j ddddtjj|jd}t |d5}|j d dddtjj|jd }t |d5}|j d dddtjj|jd }t |d5}|j d dddtjj|jd}t |d5}|j ddddtjj|jd}t |d5}|j ddddtjj|jd}t |d5}|j dddd|jtt|jgt||||||gy#1swYxYw#1swY6xYw#1swYxYw#1swYxYw#1swYmxYw#1swY*xYw#1swYxYw#1swYxYw)zd Find Python files that don't end with `.py`, but contain a Python shebang. r^wz#!/usr/bin/env python Nbcz hello world ez#!/usr/bin/env python3 rz#!/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,r_r`rUrawriterergrwr ) rpythonfdpython3pythonw python3argspython3d python38mnotfirsts r test_shebangzTestIterSourceCode.test_shebangs dllC0 &#  0" HH. / 0 3 "'',,t||S13 7 '2 HH% & ''',,t||S1 '3  12 HH/ 0 1'',,t||S1 '3  12 HH/ 0 1ggll4<<5 +s # 0r HH. / 077<< c2 (C  4B HH2 3 4GGLLs3 )S ! 5R HH3 4 577<< c2 (C  7B HH5 6 7  >4<<.1 2 +x  C 0 0  ' ' 1 1 1 1 0 0 4 4 5 5  7 7s_KK&K)6K6LL&L6L)KK&)K36LL LL&)L2ctjj|jd}tjj|jd}tj||j dd}tj||j dd}|j tt||gt||gy)zr L{iterSourceCode} can be given multiple directories. It will recurse into each of them. rrrtrsruN) r,r_r`rUrvrergrwr )rfoopathbarpathrxrys rtest_multipleDirectoriesz+TestIterSourceCode.test_multipleDirectoriess '',,t||U3'',,t||U3 ""5&1 ""5&1  >7G"45 6 E5> " $rcr|jd}|jtt|g|gy)z If one of the paths given to L{iterSourceCode} is not a directory but a file, it will include that in its output. ze.pyN)rergrhr )repaths rtest_explicitFilesz%TestIterSourceCode.test_explicitFiless5 ""6* neW56 "rN)rr r!r"rVr[rerirnrpr{rrrr#rrrQrQbs=*$ C LC +,\ $"rrQc4eZdZdZdZdZdZdZdZdZ y) TestReporterz Tests for L{Reporter}. ctj}td|}|jddddd|j d|j y)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. Nrk a problembad line of sourcez2foo.py:3:8: a problem bad line of source ^ r*r+rrLrgr:rerrreporters rtest_syntaxErrorzTestReporter.test_syntaxErrorsPkkmD#&X{Aq:NO  LLN  rctj}td|}|jddddd|j d|j y)zy C{syntaxError} doesn't include a caret pointing to the error if C{offset} is passed as C{None}. Nrkrrrz'foo.py:3: a problem bad line of source rrs rtest_syntaxErrorNoOffsetz%TestReporter.test_syntaxErrorNoOffsetsP kkmD#&X{At1 3 $ LLN rctj}td|}|jddddd|j d|j y)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. Nrrz:1:1: a problem rrs rtest_syntaxErrorNoTextz#TestReporter.test_syntaxErrorNoTextsH kkmD#&Y Q4@ 4s||~Frc tj}ddg}td|}|jdddt |ddzd j ||j d |d zd zd zd z|jy)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. rzmore bad lines of sourceNrkrrr zfoo.py:3:25: a problem z ^ )r*r+rrLlenr`rgr:)rrlinesrs rtest_multiLineSyntaxErrorz&TestReporter.test_multiLineSyntaxError s kkm & D#&X{As58}q7H!YYu- /  ' 2Y  LLN  rctj}td|}|jdd|j d|j y)zO C{unexpectedError} reports an error processing a source file. Nz source.pyz error messagezsource.py: error message )r*r+rrHrgr:rs rtest_unexpectedErrorz!TestReporter.test_unexpectedError sBkkmD#&  o> 5s||~Frctj}t|d}tdt dd}|j ||j |j|dy)z C{flake} reports a code warning from Pyflakes. It is exactly the str() of a L{pyflakes.messages.Message}. Nrk*rtr)r*r+rrrrCrgr:)routrrFs r test_flakezTestReporter.test_flake)sU kkmC&xb59w G9B8rN) rr r!r"rrrrrrr#rrrrs'  G(G 9rrceZdZdZej dZdZdZdZ dZ dZ dZ d Z d Zd Zd Zd Zeej(dk(ddZdZdZdZdZdZdZdZy) CheckTestszL Tests for L{check} and L{checkPath} which check a file for flakes. c#TKtj\}} tj|d5}t |ds|j d}|j |ddd|tj|y#1swY#xYw#tj|wxYww)zV Make a temporary file containing C{content} and return a path to it. wbdecodeasciiN)rSmkstempr,fdopenhasattrencoderremove)rcontentrnamers r makeTempFilezCheckTests.makeTempFile:s ##%D 2t$ !w1%nnW5G  !J IIdO  ! ! IIdOs3B(B/B B,B(B BB%%B(ctj}t|t|}|j ||j ft |dj|fy)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+rrrgr:rr`)rr_ errorListrcounts rassertHasErrorszCheckTests.assertHasErrorsIsNkkmS)T2  CLLN #c)nbggi6H%I Krc<g}t|}t||}||fS)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. )r?r)rr_rArrs r getErrorszCheckTests.getErrorsUs)"3'$)czrcPddlm}|j|jty)Nr)pyflakes)pyflakes.scriptsrassertIsr)rscript_pyflakess rtest_legacyScriptzCheckTests.test_legacyScriptcs@ o//;rct|jd5}|j|gdddy#1swYyxYw)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}. zdef foo(): pass Nrr)rfNames rtest_missingTrailingNewlinez&CheckTests.test_missingTrailingNewlinegs:   7 8 ,E   + , , ,.7cv|jd\}}|j|d|j|dgy)z: L{checkPath} handles non-existing files. extremo)rHrzNo such file or directoryN)rrg)rrerrorss rtest_checkPathNonExistingz$CheckTests.test_checkPathNonExistingps>y1 v "   H I Krc d}d} |||j|j|5}trd}ntjdk\rd}nd }tstjdk\rd }nd }|j|d |||d |dz zfzgdddy#t$rP}ts@tjdkr-|j |j jddkDYd}~d}~wwxYw#1swYyxYw)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''' ct|yr)exec)sources revaluatez6CheckTests.test_multilineSyntaxError..evaluates Lrr rrNz=end of file (EOF) while scanning triple-quoted string literalz>unterminated triple-quoted string literal (detected at line 8)invalid syntax rz%s:8:%d: %s '''quux''' %s^  ) fail SyntaxErrorrr version_info assertTruetextrrr)rrrr sourcePathrFcolumns rtest_multilineSyntaxErrorz$CheckTests.test_multilineSyntaxErrorzs    V  IIK   v & :*Y!!W,Z*s''72  67C6A:$67 89 : : :  8C,,w6 T 2Q 67 8  : :s$BA C5 C2"AC--C25C>c,|jd5}trd}ntjdk\rd}nd}tstjdk\rd}nd}d|d z z}d j ||||}|j ||gd d d y #1swYy xYw) The error reported for source files which end prematurely causing a syntax error reflects the cause for the syntax error. zdef foo(zparenthesis is never closedrz'(' was never closedzunexpected EOF while parsingr rrz{}:1:{}: {} def foo( {}^ N)rrrrformatr)rrrMrspacesexpecteds rtest_eofSyntaxErrorzCheckTests.test_eofSyntaxErrors   z * 9j3!!W,,4s''72FQJ'F5<<FCH  hZ 8% 9 9 9s A/B  Bc||jd5}|j||dgdddy#1swYyxYw)rzif True: foo =z$:2:7: invalid syntax foo = ^ Nrrrs rtest_eofSyntaxErrorWithTabz%CheckTests.test_eofSyntaxErrorWithTabsO   2 3 z        s2;c d}|j|5}tjdk\rd}nd}trd}ntjdk\rd}nd}d|d z zd z}|j ||d |d |d |gdddy#1swYyxYw)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 rrz:1:5: Generator expression must be parenthesizedz,max(1 for i in range(10), key=lambda x: x+1)z ^)r*r+rrrgr:split)rrrrerrlinesexpected_errors rtest_stdinReportsErrorsz"CheckTests.test_stdinReportsErrorsskBkkmS%; "<<>''-cr2  >2rN)rr r!r" contextlibcontextmanagerrrrrrrrrrrrrr rplatformrr rrrrr$r)r#rrrr5s   K <,K/:b92 >$.2 CLLG #%=>H?H T 11 y9$#43rrcHeZdZdZdZdZdZd dZdZdZ d Z d Z d Z y) IntegrationTestszF Tests of the pyflakes script that actually spawn the script. ctj|_tjj |jd|_y)Ntemp)rSrTrUr,r_r` tempfilepathr7s rrVzIntegrationTests.setUps-'') GGLLv>rcBtj|jyrrXr7s rr[zIntegrationTests.tearDownr\rcddl}tjj|j}tjj |dddS)z9 Return the path to the pyflakes binary. rNz..binr)rr,r_dirname__file__r`)rr package_dirs rgetPyflakesBinaryz"IntegrationTests.getPyflakesBinarys8 ggooh&7&78 ww||KujAArNcttj}tjj t j |d<t j|jg}|j||rhtj||tjtjtj}|j|jd\}}nHtj||tjtj}|j\}}|j}|j!d}|j!d}|||fS)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/r2rr)r;r2rr )dictr,environpathsepr`rr_ executabler8extend subprocessPopenPIPE communicaterwaitr) rpathsr/r;commandpr2rrvs r runPyflakeszIntegrationTests.runPyflakess2::JJOOCHH5L>>4#9#9#;<u   c(2 QA }}U\\'-BC VV  c(2 QA }} VV VVXw'w'##rct|jdj|j|jg}|j |dy)z When a Python source file is all good, the return code is zero and no messages are printed to either stdout or stderr. r^)r'r'rN)rar1rbrJrg)rds r test_goodFilezIntegrationTests.test_goodFilesF T  $**,   d//0 1 K(rcBt|jd5}|jdddd|j|jg}t |jt dd}|j ||tjddfy#1swYmxYw)z When a Python source file has warnings, the return code is non-zero and the warnings are printed to stdout. rsimport contraband Nrr r') rar1rrJrrrgr,r-)rrrLrs rtest_fileWithFlakesz$IntegrationTests.test_fileWithFlakess $##T * -b HH+ , -   d//0 1 1 147LI z"**6A>?  - -s BBc|j|jg}dj|jtj}|j |d|dfy) 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'rN)rJr1rr,r-rg)rrL error_msgs rtest_errors_iozIntegrationTests.test_errors_iosT   d//0 15<?rr) rr r!r"rVr[r8rJrMrOrSrUrWr#rrr.r.s7?$B$4) @ 00&@rr.ceZdZdZddZy)TestMainz. Tests of the pyflakes main function. Nc: t|5}t|dddtd#1swYxYw#t$rX}|j |j t t|j }j|j|fcYd}~Sd}~wwxYw)N)rzSystemExit not raised) r%r RuntimeError SystemExitassertIsInstancecodeboolintr;r<)rrFr/capturerrIs rrJzTestMain.runPyflakess 8#E* !g%  !67 7 ! ! 7  ! !!&&$ /QVVBNNGMM26 6 7s, 9 -969 BA BBBr)rr r!r"rJr#rrrYrYs  8rrY) r"r*r*r,rrYrArSpyflakes.checkerrpyflakes.messagesrpyflakes.reporterr pyflakes.apirrrr r pyflakes.test.harnessr r rrr%r?rQrrr.rYr#rrrgs !*&3%%'':NN.y"y"xT98T9n`3`3F e@xe@P 8 8r