U
    W[h                     @   s   d Z ddlmZmZmZ ddl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mZ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eZG dd deZG dd de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}.
    )divisionabsolute_importprint_functionN)getmro)reflect)_PY3NativeStringIO   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krt d|f |}|dkrL| D ] \}}}}}|d|||f  q&n|dkr| D ]8\}}}}}|d|||f  |dt||   qXn|dkr| D ] \}}}}}|d	|||f  q|d
 n|dkrT| D ]x\}}}}}|d	|||f  |d |D ]\}	}
|d|	t|
f  q|d |D ]\}	}
|d|	t|
f  q2qd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   z	%s:%s:%s
r   z  File "%s", line %s, in %s
z    %s
r   z%s:%d: %s(...)
zA [Capture of Locals and Globals disabled (use captureVars=True)]
r   z [ Locals ]
z
  %s : %s
z ( Globals )
N)
ValueError	linecachegetlinestriprepr)frameswritedetailwmethodfilenamelinenoZ	localVarsZ
globalVarsnamevalr   r   r   format_frames#   s6    

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   s4   t | dkstdd}t| D ]}t||}q |S )aE  
    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 frames: [(methodname, filename, lineno, locals, globals), ...]
    r   zMust pass some framesN)lenAssertionErrorreversed_TracebackFrame)r   tbframer   r   r   
_Traceback^   s
    	r+   c                   @   s   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*   |\}}}}}t ||| _|| _|| _dS )z
        @param frame: (methodname, filename, lineno, locals, globals)
        @param tb_next: next inner _TracebackFrame object, or None if this
           is the innermost frame.
        N)_Frametb_frame	tb_linenotb_next)selfr*   r/   r    r   r   localzglobalzr   r   r   __init__w   s    z_TracebackFrame.__init__Nr   r   r   r$   r3   r   r   r   r   r(   q   s   r(   c                   @   s   e Zd ZdZdd ZdS )r,   z
    A fake frame object, used by L{_Traceback}.

    @ivar f_code: fake L{code<types.CodeType>} object
    @ivar f_globals: fake f_globals dictionary (usually empty)
    @ivar f_locals: fake f_locals dictionary (usually empty)
    c                 C   s   t ||| _i | _i | _dS )z
        @param name: method/function name for this frame.
        @type name: C{str}
        @param filename: filename for this frame.
        @type name: C{str}
        N)_Codef_code	f_globalsf_localsr0   r    r   r   r   r   r3      s    z_Frame.__init__Nr4   r   r   r   r   r,      s   r,   c                   @   s   e Zd ZdZdd ZdS )r5   zB
    A fake code object, used by L{_Traceback} via L{_Frame}.
    c                 C   s   || _ || _d S N)co_nameco_filenamer9   r   r   r   r3      s    z_Code.__init__Nr4   r   r   r   r   r5      s   r5   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    rA   c                   @   s   e Zd ZdZdZdZer$ejd Z	ne
ejd Z	d.ddZdd	 Zd
d Zdd Zeeddrjdd Zned de_edd Zdd ZeeZdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd/d&d'Zd0d(d)Zd1d*d+Z d2d,d-Z!dS )3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   NZYIELD_VALUEFc                 C   s  t d a t | _ d | _ | _}|| _t|tr>|dkr>tdd}|dkrR|  }|dkrt	 \| _| _}| jdkr|t
 d}n:|dkrt|tr|j| _n
t|| _|| _n|| _|| _t| jtr| | j dS t| jdr| | jj | j`dS |dkr*|r|}nt| jddr*| jj}g  }| _g  }| _|| _|rR|j}	nt| jtshd }	}|r|	r|	j}	|d8 }qh|	r|r|	j }
|	j|	jkri }n
|	j }||
fD ]}d|kr|d= q|
 }
| }nd }
}|d|	jj|	jj|	j |
|f |	j}	q|dk	r|j}	|r|	j }
|	j|	jkrRi }n
|	j }||
fD ]}d|krd|d= qdt!|
 }
t!| }nd }
}|"|	jj|	jj|j#|
|f |j$}qt%&| jr t'| jtr t(| j}t!t)t*j+|| _,n
| 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}.
           Nz$Strings are not supported by Failurer   __failure____traceback____builtins__r   )-counttypevaluecaptureVars
isinstancestr	TypeError_findFailuresysexc_infor#   	Exception	__class__rB   _extrapolatehasattrrD   getattrrE   r   stackr)   r-   f_backr8   copyr7   itemsinsertr6   r;   r<   f_linenolistr>   r.   r/   inspectisclass
issubclassr   mapr   qualparents)r0   	exc_valueexc_typeexc_tbrJ   r)   ZstackOffsetr   rV   r@   r1   r2   dZparentCsr   r   r   r3      s    




















zFailure.__init__c                 C   st   t  |j| _t \}}}g }|dk	r^|j}|jtkrV||jj|jj	|j
ddf |j}q || 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   )rX   __dict__rO   rP   r-   r6   r=   r>   r;   r<   r.   r/   extendr   )r0   ZotherFailure_r)   r   r@   r   r   r   rS   |  s     

  zFailure._extrapolatec                 G   s$   | j | }|s tr|   n| |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}
        )checkr   raiseException)r0   
errorTypeserrorr   r   r   trap  s    

zFailure.trapc                 G   sB   |D ]8}|}t |r*t|tr*t|}|| jk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)r]   r^   r_   rQ   r   ra   rb   )r0   rl   rm   errr   r   r   rj     s    


zFailure.checkwith_tracebackc                 C   s   | j | jd S r:   )rI   rp   r)   r0   r   r   r   rk     s    zFailure.raiseExceptionzBdef raiseException(self):
    raise self.type, self.value, self.tbzf
        raise the original exception, preserving traceback
        information if available.
        c                 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.
        )throwrH   rI   r)   )r0   gr   r   r   throwExceptionIntoGenerator  s    z#Failure.throwExceptionIntoGeneratorc                 C   s   t  d }|sdS d}|}|jr.|}|j}q|j}|j| jjkrN|jdS |jj	rj|jj	|j
 | jkrndS |r|j}|j| jjkr|jdS |jj}|r|j| jjkr|jdS dS )zV
        Find the failure that represents the exception currently in context.
        Nr0   )rO   rP   r/   r-   r6   rk   r?   r8   getco_codetb_lasti_yieldOpcodert   rW   )clsr)   ZsecondLastTbZlastTbZ	lastFramer*   r   r   r   rN     s,    	zFailure._findFailurec                 C   s"   dt | jt | j|  f S )Nz<%s %s: %s>)r   ra   rR   rH   getErrorMessagerq   r   r   r   __repr__)  s    
zFailure.__repr__c                 C   s   d|    S )Nz[Failure instance: %s])getBriefTracebackrq   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k	rPdd | jD |d< d|d	< |S )
z1Avoid pickling objects in the traceback.
        c              	   S   s6   g | ].}|d  |d |d t |d t |d gqS r   rC         r	   _safeReprVars.0vr   r   r   
<listcomp>:  s     

z(Failure.__getstate__.<locals>.<listcomp>r   Nr)   c              	   S   s6   g | ].}|d  |d |d t |d t |d gqS r   r   r   r   r   r   r   H  s     

rV   rC   pickled)r   rg   rX   r   rV   )r0   cr   r   r   __getstate__3  s    

	

zFailure.__getstate__c                 C   s$   |   | _t| jddr d| j_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}.
        rE   N)r   rg   rU   rI   rE   rq   r   r   r   cleanFailureT  s    
zFailure.cleanFailurec                 C   s0   | j dk	r| j S t| jdkr(t| jS d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   r+   rq   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.
        )rK   rI   rB   r{   r   safe_strrq   r   r   r   r{   s  s    
zFailure.getErrorMessagec                 C   s   t  }| j|d | S )N)file)StringIOprintBriefTracebackgetvalue)r0   ior   r   r   r}   |  s    zFailure.getBriefTracebackr   c                 C   s   t  }| j|||d | S )N)r   elideFrameworkCoder   )r   printTracebackr   )r0   r   r   r   r   r   r   getTraceback  s
    zFailure.getTracebackc                 C   s`  |dkrddl m} |j}|j}|dkr4| js4d}n|}|dkr^|d| j| jrRdpTdf  nD|d	kr| jrrd
}nd}|d|t	| j
t	| jf  n|d | jr|st| jt d || |dtf  t| j|| n|d	ks|d |d	ks|dt| j
t	| jf  t| jtrD|d | j||| |dkr\|d| j  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):
z%s
z	Failure: z%s: %s
z (chained Failure)
z*--- End of Failure #%d ---
)twisted.pythonr   Zlogerrr   rJ   rG   r   r   r   r   rH   rI   r"   rV   traceupLengthEXCEPTION_CAUGHT_HEREra   rK   rB   r   )r0   r   r   r   r   r   ZformatDetailZ	hasFramesr   r   r   r     sN    






zFailure.printTracebackc                 C   s   | j ||dd dS )z;
        Print a traceback as densely as possible.
        r   r   Nr   r0   r   r   r   r   r   r     s    zFailure.printBriefTracebackc                 C   s   | j ||dd dS )zQ
        Print a traceback with detailed locals and globals information.
        r   r   Nr   r   r   r   r   printDetailedTraceback  s    zFailure.printDetailedTraceback)NNNF)r   r   )NFr   )Nr   )Nr   )"r   r   r   r$   r   rV   r   opcodeZopmapry   chrr3   rS   rn   rj   rU   BaseExceptionrk   execrA   rt   rN   classmethodr|   r~   r   r   r   r{   r}   r   r   r   r   r   r   r   r   rB      sF     
 $ !

9!	
  
F
rB   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   Z	safe_repr)r   r    objr   r   r   r     s     z!_safeReprVars.<locals>.<listcomp>r   )ZvarsDictItemsr   r   r   r     s    r   TFc           	      C   s   |||fdkrnt  }|d | jksntrnzt|d }W n   d}Y nX td|f  ddl}||d  || |||| dS )z;
    Initialize failure object, possibly spawning pdb.
    )NNNr   rC   z
broken strz8Jumping into debugger for post-mortem of exception '%s':Nr   )rO   rP   rR   DO_POST_MORTEMrL   printpdbZpost_mortem)	r0   rc   rd   re   rJ   ZFailure__init__excZstrreprr   r   r   r   
_debuginit  s    
r   c                   C   s
   t t_dS )z*
    Enable debug hooks for Failures.
    N)r   rB   r3   r   r   r   r   startDebugMode  s    r   )r   )&r$   Z
__future__r   r   r   rX   rO   r   r]   r   r   r   r   Ztwisted.python.compatr   r   r   rG   r   rQ   r
   r"   r   r#   r+   objectr(   r,   r5   r=   rA   r   rB   r   r   r3   r   r   r   r   r   r   <module>   sB   
/
    +
