def showwarning(self, message, category, filename, lineno, file=None, line=None): """ Twisted-enabled wrapper around L{warnings.showwarning}. If C{file} is C{None}, the default behaviour is to emit the warning to the log system, otherwise the original L{warnings.showwarning} Python function is called. """ if file is None: self.msg( warning=message, category=reflect.qual(category), filename=filename, lineno=lineno, format="%(filename)s:%(lineno)s: %(category)s: %(warning)s") else: if sys.version_info < (2, 6): _oldshowwarning(message, category, filename, lineno, file) else: _oldshowwarning(message, category, filename, lineno, file, line)
def proxyForInterface(iface, originalAttribute="original"): """ Create a class which proxies all method calls which adhere to an interface to another provider of that interface. This function is intended for creating specialized proxies. The typical way to use it is by subclassing the result:: class MySpecializedProxy(proxyForInterface(IFoo)): def someInterfaceMethod(self, arg): if arg == 3: return 3 return self.original.someInterfaceMethod(arg) @param iface: The Interface to which the resulting object will conform, and which the wrapped object must provide. @param originalAttribute: name of the attribute used to save the original object in the resulting class. Default to C{original}. @type originalAttribute: C{str} @return: A class whose constructor takes the original object as its only argument. Constructing the class creates the proxy. """ def __init__(self, original): setattr(self, originalAttribute, original) contents = {"__init__": __init__} for name in iface: contents[name] = _ProxyDescriptor(name, originalAttribute) proxy = type("(Proxy for %s)" % (reflect.qual(iface),), (object,), contents) declarations.classImplements(proxy, iface) return proxy
def getComponent(self, interface, 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. """ k = reflect.qual(interface) if k in self._adapterCache: return self._adapterCache[k] else: adapter = interface.__adapt__(self) if adapter is not None and not (hasattr( adapter, "temporaryAdapter") and adapter.temporaryAdapter): self._adapterCache[k] = adapter if (hasattr(adapter, "multiComponent") and adapter.multiComponent): self.addComponent(adapter) if adapter is None: return default return adapter
def getComponent(self, interface, 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. """ k = reflect.qual(interface) if k in self._adapterCache: return self._adapterCache[k] else: adapter = interface.__adapt__(self) if adapter is not None and not (hasattr(adapter, "temporaryAdapter") and adapter.temporaryAdapter): self._adapterCache[k] = adapter if hasattr(adapter, "multiComponent") and adapter.multiComponent: self.addComponent(adapter) if adapter is None: return default return adapter
def proxyForInterface(iface, originalAttribute='original'): """ Create a class which proxies all method calls which adhere to an interface to another provider of that interface. This function is intended for creating specialized proxies. The typical way to use it is by subclassing the result:: class MySpecializedProxy(proxyForInterface(IFoo)): def someInterfaceMethod(self, arg): if arg == 3: return 3 return self.original.someInterfaceMethod(arg) @param iface: The Interface to which the resulting object will conform, and which the wrapped object must provide. @param originalAttribute: name of the attribute used to save the original object in the resulting class. Default to C{original}. @type originalAttribute: C{str} @return: A class whose constructor takes the original object as its only argument. Constructing the class creates the proxy. """ def __init__(self, original): setattr(self, originalAttribute, original) contents = {"__init__": __init__} for name in iface: contents[name] = _ProxyDescriptor(name, originalAttribute) proxy = type("(Proxy for %s)" % (reflect.qual(iface), ), (object, ), contents) declarations.classImplements(proxy, iface) return proxy
def doRead(self): """ Called when data is available for reading. Subclasses must override this method. The result will be interpreted in the same way as a result of doWrite(). """ raise NotImplementedError("%s does not implement doRead" % reflect.qual(self.__class__))
def __repr__(self): return "<%s run=%d errors=%d failures=%d todos=%d dones=%d skips=%d>" % ( reflect.qual(self.__class__), self.testsRun, len(self.errors), len(self.failures), len(self.expectedFailures), len(self.skips), len(self.unexpectedSuccesses), )
def writeSomeData(self, data): """ Write as much as possible of the given data, immediately. This is called to invoke the lower-level writing functionality, such as a socket's send() method, or a file's write(); this method returns an integer or an exception. If an integer, it is the number of bytes written (possibly zero); if an exception, it indicates the connection was lost. """ raise NotImplementedError("%s does not implement writeSomeData" % reflect.qual(self.__class__))
def _makeContext(self): ctx = self._contextFactory(self.method) # Disallow insecure SSLv2. Applies only for SSLv23_METHOD. ctx.set_options(SSL.OP_NO_SSLv2) if self.certificate is not None and self.privateKey is not None: ctx.use_certificate(self.certificate) ctx.use_privatekey(self.privateKey) for extraCert in self.extraCertChain: ctx.add_extra_chain_cert(extraCert) # Sanity check ctx.check_privatekey() verifyFlags = SSL.VERIFY_NONE if self.verify: verifyFlags = SSL.VERIFY_PEER if self.requireCertificate: verifyFlags |= SSL.VERIFY_FAIL_IF_NO_PEER_CERT if self.verifyOnce: verifyFlags |= SSL.VERIFY_CLIENT_ONCE if self.caCerts: store = ctx.get_cert_store() for cert in self.caCerts: store.add_cert(cert) # It'd be nice if pyOpenSSL let us pass None here for this behavior (as # the underlying OpenSSL API call allows NULL to be passed). It # doesn't, so we'll supply a function which does the same thing. def _verifyCallback(conn, cert, errno, depth, preverify_ok): return preverify_ok ctx.set_verify(verifyFlags, _verifyCallback) if self.verifyDepth is not None: ctx.set_verify_depth(self.verifyDepth) if self.enableSingleUseKeys: ctx.set_options(SSL.OP_SINGLE_DH_USE) if self.fixBrokenPeers: ctx.set_options(self._OP_ALL) if self.enableSessions: name = "%s-%d" % (reflect.qual(self.__class__), _sessionCounter()) sessionName = md5(networkString(name)).hexdigest() ctx.set_session_id(sessionName) if not self.enableSessionTickets: ctx.set_options(self._OP_NO_TICKET) return ctx
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 _makeContext(self): ctx = self._contextFactory(self.method) ctx.set_options(self._options) if self.certificate is not None and self.privateKey is not None: ctx.use_certificate(self.certificate) ctx.use_privatekey(self.privateKey) for extraCert in self.extraCertChain: ctx.add_extra_chain_cert(extraCert) # Sanity check ctx.check_privatekey() verifyFlags = SSL.VERIFY_NONE if self.verify: verifyFlags = SSL.VERIFY_PEER if self.requireCertificate: verifyFlags |= SSL.VERIFY_FAIL_IF_NO_PEER_CERT if self.verifyOnce: verifyFlags |= SSL.VERIFY_CLIENT_ONCE if self.caCerts: store = ctx.get_cert_store() for cert in self.caCerts: store.add_cert(cert) # It'd be nice if pyOpenSSL let us pass None here for this behavior (as # the underlying OpenSSL API call allows NULL to be passed). It # doesn't, so we'll supply a function which does the same thing. def _verifyCallback(conn, cert, errno, depth, preverify_ok): return preverify_ok ctx.set_verify(verifyFlags, _verifyCallback) if self.verifyDepth is not None: ctx.set_verify_depth(self.verifyDepth) if self.enableSessions: name = "%s-%d" % (reflect.qual(self.__class__), _sessionCounter()) sessionName = md5(networkString(name)).hexdigest() ctx.set_session_id(sessionName) if self.dhParameters: ctx.load_tmp_dh(self.dhParameters._dhFile.path) ctx.set_cipher_list(nativeString(self._cipherString)) return ctx
def showwarning(self, message, category, filename, lineno, file=None, line=None): """ Twisted-enabled wrapper around L{warnings.showwarning}. If C{file} is C{None}, the default behaviour is to emit the warning to the log system, otherwise the original L{warnings.showwarning} Python function is called. """ if file is None: self.msg(warning=message, category=reflect.qual(category), filename=filename, lineno=lineno, format="%(filename)s:%(lineno)s: %(category)s: %(warning)s") else: if sys.version_info < (2, 6): _oldshowwarning(message, category, filename, lineno, file) else: _oldshowwarning(message, category, filename, lineno, file, line)
def assertDefaultTraceback(self, captureVars=False): """ Assert that L{printTraceback} produces and prints a default traceback. The default traceback consists of a header:: Traceback (most recent call last): The body with traceback:: File "/twisted/trial/_synctest.py", line 1180, in _run runWithWarningsSuppressed(suppress, method) And the footer:: --- <exception caught here> --- File "twisted/test/test_failure.py", line 39, in getDivisionFailure 1/0 exceptions.ZeroDivisionError: float division @param captureVars: Enables L{Failure.captureVars}. @type captureVars: C{bool} """ if captureVars: exampleLocalVar = 'xyzzy' f = getDivisionFailure(captureVars=captureVars) out = NativeStringIO() f.printTraceback(out) tb = out.getvalue() stack = '' for method, filename, lineno, localVars, globalVars in f.frames: stack += ' File "%s", line %s, in %s\n' % (filename, lineno, method) stack += ' %s\n' % (linecache.getline(filename, lineno).strip(), ) self.assertTracebackFormat( tb, "Traceback (most recent call last):", "%s\n%s%s: %s\n" % (failure.EXCEPTION_CAUGHT_HERE, stack, reflect.qual( f.type), reflect.safe_str(f.value))) if captureVars: self.assertEqual(None, re.search('exampleLocalVar.*xyzzy', tb))
def assertDefaultTraceback(self, captureVars=False): """ Assert that L{printTraceback} produces and prints a default traceback. The default traceback consists of a header:: Traceback (most recent call last): The body with traceback:: File "/twisted/trial/_synctest.py", line 1180, in _run runWithWarningsSuppressed(suppress, method) And the footer:: --- <exception caught here> --- File "twisted/test/test_failure.py", line 39, in getDivisionFailure 1/0 exceptions.ZeroDivisionError: float division @param captureVars: Enables L{Failure.captureVars}. @type captureVars: C{bool} """ if captureVars: exampleLocalVar = 'xyzzy' f = getDivisionFailure(captureVars=captureVars) out = NativeStringIO() f.printTraceback(out) tb = out.getvalue() stack = '' for method, filename, lineno, localVars, globalVars in f.frames: stack += ' File "%s", line %s, in %s\n' % (filename, lineno, method) stack += ' %s\n' % (linecache.getline( filename, lineno).strip(),) self.assertTracebackFormat(tb, "Traceback (most recent call last):", "%s\n%s%s: %s\n" % (failure.EXCEPTION_CAUGHT_HERE, stack, reflect.qual(f.type), reflect.safe_str(f.value))) if captureVars: self.assertEqual(None, re.search('exampleLocalVar.*xyzzy', tb))
def addComponent(self, component, ignoreClass=0): """ Add a component to me, for all appropriate interfaces. In order to determine which interfaces are appropriate, the component's provided interfaces 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 declarations.providedBy(component): if ignoreClass or (self.locateAdapterClass(self.__class__, iface, None) == component.__class__): self._adapterCache[reflect.qual(iface)] = component
def addComponent(self, component, ignoreClass=0): """ Add a component to me, for all appropriate interfaces. In order to determine which interfaces are appropriate, the component's provided interfaces 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 declarations.providedBy(component): if (ignoreClass or (self.locateAdapterClass( self.__class__, iface, None) == component.__class__)): self._adapterCache[reflect.qual(iface)] = component
def printTraceback(self, file=None, elideFrameworkCode=False, detail='default'): """ 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'}. """ if file is None: from twisted.python import log file = log.logerr w = file.write if detail == 'verbose' and not self.captureVars: # We don't have any locals or globals, so rather than show them as # empty make the output explicitly say that we don't have them at # all. formatDetail = 'verbose-vars-not-captured' else: formatDetail = detail # 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, reflect.safe_str( self.type), reflect.safe_str(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, formatDetail) w("%s\n" % (EXCEPTION_CAUGHT_HERE, )) format_frames(self.frames, w, formatDetail) elif not detail == 'brief': # Yeah, it's not really a traceback, despite looking like one... w("Failure: ") # postamble, if any if not detail == 'brief': 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 removeAll(self): raise NotImplementedError( reflect.qual(self.__class__) + " did not implement removeAll")
def getWriters(self): raise NotImplementedError( reflect.qual(self.__class__) + " did not implement getWriters")
def doIteration(self, delay): """ Do one iteration over the readers and writers which have been added. """ raise NotImplementedError( reflect.qual(self.__class__) + " did not implement doIteration")
def __getattr__(self, k): kstring='get_%s'%k if hasattr(self.__class__,kstring): return getattr(self,kstring)() raise AttributeError("%s instance has no accessor for: %s" % (qual(self.__class__),k))
def setComponent(self, interfaceClass, component): """ Cache a provider of the given interface. """ self._adapterCache[reflect.qual(interfaceClass)] = component
def getDestination(self): raise NotImplementedError( reflect.qual(self.__class__) + " did not implement " "getDestination")
def doWrite(self): """Raises a RuntimeError""" raise RuntimeError("doWrite called on a %s" % reflect.qual(self.__class__))
def addReader(self, reader): raise NotImplementedError( reflect.qual(self.__class__) + " did not implement addReader")
def assertDetailedTraceback(self, captureVars=False, cleanFailure=False): """ Assert that L{printDetailedTraceback} produces and prints a detailed traceback. The detailed traceback consists of a header:: *--- Failure #20 --- The body contains the stacktrace:: /twisted/trial/_synctest.py:1180: _run(...) /twisted/python/util.py:1076: runWithWarningsSuppressed(...) --- <exception caught here> --- /twisted/test/test_failure.py:39: getDivisionFailure(...) If C{captureVars} is enabled the body also includes a list of globals and locals:: [ Locals ] exampleLocalVar : 'xyz' ... ( Globals ) ... Or when C{captureVars} is disabled:: [Capture of Locals and Globals disabled (use captureVars=True)] When C{cleanFailure} is enabled references to other objects are removed and replaced with strings. And finally the footer with the L{Failure}'s value:: exceptions.ZeroDivisionError: float division *--- End of Failure #20 --- @param captureVars: Enables L{Failure.captureVars}. @type captureVars: C{bool} @param cleanFailure: Enables L{Failure.cleanFailure}. @type cleanFailure: C{bool} """ if captureVars: exampleLocalVar = 'xyz' f = getDivisionFailure(captureVars=captureVars) out = NativeStringIO() if cleanFailure: f.cleanFailure() f.printDetailedTraceback(out) tb = out.getvalue() start = "*--- Failure #%d%s---\n" % (f.count, (f.pickled and ' (pickled) ') or ' ') end = "%s: %s\n*--- End of Failure #%s ---\n" % (reflect.qual(f.type), reflect.safe_str(f.value), f.count) self.assertTracebackFormat(tb, start, end) # Variables are printed on lines with 2 leading spaces. linesWithVars = [line for line in tb.splitlines() if line.startswith(' ')] if captureVars: self.assertNotEqual([], linesWithVars) if cleanFailure: line = ' exampleLocalVar : "\'xyz\'"' else: line = " exampleLocalVar : 'xyz'" self.assertIn(line, linesWithVars) else: self.assertEqual([], linesWithVars) self.assertIn(' [Capture of Locals and Globals disabled (use ' 'captureVars=True)]\n', tb)
def __repr__(self): return ('<%s run=%d errors=%d failures=%d todos=%d dones=%d skips=%d>' % (reflect.qual(self.__class__), self.testsRun, len(self.errors), len(self.failures), len(self.expectedFailures), len(self.skips), len(self.unexpectedSuccesses)))
def unsetComponent(self, interfaceClass): """Remove my component specified by the given interface class.""" del self._adapterCache[reflect.qual(interfaceClass)]
def logPrefix(self): """Returns the name of my class, to prefix log entries with. """ return reflect.qual(self.factory.__class__)
def printTraceback(self, file=None, elideFrameworkCode=False, detail='default'): """ 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'}. """ if file is None: from twisted.python import log file = log.logerr w = file.write if detail == 'verbose' and not self.captureVars: # We don't have any locals or globals, so rather than show them as # empty make the output explicitly say that we don't have them at # all. formatDetail = 'verbose-vars-not-captured' else: formatDetail = detail # 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, reflect.safe_str(self.type), reflect.safe_str(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, formatDetail) w("%s\n" % (EXCEPTION_CAUGHT_HERE,)) format_frames(self.frames, w, formatDetail) elif not detail == 'brief': # Yeah, it's not really a traceback, despite looking like one... w("Failure: ") # postamble, if any if not detail == 'brief': 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 installWaker(self): raise NotImplementedError( reflect.qual(self.__class__) + " did not implement installWaker")
def removeWriter(self, writer): raise NotImplementedError( reflect.qual(self.__class__) + " did not implement removeWriter")
def assertDetailedTraceback(self, captureVars=False, cleanFailure=False): """ Assert that L{printDetailedTraceback} produces and prints a detailed traceback. The detailed traceback consists of a header:: *--- Failure #20 --- The body contains the stacktrace:: /twisted/trial/_synctest.py:1180: _run(...) /twisted/python/util.py:1076: runWithWarningsSuppressed(...) --- <exception caught here> --- /twisted/test/test_failure.py:39: getDivisionFailure(...) If C{captureVars} is enabled the body also includes a list of globals and locals:: [ Locals ] exampleLocalVar : 'xyz' ... ( Globals ) ... Or when C{captureVars} is disabled:: [Capture of Locals and Globals disabled (use captureVars=True)] When C{cleanFailure} is enabled references to other objects are removed and replaced with strings. And finally the footer with the L{Failure}'s value:: exceptions.ZeroDivisionError: float division *--- End of Failure #20 --- @param captureVars: Enables L{Failure.captureVars}. @type captureVars: C{bool} @param cleanFailure: Enables L{Failure.cleanFailure}. @type cleanFailure: C{bool} """ if captureVars: exampleLocalVar = 'xyz' f = getDivisionFailure(captureVars=captureVars) out = NativeStringIO() if cleanFailure: f.cleanFailure() f.printDetailedTraceback(out) tb = out.getvalue() start = "*--- Failure #%d%s---\n" % (f.count, (f.pickled and ' (pickled) ') or ' ') end = "%s: %s\n*--- End of Failure #%s ---\n" % (reflect.qual( f.type), reflect.safe_str(f.value), f.count) self.assertTracebackFormat(tb, start, end) # Variables are printed on lines with 2 leading spaces. linesWithVars = [ line for line in tb.splitlines() if line.startswith(' ') ] if captureVars: self.assertNotEqual([], linesWithVars) if cleanFailure: line = ' exampleLocalVar : "\'xyz\'"' else: line = " exampleLocalVar : 'xyz'" self.assertIn(line, linesWithVars) else: self.assertEqual([], linesWithVars) self.assertIn( ' [Capture of Locals and Globals disabled (use ' 'captureVars=True)]\n', tb)
def _getLogPrefix(self): return reflect.qual(self._factory.__class__)
def doWrite(self): """Raises a RuntimeError""" raise RuntimeError( "doWrite called on a %s" % reflect.qual(self.__class__))