| Index: third_party/twisted_8_1/twisted/python/failure.py
|
| diff --git a/third_party/twisted_8_1/twisted/python/failure.py b/third_party/twisted_8_1/twisted/python/failure.py
|
| deleted file mode 100644
|
| index 76d5b7f0395aea6f09b7603ecfaad106119dd629..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/python/failure.py
|
| +++ /dev/null
|
| @@ -1,550 +0,0 @@
|
| -# -*- test-case-name: twisted.test.test_failure -*-
|
| -# See also test suite twisted.test.test_pbfailure
|
| -
|
| -# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -"""
|
| -Asynchronous-friendly error mechanism.
|
| -
|
| -See L{Failure}.
|
| -"""
|
| -
|
| -# System Imports
|
| -import sys
|
| -import linecache
|
| -import inspect
|
| -import opcode
|
| -from cStringIO import StringIO
|
| -
|
| -from twisted.python import reflect
|
| -
|
| -count = 0
|
| -traceupLength = 4
|
| -
|
| -class DefaultException(Exception):
|
| - pass
|
| -
|
| -def format_frames(frames, write, detail="default"):
|
| - """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: Three detail levels are available:
|
| - default, brief, and verbose.
|
| - @type detail: string
|
| - """
|
| - if detail not in ('default', 'brief', 'verbose'):
|
| - raise ValueError, "Detail must be default, brief, or verbose. (not %r)" % (detail,)
|
| - w = write
|
| - if detail == "brief":
|
| - for method, filename, lineno, localVars, globalVars in frames:
|
| - w('%s:%s:%s\n' % (filename, lineno, method))
|
| - elif detail == "default":
|
| - for method, filename, lineno, localVars, globalVars in frames:
|
| - w( ' File "%s", line %s, in %s\n' % (filename, lineno, method))
|
| - w( ' %s\n' % linecache.getline(filename, lineno).strip())
|
| - elif detail == "verbose":
|
| - for method, filename, lineno, localVars, globalVars in frames:
|
| - w("%s:%d: %s(...)\n" % (filename, lineno, method))
|
| - w(' [ Locals ]\n')
|
| - # Note: the repr(val) was (self.pickled and val) or repr(val)))
|
| - for name, val in localVars:
|
| - w(" %s : %s\n" % (name, repr(val)))
|
| - w(' ( Globals )\n')
|
| - for name, val in globalVars:
|
| - w(" %s : %s\n" % (name, repr(val)))
|
| -
|
| -# slyphon: i have a need to check for this value in trial
|
| -# so I made it a module-level constant
|
| -EXCEPTION_CAUGHT_HERE = "--- <exception caught here> ---"
|
| -
|
| -
|
| -
|
| -class NoCurrentExceptionError(Exception):
|
| - """
|
| - Raised when trying to create a Failure from the current interpreter
|
| - exception state and there is no current exception state.
|
| - """
|
| -
|
| -
|
| -class _Traceback(object):
|
| - """
|
| - Fake traceback object which can be passed to functions in the standard
|
| - library L{traceback} module.
|
| - """
|
| -
|
| - def __init__(self, frames):
|
| - """
|
| - 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 object, since locals and globals are not used in
|
| - standard tracebacks.
|
| -
|
| - @param frames: [(methodname, filename, lineno, locals, globals), ...]
|
| - """
|
| - assert len(frames) > 0, "Must pass some frames"
|
| - head, frames = frames[0], frames[1:]
|
| - name, filename, lineno, localz, globalz = head
|
| - self.tb_frame = _Frame(name, filename)
|
| - self.tb_lineno = lineno
|
| - if len(frames) == 0:
|
| - self.tb_next = None
|
| - else:
|
| - self.tb_next = _Traceback(frames)
|
| -
|
| -
|
| -class _Frame(object):
|
| - """
|
| - A fake frame object, used by L{_Traceback}.
|
| - """
|
| -
|
| - def __init__(self, name, filename):
|
| - self.f_code = _Code(name, filename)
|
| - self.f_globals = {}
|
| -
|
| -
|
| -class _Code(object):
|
| - """
|
| - A fake code object, used by L{_Traceback} via L{_Frame}.
|
| - """
|
| - def __init__(self, name, filename):
|
| - self.co_name = name
|
| - self.co_filename = filename
|
| -
|
| -
|
| -class Failure:
|
| - """A basic abstraction for an error that has occurred.
|
| -
|
| - This is necessary because Python's built-in error mechanisms are
|
| - inconvenient for asynchronous communication.
|
| -
|
| - @ivar value: The exception instance responsible for this failure.
|
| - @ivar type: The exception's class.
|
| - """
|
| -
|
| - pickled = 0
|
| - stack = None
|
| -
|
| - # The opcode of "yield" in Python bytecode. We need this in _findFailure in
|
| - # order to identify whether an exception was thrown by a
|
| - # throwExceptionIntoGenerator.
|
| - _yieldOpcode = chr(opcode.opmap["YIELD_VALUE"])
|
| -
|
| - def __init__(self, exc_value=None, exc_type=None, exc_tb=None):
|
| - """Initialize me with an explanation of the error.
|
| -
|
| - By default, this will use the current X{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" Failure will
|
| - be searched for. If the current exception handler that this
|
| - Failure is being constructed in is handling an exception
|
| - raised by L{raiseException}, then this Failure will act like
|
| - the original Failure.
|
| - """
|
| - global count
|
| - count = count + 1
|
| - self.count = count
|
| - self.type = self.value = tb = None
|
| -
|
| - #strings Exceptions/Failures are bad, mmkay?
|
| - if isinstance(exc_value, (str, unicode)) and exc_type is None:
|
| - import warnings
|
| - warnings.warn(
|
| - "Don't pass strings (like %r) to failure.Failure (replacing with a DefaultException)." %
|
| - exc_value, DeprecationWarning, stacklevel=2)
|
| - exc_value = DefaultException(exc_value)
|
| -
|
| - stackOffset = 0
|
| -
|
| - if exc_value is None:
|
| - exc_value = self._findFailure()
|
| -
|
| - if exc_value is None:
|
| - self.type, self.value, tb = sys.exc_info()
|
| - if self.type is None:
|
| - raise NoCurrentExceptionError()
|
| - stackOffset = 1
|
| - elif exc_type is None:
|
| - if isinstance(exc_value, Exception):
|
| - self.type = exc_value.__class__
|
| - else: #allow arbitrary objects.
|
| - self.type = type(exc_value)
|
| - self.value = exc_value
|
| - else:
|
| - self.type = exc_type
|
| - self.value = exc_value
|
| - if isinstance(self.value, Failure):
|
| - self.__dict__ = self.value.__dict__
|
| - return
|
| - if tb is None:
|
| - if exc_tb:
|
| - tb = exc_tb
|
| -# else:
|
| -# log.msg("Erf, %r created with no traceback, %s %s." % (
|
| -# repr(self), repr(exc_value), repr(exc_type)))
|
| -# for s in traceback.format_stack():
|
| -# log.msg(s)
|
| -
|
| - frames = self.frames = []
|
| - stack = self.stack = []
|
| -
|
| - # added 2003-06-23 by Chris Armstrong. Yes, I actually have a
|
| - # use case where I need this traceback object, and I've made
|
| - # sure that it'll be cleaned up.
|
| - self.tb = tb
|
| -
|
| - if tb:
|
| - f = tb.tb_frame
|
| - elif not isinstance(self.value, Failure):
|
| - # we don't do frame introspection since it's expensive,
|
| - # and if we were passed a plain exception with no
|
| - # traceback, it's not useful anyway
|
| - f = stackOffset = None
|
| -
|
| - while stackOffset and f:
|
| - # This excludes this Failure.__init__ frame from the
|
| - # stack, leaving it to start with our caller instead.
|
| - f = f.f_back
|
| - stackOffset -= 1
|
| -
|
| - # Keeps the *full* stack. Formerly in spread.pb.print_excFullStack:
|
| - #
|
| - # The need for this function arises from the fact that several
|
| - # PB classes have the peculiar habit of discarding exceptions
|
| - # with bareword "except:"s. This premature exception
|
| - # catching means tracebacks generated here don't tend to show
|
| - # what called upon the PB object.
|
| -
|
| - while f:
|
| - localz = f.f_locals.copy()
|
| - if f.f_locals is f.f_globals:
|
| - globalz = {}
|
| - else:
|
| - globalz = f.f_globals.copy()
|
| - for d in globalz, localz:
|
| - if d.has_key("__builtins__"):
|
| - del d["__builtins__"]
|
| - stack.insert(0, [
|
| - f.f_code.co_name,
|
| - f.f_code.co_filename,
|
| - f.f_lineno,
|
| - localz.items(),
|
| - globalz.items(),
|
| - ])
|
| - f = f.f_back
|
| -
|
| - while tb is not None:
|
| - f = tb.tb_frame
|
| - localz = f.f_locals.copy()
|
| - if f.f_locals is f.f_globals:
|
| - globalz = {}
|
| - else:
|
| - globalz = f.f_globals.copy()
|
| - for d in globalz, localz:
|
| - if d.has_key("__builtins__"):
|
| - del d["__builtins__"]
|
| -
|
| - frames.append([
|
| - f.f_code.co_name,
|
| - f.f_code.co_filename,
|
| - tb.tb_lineno,
|
| - localz.items(),
|
| - globalz.items(),
|
| - ])
|
| - tb = tb.tb_next
|
| - if inspect.isclass(self.type) and issubclass(self.type, Exception):
|
| - parentCs = reflect.allYourBase(self.type)
|
| - self.parents = map(reflect.qual, parentCs)
|
| - self.parents.append(reflect.qual(self.type))
|
| - else:
|
| - self.parents = [self.type]
|
| -
|
| - def trap(self, *errorTypes):
|
| - """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.
|
| -
|
| - @type errorTypes: L{Exception}
|
| - """
|
| - error = self.check(*errorTypes)
|
| - if not error:
|
| - raise self
|
| - return error
|
| -
|
| - def check(self, *errorTypes):
|
| - """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.
|
| - """
|
| - for error in errorTypes:
|
| - err = error
|
| - if inspect.isclass(error) and issubclass(error, Exception):
|
| - err = reflect.qual(error)
|
| - if err in self.parents:
|
| - return error
|
| - return None
|
| -
|
| -
|
| - def raiseException(self):
|
| - """
|
| - raise the original exception, preserving traceback
|
| - information if available.
|
| - """
|
| - raise self.type, self.value, self.tb
|
| -
|
| -
|
| - def throwExceptionIntoGenerator(self, g):
|
| - """
|
| - 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.
|
| - """
|
| - return g.throw(self.type, self.value, self.tb)
|
| -
|
| -
|
| - def _findFailure(cls):
|
| - """
|
| - Find the failure that represents the exception currently in context.
|
| - """
|
| - tb = sys.exc_info()[-1]
|
| - if not tb:
|
| - return
|
| -
|
| - secondLastTb = None
|
| - lastTb = tb
|
| - while lastTb.tb_next:
|
| - secondLastTb = lastTb
|
| - lastTb = lastTb.tb_next
|
| -
|
| - lastFrame = lastTb.tb_frame
|
| -
|
| - # NOTE: f_locals.get('self') is used rather than
|
| - # f_locals['self'] because psyco frames do not contain
|
| - # anything in their locals() dicts. psyco makes debugging
|
| - # difficult anyhow, so losing the Failure objects (and thus
|
| - # the tracebacks) here when it is used is not that big a deal.
|
| -
|
| - # handle raiseException-originated exceptions
|
| - if lastFrame.f_code is cls.raiseException.func_code:
|
| - return lastFrame.f_locals.get('self')
|
| -
|
| - # handle throwExceptionIntoGenerator-originated exceptions
|
| - # this is tricky, and differs if the exception was caught
|
| - # inside the generator, or above it:
|
| -
|
| - # it is only really originating from
|
| - # throwExceptionIntoGenerator if the bottom of the traceback
|
| - # is a yield.
|
| - # Pyrex and Cython extensions create traceback frames
|
| - # with no co_code, but they can't yield so we know it's okay to just return here.
|
| - if ((not lastFrame.f_code.co_code) or
|
| - lastFrame.f_code.co_code[lastTb.tb_lasti] != cls._yieldOpcode):
|
| - return
|
| -
|
| - # if the exception was caught above the generator.throw
|
| - # (outside the generator), it will appear in the tb (as the
|
| - # second last item):
|
| - if secondLastTb:
|
| - frame = secondLastTb.tb_frame
|
| - if frame.f_code is cls.throwExceptionIntoGenerator.func_code:
|
| - return frame.f_locals.get('self')
|
| -
|
| - # if the exception was caught below the generator.throw
|
| - # (inside the generator), it will appear in the frames' linked
|
| - # list, above the top-level traceback item (which must be the
|
| - # generator frame itself, thus its caller is
|
| - # throwExceptionIntoGenerator).
|
| - frame = tb.tb_frame.f_back
|
| - if frame and frame.f_code is cls.throwExceptionIntoGenerator.func_code:
|
| - return frame.f_locals.get('self')
|
| -
|
| - _findFailure = classmethod(_findFailure)
|
| -
|
| - def __repr__(self):
|
| - return "<%s %s>" % (self.__class__, self.type)
|
| -
|
| - def __str__(self):
|
| - return "[Failure instance: %s]" % self.getBriefTraceback()
|
| -
|
| - def __getstate__(self):
|
| - """Avoid pickling objects in the traceback.
|
| - """
|
| - if self.pickled:
|
| - return self.__dict__
|
| - c = self.__dict__.copy()
|
| -
|
| - c['frames'] = [
|
| - [
|
| - v[0], v[1], v[2],
|
| - [(j[0], reflect.safe_repr(j[1])) for j in v[3]],
|
| - [(j[0], reflect.safe_repr(j[1])) for j in v[4]]
|
| - ] for v in self.frames
|
| - ]
|
| -
|
| - # added 2003-06-23. See comment above in __init__
|
| - c['tb'] = None
|
| -
|
| - if self.stack is not None:
|
| - # XXX: This is a band-aid. I can't figure out where these
|
| - # (failure.stack is None) instances are coming from.
|
| - c['stack'] = [
|
| - [
|
| - v[0], v[1], v[2],
|
| - [(j[0], reflect.safe_repr(j[1])) for j in v[3]],
|
| - [(j[0], reflect.safe_repr(j[1])) for j in v[4]]
|
| - ] for v in self.stack
|
| - ]
|
| -
|
| - c['pickled'] = 1
|
| - return c
|
| -
|
| - def cleanFailure(self):
|
| - """Remove references to other objects, replacing them with strings.
|
| - """
|
| - self.__dict__ = self.__getstate__()
|
| -
|
| - def getTracebackObject(self):
|
| - """
|
| - 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.
|
| - """
|
| - if self.tb is not None:
|
| - return self.tb
|
| - elif len(self.frames) > 0:
|
| - return _Traceback(self.frames)
|
| - else:
|
| - return None
|
| -
|
| - def getErrorMessage(self):
|
| - """Get a string of the exception which caused this Failure."""
|
| - if isinstance(self.value, Failure):
|
| - return self.value.getErrorMessage()
|
| - return reflect.safe_str(self.value)
|
| -
|
| - def getBriefTraceback(self):
|
| - io = StringIO()
|
| - self.printBriefTraceback(file=io)
|
| - return io.getvalue()
|
| -
|
| - def getTraceback(self, elideFrameworkCode=0, detail='default'):
|
| - io = StringIO()
|
| - self.printTraceback(file=io, elideFrameworkCode=elideFrameworkCode, detail=detail)
|
| - return io.getvalue()
|
| -
|
| - def printTraceback(self, file=None, elideFrameworkCode=0, detail='default'):
|
| - """Emulate Python's standard error reporting mechanism.
|
| - """
|
| - if file is None:
|
| - file = log.logerr
|
| - w = file.write
|
| -
|
| - # Preamble
|
| - if detail == 'verbose':
|
| - w( '*--- Failure #%d%s---\n' %
|
| - (self.count,
|
| - (self.pickled and ' (pickled) ') or ' '))
|
| - elif detail == 'brief':
|
| - if self.frames:
|
| - hasFrames = 'Traceback'
|
| - else:
|
| - hasFrames = 'Traceback (failure with no frames)'
|
| - w("%s: %s: %s\n" % (hasFrames, self.type, self.value))
|
| - else:
|
| - w( 'Traceback (most recent call last):\n')
|
| -
|
| - # Frames, formatted in appropriate style
|
| - if self.frames:
|
| - if not elideFrameworkCode:
|
| - format_frames(self.stack[-traceupLength:], w, detail)
|
| - w("%s\n" % (EXCEPTION_CAUGHT_HERE,))
|
| - format_frames(self.frames, w, detail)
|
| - elif not detail == 'brief':
|
| - # Yeah, it's not really a traceback, despite looking like one...
|
| - w("Failure: ")
|
| -
|
| - # postamble, if any
|
| - if not detail == 'brief':
|
| - # Unfortunately, self.type will not be a class object if this
|
| - # Failure was created implicitly from a string exception.
|
| - # qual() doesn't make any sense on a string, so check for this
|
| - # case here and just write out the string if that's what we
|
| - # have.
|
| - if isinstance(self.type, (str, unicode)):
|
| - w(self.type + "\n")
|
| - else:
|
| - w("%s: %s\n" % (reflect.qual(self.type),
|
| - reflect.safe_str(self.value)))
|
| - # chaining
|
| - if isinstance(self.value, Failure):
|
| - # TODO: indentation for chained failures?
|
| - file.write(" (chained Failure)\n")
|
| - self.value.printTraceback(file, elideFrameworkCode, detail)
|
| - if detail == 'verbose':
|
| - w('*--- End of Failure #%d ---\n' % self.count)
|
| -
|
| - def printBriefTraceback(self, file=None, elideFrameworkCode=0):
|
| - """Print a traceback as densely as possible.
|
| - """
|
| - self.printTraceback(file, elideFrameworkCode, detail='brief')
|
| -
|
| - def printDetailedTraceback(self, file=None, elideFrameworkCode=0):
|
| - """Print a traceback with detailed locals and globals information.
|
| - """
|
| - self.printTraceback(file, elideFrameworkCode, detail='verbose')
|
| -
|
| -# slyphon: make post-morteming exceptions tweakable
|
| -
|
| -DO_POST_MORTEM = True
|
| -
|
| -def _debuginit(self, exc_value=None, exc_type=None, exc_tb=None,
|
| - Failure__init__=Failure.__init__.im_func):
|
| - if (exc_value, exc_type, exc_tb) == (None, None, None):
|
| - exc = sys.exc_info()
|
| - if not exc[0] == self.__class__ and DO_POST_MORTEM:
|
| - print "Jumping into debugger for post-mortem of exception '%s':" % exc[1]
|
| - import pdb
|
| - pdb.post_mortem(exc[2])
|
| - Failure__init__(self, exc_value, exc_type, exc_tb)
|
| -
|
| -def startDebugMode():
|
| - """Enable debug hooks for Failures."""
|
| - Failure.__init__ = _debuginit
|
| -
|
| -
|
| -# Sibling imports - at the bottom and unqualified to avoid unresolvable
|
| -# circularity
|
| -import log
|
|
|