o `.@sdZddlZddlmZddlmZddlZddlmZddl Z ddl m Z m Z ddl Z ddlZddlmZddlmZmZmZmZdd lmZmZdd lmZdd lmZmZdd lmZm Z dd l!m"Z"ddl#m$Z$ddl%m&Z&m'Z'm(Z(gdZ)GdddZ*ddZ+ddZ,GdddZ-Gddde-Z.GdddeZ/ddZ0d+d"e j fd#d$Z1 &d,d"e.fd'd(Z2e3d)kre2Z4e5d*e4j6dSdS)-z'Synchronous IO wrappers around jeepney N)deque) ECONNRESET)count)DefaultSelector EVENT_READ)Optional)ParserMessage MessageType HeaderFields) AuthenticatorBEGIN)get_bus)FileDescriptor fds_buf_size) ProxyBase unwrap_msg)Router) message_bus)MessageFilters FilterHandlecheck_replyable)open_dbus_connectionDBusConnectionProxyc@s4eZdZddZddZddZddZd d Zd S) _FuturecCs d|_dSN_resultselfr"5/usr/lib/python3/dist-packages/jeepney/io/blocking.py__init__ z_Future.__init__cCs t|jSr)boolrr r"r"r#done"r%z _Future.donecCd|f|_dSNFr)r! exceptionr"r"r# set_exception%z_Future.set_exceptioncCr()NTr)r!resultr"r"r# set_result(r,z_Future.set_resultcCs|j\}}|r |S|rr)r!successvaluer"r"r#r-+s z_Future.resultN)__name__ __module__ __qualname__r$r'r+r.r-r"r"r"r#rs  rcCs|dur t|SdSr)time monotonictimeoutr"r"r#timeout_to_deadline2s r8cCs|dur t|tdSdS)Ng)maxr4r5)deadliner"r"r#deadline_to_timeout7sr;c@sxeZdZdZddejfddZddZdd Zd ed e e e j ffd d Z ddZ ddZdddZddZddZdS)DBusConnectionBasez8Connection machinery shared by this module and threadingFsockcCsB||_||_t|_tdd|_t|_|j|t |_ d|_ dS)Nr)start) r= enable_fdsrparserroutgoing_serialrselectorregisterr select_key unique_name)r!r=r?r"r"r#r$?s  zDBusConnectionBase.__init__cCs|Srr"r r"r"r# __enter__HszDBusConnectionBase.__enter__cCs |dSr))close)r!exc_typeexc_valexc_tbr"r"r#__exit__KszDBusConnectionBase.__exit__messagereturncCs<|dur t|j}|jrtdnd}|j||d}||fS)Ni)serialfds)nextrAr?array serialise)r!rLrOrPdatar"r"r# _serialiseOs  zDBusConnectionBase._serialisecCsD|j|gtjtj|fg}|t|kr |j||ddSdSr)r=sendmsgsocket SOL_SOCKET SCM_RIGHTSlensendall)r!rTrP bytes_sentr"r"r#_send_with_fdsVs  z!DBusConnectionBase._send_with_fdscCs> |j}|dur |S|jt|d\}}|jj||dq)NTr6)rP)r@get_next_message_read_some_datar;add_data)r!r:msgbrPr"r"r#_receive_s zDBusConnectionBase._receiveNcCsN|j|D]\}}||jkr$|jr|St|jdgfSqt)Ni) rBselectrDr?_read_with_fds unwrap_readr=recv TimeoutError)r!r7keyevr"r"r#r_hs  z"DBusConnectionBase._read_some_datacCsT|j}|j|t\}}}}|ttdd@r!|tdt |t |fS)N MSG_CTRUNCrz&Unable to receive all file descriptors) r@ bytes_desiredr=recvmsgrgetattrrWrG RuntimeErrorrfr from_ancdata)r!nbytesrTancdataflags_r"r"r#rers z!DBusConnectionBase._read_with_fdscCs|j|jdS)zClose the connectionN)rBrGr=r r"r"r#rGzs zDBusConnectionBase.closeFr)r1r2r3__doc__rWr$rFrKr bytesrrRrUr]rcr_rerGr"r"r"r#r<=s   r<cseZdZddejffdd ZddefddZeZdd d efd d Zdd d dZ dddddZ dddde e fddZ dd d efddZZS)rFr=csJt||d|_tt|_t|_tt ||_ |j }|d|_ dS)NFr) superr$ _unwrap_replyrrrouterr_filtersrr bus_proxyHellorE)r!r=r? hello_reply __class__r"r#r$s   zDBusConnection.__init__NrLcCs4|||\}}|r|||dS|j|dS)z.Serialise and send a :class:`~.Message` objectN)rUr]r=r[)r!rLrOrTrPr"r"r#sendszDBusConnection.sendr6rMcCs|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. )rcr8)r!r7r"r"r#receiveszDBusConnection.receivecCs:|j|d}|j||j|D]}|j|qdS)z\Receive one message and apply filters See :meth:`filter`. Returns nothing. r6N)rrzincomingr{matchesqueueappend)r!r7rafilterr"r"r# recv_messagess  zDBusConnection.recv_messagesr7unwrapc Cst|t|}|dur|j}t|j}|j||d |jt|d}|jj t j d}||kr9|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)rOTr6)rr8ryrQrA send_messagerr;headerfieldsgetr reply_serialrrzrr{rrr) r!rLr7rr:rOmsg_inreply_torr"r"r#send_and_get_replys"  z!DBusConnection.send_and_get_replyr)rbufsizercCs |dur t|d}t|j||S)aCreate 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)rrr{)r!rulerrr"r"r#rs zDBusConnection.filtercCs8t|}t|dkr|jt|dt|dks |S)aZProcess 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 rr6)r8rZrr;popleft)r!rr7r:r"r"r#recv_until_filtereds   z"DBusConnection.recv_until_filteredrur)r1r2r3rWr$r rrrrrrrrr __classcell__r"r"rr#rs   rcs6eZdZdZddfdd ZddZdd ZZS) rajA 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 Nr6cst|||_||_dSr)rxr$ _connection_timeout)r!msggen connectionr7rr"r#r$s  zProxy.__init__cCs4|jdurdnd|j}d|jd|j|dS)Nz , timeout=zProxy(z, ))r_msggenr)r!extrar"r"r#__repr__szProxy.__repr__cstfdd}|S)Ncs@|dj}|i|}|jjtjusJjj||ddS)NrTr)poprr message_typer method_callrr)argskwargsr7ramake_msgr!r"r#inner s z!Proxy._method_call..inner) functoolswraps)r!rrr"rr# _method_callszProxy._method_call)r1r2r3rvr$rrrr"r"rr#rs rcCs|s tttt|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. )ConnectionResetErrorrosstrerror)rbr"r"r#rfsrfF@rMc stjtjdt|fdd}z)|j|t|d}|D]}|j||t|jdq |jt Wn!tj yU}z  t d|d|d}~w  dS) z=Create a socket and authenticate ready to send D-Bus messages)familycst||Sr) settimeoutr;)methrr:r=r"r#with_sock_deadline(sz'prep_socket..with_sock_deadline)r?izDid not authenticate in z secondsN)rWAF_UNIXr8connectr r[feedrfrgr r7rGrhr)addrr?r7rauthrreq_dataer"rr# prep_socket s&    rSESSION?cCs$t|}t|||d}t||}|S)aConnect 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)rrr)busr? auth_timeoutbus_addrr=connr"r"r#r>s r__main__z Unique name:)Fr)rFr)7rvrR collectionsrerrnorr itertoolsrr selectorsrrrWr4typingrjeepneyrr r r jeepney.authr r jeepney.busr jeepney.fdsrrjeepney.wrappersrrjeepney.routingrjeepney.bus_messagesrcommonrrr__all__rr8r;r<rrrfrrr1rprintrEr"r"r"r#sH       Cm(