
    +c :                        d dl Z d dlmZ d dlZd dlm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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jR                  e*      Z+g dZ,ed        Z- G d de      Z.d!ddde.fdZ/ G d de%      Z0 G d d      Z1 G d d      Z2 G d de      Z3e	d!ddd        Z4y# e
$ r	 d dlm	Z	 Y w xY w)"    N)contextmanager)count)Optional)asynccontextmanager)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               #     K   	 d  y # t         $ rl} | j                  t        j                  t        j                  hv rt	        j
                  d      d t	        j                  dj                  |             | d } ~ ww xY ww)Nzthis socket was already closedzsocket connection broken: {})OSErrorerrnoEBADFENOTSOCKtrioClosedResourceErrorBrokenResourceErrorformat)excs    1/usr/lib/python3/dist-packages/jeepney/io/trio.py)_translate_socket_errors_to_stream_errorsr)   0   so     	 99enn55**+KLRVV**.55c:s%   B	 B	A>A'A99A>>Bc                   r    e Zd ZdZddZdddefdZdefdZdde	fd	Z
d
efdZd Zd Zd Zed        Zy)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.
    c                     || _         || _        t               | _        t	        d      | _        d | _        t        j                         | _	        t        j                         | _
        d | _        y )Nr   )start)socket
enable_fdsr   parserr   outgoing_serialunique_namer#   Lock	send_lock	recv_lock_leftover_to_send)selfr.   r/   s      r(   __init__zDBusConnection.__init__I   sO    $h$1~!%    Nserialmessagec                Z  K   | j                   4 d{    |t        | j                        }| j                  rt	        j                  d      nd}|j                  ||      }| j                  ||       d{    ddd      d{    y7 |7 7 	# 1 d{  7  sw Y   yxY ww)z.Serialise and send a :class:`~.Message` objectNi)fds)r4   nextr1   r/   array	serialise
_send_data)r7   r<   r;   r?   datas        r(   sendzDBusConnection.sendS   s     >> 	- 	-~d223&*oo%++c"4C$$V$5D//$,,,	- 	- 	-
 -	- 	- 	- 	-sW   B+BB+A#B:B;B?B+
BB+BB+B(BB($B+rD   c                   K   | j                   j                  rt        j                  d      t	               5  | j
                  r#| j                  | j
                         d {    t        |      5 }|rZ| j                   j                  |gt        j                   j                  t        j                   j                  |fg       d {   }n#| j                   j                  |       d {   }| j                  ||       d {    d d d        d d d        y 7 7 U7 37 # 1 sw Y   xY w# 1 sw Y   y xY ww)Nz!can't send data after sending EOF)r.   did_shutdown_SHUT_WRr#   r$   r)   r6   _send_remainder
memoryviewsendmsg
SOL_SOCKET
SCM_RIGHTSrE   )r7   rD   r?   sents       r(   rC   zDBusConnection._send_data^   s    ;;++**+NOO68 	7%%**4+A+ABBBD! 7T!%!4!4dV..0F0F? > " D "&!1!1$!77D**46667	7 	7 C 867 7	7 	7s}   6D>+D2#D$D23AD&
D #D&.D"/D&D$	D&D2	D>D2 D&"D&$D&&D/	+D22D;7D>c                 "  K   	 |t        |      k  rE||d  5 }| j                  j                  |       d {   }d d d        |z  }|t        |      k  rEd | _        y 7 (# 1 sw Y   'xY w# t        j
                  $ r ||d  | _         w xY wwN)lenr.   rE   r6   r#   	Cancelled)r7   rD   already_sent	remainingrM   s        r(   rH   zDBusConnection._send_remainderq   s     	T*,-( =I!%!1!1)!<<D=$ T* &*D" == = ~~ 	 &*,-%8D"	sH   BA- A!AA!A- A- BA!!A*&A- -BBreturnc                 h  K   | j                   4 d{    	 | j                  j                         }||cddd      d{    S | j                          d{   \  }}|st	        j
                  d      | j                  j                  ||       ~7 7 V7 ?# 1 d{  7  sw Y   yxY ww)z5Return the next available message from the connectionNzSocket closed at the other end)r5   r0   get_next_message
_read_datar#   EndOfChanneladd_data)r7   msgbr?   s       r(   receivezDBusConnection.receive   s     >> 	- 	-kk224?		- 	- 	-  $003++,LMM$$Q, 	- 	- 1	- 	- 	-sa   B2BB2BB2BB2BB;BB2B2BB/#B&$B/+B2c                 0  K   | j                   r| j                  j                         }t               5  | j                  j                  |t                      d {   \  }}}}d d d        t        t        j                  dd      z  r| j                          t        d      t        j                        fS t               5  | j                  j                  d       d {   }d d d        |g fS 7 # 1 sw Y   xY w7 # 1 sw Y   g fS xY ww)N
MSG_CTRUNCr   z&Unable to receive all file descriptorsi   )r/   r0   bytes_desiredr)   r.   recvmsgr   getattrr#   _closeRuntimeErrorr   from_ancdatarecv)r7   nbytesrD   ancdataflags_s         r(   rW   zDBusConnection._read_data   s     ??[[..0F:< 040C0CLN1 +'gua wt{{L!<<"#KLL44W=== ;< 4![[--d3348O+  448OsY   1D(C9C7	C9%A"DD&D'D+D7C99D>DDD
Dc                 F    | j                   j                          d | _        y rO   )r.   closer6   r7   s    r(   rb   zDBusConnection._close   s    !%r9   c                 ,   K   | j                          yw)zClose the D-Bus connectionN)rb   rl   s    r(   aclosezDBusConnection.aclose   s     s   c                `  K   t        j                         4 d{   }t        |       }|j                  |       d{    	 | |j	                          d{    ddd      d{    y7 W7 57 # |j	                          d{  7   w xY w7 )# 1 d{  7  sw Y   yxY ww)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-   rn   )r7   nurseryrouters      r(   rs   zDBusConnection.router   s      $$& 	& 	&'%F,,w'''&mmo%%	& 	& 	&' &fmmo%%	& 	& 	& 	&s   B.A3B. BA5 BA9
BA7B"B.-B.B.5B7B9BB
BBB.B+B" B+'B.)F)r   )__name__
__module____qualname____doc__r8   r   rE   bytesrC   rI   rH   r\   rW   rb   rn   r   rs    r9   r(   r+   r+   ?   sd    & 6: -' -7U 7&* -w -"&
 & &r9   r+   Fr/   rT   c                  K   t        |       }t        j                  |       d{   }t        |      }|D ]B  }|j	                  |       d{    |j                  |j                          d{          D |j	                  t               d{    t        |j                  |      }|j                         4 d{   }|j                  t        j                                d{   }|j                  d   |_        ddd      d{    |S 7 7 7 7 7 ]7 47 # 1 d{  7  sw Y   |S xY ww)zHOpen a plain D-Bus connection

    :return: :class:`DBusConnection`
    Nrz   r   )r   r#   open_unix_socketr
   send_allfeedreceive_somer   r+   r.   rs   send_and_get_replyr   Hellobodyr2   )	busr/   bus_addrsockauthrreq_dataconnrs   replys	            r(   r   r      s    
 s|H%)%:%:8%DDD Z0E .mmH%%%

**,,-. --
$++*=D {{} ) )//0A0A0CDD ::a=) ) K#  E
 	&,)D) ) ) ) Ks   $E D)E D"E 3D 
4"E D"/E D$E 
'D*1D&2D*
E D(E E  E "E $E &D*(E *D=0D31D=8E c                   F     e Zd Zdef fdZed        Zd Zd Zd Z	 xZ
S )TrioFilterHandlefiltersc                 6    t         |   |||       || _        y rO   )superr8   send_channel)r7   r   rulesend_chnrecv_chn	__class__s        r(   r8   zTrioFilterHandle.__init__   s    $1$r9   c                     | j                   S rO   queuerl   s    r(   receive_channelz TrioFilterHandle.receive_channel   s    zzr9   c                 t   K   | j                          | j                  j                          d {    y 7 wrO   )rk   r   rn   rl   s    r(   rn   zTrioFilterHandle.aclose   s'     

&&(((s   .868c                 "   K   | j                   S wrO   r   rl   s    r(   
__aenter__zTrioFilterHandle.__aenter__   s     zzs   c                 @   K   | j                          d {    y 7 wrO   )rn   )r7   exc_typeexc_valexc_tbs       r(   	__aexit__zTrioFilterHandle.__aexit__   s     kkms   )rt   ru   rv   r   r8   propertyr   rn   r   r   __classcell__r   s   @r(   r   r      s2    % %  )r9   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)Futurez4A very simple Future for trio based on `trio.Event`.c                 D    d | _         t        j                         | _        y rO   )_outcomer#   Event_eventrl   s    r(   r8   zFuture.__init__   s    jjlr9   c                 X    t        |      | _        | j                  j                          y rO   )r   r   r   set)r7   results     r(   
set_resultzFuture.set_result   s    fr9   c                 X    t        |      | _        | j                  j                          y rO   )r   r   r   r   )r7   r'   s     r(   set_exceptionzFuture.set_exception   s    c
r9   c                    K   | j                   j                          d {    | j                  j                         S 7 wrO   )r   waitr   unwraprl   s    r(   getz
Future.get   s4     kk   }}##%% 	!s   A?AN)rt   ru   rv   rw   r8   r   r   r   ry   r9   r(   r   r      s    >#&r9   r   c                       e Zd ZdZdZdZdefdZed        Z	dddZ
defd	Zdd
ddeej                     fdZdej"                  fdZd ZdefdZej*                  fdZy)rq   zA client D-Bus connection which can wait for replies.

    This runs a separate receiver task and dispatches received messages.
    Nr   c                 N    || _         t               | _        t               | _        y rO   )_connr   _repliesr   _filters)r7   r   s     r(   r8   zDBusRouter.__init__  s    
$&(r9   c                 .    | j                   j                  S rO   )r   r2   rl   s    r(   r2   zDBusRouter.unique_name  s    zz%%%r9   r:   c                Z   K   | j                   j                  ||       d{    y7 w)z/Send a message, don't wait for a reply
        r:   N)r   rE   )r7   r<   r;   s      r(   rE   zDBusRouter.send  s"      jjoogfo555s   !+)+rT   c                 n  K   t        |       | j                  t        d      t        | j                  j
                        }| j                  j                  |t                     5 }| j                  ||       d{    |j                          d{   cddd       S 7 %7 # 1 sw Y   yxY ww)zSend a method call message and wait for the reply

        Returns the reply message (method return or error message type).
        NzThis DBusRouter has stoppedr:   )r   _rcv_cancel_scoper   r@   r   r1   r   catchr   rE   r   )r7   r<   r;   	reply_futs       r(   r   zDBusRouter.send_and_get_reply  s     
 	 !!)<==djj001]]  2 	+i))GF)333#--/)	+ 	+3)	+ 	+sB   A&B5(B)?B% B)B'B)
B5%B)'B))B2.B5r   )channelbufsizer   c                l    |t        j                  |      \  }}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   )r7   r   r   r   recv_channels        r(   filterzDBusRouter.filter#  s8    * ?$($<$<W$E!G\LtWlKKr9   rr   c                    K   | j                   t        d      |j                  | j                         d {   | _         y 7 
w)Nz+DBusRouter receiver task is already running)r   rc   r-   	_receiver)r7   rr   s     r(   r-   zDBusRouter.start@  s9     !!-LMM'.}}T^^'D!D!Ds   6AAAc                    K   | j                   !| j                   j                          d| _         t        j                  d       d{    y7 w)z Stop the sender & receiver tasksNr   )r   cancelr#   sleeprl   s    r(   rn   zDBusRouter.acloseE  sA      !!-""))+%)D" jjms   AAA	ArZ   c                     | j                   j                  |      ry| j                  j                  |      D ]  }	 |j                  j                  |         y# t        j                  $ r Y 7w xY w)zHandle one received messageN)r   dispatchr   matchesr   send_nowaitr#   
WouldBlock)r7   rZ   r   s      r(   	_dispatchzDBusRouter._dispatchR  sf    ==!!#&mm++C0 	F##//4	 ?? s   AA0/A0c           	      4  K   t        j                         5 }d| _        |j                  |       	 	 | j                  j                          d{   }| j                  |       47 # d| _        | j                  j                          t        j                  d      5 }| j                  j                  j                         D ],  }d|_        |j                  j                          d{  7   . 	 ddd       w # 1 sw Y   w xY wxY w# 1 sw Y   yxY ww)z'Receiver loop - runs in a separate taskTNF   )r#   CancelScope
is_runningstartedr   r\   r   r   drop_allmove_on_afterr   r   valuesshieldr   rn   )r7   task_statuscscoperZ   cleanup_scoper   s         r(   r   zDBusRouter._receiver]  s      	;6"DO'; $

 2 2 44CNN3' 4 #(&&( ''* ;m"&--"7"7">">"@ ;/3,$1188:::;; ; ;	; 	;sX   DDA(A&A((7D	AC=	+C.,C=	4	D	=DD		DDD)rt   ru   rv   rw   _nursery_mgrr   r+   r8   r   r2   rE   r   r   r   r#   MemorySendChannelr   Nurseryr-   rn   r   TASK_STATUS_IGNOREDr   ry   r9   r(   rq   rq      s     L)^ )
 & & -1 6
+7 + IMVW Lx0F0F'G L:E4<< E
		W 	 +/*B*B ;r9   rq   c                   (     e Zd ZdZ fdZd Z x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                 h    t         |   |       t        |t              st	        d      || _        y )Nz)Proxy can only be used with DBusRequester)r   r8   
isinstancerq   	TypeError_router)r7   msggenrs   r   s      r(   r8   zProxy.__init__~  s-     &*-GHHr9   c                       fd}|S )Nc                     K    | i |}|j                   j                  t        j                  u sJ j                  j                  |       d {   }t        |      S 7 wrO   )headermessage_typer   method_callr   r   r   )argskwargsrZ   r   make_msgr7   s       r(   innerz!Proxy._method_call.<locals>.inner  s[     D+F+C::**k.E.EEEE,,99#>>Ee$$ ?s   AA$A"A$ry   )r7   r   r   s   `` r(   _method_callzProxy._method_call  s    	% r9   )rt   ru   rv   rw   r8   r   r   r   s   @r(   r   r   s  s    	r9   r   c               0  K   t        | |       d{   }|4 d{    |j                         4 d{   }| ddd      d{    ddd      d{    y7 N7 E7 .7 # 1 d{  7  sw Y   +xY w7 "# 1 d{  7  sw Y   yxY ww)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:
                ...
    rz   N)r   rs   )r   r/   r   rtrs       r(   r   r     s     & &cjAAD  ;;= 	 	CI	 	   B	 	 	 	 	   s   BA"
BA$BBA&BA*BA(BBA?B$B&B(B*A<	0A31A<	8B?BBB
BB)SESSION)5rA   
contextlibr   r    	itertoolsr   loggingtypingr   r   ImportErrorasync_generator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   	getLoggerrt   log__all__r)   r+   r   r   r   rq   r   r   ry   r9   r(   <module>r     s     %    4. !   -  4 : : 2 ,  g!& 
 
{&W {&|E n 4| (& &&r; r;jI 6   K  434s   C C,+C,