o
    bD                     @   s  d Z ddlmZ ddlZddl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 d
dddddddddd
ZedZdZdZdZdejdefddZdejdefddZdejdefdd Zd!d" Zd#d$ ZG d%d& d&eZd'd( ZdS ))zcheck for signs of poor design    )defaultdictN)IfBoolOp)
decorators)IAstroidChecker)BaseChecker)check_messages)utils)zToo many ancestors (%s/%s)too-many-ancestorsznUsed when class has too many parent classes, try to reduce this to get a simpler (and so easier to use) class.)z$Too many instance attributes (%s/%s)too-many-instance-attributeszsUsed when class has too many instance attributes, try to reduce this to get a simpler (and so easier to use) class.)zToo few public methods (%s/%s)too-few-public-methodszLUsed when class has too few public methods, so be sure it's really worth it.)zToo many public methods (%s/%s)too-many-public-methodsznUsed when class has too many public methods, try to reduce this to get a simpler (and so easier to use) class.)z"Too many return statements (%s/%s)too-many-return-statementszWUsed when a function or method has too many return statement, making it hard to follow.)zToo many branches (%s/%s)too-many-brancheszOUsed when a function or method has too many branches, making it hard to follow.)zToo many arguments (%s/%s)too-many-argumentsz8Used when a function or method takes too many arguments.)z Too many local variables (%s/%s)too-many-localsz<Used when a function or method has too many local variables.)zToo many statements (%s/%s)too-many-statementszpUsed when a function or method has too many statements. You should then split it in smaller functions / methods.)z4Too many boolean expressions in if statement (%s/%s)too-many-boolean-expressionsz@Used when an if statement contains too many boolean expressions.)
ZR0901ZR0902ZR0903ZR0904ZR0911ZR0912ZR0913ZR0914ZR0915ZR0916z^_{2}[a-z]+_{2}$	dataclassdataclassesztyping.NamedTuplenodereturnc                 C   s$   |   D ]}| tkr dS qdS )z2Check if a class node is a typing.NamedTuple classTF)	ancestorsqnameTYPING_NAMEDTUPLE)r   base r   ^/var/www/secure340b-portal/env/lib/python3.10/site-packages/pylint/checkers/design_analysis.py_is_typing_namedtupleb   s
   r   c              	   C   sj   | j D ]/}z| }W n
 tjy   Y qw |D ]}t|tjs!q|jdkr1| jdkr1  dS qqdS )zCheck if a class definition defines an Enum class.

    :param node: The class node to check.
    :type node: astroid.ClassDef

    :returns: True if the given node represents an Enum class. False otherwise.
    :rtype: bool
    EnumenumTF)basesinferredastroidZInferenceError
isinstanceClassDefnameroot)r   r   Zinferred_basesZancestorr   r   r   _is_enum_classj   s   
	r(   c                 C   s|   | j sdS |  j}| j jD ]-}t|tjr|j}t|tjtj	fs#qt|tjr-|j
}n|j}|tkr;t|v r; dS qdS )zCheck if a class definition defines a Python 3.7+ dataclass

    :param node: The class node to check.
    :type node: astroid.ClassDef

    :returns: True if the given node represents a dataclass class. False otherwise.
    :rtype: bool
    FT)r   r'   localsnodesr$   r#   CallfuncName	Attributer&   attrnameDATACLASS_DECORATOR)r   Zroot_locals	decoratorr&   r   r   r   _is_dataclass   s   	
r2   c                 C   s6   d}|   D ]}t|tr|t|7 }q|d7 }q|S )zCounts the number of boolean expressions in BoolOp `bool_op` (recursive)

    example: a and (b or c or (d and e)) ==> 5 boolean expressions
    r      )Zget_childrenr$   r   _count_boolean_expressions)Zbool_opnb_bool_exprZ	bool_exprr   r   r   r4      s   

r4   c                 C   sF   t dd |  D }|  D ]}t|jr |jdkr |d7 }q|S )Nc                 s        | ]}|j d sdV  qdS _r3   Nr&   
startswith.0methodr   r   r   	<genexpr>   s    z*_count_methods_in_class.<locals>.<genexpr>__init__r3   )summethods	mymethodsSPECIAL_OBJsearchr&   )r   all_methodsr=   r   r   r   _count_methods_in_class   s   rF   c                   @   s  e Zd ZdZefZdZeZd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dd	fdd ddd!d	fd"dddd#d	ff
Z
dQd%d&Zd'd( Zd)d* Zejd+d, Zed-d.d/d0d1d2 Zed/d0d3d4 Zed5d6d7d8d9d:d;d< ZeZed5d6d7d8d9d=d> ZeZd?d@ ZdAdB ZdCdD ZdEdF ZedGdHdI ZdJdK ZdLdM ZeZdRdOdPZ d$S )SMisdesignCheckerzchecks for sign of poor/misdesign:
    * number of methods, attributes, local variables...
    * size, complexity of functions, methods
    Zdesignzmax-args   intz<int>z2Maximum number of arguments for function / method.)defaulttypemetavarhelpz
max-locals   z4Maximum number of locals for function / method body.zmax-returns   z<Maximum number of return / yield for function / method body.zmax-branches   z4Maximum number of branch for function / method body.zmax-statements2   z7Maximum number of statements in function / method body.zmax-parents   z<num>z2Maximum number of parents for a class (see R0901).zmax-attributesz5Maximum number of attributes for a class (see R0902).zmin-public-methods   z9Minimum number of public methods for a class (see R0903).zmax-public-methods   z9Maximum number of public methods for a class (see R0904).zmax-bool-exprz9Maximum number of boolean expressions in an if statement.Nc                 C   s(   t | | d | _d | _d | _d | _d S N)r   r?   stats_returns	_branches_stmts)selflinterr   r   r   r?   %  s
   
zMisdesignChecker.__init__c                 C   s&   | j  | _g | _tt| _g | _dS )zinitialize visit variablesN)r\   Z	add_statsrW   rX   r   rJ   rY   rZ   r[   r   r   r   open,  s   

zMisdesignChecker.openc                 C   s*   t t| jD ]}| j|  |7  < qd S rV   )rangelenrZ   )r[   amountir   r   r   _inc_all_stmts3  s   zMisdesignChecker._inc_all_stmtsc                 C   s   t j| dd dS )Nzignored-argument-names)rK   )r	   Zget_global_optionr]   r   r   r   _ignored_argument_names7  s   z(MisdesignChecker._ignored_argument_namesr
   r   r   r   c                 C   sl   t t| }|| jjkr| jd||| jjfd t |j| jjkr4| jd|t |j| jjfd dS dS )zNcheck size of inheritance hierarchy and number of instance attributes
        r
   r   argsr   N)r`   listr   configZmax_parentsadd_messageZinstance_attrsZmax_attributes)r[   r   Z
nb_parentsr   r   r   visit_classdef;  s   	

zMisdesignChecker.visit_classdefc                 C   s   t dd | D }|| jjkr| jd||| jjfd |jdks.t|s.t|s.t|r0dS t	|}|| jj
k rH| jd||| jj
fd dS dS )zcheck number of public methodsc                 s   r6   r7   r9   r;   r   r   r   r>   V      
z2MisdesignChecker.leave_classdef.<locals>.<genexpr>r   re   classNr   )r@   rB   rh   Zmax_public_methodsri   rL   r(   r2   r   rF   Zmin_public_methods)r[   r   Z
my_methodsrE   r   r   r   leave_classdefS  s4   
	

zMisdesignChecker.leave_classdefr   r   r   r   r   zkeyword-arg-before-varargc                    s   | j d |jj}| j |dur;d} r t fdd|D }t|| }|| jjkr:| jd|t|| jjfd nd}t|j	| }|| jj
krV| jd||| jj
fd | jd dS )	zdcheck function name, docstring, arguments, redefinition,
        variable names, max locals
        r   Nc                 3   s     | ]}  |jrd V  qdS )r3   N)matchr&   )r<   argZignored_argument_namesr   r   r>     rk   z5MisdesignChecker.visit_functiondef.<locals>.<genexpr>r   re   r   r3   )rX   appendrf   rd   r@   r`   rh   Zmax_argsri   r)   Z
max_localsrZ   )r[   r   rf   Zignored_args_numZargnumZlocnumr   rp   r   visit_functiondef}  s0   z"MisdesignChecker.visit_functiondefc                 C   s   | j  }|| jjkr| jd||| jjfd | j| }|| jjkr.| jd||| jjfd | j }|| jjkrG| jd||| jjfd dS dS )zkmost of the work is done here on close:
        checks for max returns, branch, return in __init__
        r   re   r   r   N)	rX   poprh   Zmax_returnsri   rY   Zmax_branchesrZ   Zmax_statements)r[   r   returnsbranchesZstmtsr   r   r   leave_functiondef  s,   






z"MisdesignChecker.leave_functiondefc                 C   s    | j sdS | j d  d7  < dS )zcount number of returnsNr3   )rX   )r[   r8   r   r   r   visit_return  s   zMisdesignChecker.visit_returnc                 C   s   |j r
| d dS dS )zWdefault visit method -> increments the statements counter if
        necessary
        r3   N)Zis_statementrc   r[   r   r   r   r   visit_default  s   zMisdesignChecker.visit_defaultc                 C   s2   t |j}|jr|d7 }| || | | dS increments the branches counterr3   N)r`   handlersorelse_inc_branchrc   r[   r   ru   r   r   r   visit_tryexcept  s
   
z MisdesignChecker.visit_tryexceptc                 C   s   |  |d | d dS )r|   rT   N)r   rc   ry   r   r   r   visit_tryfinally  s   z!MisdesignChecker.visit_tryfinallyr   c                 C   sT   |  | d}|jrt|jdkst|jd ts|d7 }| || | | dS )z>increments the branches counter and checks boolean expressionsr3   r   N)_check_boolean_expressionsr~   r`   r$   r   r   rc   r   r   r   r   visit_if  s   
$zMisdesignChecker.visit_ifc                 C   sH   |j }t|ts
dS t|}|| jjkr"| jd||| jjfd dS dS )zwGo through "if" node `node` and counts its boolean expressions

        if the "if" node test is a BoolOp node
        Nr   re   )testr$   r   r4   rh   Zmax_bool_exprri   )r[   r   	conditionr5   r   r   r   r     s   


z+MisdesignChecker._check_boolean_expressionsc                 C   s"   d}|j r	|d7 }| || dS r{   )r~   r   r   r   r   r   visit_while  s   zMisdesignChecker.visit_whiler3   c                 C   s   | j |   |7  < dS )r|   N)rY   scope)r[   r   Zbranchesnumr   r   r   r     s   zMisdesignChecker._inc_branchrV   )r3   )!__name__
__module____qualname____doc__r   Z__implements__r&   MSGSZmsgspriorityoptionsr?   r^   rc   r   Zcachedpropertyrd   r   rj   rm   rr   Zvisit_asyncfunctiondefrv   Zleave_asyncfunctiondefrx   rz   r   r   r   r   r   Z	visit_forr   r   r   r   r   rG      s    





a


)
"


rG   c                 C   s   |  t|  dS )z.required method to auto register this checker N)Zregister_checkerrG   )r\   r   r   r   register  s   r   )r   collectionsr   rer#   r   r   r   Zpylint.interfacesr   Zpylint.checkersr   Zpylint.checkers.utilsr   Zpylintr	   r   compilerC   r0   ZDATACLASS_IMPORTr   r%   boolr   r(   r2   r4   rF   rG   r   r   r   r   r   <module>   sD   
;
  \