o
    b,                     @   s   d Z ddlmZmZmZmZ ddlmZmZ G dd deZ	G dd deZ
G dd	 d	eZG d
d deZG dd deZG dd deZG dd deZdS )z
Tests for L{twisted.internet.defer.inlineCallbacks}.

Some tests for inlineCallbacks are defined in L{twisted.test.test_defgen} as
well.
    )CancelledErrorDeferredinlineCallbacksreturnValue)SynchronousTestCaseTestCasec                   @      e Zd ZdZdd ZdS )StopIterationReturnTestsz
    On Python 3.4 and newer generator functions may use the C{return} statement
    with a value, which is attached to the L{StopIteration} exception that is
    raised.

    L{inlineCallbacks} will use this value when it fires the C{callback}.
    c                 C   sD   dt i}td| t }|d |}|d | | |d dS )z
        If the C{return} statement has a value it is propagated back to the
        L{Deferred} that the C{inlineCallbacks} function returned.
        r   z>
@inlineCallbacks
def f(d):
    yield d
    return 14
        fN   )r   execr   callbackassertEqualsuccessResultOf)selfenvirond1d2 r   E/usr/lib/python3/dist-packages/twisted/internet/test/test_inlinecb.pytest_returnWithValue   s   	
z-StopIterationReturnTests.test_returnWithValueN)__name__
__module____qualname____doc__r   r   r   r   r   r	      s    r	   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )NonLocalExitTestsa  
    It's possible for L{returnValue} to be (accidentally) invoked at a stack
    level below the L{inlineCallbacks}-decorated function which it is exiting.
    If this happens, L{returnValue} should report useful errors.

    If L{returnValue} is invoked from a function not decorated by
    L{inlineCallbacks}, it will emit a warning if it causes an
    L{inlineCallbacks} function further up the stack to exit.
    c                 C   s   t d dS )z
        This method mistakenly invokes L{returnValue}, despite the fact that it
        is not decorated with L{inlineCallbacks}.
           N)r   r   r   r   r   mistakenMethod?   s   z NonLocalExitTests.mistakenMethodc                 C   sZ   |  |dg | j| jgd}|  t|d |  |d d t |  |d d d dS )ac  
        Flush the current warnings and assert that we have been told that
        C{mistakenMethod} was invoked, and that the result from the Deferred
        that was fired (appended to the given list) is C{mistakenMethod}'s
        result.  The warning should indicate that an inlineCallbacks function
        called 'inline' was made to exit.
        r   )offendingFunctionsr   categorymessagezreturnValue() in 'mistakenMethod' causing 'inline' to exit: returnValue should only be invoked by functions decorated with inlineCallbacksN)r   flushWarningsr   lenDeprecationWarning)r   
resultListwarningsr   r   r   assertMistakenMethodWarningF   s   
z-NonLocalExitTests.assertMistakenMethodWarningc                    s4   t  fdd}| }g }||j  | dS )z
        L{returnValue} will emit a non-local exit warning in the simplest case,
        where the offending function is invoked immediately.
        c                   3   s        td dV  d S )N   r   r   r   r   r   r   r   inline_   s   
zANonLocalExitTests.test_returnValueNonLocalWarning.<locals>.inlineN)r   addCallbackappendr'   )r   r*   dresultsr   r   r   test_returnValueNonLocalWarningY   s   z1NonLocalExitTests.test_returnValueNonLocalWarningc                    sR   t   t fdd}| }g }||j |g   d | dS )z
        L{returnValue} will emit a non-local warning in the case where the
        L{inlineCallbacks}-decorated function has already yielded a Deferred
        and therefore moved its generator function along.
        c                   3   s     V     td d S )Nr(   r)   r   causer   r   r   r*   r   s   zBNonLocalExitTests.test_returnValueNonLocalDeferred.<locals>.inliner   N)r   r   r+   r,   r   r   r'   )r   r*   effectr.   r   r0   r    test_returnValueNonLocalDeferredj   s   
z2NonLocalExitTests.test_returnValueNonLocalDeferredN)r   r   r   r   r   r'   r/   r3   r   r   r   r   r   4   s    
r   c                   @   s   e Zd Zdd Zdd ZdS )ForwardTraceBackTestsc                    s\   t dd  t  fdd}| }| |}| }| d| | d| | d| dS )	z
        Chained inlineCallbacks are forwarding the traceback information
        from generator to generator.

        A first simple test with a couple of inline callbacks.
        c                   s       dV  t dNzforcing generatorError Marker	Exceptionr   r   r   r   erroring      z>ForwardTraceBackTests.test_forwardTracebacks.<locals>.erroringc                   3         V  d S Nr   r   r:   r   r   calling      z=ForwardTraceBackTests.test_forwardTracebacks.<locals>.callingin erroring
in callingr7   N)r   failureResultOfgetTracebackassertInr   r?   r-   r
   tbr   r>   r   test_forwardTracebacks   s   

z,ForwardTraceBackTests.test_forwardTracebacksc                    s   t dd t fddt fdd t  fdd}| }| |}| }| d	| | d
| | d| | d| | d| | d| | d	|  dS )a  
        Several Chained inlineCallbacks gives information about all generators.

        A wider test with a 4 chained inline callbacks.

        Application stack-trace should be reported, and implementation details
        like "throwExceptionIntoGenerator" symbols are omitted from the stack.

        Note that the previous test is testing the simple case, and this one is
        testing the deep recursion case.

        That case needs specific code in failure.py to accomodate to stack
        breakage introduced by throwExceptionIntoGenerator.

        Hence we keep the two tests in order to sort out which code we
        might have regression in.
        c                   s   r5   r6   r8   r   r   r   r   r:      r;   zDForwardTraceBackTests.test_forwardLotsOfTracebacks.<locals>.erroringc                   3   r<   r=   r   r   r>   r   r   calling3   r@   zDForwardTraceBackTests.test_forwardLotsOfTracebacks.<locals>.calling3c                   3   r<   r=   r   r   )rI   r   r   calling2   r@   zDForwardTraceBackTests.test_forwardLotsOfTracebacks.<locals>.calling2c                   3   r<   r=   r   r   )rJ   r   r   r?      r@   zCForwardTraceBackTests.test_forwardLotsOfTracebacks.<locals>.callingrA   rB   zin calling2zin calling3throwExceptionIntoGeneratorr7   N)r   rC   rD   rE   assertNotInrF   r   )rJ   rI   r:   r   test_forwardLotsOfTracebacks   s$   

z2ForwardTraceBackTests.test_forwardLotsOfTracebacksN)r   r   r   rH   rM   r   r   r   r   r4      s    r4   c                   @      e Zd ZdZdS )UntranslatedErrorzL
    Untranslated exception type when testing an exception translation.
    Nr   r   r   r   r   r   r   r   rO          rO   c                   @   rN   )TranslatedErrorzJ
    Translated exception type when testing an exception translation.
    NrP   r   r   r   r   rR      rQ   rR   c                   @   r   )DontFailz 
    Sample exception type.
    c                 C   s   t |  || _d S r=   )r9   __init__actualValue)r   actualr   r   r   rT      s   

zDontFail.__init__N)r   r   r   r   rT   r   r   r   r   rS      s    rS   c                   @   sh   e Zd ZdZdd Zdd ZedddZd	d
 ZdddZ	dd Z
dd Zdd Zdd Zdd ZdS )CancellationTestsa!  
    Tests for cancellation of L{Deferred}s returned by L{inlineCallbacks}.
    For each of these tests, let:
        - C{G} be a generator decorated with C{inlineCallbacks}
        - C{D} be a L{Deferred} returned by C{G}
        - C{C} be a L{Deferred} awaited by C{G} with C{yield}
    c                 C   s
   g | _ dS )z>
        Set up the list of outstanding L{Deferred}s.
        N)deferredsOutstandingr   r   r   r   setUp   s   
zCancellationTests.setUpc                 C   s   | j r|   | j sdS dS )zG
        If any L{Deferred}s are still outstanding, fire them.
        N)rX   deferredGottenr   r   r   r   tearDown   s   zCancellationTests.tearDownNc              
   c   sn    |du r| j }z| V }W n  ty   t  ty. } z|jd }W Y d}~nd}~ww t|d  dS )z
        Generator for testing cascade cancelling cases.

        @param getChildDeferred: Some callable returning L{Deferred} that we
            awaiting (with C{yield})
        Nr(   r   )getDeferredrO   rR   rS   rU   r   )r   getChildDeferredxdfr   r   r   sampleInlineCB   s   z CancellationTests.sampleInlineCBc                 C   s   | j t  | j d S )z
        A sample function that returns a L{Deferred} that can be fired on
        demand, by L{CancellationTests.deferredGotten}.

        @return: L{Deferred} that can be fired on demand.
        )rX   r,   r   r   r   r   r   r\     s   
zCancellationTests.getDeferredc                 C   s   | j d| dS )z
        Fire the L{Deferred} returned from the least-recent call to
        L{CancellationTests.getDeferred}.

        @param result: result object to be used when firing the L{Deferred}.
        r   N)rX   popr   )r   resultr   r   r   rZ     s   z CancellationTests.deferredGottenc                    sJ   dg  fdd}| j |d}|dd  |  |  d td d	S )
zN
        When C{D} cancelled, C{C} will be immediately cancelled too.
        FAILUREc                     s    t  }  fdd}| | | S )Nc                    s   |  t d< | S )Nr   )checkr   rc   childResultHolderr   r   _eb#  s   zWCancellationTests.test_cascadeCancellingOnCancel.<locals>.getChildDeferred.<locals>._ebr   
addErrback)r-   ri   rg   r   r   r]      s   
zJCancellationTests.test_cascadeCancellingOnCancel.<locals>.getChildDeferredr]   c                 S   s   d S r=   r   rf   r   r   r   <lambda>+      zBCancellationTests.test_cascadeCancellingOnCancel.<locals>.<lambda>r   zno cascade cancelling occursN)r`   rk   cancelr   r   )r   r]   r-   r   rg   r   test_cascadeCancellingOnCancel  s   
z0CancellationTests.test_cascadeCancellingOnCancelc                 C   s(   |   }|  | t| |j dS )zg
        When C{D} cancelled, CancelledError from C{C} will be errbacked
        through C{D}.
        N)r`   ro   assertRaisesr   rC   raiseException)r   r-   r   r   r   "test_errbackCancelledErrorOnCancel3  s   
z4CancellationTests.test_errbackCancelledErrorOnCancelc                    sB   dd }t | |  fdd}|  | t| |j dS )z
        When C{D} is cancelled, and C raises a particular type of error, C{G}
        may catch that error at the point of yielding and translate it into
        a different error which may be received by application code.
        c                 S   s   |  t  d S r=   )errbackrO   itr   r   r   ro   F  s   z>CancellationTests.test_errorToErrorTranslation.<locals>.cancelc                          S r=   r   r   ar   r   rm   J  rn   z@CancellationTests.test_errorToErrorTranslation.<locals>.<lambda>N)r   r`   ro   rq   rR   rC   rr   )r   ro   r-   r   rx   r   test_errorToErrorTranslation?  s   
z.CancellationTests.test_errorToErrorTranslationc                    sL   dd }t | |  fdd}g }||j |  | |dg dS )z
        When C{D} is cancelled, and C{C} raises a particular type of error,
        C{G} may catch that error at the point of yielding and translate it
        into a result value which may be received by application code.
        c                 S   s   |  td d S )Ni  )rt   rS   ru   r   r   r   ro   X  s   z@CancellationTests.test_errorToSuccessTranslation.<locals>.cancelc                      rw   r=   r   r   rx   r   r   rm   \  rn   zBCancellationTests.test_errorToSuccessTranslation.<locals>.<lambda>i  N)r   r`   r+   r,   ro   assertEquals)r   ro   r-   r.   r   rx   r   test_errorToSuccessTranslationQ  s   z0CancellationTests.test_errorToSuccessTranslationc                    s\   t  fdd  fdd}| j|d}|  | | d | | |d dS )	a"  
        When C{D} is cancelled, it won't reach the callbacks added to it by
        application code until C{C} reaches the point in its callback chain
        where C{G} awaits it.  Otherwise, application code won't be able to
        track resource usage that C{D} may be using.
        c                    s   |  t  S r=   )trapr   rf   )moreDeferredr   r   deferMeMorek  s   
zDCancellationTests.test_asynchronousCancellation.<locals>.deferMeMorec                     s   t  } |   | S r=   rj   )r-   )r   r   r   deferMeo  s   
z@CancellationTests.test_asynchronousCancellation.<locals>.deferMerl   i  i  N)r   r`   ro   assertNoResultr   r   r   )r   r   r-   r   )r   r~   r   test_asynchronousCancellationb  s   

z/CancellationTests.test_asynchronousCancellationr=   )r   r   r   r   rY   r[   r   r`   r\   rZ   rp   rs   rz   r|   r   r   r   r   r   rW      s    

	rW   N)r   twisted.internet.deferr   r   r   r   twisted.trial.unittestr   r   r	   r   r4   r9   rO   rR   rS   rW   r   r   r   r   <module>   s   LI
