U
    [e                     @   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ejejdddZddeddd	Z	ed
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   T/var/www/html/services/stratfitenv/lib/python3.8/site-packages/jeepney/io/asyncio.py__init__   s    zDBusConnection.__init__Nserial)messagec             
      sX   | j 4 I dH : |dkr"t| j}| j|| | j I dH  W 5 Q I dH R X dS )z.Serialise and send a :class:`~.Message` objectN)r   nextr   r   writeZ	serialisedrainr   r#   r"   r   r   r   send    s
    
zDBusConnection.sendreturnc                    sB   | j  }|dk	r|S | jdI dH }|s0t| j | q dS )z5Return the next available message from the connectionNi   )r   Zget_next_messager   readEOFErrorZ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   r0   4   s    
zDBusConnection.closec                    s   | S Nr   r2   r   r   r   
__aenter__9   s    zDBusConnection.__aenter__c                    s   |   I d H  d S r3   )r0   r   exc_typeexc_valexc_tbr   r   r   	__aexit__<   s    zDBusConnection.__aexit__)__name__
__module____qualname____doc__r   StreamReaderStreamWriterr    r   r(   r/   r0   r4   r9   r   r   r   r   r      s   r   SESSIONc           
   
      s   t | }t|I dH \}}t }|D ]B}|| | I dH  |dI dH }|s^td|| q&|t	 | I dH  t
||}t|4 I dH ,}ttt| dI dH }	|	d |_W 5 Q I dH R X |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   ZHellor   )
busZbus_addrr   r   ZauthrZreq_datar.   connrouterZ
reply_bodyr   r   r   open_dbus_connection@   s"    


rJ   c                   @   s   e Zd ZdZdZdZdZedddZe	dd Z
ddd	d
ZedddZdddeej dddZdd Zdd ZedddZdd ZdS )rD   zA '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.
    N)rH   c                 C   s*   || _ t | _t | _t|  | _d S r3   )	_connr   _repliesr   _filtersr   create_task	_receiver	_rcv_task)r   rH   r   r   r   r    j   s    zDBusRouter.__init__c                 C   s   | j jS r3   )rK   r   r2   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)rK   r(   r'   r   r   r   r(   t   s    zDBusRouter.sendr)   c              
      sn   t | | j rtdt| jj}| j|t	
 ,}| j||dI dH  |I dH W  5 Q R  S Q R X dS )zSend 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   rP   doner   r$   rK   r   rL   Zcatchr   Futurer(   )r   r#   r"   Z	reply_futr   r   r   send_and_get_replyx   s    
zDBusRouter.send_and_get_replyr   )queuebufsize)rT   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   rM   r   Queue)r   rulerT   rU   r   r   r   filter   s    zDBusRouter.filterc                    s   | S r3   r   r2   r   r   r   r4      s    zDBusRouter.__aenter__c              	      sH   | j  r| j   n.| j   ttj | j I d H  W 5 Q R X dS )NF)rP   rQ   resultcancel
contextlibsuppressr   CancelledErrorr5   r   r   r   r9      s    

zDBusRouter.__aexit__)r-   c              	   C   sR   | j |rdS t| j|D ],}z|j| W q  tjk
rJ   Y q X q dS )zHandle one received messageN)	rL   dispatchlistrM   matchesrT   
put_nowaitr   	QueueFull)r   r-   rX   r   r   r   	_dispatch   s    zDBusRouter._dispatchc                    s2   z | j I dH }| | qW 5 | j   X dS )z'Receiver loop - runs in a separate taskN)rL   Zdrop_allrK   r/   rc   )r   r-   r   r   r   rO      s    zDBusRouter._receiver)r:   r;   r<   r=   Z_nursery_mgrZ_send_cancel_scopeZ_rcv_cancel_scoper   r    propertyr   r(   r   rS   r   r   rV   rX   r4   r9   rc   rO   r   r   r   r   rD   `   s   
rD   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_routerzOpen a D-Bus 'router' to send and receive messages

    Use as an async context manager::

        async with open_dbus_router() as router:
            ...
    Nr@   c                 C   s
   || _ d S r3   )rG   )r   rG   r   r   r   r       s    zopen_dbus_router.__init__c                    s.   t | jI d H | _t| j| _| j I d H S r3   )rJ   rG   rH   rD   req_ctxr4   r2   r   r   r   r4      s    zopen_dbus_router.__aenter__c                    s*   | j |||I d H  | j I d H  d S r3   )rf   r9   rH   r0   r5   r   r   r   r9      s    zopen_dbus_router.__aexit__)r@   )	r:   r;   r<   r=   rH   rf   r    r4   r9   r   r   r   r   re      s   
re   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )rF   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 r3   )superr    _router)r   ZmsggenrI   	__class__r   r   r       s    zProxy.__init__c                 C   s   d | j| jS )NzProxy({}, {}))formatZ_msggenrh   r2   r   r   r   __repr__   s    zProxy.__repr__c                    s    fdd}|S )Nc                     s6    | |}|j jtjkstj|I d H }t|S r3   )headerZmessage_typer   method_callAssertionErrorrh   rS   r   )argskwargsr-   Zreplymake_msgr   r   r   inner   s    
z!Proxy._method_call.<locals>.innerr   )r   rs   rt   r   rr   r   _method_call   s    zProxy._method_call)r:   r;   r<   r=   r    rl   ru   __classcell__r   r   ri   r   rF      s   
rF   )r@   )r   r[   	itertoolsr   typingr   Zjeepney.authr   r   Zjeepney.busr   Zjeepneyr   r   r	   Zjeepney.wrappersr
   r   Zjeepney.bus_messagesr   commonr   r   r   r   r   r   rJ   rD   re   rF   r   r   r   r   <module>   s   0
 X