o
    éT•jr  ã                   @   sö   d Z ddgZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlZdZG dd„ dƒZd	d
„ Zdd„ ZG dd„ dƒZdd„ Zdd„ Zddd„Zdd„ ZG dd„ dƒZdd„ Zedkryeƒ  dS dS )a·  program/module to trace Python program or function execution

Sample use, command line:
  trace.py -c -f counts --ignore-dir '$prefix' spam.py eggs
  trace.py -t --ignore-dir '$prefix' spam.py eggs
  trace.py --trackcalls spam.py eggs

Sample use, programmatically
  import sys

  # create a Trace object, telling it what to ignore, and whether to
  # do tracing or line-counting or both.
  tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,],
                       trace=0, count=1)
  # run the new command using the given tracer
  tracer.run('main()')
  # make a report, placing output in /tmp
  r = tracer.results()
  r.write_results(show_missing=True, coverdir="/tmp")
ÚTraceÚCoverageResultsé    N)Ú	monotonicz#pragma NO COVERc                   @   s   e Zd Zddd„Zdd„ ZdS )Ú_IgnoreNc                 C   s:   |st ƒ nt |ƒ| _|sg ndd„ |D ƒ| _ddi| _d S )Nc                 S   s   g | ]}t j |¡‘qS © )ÚosÚpathÚnormpath©Ú.0Údr   r   ú/usr/lib/python3.10/trace.pyÚ
<listcomp>H   s    ÿz$_Ignore.__init__.<locals>.<listcomp>z<string>é   )ÚsetÚ_modsÚ_dirsÚ_ignore)ÚselfÚmodulesÚdirsr   r   r   Ú__init__F   s
   ÿz_Ignore.__init__c                 C   s¦   || j v r
| j | S || jv rd| j |< dS | jD ]}| |d ¡r*d| j |<  dS q|d u r6d| j |< dS | jD ]}| |tj ¡rKd| j |<  dS q9d| j |< dS )Nr   Ú.r   )r   r   Ú
startswithr   r   Úsep)r   ÚfilenameÚ
modulenameÚmodr   r   r   r   ÚnamesL   s(   





þ


þ
z_Ignore.names©NN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r   r   E   s    
r   c                 C   s    t j | ¡}t j |¡\}}|S )ú,Return a plausible module name for the path.)r   r   ÚbasenameÚsplitext)r   Úbaser   Úextr   r   r   Ú_modnamew   s   r(   c                 C   sÂ   t j | ¡}d}tjD ] }t j |¡}| |¡r+|t|ƒ t jkr+t|ƒt|ƒkr+|}q|r9| t|ƒd d… }n| }t j |¡\}}| t jd¡}t j	rT| t j	d¡}t j 
|¡\}}| d¡S )r#   Ú r   Nr   )r   r   ÚnormcaseÚsysr   Úlenr   Ú
splitdriveÚreplaceÚaltsepr%   Úlstrip)r   ÚcomparepathÚlongestÚdirr&   Údriver   r'   r   r   r   Ú_fullmodname~   s"   
€
r5   c                   @   s>   e Zd Z		ddd„Zdd„ Zdd„ Zdd
d„Zddd„ZdS )r   Nc              
   C   s  || _ | j d u ri | _ | j  ¡ | _|| _| jd u ri | _| j ¡ | _|| _| jd u r-i | _| j ¡ | _|| _|| _| jr‹z,t| jdƒ�}t 	|¡\}}}W d   ƒ n1 sVw   Y  |  
| j|||d�¡ W d S  tttfyŠ } ztd| j|f tjd� W Y d }~d S d }~ww d S )NÚrb)ÚcallerszSkipping counts file %r: %s©Úfile)ÚcountsÚcopyÚcounterÚcalledfuncsr7   ÚinfileÚoutfileÚopenÚpickleÚloadÚupdateÚ	__class__ÚOSErrorÚEOFErrorÚ
ValueErrorÚprintr+   Ústderr)r   r:   r=   r>   r7   r?   ÚfÚerrr   r   r   r   ›   s:   


ÿÿÿ€ÿúzCoverageResults.__init__c                 C   s   |  d¡o	| d¡S )z_Return True if the filename does not refer to a file
        we want to have reported.
        ú<ú>)r   Úendswith)r   r   r   r   r   Úis_ignored_filenameµ   s   z#CoverageResults.is_ignored_filenamec           	      C   sn   | j }| j}| j}|j }|j}|j}|D ]}| |d¡||  ||< q|D ]}d||< q%|D ]}d||< q.dS )z.Merge in the data from another CoverageResultsr   r   N)r:   r=   r7   Úget)	r   Úotherr:   r=   r7   Úother_countsÚother_calledfuncsÚother_callersÚkeyr   r   r   rC   »   s   

ÿzCoverageResults.updateTFc           "   
   C   s  | j r tƒ  tdƒ | j }t|ƒD ]\}}}td|||f ƒ q| jrhtƒ  tdƒ d }}	t| jƒD ]4\\}
}}\}}}|
|krNtƒ  td|
dƒ |
}d}	||
kr]|	|kr]td|ƒ |}	td||||f ƒ q3i }| jD ]\}}| |i ¡ }||< | j||f ||< qmi }| ¡ D ]Ž\}}|  |¡r•q‹| d¡r |d	d
… }|d	u r³t	j
 t	j
 |¡¡}t|ƒ}n|}t	j
 |¡sÀt	 |¡ t|ƒ}|rËt|ƒ}ni }t |¡}t	j
 ||d ¡}t|dƒ�}t |j¡\}}W d	  ƒ n1 sów   Y  |  |||||¡\}}|�r|�rtd| | ƒ}||||f||< q‹|�r<|�r<tdƒ t|ƒD ]}|| \}}}}td||  ƒ �q(| j�r‡z)t| jdƒ�} t | j| j | jf| d¡ W d	  ƒ W d	S 1 �sbw   Y  W d	S  t�y† }! ztd|! tj d� W Y d	}!~!d	S d	}!~!ww d	S )af  
        Write the coverage results.

        :param show_missing: Show lines that had no hits.
        :param summary: Include coverage summary per module.
        :param coverdir: If None, the results of each module are placed in its
                         directory, otherwise it is included in the directory
                         specified.
        zfunctions called:z*filename: %s, modulename: %s, funcname: %szcalling relationships:r)   z***z  -->z    %s.%s -> %s.%sz.pycNéÿÿÿÿz.coverr6   éd   zlines   cov%   module   (path)z%5d   %3d%%   %s   (%s)Úwbr   z"Can't save counts files because %sr8   )!r=   rH   Úsortedr7   r:   rP   ÚitemsrO   rN   r   r   ÚdirnameÚabspathr(   ÚexistsÚmakedirsr5   Ú_find_executable_linenosÚ	linecacheÚgetlinesÚjoinr@   ÚtokenizeÚdetect_encodingÚreadlineÚwrite_results_fileÚintr?   rA   ÚdumprE   r+   rI   )"r   Úshow_missingÚsummaryÚcoverdirÚcallsr   r   ÚfuncnameÚlastfileÚ	lastcfileÚpfileÚpmodÚpfuncÚcfileÚcmodÚcfuncÚper_fileÚlinenoÚ	lines_hitÚsumsÚcountr3   ÚlnotabÚsourceÚ	coverpathÚfpÚencodingÚ_Ún_hitsÚn_linesÚpercentÚmrJ   rK   r   r   r   Úwrite_resultsÍ   s�   
ÿÿ






ÿÿ€ÿ(ÿ €ÿúzCoverageResults.write_resultsc              
   C   s  z	t |d|d�}W n ty' } ztd||f tjd� W Y d}~dS d}~ww d}d}	|�J t|dƒD ]9\}
}|
|v rN| d	||
  ¡ |	d7 }	|d7 }n|
|v r`t|vr`| d
¡ |d7 }n| d¡ | | d¡¡ q4W d  ƒ |	|fS 1 s{w   Y  |	|fS )z'Return a coverage results file in path.Úw©r   z3trace: Could not open %r for writing: %s - skippingr8   N)r   r   r   r   z%5d: z>>>>>> z       é   )	r@   rE   rH   r+   rI   Ú	enumerateÚwriteÚPRAGMA_NOCOVERÚ
expandtabs)r   r   Úlinesr{   rx   r   r?   rK   r‚   r�   rw   Úliner   r   r   rf   )  s:   ÿÿ€ý



ò
ÿïz"CoverageResults.write_results_file)NNNNN)TFN©N)r    r!   r"   r   rO   rC   r…   rf   r   r   r   r   r   š   s    
ÿ
\c                 C   s,   i }t  | ¡D ]\}}||vrd||< q|S )z:Return dict where keys are lines in the line number table.r   )ÚdisÚfindlinestarts)ÚcodeÚstrsÚlinenosr€   rw   r   r   r   Ú_find_lines_from_codeI  s   €r•   c                 C   s4   t | |ƒ}| jD ]}t |¡r| t||ƒ¡ q|S )z<Return lineno dict for all code objects reachable from code.)r•   Ú	co_constsÚinspectÚiscoderC   Ú_find_lines)r’   r“   r”   Úcr   r   r   r™   S  s   


€r™   c                 C   s    i }t j}t| |d��;}t |j¡}|D ])\}}}}	}
|t jkr;|t jkr;|\}}|	\}}t||d ƒD ]}d||< q4|}qW d  ƒ |S 1 sIw   Y  |S )zÄReturn a dict of possible docstring positions.

    The dict maps line numbers to strings.  There is an entry for
    line that contains only a string or a part of a triple-quoted
    string.
    r‡   r   N)ÚtokenÚINDENTr@   rc   Úgenerate_tokensre   ÚSTRINGÚrange)r   r   r   Ú
prev_ttyperJ   ÚtokÚttypeÚtstrÚstartÚendrŽ   ÚslineÚscolÚelineÚecolÚir   r   r   Ú_find_strings_  s"   


ù
þ
ö
r«   c              
   C   sœ   zt  | ¡�}| ¡ }|j}W d  ƒ n1 sw   Y  W n ty= } ztd| |f tjd� i W  Y d}~S d}~ww t|| dƒ}t	| |ƒ}t
||ƒS )zAReturn dict where keys are line numbers in the line number table.Nz%Not printing coverage data for %r: %sr8   Úexec)rc   r@   Úreadr   rE   rH   r+   rI   Úcompiler«   r™   )r   rJ   Úprogr   rK   r’   r“   r   r   r   r_   v  s$   þ€ÿÿ€ý

r_   c                   @   sv   e Zd Z			ddd„Zdd	„ Zdd
d„Zdd„ Zd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 ) r   r   r   r   NFc
           
      C   sÊ   || _ || _t||ƒ| _i | _i | _d| _|| _i | _i | _	i | _
d| _|	r*tƒ | _|r2| j| _dS |r:| j| _dS |rH|rH| j| _| j| _dS |rT| j| _| j| _dS |r`| j| _| j| _dS d| _dS )ax  
        @param count true iff it should count number of times each
                     line is executed
        @param trace true iff it should print out each line that is
                     being counted
        @param countfuncs true iff it should just output a list of
                     (filename, modulename, funcname,) for functions
                     that were called at least once;  This overrides
                     `count' and `trace'
        @param ignoremods a list of the names of modules to ignore
        @param ignoredirs a list of the names of directories to ignore
                     all of the (recursive) contents of
        @param infile file from which to read stored counts to be
                     added into the results
        @param outfile file in which to write the results
        @param timing true iff timing information be displayed
        r   Nr   )r>   r?   r   Úignorer:   ÚpathtobasenameÚ	donothingÚtraceÚ_calledfuncsÚ_callersÚ_caller_cacheÚ
start_timeÚ_timeÚglobaltrace_trackcallersÚglobaltraceÚglobaltrace_countfuncsÚglobaltrace_ltÚlocaltrace_trace_and_countÚ
localtraceÚlocaltrace_traceÚlocaltrace_count)
r   rz   r³   Ú
countfuncsÚcountcallersÚ
ignoremodsÚ
ignoredirsr>   r?   Útimingr   r   r   r   …  s6   
zTrace.__init__c                 C   s    dd l }|j}|  |||¡ d S )Nr   )Ú__main__Ú__dict__Úrunctx)r   ÚcmdrÆ   Údictr   r   r   Úrun·  s   z	Trace.runc              	   C   s†   |d u ri }|d u ri }| j st | j¡ t | j¡ zt|||ƒ W | j s2t d ¡ t d ¡ d S d S | j sBt d ¡ t d ¡ w w r�   )r²   Ú	threadingÚsettracerº   r+   r¬   )r   rÉ   ÚglobalsÚlocalsr   r   r   rÈ   ¼  s   

þ
þzTrace.runctxc             	   O   sP   d }| j st | j¡ z||i |¤Ž}W | j st d ¡ |S | j s't d ¡ w w r�   )r²   r+   rÍ   rº   )r   ÚfuncÚargsÚkwÚresultr   r   r   ÚrunfuncÉ  s   
þÿzTrace.runfuncc           
      C   sð   |j }|j}|rt|ƒ}nd }|j}d }|| jv r&| j| d ur%| j| }nCd | j|< dd„ t |¡D ƒ}t|ƒdkridd„ t |d ¡D ƒ}t|ƒdkridd„ t |d ¡D ƒ}	t|	ƒdkri|	d j}|| j|< |d ursd||f }|||fS )Nc                 S   s   g | ]	}t  |¡r|‘qS r   )r—   Ú
isfunction)r   rJ   r   r   r   r   å  ó    
ÿz1Trace.file_module_function_of.<locals>.<listcomp>r   c                 S   s   g | ]	}t |tƒr|‘qS r   )Ú
isinstancerÊ   r
   r   r   r   r   ë  rÖ   r   c                 S   s   g | ]	}t |d ƒr|‘qS )Ú	__bases__)Úhasattr)r   rš   r   r   r   r   î  rÖ   z%s.%s)	Úf_codeÚco_filenamer(   Úco_namer¶   ÚgcÚget_referrersr,   r    )
r   Úframer’   r   r   rm   ÚclsnameÚfuncsÚdictsÚclassesr   r   r   Úfile_module_function_ofÔ  s.   


€



zTrace.file_module_function_ofc                 C   s4   |dkr|   |¡}|   |j¡}d| j||f< dS dS )zkHandler for call events.

        Adds information about who called who to the self._callers dict.
        Úcallr   N)rä   Úf_backrµ   )r   rß   ÚwhyÚargÚ	this_funcÚparent_funcr   r   r   r¹   ý  s
   
üzTrace.globaltrace_trackcallersc                 C   s$   |dkr|   |¡}d| j|< dS dS )zoHandler for call events.

        Adds (filename, modulename, funcname) to the self._calledfuncs dict.
        rå   r   N)rä   r´   )r   rß   rç   rè   ré   r   r   r   r»     s   
þzTrace.globaltrace_countfuncsc                 C   sp   |dkr6|j }|j dd¡}|r4t|ƒ}|dur0| j ||¡}|s2| jr-td||jf ƒ | j	S dS dS dS dS )z’Handler for call events.

        If the code block being entered is to be ignored, returns `None',
        else returns self.localtrace.
        rå   Ú__file__Nz! --- modulename: %s, funcname: %s)
rÚ   Ú	f_globalsrP   r(   r°   r   r³   rH   rÜ   r¾   )r   rß   rç   rè   r’   r   r   Ú	ignore_itr   r   r   r¼     s"   ÿúñzTrace.globaltrace_ltc                 C   s„   |dkr?|j j}|j}||f}| j |d¡d | j|< | jr*tdtƒ | j  dd� tj	 
|¡}td||t ||¡f dd� | jS )	NrŽ   r   r   ú%.2fú ©r¥   ú
%s(%d): %sr)   )rÚ   rÛ   Úf_linenor:   rP   r·   rH   r¸   r   r   r$   r`   Úgetliner¾   )r   rß   rç   rè   r   rw   rU   Úbnamer   r   r   r½   (  s   
ÿÿz Trace.localtrace_trace_and_countc                 C   sd   |dkr/|j j}|j}| jrtdtƒ | j  dd� tj |¡}td||t	 
||¡f dd� | jS )NrŽ   rî   rï   rð   rñ   r)   )rÚ   rÛ   rò   r·   rH   r¸   r   r   r$   r`   ró   r¾   )r   rß   rç   rè   r   rw   rô   r   r   r   r¿   7  s   
ÿÿzTrace.localtrace_tracec                 C   s<   |dkr|j j}|j}||f}| j |d¡d | j|< | jS )NrŽ   r   r   )rÚ   rÛ   rò   r:   rP   r¾   )r   rß   rç   rè   r   rw   rU   r   r   r   rÀ   D  s   zTrace.localtrace_countc                 C   s   t | j| j| j| j| jd�S )N)r>   r?   r=   r7   )r   r:   r>   r?   r´   rµ   )r   r   r   r   ÚresultsL  s
   
ýzTrace.results)	r   r   r   r   r   r   NNFr   )r    r!   r"   r   rË   rÈ   rÔ   rä   r¹   r»   r¼   r½   r¿   rÀ   rõ   r   r   r   r   r   „  s     
þ2
)	c                     sì  dd l } |  ¡ }|jdddd� | dd¡}|jdd	d
dd� |jddd
dd� |jddd
dd� |jddd
dd� | d¡}| ¡ }|jddd
dd� |jddd
dd� |jdddd � |jd!d"d#d � |jd$d%d
d&d� |jd'd(d
d)d� |jd*d+d
d,d� | d-d.¡}|jd/d0g d1d2� |jd3d0g d4d2� |jd5d
d6d7d2� |jd8d9d:d;� |jd<| jd=d;� | ¡ }|jrÃt 	d>¡‰t 	d?¡‰ ‡ ‡fd@dA„‰dBdC„ |j
D ƒ|_
‡fdDdC„|jD ƒ|_|jrû|jsé| dE¡ t|j|jdF�}| |j|j|j¡S t|j|j|j|jgƒ�s| dG¡ |j�r|j�s|j�r| dH¡ |j�r+|j�s+| dI¡ |jd u �r6| dJ¡ t|j|j|j|j|j
|j|j|j|jdK�	}zk|j�rudd l}|j}| |¡\}	}
}|jg|j¢t _!dL|j|
j"|
j#|
d dMœ}n:|jg|j¢t _!t$j% &|j¡t j%d< t' (|j¡�}t)| *¡ |jdNƒ}W d   ƒ n	1 �s¢w   Y  |jdLd d dOœ}| +|||¡ W n( t,�yÖ } zt  -dPt j!d |f ¡ W Y d }~nd }~w t.�yß   Y nw | /¡ }|j0�sô| |j|j|j¡ d S d S )QNr   z	--versionÚversionz	trace 2.0)Úactionrö   zMain optionsz(One of these (or --report) must be givenz-cz--countÚ
store_truez»Count the number of times each line is executed and write the counts to <module>.cover for each module executed, in the module's directory. See also --coverdir, --file, --no-report below.)r÷   Úhelpz-tz--tracez3Print each line to sys.stdout before it is executedz-lz--listfuncsz§Keep track of which functions are executed at least once and write the results to sys.stdout after the program exits. Cannot be specified alongside --trace or --count.z-Tz--trackcallsz^Keep track of caller/called pairs and write the results to sys.stdout after the program exits.Ú	Modifiersz-rz--reportz¶Generate a report from a counts file; does not execute any code. --file must specify the results file to read, which must have been created in a previous run with --count --file=FILEz-Rz--no-reportz^Do not generate the coverage report files. Useful if you want to accumulate over several runs.z-fz--filez+File to accumulate counts over several runs)rù   z-Cz
--coverdirz†Directory where the report files go. The coverage report for <package>.<module> will be written to file <dir>/<package>/<module>.coverz-mz	--missingz?Annotate executable lines that were not executed with ">>>>>> "z-sz	--summaryz\Write a brief summary for each file to sys.stdout. Can only be used with --count or --reportz-gz--timingzQPrefix each line with the time since the program started. Only used while tracingÚFilterszCan be specified multiple timesz--ignore-moduleÚappendzqIgnore the given module(s) and its submodules (if it is a package). Accepts comma separated list of module names.)r÷   Údefaultrù   z--ignore-dirzWIgnore files in the given directory (multiple directories can be joined by os.pathsep).z--moduleFzTrace a module. Úprognameú?zfile to run as main program)Únargsrù   Ú	argumentszarguments to the programÚstdlibÚ
platstdlibc                    s4   t j t j | ¡¡} |  dˆ¡ dˆ ¡} t j | ¡S )Nz$prefixz$exec_prefix)r   r   Ú
expanduserÚ
expandvarsr.   r	   )Ús)Ú_exec_prefixÚ_prefixr   r   Úparse_ignore_dir�  s   zmain.<locals>.parse_ignore_dirc                 S   s$   g | ]}|  d ¡D ]}| ¡ ‘q	qS )ú,)ÚsplitÚstrip)r   rª   r   r   r   r   r   ¢  s
    
ÿÿzmain.<locals>.<listcomp>c                    s&   g | ]}|  tj¡D ]}ˆ |ƒ‘q
qS r   )r  r   Úpathsep)r   rª   r  )r	  r   r   r   ¤  s
    ÿÿz-r/--report requires -f/--file)r>   r?   zLmust specify one of --trace, --count, --report, --listfuncs, or --trackcallsz8cannot specify both --listfuncs and (--trace or --count)z3--summary can only be used with --count or --reportz3progname is missing: required with the main options)rÁ   rÂ   rÃ   rÄ   r>   r?   rÅ   rÆ   )r    rë   Ú__package__Ú
__loader__Ú__spec__Ú
__cached__r¬   )rë   r    r  r  zCannot run file %r because: %s)1ÚargparseÚArgumentParserÚadd_argumentÚadd_argument_groupÚadd_mutually_exclusive_groupÚ	REMAINDERÚ
parse_argsÚ
ignore_dirÚ	sysconfigÚget_pathÚignore_moduleÚreportr9   Úerrorr   r…   Úmissingrj   rk   Úanyr³   rz   Ú	listfuncsÚ
trackcallsrþ   r   rÅ   ÚmoduleÚrunpyÚ_get_module_detailsrÛ   r  r+   ÚargvÚparentÚloaderr   r   r[   ÚioÚ	open_coder®   r­   rÈ   rE   ÚexitÚ
SystemExitrõ   Ú	no_report)r  ÚparserÚgrpÚ_grpÚoptsrõ   Útr$  Úmodule_nameÚmod_nameÚmod_specr’   Úglobsr~   rK   r   )r  r  r	  r   ÚmainR  sô   ÿ
ÿ
ÿ
ÿ
ÿ

ÿ
ÿÿÿ
ÿ
ÿ
ÿÿ
ÿ
ÿ
ÿÿ
ÿ

ÿ
ÿ




ýú	ÿü$€ÿÿr7  rÆ   r�   )Ú__doc__Ú__all__r)  r`   r   r+   r  r›   rc   r—   rÝ   r�   rA   Útimer   r¸   rÌ   r‹   r   r(   r5   r   r•   r™   r«   r_   r   r7  r    r   r   r   r   Ú<module>   s@   2 0

 O 
ÿ