o
    h)                     @   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re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.7.0c                   @   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   </var/www/html/ai/venv/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meth	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   n1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   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/   valuesr8   )r   	num_edges	num_nodesr   r   r   
complexityU   s   
zPathGraph.complexityN)r   )r   r   r    r   r3   r(   rA   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 )superrB   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   rG   i   r   zPathGraphingAstVisitor.resetc                 C   s   |D ]}|  | qd S r   )r   )r   	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: %rrC   pointr%   )rE   r$   r,   
col_offsetrI   appendPathNoderJ   rL   bodyr"   r3   r*   rF   rG   )r   r   r+   r$   pathnodebottomr   r   r   visitFunctionDefq   s$   


z'PathGraphingAstVisitor.visitFunctionDefc                 C   s0   | j }|  j |jd 7  _ | |j || _ d S )N.)rE   r$   rL   rR   )r   r   old_classnamer   r   r   visitClassDef   s   
z$PathGraphingAstVisitor.visitClassDefc                 C   s,   | j sd S t|}| j| j | || _ |S r   )rJ   r"   rI   r3   )r   r$   rS   r   r   r   rQ      s   z%PathGraphingAstVisitor.appendPathNodec                 C   s,   |j d u rd}n|j }d| }| | d S )Nr   zStmt %d)r,   rQ   )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   stmtrY   rD   rB   r   )r   r   r   rH   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   r\   )NzIf %dr]   r_   r   r   r   visitIf   ra   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` statementsNrM   )
rI   r*   r,   rP   r"   _subgraph_parserF   rE   rG   rQ   )r   r   r$   extra_blocksrS   r   r   r   r^      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` statementsrC   rN   rO   N)rJ   rL   rR   r0   orelser"   rI   r3   )r   r   rS   rd   
loose_endsextrarT   ler   r   r   rc      s&   

z&PathGraphingAstVisitor._subgraph_parsec                 C   s    d|j  }| j|||jd d S )NzTryExcept %d)rd   )r,   r^   handlersr_   r   r   r   visitTryExcept   s   
z%PathGraphingAstVisitor.visitTryExceptc                 C   s$   d|j  }| | | |j d S )NzWith %d)r,   rQ   rL   rR   r_   r   r   r   	visitWith   s   

z PathGraphingAstVisitor.visitWith)r   )r   r   r    r!   r   rG   rL   rU   visitAsyncFunctionDefrX   rQ   rY   r   r`   visitAsyncForvisitFor
visitWhilerb   r^   rc   rj   visitTryrk   visitAsyncWith__classcell__r   r   rH   r   rB   ^   s(    
rB   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.mccabe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t ddd}t|dd }t|tr+|d |j|fi | |jd	 d S |j|fi | d S )
Nz--max-complexityrv   storezMcCabe complexity thresholdTrue)r   actiontypehelpparse_from_configconfig_optionsr}   zmax-complexity)intr   rZ   r.   pop
add_optionr~   r0   )clsparserflagkwargsconfig_optsr   r   r   add_options   s   

zMcCabeChecker.add_optionsc                 C   s   t |j| _d S r   )r   max_complexity)r   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   )r   rB   r   r   rF   r>   rA   _error_tmplr+   r,   r-   r{   )r   r   rI   textr   r   r   run  s   
zMcCabeChecker.runN)r   r   r    r!   r$   __version__version_coder   r   r   classmethodr   r   r   r   r   r   r   rs      s    

rs      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writers   r   r   r0   r8   r&   join)
code	thresholdrw   r   ecomplxr,   offsetr   checkr   r   r   get_code_complexity  s   r   c                 C   s   t | }t||| dS )z"Returns the complexity of a module)rw   )_readr   )module_pathr   r   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 rn 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 sw   Y  d S d S )	N)r<      )   r   rU)   r   rbzlatin-1)encodingr)
r   version_infoopenreadtokenizedetect_encodingreadlineLookupErrorr   UnicodeError)rw   fr   _r   r   r   r   *  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)destr|   rz   z-mz--minr   zminimum complexity for outputr   )r   r|   r{   r   r   r   zgraph {r4   )r   argvoptparseOptionParserr   
parse_argsr   r   r   r   rB   r   r   r&   rF   r>   r   rA   r(   r$   )r   oparr   r   r   r   r   rI   r   r   r   main;  s8   

r   __main__r   )r   r   )r   r   )r!   
__future__r   r   r   r   collectionsr   r   r   ImportErrorflake8.utilr   objectr   r"   r*   rB   rs   r   r   r   r   r   r   r   r   r   r   <module>   s4     
-

