
    L-Ph                       d Z ddlm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mZ ddlmZ ddlmZ ddlmZmZmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddl m!Z!m"Z" ddl#m$Z$ ddl%m&Z&m'Z'  e!e          Z G d d          Z( G d d          Z) edd           G d d                      Z* G d de          Z+e,e&e-e.ee/         ee/         f                  f         Z0 G d d          Z1 G d de1          Z2 G d de1          Z3 G d d e1          Z4 G d! d"ej5                  Z6d*d'Z7 G d( d)          Z8dS )+zCode parsing for coverage.py.    )annotationsN)IterableSequence)	dataclass)CodeType)castCallableOptionalProtocol)env)code_objects)short_stack)NoSource	NotPython)isolate_module	nice_pair)generate_tokens)TArcTLineNoc                      e Zd ZdZ	 	 	 d)d*d	Zd+dZd,dZ ej        d          d-d            Z	d.dZ
d/dZd0dZd,dZd1dZd,dZd0d Zej        d2d"            Zd3d%Zd4d'Zd4d(ZdS )5PythonParserzParse code to find executable lines, excluded lines, etc.

    This information is all based on static analysis: no code execution is
    involved.

    Ntext
str | NonefilenameexcludereturnNonec                   |s|s
J d            |pd| _         ||| _        nJddlm} 	  || j                   | _        n-# t          $ r }t          d| j          d|           |d}~ww xY w|| _        d| _        t                      | _	        t                      | _
        t                      | _        t                      | _        t                      | _        d| _        i | _        d| _        d| _        i | _        dS )	z
        Source can be provided as `text`, the text itself, or `filename`, from
        which the text will be read.  Excluded lines are those that match
        `exclude`, a regex string.

        z*PythonParser needs either text or filenamez<code>Nr   )get_python_sourcezNo source for code: 'z': F)r   r   coverage.pythonr   OSErrorr   r   	_ast_rootset
statementsexcludedraw_statementsraw_excludedraw_docstringsshow_tokens
_multiline	_all_arcs_missing_arc_fragments_with_jump_fixers)selfr   r   r   r   errs         O/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/coverage/parser.py__init__zPythonParser.__init__(   s6    MxMM!MMMM ,H!DII999999Y--dm<<		 Y Y YNt}NNNNOOUXXY  *.
 ), '*ee -0EE +.%% -0EE ! 35 ,0<@#@Bs   ? 
A)	A$$A)regexstrset[TLineNo]c           	         t                      }d}d}t          j        | j        t          j                  D ]}|                                \  }}| j                            d||          z   }| j                            d||          z   }	|                     fdt          |dz   |	dz             D                        |}|}|S )zFind the lines matching a regex.

        Returns a set of line numbers, the lines that contain a match for
        `regex`. The entire line needn't match, just a part of it.
        Handles multiline regex patterns.

        r   )flags
c              3  N   K   | ]}j                             ||          V   d S Nr*   get).0ir.   s     r0   	<genexpr>z.PythonParser.lines_matching.<locals>.<genexpr>v   s5      bb4?..q!44bbbbbb          )	r#   refinditerr   	MULTILINEspancountupdaterange)
r.   r2   matches
last_startlast_start_linematchstartend
start_lineend_lines
   `         r0   lines_matchingzPythonParser.lines_matchingf   s     !$
[	FFF 	) 	)EJE3(49??4U+S+SSJ&z3)O)OOHNNbbbbeJQRNT\_`T`>a>abbbbbbJ(OOr?   c           
     	   | j         r8|                     | j                   | _        t          | j                  | _        d}d}d}d}d}d}| j        J t          | j                  }|D ]\  }}	\  }
}\  }}}| j        rJt          t          j
                            ||          ddt          |
|f          dd|	dd|           |t          j        k    r|d	z  }n|t          j        k    r|d	z  }n|t          j        k    rn|	d
k    rT|dk    rN| j                            t%          ||d	z                       }|s |r| j                            |           |}d}nN|	dv r|d	z  }nD|	dv r|d	z  }n:|t          j        k    r*|r&||k    r t%          ||d	z             D ]}|| j        |<   d}|	                                r<|t          j        k    r,d}|s(|
}|r||k    rd}|r| j                            |           |sGt1          | j        | j                  }| j                            |                                           t:          j        j        r*| j        r#| j        rtA          | j                  | j        d	<   | !                    | j                  | _        | j"        J tG          j$        | j"                  D ]}tK          |tF          j&        tF          j'        tF          j(        tF          j)        f          r|j*        r|j*        d         }tK          |tF          j+                  rtK          |j,        tF          j-                  rgtK          |j,        j,        t\                    rH| j/                            t%          |j0        tc          td          |j3                  d	z                        tK          |tF          j&        tF          j'        tF          j(        f          rtA          d |j4        D             |j0                  }| j                            t%          ||j0        d	z                       rC| j                            t%          |tc          td          |j3                  d	z                        dS )zwParse the source to find the interesting facts about its lines.

        A handful of attributes are updated.

        r   FTNz>10 z>520r@   :z([{z)]})r   c              3  $   K   | ]}|j         V  d S r9   lineno)r<   ds     r0   r>   z*PythonParser._raw_parse.<locals>.<genexpr>   s$      !H!Hq!(!H!H!H!H!H!Hr?   )default)5r   rQ   r'   r#   r%   r   r   r)   printtokenizetok_namer;   r   tokenINDENTDEDENTOPintersectionrH   addNEWLINEr*   stripCOMMENT
ByteParserr   r&   rG   _find_statementsr   
PYBEHAVIORmodule_firstline_1minfirst_linesr"   astwalk
isinstanceClassDefFunctionDefAsyncFunctionDefModulebodyExprvalueConstantr3   r(   rX   r   int
end_linenodecorator_list)r.   indentexclude_indent	excluding
first_lineemptynestingtokgentoktypettextslineno_elinenoltextshould_excludelbyte_parsernodefirsts                      r0   
_raw_parsezPythonParser._raw_parse{   s    < 	3 $ 3 3DL A AD 122DM 	
y$$$ ++AG -	3 -	3=GULWa,7A %))'7;;;;;w0111115555%%    %,&&!EL((!EH$$C<<GqLL225Wq[3Q3QRR # % ) ) ))'222)/$(	e^^qLGGe^^qLGEM)) 8'Z"7"7 #:wqy99 8 8-7**
{{}} 
3H,<!<!<! 3!(J  *V~%=%=$)	  3))'222  	G$TYGGGK&&{'C'C'E'EFFF
 >, 	: 	:TEX 	:!$T%8!9!9DOA((77 ~)))HT^,, 	\ 	\D$s@TVYV` abb 
9 	 IaLE"5#(33&u{CLAA 'u{'8#>>
 +22!%,S%:J0K0Ka0OPP  
 $s@T UVV \ !H!HD4G!H!H!HRVR]^^^
=--eJa.P.PQQ \M((z4T_;U;UXY;Y)Z)Z[[[%	\ 	\r?   i  )maxsizerX   r   c                    |dk     r| j                             | |            }n| j                             ||          }|S )zAReturn the first line number of the statement including `lineno`.r   r:   )r.   rX   s     r0   r~   zPythonParser.first_line   sI     A::o))6'F7;;;FF_((88Fr?   linenosIterable[TLineNo]c                       fd|D             S )zMap the line numbers in `linenos` to the correct first line of the
        statement.

        Returns a set of the first lines.

        c                :    h | ]}                     |          S  r~   )r<   r   r.   s     r0   	<setcomp>z+PythonParser.first_lines.<locals>.<setcomp>   s%    444q""444r?   r   )r.   r   s   ` r0   rl   zPythonParser.first_lines   s     5444G4444r?   linesc                ,    |                      |          S )z)Implement `FileReporter.translate_lines`.)rl   )r.   r   s     r0   translate_lineszPythonParser.translate_lines   s    &&&r?   arcsIterable[TArc]	set[TArc]c                F      fd                      |          D             S )z(Implement `FileReporter.translate_arcs`.c                j    h | ]/\  }}                     |                               |          f0S r   r   )r<   abr.   s      r0   r   z.PythonParser.translate_arcs.<locals>.<setcomp>   s:    aaaVa##T__Q%7%78aaar?   )fix_with_jumps)r.   r   s   ` r0   translate_arcszPythonParser.translate_arcs   s,    aaaatGZGZ[_G`G`aaaar?   c                   	 t          j        | j                  | _        |                                  n{# t
          j        t          t          f$ r\}t          |d          r|j
        }n|j        d         d         }t          d| j         d|j        d         d| z             |d}~ww xY w| j        | j        z  }| j        |z
  }|                     |          |z
  | _        dS )zParse source text to find executable lines, excluded lines, etc.

        Sets the .excluded and .statements attributes, normalized to the first
        line of multi-line statements.

        rX   r@   r   zCouldn't parse 'z' as Python source: z	 at line N)rm   parser   r"   r   r\   
TokenErrorIndentationErrorSyntaxErrorhasattrrX   argsr   r   r%   r(   r&   rl   r$   )r.   r/   rX   ignorestartss        r0   parse_sourcezPythonParser.parse_source  s    	 Yty11DNOO#%5{C 	 	 	sH%% (!QF4=FFF8A;336334  	 !44$v-**622V;s   25 B-AB((B-c                X    | j         |                                  | j         J | j         S )zGet information about the arcs available in the code.

        Returns a set of line number pairs.  Line numbers have been normalized
        to the first line of multi-line statements.

        )r+   _analyze_astr.   s    r0   r   zPythonParser.arcs  s4     >!~)))~r?   c                   | j         J t          | j        | j         | j        | j                  }|                                 |j        }t          j        j	        r5|
                                | _        | j        r|                     |          }t                      | _        |D ]Q\  }}|                     |          }|                     |          }||k    r| j                            ||f           R|j        | _        dS )zkRun the AstArcAnalyzer and save its results.

        `_all_arcs` is the set of arcs in the code.

        N)r"   AstArcAnalyzerr   r&   r*   analyzer   r   ri   exit_through_withwith_jump_fixersr-   r   r#   r+   r~   rc   missing_arc_fragmentsr,   )r.   aaar   l1l2fl1fl2s          r0   r   zPythonParser._analyze_ast&  s     ~)))T]DND<OQUQ`aax>+ 	1%(%9%9%;%;D"% 1**400 	/ 	/FB//"%%C//"%%Cczz""C:...&)&?###r?   c                   t                      }t                      }|D ]}|| j        v r|d         }|                    |           | j        |         \  }}|| j        v rC|                    |           | j        |         \  }}|                    |           || j        v C|                    ||d         f           |                    |           t          |          |z  |z
  }|S )a  Adjust arcs to fix jumps leaving `with` statements.

        Consider this code:

            with open("/tmp/test", "w") as f1:
                a = 2
                b = 3
            print(4)

        In 3.10+, we get traces for lines 1, 2, 3, 1, 4.  But we want to present
        it to the user as if it had been 1, 2, 3, 4.  The arc 3->1 should be
        replaced with 3->4, and 1->4 should be removed.

        For this code, the fixers dict is {(3, 1): ((1, 4), (3, 4))}.  The key
        is the actual measured arc from the end of the with block back to the
        start of the with-statement.  The values are start_next (the with
        statement to the next statement after the with), and end_next (the end
        of the with-statement to the next statement after the with).

        With nested with-statements, we have to trace through a few levels to
        correct a longer chain of arcs.

        r   r@   )r#   r-   rc   )r.   r   	to_removeto_addarcend0
start_nextend_nexts           r0   r   zPythonParser.fix_with_jumps>  s    0 EE	 
	* 
	*Cd,,,1vc"""'+'=c'B$
H D$:::MM*---+/+A*+M(JMM(+++ !D$::: 

D(1+.///j)))D		F"i/r?   dict[TLineNo, int]c                    t          j        t                    }|                                 D ]D\  }}|dk    sJ d|d| j                     || j        v r*|| j        v r4||xx         dz  cc<   E|S )zYGet a count of exits from that each line.

        Excluded lines are excluded.

        r   zl1=z  should be greater than zero in r@   )collectionsdefaultdictrx   r   r   r%   )r.   exit_countsr   r   s       r0   r   zPythonParser.exit_countsf  s     +6*A#*F*Fiikk 	! 	!FB666RbRR4=RR666T]""T]""OOOq OOOOr?   
action_msgrN   c                L    ||dk     rd}nd}|                     |          }|S )z=Apply some defaulting and formatting to an arc's description.Nr   zjump to the function exitzjump to line {lineno}rW   )format)r.   r   rN   s      r0   _finish_action_msgzPythonParser._finish_action_msgz  s9    Qww8

4
&&c&22
r?   rM   c                f   | j         |                                  | j         J | j                             ||fdg          }g }|D ]V\  }}|                     ||          }d| d| }||d|                    |           z  }|                    |           Wd                    |          S )z5Provide an English sentence describing a missing arc.NNNzline z didn't z	 because rW   z or )r,   r   r;   r   r   appendjoin)r.   rM   rN   fragment_pairsmsgsmissing_cause_msgr   msgs           r0   missing_arc_descriptionz$PythonParser.missing_arc_description  s    &..:::488%~VV-; 	 	)z00SAAJ5%5555C ,K#4#;#;5#;#I#IKKKKK{{4   r?   c                    | j         |                                  | j         J | j                             ||fdg          }|                     |d         d         |          }|S )z2Provide an English description of an arc's effect.Nr   r   r@   )r,   r   r;   r   )r.   rM   rN   r   r   s        r0   arc_descriptionzPythonParser.arc_description  so    &..:::488%~VV,,^A->q-A3GG
r?   )NNN)r   r   r   r   r   r   r   r   )r2   r3   r   r4   r   r   )rX   r   r   r   )r   r   r   r4   )r   r   r   r4   )r   r   r   r   )r   r   )r   r   )r   r   rN   r   r   r3   )rM   r   rN   r   r   r3   )__name__
__module____qualname____doc__r1   rQ   r   	functools	lru_cacher~   rl   r   r   r   r   r   r   r   r   r   r   r   r?   r0   r   r   !   s          #"	<C <C <C <C <C|   *k\ k\ k\ k\Z Y&&&   '&5 5 5 5' ' ' 'b b b b< < < <0
 
 
 
@ @ @ @0& & & &P    &   ! ! ! !&     r?   r   c                  8    e Zd ZdZ	 	 dddZddZddZddZdS )rg   z3Parse bytecode to understand the structure of code.Nr   r3   codeCodeType | Noner   r   r   r   c                b    || _         |	|| _        d S |J t          ||dd          | _        d S )NexecT)dont_inherit)r   r   compile)r.   r   r   r   s       r0   r1   zByteParser.__init__  sF     	DIII'''  hTJJJDIIIr?   Iterable[ByteParser]c                D      fdt           j                  D             S )a|  Iterate over all the code objects nested within this one.

        The iteration includes `self` as its first value.

        We skip code objects named `__annotate__` since they are deferred
        annotations that usually are never run.  If there are errors in the
        annotations, they will be caught by type checkers or other tools that
        use annotations.

        c              3  Z   K   | ]%}|j         d k    t          j        |          V  &dS )__annotate__)r   N)co_namerg   r   )r<   cr.   s     r0   r>   z+ByteParser.child_parsers.<locals>.<genexpr>  sK       
 
yN** tyq)))****
 
r?   )r   r   r   s   `r0   child_parserszByteParser.child_parsers  s8    
 
 
 
!$),,
 
 
 	
r?   r   c              #    K   t          | j        d          r(| j                                        D ]\  }}}|r|V  dS | j        j        ddd         }| j        j        ddd         }d}| j        j        }d}t          ||          D ](\  }}	|r||k    r|V  |}||z  }|	dk    r|	dz  }	||	z  })||k    r|V  dS dS )zYield the line numbers possible in this code object.

        Uses co_lnotab described in Python/compile.c to find the
        line numbers.  Produces a sequence: l0, l1, ...
        co_linesr   NrA   r@         )r   r   r   	co_lnotabco_firstlinenozip)
r.   r   linebyte_incrementsline_incrementslast_line_numline_numbyte_num	byte_incr	line_incrs
             r0   _line_numberszByteParser._line_numbers  s%      49j)) 	"i0022  
1d JJJ 
 #i1!$Q$7O"i1!$Q$7O,0My/HH(+O_(M(M & &$	9 *=00&(0	)H$$&II%=(( )(r?   c              #  l   K   |                                  D ]}|                                E d{V  dS )zFind the statements in `self.code`.

        Produce a sequence of line numbers that start statements.  Recurses
        into all code objects reachable from `self.code`.

        N)r   r   )r.   bps     r0   rh   zByteParser._find_statements  sT       $$&& 	* 	*B''))))))))))	* 	*r?   r   )r   r3   r   r   r   r   r   r   )r   r   )r   r   )r   r   r   r   r1   r   r   rh   r   r?   r0   rg   rg     s|        ==
 !%#	K K K K K
 
 
 
"   >	* 	* 	* 	* 	* 	*r?   rg   T)frozenorderc                  ,    e Zd ZU dZded<   dZded<   dS )ArcStarta?  The information needed to start an arc.

    `lineno` is the line number the arc starts from.

    `cause` is an English text fragment used as the `missing_cause_msg` for
    AstArcAnalyzer.missing_arc_fragments.  It will be used to describe why an
    arc wasn't executed, so should fit well into a sentence of the form,
    "Line 17 didn't run because {cause}."  The fragment can include "{lineno}"
    to have `lineno` interpolated into it.

    As an example, this code::

        if something(x):        # line 1
            func(x)             # line 2
        more_stuff()            # line 3

    would have two ArcStarts:

    - ArcStart(1, "the condition on line 1 was always true")
    - ArcStart(1, "the condition on line 1 was never true")

    The first would be used to create an arc from 1 to 3, creating a message like
    "line 1 didn't jump to line 3 because the condition on line 1 was always true."

    The second would be used for the arc from 1 to 2, creating a message like
    "line 1 didn't jump to line 2 because the condition on line 1 was never true."

    r   rX    r3   causeN)r   r   r   r   __annotations__r  r   r?   r0   r   r     s2          8 OOOEOOOOOOr?   r   c                       e Zd ZdZ	 	 dddZdS )	TAddArcFnz&The type for AstArcAnalyzer.add_arc().NrM   r   rN   r   r   r   r   r   c                    dS )ab  
        Record an arc from `start` to `end`.

        `missing_cause_msg` is a description of the reason the arc wasn't
        taken if it wasn't taken.  For example, "the condition on line 10 was
        never true."

        `action_msg` is a description of what the arc does, like "jump to line
        10" or "exit from function 'fooey'."

        Nr   r.   rM   rN   r   r   s        r0   __call__zTAddArcFn.__call__  s      r?   r   
rM   r   rN   r   r   r   r   r   r   r   )r   r   r   r   r  r   r?   r0   r  r    s;        00
 )-!%      r?   r  c                  2    e Zd ZdZddZdd	Zdd
ZddZdS )Blocka;  
    Blocks need to handle various exiting statements in their own ways.

    All of these methods take a list of exits, and a callable `add_arc`
    function that they can use to add arcs if needed.  They return True if the
    exits are handled, or False if the search should continue up the block
    stack.
    exitsset[ArcStart]add_arcr  r   boolc                    dS )zProcess break exits.Fr   r.   r  r  s      r0   process_break_exitszBlock.process_break_exits8      ur?   c                    dS )zProcess continue exits.Fr   r  s      r0   process_continue_exitszBlock.process_continue_exits<  r  r?   c                    dS )zProcess raise exits.Fr   r  s      r0   process_raise_exitszBlock.process_raise_exits@  r  r?   c                    dS )zProcess return exits.Fr   r  s      r0   process_return_exitszBlock.process_return_exitsD  r  r?   Nr  r  r  r  r   r  )r   r   r   r   r  r  r  r  r   r?   r0   r  r  .  sn                       r?   r  c                  *    e Zd ZdZddZddZddZdS )	LoopBlockz@A block on the block stack representing a `for` or `while` loop.rM   r   r   r   c                :    || _         t                      | _        d S r9   )rM   r#   break_exits)r.   rM   s     r0   r1   zLoopBlock.__init__K  s    
*-%%r?   r  r  r  r  r  c                :    | j                             |           dS NT)r  rG   r  s      r0   r  zLoopBlock.process_break_exitsQ  s    &&&tr?   c                H    |D ]} ||j         | j        |j                   dS r   )rX   rM   r  r.   r  r  xits       r0   r  z LoopBlock.process_continue_exitsU  s3     	7 	7CGCJ
CI6666tr?   N)rM   r   r   r   r  )r   r   r   r   r1   r  r  r   r?   r0   r  r  I  sV        JJ0 0 0 0        r?   r  c                  *    e Zd ZdZddZddZddZdS )FunctionBlockz>A block on the block stack representing a function definition.rM   r   namer3   r   r   c                "    || _         || _        d S r9   rM   r&  )r.   rM   r&  s      r0   r1   zFunctionBlock.__init__]  s    
			r?   r  r  r  r  r  c                \    |D ](} ||j         | j         |j        d| j                   )dS )Nzexcept from function TrX   rM   r  r&  r"  s       r0   r  z!FunctionBlock.process_raise_exitsc  M     	 	CG
TZK5	55    tr?   c                \    |D ](} ||j         | j         |j        d| j                   )dS )Nzreturn from function Tr*  r"  s       r0   r  z"FunctionBlock.process_return_exitsk  r+  r?   N)rM   r   r&  r3   r   r   r  )r   r   r   r   r1   r  r  r   r?   r0   r%  r%  [  sV        HH           r?   r%  c                  "    e Zd ZdZddZddZdS )TryBlockz6A block on the block stack representing a `try` block.handler_startTLineNo | Nonefinal_startr   r   c                "    || _         || _        d S r9   )r/  r1  )r.   r/  r1  s      r0   r1   zTryBlock.__init__v  s    *&r?   r  r  r  r  r  c                V    | j         !|D ]} ||j        | j         |j                   dS r   )r/  rX   r  r"  s       r0   r  zTryBlock.process_raise_exits|  s?    ) C C
D$6	BBBBtr?   N)r/  r0  r1  r0  r   r   r  )r   r   r   r   r1   r  r   r?   r0   r.  r.  t  sB        @@' ' ' '     r?   r.  c                      e Zd ZdZddZdS )	NodeListzA synthetic fictitious node, containing a sequence of nodes.

    This is used when collapsing optimized if-statements, to represent the
    unconditional execution of one of the clauses.

    rt   Sequence[ast.AST]r   r   c                8    || _         |d         j        | _        d S Nr   )rt   rX   )r.   rt   s     r0   r1   zNodeList.__init__  s    	1gnr?   N)rt   r6  r   r   )r   r   r   r   r1   r   r?   r0   r5  r5    s2         % % % % % %r?   r5  r   ast.ASTr   tuple[bool, bool]c                   t          | t          j                  rdt          | j                  fS t          | t          j                  r | j        dv rdt          | j                  fS nt          | t          j                  r;t          | j	        t          j
                  rt          | j                  \  }}|| fS t          | t          j                  rpd | j        D             }t          d |D                       }|rDt          | j	        t          j                  rt"          nt          }d |d |D                       fS dS )zIs this a compile-time constant test expression?

    We don't try to mimic all of CPython's optimizations.  We just have to
    handle the kinds of constant expressions people might actually use.

    T)TrueFalser   	__debug__c                ,    g | ]}t          |          S r   )is_constant_test_expr)r<   vs     r0   
<listcomp>z)is_constant_test_expr.<locals>.<listcomp>  s!    >>>Q%a((>>>r?   c              3      K   | ]	\  }}|V  
d S r9   r   )r<   is_constr   s      r0   r>   z(is_constant_test_expr.<locals>.<genexpr>  s&      ;;{x(;;;;;;r?   c              3      K   | ]	\  }}|V  
d S r9   r   )r<   r   rA  s      r0   r>   z(is_constant_test_expr.<locals>.<genexpr>  s&      //$!QA//////r?   )FF)ro   rm   rw   r  rv   NameidevalUnaryOpopNotr@  operandBoolOpvaluesallOrany)r   is_constantvalretsrJ  s        r0   r@  r@    sC    $%% 0T$*%%%%	D#(	#	# 07<<<dg&& =	D#+	&	& 0:dgsw+G+G 00>>SG##	D#*	%	% 0>>$+>>>;;d;;;;; 	0"47CF33<B//$///////<r?   c                     e Zd ZdZdVdZdWdZdXdZdYdZdZdZeZ	d[dZ
	 	 d\d]dZd^d Zd_d!Zd`d"Zdad$ZeZdbd&ZeZeZdcd(Zddd)Zh d*Zded,Z	 	 d\dfd3Zdgd5Zdhd7Zdid9Zdjd;Zdkd=Zdkd>Zdkd?Zdkd@Z dldBZ!dmdCZ"e"Z#dndEZ$dodGZ%e%Z&e"Z'e"Z(dpdHZ)e*j+        dIk    rdqdKZ,drdLZ-dsdNZ.dtdPZ/dudRZ0dvdSZ1dwdUZ2e2Z3dS )xr   a  Analyze source text with an AST to find executable code paths.

    The .analyze() method does the work, and populates these attributes:

    `arcs`: a set of (from, to) pairs of the the arcs possible in the code.

    `missing_arc_fragments`: a dict mapping (from, to) arcs to lists of
    message fragments explaining why the arc is missing from execution::

        { (start, end): [(missing_cause_msg, action_msg), ...], }

    For an arc starting from line 17, they should be usable to form complete
    sentences like: "Line 17 didn't {action_msg} because {missing_cause_msg}".

    NOTE: Starting in July 2024, I've been whittling this down to only report
    arc that are part of true branches.  It's not clear how far this work will
    go.

    r   r3   	root_noder9  r$   r4   	multilinedict[TLineNo, TLineNo]r   r   c                   || _         || _        fd|D             | _        | _        t	          t          t          j        dd                              }|rWt          d| j                    t          d| j                    t          t          j
        | j        dd                     t                      | _        t          j        t                    | _        g | _        t                      | _        t                      | _        t                      | _        t                      | _        t	          t          t          j        d	d                              | _        d S )
Nc                <    h | ]}                     ||          S r   )r;   )r<   r   rW  s     r0   r   z*AstArcAnalyzer.__init__.<locals>.<setcomp>  s'    CCC19==A..CCCr?   COVERAGE_AST_DUMP0zStatements: zMultiline map: T   )include_attributesr{   COVERAGE_TRACK_ARCS)r   rV  r$   rW  r  rx   osgetenvr[   rm   dumpr#   r   r   r   listr   block_stackcurrent_with_startsall_with_startswith_entries
with_exitsdebug)r.   r   rV  r$   rW  dump_asts       ` r0   r1   zAstArcAnalyzer.__init__  s6    !"CCCC
CCC" BI&93??@@AA 	O2223334DN44555#(4>d1MMMNNN"uu	4?4KD4Q4Q"(* 25 -0UU'*uu%(UU #bi(=sCCDDEE


r?   c                    t          j        | j                  D ]/}|j        j        }t          | d| d          }| ||           0dS )zFExamine the AST tree from `self.root_node` to determine possible arcs._code_object__N)rm   rn   rV  	__class__r   getattr)r.   r   	node_namecode_object_handlers       r0   r   zAstArcAnalyzer.analyze  sd    HT^,, 	* 	*D/I")$0L0L0Ld"S"S".##D)))		* 	*r?   dict[TArc, tuple[TArc, TArc]]c                "    i } fd j         D             } j        D ]ofd|D             }|st          |          dk    sJ d| d            |                                }fd j        D             }|D ]}|f||ff||f<   p|S )aK  Get a dict with data for fixing jumps out of with statements.

        Returns a dict.  The keys are arcs leaving a with-statement by jumping
        back to its start.  The values are pairs: first, the arc from the start
        to the next statement, then the arc that exits the with without going
        to the start.

        c                D    h | ]}|d          j         v |j        v|S )r   )rf  rg  )r<   r   r.   s     r0   r   z2AstArcAnalyzer.with_jump_fixers.<locals>.<setcomp>  sB     
 
 
1v---#T=N2N2N 2N2N2Nr?   c                8    h | ]}|d          k    |d         S )r   r@   r   r<   r   rM   s     r0   r   z2AstArcAnalyzer.with_jump_fixers.<locals>.<setcomp>  s&    EEESVu__SV___r?   r@   zExpected one arc, got z with start = c                8    h | ]}|d          k    |d         S )r@   r   r   ru  s     r0   r   z2AstArcAnalyzer.with_jump_fixers.<locals>.<setcomp>  s&    IIIsQ5CFr?   )r   rf  lenpoprh  )r.   fixers
with_nextsnextsnxtendsrN   rM   s   `      @r0   r   zAstArcAnalyzer.with_jump_fixers  s     
 
 
 
y
 
 


 ) 	B 	BEEEEEzEEEE u::???$TU$T$T%$T$T???))++CIIIIdoIIID B B).sCj'AU|$$Br?   r   
ast.Modulec                    |                      |          }|j        rD|                     |j                  }|D ]%}|                     |j        | |j        d           &d S |                     ||            d S )Nzexit the module)line_for_nodert   process_bodyr  rX   r  r.   r   rM   r  r#  s        r0   _code_object__Modulez#AstArcAnalyzer._code_object__Module  s    ""4((9 	(%%di00E O OSZ%<MNNNNO O LL'''''r?   ast.FunctionDefc                   |                      |          }| j                            t          ||j                             |                     |j                  }|                     |           | j                                         d S )Nr(  )	r  rd  r   r%  r&  r  rt   r  rx  r.   r   rM   r  s       r0   _code_object__FunctionDefz(AstArcAnalyzer._code_object__FunctionDef  s    ""4((E	 J J JKKK!!$),,!!%(((r?   ast.ClassDefc                    |                      |          }|                     |j                  }|D ]-}|                     |j        | |j        d|j                   .d S )Nzexit class )r  r  rt   r  rX   r  r&  r  s        r0   _code_object__ClassDefz%AstArcAnalyzer._code_object__ClassDef  ss    ""4((!!$),, 	U 	UCLLeVSY8Sdi8S8STTTT	U 	Ur?   NrM   r   rN   r   r   r   c           
     Z   | j         r8t          d| d| d|d|           t          t                      d           | j                            ||f           || j        v r| j                            ||f           ||&| j        ||f                             ||f           dS dS )z@Add an arc, including message fragments to use if it is missing.zAdding possible arc: (z, z): z

)rN   N)	ri  r[   r   r   rc   re  rg  r   r   r  s        r0   r  zAstArcAnalyzer.add_arc$  s     : 	-a5aaCaa<MaaS]aabbb+--V,,,,	ucl###D,,,!!5#,///(J,B&s|4;;=NPZ<[\\\\\ -C,Br?   Iterable[Block]c                *    t          | j                  S )z.Yield the blocks in nearest-to-farthest order.)reversedrd  r   s    r0   nearest_blockszAstArcAnalyzer.nearest_blocks6  s    ()))r?   c                   |j         j        }t          t          t          t
          j        gt          f                  t          | d| d                    }| ||          }n|j	        }| j
                            ||          S )z}What is the right line number to use for this node?

        This dispatches to _line__Node functions where needed.

        _line__N)rm  r   r   r
   r	   rm   ASTr   rn  rX   rW  r;   )r.   r   ro  handlerr   s        r0   r  zAstArcAnalyzer.line_for_node:  s     N+	Xswi012D/I//66
 
 74==DD;D~!!$---r?   c                H    |j         r|j         d         j        }n|j        }|S )zSCompute first line number for things that can be decorated (classes and functions).r   )rz   rX   )r.   r   rX   s      r0   _line_decoratedzAstArcAnalyzer._line_decoratedP  s+     	!(+2FF[Fr?   
ast.Assignc                6    |                      |j                  S r9   )r  rv   r.   r   s     r0   _line__AssignzAstArcAnalyzer._line__AssignX  s    !!$*---r?   ast.Dictc                    |j         r1|j         d         |j         d         j        S |j        d         j        S |j        S r8  )keysrX   rN  r  s     r0   _line__DictzAstArcAnalyzer._line__Dict]  s@    9 	y|'y|** {1~,,;r?   ast.Listc                ^    |j         r |                     |j         d                   S |j        S r8  )eltsr  rX   r  s     r0   _line__ListzAstArcAnalyzer._line__Listk  s.    9 	%%dil333;r?   c                z    t           j        j        rdS |j        r |                     |j        d                   S dS Nr@   r   )r   ri   rj   rt   r  r  s     r0   _line__ModulezAstArcAnalyzer._line__Moduleq  s?    >, 	1Y 	%%dil333 1r?   >   ru   PassAssertAssignDeleteGlobalImportNonlocal	AnnAssign	AugAssign
ImportFromr  c                x   |j         j        }t          t          t          t
          j        gt          t                   f                  t          | d| d                    }| ||          }nJt          j        r|| j        vrt          d|           t          |                     |                    h}|S )a  Find the set of arc starts that exit this node.

        Return a set of ArcStarts, exits from this node to the next. Because a
        node represents an entire sub-tree (including its children), the exits
        from a node can be arbitrarily complex::

            if something(1):
                if other(2):
                    doit(3)
                else:
                    doit(5)

        There are three exits from line 1: they start at lines 1, 3 and 5.
        There are two exits from line 2: lines 3 and 5.

        	_handle__Nz*** Unhandled: )rm  r   r   r
   r	   rm   r  r#   r   rn  r   TESTINGOK_TO_DEFAULTRuntimeErrorr  )r.   r   ro  r  
arc_startss        r0   
node_exitszAstArcAnalyzer.node_exits  s    " N+	XswiX678D1i11488
 
  JJ { AD$666&'?'?'?@@@ #4#5#5d#;#;<<=Jr?   rt   r6  
from_startArcStart | Noneprev_startsset[ArcStart] | Nonec                V   ||t                      }n|h}n|J |D ]}|                     |          }|| j        vr/|                     |          }|8|}|                     |          }|D ]#}|                     |j        ||j                   $|                     |          }|S )a  Process the body of a compound statement.

        `body` is the body node to process.

        `from_start` is a single `ArcStart` that starts an arc into this body.
        `prev_starts` is a set of ArcStarts that can all be the start of arcs
        into this body.  Only one of `from_start` and `prev_starts` should be
        given.

        Records arcs within the body by calling `self.add_arc`.

        Returns a set of ArcStarts, the exits from this body.

        )r#   r  r$   find_non_missing_noder  rX   r  r  )r.   rt   r  r  	body_noderX   maybe_body_node
prev_starts           r0   r  zAstArcAnalyzer.process_body  s    ( !!ee)l%%%  
	5 
	5I''	22FT_,,"&"<"<Y"G"G"*+	++I66) J J
Z.
8HIIII//)44KKr?   ast.AST | Nonec                .   |                      |          }|| j        v r|S t          t          t          t
          j        gt          t
          j                 f                  t          | d|j        j	         d                    }| ||          }nd}|S )a  Search `node` looking for a child that has not been optimized away.

        This might return the node you started with, or it will work recursively
        to find a child node in self.statements.

        Returns a node, or None if none of the node remains.

        
_missing__N)
r  r$   r   r
   r	   rm   r  rn  rm  r   )r.   r   rX   
missing_fnret_nodes        r0   r  z$AstArcAnalyzer.find_non_missing_node  s     ##D))T_$$KXswi#')::;<D@t~'>@@$GG
 

 !!z$''HHHr?   ast.Ifc                    |                      t          |j                            }|r|S |j        r'|                      t          |j                            S d S r9   )r  r5  rt   orelse)r.   r   non_missings      r0   _missing__IfzAstArcAnalyzer._missing__If  s]     00$)1D1DEE 	; 	E--ht{.C.CDDDtr?   r5  c                    g }|j         D ].}|                     |          }||                    |           /|sd S t          |          dk    r|d         S t	          |          S r  )rt   r  r   rw  r5  )r.   r   non_missing_childrenchildmaybe_childs        r0   _missing__NodeListz!AstArcAnalyzer._missing__NodeList  s      "Y 	9 	9E44U;;K&$++K888 $ 	4#$$))'**,---r?   	ast.Whilec                N   |                      t          |j                            }|sd S t          j                    }|j        |_        t          j                    |_        |j        |j        _        d|j        _        t          |d          sJ |j        |_        g |_
        |S )Nr<  rt   )r  r5  rt   rm   WhilerX   rF  testrG  r   r  )r.   r   
body_nodes	new_whiles       r0   _missing__WhilezAstArcAnalyzer._missing__While
  s    //0C0CDD
 	4IKK	%,		 * 1	"	z6*****#		r?   r  c                p    |                                  D ] }|                    || j                  r dS !dS )z0Add arcs due to jumps from `exits` being breaks.N)r  r  r  r.   r  blocks      r0   r  z"AstArcAnalyzer.process_break_exits(  M    ((** 	 	E((== 	 	r?   c                p    |                                  D ] }|                    || j                  r dS !dS )z3Add arcs due to jumps from `exits` being continues.N)r  r  r  r  s      r0   r  z%AstArcAnalyzer.process_continue_exits.  sM    ((** 	 	E++E4<@@ 	 	r?   c                p    |                                  D ] }|                    || j                  r dS !dS )z0Add arcs due to jumps from `exits` being raises.N)r  r  r  r  s      r0   r  z"AstArcAnalyzer.process_raise_exits4  r  r?   c                p    |                                  D ] }|                    || j                  r dS !dS )z1Add arcs due to jumps from `exits` being returns.N)r  r  r  r  s      r0   r  z#AstArcAnalyzer.process_return_exits:  sM    ((** 	 	E))%>> 	 	r?   	ast.Breakc                    |                      |          }t          |d          }|                     |h           t                      S )Nz*the break on line {lineno} wasn't executedr  )r  r   r  r#   )r.   r   herebreak_starts       r0   _handle__BreakzAstArcAnalyzer._handle__BreakK  sG    !!$''t+WXXX  +///uur?   c                Z   |j         }|j         }|j        }|rd}|D ]7}|                     |          }|||k    r|                     ||           |}8|J |                     ||           |}|j        s"J d|j        d| j         d|j                      |J t          |          hS )zBAdd arcs for things that can be decorated (classes and functions).NzOops: node.body = z in @)rX   rz   r  r  rt   r   r   )r.   r   	main_linelastdecsdec_node	dec_starts          r0   _handle_decoratedz AstArcAnalyzer._handle_decoratedQ  s    ![	#{" 	WD  ! ! ..x88	#	T(9(9LLy111 ###LLy)))D
 9VVVtyVVVVVVVVVr?   ast.Continuec                    |                      |          }t          |d          }|                     |h           t                      S )Nz-the continue on line {lineno} wasn't executedr  )r  r   r  r#   )r.   r   r  continue_starts       r0   _handle__Continuez AstArcAnalyzer._handle__Continuek  sH    !!$''!$.]^^^##^$4555uur?   ast.Forc                <   |                      |j                  }| j                            t	          |                     t          |d          }|                     |j        |          }|D ]#}|                     |j	        ||j
                   $| j                                        }t          |t                    sJ |j        }t          |d          }|j        r"|                     |j        |          }||z  }n|                    |           |S )NrM   z'the loop on line {lineno} never startedr  r  z)the loop on line {lineno} didn't complete)r  iterrd  r   r  r   r  rt   r  rX   r  rx  ro   r  r  rc   )r.   r   rM   r  r  r#  my_block
else_exitss           r0   _handle__ForzAstArcAnalyzer._handle__Forq  s    ""49--	 6 6 6777e+TUUU
!!$)
!CC 	7 	7CLLUCI6666#''))(I.....$e+VWWW
; 	"**4;:*NNJZEE IIj!!!r?   c                T   |                      |j                  }t          |j                  \  }}t                      }|r|r0t	          |d          }||                     |j        |          z  }|r|s0t	          |d          }||                     |j        |          z  }|S )N-the condition on line {lineno} was never truer  r  .the condition on line {lineno} was always true)r  r  r@  r#   r   r  rt   r  )r.   r   rM   constant_testrS  r  r  s          r0   _handle__IfzAstArcAnalyzer._handle__If  s    ""49--249==s 	I 	I!%/^___JT&&tyZ&HHHE 	KC 	K!%/_```JT&&t{z&JJJEr?   )   
   	ast.Matchc                   |                      |          }|}t                      }|j        D ]e}|                      |j                  }|                     ||d           t          |d          }||                     |j        |          z  }|}f|j        }t          |t          j
                  r'|j        d         }t          |t          j
                  't          |t          j                  r/|j        (|j        }t          |t          j                  r|j        (t          |t          j                  o|j        d u o|j        d u }	|	s$|                    t          |d                     |S )Nz+the pattern on line {lineno} always matchedz*the pattern on line {lineno} never matchedr  r  )r  r#   casespatternr  r   r  rt   ro   rm   MatchOrpatternsMatchAsguardrc   )
r.   r   rM   rJ   r  case
case_startr  r  had_wildcards
             r0   _handle__MatchzAstArcAnalyzer._handle__Match  s   &&t,,EJEEE
 ( (!//==
Z5bccc%F  
 **49*LLL'

 lGWck22 /!*2. Wck22 /Wck22 *w7R!/ Wck22 *w7R 7CK00 'Ot+'J$&    		Z/\]]]   Lr?   c                    |                      |          }|                     |j        t          |                    }|S )Nr  )r  r  rt   r   r  s       r0   _handle__NodeListz AstArcAnalyzer._handle__NodeList  s:    ""4((!!$)!HHr?   	ast.Raisec                    |                      |          }t          |d          }|                     |h           t                      S )Nz*the raise on line {lineno} wasn't executedr  )r  r   r  r#   )r.   r   r  raise_starts       r0   _handle__RaisezAstArcAnalyzer._handle__Raise  sG    !!$''t+WXXX  +///uur?   
ast.Returnc                    |                      |          }t          |d          }|                     |h           t                      S )Nz+the return on line {lineno} wasn't executedr  )r  r   r  r#   )r.   r   r  return_starts       r0   _handle__ReturnzAstArcAnalyzer._handle__Return  sG    !!$'',YZZZ!!<.111uur?   ast.Tryc                z   |j         r!|                     |j         d                   }nd }|j        r!|                     |j        d                   }nd }||J t          ||          }| j                            |           |                     |          }|                     |j        t          |                    }|j        rd |_	        n| j        
                                 t                      }|j         rQ|j         D ]I}|                     |          }d}	t          ||	          }
||                     |j        |
          z  }J|j        r|                     |j        |          }||z  }|j        r;| j        
                                 |}|                     |j        |          }|r|}|S )Nr   r  z3the exception caught by line {lineno} didn't happenr  )r  )handlersr  	finalbodyr.  rd  r   r  rt   r   r/  rx  r#   r  )r.   r   r/  r1  	try_blockrM   r  handler_exitshandler_node
from_causer  
final_fromfinal_exitss                r0   _handle__TryzAstArcAnalyzer._handle__Try  s   = 	! ..t}Q/?@@MM M> 	,,T^A->??KKK (K,C,C,C]K88		***""4((!!$)!HH
 > 	#&*I##  """'*uu= 	] $ ] ] $ 2 2< @ @R
%m:FFF
!2!2<3DQ[!2!\!\\; 	F%%dku%EEE> 		$  """J++DN
+SSK $ $r?   c                *   |                      |j                  x}}t          |j                  \  }}d}|rd}t          j        j        rd}|r |                      |j        d                   }| j                            t          |                     t          |d          }|                     |j        |          }|D ]#}	|                     |	j        ||	j                   $t                      }| j                                        }
t#          |
t                    sJ |                    |
j                   t          |d          }|j        r"|                     |j        |          }||z  }n|s|                    |           |S )	NFTr   r  r  r  r  r  )r  r  r@  r   ri   keep_constant_testrt   rd  r   r  r   r  r  rX   r  r#   rx  ro   rG   r  r  rc   )r.   r   rM   to_topr  r   top_is_body0r  r  r#  r  r  s               r0   _handle__WhilezAstArcAnalyzer._handle__While  s   ++DI6660;;q 	 L>, 	! L 	6''	!55F	 7 7 7888e+Z[[[
!!$)
!CC 	8 	8CLLVSY7777#''))(I.....X)***e+[\\\
; 	&**4;:*NNJZEE ! &		*%%%r?   ast.Withc                    t           j        j        r fd|j        D             }n                     |          g}t           j        j        r9|D ]6} j                            |            j                            |           7 	                    |j
        t          |d                             }t           j        j        rw|d         } j                            |           t          |          h}|rC|D ]>}                     |j        |            j                            |j        |f           ?|}|S )Nc                D    g | ]}                     |j                  S r   )r  context_expr)r<   itemr.   s     r0   rB  z0AstArcAnalyzer._handle__With.<locals>.<listcomp>   s*    SSSd(():;;SSSr?   r  r  )r   ri   exit_with_through_ctxmgritemsr  r   re  rc   rf  r  rt   r   remover  rX   rh  )r.   r   r   rM   r  	with_exitr#  s   `      r0   _handle__WithzAstArcAnalyzer._handle__With  sH   >2 	0SSSS
SSSFF((../F>+ 	0 0 0(,,U333$((////!!$)8L8L!MM>+ 	"2JE$++E222!%)I "  = =CLLU333O''U(;<<<<!r?   )
r   r3   rV  r9  r$   r4   rW  rX  r   r   r   )r   rq  )r   r~  r   r   )r   r  r   r   )r   r  r   r   r   r	  )r   r  )r   r9  r   r   )r   r  r   r   )r   r  r   r   )r   r  r   r   )r   r  r   r   )r   r~  r   r   )r   r9  r   r  )rt   r6  r  r  r  r  r   r  )r   r9  r   r  )r   r  r   r  )r   r5  r   r  )r   r  r   r  )r  r  r   r   )r   r  r   r  )r   r  r   r  )r   r  r   r  )r   r  r   r  )r   r  r   r  )r   r  r   r  )r   r5  r   r  )r   r  r   r  )r   r  r   r  )r   r  r   r  )r   r  r   r  )r   r$  r   r  )4r   r   r   r   r1   r   r   r  r  _code_object__AsyncFunctionDefr  r  r  r  r  r  _line__ClassDefr  _line__FunctionDef_line__AsyncFunctionDefr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  _handle__ClassDefr  r  _handle__AsyncFor_handle__FunctionDef_handle__AsyncFunctionDefr  sysversion_infor	  r  r  r  r  r#  r-  _handle__AsyncWithr   r?   r0   r   r     sy        ($F $F $F $FL* * * *   >( ( ( (    &?"U U U U )-!%] ] ] ] ]$* * * *. . . .,   . . . . &O	 	 	 	 )-        M
! ! ! !L '+,0	) ) ) ) )V   B	 	 	 	. . . .    <            "          0 *      ( %, 1
 
 
 
 7""	 	 	 	@   
      5 5 5 5n   :   0 'r?   r   )r   r9  r   r:  )9r   
__future__r   rm   r   r   r`  rB   r6  r^   r\   collections.abcr   r   dataclassesr   typesr   typingr   r	   r
   r   coverager   coverage.bytecoder   coverage.debugr   coverage.exceptionsr   r   coverage.miscr   r   coverage.phystokensr   coverage.typesr   r   r   rg   r   r  dictrc  tupler3   TArcFragmentsr  r  r%  r.  r  r5  r@  r   r   r?   r0   <module>rH     s   $ # " " " " " " 



         				 				 



   . . . . . . . . ! ! ! ! ! !       5 5 5 5 5 5 5 5 5 5 5 5       * * * * * * & & & & & & 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 / / / / / / ( ( ( ( ( ( ( (^B~ ~ ~ ~ ~ ~ ~ ~BK* K* K* K* K* K* K* K*d $d###       $#B       , T4hsmXc]&B CDDE       6       $    E   2    u   	% 	% 	% 	% 	%sw 	% 	% 	%   0M
' M
' M
' M
' M
' M
' M
' M
' M
' M
'r?   