def getComponent(self, interface, registry=None, default=None): """Create or retrieve an adapter for the given interface. If such an adapter has already been created, retrieve it from the cache that this instance keeps of all its adapters. Adapters created through this mechanism may safely store system-specific state. If you want to register an adapter that will be created through getComponent, but you don't require (or don't want) your adapter to be cached and kept alive for the lifetime of this Componentized object, set the attribute 'temporaryAdapter' to True on your adapter class. If you want to automatically register an adapter for all appropriate interfaces (with addComponent), set the attribute 'multiComponent' to True on your adapter class. """ registry = getRegistry(registry) k = reflect.qual(interface) if self._adapterCache.has_key(k): return self._adapterCache[k] elif implements(self, interface): return self else: adapter = registry.getAdapter(self, interface, default, lambda k, ik, d: self.locateAdapterClass(k, ik, d, registry)) if adapter is not None and adapter is not _Nothing and not ( hasattr(adapter, "temporaryAdapter") and adapter.temporaryAdapter): self._adapterCache[k] = adapter if (hasattr(adapter, "multiComponent") and adapter.multiComponent and hasattr(adapter, '__implements__')): self.addComponent(adapter) return adapter
def check(self, *errorTypes): for error in errorTypes: err = error if isinstance(error, types.ClassType) and issubclass(error, Exception): err = reflect.qual(error) if err in self.parents: return error return None
def __getattr__(self, name): """A getattr method to cause a class to be refreshed. """ if name == '__del__': raise AttributeError("Without this, Python segfaults.") updateInstance(self) log.msg("(rebuilding stale %s instance (%s))" % (reflect.qual(self.__class__), name)) result = getattr(self, name) return result
def printTraceback(self, file=None, elideFrameworkCode=0, detail='default'): """ Emulate Python's standard error reporting mechanism. """ if file is None: #file = log.logerr file = sys.stderr # changed by teratorn 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 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 addComponent(self, component, ignoreClass=0, registry=None): """ Add a component to me, for all appropriate interfaces. In order to determine which interfaces are appropriate, the component's __implements__ attribute will be scanned. If the argument 'ignoreClass' is True, then all interfaces are considered appropriate. Otherwise, an 'appropriate' interface is one for which its class has been registered as an adapter for my class according to the rules of getComponent. @return: the list of appropriate interfaces """ for iface in tupleTreeToList(component.__implements__): if (ignoreClass or (self.locateAdapterClass(self.__class__, iface, None, registry) == component.__class__)): self._adapterCache[reflect.qual(iface)] = component
def rebuild(module, doLog=1): """Reload a module and do as much as possible to replace its references. """ global lastRebuild lastRebuild = time.time() if hasattr(module, 'ALLOW_TWISTED_REBUILD'): if not module.ALLOW_TWISTED_REBUILD: raise RuntimeError, "I am not allowed to be rebuilt." if doLog: log.msg( 'Rebuilding %s...' % str(module.__name__)) from twisted.python import components components.ALLOW_DUPLICATES = 1 d = module.__dict__ _modDictIDMap[id(d)] = module newclasses = {} classes = {} functions = {} values = {} if doLog: log.msg(' (scanning %s): ' % str(module.__name__)) for k, v in d.items(): if type(v) == types.ClassType: if v.__module__ == module.__name__: classes[v] = 1 if doLog: log.logfile.write("c") log.logfile.flush() elif type(v) == types.FunctionType: if v.func_globals is module.__dict__: functions[v] = 1 if doLog: log.logfile.write("f") log.logfile.flush() elif isinstance(v, type): if v.__module__ == module.__name__: newclasses[v] = 1 if doLog: log.logfile.write("o") log.logfile.flush() values.update(classes) values.update(functions) fromOldModule = values.has_key newclasses = newclasses.keys() classes = classes.keys() functions = functions.keys() if doLog: log.msg('') log.msg(' (reload %s)' % str(module.__name__)) reload(module) linecache.clearcache() if doLog: log.msg(' (cleaning %s): ' % str(module.__name__)) for clazz in classes: if getattr(module, clazz.__name__) is clazz: log.msg("WARNING: class %s not replaced by reload!" % reflect.qual(clazz)) else: if doLog: log.logfile.write("x") log.logfile.flush() clazz.__bases__ = () clazz.__dict__.clear() clazz.__getattr__ = __getattr__ clazz.__module__ = module.__name__ if newclasses: import gc for nclass in newclasses: ga = getattr(module, nclass.__name__) if ga is nclass: log.msg("WARNING: new-class %s not replaced by reload!" % reflect.qual(nclass)) else: for r in gc.get_referrers(nclass): if getattr(r, '__class__', None) is nclass: r.__class__ = ga if doLog: log.msg('') log.msg(' (fixing %s): ' % str(module.__name__)) modcount = 0 for mk, mod in sys.modules.items(): modcount = modcount + 1 if mod == module or mod is None: continue if not hasattr(mod, '__file__'): continue changed = 0 for k, v in mod.__dict__.items(): try: hash(v) except TypeError: continue if fromOldModule(v): if type(v) == types.ClassType: if doLog: log.logfile.write("c") log.logfile.flush() nv = latestClass(v) else: if doLog: log.logfile.write("f") log.logfile.flush() nv = latestFunction(v) changed = 1 setattr(mod, k, nv) else: if type(v) == types.ClassType: for base in v.__bases__: if fromOldModule(base): latestClass(v) if doLog and not changed and ((modcount % 10) ==0) : log.logfile.write(".") log.logfile.flush() components.ALLOW_DUPLICATES = 0 if doLog: log.msg('') log.msg(' Rebuilt %s.' % str(module.__name__)) return module
def upgradeToVersion1(self): # To let Componentized instances interact correctly with # rebuild(), we cannot use class objects as dictionary keys. for (k, v) in self._adapterCache.items(): self._adapterCache[reflect.qual(k)] = v
def unsetComponent(self, interfaceClass): """Remove my component specified by the given interface class.""" del self._adapterCache[reflect.qual(interfaceClass)]
def setComponent(self, interfaceClass, component): """ """ self._adapterCache[reflect.qual(interfaceClass)] = component
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 rebuild(module, doLog=1): """Reload a module and do as much as possible to replace its references. """ global lastRebuild lastRebuild = time.time() if hasattr(module, 'ALLOW_TWISTED_REBUILD'): # Is this module allowed to be rebuilt? if not module.ALLOW_TWISTED_REBUILD: raise RuntimeError, "I am not allowed to be rebuilt." if doLog: log.msg('Rebuilding %s...' % str(module.__name__)) ## Safely handle adapter re-registration from twisted.python import components components.ALLOW_DUPLICATES = 1 d = module.__dict__ _modDictIDMap[id(d)] = module newclasses = {} classes = {} functions = {} values = {} if doLog: log.msg(' (scanning %s): ' % str(module.__name__)) for k, v in d.items(): if type(v) == types.ClassType: # Failure condition -- instances of classes with buggy # __hash__/__cmp__ methods referenced at the module level... if v.__module__ == module.__name__: classes[v] = 1 if doLog: log.logfile.write("c") log.logfile.flush() elif type(v) == types.FunctionType: if v.func_globals is module.__dict__: functions[v] = 1 if doLog: log.logfile.write("f") log.logfile.flush() elif isinstance(v, type): if v.__module__ == module.__name__: newclasses[v] = 1 if doLog: log.logfile.write("o") log.logfile.flush() values.update(classes) values.update(functions) fromOldModule = values.has_key newclasses = newclasses.keys() classes = classes.keys() functions = functions.keys() if doLog: log.msg('') log.msg(' (reload %s)' % str(module.__name__)) # Boom. reload(module) # Make sure that my traceback printing will at least be recent... linecache.clearcache() if doLog: log.msg(' (cleaning %s): ' % str(module.__name__)) for clazz in classes: if getattr(module, clazz.__name__) is clazz: log.msg("WARNING: class %s not replaced by reload!" % reflect.qual(clazz)) else: if doLog: log.logfile.write("x") log.logfile.flush() clazz.__bases__ = () clazz.__dict__.clear() clazz.__getattr__ = __getattr__ clazz.__module__ = module.__name__ if newclasses: import gc for nclass in newclasses: ga = getattr(module, nclass.__name__) if ga is nclass: log.msg("WARNING: new-class %s not replaced by reload!" % reflect.qual(nclass)) else: for r in gc.get_referrers(nclass): if getattr(r, '__class__', None) is nclass: r.__class__ = ga if doLog: log.msg('') log.msg(' (fixing %s): ' % str(module.__name__)) modcount = 0 for mk, mod in sys.modules.items(): modcount = modcount + 1 if mod == module or mod is None: continue if not hasattr(mod, '__file__'): # It's a builtin module; nothing to replace here. continue changed = 0 for k, v in mod.__dict__.items(): try: hash(v) except TypeError: continue if fromOldModule(v): if type(v) == types.ClassType: if doLog: log.logfile.write("c") log.logfile.flush() nv = latestClass(v) else: if doLog: log.logfile.write("f") log.logfile.flush() nv = latestFunction(v) changed = 1 setattr(mod, k, nv) else: # Replace bases of non-module classes just to be sure. if type(v) == types.ClassType: for base in v.__bases__: if fromOldModule(base): latestClass(v) if doLog and not changed and ((modcount % 10) == 0): log.logfile.write(".") log.logfile.flush() components.ALLOW_DUPLICATES = 0 if doLog: log.msg('') log.msg(' Rebuilt %s.' % str(module.__name__)) return module
def rebuild(module, doLog=1): """Reload a module and do as much as possible to replace its references. """ global lastRebuild lastRebuild = time.time() if hasattr(module, 'ALLOW_TWISTED_REBUILD'): # Is this module allowed to be rebuilt? if not module.ALLOW_TWISTED_REBUILD: raise RuntimeError, "I am not allowed to be rebuilt." if doLog: log.msg( 'Rebuilding %s...' % str(module.__name__)) ## Safely handle adapter re-registration from twisted.python import components components.ALLOW_DUPLICATES = 1 d = module.__dict__ _modDictIDMap[id(d)] = module newclasses = {} classes = {} functions = {} values = {} if doLog: log.msg(' (scanning %s): ' % str(module.__name__)) for k, v in d.items(): if type(v) == types.ClassType: # Failure condition -- instances of classes with buggy # __hash__/__cmp__ methods referenced at the module level... if v.__module__ == module.__name__: classes[v] = 1 if doLog: log.logfile.write("c") log.logfile.flush() elif type(v) == types.FunctionType: if v.func_globals is module.__dict__: functions[v] = 1 if doLog: log.logfile.write("f") log.logfile.flush() elif object and isinstance(v, type): if v.__module__ == module.__name__: newclasses[v] = 1 if doLog: log.logfile.write("o") log.logfile.flush() values.update(classes) values.update(functions) fromOldModule = values.has_key newclasses = newclasses.keys() classes = classes.keys() functions = functions.keys() if doLog: log.msg('') log.msg(' (reload %s)' % str(module.__name__)) # Boom. reload(module) # Make sure that my traceback printing will at least be recent... linecache.clearcache() if doLog: log.msg(' (cleaning %s): ' % str(module.__name__)) for clazz in classes: if getattr(module, clazz.__name__) is clazz: log.msg("WARNING: class %s not replaced by reload!" % reflect.qual(clazz)) else: if doLog: log.logfile.write("x") log.logfile.flush() clazz.__bases__ = () clazz.__dict__.clear() clazz.__getattr__ = __getattr__ clazz.__module__ = module.__name__ if newclasses: import gc if (2, 2, 0) <= sys.version_info[:3] < (2, 2, 2): hasBrokenRebuild = 1 gc_objects = gc.get_objects() else: hasBrokenRebuild = 0 for nclass in newclasses: ga = getattr(module, nclass.__name__) if ga is nclass: log.msg("WARNING: new-class %s not replaced by reload!" % reflect.qual(nclass)) else: if hasBrokenRebuild: for r in gc_objects: if not getattr(r, '__class__', None) is nclass: continue r.__class__ = ga else: for r in gc.get_referrers(nclass): if getattr(r, '__class__', None) is nclass: r.__class__ = ga if doLog: log.msg('') log.msg(' (fixing %s): ' % str(module.__name__)) modcount = 0 for mk, mod in sys.modules.items(): modcount = modcount + 1 if mod == module or mod is None: continue if not hasattr(mod, '__file__'): # It's a builtin module; nothing to replace here. continue changed = 0 for k, v in mod.__dict__.items(): try: hash(v) except TypeError: continue if fromOldModule(v): if type(v) == types.ClassType: if doLog: log.logfile.write("c") log.logfile.flush() nv = latestClass(v) else: if doLog: log.logfile.write("f") log.logfile.flush() nv = latestFunction(v) changed = 1 setattr(mod, k, nv) else: # Replace bases of non-module classes just to be sure. if type(v) == types.ClassType: for base in v.__bases__: if fromOldModule(base): latestClass(v) if doLog and not changed and ((modcount % 10) ==0) : log.logfile.write(".") log.logfile.flush() components.ALLOW_DUPLICATES = 0 if doLog: log.msg('') log.msg(' Rebuilt %s.' % str(module.__name__)) return module