o
    `.                     @   s  d Z ddlZddlmZ ddlmZ ddlZddlmZ ddl	Z	ddl
mZmZ ddlZddlZddlmZ ddlmZ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 ddlmZm Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z&m'Z'm(Z( g dZ)G dd dZ*dd Z+dd Z,G dd dZ-G dd de-Z.G dd deZ/dd Z0d+d"ejfd#d$Z1	&d,d"e.fd'd(Z2e3d)kre2 Z4e5d*e4j6 dS dS )-z'Synchronous IO wrappers around jeepney
    N)deque)
ECONNRESET)count)DefaultSelector
EVENT_READ)Optional)ParserMessageMessageTypeHeaderFields)AuthenticatorBEGIN)get_bus)FileDescriptorfds_buf_size)	ProxyBase
unwrap_msg)Router)message_bus   )MessageFiltersFilterHandlecheck_replyable)open_dbus_connectionDBusConnectionProxyc                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )_Futurec                 C   s
   d | _ d S N_resultself r"   5/usr/lib/python3/dist-packages/jeepney/io/blocking.py__init__      
z_Future.__init__c                 C   s
   t | jS r   )boolr   r    r"   r"   r#   done"   r%   z_Future.donec                 C      d|f| _ d S NFr   )r!   Z	exceptionr"   r"   r#   set_exception%      z_Future.set_exceptionc                 C   r(   )NTr   )r!   resultr"   r"   r#   
set_result(   r+   z_Future.set_resultc                 C   s   | j \}}|r	|S |r   r   )r!   Zsuccessvaluer"   r"   r#   r,   +   s   
z_Future.resultN)__name__
__module____qualname__r$   r'   r*   r-   r,   r"   r"   r"   r#   r      s    r   c                 C   s   | d ur
t  |  S d S r   )time	monotonictimeoutr"   r"   r#   timeout_to_deadline2   s   r6   c                 C   s   | d urt | t  dS d S )Ng        )maxr2   r3   )deadliner"   r"   r#   deadline_to_timeout7   s   r9   c                   @   sx   e Zd ZdZddejfddZdd Zdd	 Zd
ede	e
ej ffddZdd Zdd ZdddZdd Zdd ZdS )DBusConnectionBasez8Connection machinery shared by this module and threadingFsockc                 C   sB   || _ || _t | _tdd| _t | _| j|t	| _
d | _d S )Nr   )start)r;   
enable_fdsr   parserr   outgoing_serialr   selectorregisterr   
select_keyunique_name)r!   r;   r=   r"   r"   r#   r$   ?   s   
zDBusConnectionBase.__init__c                 C   s   | S r   r"   r    r"   r"   r#   	__enter__H   s   zDBusConnectionBase.__enter__c                 C   s   |    dS r)   )close)r!   exc_typeZexc_valexc_tbr"   r"   r#   __exit__K   s   zDBusConnectionBase.__exit__messagereturnc                 C   s<   |d u r	t | j}| jrtdnd }|j||d}||fS )Ni)serialfds)nextr?   r=   arrayZ	serialise)r!   rI   rL   rM   datar"   r"   r#   
_serialiseO   s
   
zDBusConnectionBase._serialisec                 C   sD   | j |gtjtj|fg}|t|k r | j ||d   d S d S r   )r;   ZsendmsgsocketZ
SOL_SOCKETZ
SCM_RIGHTSlensendall)r!   rP   rM   Z
bytes_sentr"   r"   r#   _send_with_fdsV   s   z!DBusConnectionBase._send_with_fdsc                 C   s>   	 | j  }|d ur|S | jt|d\}}| j j||d q)NTr4   )rM   )r>   Zget_next_message_read_some_datar9   Zadd_data)r!   r8   msgbrM   r"   r"   r#   _receive_   s   
zDBusConnectionBase._receiveNc                 C   sN   | j |D ]\}}|| jkr$| jr|    S t| jdg f  S qt)Ni   )	r@   ZselectrB   r=   _read_with_fdsunwrap_readr;   recvTimeoutError)r!   r5   keyZevr"   r"   r#   rV   h   s   
z"DBusConnectionBase._read_some_datac                 C   sT   | j  }| j|t \}}}}|ttdd@ r!|   tdt	|t
|fS )NZ
MSG_CTRUNCr   z&Unable to receive all file descriptors)r>   Zbytes_desiredr;   Zrecvmsgr   getattrrR   rE   RuntimeErrorr[   r   Zfrom_ancdata)r!   nbytesrP   Zancdataflags_r"   r"   r#   rZ   r   s   
z!DBusConnectionBase._read_with_fdsc                 C   s   | j   | j  dS )zClose the connectionN)r@   rE   r;   r    r"   r"   r#   rE   z   s   
zDBusConnectionBase.closeFr   )r/   r0   r1   __doc__rR   r$   rD   rH   r	   bytesr   rO   rQ   rU   rY   rV   rZ   rE   r"   r"   r"   r#   r:   =   s    		
	
r:   c                       s   e Zd Zddejf fddZddefddZeZdd	d
efddZdd	ddZ	dddddZ
ddddee fddZdd	d
efddZ  ZS )r   Fr;   c                    sJ   t  || d| _tt| _t | _tt	| | _
| j
 }|d | _d S )NFr   )superr$   _unwrap_replyr   r   routerr   _filtersr   r   Z	bus_proxyZHellorC   )r!   r;   r=   Zhello_reply	__class__r"   r#   r$      s   

zDBusConnection.__init__NrI   c                 C   s4   |  ||\}}|r| || dS | j| dS )z.Serialise and send a :class:`~.Message` objectN)rQ   rU   r;   rT   )r!   rI   rL   rP   rM   r"   r"   r#   send   s   zDBusConnection.sendr4   rJ   c                C   s   |  t|S )a+  Return the next available message from the connection

        If the data is ready, this will return immediately, even if timeout<=0.
        Otherwise, it will wait for up to timeout seconds, or indefinitely if
        timeout is None. If no message comes in time, it raises TimeoutError.
        )rY   r6   )r!   r5   r"   r"   r#   receive   s   zDBusConnection.receivec                C   s:   | j |d}| j| | j|D ]}|j| qdS )z\Receive one message and apply filters

        See :meth:`filter`. Returns nothing.
        r4   N)rn   ri   incomingrj   matchesqueueappend)r!   r5   rW   filterr"   r"   r#   recv_messages   s
   zDBusConnection.recv_messagesr5   unwrapc          	      C   s   t | t|}|du r| j}t| j}| j||d 	 | jt|d}|jj	
tjd}||kr9|r7t|S |S | j| | j|D ]}|j| qEq)zSend a message, wait for the reply and return it

        Filters are applied to other messages received before the reply -
        see :meth:`add_filter`.
        N)rL   Tr4   )r   r6   rh   rN   r?   send_messagern   r9   headerZfieldsgetr   Zreply_serialr   ri   ro   rj   rp   rq   rr   )	r!   rI   r5   rv   r8   rL   Zmsg_inZreply_tors   r"   r"   r#   send_and_get_reply   s"   
z!DBusConnection.send_and_get_replyr   )rq   bufsizerq   c                C   s    |du r	t |d}t| j||S )a  Create a filter for incoming messages

        Usage::

            with conn.filter(rule) as matches:
                # matches is a deque containing matched messages
                matching_msg = conn.recv_until_filtered(matches)

        :param jeepney.MatchRule rule: Catch messages matching this rule
        :param collections.deque queue: Matched messages will be added to this
        :param int bufsize: If no deque is passed in, create one with this size
        N)maxlen)r   r   rj   )r!   Zrulerq   r|   r"   r"   r#   rs      s   
zDBusConnection.filterc                C   s8   t |}t|dkr| jt|d t|dks
| S )aZ  Process incoming messages until one is filtered into queue

        Pops the message from queue and returns it, or raises TimeoutError if
        the optional timeout expires. Without a timeout, this is equivalent to::

            while len(queue) == 0:
                conn.recv_messages()
            return queue.popleft()

        In the other I/O modules, there is no need for this, because messages
        are placed in queues by a separate task.

        :param collections.deque queue: A deque connected by :meth:`filter`
        :param float timeout: Maximum time to wait in seconds
        r   r4   )r6   rS   rt   r9   popleft)r!   rq   r5   r8   r"   r"   r#   recv_until_filtered   s
   z"DBusConnection.recv_until_filteredrd   r   )r/   r0   r1   rR   r$   r	   rm   rx   rn   rt   r{   r   r   rs   r   __classcell__r"   r"   rk   r#   r      s    	
r   c                       s6   e Zd ZdZdd fdd
Zdd Zdd	 Z  ZS )
r   aj  A blocking proxy for calling D-Bus methods

    You can call methods on the proxy object, such as ``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.

    You can set a time limit on a call by passing ``_timeout=`` in the method
    call, or set a default when creating the proxy. The ``_timeout`` argument
    is not passed to the message generator.
    All timeouts are in seconds, and :exc:`TimeoutErrror` is raised if it
    expires before a reply arrives.

    :param msggen: A message generator object
    :param ~blocking.DBusConnection connection: Connection to send and receive messages
    :param float timeout: Default seconds to wait for a reply, or None for no limit
    Nr4   c                   s   t  | || _|| _d S r   )rg   r$   _connection_timeout)r!   ZmsggenZ
connectionr5   rk   r"   r#   r$      s   
zProxy.__init__c                 C   s4   | j d u rdnd| j  }d| j d| j | dS )N z
, timeout=zProxy(z, ))r   Z_msggenr   )r!   Zextrar"   r"   r#   __repr__  s   zProxy.__repr__c                    s   t   fdd}|S )Nc                     s@   | dj} | i |}|jjtju sJ jj||ddS )Nr   Tru   )popr   ry   Zmessage_typer
   Zmethod_callr   r{   )argskwargsr5   rW   make_msgr!   r"   r#   inner	  s   z!Proxy._method_call.<locals>.inner)	functoolswraps)r!   r   r   r"   r   r#   _method_call  s   zProxy._method_call)r/   r0   r1   re   r$   r   r   r   r"   r"   rk   r#   r      s
    r   c                 C   s   | s
t ttt| S )zRaise ConnectionResetError from an empty read.

    Sometimes the socket raises an error itself, sometimes it gives no data.
    I haven't worked out when it behaves each way.
    )ConnectionResetErrorr   osstrerror)rX   r"   r"   r#   r[     s   r[   F       @rJ   c              
      s   t j t jdt|  fdd}z)|j|  t|d}|D ]}|j| |t|jd q |jt	 W n! t j
yU } z  td| d|d}~w      d S )	z=Create a socket and authenticate ready to send D-Bus messages)Zfamilyc                    s    t  | | S r   )
settimeoutr9   )Zmethr   r8   r;   r"   r#   with_sock_deadline(  s   z'prep_socket.<locals>.with_sock_deadline)r=   i   zDid not authenticate in z secondsN)rR   ZAF_UNIXr6   Zconnectr   rT   Zfeedr[   r\   r   r5   rE   r]   r   )Zaddrr=   r5   r   ZauthrZreq_dataer"   r   r#   prep_socket   s&   

r   SESSION      ?c                 C   s$   t | }t|||d}t||}|S )a  Connect to a D-Bus message bus

    Pass ``enable_fds=True`` to allow sending & receiving file descriptors.
    An error will be raised if the bus does not allow this. For simplicity,
    it's advisable to leave this disabled unless you need it.

    D-Bus has an authentication step before sending or receiving messages.
    This takes < 1 ms in normal operation, but there is a timeout so that client
    code won't get stuck if the server doesn't reply. *auth_timeout* configures
    this timeout in seconds.
    r4   )r   r   r   )Zbusr=   Zauth_timeoutZbus_addrr;   connr"   r"   r#   r   >  s   
r   __main__zUnique name:)Fr   )r   Fr   )7re   rO   collectionsr   errnor   r   	itertoolsr   r   Z	selectorsr   r   rR   r2   typingr   Zjeepneyr   r	   r
   r   Zjeepney.authr   r   Zjeepney.busr   Zjeepney.fdsr   r   Zjeepney.wrappersr   r   Zjeepney.routingr   Zjeepney.bus_messagesr   commonr   r   r   __all__r   r6   r9   r:   r   r   r[   r   r   r/   r   printrC   r"   r"   r"   r#   <module>   sH    Cm(
