o
    b:                     @   s   d Z ddlmZ ddlZddlmZ ddlmZ ddlZddl	m
Z
 ddlmZ ddlmZmZ dd	lmZ G d
d dZdd ZG dd dZddiZdd ZG dd deeZdd ZdddZdddZedkrpe  dS dS )zGa similarities / code duplication command line tool and pylint checker
    )print_functionN)defaultdict)groupby)decoding_stream)IRawChecker)BaseCheckertable_lines_from_stats)Tablec                   @   sT   e Zd ZdZ				dddZdddZd	d
 Zdd Zdd Zdd Z	dd Z
dS )Similarz,finds copy-pasted lines of code in a project   Fc                 C   s"   || _ || _|| _|| _g | _d S N)	min_linesignore_commentsignore_docstringsignore_importslinesets)selfr   r   r   r    r   V/var/www/secure340b-portal/env/lib/python3.10/site-packages/pylint/checkers/similar.py__init__$   s
   
zSimilar.__init__Nc                 C   sX   |du r|j }nt||j }z| jt|| | j| j| j W dS  ty+   Y dS w )z(append a file to search for similaritiesN)		readlinesr   r   appendLineSetr   r   r   UnicodeDecodeError)r   Zstreamidstreamencodingr   r   r   r   append_stream1   s    
	zSimilar.append_streamc                 C   s   |  |   dS )z<start looking for similarities and display results on stdoutN)_display_sims_compute_simsr   r   r   r   runD      zSimilar.runc                 C   s   t t}|  D ]7\}}}}}|| }|D ]}||f|v s#||f|v r3|||f |||f  nq|||f||fh qg }	| D ]\}}
|
D ]	}|	||f qLqF|	  |	  |	S )z&compute similarities in appended files)r   list
_iter_simsaddr   itemssortreverse)r   Zno_duplicatesnumlineset1Zidx1lineset2Zidx2Z	duplicatecouplessimsZ	ensemblesr   r   r   r   H   s&   zSimilar._compute_simsc           	      C   s   d}|D ]A\}}t   t |dt|d t|}|D ]\}}t d|j|f  q|j|||  D ]	}t d|  q1||t|d  7 }qtdd | jD }t d	|||d
 | f  dS )z'display computed similarities on stdoutr   zsimilar lines infiles==%s:%sz     c                 S   s   g | ]}t |qS r   len.0linesetr   r   r   
<listcomp>i   s    z)Similar._display_sims.<locals>.<listcomp>z)TOTAL lines=%s duplicates=%s percent=%.2f      Y@N)printr1   sortedname_real_linesrstripsumr   )	r   r,   Znb_lignes_dupliqueesr(   r+   r4   idxlineZnb_total_lignesr   r   r   r   \   s&   
zSimilar._display_simsc                 c   s    |j }|j }|j}d}| j}|t|k rxd}d}	||| D ]L}
d}tt||||
D ]'\}	\\}}\}}||krO||krH|	||||
fV  t||	} n|rU|d7 }q.|	d7 }	||krf|	||||
fV  t||	}q||7 }|t|k sdS dS )z+find similarities in the two given linesetsr   r/   N)enumerate_strippedfindr   r1   	enumeratezipmax)r   r)   r*   Zlines1Zlines2r@   Zindex1r   skipr(   index2Z	non_blank_line1line2r   r   r   _find_commons   s:   

zSimilar._find_commonc                 c   sR    t | jdd D ]\}}| j|d d D ]}| ||D ]}|V  qqq
dS )zWiterate on similarities among all files, by making a cartesian
        product
        Nr/   )rA   r   rI   )r   r=   r4   r*   simr   r   r   r#      s   zSimilar._iter_sims)r   FFFr   )__name__
__module____qualname____doc__r   r   r    r   r   rI   r#   r   r   r   r   r
   !   s    

r
   c                 C   s   |r!t d| }dd |jD }dd t|dd dD }d	}g }d
}	t| ddD ]J\}
}| }|rX|	sM|dsA|drM|d
d }	|dd
 }|	rX||	rVd
}	d}|rd|	|
|}|rdd}|rp|
ddd  }|| q+|S )z\return lines with leading/trailing whitespace and any ignored code
    features removed
     c                 s   s(    | ]}|j t|tjtjffV  qd S r   )lineno
isinstanceastroidImport
ImportFrom)r3   noder   r   r   	<genexpr>   s
    
z!stripped_lines.<locals>.<genexpr>c                 S   s$   i | ]\}}|t d d |D qS )c                 s   s    | ]\}}|V  qd S r   r   )r3   rF   Z	is_importr   r   r   rW          z,stripped_lines.<locals>.<dictcomp>.<genexpr>)all)r3   rQ   Znode_is_import_groupr   r   r   
<dictcomp>   s    z"stripped_lines.<locals>.<dictcomp>c                 S   s   | d S )Nr   r   )xr   r   r   <lambda>   s    z stripped_lines.<locals>.<lambda>)keyFNr/   )startz"""z'''   #r   )rS   parsejoinbodyr   rA   strip
startswithendswithgetsplitr   )linesr   r   r   treeZnode_is_import_by_linenoZline_begins_importZcurrent_line_is_importZstrippedlines	docstringrQ   r>   r   r   r   stripped_lines   sB   
rl   c                   @   sb   e Zd ZdZ			dddZdd Zdd Zd	d
 Zdd Zdd Z	dddZ
dd Zdd ZdS )r   z7Holds and indexes all the lines of a single source fileFc                 C   s*   || _ || _t||||| _|  | _d S r   )r9   r:   rl   _stripped_lines	_mk_index_index)r   r9   ri   r   r   r   r   r   r   r      s   zLineSet.__init__c                 C   s
   d| j  S )Nz<Lineset for %s>r9   r   r   r   r   __str__      
zLineSet.__str__c                 C   s
   t | jS r   )r1   r:   r   r   r   r   __len__   rr   zLineSet.__len__c                 C   s
   | j | S r   rm   )r   indexr   r   r   __getitem__   rr   zLineSet.__getitem__c                 C   s   | j |j k S r   rp   )r   otherr   r   r   __lt__   s   zLineSet.__lt__c                 C   s   t | S r   )idr   r   r   r   __hash__   s   zLineSet.__hash__r   c                 c   s@    |}|r| j |d }n| j }|D ]}||fV  |d7 }qdS )zgreturn an iterator on stripped lines, starting from a given index
        if specified, else 0
        Nr/   rt   )r   Zstart_atr=   ri   r>   r   r   r   r?      s   

zLineSet.enumerate_strippedc                 C   s   | j |dS )z7return positions of the given stripped line in this setr   )ro   rg   )r   Zstripped_liner   r   r   r@      s   zLineSet.findc                 C   s2   t t}t| jD ]\}}|r|| | q	|S )zcreate the index for this set)r   r"   rA   rm   r   )r   ru   line_nor>   r   r   r   rn      s   zLineSet._mk_indexN)FFFr   )rL   rM   rN   rO   r   rq   rs   rv   rx   rz   r?   r@   rn   r   r   r   r   r      s    

r   R0801)zSimilar lines in %s files
%szduplicate-codezIndicates that a set of similar lines has been detected among multiple file. This usually means that the code should be refactored to avoid this duplication.c                 C   s2   g d}|t ||d7 }| t|dddd dS )z/make a layout with some stats about duplication)rP   nowprevious
differencenb_duplicated_linespercent_duplicated_linesr   r/   )childrencolsZrheadersZcheadersN)r   r   r	   )sectstatsZ	old_statsri   r   r   r   report_similarities  s
   r   c                	   @   s   e Zd ZdZ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fZ	dde
ffZd ddZd!ddZdd Zdd Zdd ZdS )"SimilarCheckerzchecks for similarities and duplicated code. This computation may be
    memory / CPU intensive, so you should disable it if you experiment some
    problems.
    Zsimilaritiesmin-similarity-linesr   intz<int>z%Minimum lines number of a similarity.)defaulttypemetavarhelpignore-commentsTZynz<y or n>z,Ignore comments when computing similarities.ignore-docstringsz.Ignore docstrings when computing similarities.ignore-importsFz+Ignore imports when computing similarities.ZRP0801ZDuplicationNc                 C   s(   t | | tj| dddd d | _d S )Nr   T)r   r   r   )r   r   r
   r   )r   linterr   r   r   r   N  s
   
zSimilarChecker.__init__c                 C   sn   t | |||| |dkr| jj| _dS |dkr| jj| _dS |dkr*| jj| _dS |dkr5| jj| _dS dS )zmethod called to set an option (registered in the options list)

        overridden to report options setting to Similar
        r   r   r   r   N)r   
set_optionconfigZmin_similarity_linesr   r   r   r   )r   optnamevalueactionoptdictr   r   r   r   U  s   zSimilarChecker.set_optionc                 C   s   g | _ | jjddd| _dS )z<init the checkers: reset linesets and statistics informationr   r   N)r   r   Z	add_statsr   r   r   r   r   opend  s   zSimilarChecker.openc                 C   sB   |  }| | jj||j W d   dS 1 sw   Y  dS )zprocess a module

        the module's content is accessible via the stream object

        stream must implement the readlines method
        N)r   r   r   Zcurrent_namefile_encoding)r   rV   r   r   r   r   process_modulek  s   
"zSimilarChecker.process_modulec           
      C   s   t dd | jD }d}| j}|  D ]F\}}g }|D ]\}}|d|j|f  q|  |j|||  D ]	}	||	  q7| j	dt
|d|fd ||t
|d  7 }q||d	< |oe|d
 | |d< dS )zAcompute and display similarities on closing (i.e. end of parsing)c                 s   s    | ]}t |V  qd S r   r0   r2   r   r   r   rW   w  rX   z'SimilarChecker.close.<locals>.<genexpr>r   r.   r}   
)argsr/   r   r6   r   N)r<   r   r   r   r   r9   r&   r:   r;   Zadd_messager1   rb   )
r   totalZ
duplicatedr   r(   r+   msgr4   r=   r>   r   r   r   closeu  s   zSimilarChecker.closer   )NN)rL   rM   rN   rO   r   Z__implements__r9   MSGSZmsgsoptionsr   Zreportsr   r   r   r   r   r   r   r   r   r     sP    


'


r   c                 C   s   |  t|  dS )z.required method to auto register this checker N)Zregister_checkerr   )r   r   r   r   register  r!   r   c                 C   s$   t d t   t d t|  dS )z&display command line usage informationz*finds copy pasted blocks in a set of filesz~Usage: symilar [-d|--duplicates min_duplicated_lines] [-i|--ignore-comments] [--ignore-docstrings] [--ignore-imports] file1...N)r7   sysexit)statusr   r   r   usage  s   r   c              	   C   s  | du rt jdd } ddlm} d}d}d}d}d}d}|| ||\}}	|D ])\}
}|
d	v r4t|}q'|
d
v r<t  q'|
dv rCd}q'|
dv rJd}q'|
dv rPd}q'|	sWtd t||||}|	D ]}t|}||| W d   n1 sww   Y  q`|  t 	d dS )z$standalone command line access pointNr/   r   )getoptZhdi)r   zduplicates=r   r   r   r   F)z-dz--duplicates)z-hz--help)z-iz--ignore-commentsT)z--ignore-docstrings)z--ignore-imports)
r   argvr   r   r   r
   r   r   r    r   )r   r   Zs_optsZl_optsr   r   r   r   optsr   optvalrK   filenamer   r   r   r   Run  s@   

r   __main__r|   r   )rO   
__future__r   r   collectionsr   	itertoolsr   rS   Zpylint.utilsr   Zpylint.interfacesr   Zpylint.checkersr   r   Zpylint.reporters.ureports.nodesr	   r
   rl   r   r   r   r   r   r   r   rL   r   r   r   r   <module>   s.   z,=
p

(
