o
    _c7                     @   s   d Z ddlmZ ddlZddl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 dd	lmZ dd
lmZ eeZG dd deZG dd deZG dd deZdee dee fddZdS )zCoverage module.    )
cmp_to_keyN)AnyDictList)helper)
CDPSession)	PageError)EVALUATION_SCRIPT_URL)
debugError)
merge_dictc                   @   sn   e Zd ZdZdeddfddZddededdfd	d
Zde	fddZ
ddededdfddZde	fddZdS )Coveragea  Coverage class.

    Coverage gathers information about parts of JavaScript and CSS that were
    used by the page.

    An example of using JavaScript and CSS coverage to get percentage of
    initially executed code::

        # Enable both JavaScript and CSS coverage
        await page.coverage.startJSCoverage()
        await page.coverage.startCSSCoverage()

        # Navigate to page
        await page.goto('https://example.com')
        # Disable JS and CSS coverage and get results
        jsCoverage = await page.coverage.stopJSCoverage()
        cssCoverage = await page.coverage.stopCSSCoverage()
        totalBytes = 0
        usedBytes = 0
        coverage = jsCoverage + cssCoverage
        for entry in coverage:
            totalBytes += len(entry['text'])
            for range in entry['ranges']:
                usedBytes += range['end'] - range['start'] - 1

        print('Bytes used: {}%'.format(usedBytes / totalBytes * 100))
    clientreturnNc                 C   s   t || _t|| _d S N)
JSCoverage_jsCoverageCSSCoverage_cssCoverageselfr    r   =/usr/local/lib/python3.10/dist-packages/pyppeteer/coverage.py__init__1   s   
zCoverage.__init__optionskwargsc                    "   t ||}| j|I dH  dS )a  Start JS coverage measurement.

        Available options are:

        * ``resetOnNavigation`` (bool): Whether to reset coverage on every
          navigation. Defaults to ``True``.
        * ``reportAnonymousScript`` (bool): Whether anonymous script generated
          by the page should be reported. Defaults to ``False``.

        .. note::
            Anonymous scripts are ones that don't have an associated url. These
            are scripts that are dynamically created on the page using ``eval``
            of ``new Function``. If ``reportAnonymousScript`` is set to
            ``True``, anonymous scripts will have
            ``__pyppeteer_evaluation_script__`` as their url.
        N)r   r   startr   r   r   r   r   r   startJSCoverage5   s   
zCoverage.startJSCoveragec                       | j  I dH S )ac  Stop JS coverage measurement and get result.

        Return list of coverage reports for all scripts. Each report includes:

        * ``url`` (str): Script url.
        * ``text`` (str): Script content.
        * ``ranges`` (List[Dict]): Script ranges that were executed. Ranges are
          sorted and non-overlapping.

          * ``start`` (int): A start offset in text, inclusive.
          * ``end`` (int): An end offset in text, exclusive.

        .. note::
           JavaScript coverage doesn't include anonymous scripts by default.
           However, scripts with sourceURLs are reported.
        N)r   stopr   r   r   r   stopJSCoverageJ   s   zCoverage.stopJSCoveragec                    r   )zStart CSS coverage measurement.

        Available options are:

        * ``resetOnNavigation`` (bool): Whether to reset coverage on every
          navigation. Defaults to ``True``.
        N)r   r   r   r   r   r   r   startCSSCoverage]   s   
	zCoverage.startCSSCoveragec                    r   )a  Stop CSS coverage measurement and get result.

        Return list of coverage reports for all non-anonymous scripts. Each
        report includes:

        * ``url`` (str): StyleSheet url.
        * ``text`` (str): StyleSheet content.
        * ``ranges`` (List[Dict]): StyleSheet ranges that were executed. Ranges
          are sorted and non-overlapping.

          * ``start`` (int): A start offset in text, inclusive.
          * ``end`` (int): An end offset in text, exclusive.

        .. note::
           CSS coverage doesn't include dynamically injected style tags without
           sourceURLs (but currently includes... to be fixed).
        N)r   r    r!   r   r   r   stopCSSCoveragei   s   zCoverage.stopCSSCoverager   )__name__
__module____qualname____doc__r   r   r   r   r   r   r"   r#   r$   r   r   r   r   r      s    

r   c                   @   l   e Zd ZdZdeddfddZddededdfd	d
ZdeddfddZ	deddfddZ
defddZdS )r   zJavaScript Coverage class.r   r   Nc                 C   s.   || _ d| _t | _t | _t | _d| _d S NF)_client_enableddict_scriptURLs_scriptSourceslist_eventListeners_resetOnNavigationr   r   r   r   r      s   
zJSCoverage.__init__r   r   c                    s   t ||} jrtdd|vrdnt|d  _t|d _d _ j   j	  t
 jd fddt
 jd jg _ jd	I d
H   jddddI d
H   jdI d
H   jdddiI d
H  d
S )Start coverage measurement.zJSCoverage is always enabled.resetOnNavigationTZreportAnonymousScriptzDebugger.scriptParsedc                        j j | S r   )r+   _loopcreate_task_onScriptParseder!   r   r   <lambda>       z"JSCoverage.start.<locals>.<lambda> Runtime.executionContextsClearedzProfiler.enableNzProfiler.startPreciseCoverageF)Z	callCountZdetailedzDebugger.enablezDebugger.setSkipAllPausesskip)r   r,   r   boolr2   get_reportAnonymousScriptr.   clearr/   r   addEventListenerr+   _onExecutionContextsClearedr1   sendr   r   r!   r   r      s4   




	
zJSCoverage.starteventc                 C   "   | j sd S | j  | j  d S r   )r2   r.   rB   r/   r   rF   r   r   r   rD         
z&JSCoverage._onExecutionContextsClearedc              
      s   | dtkr
d S | ds| jsd S | d}| d}|s(| jr(d| }z| jdd|iI d H }|| j|< | d| j|< W d S  ty\ } ztt	| W Y d }~d S d }~ww )NurlscriptIdzdebugger://VMzDebugger.getScriptSourceZscriptSource)
r@   r	   rA   r+   rE   r.   r/   	Exceptionr
   logger)r   rF   rK   rJ   responser:   r   r   r   r8      s(   





zJSCoverage._onScriptParsedc           	         s   | j stdd| _ | jdI dH }| jdI dH  | jdI dH  | jdI dH  t| j g }|dg D ]>}| j|d	}| j	|d	}|du sY|du rZq=g }|d
g D ]}|
|dg  qbt|}||||d q=|S )-Stop coverage measurement and return results.zJSCoverage is not enabled.FzProfiler.takePreciseCoverageNzProfiler.stopPreciseCoveragezProfiler.disablezDebugger.disableresultrK   Z	functionsrangesrJ   rQ   text)r,   r   r+   rE   r   removeEventListenersr1   r@   r.   r/   extendconvertToDisjointRangesappend)	r   rP   coverageentryrJ   rS   ZflattenRangesfuncrQ   r   r   r   r       s*   zJSCoverage.stopr   )r%   r&   r'   r(   r   r   r   r   r   rD   r8   r   r    r   r   r   r   r   ~   s    r   c                   @   r)   )r   zCSS Coverage class.r   r   Nc                 C   s,   || _ d| _t | _t | _g | _d| _d S r*   )r+   r,   r-   _stylesheetURLs_stylesheetSourcesr1   r2   r   r   r   r   r      s   
zCSSCoverage.__init__r   r   c                    s   t ||} jrtdd|vrdnt|d  _d _ j   j  t	 j
d fddt	 j
d jg _ j
dI d	H   j
d
I d	H   j
dI d	H  d	S )r3   zCSSCoverage is already enabled.r4   TzCSS.styleSheetAddedc                    r5   r   )r+   r6   r7   _onStyleSheetr9   r!   r   r   r;      r<   z#CSSCoverage.start.<locals>.<lambda>r=   z
DOM.enableNz
CSS.enablezCSS.startRuleUsageTracking)r   r,   r   r?   r2   r[   rB   r\   r   rC   r+   rD   r1   rE   r   r   r!   r   r      s,   




	zCSSCoverage.startrF   c                 C   rG   r   )r2   r[   rB   r\   rH   r   r   r   rD      rI   z'CSSCoverage._onExecutionContextsClearedc              
      s   | di }| dsd S z#| jdd|d iI d H }|d | j|d < |d | j|d < W d S  tyI } ztt| W Y d }~d S d }~ww )NheaderZ	sourceURLzCSS.getStyleSheetTextstyleSheetIdrS   )r@   r+   rE   r[   r\   rL   r
   rM   )r   rF   r^   rN   r:   r   r   r   r]     s   


zCSSCoverage._onStyleSheetc           	         s   | j stdd| _ | jdI dH }| jdI dH  | jdI dH  t| j i }|d D ]&}||d }|sEg }|||d < ||d	 |d
 |d rSdndd q2g }| j	D ]}| j	|}| j
|}t||g }||||d q^|S )rO   zCSSCoverage is not enabled.FzCSS.stopRuleUsageTrackingNzCSS.disablezDOM.disableZ	ruleUsager_   startOffset	endOffsetused   r   )r`   ra   countrR   )r,   r   r+   rE   r   rT   r1   r@   rW   r[   r\   rV   )	r   rP   ZstyleSheetIdToCoveragerY   rQ   rX   r_   rJ   rS   r   r   r   r      s8   


zCSSCoverage.stopr   )r%   r&   r'   r(   r   r   r   r   r   rD   r]   r   r    r   r   r   r   r      s    r   nestedRangesr   c           	      C   s  g }| D ]}| |d d|d | |d d|d qdtdtdtfd	d
}|jt|d g }g }d}|D ]M}|rm||d k rm|t|d  dkrm|rR|d nd}|rc|d |krc|d |d< n
| ||d d |d }|d dkr| |d d  q8|  q8dd |D S )zConvert ranges.r`   r   )offsettyperangera   rc   abr   c                 S   s   | d |d kr| d |d  S | d |d kr |d | d  S | d d | d d  }|d d |d d  }| d dkrB|| S || S )Nrf   rg   rh   ra   r`   r   r   )ri   rj   ZaLengthZbLengthr   r   r   
_sort_funcA  s   z+convertToDisjointRanges.<locals>._sort_func)keyrf   Nend)r   rn   rg   rh   rd   c                 S   s$   g | ]}|d  |d  dkr|qS )rn   r   rc   r   ).0rh   r   r   r   
<listcomp>e  s   $ z+convertToDisjointRanges.<locals>.<listcomp>)rW   r   intsortr   lenpop)	re   ZpointsZnested_rangerk   ZhitCountStackresultsZ
lastOffsetpointZ
lastResultr   r   r   rV   6  s8   


rV   )r(   	functoolsr   loggingtypingr   r   r   Z	pyppeteerr   Zpyppeteer.connectionr   Zpyppeteer.errorsr   Zpyppeteer.execution_contextr	   Zpyppeteer.helperr
   Zpyppeteer.utilr   	getLoggerr%   rM   objectr   r   r   rV   r   r   r   r   <module>   s"   
j]
[