o
    ÷ÑÐbÅ)  ã                   @   s  d Z ddlmZ ddlZddlZddlZddlmZ zddlZddlm	Z	 W n e
y7   ddlmZm	Z	 Y nw 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dd„Zddd„Zdd„ Zd dd„Zedkr„eejdd… ƒ dS dS )!z— Meager code path measurement tool.
    Ned Batchelder
    http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html
    MIT License.
é    )Úwith_statementN)Údefaultdict)Úiter_child_nodes)Úastr   z0.6.1c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )Ú
ASTVisitorz'Performs a depth-first walk of the AST.c                 C   s   d | _ i | _d S ©N)ÚnodeÚ_cache©Úself© r   úE/var/www/secure340b-portal/env/lib/python3.10/site-packages/mccabe.pyÚ__init__   ó   
zASTVisitor.__init__c                 G   s$   t |ƒD ]}| j|g|¢R Ž  qd S r   )r   Údispatch)r   r   ÚargsÚchildr   r   r   Údefault   s   ÿzASTVisitor.defaultc                 G   sT   || _ |j}| j |¡}|d u r"|j}t| jd| | jƒ}|| j|< ||g|¢R Ž S )NÚvisit)r   Ú	__class__r	   ÚgetÚ__name__ÚgetattrÚvisitorr   )r   r   r   ÚklassÚmethZ	classNamer   r   r   r   !   s   
zASTVisitor.dispatchc                 G   s$   || _ | j|_| j|g|¢R Ž  dS )z&Do preorder walk of tree using visitorN)r   r   r   )r   Útreer   r   r   r   r   Úpreorder+   s   zASTVisitor.preorderN)r   Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r   r      s    
r   c                   @   s&   e Zd Zd	dd„Zdd„ Zdd„ ZdS )
ÚPathNodeÚcirclec                 C   s   || _ || _d S r   )ÚnameÚlook)r   r#   r$   r   r   r   r   3   r   zPathNode.__init__c                 C   s   t d| j| j|  ¡ f ƒ d S )Nznode [shape=%s,label="%s"] %d;)Úprintr$   r#   Údot_idr
   r   r   r   Úto_dot7   s   ÿzPathNode.to_dotc                 C   s   t | ƒS r   )Úidr
   r   r   r   r&   ;   s   zPathNode.dot_idN)r"   )r   r   r   r   r'   r&   r   r   r   r   r!   2   s    
r!   c                   @   s.   e Zd Zddd„Zdd„ Zdd„ Zdd	„ Zd
S )Ú	PathGraphr   c                 C   s&   || _ || _|| _|| _ttƒ| _d S r   )r#   ÚentityÚlinenoÚcolumnr   ÚlistÚnodes)r   r#   r*   r+   r,   r   r   r   r   @   s
   zPathGraph.__init__c                 C   s   | j |  |¡ g | j |< d S r   )r.   Úappend)r   Zn1Zn2r   r   r   ÚconnectG   s   zPathGraph.connectc                 C   s^   t dƒ | jD ]}| ¡  q| j ¡ D ]\}}|D ]}t d| ¡ | ¡ f ƒ qqt dƒ d S )Nz
subgraph {z	%s -- %s;Ú})r%   r.   r'   Úitemsr&   )r   r   ZnextsÚnextr   r   r   r'   L   s   

ÿzPathGraph.to_dotc                 C   s.   t dd„ | j ¡ D ƒƒ}t| jƒ}|| d S )zG Return the McCabe complexity for the graph.
            V-E+2
        c                 S   s   g | ]}t |ƒ‘qS r   )Úlen)Ú.0Únr   r   r   Ú
<listcomp>Y   s    z(PathGraph.complexity.<locals>.<listcomp>é   )Úsumr.   Úvaluesr4   )r   Z	num_edgesZ	num_nodesr   r   r   Ú
complexityU   s   
zPathGraph.complexityN)r   )r   r   r   r   r0   r'   r;   r   r   r   r   r)   ?   s
    
	r)   c                       s¦   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Zdd	„ ZeZd
d„ Z	dd„ Z
dd„ Z‡ fdd„Zdd„ Ze Z ZZdd„ Zddd„Zdd„ Zdd„ ZeZdd„ ZeZ‡  ZS ) ÚPathGraphingAstVisitorz\ A visitor for a parsed Abstract Syntax Tree which finds executable
        statements.
    c                    s&   t t| ƒ ¡  d| _i | _|  ¡  d S )NÚ )Úsuperr<   r   Ú	classnameÚgraphsÚresetr
   ©r   r   r   r   c   s   zPathGraphingAstVisitor.__init__c                 C   s   d | _ d | _d S r   )ÚgraphÚtailr
   r   r   r   rA   i   r   zPathGraphingAstVisitor.resetc                 C   s   |D ]}|   |¡ qd S r   )r   )r   Z	node_listr   r   r   r   Údispatch_listm   s   ÿz$PathGraphingAstVisitor.dispatch_listc                 C   sÜ   | j rd| j |jf }n|j}d|j|j|f }| jd urE|  |¡}|| _|  |j¡ t	ddd}| j 
| j|¡ | j 
||¡ || _d S t|||j|jƒ| _t	|ƒ}|| _|  |j¡ | j| jd| j |jf < |  ¡  d S )Nú%s%sz	%d:%d: %rr=   Úpoint©r$   )r?   r#   r+   Ú
col_offsetrC   ÚappendPathNoderD   rE   Úbodyr!   r0   r)   r@   rA   )r   r   r*   r#   ÚpathnodeÚbottomr   r   r   ÚvisitFunctionDefq   s$   


z'PathGraphingAstVisitor.visitFunctionDefc                 C   s0   | j }|  j |jd 7  _ |  |j¡ || _ d S )NÚ.)r?   r#   rE   rK   )r   r   Zold_classnamer   r   r   ÚvisitClassDef   s   
z$PathGraphingAstVisitor.visitClassDefc                 C   s,   | j sd S t|ƒ}| j | j |¡ || _ |S r   )rD   r!   rC   r0   )r   r#   rL   r   r   r   rJ   “   s   z%PathGraphingAstVisitor.appendPathNodec                 C   s,   |j d u rd}n|j }d| }|  |¡ d S )Nr   zStmt %d)r+   rJ   )r   r   r+   r#   r   r   r   ÚvisitSimpleStatement›   s
   
z+PathGraphingAstVisitor.visitSimpleStatementc                    s6   t |tjƒr|  |¡ d S tt| ƒj|g|¢R Ž  d S r   )Ú
isinstancer   ÚstmtrQ   r>   r<   r   )r   r   r   rB   r   r   r   £   s   zPathGraphingAstVisitor.defaultc                 C   ó   d|j  }|  ||¡ d S )NzLoop %d©r+   Ú	_subgraph©r   r   r#   r   r   r   Ú	visitLoop©   ó   
z PathGraphingAstVisitor.visitLoopc                 C   rT   )NzIf %drU   rW   r   r   r   ÚvisitIf¯   rY   zPathGraphingAstVisitor.visitIfr   c                 C   sr   | j du r+t|||j|jƒ| _ t|ƒ}|  |||¡ | j | jd| j|f < |  ¡  dS |  	|¡}|  |||¡ dS )z?create the subgraphs representing any `if` and `for` statementsNrF   )
rC   r)   r+   rI   r!   Ú_subgraph_parser@   r?   rA   rJ   )r   r   r#   Úextra_blocksrL   r   r   r   rV   ³   s   

z PathGraphingAstVisitor._subgraphc                 C   s°   g }|| _ |  |j¡ | | j ¡ |D ]}|| _ |  |j¡ | | j ¡ q|jr8|| _ |  |j¡ | | j ¡ n| |¡ |rVtddd}|D ]	}| j ||¡ qG|| _ dS dS )z@parse the body and any `else` block of `if` and `for` statementsr=   rG   rH   N)rD   rE   rK   r/   Úorelser!   rC   r0   )r   r   rL   r\   Z
loose_endsÚextrarM   Úler   r   r   r[   À   s&   

üz&PathGraphingAstVisitor._subgraph_parsec                 C   s    d|j  }| j|||jd d S )NzTryExcept %d)r\   )r+   rV   ÚhandlersrW   r   r   r   ÚvisitTryExceptÖ   s   
z%PathGraphingAstVisitor.visitTryExceptc                 C   s$   d|j  }|  |¡ |  |j¡ d S )NzWith %d)r+   rJ   rE   rK   rW   r   r   r   Ú	visitWithÜ   s   

z PathGraphingAstVisitor.visitWith)r   )r   r   r   r    r   rA   rE   rN   ZvisitAsyncFunctionDefrP   rJ   rQ   r   rX   ZvisitAsyncForZvisitForZ
visitWhilerZ   rV   r[   ra   ZvisitTryrb   ZvisitAsyncWithÚ__classcell__r   r   rB   r   r<   ^   s(    
r<   c                   @   sL   e Zd ZdZdZeZdZdZdZ	dd„ Z
edd	„ ƒZed
d„ ƒZdd„ ZdS )ÚMcCabeCheckerz%McCabe cyclomatic complexity checker.ZmccabeZC901zC901 %r is too complex (%d)éÿÿÿÿc                 C   s
   || _ d S r   )r   )r   r   Úfilenamer   r   r   r   ì   s   
zMcCabeChecker.__init__c                 C   sl   d}ddddddœ}t |dd ƒ}t|tƒr+| d	¡ |j|fi |¤Ž |j d
¡ d S |j|fi |¤Ž d S )Nz--max-complexityre   ÚstoreÚintzMcCabe complexity thresholdÚTrue)r   ÚactionÚtypeÚhelpÚparse_from_configÚconfig_optionsrm   zmax-complexity)r   rR   r-   ÚpopÚ
add_optionrn   r/   )ÚclsÚparserÚflagÚkwargsZconfig_optsr   r   r   Úadd_optionsï   s   û

zMcCabeChecker.add_optionsc                 C   s   t |jƒ| _d S r   )rh   Úmax_complexity)rq   Úoptionsr   r   r   Úparse_options  s   zMcCabeChecker.parse_optionsc                 c   sp    | j dk rd S tƒ }| | j|¡ |j ¡ D ]}| ¡ | j kr5| j|j| ¡ f }|j	|j
|t| ƒfV  qd S )Nr   )rv   r<   r   r   r@   r:   r;   Ú_error_tmplr*   r+   r,   rk   )r   r   rC   Útextr   r   r   Úrun  s   €
€ýzMcCabeChecker.runN)r   r   r   r    r#   Ú__version__ÚversionÚ_codery   rv   r   Úclassmethodru   rx   r{   r   r   r   r   rd   ä   s    

rd   é   Ústdinc           
      C   sª   z
t | |dtjƒ}W n ty$   t ¡ d }tj d||f ¡ Y dS w g }|t_	t||ƒ 
¡ D ]\}}}}	| d|||f ¡ q1t|ƒdkrJdS td |¡ƒ t|ƒS )NÚexecé   zUnable to parse %s: %s
r   z%s:%d:1: %sÚ
)Úcompiler   ÚPyCF_ONLY_ASTÚSyntaxErrorÚsysÚexc_infoÚstderrÚwriterd   rv   r{   r/   r4   r%   Újoin)
ÚcodeÚ	thresholdrf   r   ÚeZcomplxr+   Úoffsetrz   Úcheckr   r   r   Úget_code_complexity  s   ýr’   c                 C   s@   t | dƒ}| ¡ }W d  ƒ n1 sw   Y  t||| dS )z"Returns the complexity of a moduleÚrUN)rf   )ÚopenÚreadr’   )Úmodule_pathrŽ   Úmodr   r   r   r   Úget_module_complexity$  s   
ÿr˜   c                 C   s<  dt j  k rdk r(n nt| dƒ}| ¡ W  d   ƒ S 1 s!w   Y  d S dt j  kr3dk rœn d S 	 zt| dƒ}t |j¡\}}W d   ƒ n1 sPw   Y  W n( ttt	fy~   t| dd}| ¡ W  d   ƒ  Y S 1 sww   Y  Y nw t| d|d}| ¡ W  d   ƒ S 1 s•w   Y  d S d S )	N)r8   é   )é   r   r“   )é   r   Úrbzlatin-1)ÚencodingÚr)
rˆ   Úversion_infor”   r•   ÚtokenizeÚdetect_encodingÚreadlineÚLookupErrorr‡   ÚUnicodeError)rf   Úfr   Ú_r   r   r   Ú_read+  s(   $ÿÿ€(ÿþ$ÿ÷r§   c                 C   s   | d u rt jdd … } t ¡ }|jdddddd |jdd	d
dddd | | ¡\}}t|d ƒ}t||d dtj	ƒ}t
ƒ }| ||¡ |jrgtdƒ |j ¡ D ]}|jr\| ¡ |jkr`| ¡  qPtdƒ d S |j ¡ D ]}| ¡ |jkr}t|j| ¡ ƒ qld S )Nrƒ   z-dz--dotÚdotzoutput a graphviz dot fileÚ
store_true)Údestrl   rj   z-mz--minrŽ   zminimum complexity for outputrh   )rª   rl   rk   r   r   r‚   zgraph {r1   )rˆ   ÚargvÚoptparseÚOptionParserrp   Ú
parse_argsr§   r…   r   r†   r<   r   r¨   r%   r@   r:   rŽ   r;   r'   r#   )r«   Zoparrw   r   r   r   r   rC   r   r   r   Úmain<  s:   
ÿ
þÿ€€þr¯   Ú__main__rƒ   )r€   r   )r€   r   )r    Ú
__future__r   r¬   rˆ   r    Úcollectionsr   r   r   ÚImportErrorZflake8.utilr|   Úobjectr   r!   r)   r<   rd   r’   r˜   r§   r¯   r   r«   r   r   r   r   Ú<module>   s4    ÿ 
-

ÿ