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rÅe2ƒ 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!   Ú	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!   Ú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   r8   c                 C   s   | d urt | t ¡  dƒS d S )Ng        )Úmaxr4   r5   )Údeadliner"   r"   r#   Údeadline_to_timeout7   s   r;   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_typeÚ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)ÚnextrA   r?   ÚarrayÚ	serialise)r!   rL   rO   rP   Ú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=   ÚsendmsgÚsocketÚ
SOL_SOCKETÚ
SCM_RIGHTSÚlenÚsendall)r!   rT   rP   Ú
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)NTr6   )rP   )r@   Úget_next_messageÚ_read_some_datar;   Úadd_data)r!   r:   ÚmsgÚbrP   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   )	rB   ÚselectrD   r?   Ú_read_with_fdsÚunwrap_readr=   ÚrecvÚTimeoutError)r!   r7   ÚkeyÚevr"   r"   r#   r_   h   s   
üz"DBusConnectionBase._read_some_datac                 C   sT   | j  ¡ }| j |tƒ ¡\}}}}|ttddƒ@ r!|  ¡  tdƒ‚t	|ƒt
 |¡fS )NÚ
MSG_CTRUNCr   z&Unable to receive all file descriptors)r@   Úbytes_desiredr=   Úrecvmsgr   ÚgetattrrW   rG   ÚRuntimeErrorrf   r   Úfrom_ancdata)r!   ÚnbytesrT   ÚancdataÚflagsÚ_r"   r"   r#   re   r   s   
z!DBusConnectionBase._read_with_fdsc                 C   s   | j  ¡  | j ¡  dS )zClose the connectionN)rB   rG   r=   r    r"   r"   r#   rG   z   s   
zDBusConnectionBase.close©Fr   )r1   r2   r3   Ú__doc__rW   r$   rF   rK   r	   Úbytesr   rR   rU   r]   rc   r_   re   rG   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   Ú	bus_proxyÚHellorE   )r!   r=   r?   Úhello_reply©Ú	__class__r"   r#   r$   �   s   

zDBusConnection.__init__NrL   c                 C   s4   |   ||¡\}}|r|  ||¡ dS | j |¡ dS )z.Serialise and send a :class:`~.Message` objectN)rU   r]   r=   r[   )r!   rL   rO   rT   rP   r"   r"   r#   ÚsendŽ   s   zDBusConnection.sendr6   rM   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.
        )rc   r8   )r!   r7   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.
        r6   N)r‚   rz   Úincomingr{   ÚmatchesÚqueueÚappend)r!   r7   ra   Úfilterr"   r"   r#   Úrecv_messages¡   s
   ÿzDBusConnection.recv_messages©r7   Ú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)z¤Send a message, wait for the reply and return it

        Filters are applied to other messages received before the reply -
        see :meth:`add_filter`.
        N)rO   Tr6   éÿÿÿÿ)r   r8   ry   rQ   rA   Úsend_messager‚   r;   ÚheaderÚfieldsÚgetr   Úreply_serialr   rz   rƒ   r{   r„   r…   r†   )	r!   rL   r7   rŠ   r:   rO   Úmsg_inÚreply_tor‡   r"   r"   r#   Úsend_and_get_reply«   s"   
õz!DBusConnection.send_and_get_replyr   )r…   Úbufsizer…   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   r{   )r!   Úruler…   r”   r"   r"   r#   r‡   Æ   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   r6   )r8   rZ   rˆ   r;   Úpopleft)r!   r…   r7   r:   r"   r"   r#   Úrecv_until_filtered×   s
   ÿz"DBusConnection.recv_until_filteredru   r   )r1   r2   r3   rW   r$   r	   r�   rŒ   r‚   rˆ   r“   r   r   r‡   r˜   Ú__classcell__r"   r"   r   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
    Nr6   c                   s   t ƒ  |¡ || _|| _d S r   )rx   r$   Ú_connectionÚ_timeout)r!   ÚmsggenÚ
connectionr7   r   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›   Ú_msggenrš   )r!   Ú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›   Tr‰   )Úpopr›   r�   Úmessage_typer
   Úmethod_callrš   r“   )ÚargsÚkwargsr7   ra   ©Ú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)r1   r2   r3   rv   r$   r¢   r­   r™   r"   r"   r   r#   r   í   s
    r   c                 C   s   | s
t tt t¡ƒ‚| S )z´Raise 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)rb   r"   r"   r#   rf     s   rf   Fç       @rM   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)Úfamilyc                    s   ˆ  tˆ ƒ¡ | |Ž S r   )Ú
settimeoutr;   )Úmethr¦   ©r:   r=   r"   r#   Úwith_sock_deadline(  s   z'prep_socket.<locals>.with_sock_deadline)r?   i   zDid not authenticate in z secondsN)rW   ÚAF_UNIXr8   Úconnectr   r[   Úfeedrf   rg   r   r7   rG   rh   r³   )Úaddrr?   r7   r¶   ÚauthrÚ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.
    r6   )r   r¾   r   )Úbusr?   Úauth_timeoutÚbus_addrr=   Úconnr"   r"   r#   r   >  s   
r   Ú__main__zUnique name:)Fr±   )r¿   FrÀ   )7rv   rR   Úcollectionsr   Úerrnor   r«   Ú	itertoolsr   r¯   Ú	selectorsr   r   rW   r4   Útypingr   Újeepneyr   r	   r
   r   Újeepney.authr   r   Újeepney.busr   Újeepney.fdsr   r   Újeepney.wrappersr   r   Újeepney.routingr   Újeepney.bus_messagesr   Úcommonr   r   r   Ú__all__r   r8   r;   r<   r   r   rf   r¾   r   r1   rÄ   ÚprintrE   r"   r"   r"   r#   Ú<module>   sH    Cm(ÿ
þþ