
    hgoD                        U d dl mZmZ d dlZd dlmZ d dlmZm	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 ej        d          Z ej        d          ZdZdadad	 Z ej        d
          aej        ed<    ej        d          aej        ed<   d Zd Zed             Z ed             Z!d Z"d Z# G d de$          Z% G d de          Z& G d de$          Z'e G d d                      Z( G d d          Z) G d de)          Z* G d  d!e)ej+        j,                  Z-e	d"ej.        e-         fd#            Z/d"e-fd$Z0dS )%    )ConnectionClosedconnect_websocket_urlN)defaultdict)contextmanagerasynccontextmanager)	dataclasstrio_cdpTi   c                 b    | a t          j        d                    t                               ad S )Nz&selenium.webdriver.common.devtools.v{})version	importlibimport_moduleformatdevtools)vers    [/var/www/fb-scrape/myenv/lib/python3.11/site-packages/selenium/webdriver/common/bidi/cdp.pyimport_devtoolsr   3   s-     G&'O'V'VW^'_'_``HHH    connection_context_connection_contextsession_context_session_contextc                 v    	 t                                           S # t          $ r t          |  d          w xY w)z
    Look up the current connection. If there is no current connection, raise a
    ``RuntimeError`` with a helpful message.
    z*() must be called in a connection context.)r   getLookupErrorRuntimeErrorfn_names    r   get_connection_contextr   >   sP    
S"&&((( S S SgQQQRRRS    8c                 v    	 t                                           S # t          $ r t          |  d          w xY w)z{
    Look up the current session. If there is no current session, raise a
    ``RuntimeError`` with a helpful message.
    z'() must be called in a session context.)r   r   r   r   r   s    r   get_session_contextr"   I   sP    
P##%%% P P PgNNNOOOPr    c              #      K   t                               |           }	 dV  t                               |           dS # t                               |           w xY w)zd This context manager installs ``connection`` as the session context for the current
    Trio task. N)r   setreset)
connectiontokens     r   r   r   T   s^        ##J//E)!!%(((((!!%((((	   > Ac              #      K   t                               |           }	 dV  t                               |           dS # t                               |           w xY w)za This context manager installs ``session`` as the session context for the current
    Trio task. N)r   r$   r%   )sessionr'   s     r   r   r   _   s^         ))E&u%%%%%u%%%%r(   c                 2    t          j        d|           adS )z
    Install ``connection`` in the root context so that it will become the default
    connection for all tasks. This is generally not recommended, except it may be
    necessary in certain use cases such as running inside Jupyter notebook.
    r   defaultN)contextvars
ContextVarr   )r&   s    r   set_global_connectionr0   j   s+     &01F9CE E Er   c                 2    t          j        d|           adS )z
    Install ``session`` in the root context so that it will become the default
    session for all tasks. This is generally not recommended, except it may be
    necessary in certain use cases such as running inside Jupyter notebook.
    r   r,   N)r.   r/   r   )r*   s    r   set_global_sessionr2   u   s!     #-.@'RRRr   c                       e Zd ZdZd Zd ZdS )BrowserErrorzi This exception is raised when the browser's response to a command
    indicates that an error occurred. c                 n    |d         | _         |d         | _        |                    d          | _        d S )Ncodemessagedata)r6   r7   r   detail)selfobjs     r   __init__zBrowserError.__init__   s-    K	9~ggfoor   c                 N    d                     | j        | j        | j                  S )Nz#BrowserError<code={} message={}> {})r   r6   r7   r9   r:   s    r   __str__zBrowserError.__str__   s*    4;;DI<@L$+W W 	Wr   N)__name__
__module____qualname____doc__r<   r?    r   r   r4   r4      sA        * *& & &
W W W W Wr   r4   c                       e Zd ZdZd Zd ZdS )CdpConnectionClosedzC Raised when a public method is called on a closed CDP connection. c                     || _         dS )zn
        Constructor.
        :param reason:
        :type reason: wsproto.frame_protocol.CloseReason
        N)reason)r:   rH   s     r   r<   zCdpConnectionClosed.__init__   s     r   c                 L    d                     | j        j        | j                  S )z Return representation. z{}<{}>)r   	__class__r@   rH   r>   s    r   __repr__zCdpConnectionClosed.__repr__   s    t~6DDDr   N)r@   rA   rB   rC   r<   rK   rD   r   r   rF   rF      s=        MM  E E E E Er   rF   c                       e Zd ZdZdS )InternalErrorzh This exception is only raised when there is faulty logic in TrioCDP or
    the integration with PyCDP. N)r@   rA   rB   rC   rD   r   r   rM   rM      s        $ $ $ $r   rM   c                   ,    e Zd ZU dZdZej        ed<   dS )CmEventProxyz A proxy object returned by :meth:`CdpBase.wait_for()``. After the
    context manager executes, this proxy object will have a value set that
    contains the returned event. Nvalue)r@   rA   rB   rC   rP   typingAny__annotations__rD   r   r   rO   rO      s0         % % E6:r   rO   c                       e Zd Zd Zdej        eeej        f         defdZ	dddZ
eddej        e         dej        ed	f         fd
            Zd Zd Zd Zd	S )CdpBasec                     || _         || _        || _        t          t                    | _        t          j                    | _        t                      | _
        t                      | _        d S )N)ws
session_id	target_idr   r$   channels	itertoolscountid_iterdictinflight_cmdinflight_result)r:   rW   rX   rY   s       r   r<   zCdpBase.__init__   sS    $"#C(( (( FF#vvr   cmdreturnc                 
  K   t          | j                  }t          j                    }||f| j        |<   t          |          }||d<   | j        r
| j        |d<   t          j        |          }	 | j        	                    |           d{V  n'# t          $ r}t          |j                  dd}~ww xY w|                                 d{V  | j                            |          }t!          |t"                    r||S )z
        Execute a command on the server and wait for the result.
        :param cmd: any CDP command
        :returns: a CDP result
        id	sessionIdN)nextr]   trioEventr_   rX   jsondumpsrW   send_messageWsConnectionClosedrF   rH   waitr`   pop
isinstance	Exception)r:   ra   cmd_id	cmd_eventrequestrequest_strwccresponses           r   executezCdpBase.execute   s!      dl##JLL	$'N&!s))? 	3#'?GK j))	<'&&{3333333333! 	< 	< 	<%cj11t;	<nn'++F33h	** 	Ns   0 B 
B5B00B5
   )buffer_sizec                ~    t          j        |          \  }}|D ]"}| j        |                             |           #|S )zZ Return an async iterator that iterates over events matching the
        indicated types. )rg   open_memory_channelrZ   add)r:   ry   event_typessenderreceiver
event_types         r   listenzCdpBase.listen   sK      3K@@% 	2 	2JM*%))&1111r   r   Nc                8  K   t          j        |          \  }}| j        |                             |           t	                      }|W V  |4 d{V  |                                 d{V }ddd          d{V  n# 1 d{V swxY w Y   ||_        dS )z
        Wait for an event of the given type and return it.
        This is an async context manager, so you should open it inside an async
        with block. The block will not exit until the indicated event is
        received.
        N)rg   r{   rZ   r|   rO   receiverP   )r:   r   ry   r~   r   proxyevents          r   wait_forzCdpBase.wait_for   s/       3K@@j!%%f--- 	- 	- 	- 	- 	- 	- 	- 	-"**,,,,,,,,E	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	-s   B
BBc                 f    d|v r|                      |           dS |                     |           dS )z]
        Handle incoming WebSocket data.
        :param dict data: a JSON dictionary
        rd   N)_handle_cmd_response_handle_event)r:   r8   s     r   _handle_datazCdpBase._handle_data   sA    
 4<<%%d+++++t$$$$$r   c                    |d         }	 | j                             |          \  }}n># t          $ r1 t                              d                    |                     Y dS w xY wd|v rt          |d                   | j        |<   nS	 |                    |d                   }t          d          # t          $ r}|j        }Y d}~nd}~ww xY w|| j        |<   |                                 dS )z
        Handle a response to a command. This will set an event flag that will
        return control to the task that called the command.
        :param dict data: response as a JSON dictionary
        rd   z7Got a message with a command ID that does not exist: {}Nerrorresultz<The command's generator function did not exit when expected!)r_   rn   KeyErrorloggerwarningr   r4   r`   sendrM   StopIterationrP   r$   )r:   r8   rq   ra   r   rv   exitreturn_s           r   r   zCdpBase._handle_cmd_response   s"    d	*..v66JC 	 	 	NN ,,2F4LL: : :FF	 d?? ,8W+F+FD ((%88DN33# %B C C C  % % %*%+2D (		s'   ( 7A#"A#	*B3 3
C=C		Cc                    t           j                            |          }t                              d|           t                      }| j        t          |                   D ]n}	 |                    |           # t          j
        $ r t                              d||           Y Ft          j        $ r |                    |           Y kw xY w|r$| j        t          |          xx         |z  cc<   dS dS )zW
        Handle an event.
        :param dict data: event as a JSON dictionary
        zReceived event: %sz0Unable to send event "%r" due to full channel %sN)r   utilparse_json_eventr   debugr$   rZ   typesend_nowaitrg   
WouldBlockr   BrokenResourceErrorr|   )r:   r8   r   	to_remover~   s        r   r   zCdpBase._handle_event  s    ..t44)5111EE	mDKK0 	& 	&F&""5))))? , , ,O"F, , , , ,+ & & &f%%%%%& 	4M$u++&&&)3&&&&&	4 	4s   &A<<+C)#CC)rx   )r@   rA   rB   r<   rQ   	Generatorr^   r
   rR   rw   r   r   TypeAsyncGeneratorrO   r   r   r   r   rD   r   r   rU   rU      s        & & &!1$6:2E!F 1    0 02       Q !,"45    % % %  :4 4 4 4 4r   rU   c                   N     e Zd ZdZ fdZed             Zed             Z xZS )
CdpSessionz
    Contains the state for a CDP session.
    Generally you should not instantiate this object yourself; you should call
    :meth:`CdpConnection.open_session`.
    c                     t                                          |||           d| _        t          j                    | _        d| _        t          j                    | _        dS )z
        Constructor.
        :param trio_websocket.WebSocketConnection ws:
        :param devtools.target.SessionID session_id:
        :param devtools.target.TargetID target_id:
        r   N)superr<   _dom_enable_countrg   Lock_dom_enable_lock_page_enable_count_page_enable_lock)r:   rW   rX   rY   rJ   s       r   r<   zCdpSession.__init__)  sS     	Z333!" $	"#!%r   c                "  K   | j         4 d{V  | xj        dz  c_        | j        dk    r7|                     t          j                                                   d{V  ddd          d{V  n# 1 d{V swxY w Y   dW V  | j         4 d{V  | xj        dz  c_        | j        dk    r7|                     t          j                                                   d{V  ddd          d{V  dS # 1 d{V swxY w Y   dS )z
        A context manager that executes ``dom.enable()`` when it enters and then
        calls ``dom.disable()``.
        This keeps track of concurrent callers and only disables DOM events when
        all callers have exited.
        N   r   )r   r   rw   r   domenabledisabler>   s    r   
dom_enablezCdpSession.dom_enable7  s<      ( 	: 	: 	: 	: 	: 	: 	: 	:""a'""%**ll8<#6#6#8#8999999999	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	:
 	( 	; 	; 	; 	; 	; 	; 	; 	;""a'""%**ll8<#7#7#9#9:::::::::	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	;%   AA55
A?A?AC>>
DDc                "  K   | j         4 d{V  | xj        dz  c_        | j        dk    r7|                     t          j                                                   d{V  ddd          d{V  n# 1 d{V swxY w Y   dW V  | j         4 d{V  | xj        dz  c_        | j        dk    r7|                     t          j                                                   d{V  ddd          d{V  dS # 1 d{V swxY w Y   dS )z
        A context manager that executes ``page.enable()`` when it enters and
        then calls ``page.disable()`` when it exits.
        This keeps track of concurrent callers and only disables page events
        when all callers have exited.
        Nr   r   )r   r   rw   r   pager   r   r>   s    r   page_enablezCdpSession.page_enableL  s<      ) 	; 	; 	; 	; 	; 	; 	; 	;##q(##&!++ll8=#7#7#9#9:::::::::	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	;
 	) 	< 	< 	< 	< 	< 	< 	< 	<##q(##&!++ll8=#8#8#:#:;;;;;;;;;	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	<r   )	r@   rA   rB   rC   r<   r   r   r   __classcell__rJ   s   @r   r   r   "  sz         - - - - - ; ; ;( < < < < < < <r   r   c                   h     e Zd ZdZ fdZd Zedej        e	         fd            Z
d	dZd Z xZS )
CdpConnectiona)  
    Contains the connection state for a Chrome DevTools Protocol server.
    CDP can multiplex multiple "sessions" over a single connection. This class
    corresponds to the "root" session, i.e. the implicitly created session that
    has no session ID. This class is responsible for reading incoming WebSocket
    messages and forwarding them to the corresponding session, as well as
    handling messages targeted at the root session itself.
    You should generally call the :func:`open_cdp()` instead of
    instantiating this class directly.
    c                 v    t                                          |dd           t                      | _        dS )zS
        Constructor
        :param trio_websocket.WebSocketConnection ws:
        N)rX   rY   )r   r<   r^   sessions)r:   rW   rJ   s     r   r<   zCdpConnection.__init__n  s3    
 	===r   c                 H   K   | j                                          d{V  dS )a|  
        Close the underlying WebSocket connection.
        This will cause the reader task to gracefully exit when it tries to read
        the next message from the WebSocket. All of the public APIs
        (``execute()``, ``listen()``, etc.) will raise
        ``CdpConnectionClosed`` after the CDP connection is closed.
        It is safe to call this multiple times.
        N)rW   acloser>   s    r   r   zCdpConnection.aclosev  s2       gnnr   rb   c                   K   |                      |           d{V }t          |          5  |W V  ddd           dS # 1 swxY w Y   dS )a  
        This context manager opens a session and enables the "simple" style of calling
        CDP APIs.
        For example, inside a session context, you can call ``await dom.get_document()``
        and it will execute on the current session automatically.
        N)connect_sessionr   )r:   rY   r*   s      r   open_sessionzCdpConnection.open_session  s       ,,Y77777777W%% 	 	MMMM	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   A  AAr   c                    K   |                      t          j                            |d                     d{V }t	          | j        ||          }|| j        |<   |S )zV
        Returns a new :class:`CdpSession` connected to the specified target.
        TN)rw   r   targetattach_to_targetr   rW   r   )r:   rY   rX   r*   s       r   r   zCdpConnection.connect_session  sv      
  <<(H(Ht) )        
TWj)<<$+j!r   c                 D  K   	 	 | j                                          d{V }n# t          $ r Y dS w xY w	 t          j        |          }n&# t          j        $ r t          dd|d          w xY wt                              d|           d|v rzt          j
                            |d                   }	 | j        |         }n0# t          $ r# t          d                    |                    w xY w|                    |           n|                     |           )	z
        Runs in the background and handles incoming messages: dispatching
        responses to commands and events to listeners.
        TNiDzClient received invalid JSON)r6   r7   r8   zReceived message %rre   z3Browser sent a message for an invalid session: {!r})rW   get_messagerl   ri   loadsJSONDecodeErrorr4   r   r   r   r   	SessionIDr   r   r   r   )r:   r7   r8   rX   r*   s        r   _reader_taskzCdpConnection._reader_task  s|     	( $ 3 3 5 5555555%   
 z'**'   ""=#$ $    LL.555d""%_66tK7HII
K"mJ7GG K K K& (77=vj7I7IK K KK $$T****!!$'''7	(s#   % 
33A #A/7C -C2)rb   r   )r@   rA   rB   rC   r<   r   r   rQ   AsyncIteratorr   r   r   r   r   r   s   @r   r   r   b  s        	 	    	 	 	 
 ,
 
 
 
	 	 	 	!( !( !( !( !( !( !(r   r   rb   c                  K   t          j                    4 d{V }t          ||            d{V }	 t          |          5  |W V  ddd           n# 1 swxY w Y   |                                 d{V  n# |                                 d{V  w xY w	 ddd          d{V  dS # 1 d{V swxY w Y   dS )a  
    This async context manager opens a connection to the browser specified by
    ``url`` before entering the block, then closes the connection when the block
    exits.
    The context manager also sets the connection as the default connection for the
    current task, so that commands like ``await target.get_targets()`` will run on this
    connection automatically. If you want to use multiple connections concurrently, it
    is recommended to open each on in a separate task.
    N)rg   open_nurseryconnect_cdpr   r   )urlnurseryconns      r   open_cdpr     s       ""              g #........	 #D))  



               ++--$++--                                                           sL   B.A;A	A;A	A;A	A; B.;BB..
B8;B8c                    K   t          | |t                     d{V }t          |          }|                     |j                   |S )a  
    Connect to the browser specified by ``url`` and spawn a background task in the
    specified nursery.
    The ``open_cdp()`` context manager is preferred in most situations. You should only
    use this function if you need to specify a custom nursery.
    This connection is not automatically closed! You can either use the connection
    object as a context manager (``async with conn:``) or else call ``await
    conn.aclose()`` on it when you are done with it.
    If ``set_context`` is True, then the returned connection will be installed as
    the default connection for the current task. This argument is for unusual use cases,
    such as running inside of a notebook.
    )max_message_sizeN)r   MAX_WS_MESSAGE_SIZEr   
start_soonr   )r   r   rW   cdp_conns       r   r   r     ss       %Wc6IK K K 
K 
K 
K 
K 
K 
KBR  Hx,---Or   )1trio_websocketr   rl   r   rg   collectionsr   
contextlibr   r   dataclassesr   r.   r   r[   ri   loggingrQ   	getLoggerr   TypeVarr
   r   r   r   r   r/   r   rS   r   r   r"   r   r   r0   r2   rp   r4   rF   rM   rO   rU   r   abcAsyncResourcer   r   r   r   rD   r   r   <module>r      sr  6          # # # # # # < < < < < < < < ! ! ! ! ! !                
	:	&	&FN3 
a a a /Ek.DEY.Z.Z [+ Z Z Z+A;+ABS+T+T +( T T TS S SP P P ) ) ) & & &E E ES S SW W W W W9 W W WE E E E E, E E E $ $ $ $ $I $ $ $
        u4 u4 u4 u4 u4 u4 u4 u4p=< =< =< =< =< =< =< =<@X( X( X( X( X(GTX3 X( X( X(v  6/>        (}      r   