
    /~h                    .   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jj                        Z6 G d# d$      Z7y)%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ddZddZddZddZddZej                  dd       ZddZddZddZy) PythonParserzParse code to find executable lines, excluded lines, etc.

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

    Nc                   |s	|sJ d       |xs d| _         ||| _        nddlm} 	  || j                         | _        || _        d| _        t               | _	        t               | _
        t               | _        t               | _        t               | _        d| _        i | _        d| _        d| _        i | _        y# t        $ r!}t        d| j                    d|       |d}~ww xY w)	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)filenametextcoverage.pythonr   OSErrorr   exclude	_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         X/var/www/peopleoo.sandbox-dev.co.uk/venv/lib/python3.12/site-packages/coverage/parser.py__init__zPythonParser.__init__(   s     xM!MM ,H!DI9Y-dmm<	  *.
 ), '*e -0E +.% -0E ! 35 ,0<@#@BQ  Y!6t}}oSNOUXXYs   B< <	C&C!!C&c           	         t               }d}d}t        j                  | j                  t        j                        D ]  }|j                         \  }}| j                  j                  d||      z   }| j                  j                  d||      z   }	|j                   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  V   K   | ]   }j                   j                  ||       " y wNr'   get).0ir+   s     r-   	<genexpr>z.PythonParser.lines_matching.<locals>.<genexpr>v   s"     b4??..q!4bs   &)      )	r    refinditerr   	MULTILINEspancountupdaterange)
r+   regexmatches
last_startlast_start_linematchstartend
start_lineend_lines
   `         r-   lines_matchingzPythonParser.lines_matchingf   s     !$
[[		F 	)EJE3(499??4U+SSJ&z3)OOHNNbeJQRNT\_`T`>abbJ(O	)     c           
     	   | j                   r:| j                  | j                         | _        t        | j                        | _        d}d}d}d}d}d}| j
                  J t        | j
                        }|D ]  \  }}	\  }
}\  }}}| j                  rBt        t        j                  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(  rj|	d
k(  rQ|dk(  rL| j                  j#                  t%        ||d	z               }|su|rs| j                  j'                  |       |}d}nS|	dv r|d	z  }nI|	dv rE|d	z  }n?|t        j(                  k(  r,|r(||k7  r#t%        ||d	z         D ]  }|| j*                  |<    d}|	j-                         s^|t        j.                  k7  ssd}|ry|
}|r||k  rd}|s| j                  j'                  |        |sJt1        | j
                  | j2                        }| j4                  j7                  |j9                                t:        j<                  j>                  r.| j*                  r"tA        | j4                        | j*                  d	<   | jC                  | j                        | _        | jD                  J tG        jH                  | jD                        D ]  }tK        |tF        jL                  tF        jN                  tF        jP                  tF        jR                  f      r|jT                  r|jT                  d   }tK        |tF        jV                        rtK        |jX                  tF        jZ                        rntK        |jX                  jX                  t\              rJ| j^                  j7                  t%        |j`                  tc        td        |jf                        d	z                tK        |tF        jL                  tF        jN                  tF        jP                  f      sNtA        d |jh                  D        |j`                        }| j                  j#                  t%        ||j`                  d	z               s| j                  j7                  t%        |tc        td        |jf                        d	z                 y)zwParse the source to find the interesting facts about its lines.

        A handful of attributes are updated.

        r   FTNz>10 z>520r9   :z([{z)]})r   c              3  4   K   | ]  }|j                     y wr3   lineno)r6   ds     r-   r8   z*PythonParser._raw_parse.<locals>.<genexpr>   s     !Hq!((!Hs   )default)5r   rK   r$   r    r"   r   r   r&   printtokenizetok_namer5   r   tokenINDENTDEDENTOPintersectionrA   addNEWLINEr'   stripCOMMENT
ByteParserr   r#   r@   _find_statementsr   
PYBEHAVIORmodule_firstline_1minfirst_linesr   astwalk
isinstanceClassDefFunctionDefAsyncFunctionDefModulebodyExprvalueConstantstrr%   rS   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                      r-   
_raw_parsezPythonParser._raw_parse{   s    << $ 3 3DLL AD 1 12DM 	
yy$$$ +AG -	3=GULWa,7A%%))'7;w015%  %,,&!ELL(!EHH$C<GqL225Wq[3QR # % ))'2)/$(	e^qLGe^qLGEMM)'Z"7 #:wqy9 8-7*8
{{}H,<,<!<!!(J V~%=$)	 ))'2[-	3` $TYYGK&&{'C'C'EF
 >>,,!$T%8%8!9DOOA((7 ~~)))HHT^^, 	\D$s@T@TVYV`V` ab99 IIaLE"5#((3&u{{CLLA&u{{'8'8#>++22!%,,S%:J:J0Ka0OP
 $s@T@T UV !HD4G4G!HRVR]R]^
==--eJa.PQMM((z4T__;UXY;Y)Z[%	\rL   i  )maxsizec                    |dk  r!| j                   j                  | |        }|S | j                   j                  ||      }|S )zAReturn the first line number of the statement including `lineno`.r   r4   )r+   rS   s     r-   rz   zPythonParser.first_line   sL     A:oo))6'F7;;F  __((8FrL   c                J    |D ch c]  }| j                  |       c}S c c}w )zMap the line numbers in `linenos` to the correct first line of the
        statement.

        Returns a set of the first lines.

        )rz   )r+   linenosr   s      r-   rg   zPythonParser.first_lines   s!     -44q"444s    c                $    | j                  |      S )z)Implement `FileReporter.translate_lines`.)rg   )r+   liness     r-   translate_lineszPythonParser.translate_lines   s    &&rL   c                    | j                  |      D ch c]'  \  }}| j                  |      | j                  |      f) c}}S c c}}w )z(Implement `FileReporter.translate_arcs`.)fix_with_jumpsrz   )r+   arcsabs       r-   translate_arcszPythonParser.translate_arcs   s=    GKGZGZ[_G`aVa#T__Q%78aaas   ,Ac                   	 t        j                  | j                        | _        | j	                          | j                  | j                  z  }| j                   |z
  }| j#                  |      |z
  | _        y# 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)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.

        rS   r9   r   zCouldn't parse 'z' as Python source: z	 at line N)rh   parser   r   r   rW   
TokenErrorIndentationErrorSyntaxErrorhasattrrS   argsr   r   r"   r%   r#   rg   r!   )r+   r,   rS   ignorestartss        r-   parse_sourcezPythonParser.parse_source  s    	 YYtyy1DNOO !4!44$$v-**62V; ##%5{C 	sH%!Q"4==/1EF88A;/6(34 	s   4A8 8C5AC00C5c                n    | j                   | 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    r-   r   zPythonParser.arcs  s4     >>!~~)))~~rL   c                :   | j                   J t        | j                  | j                   | j                  | j                        }|j                          |j                  }t        j                  j                  r2|j                         | _        | j                  r| j                  |      }t               | _        |D ]J  \  }}| j                  |      }| j                  |      }||k7  s.| j                  j!                  ||f       L |j"                  | _        y)zkRun the AstArcAnalyzer and save its results.

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

        N)r   AstArcAnalyzerr   r#   r'   analyzer   r   rd   exit_through_withwith_jump_fixersr*   r   r    r(   rz   r^   missing_arc_fragmentsr)   )r+   aaar   l1l2fl1fl2s          r-   r   zPythonParser._analyze_ast&  s     ~~)))T]]DNND<O<OQUQ`Q`axx>>++%(%9%9%;D"%%**40 	/FB//"%C//"%Ccz""C:.		/ '*&?&?#rL   c                   t               }t               }|D ]  }|| j                  v s|d   }|j                  |       | j                  |   \  }}|| j                  v rC|j                  |       | j                  |   \  }}|j                  |       || j                  v rC|j                  ||d   f       |j                  |        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   r9   )r    r*   r^   )r+   r   	to_removeto_addarcend0
start_nextend_nexts           r-   r   zPythonParser.fix_with_jumps>  s    0 E	 
	*Cd,,,1vc"'+'='=c'B$
H D$:$::MM*-+/+A+A*+M(JMM(+ !D$:$:: 

D(1+./j)
	* D	F"i/rL   c                    t        j                  t              }| j                         D ]L  \  }}|dkD  sJ d|d| j                          || j
                  v r1|| j
                  v r@||xx   dz  cc<   N |S )zYGet a count of exits from that each line.

        Excluded lines are excluded.

        r   zl1=z  should be greater than zero in r9   )collectionsdefaultdictrt   r   r   r"   )r+   exit_countsr   r   s       r-   r   zPythonParser.exit_countsf  s     +6*A*A#*Fiik 	!FB6RcbU"B4==/RR6T]]"T]]"Oq O	! rL   c                B    |
|dk  rd}nd}|j                  |      }|S )z=Apply some defaulting and formatting to an arc's description.r   zjump to the function exitzjump to line {lineno}rR   )format)r+   
action_msgrH   s      r-   _finish_action_msgzPythonParser._finish_action_msgz  s2    Qw8
4
&&c&2
rL   c                X   | j                   | j                          | j                   J | j                   j                  ||fdg      }g }|D ]J  \  }}| j                  ||      }d| d| }||d|j	                  |       z  }|j                  |       L dj                  |      S )z5Provide an English sentence describing a missing arc.NNzline z didn't z	 because rR   z or )r)   r   r5   r   r   appendjoin)r+   rG   rH   fragment_pairsmsgsmissing_cause_msgr   msgs           r-   missing_arc_descriptionz$PythonParser.missing_arc_description  s    &&...:::4488%~V-; 	)z00SAJ%5C ,#4#;#;5#;#I"JKKKK	 {{4  rL   c                    | j                   | j                          | j                   J | j                   j                  ||fdg      }| j                  |d   d   |      }|S )z2Provide an English description of an arc's effect.r   r   r9   )r)   r   r5   r   )r+   rG   rH   r   r   s        r-   arc_descriptionzPythonParser.arc_description  sl    &&...:::4488%~V,,^A->q-A3G
rL   )NNN)r   
str | Noner   r   r   r   returnNone)rB   rs   r   set[TLineNo]r   r   )rS   r   r   r   )r   Iterable[TLineNo]r   r   )r   r   r   r   )r   zIterable[TArc]r   	set[TArc])r   r   )r   zdict[TLineNo, int])r   r   rH   r   r   rs   )rG   r   rH   r   r   rs   )__name__
__module____qualname____doc__r.   rK   r   	functools	lru_cacherz   rg   r   r   r   r   r   r   r   r   r   r    rL   r-   r   r   !   s      #"	<C<C <C 	<C
 
<C|*k\Z Y& '5'b<0
@0&P  &!&rL   r   c                  D    e Zd ZdZ	 	 d	 	 	 	 	 	 	 ddZd	dZd
dZd
dZy)rb   z3Parse bytecode to understand the structure of code.Nc                V    || _         ||| _        y |J t        ||dd      | _        y )NexecT)dont_inherit)r   codecompile)r+   r   r   r   s       r-   r.   zByteParser.__init__  s8     	DI'''  hTJDIrL   c                @      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  j   K   | ]*  }|j                   d k7  rt        j                  |       , yw)__annotate__)r   N)co_namerb   r   )r6   cr+   s     r-   r8   z+ByteParser.child_parsers.<locals>.<genexpr>  s3      
yyN* tyyq))
s   03)r   r   r   s   `r-   child_parserszByteParser.child_parsers  s    
!$)),
 	
rL   c              #    K   t        | j                  d      r+| j                  j                         D ]  \  }}}|s
|  y| j                  j                  ddd   }| j                  j                  ddd   }d}| j                  j                  }d}t        ||      D ]&  \  }}	|r||k7  r| |}||z  }|	dk\  r|	dz  }	||	z  }( ||k7  r| yyw)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   Nr:   r9         )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
             r-   _line_numberszByteParser._line_numbers  s      499j)"ii002 
1dJ
 #ii11!$Q$7O"ii11!$Q$7O Myy//HH(+O_(M &$	9=0&(0	)H$&II%& =( )s   :CBCc              #  j   K   | j                         D ]  }|j                         E d{     y7 w)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     r-   rc   zByteParser._find_statements  s5      $$& 	*B'')))	*)s   '313r   )r   rs   r   zCodeType | Noner   r   r   r   )r   zIterable[ByteParser])r   r   )r   r   r   r   r.   r   r   rc   r   rL   r-   rb   rb     sL    =
 !%#	KK K 	K
 
K
">	*rL   rb   T)frozenorderc                  *    e Zd ZU dZded<   dZded<   y)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   rS    rs   causeN)r   r   r   r   __annotations__r   r   rL   r-   r   r     s    8 OE3OrL   r   c                  0    e Zd ZdZ	 	 d	 	 	 	 	 	 	 	 	 ddZy)	TAddArcFnz&The type for AstArcAnalyzer.add_arc().Nc                     y)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+   rG   rH   r   r   s        r-   __call__zTAddArcFn.__call__  s    rL   r   
rG   r   rH   r   r   r   r   r   r   r   )r   r   r   r   r   r   rL   r-   r   r     sB    0
 )-!%  &	
  
rL   r   c                  0    e Zd ZdZddZddZddZddZy)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.
    c                     y)zProcess break exits.Fr   r+   exitsadd_arcs      r-   process_break_exitszBlock.process_break_exits8      rL   c                     y)zProcess continue exits.Fr   r  s      r-   process_continue_exitszBlock.process_continue_exits<  r	  rL   c                     y)zProcess raise exits.Fr   r  s      r-   process_raise_exitszBlock.process_raise_exits@  r	  rL   c                     y)zProcess return exits.Fr   r  s      r-   process_return_exitszBlock.process_return_exitsD  r	  rL   Nr  set[ArcStart]r  r   r   bool)r   r   r   r   r  r  r  r  r   rL   r-   r  r  .  s    rL   r  c                  (    e Zd ZdZddZddZddZy)	LoopBlockz@A block on the block stack representing a `for` or `while` loop.c                0    || _         t               | _        y r3   )rG   r    break_exits)r+   rG   s     r-   r.   zLoopBlock.__init__K  s    
*-%rL   c                :    | j                   j                  |       yNT)r  r@   r  s      r-   r  zLoopBlock.process_break_exitsQ  s    &rL   c                b    |D ]*  } ||j                   | j                  |j                         , yr  )rS   rG   r   r+   r  r  xits       r-   r  z LoopBlock.process_continue_exitsU  s,     	7CCJJ

CII6	7rL   N)rG   r   r   r   r  )r   r   r   r   r.   r  r  r   rL   r-   r  r  I  s    J0rL   r  c                  (    e Zd ZdZddZddZddZy)FunctionBlockz>A block on the block stack representing a function definition.c                     || _         || _        y r3   rG   name)r+   rG   r   s      r-   r.   zFunctionBlock.__init__]  s    
	rL   c                    |D ]9  } ||j                   | j                   |j                  d| j                         ; y)Nzexcept from function TrS   rG   r   r   r  s       r-   r  z!FunctionBlock.process_raise_exitsc  A     	C

TZZK'		}5	
 rL   c                    |D ]9  } ||j                   | j                   |j                  d| j                         ; y)Nzreturn from function Tr"  r  s       r-   r  z"FunctionBlock.process_return_exitsk  r#  rL   N)rG   r   r   rs   r   r   r  )r   r   r   r   r.   r  r  r   rL   r-   r  r  [  s    HrL   r  c                       e Zd ZdZddZddZy)TryBlockz6A block on the block stack representing a `try` block.c                     || _         || _        y r3   )handler_startfinal_start)r+   r(  r)  s      r-   r.   zTryBlock.__init__v  s    *&rL   c                z    | j                   /|D ]*  } ||j                  | j                   |j                         , yr  )r(  rS   r   r  s       r-   r  zTryBlock.process_raise_exits|  s<    ) C

D$6$6		BCrL   N)r(  TLineNo | Noner)  r+  r   r   r  )r   r   r   r   r.   r  r   rL   r-   r&  r&  t  s    @'rL   r&  c                      e Zd ZdZddZy)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.

    c                :    || _         |d   j                  | _        y Nr   )ro   rS   )r+   ro   s     r-   r.   zNodeList.__init__  s    	1gnnrL   N)ro   Sequence[ast.AST]r   r   )r   r   r   r   r.   r   rL   r-   r-  r-    s    %rL   r-  c                     e Zd ZdZ	 	 	 	 	 	 	 	 	 	 d*dZd+dZd,dZd-dZd.dZeZ	d/dZ
	 	 d0	 	 	 	 	 	 	 	 	 d1d	Zd2d
Zd3dZd4dZd5dZeZd6dZeZeZd7dZd8dZh dZd9dZ	 	 d0	 	 	 	 	 	 	 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!dAdZ"dBdZ#e#Z$dCdZ%dDd Z&e&Z'e#Z(e#Z)dEd!Z*e+jX                  d"k\  rdFd#Z-dGd$Z.dHd%Z/dId&Z0dJd'Z1dKd(Z2dLd)Z3e3Z4y)Mr   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.

    c                   || _         || _        |D ch c]  }|j                  ||       c}| _        || _        t        t        t        j                  dd                  }|r[t        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                  | _        y c c}w )	NCOVERAGE_AST_DUMP0zStatements: zMultiline map: T   )include_attributesrw   COVERAGE_TRACK_ARCS)r   	root_noder5   r!   	multiliner  rt   osgetenvrV   rh   dumpr    r   r   r   listr   block_stackcurrent_with_startsall_with_startswith_entries
with_exitsdebug)r+   r   r8  r!   r9  r   dump_asts          r-   r.   zAstArcAnalyzer.__init__  s	    !"8BC19==A.C" BII&93?@AL 123ODNN#345#((4>>d1MN"u	4?4K4KD4Q"(* 25 -0U'*u%(U #bii(=sCDE
7 Ds   Ec                    t        j                  | j                        D ]3  }|j                  j                  }t        | d|z   d      }|, ||       5 y)zFExamine the AST tree from `self.root_node` to determine possible arcs._code_object__N)rh   ri   r8  	__class__r   getattr)r+   r   	node_namecode_object_handlers       r-   r   zAstArcAnalyzer.analyze  sP    HHT^^, 	*D//I")$0@90Ld"S".#D)		*rL   c                   i }| j                   D ch c]#  }|d   | j                  v r|| j                  vr|% }}| j                  D ]  }|D ch c]  }|d   |k(  s|d    }}|s!t        |      dk(  sJ d| d|       |j	                         }| j
                  D ch c]  }|d   |k(  s|d    }}|D ]  }||f||ff|||f<     |S c c}w c c}w c c}w )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.

        r   r9   zExpected one arc, got z with start = )r   r@  rA  lenpoprB  )	r+   fixersr   
with_nextsrG   nextsnxtendsrH   s	            r-   r   zAstArcAnalyzer.with_jump_fixers  s"     yy
1v---#T=N=N2N 

 

 )) 	BE'1ESVu_SVEEEu:?T&<UG?%$TT?))+C&*ooIsQ5CFIDI B).sCj'AU|$B	B 
 F
 Js   (CCC!C/Cc                    | j                  |      }|j                  rL| j                  |j                        }|D ]+  }| j                  |j                  | |j
                  d       - y | j                  ||        y )Nzexit the module)line_for_nodero   process_bodyr  rS   r   r+   r   rG   r  r  s        r-   _code_object__Modulez#AstArcAnalyzer._code_object__Module  sm    ""4(99%%dii0E OSZZ%<MNO LL'rL   c                   | j                  |      }| j                  j                  t        ||j                               | j                  |j                        }| j                  |       | j                  j                          y )Nr  )	rT  r>  r   r  r   rU  ro   r  rM  r+   r   rG   r  s       r-   _code_object__FunctionDefz(AstArcAnalyzer._code_object__FunctionDef  se    ""4(E		 JK!!$)),!!%(rL   c                    | j                  |      }| j                  |j                        }|D ]8  }| j                  |j                  | |j
                  d|j                         : y )Nzexit class )rT  rU  ro   r  rS   r   r   rV  s        r-   _code_object__ClassDefz%AstArcAnalyzer._code_object__ClassDef  s^    ""4(!!$)), 	UCLLeVSYY+dii]8ST	UrL   Nc           
     R   | j                   r,t        d| d| d|d|       t        t               d       | j                  j	                  ||f       || j
                  v r| j                  j	                  ||f       ||#| j                  ||f   j                  ||f       yy)z@Add an arc, including message fragments to use if it is missing.zAdding possible arc: (z, z): z

)rH   N)	rC  rV   r   r   r^   r?  rA  r   r   r   s        r-   r  zAstArcAnalyzer.add_arc  s     ::*5'C5<M;PPRS]R`ab+-V,		ucl#D,,,!!5#,/(J,B&&s|4;;=NPZ<[\ -CrL   c                ,    t        | j                        S )z.Yield the blocks in nearest-to-farthest order.)reversedr>  r   s    r-   nearest_blockszAstArcAnalyzer.nearest_blocks  s    (())rL   c                   |j                   j                  }t        t        t        t
        j                  gt        f      t        | d|z   d            }|	 ||      }n|j                  }| 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)rG  r   r   r
   r	   rh   ASTr   rH  rS   r9  r5   )r+   r   rI  handlerr   s        r-   rT  zAstArcAnalyzer.line_for_node"  sw     NN++	Xswwi012D)i/6
 4=D;;D~~!!$--rL   c                l    |j                   r|j                   d   j                  }|S |j                  }|S )zSCompute first line number for things that can be decorated (classes and functions).r   )rv   rS   )r+   r   rS   s      r-   _line_decoratedzAstArcAnalyzer._line_decorated8  s8    ((+22F  [[FrL   c                8    | j                  |j                        S r3   )rT  rq   r+   r   s     r-   _line__AssignzAstArcAnalyzer._line__Assign@  s    !!$**--rL   c                    |j                   rA|j                   d   |j                   d   j                  S |j                  d   j                  S |j                  S r/  )keysrS   valuesrh  s     r-   _line__DictzAstArcAnalyzer._line__DictE  sK    99yy|'yy|*** {{1~,,,;;rL   c                n    |j                   r| j                  |j                   d         S |j                  S r/  )eltsrT  rS   rh  s     r-   _line__ListzAstArcAnalyzer._line__ListS  s,    99%%diil33;;rL   c                    t         j                  j                  ry|j                  r| j	                  |j                  d         S yNr9   r   )r   rd   re   ro   rT  rh  s     r-   _line__ModulezAstArcAnalyzer._line__ModuleY  s7    >>,,YY%%diil33 rL   >   rp   PassAssertAssignDeleteGlobalImportNonlocal	AnnAssign	AugAssign
ImportFromc                `   |j                   j                  }t        t        t        t
        j                  gt        t           f      t        | d|z   d            }|
 ||      }|S t        j                  r|| j                  vrt        d|       t        | j                  |            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: )rG  r   r   r
   r	   rh   rc  r    r   rH  r   TESTINGOK_TO_DEFAULTRuntimeErrorrT  )r+   r   rI  rd  
arc_startss        r-   
node_exitszAstArcAnalyzer.node_exitsh  s    " NN++	XswwiX678D+	148
  J  {{D$6$66&'?@@ #4#5#5d#;<=JrL   c                L   ||t               }n|h}n|J |D ]  }| j                  |      }|| j                  vr'| j                  |      }|6|}| j                  |      }|D ])  }| j	                  |j
                  ||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    rT  r!   find_non_missing_noder  rS   r   r  )r+   ro   
from_startprev_starts	body_noderS   maybe_body_node
prev_starts           r-   rU  zAstArcAnalyzer.process_body  s    ( !!e)l%%%  
	5I''	2FT__,"&"<"<Y"G"*+	++I6) J
Z..
8H8HIJ//)4K
	5 rL   c                (   | j                  |      }|| j                  v r|S t        t        t        t
        j                  gt        t
        j                     f      t        | d|j                  j                  z   d            }|
 ||      }|S 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)
rT  r!   r   r
   r	   rh   rc  rH  rG  r   )r+   r   rS   
missing_fnret_nodes        r-   r  z$AstArcAnalyzer.find_non_missing_node  s     ##D)T__$KXswwi#'')::;<D,)@)@@$G

 !!$'H  HrL   c                    | j                  t        |j                              }|r|S |j                  r$| j                  t        |j                              S y r3   )r  r-  ro   orelse)r+   r   non_missings      r-   _missing__IfzAstArcAnalyzer._missing__If  sJ     00$))1DE;;--ht{{.CDDrL   c                    g }|j                   D ]'  }| j                  |      }||j                  |       ) |sy t        |      dk(  r|d   S t	        |      S rr  )ro   r  r   rL  r-  )r+   r   non_missing_childrenchildmaybe_childs        r-   _missing__NodeListz!AstArcAnalyzer._missing__NodeList  sn      "YY 	9E44U;K&$++K8	9 $#$)'**,--rL   c                t   | j                  t        |j                              }|sy t        j                         }|j
                  |_        t        j                         |_        |j
                  |j                  _        d|j                  _        t        |d      sJ |j                  |_        g |_
        |S )NTruero   )r  r-  ro   rh   WhilerS   Nametestidr   r  )r+   r   
body_nodes	new_whiles       r-   _missing__WhilezAstArcAnalyzer._missing__While  s    //0CD
IIK	%,,		 * 1 1	"	z6***#		rL   c                    |j                   j                  }|dv ryt        |t        j                        r|j
                  dv ryy)z Is this a compile-time constant?)rr   NameConstantNumr  )r  Falser   	__debug__r  N)rG  r   rj   rh   r  r  )r+   r   rI  s      r-   is_constant_exprzAstArcAnalyzer.is_constant_expr  s>    NN++	;;chh'ww@@rL   c                j    | j                         D ]   }|j                  || j                        s  y y)z0Add arcs due to jumps from `exits` being breaks.N)r`  r  r  r+   r  blocks      r-   r  z"AstArcAnalyzer.process_break_exits  1    ((* 	E((=	rL   c                j    | j                         D ]   }|j                  || j                        s  y y)z3Add arcs due to jumps from `exits` being continues.N)r`  r  r  r  s      r-   r  z%AstArcAnalyzer.process_continue_exits   s1    ((* 	E++E4<<@	rL   c                j    | j                         D ]   }|j                  || j                        s  y y)z0Add arcs due to jumps from `exits` being raises.N)r`  r  r  r  s      r-   r  z"AstArcAnalyzer.process_raise_exits&  r  rL   c                j    | j                         D ]   }|j                  || j                        s  y y)z1Add arcs due to jumps from `exits` being returns.N)r`  r  r  r  s      r-   r  z#AstArcAnalyzer.process_return_exits,  s1    ((* 	E))%>	rL   c                v    | j                  |      }t        |d      }| j                  |h       t               S )Nz*the break on line {lineno} wasn't executedr   )rT  r   r  r    )r+   r   herebreak_starts       r-   _handle__BreakzAstArcAnalyzer._handle__Break=  s6    !!$'t+WX  +/urL   c                |   |j                   }|j                   }|j                  }|rd}|D ].  }| j                  |      }|||k7  r| j                  ||       |}0 |J | 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 @)rS   rv   rT  r  ro   r   r   )r+   r   	main_linelastdecsdec_node	dec_starts          r-   _handle_decoratedz AstArcAnalyzer._handle_decoratedC  s    ![[	#{{""D  ! ..x8	#	T(9LLy1 	!
 ###LLy)D
 99V 3tyynDqVV9rL   c                v    | j                  |      }t        |d      }| j                  |h       t               S )Nz-the continue on line {lineno} wasn't executedr  )rT  r   r  r    )r+   r   r  continue_starts       r-   _handle__Continuez AstArcAnalyzer._handle__Continue]  s7    !!$'!$.]^##^$45urL   c                B   | j                  |j                        }| j                  j                  t	        |             t        |d      }| j                  |j                  |      }|D ])  }| j                  |j                  ||j                         + | j                  j                         }t        |t              sJ |j                  }t        |d      }|j                  r$| j                  |j                  |      }||z  }|S |j                  |       |S )NrG   z'the loop on line {lineno} never startedr  r  z)the loop on line {lineno} didn't complete)rT  iterr>  r   r  r   rU  ro   r  rS   r   rM  rj   r  r  r^   )r+   r   rG   r  r  r  my_block
else_exitss           r-   _handle__ForzAstArcAnalyzer._handle__Forc  s    ""499-	 67e+TU
!!$))
!C 	7CLLUCII6	7##'')(I...$$e+VW
;;**4;;:*NJZE  IIj!rL   c                    | j                  |j                        }t        |d      }| j                  |j                  |      }t        |d      }|| j                  |j
                  |      z  }|S )N-the condition on line {lineno} was never truer  r  .the condition on line {lineno} was always true)rT  r  r   rU  ro   r  )r+   r   rG   r  r  s        r-   _handle__IfzAstArcAnalyzer._handle__If|  sl    ""499-e+Z[
!!$))
!Ce+[\
""4;;:"FFrL   )   
   c                   | j                  |      }|}t               }|j                  D ]_  }| j                  |j                        }| j	                  ||d       t        |d      }|| j                  |j                  |      z  }|}a j                  }t        |t        j                        r*|j                  d   }t        |t        j                        r*t        |t        j                        r?|j                  3|j                  }t        |t        j                        r|j                  3t        |t        j                        xr |j                  d u xr |j                  d u }	|	s|j                  t        d             |S )Nz+the pattern on line {lineno} always matchedz*the pattern on line {lineno} never matchedr  r  )rT  r    casespatternr  r   rU  ro   rj   rh   MatchOrpatternsMatchAsguardr^   )
r+   r   rG   rD   r  case
case_startr  r  had_wildcards
             r-   _handle__MatchzAstArcAnalyzer._handle__Match  sW   &&t,EJEE

 (!//=
Z5bc%F
 **499*LL'
( llGWckk2!**2. Wckk2Wckk2w7R!// Wckk2w7R 7CKK0 'OOt+'JJ$&   		Z/\] LrL   c                t    | j                  |      }| j                  |j                  t        |            }|S )Nr  )rT  rU  ro   r   rY  s       r-   _handle__NodeListz AstArcAnalyzer._handle__NodeList  s4    ""4(!!$))!HrL   c                v    | j                  |      }t        |d      }| j                  |h       t               S )Nz*the raise on line {lineno} wasn't executedr  )rT  r   r  r    )r+   r   r  raise_starts       r-   _handle__RaisezAstArcAnalyzer._handle__Raise  s6    !!$'t+WX  +/urL   c                v    | j                  |      }t        |d      }| j                  |h       t               S )Nz+the return on line {lineno} wasn't executedr  )rT  r   r  r    )r+   r   r  return_starts       r-   _handle__ReturnzAstArcAnalyzer._handle__Return  s6    !!$',YZ!!<.1urL   c                   |j                   r| j                  |j                   d         }nd }|j                  r| j                  |j                  d         }nd }||J t        ||      }| j                  j                  |       | j                  |      }| j                  |j                  t        |            }|j                  rd |_	        n| j                  j                          t               }|j                   rQ|j                   D ]B  }| j                  |      }d}	t        ||	      }
|| j                  |j                  |
      z  }D |j                  r| j                  |j                  |      }||z  }|j                  r=| j                  j                          |}| j                  |j                  |      }|r|}|S )Nr   r  z3the exception caught by line {lineno} didn't happenr  )r  )handlersrT  	finalbodyr&  r>  r   rU  ro   r   r(  rM  r    r  )r+   r   r(  r)  	try_blockrG   r  handler_exitshandler_node
from_causer  
final_fromfinal_exitss                r-   _handle__TryzAstArcAnalyzer._handle__Try  s   == ..t}}Q/?@M M>>,,T^^A->?KK (K,CCC]K8		*""4(!!$))!H
 >>&*I#  "'*u== $ ] $ 2 2< @R
%m:F
!2!2<3D3DQ[!2!\\	] ;;%%dkku%EE>>  "J++DNN
+SK $rL   c                6   | j                  |j                        x}}| j                  |j                        }d}|rd}t        j                  j
                  rd}|r| j                  |j                  d         }| j                  j                  t        |             t        |d      }| j                  |j                  |      }|D ])  }| j                  |j                  ||j                         + t               }| j                  j!                         }	t#        |	t              sJ |j%                  |	j&                         t        |d      }|j(                  r$| j                  |j(                  |      }
||
z  }|S |s|j+                  |       |S )	NFTr   r  r  r  r  r  )rT  r  r  r   rd   keep_constant_testro   r>  r   r  r   rU  r  rS   r   r    rM  rj   r@   r  r  r^   )r+   r   rG   to_topconstant_testtop_is_body0r  r  r  r  r  s              r-   _handle__WhilezAstArcAnalyzer._handle__While  s`   ++DII66--dii8L>>,, L''		!5F	 78e+Z[
!!$))
!C 	8CLLVSYY7	8##'')(I...X))*e+[\
;;**4;;:*NJZE
  !		*%rL   c                   t         j                  j                  r3|j                  D cg c]  }| j	                  |j
                         }}n| j	                  |      g}t         j                  j                  r=|D ]8  }| j                  j                  |       | j                  j                  |       : | j                  |j                  t        |d               }t         j                  j                  rz|d   }| j                  j                  |       t        |      h}|rL|D ]E  }| j                  |j                  |       | j                   j                  |j                  |f       G |}|S c c}w )Nr  r  )r   rd   exit_with_through_ctxmgritemsrT  context_exprr   r?  r^   r@  rU  ro   r   remover  rS   rB  )r+   r   itemr   rG   r  	with_exitr  s           r-   _handle__WithzAstArcAnalyzer._handle__With  s9   >>22HL

Sd(():):;SFS((./F>>++ 0((,,U3$$((/0 !!$))8L!M>>++2JE$$++E2!%)I  =CLLU3OO''U(;<= ") Ts   "E6)
r   rs   r8  ast.ASTr!   r   r9  zdict[TLineNo, TLineNo]r   r   r   )r   zdict[TArc, tuple[TArc, TArc]])r   
ast.Moduler   r   )r   ast.FunctionDefr   r   )r   zast.ClassDefr   r   r   r  )r   zIterable[Block])r   r  r   r   )r   r  r   r   )r   z
ast.Assignr   r   )r   zast.Dictr   r   )r   zast.Listr   r   )r   r  r   r   )r   r  r   r  )ro   r0  r  zArcStart | Noner  zset[ArcStart] | Noner   r  )r   r  r   ast.AST | None)r   ast.Ifr   r  )r   r-  r   r  )r   	ast.Whiler   r  )r   r  r   r   )r  r  r   r   )r   z	ast.Breakr   r  )r   r  r   r  )r   zast.Continuer   r  )r   zast.Forr   r  )r   r  r   r  )r   z	ast.Matchr   r  )r   r-  r   r  )r   z	ast.Raiser   r  )r   z
ast.Returnr   r  )r   zast.Tryr   r  )r   r  r   r  )r   zast.Withr   r  )5r   r   r   r   r.   r   r   rW  rZ  _code_object__AsyncFunctionDefr\  r  r`  rT  rf  ri  _line__ClassDefrm  _line__FunctionDef_line__AsyncFunctionDefrp  rs  r  r  rU  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   rL   r-   r   r     s   ($F$F $F !	$F
 *$F 
$FL*>( &?"U )-!%]] ] &	]
 ] 
]$*.,. &O	 )-M
!L '+,0	)) $) *	)
 
)VB	. 2" 0 *( %, 1 7"	@
5n:0 'rL   r   )8r   
__future__r   rh   r   r   r:  r;   r  rY   rW   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   rb   r   r   dictr=  tuplers   TArcFragmentsr  r  r  r&  rc  r-  r   r   rL   r-   <module>r     s   $ " 
   	 	 
   . !  5 5  * & 3 3 / (B~ ~BK* K*d $d#  $B , T4hsmXc]&B CDDE 6 $E 2u 	%sww 	%S
' S
'rL   