o
    gv                     @   sT  d 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mZmZ ddlmZ dd	lmZmZmZ dd
lmZmZmZ dZg dZg dZg dZg dZdZeej ej!ej"gZ#ej"ej!fZ$dZ%dZ&dZ'dddddddddddej(ifddd d!Z)d"d# Z*d$Z+d%Z,d&Z-d'Z.d(Z/d)Z0d*Z1G d+d, d,Z2G d-d. d.e	Z3d/d0 Z4dS )1zPython 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.
    N)reduce)List)nodes)BaseTokenChecker)check_messagesis_overload_stubis_protocol_classnode_frame_class)WarningScope)IAstroidCheckerIRawCheckerITokenChecker)	OPTION_POPragmaParserErrorparse_pragmaasync)assertdelelifexceptforifinnotraisereturnwhileyieldwith)z==<>z!=z<>z<=z>=z+=z-=z*=z**=z/=z//=z&=z|=z^=z%=z>>=z<<=)([{))]}         )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C0328c                 C   sH   |dkr|  |d |kp#|dko#|  |d |ko#| |d tjkS )Nr   r(   r)   )tokentypetokenizeCOMMENT)tokensline_endrA    rG   T/home/ubuntu/cloudmapper/venv/lib/python3.10/site-packages/pylint/checkers/format.py_last_token_on_line_is   s   rI   z
dict-valuehangingzhanging-block	continuedzcontinued-blocksinglemultic                   @   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 )TokenWrapperz3A wrapper for readable access to token information.c                 C   s
   || _ d S N_tokens)selfrE   rG   rG   rH   __init__   s   
zTokenWrapper.__init__c                 C      | j | d S )Nr(   rP   rR   idxrG   rG   rH   rA         zTokenWrapper.tokenc                 C   rT   )Nr   rP   rU   rG   rG   rH   rB      rW   zTokenWrapper.typec                 C      | j | d d S )Nr)   r   rP   rU   rG   rG   rH   
start_line      zTokenWrapper.start_linec                 C   rX   )Nr)   r(   rP   rU   rG   rG   rH   	start_col   rZ   zTokenWrapper.start_colc                 C   rT   )N   rP   rU   rG   rG   rH   line   rW   zTokenWrapper.lineN)
__name__
__module____qualname____doc__rS   rA   rB   rY   r[   r]   rG   rG   rG   rH   rN      s    rN   c                   @   s  e Zd ZdZeeef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dSd)d*Zd+d, Zd-ejd.d(fd/d0Zd1eej d2ed.d(fd3d4Zd5d6 Zd7d8 Zd9d: Zed;d<ejd.d(fd=d>Zd?d@ ZdAedBed.d(fdCdDZdAedBed.d(fdEdFZe d.efdGdHZ!e d.e"fdIdJZ#e dKed.ee fdLdMZ$dKedNed.d(fdOdPZ%dQdR Z&d(S )TFormatCheckerz]checks for :
    * unauthorized constructions
    * strict indentation
    * line length
    formatzmax-line-lengthd   intz<int>z.Maximum number of characters on a single line.)defaultrB   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.)rB   rg   rf   rh   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> )rm   LFCRLFzIExpected format of line ending, e.g. empty (any line ending), LF or CRLF.)rB   rg   rf   choicesrh   Nc                 C   s$   t | | d | _d | _d g| _d S rO   )r   rS   _lines_visited_lines_bracket_stack)rR   linterrG   rG   rH   rS   Q  s   zFormatChecker.__init__c                 C   sf   t ||dr| jd||d ||}||}||tvr+|dd | j|< | || dS )z8a new line has been encountered, process it if necessary;r0   r]   
r   N)	rI   add_messagerY   r]   rB   _JUNK_TOKENSsplitrq   check_lines)rR   rE   rF   
line_startline_numr]   rG   rG   rH   new_lineW  s   

zFormatChecker.new_line_noder   c                 C   s   d S rO   rG   )rR   r   rG   rG   rH   process_moduleb  s   zFormatChecker.process_modulerE   startc                 C   s  | j d dkr|| jdkr| j   ||d  jdkrdS d}d}d}d}d}t|| j}|| jd }	t|t|d D ]}
||
 }|jtj	krO dS |jd	ks`|j||
d  j d	krdd
}|}|jdkry|d7 }||
d  jdkrxd}q?|jdkr|d8 }|r|r||
d  jdkr|dv rq? dS |d8 }q?||
d  jdv s||
d  jtj
tjtjfv r|r|d |kr dS |
|d kr dS |dkr|s| jd|	|d  dS |dv r| jd|	|d  dS |s|dkr| jd|	|d  dS |dkrH|d dkr dS |d dv rd
}q?|d dkr dS |d dkr& dS |d dkrHddd ||
d D v rE| ||
d d  dS q?dS )a  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 it is followed by a colon, and contains no commas (i.e. is not a
        tuple).

        Args:
        tokens: list of Tokens; the entire list of Tokens.
        start: int; the position of the keyword in the token list.
        :r   r(   r!   NFr   z:=Tr$   >   r   r   r   )r   r$   r%   r&   r   r)   r   r3   r]   args)r   r   r   ,)andorr   elsec                 s   s    | ]}|j V  qd S rO   )string).0irG   rG   rH   	<genexpr>  s    z;FormatChecker._check_keyword_parentheses.<locals>.<genexpr>)rs   r   popstrr   rangelenrB   rC   NLNEWLINE	ENDMARKERrD   rx   _check_keyword_parentheses)rR   rE   r   found_and_orcontains_walrus_operatorwalrus_operator_depthcontains_double_parensdepthkeyword_tokenr}   r   rA   rG   rG   rH   r   e  s   




z(FormatChecker._check_keyword_parenthesesc                 C   s0   i }t | jffD ]\}}|D ]}|||< qq|S rO   )_KEYWORD_TOKENSr   )rR   dispatchrE   handlerrA   rG   rG   rH   _prepare_token_dispatcher  s   
z'FormatChecker._prepare_token_dispatcherc              	      s<  dg _ dg}d}d}i  _i  _  }d _d}t|D ]\}\}}	}
}}|
d |krO|
d }|tjkrD t	||d |d  n t	||d | |tj
kr]d} |	| nO|tjkryd} |	|d d | ||d d  n3|tjkrd}t|dkr|d= n"|tjkr|ds|}n|tjtjfvr|rd} ||d | |tjkr|	dr jd	|d
 z||	 }W n	 ty   Y qw ||| q|d8 }| jjkr jjdd }|jdf}ttd fdd|D d} jd| jjf|d ||kr|dkr jd|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).
        Nr   Fr(   Tr   
lzlowercase-l-suffixrv   r+   c                 3   s    | ]
} j j|V  qd S rO   )rt   _pragma_linenoget)r   namerR   rG   rH   r   "  s    z/FormatChecker.process_tokens.<locals>.<genexpr>r   r]   r.   ) rs   rq   rr   r   _last_line_ending	enumeraterC   INDENTr~   rN   r   _check_line_endingcheck_indent_levelappendDEDENTr   r   striprD   ENCODINGNUMBERendswithrx   KeyErrorconfigmax_module_linesrt   
msgs_storeget_message_definitionsmsgidnextfilter)rR   rE   indentscheck_equalr}   token_handlerslast_blank_line_numrV   tok_typerA   r   _r]   r   message_definitionnamesrG   r   rH   process_tokens  s~   







zFormatChecker.process_tokensc                 C   s   | j d ur|r|| j kr| jd|d || _ | jj}|r<tdd |d}|dkr*dnd}||kr>| jd	||f|d
 d S d S d S )Nr4   rv   c                 S   s   | |kr| | S | S rO   rG   )xyrG   rG   rH   <lambda>?  s    z2FormatChecker._check_line_ending.<locals>.<lambda>rm   rw   rn   ro   r5   r   )r   rx   r   expected_line_ending_formatr   )rR   line_endingr}   expectedrG   rG   rH   r   0  s    

z FormatChecker._check_line_endingr1   nodec              	   C   s<  |j sdS | jsdS | }|dur|j}nt|jtjr/||jj	v r/|jj
d jd }n|j j}|j}|s>J |||krR| j|dkrR| || dS || jv rYdS z|j}W n tyj   |j}Y nw |sqJ |g }t||d D ]!}d| j|< z|| j|   W qz ty   |d Y qzw dS )z7check the node line number and check it if not yet doneNr   r(   r)   rm   )is_statementrootpure_pythonprevious_sibling
fromlineno
isinstanceparentr   
TryFinally	finalbodybodytolineno	statementrr   r   _check_multi_statement_lineblockstart_tolinenoAttributeErrorr   r   rq   rstripr   )rR   r   	prev_sibl	prev_liner]   r   linesrG   rG   rH   visit_defaultH  sD   




zFormatChecker.visit_defaultc                 C   s   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	r(dS t |jtj
r=t|jjdkr=| jjr=dS t |tjr`t |jtjr`|jjtu r`| }t|s^tt|r`dS | jd|d d| j|< dS )z/Check for lines containing multiple statements.Nr(   r1   )r   r)   )r   r   With	TryExceptr   r   Iforelser   single_line_if_stmtClassDefr   r   single_line_class_stmtExprvalueConstEllipsisframer   r   r	   rx   rr   )rR   r   r]   r   rG   rG   rH   r   p  s:   
z)FormatChecker._check_multi_statement_liner]   r   c                 C   sV   | ds| jd|d dS |d}|t|d dvr)| jd|t|d dS dS )	zg
        Check that the final newline is not missing and that there is no trailing whitespace.
        rw   r-   rv   Nz	
 )rw   r   r,   )r]   
col_offset)r   rx   r   r   )rR   r]   r   stripped_linerG   rG   rH   check_line_ending  s   



zFormatChecker.check_line_endingc                 C   sR   | j j}| j j}| }t||kr%||s'| jd|t||fd dS dS dS )zN
        Check that the line length is less than the authorized value
        r*   r   N)r   max_line_lengthignore_long_linesr   r   searchrx   )rR   r]   r   	max_charsignore_long_linerG   rG   rH   check_line_length  s   zFormatChecker.check_line_lengthc                 C   s2   | j }|d| d  || dd  }|S )z>
        Remove the `# pylint ...` pattern from lines
        Nr(   )r   r   r   end)options_pattern_objr   purged_linesrG   rG   rH   remove_pylint_option_from_lines  s   z-FormatChecker.remove_pylint_option_from_linesc                 C   sL   zt | dD ]}|jdkrd|jv r W dS qW dS  ty%   Y dS w )zC
        Return true if the line length check is activated
        r)   disabler*   FT)r   groupactionmessagesr   )pylint_pattern_match_objectpragmarG   rG   rH   is_line_length_check_activated  s   z,FormatChecker.is_line_length_check_activatedr   c                 C   sL   h d}g }d}|  dD ]}|d |vr|||  d}q||7 }q|S )z]
        Split lines according to universal newlines except those in a specific sets
        >              rm   Tr   )
splitlinesr   )r   unsplit_endsresbufferatomic_linerG   rG   rH   specific_splitlines  s   
z!FormatChecker.specific_splitlineslinenoc           	      C   s   | j j}| |}t|D ]\}}| |||  qd}t|D ]\}}t||kr.d} nq |s3dS t|}|rF| |sAdS | 	|}t| |D ]\}}| 
|||  qMdS )z
        Check lines have :
            - a final newline
            - no trailing whitespace
            - less than a maximum number of characters
        FTN)r   r   r  r   r   r   r   r   r   r   r   )	rR   r   r  r   split_linesoffsetr]   potential_line_length_warningmobjrG   rG   rH   r{     s(   



zFormatChecker.check_linesc           	      C   s   | j j}|dkr
d}d}t|}|d| |kr*||d }|d7 }|d| |ksd}|rH|d dv rH||d 7 }|dd }|rH|d dv s4||ksN|rmd}|d dkrXd	}| jd
||| t| ||| fd dS dS )z%return the indent level of the stringz\t	r   Nr(   rm   z 	spacestabsr/   r   )r   indent_stringr   rx   )	rR   r   r   r}   indentlevel	unit_sizesuppli_typerG   rG   rH   r     s0   
z FormatChecker.check_indent_levelrO   )'r^   r_   r`   ra   r   r   r   __implements__r   MSGSmsgsoptionsrS   r~   r   Moduler   r   rC   	TokenInfore   r   r   r   r   r   NodeNGr   r   r   r   r   staticmethodr   boolr   r  r{   r   rG   rG   rG   rH   rb      s    



Z
f^'&
2rb   c                 C   s   |  t|  dS )z-required method to auto register this checkerN)register_checkerrb   )rt   rG   rG   rH   register.  s   r$  )5ra   rC   	functoolsr   typingr   astroidr   pylint.checkersr   pylint.checkers.utilsr   r   r   r	   pylint.constantsr
   pylint.interfacesr   r   r   pylint.utils.pragma_parserr   r   r   _ASYNC_TOKENr   _SPACED_OPERATORS_OPENING_BRACKETS_CLOSING_BRACKETS_TAB_LENGTH	frozensetr   r   rD   _EOLry   _MUST	_MUST_NOT_IGNORENODEr  rI   HANGING_DICT_VALUEHANGINGHANGING_BLOCK	CONTINUEDCONTINUED_BLOCKSINGLE_LINE	WITH_BODYrN   rb   r$  rG   rG   rG   rH   <module>   sh   ,	?    J