o
    bi                     @   s  d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlZddl	m
Z
 dadZG dd deZd#d
dZdZG dd deZdd ZG dd dZG dd dZG dd dZg Zdd ZG dd deZdd ZdZddddejfdd Zd!d" ZdS )$z9
Asynchronous-friendly error mechanism.

See L{Failure}.
    N)getmro)StringIO)reflect   c                   @   s   e Zd ZdS )DefaultExceptionN)__name__
__module____qualname__ r
   r
   8/usr/lib/python3/dist-packages/twisted/python/failure.pyr      s    r   defaultc              	   C   sx  |dvrt d|f |}|dkr*| D ]\}}}}}|| d| d| d qdS |dkrT| D ]!\}}}}}|d| d| d	| d |d
t||   q0dS |dkrq| D ]\}}}}}|d|||f  qZ|d dS |dkr| D ]B\}}}}}|d|||f  |d |D ]\}	}
|d|	 dt|
 d q|d |D ]\}	}
|d|	 dt|
 d qqwdS dS )a  
    Format and write frames.

    @param frames: is a list of frames as used by Failure.frames, with
        each frame being a list of
        (funcName, fileName, lineNumber, locals.items(), globals.items())
    @type frames: list
    @param write: this will be called with formatted strings.
    @type write: callable
    @param detail: Four detail levels are available:
        default, brief, verbose, and verbose-vars-not-captured.
        C{Failure.printDetailedTraceback} uses the latter when the caller asks
        for verbose, but no vars were captured, so that an explicit warning
        about the missing data is shown.
    @type detail: string
    )r   briefverboseverbose-vars-not-capturedzNDetail must be default, brief, verbose, or verbose-vars-not-captured. (not %r)r   :
r   z  File "z", line z, in z    %s
r   z%s:%d: %s(...)
zA [Capture of Locals and Globals disabled (use captureVars=True)]
r   z [ Locals ]
z  z : z ( Globals )
N)
ValueError	linecachegetlinestriprepr)frameswritedetailwmethodfilenamelineno	localVars
globalVarsnamevalr
   r
   r   format_frames#   s@   r"   z--- <exception caught here> ---c                   @   s   e Zd ZdZdS )NoCurrentExceptionErrorz
    Raised when trying to create a Failure from the current interpreter
    exception state and there is no current exception state.
    N)r   r   r	   __doc__r
   r
   r
   r   r#   V   s    r#   c                 C   sv   t |dks
J dd}| D ]}t||}qt|d |}t| }}|dd D ]}t||}t||_|j}q)|S )a  
    Construct a fake traceback object using a list of frames. Note that
    although frames generally include locals and globals, this information
    is not kept by this method, since locals and globals are not used in
    standard tracebacks.

    @param stackFrames: [(methodname, filename, lineno, locals, globals), ...]
    @param tbFrames: [(methodname, filename, lineno, locals, globals), ...]
    r   zMust pass some framesN   )len_Frame_TracebackFrametb_next)stackFramestbFramesstacksffirstTbtbr
   r
   r   
_Traceback]   s   


r0   c                   @      e Zd ZdZdd ZdS )r(   zq
    Fake traceback object which can be passed to functions in the standard
    library L{traceback} module.
    c                 C   s   || _ |j| _d| _dS )z-
        @param frame: _Frame object
        N)tb_framef_lineno	tb_linenor)   )selfframer
   r
   r   __init__   s   
z_TracebackFrame.__init__Nr   r   r	   r$   r7   r
   r
   r
   r   r(      s    r(   c                   @   r1   )r'   aD  
    A fake frame object, used by L{_Traceback}.

    @ivar f_code: fake L{code<types.CodeType>} object
    @ivar f_lineno: line number
    @ivar f_globals: fake f_globals dictionary (usually empty)
    @ivar f_locals: fake f_locals dictionary (usually empty)
    @ivar f_back: previous stack frame (towards the caller)
    c                 C   s6   |\}}}}}t ||| _|| _i | _i | _|| _dS )z
        @param frameinfo: (methodname, filename, lineno, locals, globals)
        @param back: previous (older) stack frame
        @type back: C{frame}
        N)_Codef_coder3   	f_globalsf_localsf_back)r5   	frameinfobackr    r   r   localzglobalzr
   r
   r   r7      s   
z_Frame.__init__Nr8   r
   r
   r
   r   r'      s    
r'   c                   @   r1   )r9   zB
    A fake code object, used by L{_Traceback} via L{_Frame}.
    c                 C   s   || _ || _d S )N)co_nameco_filename)r5   r    r   r
   r
   r   r7      s   
z_Code.__init__Nr8   r
   r
   r
   r   r9      s    r9   c                 C   s   t | j | S )a  
    Mark the given callable as extraneous to inlineCallbacks exception
    reporting; don't show these functions.

    @param f: a function that you NEVER WANT TO SEE AGAIN in ANY TRACEBACK
        reported by Failure.

    @type f: function

    @return: f
    )_inlineCallbacksExtraneousappend__code__)fr
   r
   r   _extraneous   s   rH   c                   @   s   e Zd ZdZdZdZejd Zd.ddZ	dd	 Z
d
d Zdd Zdd Zedd Zedd ZdefddZdefddZdd Zdd Zdd Zdefdd Zdefd!d"Zd/d$ed%edefd&d'Zd0d(d)Zd1d*d+Zd1d,d-ZdS )2Failurea  
    A basic abstraction for an error that has occurred.

    This is necessary because Python's built-in error mechanisms are
    inconvenient for asynchronous communication.

    The C{stack} and C{frame} attributes contain frames.  Each frame is a tuple
    of (funcName, fileName, lineNumber, localsItems, globalsItems), where
    localsItems and globalsItems are the contents of
    C{locals().items()}/C{globals().items()} for that frame, or an empty tuple
    if those details were not captured.

    @ivar value: The exception instance responsible for this failure.
    @ivar type: The exception's class.
    @ivar stack: list of frames, innermost last, excluding C{Failure.__init__}.
    @ivar frames: list of frames, innermost first.
    r   NYIELD_VALUEFc                 C   s  t d a t | _ d | _ | _}|| _t|tr|du rtdd}|du r)|  }|du rAt	 \| _| _}| jdu r>t
 d}n|du rXt|trO|j| _nt|| _|| _n|| _|| _t| jtrl| | j dS t| jdr~| | jj | j`dS |du r|r|}nt| jddr| jj}g  }| _g  }| _|| _|r|j}	n
t| jtsd }	}|r|	r|	j}	|d8 }|r|	s|	r|r|	j }
|	j|	ju ri }n|	j }||
fD ]	}d|v r|d= q|
 }
| }nd }
}|d|	jj|	jj|	j |
|f |	j}	|	s|dur]|j}	|rB|	j }
|	j|	ju r i }n|	j }||
fD ]}d|v r3|d= q)t!|
 }
t!| }nd }
}|"|	jj|	jj|j#|
|f |j$}|dust%&| jr{t'| jtr{t(| j}t!t)t*j+|| _,dS | jg| _,dS )	a-  
        Initialize me with an explanation of the error.

        By default, this will use the current C{exception}
        (L{sys.exc_info}()).  However, if you want to specify a
        particular kind of failure, you can pass an exception as an
        argument.

        If no C{exc_value} is passed, then an "original" C{Failure} will
        be searched for. If the current exception handler that this
        C{Failure} is being constructed in is handling an exception
        raised by L{raiseException}, then this C{Failure} will act like
        the original C{Failure}.

        For C{exc_tb} only L{traceback} instances or L{None} are allowed.
        If L{None} is supplied for C{exc_value}, the value of C{exc_tb} is
        ignored, otherwise if C{exc_tb} is L{None}, it will be found from
        execution context (ie, L{sys.exc_info}).

        @param captureVars: if set, capture locals and globals of stack
            frames.  This is pretty slow, and makes no difference unless you
            are going to use L{printDetailedTraceback}.
        r%   Nz$Strings are not supported by Failurer   __failure____traceback____builtins__r
   )-counttypevaluecaptureVars
isinstancestr	TypeError_findFailuresysexc_infor#   	Exception	__class__rI   _extrapolatehasattrrK   getattrrL   r   r,   r/   r2   r=   r<   copyr;   itemsinsertr:   rB   rC   r3   listrE   r4   r)   inspectisclass
issubclassr   mapr   qualparents)r5   	exc_valueexc_typeexc_tbrQ   r/   stackOffsetr   r,   rG   r@   rA   dparentCsr
   r
   r   r7      s   













	

zFailure.__init__c                 C   sz   t  |j| _t \}}}g }|dur2|j}|jtvr+||jj|jj	|j
ddf |j}|dus|| j || _dS )a,  
        Extrapolate from one failure into another, copying its stack frames.

        @param otherFailure: Another L{Failure}, whose traceback information,
            if any, should be preserved as part of the stack presented by this
            one.
        @type otherFailure: L{Failure}
        Nr
   )r]   __dict__rV   rW   r2   r:   rD   rE   rB   rC   r4   r)   extendr   )r5   otherFailure_r/   r   rG   r
   r
   r   rZ     s   


zFailure._extrapolatec                 G   s   | j | }|s|   |S )a  
        Trap this failure if its type is in a predetermined list.

        This allows you to trap a Failure in an error callback.  It will be
        automatically re-raised if it is not a type that you expect.

        The reason for having this particular API is because it's very useful
        in Deferred errback chains::

            def _ebFoo(self, failure):
                r = failure.trap(Spam, Eggs)
                print('The Failure is due to either Spam or Eggs!')
                if r == Spam:
                    print('Spam did it!')
                elif r == Eggs:
                    print('Eggs did it!')

        If the failure is not a Spam or an Eggs, then the Failure will be
        'passed on' to the next errback. In Python 2 the Failure will be
        raised; in Python 3 the underlying exception will be re-raised.

        @type errorTypes: L{Exception}
        )checkraiseException)r5   
errorTypeserrorr
   r
   r   trap  s   
zFailure.trapc                 G   sB   |D ]}|}t |rt|trt|}|| jv r|  S qdS )a  
        Check if this failure's type is in a predetermined list.

        @type errorTypes: list of L{Exception} classes or
                          fully-qualified class names.
        @returns: the matching L{Exception} type, or None if no match.
        N)ra   rb   rc   rX   r   re   rf   )r5   rs   rt   errr
   r
   r   rq     s   

zFailure.checkc                 C   s   | j | j)zf
        raise the original exception, preserving traceback
        information if available.
        )rP   with_tracebackr/   r5   r
   r
   r   rr     s   zFailure.raiseExceptionc                 C   s   | | j| j| jS )aJ  
        Throw the original exception into the given generator,
        preserving traceback information if available.

        @return: The next value yielded from the generator.
        @raise StopIteration: If there are no more values in the generator.
        @raise anything else: Anything that the generator raises.
        )throwrO   rP   r/   )r5   gr
   r
   r   throwExceptionIntoGenerator  s   z#Failure.throwExceptionIntoGeneratorc                 C   s   t  d }|s
dS d}|}|jr|}|j}|js|j}|j| jju r)|jdS |jj	r7|jj	|j
 | jkr9dS |rK|j}|j| jju rK|jdS |jj}|r^|j| jju r`|jdS dS dS )zV
        Find the failure that represents the exception currently in context.
        Nr5   )rV   rW   r)   r2   r:   rr   rF   r<   getco_codetb_lasti_yieldOpcoder{   r=   )clsr/   secondLastTblastTb	lastFramer6   r
   r
   r   rU     s4   	zFailure._findFailurereturnc                 C   s"   d t| jt| j|  S )Nz<{} {}: {}>)formatr   re   rY   rO   getErrorMessagerx   r
   r
   r   __repr__&  s
   

zFailure.__repr__c                 C   s   d|    S )Nz[Failure instance: %s])getBriefTracebackrx   r
   r
   r   __str__-  s   zFailure.__str__c                 C   s\   | j r| jS | j }dd | jD |d< d|d< | jdur(dd | jD |d< d|d	< |S )
z(Avoid pickling objects in the traceback.c              	   S   6   g | ]}|d  |d |d t |d t |d gqS r   r%         r   _safeReprVars.0vr
   r
   r   
<listcomp>6      

z(Failure.__getstate__.<locals>.<listcomp>r   Nr/   c              	   S   r   r   r   r   r
   r
   r   r   G  r   r,   r%   pickled)r   rm   r]   r   r,   )r5   cr
   r
   r   __getstate__0  s   



zFailure.__getstate__c                 C   s(   |   | _t| jddrd| j_dS dS )z
        Remove references to other objects, replacing them with strings.

        On Python 3, this will also set the C{__traceback__} attribute of the
        exception instance to L{None}.
        rL   N)r   rm   r\   rP   rL   rx   r
   r
   r   cleanFailureU  s   
zFailure.cleanFailurec                 C   s0   | j dur| j S t| jdkrt| j| jS dS )a  
        Get an object that represents this Failure's stack that can be passed
        to traceback.extract_tb.

        If the original traceback object is still present, return that. If this
        traceback object has been lost but we still have the information,
        return a fake traceback object (see L{_Traceback}). If there is no
        traceback information at all, return None.
        Nr   )r/   r&   r   r0   r,   rx   r
   r
   r   getTracebackObjecta  s
   

zFailure.getTracebackObjectc                 C   s"   t | jtr| j S t| jS )zJ
        Get a string of the exception which caused this Failure.
        )rR   rP   rI   r   r   safe_strrx   r
   r
   r   r   r  s   
zFailure.getErrorMessagec                 C   s   t  }| j|d | S )N)file)r   printBriefTracebackgetvalue)r5   ior
   r
   r   r   z  s   zFailure.getBriefTracebackr   elideFrameworkCoder   c                 C   s   t  }| j|||d | S )N)r   r   r   )r   printTracebackr   )r5   r   r   r   r
   r
   r   getTraceback  s
   zFailure.getTracebackc                 C   sb  |du rddl m} |j}|j}|dkr| jsd}n|}|dkr/|d| j| jr)dp*df  n"|d	krM| jr9d
}nd}|d|t	| j
t	| jf  n|d | jrq|sit| jt d || |t d t| j|| n|d	ksy|d |d	ks|t| j
 dt	| j d t| jtr|d | j||| |dkr|d| j  dS dS )a  
        Emulate Python's standard error reporting mechanism.

        @param file: If specified, a file-like object to which to write the
            traceback.

        @param elideFrameworkCode: A flag indicating whether to attempt to
            remove uninteresting frames from within Twisted itself from the
            output.

        @param detail: A string indicating how much information to include
            in the traceback.  Must be one of C{'brief'}, C{'default'}, or
            C{'verbose'}.
        Nr   )logr   r   z*--- Failure #%d%s---
z (pickled)  r   	Tracebackz"Traceback (failure with no frames)z%s: %s: %s
z#Traceback (most recent call last):
r   z	Failure: z: z (chained Failure)
z*--- End of Failure #%d ---
)twisted.pythonr   logerrr   rQ   rN   r   r   r   r   rO   rP   r"   r,   traceupLengthEXCEPTION_CAUGHT_HEREre   rR   rI   r   )r5   r   r   r   r   r   formatDetail	hasFramesr
   r
   r   r     sL   $
zFailure.printTracebackc                 C      | j ||dd dS )z;
        Print a traceback as densely as possible.
        r   r   Nr   r5   r   r   r
   r
   r   r        zFailure.printBriefTracebackc                 C   r   )zQ
        Print a traceback with detailed locals and globals information.
        r   r   Nr   r   r
   r
   r   printDetailedTraceback  r   zFailure.printDetailedTraceback)NNNF)r   r   )NFr   )Nr   )r   r   r	   r$   r   r,   opcodeopmapr   r7   rZ   ru   rq   rr   rH   r{   classmethodrU   rS   r   r   r   r   r   r   r   intr   r   r   r   r
   r
   r
   r   rI      s4    

 '

:%

ErI   c                 C   s   dd | D S )aq  
    Convert a list of (name, object) pairs into (name, repr) pairs.

    L{twisted.python.reflect.safe_repr} is used to generate the repr, so no
    exceptions will be raised by faulty C{__repr__} methods.

    @param varsDictItems: a sequence of (name, value) pairs as returned by e.g.
        C{locals().items()}.
    @returns: a sequence of (name, repr) pairs.
    c                 S   s   g | ]\}}|t |fqS r
   )r   	safe_repr)r   r    objr
   r
   r   r     s    z!_safeReprVars.<locals>.<listcomp>r
   )varsDictItemsr
   r
   r   r     s   r   TFc           	      C   s   |||fdkr:t  }|d | jks:tr:zt|d }W n ty'   d}Y nw td| ddl}|	|d  || |||| dS )z;
    Initialize failure object, possibly spawning pdb.
    )NNNr   r%   z
broken strz8Jumping into debugger for post-mortem of exception '{}':Nr   )
rV   rW   rY   DO_POST_MORTEMrS   BaseExceptionprintr   pdbpost_mortem)	r5   rg   rh   ri   rQ   Failure__init__excstrreprr   r
   r
   r   
_debuginit  s    r   c                   C   s
   t t_dS )z*
    Enable debug hooks for Failures.
    N)r   rI   r7   r
   r
   r
   r   startDebugMode  s   
r   )r   )r$   r]   ra   r   rV   r   r   r   r   r   r   rN   r   rX   r   r"   r   r#   r0   r(   r'   r9   rD   rH   r   rI   r   r   r7   r   r   r
   r
   r
   r   <module>   sF   
0&
    
