o
    Uh:                     @   s|  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 d dlZd dlmZ d dlmZmZ d dlmZ d d	lmZmZ d d
lmZmZmZ d dlmZmZ d dl m!Z! ddl"m#Z#m$Z$m%Z%m&Z&m'Z' e(e)Z*g dZ+edd Z,G dd deZ-d$ddde-fddZ.G dd de$Z/G dd dZ0G dd dZ1G d d! d!eZ2ed$ddd"d#Z3dS )%    N)asynccontextmanagercontextmanager)count)Optional)ValueError)Channel)AuthenticatorBEGIN)get_bus)FileDescriptorfds_buf_size)ParserMessageTypeMessage)	ProxyBase
unwrap_msg)message_bus   )MessageFiltersFilterHandleReplyMatcherRouterClosedcheck_replyable)open_dbus_connectionopen_dbus_routerProxyc               
   c   sX    zd V  W d S  t y+ }  z| jtjtjhv rtdd td| | d } ~ ww )Nzthis socket was already closedzsocket connection broken: {})OSErrorerrnoEBADFENOTSOCKtrioClosedResourceErrorBrokenResourceErrorformat)exc r&   c/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/jeepney/io/trio.py)_translate_socket_errors_to_stream_errors,   s   r(   c                   @   s~   e Zd ZdZdddZdddefdd	Zd
efddZdd
e	fddZ
defddZdd Zdd Zdd Zedd ZdS )DBusConnectiona  A plain D-Bus connection with no matching of replies.

    This doesn't run any separate tasks: sending and receiving are done in
    the task that calls those methods. It's suitable for implementing servers:
    several worker tasks can receive requests and send replies.
    For a typical client pattern, see :class:`DBusRouter`.

    Implements trio's channel interface for Message objects.
    Fc                 C   sD   || _ || _t | _tdd| _d | _t | _	t | _
d | _d S )Nr   )start)socket
enable_fdsr   parserr   outgoing_serialunique_namer!   Lock	send_lock	recv_lock_leftover_to_send)selfr+   r,   r&   r&   r'   __init__E   s   


zDBusConnection.__init__Nserialmessagec             	      s   | j 4 I dH / |du rt| j}| jrtdnd}|j||d}| ||I dH  W d  I dH  dS 1 I dH s=w   Y  dS )z.Serialise and send a :class:`~.Message` objectNi)fds)r1   nextr.   r,   array	serialise
_send_data)r4   r8   r7   r:   datar&   r&   r'   sendO   s   
.zDBusConnection.sendr?   c              	      s   | j jr
tdt Y | jr| | jI d H  t|0}|r5| j |gtj j	tj j
|fgI d H }n	| j |I d H }| ||I d H  W d    n1 sQw   Y  W d    d S W d    d S 1 siw   Y  d S )Nz!can't send data after sending EOF)r+   did_shutdown_SHUT_WRr!   r"   r(   r3   _send_remainder
memoryviewsendmsg
SOL_SOCKET
SCM_RIGHTSr@   )r4   r?   r:   sentr&   r&   r'   r>   Z   s"   


"zDBusConnection._send_datar   c                    s   z5|t |k r1||d  }| j|I d H }W d    n1 s"w   Y  ||7 }|t |k sd | _W d S  tjyF   ||d  | _ w N)lenr+   r@   r3   r!   	Cancelled)r4   r?   already_sent	remainingrG   r&   r&   r'   rB   m   s   zDBusConnection._send_remainderreturnc              	      s   | j 4 I dH / 	 | j }|dur|W  d  I dH  S |  I dH \}}|s/td| j|| q
1 I dH s=w   Y  dS )z5Return the next available message from the connectionNTzSocket closed at the other end)r2   r-   get_next_message
_read_datar!   EndOfChanneladd_data)r4   msgbr:   r&   r&   r'   receive{   s   

zDBusConnection.receivec                    s   | j rC| j }t  | j|t I d H \}}}}W d    n1 s&w   Y  |ttjdd@ r<| 	  t
d|t|fS t  | jdI d H }W d    |g fS 1 s]w   Y  |g fS )N
MSG_CTRUNCr   z&Unable to receive all file descriptorsi   )r,   r-   bytes_desiredr(   r+   recvmsgr   getattrr!   _closeRuntimeErrorr   from_ancdatarecv)r4   nbytesr?   ancdataflags_r&   r&   r'   rO      s$   

zDBusConnection._read_datac                 C   s   | j   d | _d S rH   )r+   closer3   r4   r&   r&   r'   rY      s   

zDBusConnection._closec                    s   |    dS )zClose the D-Bus connectionN)rY   rb   r&   r&   r'   aclose   s   zDBusConnection.aclosec              	   C  s   t  4 I dH -}t| }||I dH  z|V  W | I dH  n| I dH  w W d  I dH  dS 1 I dH s<w   Y  dS )aY  Temporarily wrap this connection as a :class:`DBusRouter`

        To be used like::

            async with conn.router() as req:
                reply = await req.send_and_get_reply(msg)

        While the router is running, you shouldn't use :meth:`receive`.
        Once the router is closed, you can use the plain connection again.
        N)r!   open_nursery
DBusRouterr*   rc   )r4   nurseryrouterr&   r&   r'   rg      s   ".zDBusConnection.router)F)r   )__name__
__module____qualname____doc__r5   r   r@   bytesr>   rC   rB   rT   rO   rY   rc   r   rg   r&   r&   r&   r'   r)   ;   s    
	
r)   SESSIONFr,   rM   c          	   	      s  t | }t|I dH }t|dd}ttdr,|jdgtjtjt	dfgI dH  n|
dI dH  |D ]}|
|I dH  || I dH  q6|
tI dH  t|j|d}| 4 I dH }|t I dH }|jd |_W d  I dH  |S 1 I dH sw   Y  |S )	zHOpen a plain D-Bus connection

    :return: :class:`DBusConnection`
    NF)r,   inc_null_byte	SCM_CREDS    i   rn   r   )r   r!   open_unix_socketr	   hasattrr+   rD   rE   rp   rl   send_allfeedreceive_somer
   r)   rg   send_and_get_replyr   Hellobodyr/   )	busr,   bus_addrsockauthrreq_dataconnrg   replyr&   r&   r'   r      s*   
r   c                       sF   e Zd Zdef fddZedd Zdd Zdd	 Zd
d Z	  Z
S )TrioFilterHandlefiltersc                    s   t  ||| || _d S rH   )superr5   send_channel)r4   r   rulesend_chnrecv_chn	__class__r&   r'   r5      s   
zTrioFilterHandle.__init__c                 C   s   | j S rH   queuerb   r&   r&   r'   receive_channel   s   z TrioFilterHandle.receive_channelc                    s   |    | j I d H  d S rH   )ra   r   rc   rb   r&   r&   r'   rc      s   zTrioFilterHandle.aclosec                    s   | j S rH   r   rb   r&   r&   r'   
__aenter__   s   zTrioFilterHandle.__aenter__c                    s   |   I d H  d S rH   )rc   )r4   exc_typeexc_valexc_tbr&   r&   r'   	__aexit__   s   zTrioFilterHandle.__aexit__)rh   ri   rj   r   r5   propertyr   rc   r   r   __classcell__r&   r&   r   r'   r      s    
r   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )Futurez4A very simple Future for trio based on `trio.Event`.c                 C   s   d | _ t | _d S rH   )_outcomer!   Event_eventrb   r&   r&   r'   r5      s   zFuture.__init__c                 C      t || _| j  d S rH   )r   r   r   set)r4   resultr&   r&   r'   
set_result      
zFuture.set_resultc                 C   r   rH   )r   r   r   r   )r4   r%   r&   r&   r'   set_exception   r   zFuture.set_exceptionc                    s   | j  I d H  | j S rH   )r   waitr   unwraprb   r&   r&   r'   get   s   
z
Future.getN)rh   ri   rj   rk   r5   r   r   r   r&   r&   r&   r'   r      s    r   c                   @   s   e Zd ZdZdZdZdefddZedd Z	ddd	d
Z
defddZddddeej fddZdejfddZdd ZdefddZejfddZdS )re   zA client D-Bus connection which can wait for replies.

    This runs a separate receiver task and dispatches received messages.
    Nr   c                 C   s   || _ t | _t | _d S rH   )_connr   _repliesr   _filters)r4   r   r&   r&   r'   r5   
  s   zDBusRouter.__init__c                 C   s   | j jS rH   )r   r/   rb   r&   r&   r'   r/     s   zDBusRouter.unique_namer6   c                   s   | j j||dI dH  dS )z/Send a message, don't wait for a reply
        r6   N)r   r@   )r4   r8   r7   r&   r&   r'   r@     s   zDBusRouter.sendrM   c                    s~   t | | jdu rtdt| jj}| j|t }| j	||dI dH  |
 I dH W  d   S 1 s8w   Y  dS )zSend a method call message and wait for the reply

        Returns the reply message (method return or error message type).
        NzThis DBusRouter has stoppedr6   )r   _rcv_cancel_scoper   r;   r   r.   r   catchr   r@   r   )r4   r8   r7   	reply_futr&   r&   r'   rw     s   
$zDBusRouter.send_and_get_replyr   )channelbufsizer   c                C   s,   |du rt |\}}nd}t| j|||S )a  Create a filter for incoming messages

        Usage::

            async with router.filter(rule) as receive_channel:
                matching_msg = await receive_channel.receive()

            # OR:
            send_chan, recv_chan = trio.open_memory_channel(1)
            async with router.filter(rule, channel=send_chan):
                matching_msg = await recv_chan.receive()

        If the channel fills up,
        The sending end of the channel is closed when leaving the ``async with``
        block, whether or not it was passed in.

        :param jeepney.MatchRule rule: Catch messages matching this rule
        :param trio.MemorySendChannel channel: Send matching messages here
        :param int bufsize: If no channel is passed in, create one with this size
        N)r!   open_memory_channelr   r   )r4   r   r   r   recv_channelr&   r&   r'   filter'  s   zDBusRouter.filterrf   c                    s,   | j d ur
td|| jI d H | _ d S )Nz+DBusRouter receiver task is already running)r   rZ   r*   	_receiver)r4   rf   r&   r&   r'   r*   D  s   
zDBusRouter.startc                    s0   | j dur| j   d| _ tdI dH  dS )z Stop the sender & receiver tasksNr   )r   cancelr!   sleeprb   r&   r&   r'   rc   I  s
   

zDBusRouter.acloserR   c              	   C   sJ   | j |rdS | j|D ]}z|j| W q tjy"   Y qw dS )zHandle one received messageN)r   dispatchr   matchesr   send_nowaitr!   
WouldBlock)r4   rR   r   r&   r&   r'   	_dispatchV  s   zDBusRouter._dispatchc                    s   t  K}d| _|| z	 | j I dH }| | qd| _| j  t 	d}| j
j D ]}d|_|j I dH  q2W d   w 1 sJw   Y  w 1 sSw   Y  dS )z'Receiver loop - runs in a separate taskTNF   )r!   CancelScope
is_runningstartedr   rT   r   r   drop_allmove_on_afterr   r   valuesshieldr   rc   )r4   task_statuscscoperR   cleanup_scoper   r&   r&   r'   r   a  s$   



zDBusRouter._receiver)rh   ri   rj   rk   _nursery_mgrr   r)   r5   r   r/   r@   r   rw   r   r!   MemorySendChannelr   Nurseryr*   rc   r   TASK_STATUS_IGNOREDr   r&   r&   r&   r'   re     s    
re   c                       s(   e Zd ZdZ fddZdd Z  ZS )r   a  A trio proxy for calling D-Bus methods

    You can call methods on the proxy object, such as ``await bus_proxy.Hello()``
    to make a method call over D-Bus and wait for a reply. It will either
    return a tuple of returned data, or raise :exc:`.DBusErrorResponse`.
    The methods available are defined by the message generator you wrap.

    :param msggen: A message generator object.
    :param ~trio.DBusRouter router: Router to send and receive messages.
    c                    s(   t  | t|tstd|| _d S )Nz)Proxy can only be used with DBusRequester)r   r5   
isinstancere   	TypeError_router)r4   msggenrg   r   r&   r'   r5     s   

zProxy.__init__c                    s    fdd}|S )Nc                     s<    | i |}|j jtju sJ j|I d H }t|S rH   )headermessage_typer   method_callr   rw   r   )argskwargsrR   r   make_msgr4   r&   r'   inner  s
   z!Proxy._method_call.<locals>.innerr&   )r4   r   r   r&   r   r'   _method_call  s   zProxy._method_call)rh   ri   rj   rk   r5   r   r   r&   r&   r   r'   r   w  s    
r   c             
   C  s   t | |dI dH }|4 I dH - | 4 I dH }|V  W d  I dH  n1 I dH s-w   Y  W d  I dH  dS 1 I dH sCw   Y  dS )a  Open a D-Bus 'router' to send and receive messages.

    Use as an async context manager::

        async with open_dbus_router() as req:
            ...

    :param str bus: 'SESSION' or 'SYSTEM' or a supported address.
    :return: :class:`DBusRouter`

    This is a shortcut for::

        conn = await open_dbus_connection()
        async with conn:
            async with conn.router() as req:
                ...
    rn   N)r   rg   )rz   r,   r   rtrr&   r&   r'   r     s   *.r   )rm   )4r<   r   loggingr+   
contextlibr   r   	itertoolsr   typingr   outcomer   r   r!   trio.abcr   jeepney.authr	   r
   jeepney.busr   jeepney.fdsr   r   jeepney.low_levelr   r   r   jeepney.wrappersr   r   jeepney.bus_messagesr   commonr   r   r   r   r   	getLoggerrh   log__all__r(   r)   r   r   r   re   r   r   r&   r&   r&   r'   <module>   s:    

~"u