B
    Ì‹dá4  ã               @   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 ddl	m
Z
mZmZ ddlmZ ddlmZmZmZ dd	lmZ d
dddgZedddge ƒZdd„ Zddd„ZG dd„ de
ƒZG dd„ deƒZG dd„ deƒZdd„ ZdS )zv
A Cython plugin for coverage.py

Requires the coverage package at least in version 4.0 (which added the plugin API).
é    )Úabsolute_importN)Údefaultdict)ÚCoveragePluginÚ
FileTracerÚFileReporter)Úcanonical_filenameé   )Úfind_root_package_dirÚis_package_dirÚopen_source_file)Ú__version__z.cz.cppz.ccz.cxxz.pyz.pyxz.pxdc             C   s.   t jj}x tD ]}| | }||ƒr|S qW d S )N)ÚosÚpathÚexistsÚC_FILE_EXTENSIONS)Ú	base_pathZfile_existsÚextÚ	file_name© r   ú\/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/Cython/Coverage.pyÚ_find_c_source   s    
r   Fc             C   s¢   t j |¡}t j |¡sT| d¡s&|rTt j t j | ¡|¡}t j |¡rTt j |¡}t j |¡sšx8tjD ].}t j t j ||¡¡}t j |¡rht	|ƒS qhW t	|ƒS )Nz.pxi)
r   r   Úabspathr   ÚendswithÚjoinÚdirnameÚsysÚrealpathr   )Z	main_fileÚ	file_pathÚrelative_path_searchÚabs_pathÚrel_file_pathÚsys_pathZ	test_pathr   r   r   Ú_find_dep_file_path$   s    r"   c               @   sP   e Zd ZdZdZdZdd„ Zdd„ Zdd„ Zdd	„ Z	d
d„ Z
dd„ Zdd„ ZdS )ÚPluginNc             C   s
   dt fgS )NzCython version)r   )Úselfr   r   r   Úsys_info=   s    zPlugin.sys_infoc             C   s¬   |  d¡s|  d¡rdS d }}ttj |¡ƒ}| jrN|| jkrN| j| d }|dkrˆ|  |¡\}}|sldS |  ||¡\}}|dkrˆdS | jdkr˜i | _t	|||| j| jƒS )zR
        Try to find a C source file for a file path found by the tracer.
        ú<zmemory:Nr   )
Ú
startswithr   r   r   r   Ú_c_files_mapÚ_find_source_filesÚ_read_source_linesÚ_file_path_mapÚCythonModuleTracer)r$   ÚfilenameÚc_fileÚpy_fileÚ_Úcoder   r   r   Úfile_tracer@   s     
zPlugin.file_tracerc             C   sr   t tj |¡ƒ}| jr2|| jkr2| j| \}}}n2|  |¡\}}|sHd S |  ||¡\}}|d krdd S t||||ƒS )N)r   r   r   r   r(   r)   r*   ÚCythonModuleReporter)r$   r-   r.   r    r1   r0   r   r   r   Úfile_reporter^   s    zPlugin.file_reporterc          	   C   s´  t j |¡\}}| ¡ }|tkr"nš|dkrPt d|tj¡}|r¼|d | ¡ … }nl|dkr~t d|tj¡}|r¼|d | ¡ … }n>|dkr¸|  	t j 
|¡|¡ || jkr¼| j| d d fS ndS |tkrÈ|nt|ƒ}|d kr.t |¡}t j ||¡ t jj¡}t|ƒdkr.t j t j 
|¡d	 |¡¡}t|ƒ}d }	|r¬t j |¡d d
 }	t j |	¡s^d }	y.t|dƒ}
d|
 d¡kr€dS W d Q R X W n ttfk
rª   d }Y nX ||	fS )Nz.pydz[.]cp[0-9]+-win[_a-z0-9]*$z.soz&[.](?:cpython|pypy)-[0-9]+[-_a-z0-9]*$z.pxir   )NNr   Ú.z.pyÚrbs   /* Generated by Cython é   )r   r   ÚsplitextÚlowerÚMODULE_FILE_EXTENSIONSÚreÚsearchÚIÚstartÚ_find_c_source_filesr   r(   r   r   r	   ZuncachedÚrelpathÚsplitÚsepÚlenr   r   ÚopenÚreadÚIOErrorÚOSError)r$   r-   Úbasenamer   Zplatform_suffixr.   Zpackage_rootÚpackage_pathZtest_basepathZpy_source_fileÚfr   r   r   r)   q   sH    



zPlugin._find_source_filesc             C   sˆ   t j |¡sdS t jj}xNt  |¡D ]@}||ƒd  ¡ }|tkr$|  t j ||¡|¡ || j	kr$dS q$W t
|ƒr„|  t j |¡|¡ dS )z¦
        Desperately parse all C files in the directory or its package parents
        (not re-descending) to find the (included) source file in one of them.
        Nr   )r   r   Úisdirr8   Úlistdirr9   r   r*   r   r(   r
   r?   r   )r$   Zdir_pathÚsource_filer8   r-   r   r   r   r   r?   £   s    
zPlugin._find_c_source_filesc             C   sž   | j dkri | _ || j kr&| j | }n|  |¡}|| j |< | jdkrJi | _x2| ¡ D ]&\}}t||dd}|||f| j|< qTW || jkrŒdS | j| dd… S )zý
        Parse a Cython generated C/C++ source file and find the executable lines.
        Each executable line starts with a comment header that states source file
        and line number, as well as the surrounding range of source code lines.
        NT)r   )NNr   )Ú_parsed_c_filesÚ_parse_cfile_linesr(   Úitemsr"   )r$   r.   Z
sourcefileÚ
code_linesr-   r1   r   r   r   r   r*   µ   s    





zPlugin._read_source_linesc          	   C   sj  t  d¡j}t  d¡j}t  d¡j}t  d¡j}t  d¡j}ttƒ}ttƒ}d}	t|ƒÄ}
t|
ƒ}
x´|
D ]¬}||ƒ}|s®d|krh|	dk	rh||ƒ}|rh||	  t	| 
d¡ƒ¡ qh| ¡ \}}|}	t	|ƒ}xL|
D ]D}||ƒ}|r| 
d¡ ¡ }||ƒröP ||| |< P qÌ||ƒrÌP qÌW qhW W dQ R X xB| ¡ D ]6\}}
t|
ƒ | |d	¡¡}x|D ]}|
|= qPW q,W |S )
zb
        Parse a C file and extract all source file lines that generated executable code.
        z */[*] +"(.*)":([0-9]+)$z *[*] (.*) # <<<<<<+$z *[*]/$z *__Pyx_TraceLine\(([0-9]+),zX\s*c(?:type)?def\s+(?:(?:public|external)\s+)?(?:struct|union|enum|class)(\s+[^:]+|)\s*:Nz__Pyx_TraceLine(r   r   )r;   ÚcompileÚmatchr   ÚdictÚsetrD   ÚiterÚaddÚintÚgroupÚgroupsÚrstriprP   Ú
differenceÚget)r$   r.   Zmatch_source_path_lineZmatch_current_code_lineZmatch_comment_endZmatch_trace_lineZnot_executablerQ   Zexecutable_linesZcurrent_filenameÚlinesÚlinerS   Z
trace_liner-   ÚlinenoZcomment_lineÚ	code_lineZ
dead_linesr   r   r   rO   Ï   sJ    



zPlugin._parse_cfile_lines)Ú__name__Ú
__module__Ú__qualname__r+   r(   rN   r%   r2   r4   r)   r?   r*   rO   r   r   r   r   r#   5   s   2r#   c                   s0   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Z‡  ZS )r,   zA
    Find the Python/Cython source file for a Cython module.
    c                s0   t t| ƒ ¡  || _|| _|| _|| _|| _d S )N)Úsuperr,   Ú__init__Úmodule_filer/   r.   r(   r+   )r$   rg   r/   r.   Zc_files_mapZfile_path_map)Ú	__class__r   r   rf     s    zCythonModuleTracer.__init__c             C   s   dS )NTr   )r$   r   r   r   Úhas_dynamic_source_filename  s    z.CythonModuleTracer.has_dynamic_source_filenamec             C   s–   |j j}y
| j| S  tk
r&   Y nX t||ƒ}| jr^|dd…  ¡ dkr^| j| j|< | jS | jdk	slt‚|| jkrˆ| j	|df| j|< || j|< |S )zR
        Determine source file path.  Called by the function call tracer.
        éýÿÿÿNz.py)
Úf_codeÚco_filenamer+   ÚKeyErrorr"   r/   r9   r(   ÚAssertionErrorr.   )r$   r-   ÚframerM   r   r   r   r   Údynamic_source_filename  s    



z*CythonModuleTracer.dynamic_source_filename)rb   rc   rd   Ú__doc__rf   ri   rp   Ú__classcell__r   r   )rh   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d
d„ Z‡  Z	S )r3   zP
    Provide detailed trace information for one source file to coverage.py.
    c                s&   t t| ƒ |¡ || _|| _|| _d S )N)re   r3   rf   Únamer.   Ú_code)r$   r.   rM   r    r1   )rh   r   r   rf   -  s    zCythonModuleReporter.__init__c             C   s
   t | jƒS )zJ
        Return set of line numbers that are possibly executable.
        )rU   rt   )r$   r   r   r   r^   3  s    zCythonModuleReporter.linesc             c   sT   d}xJt | j ¡ ƒD ]8\}}x||kr6g V  |d7 }qW d|fgV  |d7 }qW d S )Nr   Útxt)Úsortedrt   rP   )r$   Úcurrent_lineÚline_nora   r   r   r   Ú_iter_source_tokens9  s    
z(CythonModuleReporter._iter_source_tokensc          	   C   sF   t j | j¡r*t| jƒ
}| ¡ S Q R X nd dd„ |  ¡ D ƒ¡S dS )zA
        Return the source code of the file as a string.
        NÚ
c             s   s"   | ]}|r|d  d ndV  qdS )r   r   Ú Nr   )Ú.0Útokensr   r   r   ú	<genexpr>K  s   z.CythonModuleReporter.source.<locals>.<genexpr>)r   r   r   r-   r   rE   r   ry   )r$   rJ   r   r   r   ÚsourceB  s    zCythonModuleReporter.sourcec          	   c   sh   t j | j¡rFt| jƒ&}x|D ]}d| d¡fgV  q W W dQ R X nx|  ¡ D ]}d|fgV  qPW dS )z6
        Iterate over the source code tokens.
        ru   rz   N)r   r   r   r-   r   r[   ry   )r$   rJ   r_   r   r   r   Úsource_token_linesN  s    
"z'CythonModuleReporter.source_token_lines)
rb   rc   rd   rq   rf   r^   ry   r   r€   rr   r   r   )rh   r   r3   )  s   	r3   c             C   s   |   tƒ ¡ d S )N)Zadd_file_tracerr#   )ÚregÚoptionsr   r   r   Úcoverage_init[  s    rƒ   )F)rq   Ú
__future__r   r;   Úos.pathr   r   Úcollectionsr   Zcoverage.pluginr   r   r   Zcoverage.filesr   ZUtilsr	   r
   r   r{   r   r   rU   r:   r   r"   r#   r,   r3   rƒ   r   r   r   r   Ú<module>   s$   	
 O&2