o bi@sdZddlZddlZddlZddlZddlmZddlmZddlZddl m Z da dZ Gddde Zd#d d Zd ZGd dde ZddZGdddZGdddZGdddZgZddZGdddeZddZdZddddejfdd Zd!d"ZdS)$z9 Asynchronous-friendly error mechanism. See L{Failure}. N)getmro)StringIO)reflectc@s eZdZdS)DefaultExceptionN)__name__ __module__ __qualname__r r 8/usr/lib/python3/dist-packages/twisted/python/failure.pyrsrdefaultc Csx|dvr td|f|}|dkr*|D]\}}}}}||d|d|dqdS|dkrT|D]!\}}}}}|d|d|d |d|d t||q0dS|d krq|D]\}}}}}|d |||fqZ|d dS|dkr|D]B\}}}}}|d |||f|d|D]\} } |d| dt| dq|d|D]\} } |d| dt| dqqwdSdS)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 briefverboseverbose-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 rz%s:%d: %s(...) zA [Capture of Locals and Globals disabled (use captureVars=True)] rz [ Locals ] z z : z ( Globals ) N) ValueError linecachegetlinestriprepr) frameswritedetailwmethodfilenamelineno localVars globalVarsnamevalr r r format_frames#s@   r"z--- ---c@seZdZdZdS)NoCurrentExceptionErrorz Raised when trying to create a Failure from the current interpreter exception state and there is no current exception state. N)rrr __doc__r r r r r#Vsr#cCsvt|dks Jdd}|D]}t||}qt|d|}t|}}|ddD]}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), ...] rzMust pass some framesN)len_Frame_TracebackFrametb_next) stackFramestbFramesstacksffirstTbtbr r r _Traceback]s     r0c@eZdZdZddZdS)r(zq Fake traceback object which can be passed to functions in the standard library L{traceback} module. cCs||_|j|_d|_dS)z- @param frame: _Frame object N)tb_framef_lineno tb_linenor))selfframer r r __init__s z_TracebackFrame.__init__Nrrr r$r7r r r r r(s r(c@r1)r'aD A fake frame object, used by L{_Traceback}. @ivar f_code: fake L{code} 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) cCs6|\}}}}}t|||_||_i|_i|_||_dS)z @param frameinfo: (methodname, filename, lineno, locals, globals) @param back: previous (older) stack frame @type back: C{frame} N)_Codef_coder3 f_globalsf_localsf_back)r5 frameinfobackr rrlocalzglobalzr r r r7s   z_Frame.__init__Nr8r r r r r's r'c@r1)r9zB A fake code object, used by L{_Traceback} via L{_Frame}. cCs||_||_dS)N)co_name co_filename)r5r rr r r r7s z_Code.__init__Nr8r r r r r9s r9cCst|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 )_inlineCallbacksExtraneousappend__code__)fr r r _extraneouss rHc@seZdZdZdZdZejdZd.ddZ dd Z d d Z d d Z ddZ eddZeddZdefddZdefddZddZddZddZdefdd Zdefd!d"Zd/d$ed%edefd&d'Zd0d(d)Zd1d*d+Zd1d,d-ZdS)2Failurea 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. rN YIELD_VALUEFcCstdat|_d|_|_}||_t|tr|durtdd}|dur)|}|durAt \|_|_}|jdur>t d}n|durXt|t rO|j |_nt||_||_n||_||_t|jt rl||jdSt|jdr~||jj|j`dS|dur|r|}n t|jddr|jj}g}|_g}|_||_|r|j} n t|jt sd} }|r| r| j} |d8}|r| s| r|r| j} | j| juri} n| j} | | fD] } d| vr| d=q| } | } nd} } |d| jj| jj| j | | f| j} | s|dur]|j} |rB| j} | j| jur i} n| j} | | fD] } d| vr3| d=q)t!| } t!| } nd} } |"| jj| jj|j#| | f|j$}|dus t%&|jr{t'|jt r{t(|j} t!t)t*j+| |_,dS|jg|_,dS) 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 )-counttypevalue captureVars isinstancestr TypeError _findFailuresysexc_infor# Exception __class__rI _extrapolatehasattrrKgetattrrLrr,r/r2r=r<copyr;itemsinsertr:rBrCr3listrEr4r)inspectisclass issubclassrmaprqualparents)r5 exc_valueexc_typeexc_tbrQr/ stackOffsetrr,rGr@rAdparentCsr r r r7s                        zFailure.__init__cCszt|j|_t\}}}g}|dur2|j}|jtvr+||jj|jj |j ddf|j }|dus| |j ||_ dS)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__rVrWr2r:rDrErBrCr4r)extendr)r5 otherFailure_r/rrGr r r rZs    zFailure._extrapolatecGs|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} )checkraiseException)r5 errorTypeserrorr r r traps z Failure.trapcGsB|D]}|}t|rt|trt|}||jvr|SqdS)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)rarbrcrXrrerf)r5rsrterrr r r rqs  z Failure.checkcCs|j|j)zf raise the original exception, preserving traceback information if available. )rPwith_tracebackr/r5r r r rrszFailure.raiseExceptioncCs||j|j|jS)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. )throwrOrPr/)r5gr r r throwExceptionIntoGenerators z#Failure.throwExceptionIntoGeneratorcCstd}|s dSd}|}|jr|}|j}|js|j}|j|jjur)|jdS|jj r7|jj |j |j kr9dS|rK|j}|j|j jurK|jdS|jj }|r^|j|j jur`|jdSdSdS)zV Find the failure that represents the exception currently in context. Nr5)rVrWr)r2r:rrrFr<getco_codetb_lasti _yieldOpcoder{r=)clsr/ secondLastTblastTb lastFramer6r r r rUs4     zFailure._findFailurereturncCs"dt|jt|j|S)Nz <{} {}: {}>)formatrrerYrOgetErrorMessagerxr r r __repr__&s   zFailure.__repr__cCs d|S)Nz[Failure instance: %s])getBriefTracebackrxr r r __str__-s zFailure.__str__cCs\|jr|jS|j}dd|jD|d<d|d<|jdur(dd|jD|d<d|d <|S) z(Avoid pickling objects in the traceback.c S6g|]}|d|d|dt|dt|dgqSrr%r _safeReprVars.0vr r r 6  z(Failure.__getstate__..rNr/c Srrrrr r r rGrr,r%pickled)rrmr]rr,)r5cr r r __getstate__0s     zFailure.__getstate__cCs(||_t|jddrd|j_dSdS)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}. rLN)rrmr\rPrLrxr r r cleanFailureUs  zFailure.cleanFailurecCs0|jdur|jSt|jdkrt|j|jSdS)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&rr0r,rxr r r getTracebackObjectas zFailure.getTracebackObjectcCs"t|jtr |jSt|jS)zJ Get a string of the exception which caused this Failure. )rRrPrIrrsafe_strrxr r r rrs   zFailure.getErrorMessagecCst}|j|d|S)N)file)rprintBriefTracebackgetvalue)r5ior r r rzs zFailure.getBriefTracebackr elideFrameworkCodercCst}|j|||d|S)N)rrr)rprintTracebackr)r5rrrr r r getTracebacks zFailure.getTracebackcCsb|dur ddlm}|j}|j}|dkr|jsd}n|}|dkr/|d|j|jr)dp*dfn"|d krM|jr9d }nd }|d |t |j t |j fn|d |jrq|sit |j t d|||tdt |j||n|d ksy|d|d ks|t|j dt |j dt|j tr|d|j ||||dkr|d|jdSdS)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)logrrz*--- Failure #%d%s--- z (pickled)  r Tracebackz"Traceback (failure with no frames)z %s: %s: %s z#Traceback (most recent call last): rz Failure: z: z (chained Failure) z*--- End of Failure #%d --- )twisted.pythonrlogerrrrQrNrrrrrOrPr"r, traceupLengthEXCEPTION_CAUGHT_HERErerRrIr)r5rrrrr formatDetail hasFramesr r r rsL $  zFailure.printTracebackcC|j||dddS)z; Print a traceback as densely as possible. r rNrr5rrr r r rzFailure.printBriefTracebackcCr)zQ Print a traceback with detailed locals and globals information. rrNrrr r r printDetailedTracebackrzFailure.printDetailedTraceback)NNNF)rr )NFr )Nr)rrr r$rr,opcodeopmaprr7rZrurqrrrHr{ classmethodrUrSrrrrrrrintrrrrr r r r rIs4  '  :%   ErIcCsdd|DS)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. cSsg|] \}}|t|fqSr )r safe_repr)rr objr r r rsz!_safeReprVars..r ) varsDictItemsr r r rs rTFc Cs|||fdkr:t}|d|jks:tr:zt|d}Wn ty'd}Ynwtd|ddl}| |d||||||dS)z; Initialize failure object, possibly spawning pdb. )NNNrr%z broken strz8Jumping into debugger for post-mortem of exception '{}':Nr) rVrWrYDO_POST_MORTEMrS BaseExceptionprintrpdb post_mortem) r5rgrhrirQFailure__init__excstrreprrr r r _debuginits   rcCs tt_dS)z* Enable debug hooks for Failures. N)rrIr7r r r r startDebugModes r)r )r$r]rarrVrrrrrrrNrrXrr"rr#r0r(r'r9rDrHrrIrrr7rrr r r r sF    0&