
    ck                       U d Z ddlm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 ddlmZmZ dd	lm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 e
rddlmZ ej        dk    rddl	mZ nddl mZ h dZ!ej"        ej#        hZ$dddddddddddej%        ifdddd Z&d!e'd"<   d3d+Z( G d, d$          Z) G d- d.ee          Z*d4d2Z+dS )5zPython code format's checker.

By default, try to follow Guido's style guide :

https://www.python.org/doc/essays/styleguide/

Some parts of the process_token method is based from The Tab Nanny std module.
    )annotationsN)reduce)Match)TYPE_CHECKING)nodes)BaseRawFileCheckerBaseTokenChecker)only_required_for_messages)WarningScope)HIGH)MessageDefinitionTuple)	OPTION_POPragmaParserErrorparse_pragma)PyLinter)      )Literal>   ifindelfornotelifwithraisewhileyieldassertexceptreturn=:=)zLine too long (%s/%s)line-too-longz=Used when a line is longer than a given number of characters.)z Too many lines in module (%s/%s)too-many-linesz@Used when a module has too many lines, reducing its readability.)zTrailing whitespacetrailing-whitespacezHUsed when there is whitespace between the end of a line and the newline.)zFinal newline missingmissing-final-newlinez7Used when the last line in a file is missing a newline.)zTrailing newlinestrailing-newlinesz3Used when there are trailing blank lines in a file.)z)Bad indentation. Found %s %s, expected %sbad-indentationzUUsed when an unexpected number of indentation's tabulations or spaces has been found.)zUnnecessary semicolonunnecessary-semicolonzeUsed when a statement is ended by a semi-colon (";"), which isn't necessary (that's python, not C ;).z(More than one statement on a single linemultiple-statementsz<Used when more than on statement are found on the same line.scope)z#Unnecessary parens after %r keywordsuperfluous-parenszLUsed when a single item in parentheses follows an if, for, or other keyword.)zMixed line endings LF and CRLFmixed-line-endingsz@Used when there are mixed (LF and CRLF) newline signs in a file.)zEUnexpected line ending format. There is '%s' while it should be '%s'.unexpected-line-ending-formatz3Used when there is different newline than expected.)C0301C0302C0303C0304C0305W0311W0301C0321C0325C0327C0328z!dict[str, MessageDefinitionTuple]MSGStokensTokenWrapperline_endinttokenstrr!   boolc                    |dk    r|                      |dz
            |k    pG|dk    oA|                      |dz
            |k    o%|                     |dz
            t          j        k    S )Nr         )r@   typetokenizeCOMMENT)r<   r>   r@   s      6lib/python3.11/site-packages/pylint/checkers/format.py_last_token_on_line_isrJ   z   st    1 	0LLA&&%/	:a< :LLA&&%/:KK1%%)99    c                  B    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 )r=   z3A wrapper for readable access to token information.r<   list[tokenize.TokenInfo]r!   Nonec                    || _         d S N_tokens)selfr<   s     rI   __init__zTokenWrapper.__init__   s    rK   idxr?   rA   c                (    | j         |         d         S )NrD   rQ   rS   rU   s     rI   r@   zTokenWrapper.token       |C ##rK   c                (    | j         |         d         S )Nr   rQ   rW   s     rI   rF   zTokenWrapper.type   rX   rK   c                4    | j         |         d         d         S )NrE   r   rQ   rW   s     rI   
start_linezTokenWrapper.start_line       |C #A&&rK   c                4    | j         |         d         d         S )NrE   rD   rQ   rW   s     rI   	start_colzTokenWrapper.start_col   r\   rK   c                (    | j         |         d         S )N   rQ   rW   s     rI   linezTokenWrapper.line   rX   rK   Nr<   rM   r!   rN   )rU   r?   r!   rA   )rU   r?   r!   r?   )
__name__
__module____qualname____doc__rT   r@   rF   r[   r^   ra    rK   rI   r=   r=      s        ==   $ $ $ $$ $ $ $' ' ' '' ' ' '$ $ $ $ $ $rK   c                  x    e Zd ZdZdZeZddddddfd	d
ddddfddddddfddddddfddddddfddddddfddddd dfd!d"d#d$g d%d&d'ffZdT fd,ZdUd1Z	dVd4Z
dWd7ZdXd8ZdYd<Z ed=          dZd?            Zd[dAZd\dCZd]dFZed^dI            Zed_dK            Zed`dN            ZdadPZdbdSZ xZS )cFormatCheckerzvFormatting checker.

    Checks for :
    * unauthorized constructions
    * strict indentation
    * line length
    formatzmax-line-lengthd   r?   z<int>z.Maximum number of characters on a single line.)defaultrF   metavarhelpzignore-long-linesregexpz<regexp>z^\s*(# )?<?https?://\S+>?$z>Regexp for a line that is allowed to be longer than the limit.)rF   rm   rl   rn   zsingle-line-if-stmtFynz<y or n>zOAllow the body of an if to be on the same line as the test if there is no else.zsingle-line-class-stmtzfAllow the body of a class to be on the same line as the declaration if body contains single statement.zmax-module-linesi  z$Maximum number of lines in a module.zindent-stringz    non_empty_stringz<string>zSString used as indentation unit. This is usually "    " (4 spaces) or "\t" (1 tab).zindent-after-parenr`   zGNumber of spaces of indent required inside a hanging or continued line.zexpected-line-ending-formatchoicez<empty or LF or CRLF> )rs   LFCRLFzIExpected format of line ending, e.g. empty (any line ending), LF or CRLF.)rF   rm   rl   choicesrn   linterr   r!   rN   c                f    t                                          |           i | _        i | _        d S rP   )superrT   _lines_visited_lines)rS   rw   	__class__s     rI   rT   zFormatChecker.__init__  s0       &(8:rK   r<   r=   r>   
line_startc                ~   t          ||d          r*|                     d|                    |                     |                    |          }|                    |          }|                    |          t
          vr#|                    d          d         | j        |<   |                     ||||           dS )z9A new line has been encountered, process it if necessary.;r*   ra   
r   N)	rJ   add_messager[   ra   rF   _JUNK_TOKENSsplitrz   check_lines)rS   r<   r>   r}   line_numra   s         rI   new_linezFormatChecker.new_line  s    !&(C88 	X46;L;LX;V;VWWW$$Z00{{:&&;;z"",6 	8$(JJt$4$4Q$7DK!T8<<<<<rK   nodenodes.Modulec                    d S rP   rg   )rS   r   s     rI   process_modulezFormatChecker.process_module  s    rK   rM   startc                   ||dz            j         dk    rdS ||         j         dk    r|dk    r||dz
           j         dk    rdS d}d}d}d}d}t          ||         j                   }||         j        d         }	t          |t	          |          dz
            D ]}
||
         }|j        t          j        k    r dS |j         dk    s|j         ||
dz            j         z   dk    rd	}|}|j         dk    r|dz  }||
dz            j         dk    rd}u|j         d
k    r|dz  }|r$|r||
dz            j         d
k    r|dv r dS |dz  }||
dz            j         dv s3||
dz            j        t          j        t          j	        t          j
        hv r@|r|dz
  |k    r dS |
|dz   k    r dS |r dS |dk    r dS |                     d|	|            dS |dk    r~|d         dk    r dS |d         dv rd	}V|d         dk    r dS |d         dk    r dS |d         dk    r7dd ||
d         D             v r|                     ||
d         d            dS dS )aN  Check that there are not unnecessary parentheses after a keyword.

        Parens are unnecessary if there is exactly one balanced outer pair on a
        line and contains no commas (i.e. is not a tuple).

        Args:
        tokens: The entire list of Tokens.
        start: The position of the keyword in the token list.
        rD   (Nr   r   isFr#   T)>   r   r   r   >   r   r   :]}rE   r   r-   ra   args,>   orandr   r   elsec              3  $   K   | ]}|j         V  d S rP   )string).0is     rI   	<genexpr>z;FormatChecker._check_keyword_parentheses.<locals>.<genexpr>z  s$      <<Aqx<<<<<<rK   )r   rA   r   rangelenrF   rG   NLNEWLINE	ENDMARKERrH   r   _check_keyword_parentheses)rS   r<   r   found_and_orcontains_walrus_operatorwalrus_operator_depthcontains_double_parensdepthkeyword_tokenr   r   r@   s               rI   r   z(FormatChecker._check_keyword_parentheses  sy    %!)#s* 	F5M E)			 uqy!(D0	 F#(  !!"F5M011%=&q)uc&kkAo.. G	 G	A1IE zX[(  $.<&Q-"66$>. ,0((-%|s" 9
!a%='3. /-.*$ 5
 - &Q-2F#2M (,?? %$*a/*!a%='+EE EJ8+X-?AQRJS  0 4IA4MQV4V EAI~ # $,  $$,8- %    ! 8s? FF 8}, #'LL 1X( FF
 1X& FF 1X' <<<<<< G77qrr
AFFFFFOG	 G	rK   c                    dg}d}d}i  _         i  _        d _        d}t          |          D ]\  }\  }}}	}
}|	d         |k    rj|	d         }|t          j        k    r+                     t          |          |dz
  |dz              n'                     t          |          |dz
  |           |t          j        k    rd} 	                    ||           n|t          j        k    rAd} 
                    ||d         dz   |           |                    |d         dz              n|t          j        k    rd}t          |          dk    r|d= nc|t          j        k    r|                    d          s|}n;|t          j        t          j        fvr!|rd} 
                    ||d         |           |t          j        k    r,|                    d          r                     d	|
           |t*          v r                     ||           |dz  }| j        j        j        k    r j        j                            d          d         }|j        df}t;          t=          d fd|D                       d          }                     d| j        j        j        f|           ||k    r|dk    r                     d|
           dS dS dS )zProcess tokens and search for:

        - too long lines (i.e. longer than <max_chars>)
        - optionally bad construct (if given, bad_construct must be a compiled
          regular expression).
        r   FNrD   T
lzlowercase-l-suffixr   r%   c              3  V   K   | ]#}j         j                            |          V  $d S rP   )rw   _pragma_linenoget)r   namerS   s     rI   r   z/FormatChecker.process_tokens.<locals>.<genexpr>  s6      UUtdk8<<TBBUUUUUUrK   r   ra   r(   )rz   r{   _last_line_ending	enumeraterG   INDENTr   r=   r   _check_line_endingcheck_indent_levelappendDEDENTr   r   striprH   ENCODINGNUMBERendswithr   _KEYWORD_TOKENSr   rw   configmax_module_lines
msgs_storeget_message_definitionsmsgidnextfilter)rS   r<   indentscheck_equalr   last_blank_line_numrU   tok_typer   r   _ra   message_definitionnameslinenos   `              rI   process_tokenszFormatChecker.process_tokens~  sm    # -17@7H7H 1	= 1	=3C3(FE1dQx8# F 8 x. FMM,v"6"6aqIIIIMM,v"6"6aEEE8++  I #''9999X_, I#''aJJJwr{Q////X_, I
 #w<<!# $X[( Izz&)) 3*2'("2H4E!FF 	I  I"'K++D'"+xHHH8?* Fvs/C/C F  !5H EEE( =//<<<Adk(99 	 "&!7!O!O " "" (-/?@EtUUUUuUUUVV F   2 CD     ** 	Ax!| 	A0x@@@@@	A 	A 	A 	ArK   line_endingrA   r   c                   | j         $|r"|| j         k    r|                     d|           || _         | j        j        j        }|r>t          d |d          }|dk    rdnd}||k    r|                     d||f|	           d S d S d S )
Nr.   r   c                    | |k    r| |z   n| S rP   rg   )xys     rI   <lambda>z2FormatChecker._check_line_ending.<locals>.<lambda>  s    qAv.Da!ee1 rK   rs   r   rt   ru   r/   r   )r   r   rw   r   expected_line_ending_formatr   )rS   r   r   expecteds       rI   r   z FormatChecker._check_line_ending  s    ! 	F  F{d.DD F  !5H EEE!, ;%A 		 !D!DkSUVVK"-"5A$$6Kh&   3%x0! !     		 		 rK   r+   nodes.NodeNGc                   |j         sdS |                                j        sdS |                                }||j        }nt          |j        t          j                  r)||j        j	        v r|j        j
        d         j        dz   }nBt          |j        t          j                  rd}n |j                            d          j        }|j        }|s
J |            ||k    r6| j                            |          dk    r|                     ||           dS || j        v rdS 	 |j        }n# t$          $ r
 |j        }Y nw xY w|s
J |            g }t'          ||dz             D ]d}d| j        |<   	 |                    | j        |                                                    @# t.          $ r |                    d           Y aw xY wdS )z8Check the node line number and check it if not yet done.Nr   rD   T)futurerE   rs   )is_statementrootpure_pythonprevious_sibling
fromlineno
isinstanceparentr   
TryFinally	finalbodybodytolinenoModule	statementr{   r   _check_multi_statement_lineblockstart_tolinenoAttributeErrorr   r   rz   rstripKeyError)rS   r   	prev_sibl	prev_linera   r   liness          rI   visit_defaultzFormatChecker.visit_default  s(      	Fyy{{& 	F))++	 	F!,II t{E$455	F:>$+BW:W	F (+4q8IIU\22 	FII--T-::EIT 	!4!8!8!>!>!!C 	,,T4888F4&& 	F	%/HH 	% 	% 	%}HHH	%$1-- 	! 	!D()D%!T[.55778888 ! ! !R     !		! 	!s$   (D0 0EE52F((G
	G
ra   c                   t          |t          j                  rdS t          |t          j                  r!t          |j        t          j                  rdS t          |j        t          j                  r|j        j        s| j        j	        j
        rdS t          |j        t          j                  r0t          |j        j                  dk    r| j        j	        j        rdS t          |j        t          j                  rNt          |t          j                  r4t          |j        t          j                  r|j        j        t&          u rdS |                     d|           d| j        |<   dS )z/Check for lines containing multiple statements.NrD   r+   )r   rE   )r   r   With	TryExceptr   r   Iforelserw   r   single_line_if_stmtClassDefr   r   single_line_class_stmtFunctionDefExprvalueConstEllipsisr   r{   )rS   r   ra   s      rI   r   z)FormatChecker._check_multi_statement_line  sg    dEJ'' 	F dEO,, 	K)2
 2
 	 Ft{EH--	K&	 "6	
 Ft{EN33	DK$%%*	 "9	
 F t{E$566	4,,	 4:u{33	 
 H,		 F.T:::$%D!!!rK   r   c                    |                     d          }|t          |          d         dvr-|                     d|t          |          t                     dS dS )z,Check that there is no trailing white-space.z	
 N)r   r   r&   )ra   
col_offset
confidence)r   r   r   r   )rS   ra   r   stripped_lines       rI    check_trailing_whitespace_endingz.FormatChecker.check_trailing_whitespace_ending=  sz     K00M""$$%^; 	%}--	      	 	rK   checker_offrB   c                V   | j         j        j        }| j         j        j        }|                                }t          |          |k    r]|                    |          sJ|r| j                             d|           dS |                     d|t          |          |f           dS dS dS )z=Check that the line length is less than the authorized value.r$   r   N)	rw   r   max_line_lengthignore_long_linesr   r   searchadd_ignored_messager   )rS   ra   r   r  	max_charsignore_long_lines         rI   check_line_lengthzFormatChecker.check_line_lengthI  s    K&6	;-?{{}}t99y  	W)9)@)@)F)F 	W W//CCCCC  qD		9?U VVVVV		W 	W 	W 	WrK   options_pattern_obj
Match[str]c                    | j         }|d|                     d                                                   ||                     d          d         z   }|S )z-Remove the `# pylint ...` pattern from lines.NrD   )r   r   r   end)r  r   purged_liness      rI   remove_pylint_option_from_linesz-FormatChecker.remove_pylint_option_from_linesT  sd     $*0'--a000188::'++A..0012 	 rK   pylint_pattern_match_objectc                    	 t          |                     d                    D ]}|j        dk    rd|j        v r dS n# t          $ r Y nw xY wdS )z2Return True if the line length check is activated.rE   disabler$   FT)r   groupactionmessagesr   )r  pragmas     rI   is_line_length_check_activatedz,FormatChecker.is_line_length_check_activated^  s    	&'B'H'H'K'KLL ! !=I- !/V_2T ! 55! ! 	 	 	D	 ts   9? ? 
AAr   	list[str]c                    h d}g }d}|                      d          D ],}|d         |vr|                    ||z              d}'||z  }-|S )z]Split lines according to universal newlines except those in a specific
        sets.
        >              rs   Tr   )
splitlinesr   )r   unsplit_endsresbufferatomic_lines        rI   specific_splitlinesz!FormatChecker.specific_splitlinesj  s|    
	
 	
 	
  ++D11 	& 	&K2l2 &

6K/000+%
rK   r   c                   | j         j        j        |                     |          }t	          |          D ]q\  }}|                    d          s|                     d||z              5|                    |          t          j	        k    r| 
                    |||z              rt          fd|D                       }|sdS t          j        |          }	d}
|	r,|                     |	          sd}
|                     |	          }t	          |                     |                    D ]\  }}|                     |||z   |
            dS )zCheck given lines for potential messages.

        Check if lines have:
        - a final newline
        - no trailing white-space
        - less than a maximum number of characters
        r   r'   r   c              3  >   K   | ]}t          |          k    V  d S rP   )r   )r   ra   r	  s     rI   r   z,FormatChecker.check_lines.<locals>.<genexpr>  s?       ,
 ,
&*CII	!,
 ,
 ,
 ,
 ,
 ,
rK   NFT)rw   r   r  r)  r   r   r   rF   rG   STRINGr  anyr   r  r  r  r  )rS   r<   r}   r   r   split_linesoffsetra   potential_line_length_warningmobjr  r	  s              @rI   r   zFormatChecker.check_lines  s   $ K&6	..u55%k22 	M 	MLFD==&&   !8v OOO {{:&&(/9 M55dFVOLLL ), ,
 ,
 ,
 ,
.9,
 ,
 ,
 )
 )
% - 	F && 	?66t<< #"88>>E &d&>&>u&E&EFF 	G 	GLFD""4&+FFFF	G 	GrK   r   r   c                   | j         j        j        }|dk    rd}d}t          |          }|d|         |k    r||d         }|dz  }|d|         |k    d}|r+|d         dv r!||d         z  }|dd         }|r
|d         dv !||k    s|rCd}|d         dk    rd	}|                     d
|||z  t          |          z   |||z  f           dS dS )z&Return the indent level of the string.z\t	r   NrD   rs   z 	spacestabsr)   r   )rw   r   indent_stringr   r   )	rS   r   r   r   indentlevel	unit_sizesuppli_types	            rI   r   z FormatChecker.check_indent_level  sP   #1U? 	FKK	ZiZ F* 	IJJ'FQJE ZiZ F* 	  	 e+ 	 VAYEABBZF  	 e+ 	  H 	 	FayD   !i'#e**4fh>RS      		 	rK   rw   r   r!   rN   )r<   r=   r>   r?   r}   r?   r!   rN   )r   r   r!   rN   )r<   rM   r   r?   r!   rN   rb   )r   rA   r   r?   r!   rN   )r   r   r!   rN   )r   r   ra   r?   r!   rN   )ra   rA   r   r?   r!   rN   )ra   rA   r   r?   r  rB   r!   rN   )r  r  r!   rA   )r  r  r!   rB   )r   rA   r!   r  )
r<   r=   r}   r?   r   rA   r   r?   r!   rN   )r   rA   r   r?   r   r?   r!   rN   )rc   rd   re   rf   r   r;   msgsoptionsrT   r   r   r   r   r   r
   r   r   r  r  staticmethodr  r  r)  r   r   __classcell__)r|   s   @rI   ri   ri      s         DD
 "H	 	
   %8T 
	
 " %< 	
 % %(	 		
 ">	 	
 !*%6	 		
 !"%	 		
 * 2---@	 		
WXGt; ; ; ; ; ;
	= 	= 	= 	=   e e e eNVA VA VA VAp   0   566'! '! '! 76'!R#& #& #& #&J
 
 
 
	W 	W 	W 	W    \ 	 	 	 \	    \06G 6G 6G 6Gp       rK   ri   rw   r   rN   c                J    |                      t          |                      d S rP   )register_checkerri   )rw   s    rI   registerrC    s$    
M&1122222rK   )r<   r=   r>   r?   r@   rA   r!   rB   r<  ),rf   
__future__r   sysrG   	functoolsr   rer   typingr   astroidr   pylint.checkersr   r	   pylint.checkers.utilsr
   pylint.constantsr   pylint.interfacesr   pylint.typingr   pylint.utils.pragma_parserr   r   r   pylint.lintr   version_infor   typing_extensionsr   rH   r   r   NODEr;   __annotations__rJ   r=   ri   rC  rg   rK   rI   <module>rU     ss  
   # " " " " " 



                                @ @ @ @ @ @ @ @ < < < < < < ) ) ) ) ) ) " " " " " " 0 0 0 0 0 0 Q Q Q Q Q Q Q Q Q Q %$$$$$$v *))))))  "  (+.




 	3F	,#$	
o<+ <+ < < < <~   $ $ $ $ $ $ $ $,w w w w w$&8 w w wt3 3 3 3 3 3rK   