o
    Ž›aÆ  ã                   @   sØ   d dl Z d dlZd dlm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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 G dd„ dƒZddd„ZG dd„ dƒZG dd„ dƒZG dd„ deƒZdS )é    N)Úcount)ÚOptional)ÚAuthenticatorÚBEGIN)Úget_bus)ÚMessageÚMessageTypeÚParser)Ú	ProxyBaseÚ
unwrap_msg)Úmessage_busé   )ÚMessageFiltersÚFilterHandleÚReplyMatcherÚRouterClosedÚcheck_replyablec                   @   s`   e Zd ZdZdejdejfdd„Zddœdefd	d
„Z	defdd„Z
dd„ Zdd„ Zdd„ ZdS )ÚDBusConnectionaP  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`.
    ÚreaderÚwriterc                 C   s4   || _ || _tƒ | _tdd�| _d | _t ¡ | _	d S )Nr   )Ústart)
r   r   r	   Úparserr   Úoutgoing_serialÚunique_nameÚasyncioÚLockÚ	send_lock)Úselfr   r   © r   ú4/usr/lib/python3/dist-packages/jeepney/io/asyncio.pyÚ__init__   s   zDBusConnection.__init__N©ÚserialÚmessagec             	   Ã   sv   �| j 4 I dH š& |du rt| jƒ}| j | |¡¡ | j ¡ I dH  W d  ƒI dH  dS 1 I dH s4w   Y  dS )z.Serialise and send a :class:`~.Message` objectN)r   Únextr   r   ÚwriteÚ	serialiseÚdrain©r   r#   r"   r   r   r   Úsend    s   €
.üzDBusConnection.sendÚreturnc                 Ã   sB   �	 | j  ¡ }|dur|S | j d¡I dH }|st‚| j  |¡ q)z5Return the next available message from the connectionTNi   )r   Úget_next_messager   ÚreadÚEOFErrorÚadd_data)r   ÚmsgÚbr   r   r   Úreceive(   s   €
øzDBusConnection.receivec                 Ã   s    �| j  ¡  | j  ¡ I dH  dS )zClose the D-Bus connectionN)r   ÚcloseÚwait_closed©r   r   r   r   r2   4   s   €
zDBusConnection.closec                 Ã   ó   �| S ©Nr   r4   r   r   r   Ú
__aenter__9   ó   €zDBusConnection.__aenter__c                 Ã   s   �|   ¡ I d H  d S r6   )r2   ©r   Úexc_typeÚexc_valÚexc_tbr   r   r   Ú	__aexit__<   s   €zDBusConnection.__aexit__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚStreamReaderÚStreamWriterr    r   r)   r1   r2   r7   r=   r   r   r   r   r      s    r   ÚSESSIONc           
   	   Ã   sö   �t | ƒ}t |¡I dH \}}tƒ }|D ]!}| |¡ | ¡ I dH  | d¡I dH }|s0tdƒ‚| |¡ q| t	¡ | ¡ I dH  t
||ƒ}t|ƒ4 I dH š}t tt|ƒ ¡ d¡I dH }	|	d |_W d  ƒI dH  |S 1 I dH stw   Y  |S )zHOpen a plain D-Bus connection

    :return: :class:`DBusConnection`
    Ni   z#Socket closed before authenticationé
   r   )r   r   Úopen_unix_connectionr   r%   r'   r,   r-   Úfeedr   r   Ú
DBusRouterÚwait_forÚProxyr   ÚHellor   )
ÚbusÚbus_addrr   r   ÚauthrÚreq_datar0   ÚconnÚrouterÚ
reply_bodyr   r   r   Úopen_dbus_connection@   s*   €


þürS   c                   @   s”   e Zd 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d„ Zdd„ Zdefdd„Zdd„ ZdS )rH   z½A 'client' D-Bus connection which can wait for a specific reply.

    This runs a background receiver task, and makes it possible to send a
    request and wait for the relevant reply.
    NrP   c                 C   s*   || _ tƒ | _tƒ | _t |  ¡ ¡| _d S r6   )	Ú_connr   Ú_repliesr   Ú_filtersr   Úcreate_taskÚ	_receiverÚ	_rcv_task)r   rP   r   r   r   r    j   s   zDBusRouter.__init__c                 C   s   | j jS r6   )rT   r   r4   r   r   r   r   p   s   zDBusRouter.unique_namer!   c                Ã   s   �| j j||d�I dH  dS )z&Send a message, don't wait for a replyr!   N)rT   r)   r(   r   r   r   r)   t   s   €zDBusRouter.sendr*   c                 Ã   s|   �t |ƒ | j ¡ rtdƒ‚t| jjƒ}| j |t	 
¡ ¡�}| j||d�I dH  |I dH W  d  ƒ S 1 s7w   Y  dS )z„Send a method call message and wait for the reply

        Returns the reply message (method return or error message type).
        zThis DBusRouter has stoppedr!   N)r   rY   Údoner   r$   rT   r   rU   Úcatchr   ÚFuturer)   )r   r#   r"   Ú	reply_futr   r   r   Úsend_and_get_replyx   s   €
$þzDBusRouter.send_and_get_replyr   )ÚqueueÚbufsizer_   c                C   s   t | j||p
t |¡ƒS )ar  Create a filter for incoming messages

        Usage::

            with router.filter(rule) as queue:
                matching_msg = await queue.get()

        :param MatchRule rule: Catch messages matching this rule
        :param asyncio.Queue queue: Send matching messages here
        :param int bufsize: If no queue is passed in, create one with this size
        )r   rV   r   ÚQueue)r   Úruler_   r`   r   r   r   Úfilter‡   s   zDBusRouter.filterc                 Ã   r5   r6   r   r4   r   r   r   r7   •   r8   zDBusRouter.__aenter__c                 Ã   sb   �| j  ¡ r| j  ¡  dS | j  ¡  t tj¡� | j I d H  W d   ƒ dS 1 s*w   Y  dS )NF)rY   rZ   ÚresultÚcancelÚ
contextlibÚsuppressr   ÚCancelledErrorr9   r   r   r   r=   ˜   s   €


ý
ÿþzDBusRouter.__aexit__r/   c              	   C   sN   | j  |¡rdS t| j |¡ƒD ]}z|j |¡ W q tjy$   Y qw dS )zHandle one received messageN)	rU   ÚdispatchÚlistrV   Úmatchesr_   Ú
put_nowaitr   Ú	QueueFull)r   r/   rc   r   r   r   Ú	_dispatch£   s   ÿýzDBusRouter._dispatchc                 Ã   s.   �z	 | j  ¡ I dH }|  |¡ q| j ¡  w )z'Receiver loop - runs in a separate taskTN)rT   r1   rn   rU   Údrop_all)r   r/   r   r   r   rX   ®   s   €
þzDBusRouter._receiver)r>   r?   r@   rA   Ú_nursery_mgrÚ_send_cancel_scopeÚ_rcv_cancel_scoper   r    Úpropertyr   r)   r   r^   r   r   ra   rc   r7   r=   rn   rX   r   r   r   r   rH   `   s    
rH   c                   @   s2   e Zd ZdZdZdZd
dd„Zdd„ Zdd	„ ZdS )Úopen_dbus_routerz Open a D-Bus 'router' to send and receive messages

    Use as an async context manager::

        async with open_dbus_router() as router:
            ...
    NrD   c                 C   s
   || _ d S r6   )rL   )r   rL   r   r   r   r    Ã   s   
zopen_dbus_router.__init__c                 Ã   s0   �t | jƒI d H | _t| jƒ| _| j ¡ I d H S r6   )rS   rL   rP   rH   Úreq_ctxr7   r4   r   r   r   r7   Æ   s   €zopen_dbus_router.__aenter__c                 Ã   s,   �| j  |||¡I d H  | j ¡ I d H  d S r6   )ru   r=   rP   r2   r9   r   r   r   r=   Ë   s   €zopen_dbus_router.__aexit__©rD   )	r>   r?   r@   rA   rP   ru   r    r7   r=   r   r   r   r   rt   ¸   s    
rt   c                       s0   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Z‡  ZS )rJ   aÚ  An asyncio 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 ~asyncio.DBusRouter router: Router to send and receive messages.
    c                    s   t ƒ  |¡ || _d S r6   )Úsuperr    Ú_router)r   ÚmsggenrQ   ©Ú	__class__r   r   r    Û   s   
zProxy.__init__c                 C   s   d  | j| j¡S )NzProxy({}, {}))ÚformatÚ_msggenrx   r4   r   r   r   Ú__repr__ß   s   zProxy.__repr__c                    s   ‡ ‡fdd„}|S )Nc                  Ÿ   s<   �ˆ | i |¤Ž}|j jtju sJ ‚ˆj |¡I d H }t|ƒS r6   )ÚheaderÚmessage_typer   Úmethod_callrx   r^   r   )ÚargsÚkwargsr/   Úreply©Úmake_msgr   r   r   Úinnerã   s
   €z!Proxy._method_call.<locals>.innerr   )r   r†   r‡   r   r…   r   Ú_method_callâ   s   zProxy._method_call)r>   r?   r@   rA   r    r~   rˆ   Ú__classcell__r   r   rz   r   rJ   Ð   s
    
rJ   rv   )r   rf   Ú	itertoolsr   Útypingr   Újeepney.authr   r   Újeepney.busr   Újeepneyr   r   r	   Újeepney.wrappersr
   r   Újeepney.bus_messagesr   Úcommonr   r   r   r   r   r   rS   rH   rt   rJ   r   r   r   r   Ú<module>   s    
0 X