a
    sX)                     @   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
yn   ddlmZm	Z	 Y n0 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 )!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   %lib/python3.9/site-packages/mccabe.py__init__   s    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 rD|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   s    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  q2q&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       z(PathGraph.complexity.<locals>.<listcomp>   )sumr-   valuesr3   )r   Z	num_edgesZ	num_nodesr   r   r   
complexityU   s    
zPathGraph.complexityN)r   )r   r   r   r   r/   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   s    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r| |}|| _| |j t	ddd}| j
| j| | j
|| || _nNt|||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    r/   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   r/   )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                    s4   t |tjr| | ntt| j|g|R   d S r   )
isinstancer   ZstmtrQ   r>   r<   r   )r   r   r   rB   r   r   r      s    zPathGraphingAstVisitor.defaultc                 C   s   d|j  }| || d S )NzLoop %dr*   	_subgraphr   r   r"   r   r   r   	visitLoop   s    
z PathGraphingAstVisitor.visitLoopc                 C   s   d|j  }| || d S )NzIf %drS   rU   r   r   r   visitIf   s    
zPathGraphingAstVisitor.visitIfr   c                 C   sp   | j du rTt|||j|j| _ t|}| ||| | j | jd| j|f < |   n| 	|}| ||| 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   rT      s    


z PathGraphingAstVisitor._subgraphc                 C   s   g }|| _ | |j || j  |D ]"}|| _ | |j || j  q&|jrp|| _ | |j || j  n
|| |rtddd}|D ]}| j|| q|| _ dS )z@parse the body and any `else` block of `if` and `for` statementsr=   rG   rH   N)rD   rE   rK   r.   orelser    rC   r/   )r   r   rL   rY   Z
loose_endsZextrarM   ler   r   r   rX      s$    
z&PathGraphingAstVisitor._subgraph_parsec                 C   s    d|j  }| j|||jd d S )NzTryExcept %d)rY   )r*   rT   handlersrU   r   r   r   visitTryExcept   s    
z%PathGraphingAstVisitor.visitTryExceptc                 C   s$   d|j  }| | | |j d S )NzWith %d)r*   rJ   rE   rK   rU   r   r   r   	visitWith   s    

z PathGraphingAstVisitor.visitWith)r   )r   r   r   r   r   rA   rE   rN   ZvisitAsyncFunctionDefrP   rJ   rQ   r   rV   ZvisitAsyncForZvisitForZ
visitWhilerW   rT   rX   r]   ZvisitTryr^   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   sj   d}dddddd}t |dd }t|trT|d	 |j|fi | |jd
 n|j|fi | d S )Nz--max-complexityra   ZstoreintzMcCabe complexity thresholdTrue)r   actiontypehelpparse_from_configconfig_optionsrh   zmax-complexity)r   rR   r,   pop
add_optionri   r.   )clsparserflagkwargsZconfig_optsr   r   r   add_options   s    

zMcCabeChecker.add_optionsc                 C   s   t |j| _d S r   )rc   max_complexity)rl   optionsr   r   r   parse_options  s    zMcCabeChecker.parse_optionsc                 c   sn   | j dk rd S t }|| j| |j D ]<}| | j kr,| j|j| f }|j	|j
|t| fV  q,d S )Nr   )rq   r<   r   r   r@   r:   r;   _error_tmplr)   r*   r+   rf   )r   r   rC   textr   r   r   run  s    
zMcCabeChecker.runN)r   r   r   r   r"   __version__version_codert   rq   r   classmethodrp   rs   rv   r   r   r   r   r`      s   

r`      stdinc           
      C   s   zt | |dtj}W n4 tyH   t d }tjd||f  Y dS 0 g }|t_	t||
 D ] \}}}}	|d|||f  qbt|dkrd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writer`   rq   rv   r.   r3   r$   join)
code	thresholdrb   r   eZcomplxr*   offsetru   Zcheckr   r   r   get_code_complexity  s    r   c                 C   s@   t | d}| }W d   n1 s(0    Y  t||| dS )z"Returns the complexity of a modulerUN)rb   )openreadr   )Zmodule_pathr   modr   r   r   r   get_module_complexity$  s    &r   c                 C   s<  dt j  k rdk rPn n6t| d}| W  d    S 1 sB0    Y   ndt j  krhdk r8n nz>t| d }t|j\}}W d    n1 s0    Y  W nT ttt	f y   t| dd}| W  d     Y S 1  s0    Y  Y n0 t| d|d}| W  d    S 1 s.0    Y  d S )	N)r8      )   r   r   )   r   rbzlatin-1)encodingr)
r   version_infor   r   tokenizedetect_encodingreadlineLookupErrorr   UnicodeError)rb   fr   _r   r   r   _read+  s    *22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rtd |j D ] }|jr| |jkr|  qtd n.|j D ]"}| |jkrt|j|  qd S )Nr~   z-dz--dotdotzoutput a graphviz dot file
store_true)destrg   re   z-mz--minr   zminimum complexity for outputrc   )r   rg   rf   r   r   r}   zgraph {r0   )r   argvoptparseZOptionParserrk   
parse_argsr   r   r   r   r<   r   r   r$   r@   r:   r   r;   r&   r"   )r   Zoparrr   r   r   r   r   rC   r   r   r   main<  s4    



r   __main__r~   )r{   r|   )r{   )N)r   Z
__future__r   r   r   r   collectionsr   r   r   ImportErrorZflake8.utilrw   objectr   r    r(   r<   r`   r   r   r   r   r   r   r   r   r   r   <module>   s.    -



