U
    n5{ip8  ã                   @   s   d Z ddlZddlmZmZmZmZmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZ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 ddlmZ ddl m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z)m*Z*m+Z+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8m9Z9 edd�G dd„ de:ƒƒZ;G dd„ deƒZ<G dd„ deƒZ=e
d ƒZ>ee=gee> f Z?G d!d"„ d"e!ƒZ@G d#d$„ d$e!ƒZAeeƒG d%d&„ d&ƒƒZBeeƒG d'd(„ d(ƒƒZCG d)d*„ d*e:ƒZDG d+d,„ d,eƒZEdS )-z:
This module implements the worker classes.

@since: 12.3
é    N)ÚAnyÚ	AwaitableÚCallableÚDictÚListÚOptionalÚTextIOÚTypeVar)ÚTestCase)Úimplementer)Úfrozen)ÚProtocolÚ	TypedDict)ÚDeferredÚDeferredList)ÚProcessDone)ÚIAddressÚ
ITransport)ÚProcessProtocol)ÚLogger)ÚAMP)ÚFailure)ÚFilePath)ÚnamedObject)Ú_WORKER_AMP_STDINÚ_WORKER_AMP_STDOUTÚmanagercommandsÚworkercommands)ÚWorkerReporter)Ú
TestResult)Ú
TestLoaderÚ
TrialSuite)ÚTodoé   )Ú
StreamOpenÚStreamReceiverÚStreamWriteF)Zauto_excc                   @   s   e Zd ZU dZeed< dS )ÚWorkerExceptionz‰
    An exception was reported by a test running in a worker process.

    @ivar message: An error message describing the exception.
    ÚmessageN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚstrÚ__annotations__© r/   r/   ú>/tmp/pip-unpacked-wheel-mnhg7r0q/twisted/trial/_dist/worker.pyr'   +   s   
r'   c                   @   s   e Zd ZU dZeed< dS )Ú	RunResultzB
    Represent the result of a L{workercommands.Run} command.
    ÚsuccessN)r)   r*   r+   r,   Úboolr.   r/   r/   r/   r0   r1   6   s   
r1   c                   @   s"   e Zd ZdZeeedœdd„ZdS )ÚWorkerz)
    An object that can run actions.
    )ÚcaseÚresultÚreturnc                 Ã   s   dS )z"
        Run a test case.
        Nr/   )Úselfr5   r6   r/   r/   r0   ÚrunC   s    z
Worker.runN)r)   r*   r+   r,   r
   r   r1   r9   r/   r/   r/   r0   r4   >   s   r4   Ú_Tc                   @   sH   e Zd ZdZeƒ Zddd„Zejj	e
edœdd„ƒZejj	dd	„ ƒZd
S )ÚWorkerProtocolz5
    The worker-side trial distributed protocol.
    Fc                 C   s   t ƒ | _t| ƒ| _|| _d S ©N)r    Ú_loaderr   Ú_resultÚ_forceGarbageCollection)r8   ZforceGarbageCollectionr/   r/   r0   Ú__init__T   s    
zWorkerProtocol.__init__)ÚtestCaser7   c              	   Ã   sº   | j  ¡ �,}| j |¡}t|g| jƒ}| | j ¡ W 5 Q R X d}t|dd�I dH D ]^\}}|r`qRd}| jj	d||d� z| j  
||¡I dH  W qR tk
r®   | j 	d¡ Y qRX qRd|iS )	z*
        Run a test case by name.
        T)ZconsumeErrorsNFz Result reporting for {id} failed)ÚfailureÚidz5Additionally, reporting the reporting failure failed.r2   )r>   ZgatherReportingResultsr=   Z
loadByNamer!   r?   r9   r   ÚloggerrB   ZaddErrorFallibleÚBaseException)r8   rA   Úresultsr5   ZsuiteZallSucceededr2   r6   r/   r/   r0   r9   Y   s0    üýÿzWorkerProtocol.runc                 C   s   t  |¡ ddiS )zb
        Set up the worker, moving into given directory for tests to run in
        them.
        r2   T)ÚosÚchdir)r8   Ú	directoryr/   r/   r0   Ústart†   s    
zWorkerProtocol.startN)F)r)   r*   r+   r,   r   rD   r@   r   ÚRunÚ	responderr-   r1   r9   ÚStartrJ   r/   r/   r/   r0   r;   M   s   
,r;   c                       s$  e Zd ZdZd"‡ fdd„	Zejdd„ ƒZejdd„ ƒZ	e
jjd	d
„ ƒZeeee edœdd„Ze
jjeeeeeeef dœdd„ƒZe
jjeeeeeeef dœdd„ƒZe
jjdd„ ƒZe
jjeeee eeef dœdd„ƒZe
jjdd„ ƒZe
j jdd„ ƒZ!e"e#e$dœdd„Z%d d!„ Z&‡  Z'S )#ÚLocalWorkerAMPz7
    Local implementation of the manager commands.
    Nc                    s   t ƒ  ||¡ tƒ | _d S r<   )Úsuperr@   r%   Ú_streams)r8   ZboxReceiverÚlocator©Ú	__class__r/   r0   r@   •   s    zLocalWorkerAMP.__init__c                 C   s   d| j  ¡ iS )NÚstreamId)rP   Úopen©r8   r/   r/   r0   Ú
streamOpen™   s    zLocalWorkerAMP.streamOpenc                 C   s   | j  ||¡ i S r<   )rP   Úwrite)r8   rT   Údatar/   r/   r0   ÚstreamWrite�   s    zLocalWorkerAMP.streamWritec                 C   s   | j  | j¡ ddiS )z0
        Add a success to the reporter.
        r2   T)r>   Ú
addSuccessÚ	_testCase)r8   ÚtestNamer/   r/   r0   r[   ¢   s    zLocalWorkerAMP.addSuccess)ÚerrorÚ
errorClassÚframesr7   c              	   C   sZ   t |ƒ}t||ƒ}tdt|ƒdƒD ]2}|j || ||d  t||d  ƒg g f¡ q"|S )a   
        Helper to build a C{Failure} with some traceback.

        @param error: An C{Exception} instance.

        @param errorClass: The class name of the C{error} class.

        @param frames: A flat list of strings representing the information need
            to approximatively rebuild C{Failure} frames.

        @return: A L{Failure} instance with enough information about a test
           error.
        r   é   r#   é   )r   r   ÚrangeÚlenr`   ÚappendÚint)r8   r^   r_   r`   Z	errorTyperB   Úir/   r/   r0   Ú_buildFailureª   s    
$ÿzLocalWorkerAMP._buildFailure)r]   r_   ÚerrorStreamIdÚframesStreamIdr7   c                 C   sX   d  | j |¡¡ d¡}dd„ | j |¡D ƒ}|  t|ƒ||¡}| j | j|¡ ddiS )a¯  
        Add an error to the reporter.

        @param errorStreamId: The identifier of a stream over which the text
            of this error was previously completely sent to the peer.

        @param framesStreamId: The identifier of a stream over which the lines
            of the traceback for this error were previously completely sent to
            the peer.

        @param error: A message describing the error.
        ó    úutf-8c                 S   s   g | ]}|  d ¡‘qS ©rl   ©Údecode©Ú.0Úframer/   r/   r0   Ú
<listcomp>Ú   s    z+LocalWorkerAMP.addError.<locals>.<listcomp>r2   T)	ÚjoinrP   Úfinishro   rh   r'   r>   ÚaddErrorr\   )r8   r]   r_   ri   rj   r^   r`   rB   r/   r/   r0   rv   Å   s    
ÿzLocalWorkerAMP.addError)r]   ÚfailStreamIdÚ	failClassrj   r7   c                 C   sX   d  | j |¡¡ d¡}dd„ | j |¡D ƒ}|  t|ƒ||¡}| j | j|¡ ddiS )az  
        Add a failure to the reporter.

        @param failStreamId: The identifier of a stream over which the text of
            this failure was previously completely sent to the peer.

        @param framesStreamId: The identifier of a stream over which the lines
            of the traceback for this error were previously completely sent to the
            peer.
        rk   rl   c                 S   s   g | ]}|  d ¡‘qS rm   rn   rp   r/   r/   r0   rs   ø   s    z-LocalWorkerAMP.addFailure.<locals>.<listcomp>r2   T)	rt   rP   ru   ro   rh   r'   r>   Ú
addFailurer\   )r8   r]   rw   rx   rj   Zfailr`   rB   r/   r/   r0   ry   å   s    
ÿzLocalWorkerAMP.addFailurec                 C   s   | j  | j|¡ ddiS )z-
        Add a skip to the reporter.
        r2   T)r>   ÚaddSkipr\   )r8   r]   Úreasonr/   r/   r0   rz      s    zLocalWorkerAMP.addSkip)r]   ri   Útodor7   c                 C   sF   d  | j |¡¡ d¡}t|dkr&dn|ƒ}| j | j||¡ ddiS )zÎ
        Add an expected failure to the reporter.

        @param errorStreamId: The identifier of a stream over which the text
            of this error was previously completely sent to the peer.
        rk   rl   Nz	<unknown>r2   T)rt   rP   ru   ro   r"   r>   ÚaddExpectedFailurer\   )r8   r]   ri   r|   r^   Z_todor/   r/   r0   r}     s    
z!LocalWorkerAMP.addExpectedFailurec                 C   s   | j  | j|¡ ddiS )z<
        Add an unexpected success to the reporter.
        r2   T)r>   ÚaddUnexpectedSuccessr\   )r8   r]   r|   r/   r/   r0   r~     s    z#LocalWorkerAMP.addUnexpectedSuccessc                 C   s"   | j  |d ¡ | j  ¡  ddiS )z4
        Print test output from the worker.
        Ú
r2   T)Ú_testStreamrX   Úflush)r8   Úoutr/   r/   r0   Ú	testWrite  s    
zLocalWorkerAMP.testWrite)rA   r6   r7   c              	   Ã   sN   || _ || _| j |¡ | ¡ }z| jtj|d�I dH W ¢S | j |¡ X dS )z
        Run a test.
        )rA   N)r\   r>   Z	startTestrC   ZstopTestÚ
callRemoter   rK   )r8   rA   r6   Z
testCaseIdr/   r/   r0   r9   (  s    zLocalWorkerAMP.runc                 C   s
   || _ dS )z?
        Set the stream used to log output from tests.
        N)r€   )r8   Ústreamr/   r/   r0   ÚsetTestStream5  s    zLocalWorkerAMP.setTestStream)NN)(r)   r*   r+   r,   r@   r$   rL   rW   r&   rZ   r   Z
AddSuccessr[   r'   r-   r   r   rh   ZAddErrorrf   r   r3   rv   Z
AddFailurery   ZAddSkiprz   ZAddExpectedFailurer   r}   ZAddUnexpectedSuccessr~   Z	TestWriterƒ   r
   r   r1   r9   r†   Ú__classcell__r/   r/   rR   r0   rN   �   sR   


	û
ú
ú
  
þ

rN   c                   @   s   e Zd ZdZdS )ÚLocalWorkerAddressz
    A L{IAddress} implementation meant to provide stub addresses for
    L{ITransport.getPeer} and L{ITransport.getHost}.
    N©r)   r*   r+   r,   r/   r/   r/   r0   rˆ   <  s   rˆ   c                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )ÚLocalWorkerTransportzi
    A stub transport implementation used to support L{AMP} over a
    L{ProcessProtocol} transport.
    c                 C   s
   || _ d S r<   )Ú
_transport)r8   Ú	transportr/   r/   r0   r@   K  s    zLocalWorkerTransport.__init__c                 C   s   | j  t|¡ dS )z,
        Forward data to transport.
        N©r‹   ZwriteToChildr   ©r8   rY   r/   r/   r0   rX   N  s    zLocalWorkerTransport.writec                 C   s   |D ]}| j  t|¡ qdS )zP
        Emulate C{writeSequence} by iterating data in the C{sequence}.
        Nr�   )r8   ÚsequencerY   r/   r/   r0   ÚwriteSequenceT  s    z"LocalWorkerTransport.writeSequencec                 C   s   | j  ¡  dS )z'
        Closes the transport.
        N)r‹   ÚloseConnectionrV   r/   r/   r0   r‘   [  s    z#LocalWorkerTransport.loseConnectionc                 C   s   t ƒ S ©z:
        Return a L{LocalWorkerAddress} instance.
        ©rˆ   rV   r/   r/   r0   ÚgetHosta  s    zLocalWorkerTransport.getHostc                 C   s   t ƒ S r’   r“   rV   r/   r/   r0   ÚgetPeerg  s    zLocalWorkerTransport.getPeerN)
r)   r*   r+   r,   r@   rX   r�   r‘   r”   r•   r/   r/   r/   r0   rŠ   D  s   rŠ   c                   @   s   e Zd ZdZdS )Ú
NotRunningzN
    An operation was attempted on a worker process which is not running.
    Nr‰   r/   r/   r/   r0   r–   n  s   r–   c                   @   sl   e Zd ZdZeee edœdd„Zddœdd„Z	d	d
„ Z
dd„ Zeddœdd„Zdd„ Zdd„ Zdd„ ZdS )ÚLocalWorkeraL  
    Local process worker protocol. This worker runs as a local process and
    communicates via stdin/out.

    @ivar _ampProtocol: The L{AMP} protocol instance used to communicate with
        the worker.

    @ivar _logDirectory: The directory where logs will reside.

    @ivar _logFile: The main log file for tests output.
    )ÚampProtocolÚlogDirectoryÚlogFilec                 C   s   || _ || _|| _tƒ | _d S r<   )Ú_ampProtocolÚ_logDirectoryÚ_logFiler   ÚendDeferred)r8   r˜   r™   rš   r/   r/   r0   r@   �  s    zLocalWorker.__init__N)r7   c                 Ã   sJ   | j dkrtƒ ‚| j}| j  t¡ z|I dH  W n tk
rD   Y nX dS )z3
        Cause the worker process to exit.
        N)rŒ   r–   rž   ZcloseChildFDr   r   )r8   rž   r/   r/   r0   ÚexitŒ  s    
zLocalWorker.exitc                 C   s~   | j  t| jƒ¡ | jjdd� | j d¡ d¡| _| j d¡ d¡| _	| j  
| j¡ | j jtj| jjd�}| dd„ ¡ d	S )
zL
        When connection is made, create the AMP protocol instance.
        T)ZignoreExistingDirectoryzout.logÚwzerr.log)rI   c                 S   s   d S r<   r/   )Úxr/   r/   r0   Ú<lambda>©  rk   z,LocalWorker.connectionMade.<locals>.<lambda>N)r›   ZmakeConnectionrŠ   rŒ   rœ   ÚmakedirsÚchildrU   Ú_outLogÚ_errLogr†   r�   r„   r   rM   ÚpathZ
addErrback)r8   Údr/   r/   r0   ÚconnectionMadeš  s    þzLocalWorker.connectionMadec                 C   s   | j  ¡  | j ¡  d| _dS )zk
        On connection lost, close the log files that we're managing for stdin
        and stdout.
        N)r¥   Úcloser¦   rŒ   ©r8   r{   r/   r/   r0   ÚconnectionLost«  s    

zLocalWorker.connectionLost)r{   r7   c                 C   s&   |   |¡ | j  |¡ | j |¡ dS )z’
        When the process closes, call C{connectionLost} for cleanup purposes
        and forward the information to the C{_ampProtocol}.
        N)r¬   r›   rž   Úcallbackr«   r/   r/   r0   ÚprocessEnded´  s    
zLocalWorker.processEndedc                 C   s   | j  |¡ dS )z8
        Send data received from stdout to log.
        N)r¥   rX   rŽ   r/   r/   r0   ÚoutReceived½  s    zLocalWorker.outReceivedc                 C   s   | j  |¡ dS )z*
        Write error data to log.
        N)r¦   rX   rŽ   r/   r/   r0   ÚerrReceivedÄ  s    zLocalWorker.errReceivedc                 C   s(   |t kr| j |¡ nt | ||¡ dS )zT
        Handle data received on the specific pipe for the C{_ampProtocol}.
        N)r   r›   ZdataReceivedr   ÚchildDataReceived)r8   ZchildFDrY   r/   r/   r0   r±   Ê  s    zLocalWorker.childDataReceived)r)   r*   r+   r,   rN   r   r   r   r@   rŸ   r©   r¬   r   r®   r¯   r°   r±   r/   r/   r/   r0   r—   t  s   ü		r—   )Fr,   rG   Útypingr   r   r   r   r   r   r   r	   Zunittestr
   Zzope.interfacer   Úattrsr   Ztyping_extensionsr   r   Ztwisted.internet.deferr   r   Ztwisted.internet.errorr   Ztwisted.internet.interfacesr   r   Ztwisted.internet.protocolr   Ztwisted.loggerr   Ztwisted.protocols.ampr   Ztwisted.python.failurer   Ztwisted.python.filepathr   Ztwisted.python.reflectr   Ztwisted.trial._distr   r   r   r   Z"twisted.trial._dist.workerreporterr   Ztwisted.trial.reporterr   Ztwisted.trial.runnerr    r!   Ztwisted.trial.unittestr"   r…   r$   r%   r&   Ú	Exceptionr'   r1   r4   r:   ZWorkerActionr;   rN   rˆ   rŠ   r–   r—   r/   r/   r/   r0   Ú<module>   sH   (
C -)