
    Yf$                        d Z ddlmZ ddlZddlmZmZmZmZ ddl	m
Z
mZmZ ddlmZmZ edeedf   f   Zeeef   ZddZdd	Zdd
ZddZ	 d	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 d	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZy)z
Processors are functions that take a Frame object, and mutate the tree to perform some task.

They can mutate the tree in-place, but also can change the root frame, they should always be
called like::

    frame = processor(frame, options=...)
    )annotationsN)AnyCallableDictUnion)SELF_TIME_FRAME_IDENTIFIERFrame
FrameGroup)combine_framesdelete_frame_from_tree.c                    | y| j                   D ]8  }t        ||       |j                  sd|j                  v s,t        |d       : | S )zR
    Removes ``<frozen importlib._bootstrap`` frames that clutter the output.
    Noptionsz<frozen importlib._bootstrapchildrenreplace_with)r   remove_importlib	file_pathr   framer   childs      W/var/www/highfloat_scraper/venv/lib/python3.12/site-packages/pyinstrument/processors.pyr   r      sO     } C0??=P"5zB	C L    c                |    | y| j                   D ])  }t        ||       |j                  st        |d       + | S )z
    Removes frames that have set a local `__tracebackhide__` (e.g.
    `__tracebackhide__ = True`), to hide them from the output.
    Nr   r   r   )r   remove_tracebackhidehas_tracebackhider   r   s      r   r   r   )   sE    
 } CUG4"""5zBC Lr   c                   | yi }| j                   D ]<  }|j                  |v r||j                     }t        ||       .|||j                  <   > | j                   D ]  }t        ||        | j                  j                  d d       | S )aH  
    Converts a timeline into a time-aggregate summary.

    Adds together calls along the same call stack, so that repeated calls appear as the same
    frame. Removes time-linearity - frames are sorted according to total time spent.

    Useful for outputs that display a summary of execution (e.g. text and html outputs)
    N)intor   c                    | j                   S N)time)cs    r   <lambda>z*aggregate_repeated_calls.<locals>.<lambda>Z   s
    qvv r   T)keyreverse)r   
identifierr   aggregate_repeated_calls	_childrensort)r   r   children_by_identifierr   aggregate_frames        r   r'   r'   ;   s     }/1  =554U5E5EFO 57 8="5#3#34=  9 89
 
OO-t<Lr   c                <   | y|j                  d      |j                  d      dfdd	fd| j                  D ]U  }|j                  s: |      r2t        fd|j                  D              rt	        |      } ||       t        ||       W | S )
aO  
    Groups frames that should be hidden into :class:`FrameGroup` objects,
    according to ``hide_regex`` and ``show_regex`` in the options dict, as
    applied to the file path of the source code of the frame. If both match,
    'show' has precedence.
    Options:

    ``hide_regex``
      regular expression, which if matches the file path, hides the frame in a
      frame group.

    ``show_regex``
      regular expression, which if matches the file path, ensures the frame is
      not hidden

    Single frames are not grouped, there must be at least two frames in a
    group.
    N
hide_regex
show_regexc                    | j                   xs d}d uxr t        j                  |      }d uxr t        j                  |      }|ry|ry| j                   S )N FT)r   rematchis_application_code)r   frame_file_pathshould_showshould_hider-   r.   s       r   should_be_hiddenz8group_library_frames_processor.<locals>.should_be_hiddenx   sb    ///R!-X288J3X!-X288J3X ,,,,r   c                n    |j                  |        | j                  D ]  } |      s ||        y r    )	add_framer   )r   groupr   add_frames_to_groupr7   s      r   r;   z;group_library_frames_processor.<locals>.add_frames_to_group   s4    ^^ 	2E&#E51	2r   c              3  .   K   | ]  } |        y wr     ).0ccr7   s     r   	<genexpr>z1group_library_frames_processor.<locals>.<genexpr>   s     +ZR,<R,@+Zs   r   r   r	   )r   r	   r:   r
   )getr   r:   anyr
   group_library_frames_processor)r   r   r   r:   r;   r-   r7   r.   s       @@@@r   rD   rD   _   s    & }$[[6J$[[6J-2  ?{{U#+Z5>>+Z(Zu%Eu-&ug>? Lr   c                   | yd}| j                   D ]L  }|j                  t        k(  r5|r0|xj                  |j                  z  c_        |j	                          H|}Kd}N |r| j                   D ]  }t        ||d        | S )z2
    Combines consecutive 'self time' frames.
    NT)r   	recursive)r   r&   r   r!   remove_from_parentmerge_consecutive_self_time)r   r   rF   previous_self_time_framer   s        r   rH   rH      s     }# 
,99'(--;-((* ,1('+$
, ^^ 	PE'w$O	P Lr   c                    | yt        | j                        dk(  r:| j                  d   j                  t        k(  rt	        | j                  d   d       | j                  D ]  }t        ||        | S )z
    When a frame has only one child, and that is a self-time frame, remove
    that node and move the time to parent, since it's unnecessary - it
    clutters the output and offers no additional information.
    N   r   nothingr   r   )lenr   r&   r   r   "remove_unnecessary_self_time_nodesr   s      r   rN   rN      sm     }
5>>aENN1$5$@$@D^$^u~~a0yI C*5'BC Lr   c                    | y|| j                   }|dk  rd}|j                  dd      }| j                  D ]$  }|j                   |z  }||k  st        |d       & | j                  D ]  }t	        |||        | S )	z
    Remove nodes that represent less than e.g. 1% of the output. Options:

    ``filter_threshold``
      sets the minimum duration of a frame to be included in the output.
      Default: 0.01.
    Nr   ggE6filter_thresholdg{Gz?rL   r   )r   
total_time)r!   rB   r   r   remove_irrelevant_nodes)r   r   rQ   rP   r   proportion_of_totals         r   rR   rR      s     }ZZ
 ?J{{#5t< B#jj:5!11"5yA	B  Ow:NO Lr   c                    | ydd}dd}dd}| } ||      s| S |j                   d   } ||      s| S |j                   d   } ||      s| S  ||      r|j                   d   } ||      r|j                          |S )z
    The first few frames when using the command line are the __main__ of
    pyinstrument, the eval, and the 'runpy' module. I want to remove that from
    the output.
    Nc                    | j                   d uxr: t        j                  d| j                         xr t        | j                        dkD  S )Nz.*pyinstrument[/\\]__main__.pyr   )r   r1   r2   rM   r   r   s    r   is_initial_pyinstrument_framezQremove_first_pyinstrument_frames_processor.<locals>.is_initial_pyinstrument_frame   sA    OO4' (:EOOL(ENN#a'	
r   c                    | j                   dkD  xr8 | j                  d uxr( d| j                  v xr t        | j                        dkD  S )N皙?z<string>r   )proportion_of_parentr   rM   r   rV   s    r   is_exec_framezAremove_first_pyinstrument_frames_processor.<locals>.is_exec_frame   sO    &&, (t+(eoo-( ENN#a'		
r   c                    | j                   dkD  xrZ | j                  d uxrJ t        j                  d| j                        xs d| j                  v xr t	        | j
                        dkD  S )NrY   z
.*runpy.pyz<frozen runpy>r   )rZ   r   r1   r2   rM   r   rV   s    r   is_runpy_framezBremove_first_pyinstrument_frames_processor.<locals>.is_runpy_frame  sg    &&, (t+(-9`=MQVQ`Q`=`( ENN#a'		
r   r   rA   )r   rG   )r   r   rW   r[   r]   results         r   *remove_first_pyinstrument_frames_processorr_      s     }


 F(0__QF __QF&!
 
 # 
  Mr   )r   Frame | Noner   ProcessorOptionsreturnr`   )T)r   r`   r   ra   rF   boolrb   r`   r    )r   r`   r   ra   rQ   zfloat | Nonerb   r`   )__doc__
__future__r   r1   typingr   r   r   r   pyinstrument.framer   r	   r
   pyinstrument.frame_opsr   r   ProcessorTypestrra   r   r   r'   rD   rH   rN   rR   r_   r=   r   r   <module>rk      s    # 	 - - L L I
 eE4K001S>  $!H6t GK"2?C<"2* PT"2@LF;;"2;;r   