o
    i@(                     @   s  U d Z ddlZddlZddlZddlmZ ddlZddlm	Z	 ddl
mZ ddlmZ ddlmZ eeZejdks<J ejZejd	 Zejd
 Zejd Zejd ZeededgZeeddZerjejjjnejjj Z!i Z"ej#eej$e	e%ej#e&ej$e%ej'ej$e%  f f f f e(d< dede	de%de%de)eef f
ddZ*dede&dej+ejj, fddZ-dd Z.dede	de%de%de)eef f
ddZ/	d#dede%de0de)ee1e&e)e%e)e%d f f f f fd!d"Z2dS )$aL  
Coverage instrumentation for Python 3.12+ using sys.monitoring API.

This module supports two modes:
1. Line-level coverage: Tracks which specific lines are executed (LINE events)
2. File-level coverage: Tracks which files are executed (PY_START events)

The mode is controlled by the _DD_COVERAGE_FILE_LEVEL environment variable.
    N)CodeType)HookType)
get_logger)CoverageLines)asbool)      IMPORT_NAMEIMPORT_FROMRESUMERETURN_CONST_DD_COVERAGE_FILE_LEVELfalse_CODE_HOOKScodehookpathpackagereturnc                 C   sj   t jt jj}|dur|dkrtd| | t fS |du r.tr#dnd}td| t  t	| |||S )a  
    Instrument code for coverage tracking using Python 3.12's monitoring API.

    This function supports two modes based on _DD_COVERAGE_FILE_LEVEL:
    - Line-level (default): Uses LINE events for detailed line-by-line coverage
    - File-level: Uses PY_START events for faster file-level coverage

    Args:
        code: The code object to instrument
        hook: The hook function to call
        path: The file path
        package: The package name

    Returns:
        Tuple of (code object, CoverageLines with instrumentable lines)

    Note: Both modes use an optimized approach where callbacks return DISABLE
    after recording, meaning each line/function is only reported once per coverage context.
    Ndatadogz=Coverage tool '%s' already registered, not gathering coveragez
file-levelz
line-levelzRegistering %s coverage tool)
sys
monitoringget_toolCOVERAGE_IDlogdebugr   _USE_FILE_LEVEL_COVERAGE_register_monitoring_instrument_with_monitoring)r   r   r   r   coverage_toolmode r!   d/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/coverage/instrumentation_py3_12.pyinstrument_all_lines/   s   
r#   linec                 C   s   t | }|du rtjjS |\}}}tr/|d|df | D ]\}}||||f qtjjS ||d}||||f tjjS )zg
    Callback for LINE/PY_START events.
    Returns sys.monitoring.DISABLE to improve performance.
    Nr   )r   getr   r   DISABLEr   items)r   r$   	hook_datar   r   import_namesline_numimport_namer!   r!   r"   _event_handlerP   s   

r,   c                   C   s*   t jt jjd t jt jjtt dS )z
    Register the coverage tool with the monitoring system.

    This sets up the appropriate callback based on the coverage mode.
    r   N)r   r   use_tool_idr   register_callbackEVENTr,   r!   r!   r!   r"   r   n   s   r   c           
      C   s   t jt jj| t t }t| ||d\}}dd | jD D ]}t||||\}}	|	|	 q|||ft
| < trDt }|d | |fS |s_| jdkr_| jtkr_|d |dur_|df|d< | |fS )zq
    Instrument code using either LINE events for detailed line-by-line coverage or PY_START for file-level.
    )track_linesc                 s   s    | ]
}t |tr|V  qd S )N)
isinstancer   ).0_r!   r!   r"   	<genexpr>   s    z._instrument_with_monitoring.<locals>.<genexpr>r   <module>N )r   r   set_local_eventsr   r/   r   _extract_lines_and_imports	co_constsr#   updater   r   addco_nameco_codeEMPTY_MODULE_BYTES)
r   r   r   r   r0   linesr)   nested_coder3   nested_linesr!   r!   r"   r   x   s    

r   Tr0   .c                 C   s  t  }i }d}d}d}d}d}	tt| }
d}g }tt| j}z	 t|\}}t|\}}|tkr4q"||
v r\|
| }|dur\|r\|	| | j
dkr\t|dkr\|dur\|df||< |tu rf|| q"|}|}tjg ||ddd	}|  |tkr|dur| j| }| j| }|dkrd
|d
d| d  n|}	||v r|	tt|| d |g f||< n|	|ff||< |tkr|dur| d
| j|  }||v r|	tt|| d |g f||< n|	|ff||< q# ty   Y ||fS w )a,  
    Extract line numbers and import information from bytecode.

    This parses the bytecode to:
    1. Collect all executable line numbers (if track_lines=True)
    2. Track IMPORT_NAME and IMPORT_FROM opcodes for dependency tracking

    Args:
        code: The code object to analyze
        package: The package name for resolving relative imports
        track_lines: Whether to collect line numbers (True for LINE mode, False for PY_START mode)

    Returns:
        Tuple of (CoverageLines with executable lines, dict mapping lines to imports)
    r   NTr5      r6   bigF)signed.)r   dictdisfindlinestartsiter	enumerater>   nextr   r<   r=   lenEXTENDED_ARGappendint
from_bytesclearr	   r:   co_namesjoinsplittuplelistr
   StopIteration)r   r   r0   r@   r)   current_argprevious_arg_previous_previous_argcurrent_import_namecurrent_import_package
linestartsr$   ext	code_iteroffsetopcoder3   argimport_depthimport_from_namer!   r!   r"   r9      sh   



(

8r9   )T)3__doc__rH   osr   typesr   typingt#ddtrace.internal.bytecode_injectionr   ddtrace.internal.loggerr   /ddtrace.internal.test_visibility.coverage_linesr   ddtrace.internal.utils.formatsr   __name__r   version_inforN   opmapr	   r
   r   r   bytesr?   getenvr   r   eventsPY_STARTLINEr/   r   DictTuplestrrP   Optional__annotations__rV   r#   Literalr&   r,   r   r   boolrG   r9   r!   r!   r!   r"   <module>   sZ    




B& !


'"