U
    ¸~Hjä  ã                   @   sÄ   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZ G dd„ dƒZG d	d
„ d
ƒZG dd„ dƒZG dd„ dƒZG dd„ deƒZeejƒG dd„ deƒƒZG dd„ dejƒZdd„ ZdS )z
Utility classes for spread.
é    )Úimplementer)ÚdeferÚ
interfaces)Úbasic)ÚFailure)Úpbc                   @   s   e Zd Zdd„ Zdd„ ZdS )ÚLocalMethodc                 C   s   || _ || _d S ©N)ÚlocalÚname)Úselfr
   r   © r   ú7/tmp/pip-unpacked-wheel-ewod1tgb/twisted/spread/util.pyÚ__init__   s    zLocalMethod.__init__c                 O   s   | j j| jf|ž|ŽS r	   )r
   Ú
callRemoter   )r   ÚargsÚkwr   r   r   Ú__call__   s    zLocalMethod.__call__N)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r   r      s   r   c                   @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )ÚLocalAsRemotezN
    A class useful for emulating the effects of remote behavior locally.
    é   c                 O   sz   t | d| ƒr"t| d| ƒ||ŽS z t| d| ƒ}t |||Ž¡W S  tk
rt   tƒ }| jrf| ¡  t |¡ Y S X dS )ax  
        Call a specially-designated local method.

        self.callRemote('x') will first try to invoke a method named
        sync_x and return its result (which should probably be a
        Deferred).  Second, it will look for a method called async_x,
        which will be called and then have its result (or Failure)
        automatically wrapped in a Deferred.
        Zsync_Zasync_N)	ÚhasattrÚgetattrr   ÚsucceedÚBaseExceptionr   ÚreportAllTracebacksZprintTracebackÚfail)r   r   r   r   ÚmethodÚfr   r   r   r   #   s    
zLocalAsRemote.callRemotec                 C   s
   t | |ƒS r	   )r   )r   r   r   r   r   ÚremoteMethod8   s    zLocalAsRemote.remoteMethodN)r   r   r   Ú__doc__r   r   r!   r   r   r   r   r      s   r   c                   @   s*   e Zd ZdZd
dd„Zdd„ Zdd„ Zd	S )ÚLocalAsyncForwarderzD
    A class useful for forwarding a locally-defined interface.
    r   c                 C   s$   |  |¡st‚|| _|| _|| _d S r	   )Z
providedByÚAssertionErrorÚ	forwardedÚinterfaceClassÚfailWhenNotImplemented)r   r%   r&   r'   r   r   r   r   A   s    zLocalAsyncForwarder.__init__c                 O   s   t | j|ƒ||ŽS r	   )r   r%   )r   r   r   r   r   r   r   Ú_callMethodG   s    zLocalAsyncForwarder._callMethodc                 O   sN   | j  |¡r&tj| j|f|ž|Ž}|S | jr@t ttd| ƒ¡S t 	d ¡S d S )NzNo Such Method in Interface: %s)
r&   ZqueryDescriptionForr   ZmaybeDeferredr(   r'   r   r   ÚNotImplementedErrorr   )r   r   r   r   Úresultr   r   r   r   J   s    ÿzLocalAsyncForwarder.callRemoteN)r   )r   r   r   r"   r   r(   r   r   r   r   r   r#   <   s   
r#   c                   @   s:   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )ÚPagerz5
    I am an object which pages out information.
    Nc                 O   s>   t |ƒr|| _|| _|| _nd| _d| _|| _|j | ¡ dS )zƒ
        Create a pager with a Reference to a remote collector and
        an optional callable to invoke upon completion.
        Nr   )ÚcallableÚcallbackÚcallbackArgsÚcallbackKeywordÚ_stillPagingÚ	collectorZbrokerZregisterPageProducer)r   r1   r-   r   r   r   r   r   r   [   s    zPager.__init__c                 C   s6   | j s0| jjddd� | jdk	r0| j| j| jŽ | j S )ú5
        (internal) Method called by Broker.
        ZendedPagingF©ZpbanswerN)r0   r1   r   r-   r.   r/   ©r   r   r   r   ÚstillPagingj   s
    
zPager.stillPagingc                 C   s   | j jd|  ¡ dd� dS )r2   ÚgotPageFr3   N)r1   r   ÚnextPager4   r   r   r   ÚsendNextPaget   s    zPager.sendNextPagec                 C   s
   t ƒ ‚dS )zO
        Override this to return an object to be sent to my collector.
        N)r)   r4   r   r   r   r7   z   s    zPager.nextPagec                 C   s
   d| _ dS )z4
        Call this when you're done paging.
        r   N)r0   r4   r   r   r   Ú
stopPaging€   s    zPager.stopPaging)N)	r   r   r   r"   r   r5   r8   r7   r9   r   r   r   r   r+   V   s   

r+   c                   @   s"   e Zd ZdZddd„Zdd„ ZdS )	ÚStringPagerz:
    A simple pager that splits a string into chunks.
    é    Nc                 O   s,   || _ d| _|| _tj| ||f|ž|Ž d S )Nr   )ÚstringÚpointerÚ	chunkSizer+   r   )r   r1   Ústr>   r-   r   r   r   r   r   r   Œ   s    zStringPager.__init__c                 C   sD   | j | j| j| j … }|  j| j7  _| jt| j ƒkr@|  ¡  |S r	   )r<   r=   r>   Úlenr9   ©r   Úvalr   r   r   r7   ’   s
    zStringPager.nextPage)r;   N)r   r   r   r"   r   r7   r   r   r   r   r:   ‡   s   
r:   c                   @   sB   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dS )Ú	FilePagerzC
    Reads a file in chunks and sends the chunks as they come.
    Nc                 O   s*   g | _ tj| ||f|ž|Ž |  |¡ d S r	   )Úchunksr+   r   ÚstartProducing)r   r1   Úfdr-   r   r   r   r   r   r       s    zFilePager.__init__c                    s*   t  ¡  |ˆ ¡ˆ _ˆ j ‡ fdd„¡ d S )Nc                    s   ˆ   ¡ S r	   )r9   )Úxr4   r   r   Ú<lambda>§   ó    z*FilePager.startProducing.<locals>.<lambda>)r   Z
FileSenderZbeginFileTransferÚdeferredZaddBoth)r   rF   r   r4   r   rE   ¥   s    zFilePager.startProducingc                 C   s   || _ |s| j  ¡  d S r	   )ÚproducerÚresumeProducing)r   rK   Z	streamingr   r   r   ÚregisterProducer©   s    zFilePager.registerProducerc                 C   s
   d | _ d S r	   )rK   r4   r   r   r   ÚunregisterProducer®   s    zFilePager.unregisterProducerc                 C   s   | j  |¡ d S r	   )rD   Úappend)r   Úchunkr   r   r   Úwrite±   s    zFilePager.writec                 C   s6   | j s
dS | j  d¡}| j ¡  | jjd|dd� dS )zD
        Get the first chunk read and send it to collector.
        Nr   r6   Fr3   )rD   ÚpoprK   rL   r1   r   rA   r   r   r   r8   ´   s
    
zFilePager.sendNextPage)N)
r   r   r   r"   r   rE   rM   rN   rQ   r8   r   r   r   r   rC   š   s   
rC   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚCallbackPageCollectorzµ
    I receive pages from the peer. You may instantiate a Pager with a
    remote reference to me. I will call the callback with a list of pages
    once they are all received.
    c                 C   s   g | _ || _d S r	   )Úpagesr-   )r   r-   r   r   r   r   Ç   s    zCallbackPageCollector.__init__c                 C   s   | j  |¡ d S r	   )rT   rO   )r   Úpager   r   r   Úremote_gotPageË   s    z$CallbackPageCollector.remote_gotPagec                 C   s   |   | j¡ d S r	   )r-   rT   r4   r   r   r   Úremote_endedPagingÎ   s    z(CallbackPageCollector.remote_endedPagingN)r   r   r   r"   r   rV   rW   r   r   r   r   rS   À   s   rS   c                 O   s&   t  ¡ }| j|t|jƒf|ž|Ž |S )zr
    A utility method that will call a remote method which expects a
    PageCollector as the first argument.
    )r   ZDeferredr   rS   r-   )ZreferenceableÚ
methodNamer   r   Údr   r   r   ÚgetAllPagesÒ   s    rZ   N)r"   Zzope.interfacer   Ztwisted.internetr   r   Ztwisted.protocolsr   Ztwisted.python.failurer   Ztwisted.spreadr   r   r   r#   r+   r:   Z	IConsumerrC   ZReferenceablerS   rZ   r   r   r   r   Ú<module>   s   	 1%