def test_versionMetadata(self): """ Deprecating a function adds version information to the decorated version of that function. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(dummyCallable) self.assertEqual(version, dummy.deprecatedVersion)
def test_deprecatedPreservesName(self): """ The decorated function has the same name as the original. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(dummyCallable) self.assertEqual(dummyCallable.__name__, dummy.__name__) self.assertEqual(qual(dummyCallable), qual(dummy))
def deprecated(a): # the stacklevel is important here, because as the function is # recursive, the warnings produced have a different stack, but we # want to be sure that only the first warning is tested against warnings.warn("Woo deprecated", category=PendingDeprecationWarning, stacklevel=2) i[0] += 1 if i[0] < 3: return deprecated(a) else: return a
def test_deprecatedUpdatesDocstring(self): """ The docstring of the deprecated function is appended with information about the deprecation. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(dummyCallable) _appendToDocstring(dummyCallable, _getDeprecationDocstring(version)) self.assertEqual(dummyCallable.__doc__, dummy.__doc__)
def test_deprecateEmitsWarning(self): """ Decorating a callable with L{deprecated} emits a warning. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(dummyCallable) def addStackLevel(): dummy() self.assertWarns( DeprecationWarning, getDeprecationWarningString(dummyCallable, version), __file__, addStackLevel)
def test_deprecatedUpdatesDocstring(self): """ The docstring of the deprecated function is appended with information about the deprecation. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(dummyCallable) _appendToDocstring( dummyCallable, _getDeprecationDocstring(version)) self.assertEqual(dummyCallable.__doc__, dummy.__doc__)
def test_nestedDeprecation(self): """ L{callDeprecated} ignores all deprecations apart from the first. Multiple warnings are generated when a deprecated function calls another deprecated function. The first warning is the one generated by the explicitly called function. That's the warning that we care about. """ differentVersion = Version('Foo', 1, 2, 3) def nestedDeprecation(*args): return self.oldMethod(*args) nestedDeprecation = deprecated(differentVersion)(nestedDeprecation) self.callDeprecated(differentVersion, nestedDeprecation, 24)
def test_deprecateEmitsWarning(self): """ Decorating a callable with L{deprecated} emits a warning. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(dummyCallable) def addStackLevel(): dummy() with catch_warnings(record=True) as caught: simplefilter("always") addStackLevel() self.assertEqual(caught[0].category, DeprecationWarning) self.assertEqual(str(caught[0].message), getDeprecationWarningString(dummyCallable, version)) # rstrip in case .pyc/.pyo self.assertEqual(caught[0].filename.rstrip('co'), __file__.rstrip('co'))
def test_deprecatedReplacementWithCallable(self): """ L{deprecated} takes an additional replacement parameter that can be used to indicate the new, non-deprecated method developers should use. If the replacement parameter is a callable, its fully qualified name will be interpolated into the warning message. """ version = Version('Twisted', 8, 0, 0) decorator = deprecated(version, replacement=dummyReplacementMethod) dummy = decorator(dummyCallable) self.assertEqual(dummy.__doc__, "\n" " Do nothing.\n\n" " This is used to test the deprecation decorators.\n\n" " Deprecated in Twisted 8.0.0; please use " "%s.dummyReplacementMethod instead.\n" " " % (__name__,))
def test_deprecatedReplacement(self): """ L{deprecated} takes an additional replacement parameter that can be used to indicate the new, non-deprecated method developers should use. If the replacement parameter is a string, it will be interpolated directly into the warning message. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version, "something.foobar")(dummyCallable) self.assertEqual( dummy.__doc__, "\n" " Do nothing.\n\n" " This is used to test the deprecation decorators.\n\n" " Deprecated in Twisted 8.0.0; please use " "something.foobar" " instead.\n" " ")
def test_deprecatedReplacementWithCallable(self): """ L{deprecated} takes an additional replacement parameter that can be used to indicate the new, non-deprecated method developers should use. If the replacement parameter is a callable, its fully qualified name will be interpolated into the warning message. """ version = Version('Twisted', 8, 0, 0) decorator = deprecated(version, replacement=dummyReplacementMethod) dummy = decorator(dummyCallable) self.assertEqual( dummy.__doc__, "\n" " Do nothing.\n\n" " This is used to test the deprecation decorators.\n\n" " Deprecated in Twisted 8.0.0; please use " "%s.dummyReplacementMethod instead.\n" " " % (__name__, ))
def test_deprecatedReplacement(self): """ L{deprecated} takes an additional replacement parameter that can be used to indicate the new, non-deprecated method developers should use. If the replacement parameter is a string, it will be interpolated directly into the warning message. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version, "something.foobar")(dummyCallable) self.assertEqual(dummy.__doc__, "\n" " Do nothing.\n\n" " This is used to test the deprecation decorators.\n\n" " Deprecated in Twisted 8.0.0; please use " "something.foobar" " instead.\n" " ")
def test_deprecatedUpdatesDocstring(self): """ The docstring of the deprecated function is appended with information about the deprecation. """ def localDummyCallable(): """ Do nothing. This is used to test the deprecation decorators. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(localDummyCallable) _appendToDocstring(localDummyCallable, _getDeprecationDocstring(version, '')) self.assertEqual(localDummyCallable.__doc__, dummy.__doc__)
def test_deprecatedUpdatesDocstring(self): """ The docstring of the deprecated function is appended with information about the deprecation. """ def localDummyCallable(): """ Do nothing. This is used to test the deprecation decorators. """ version = Version('Twisted', 8, 0, 0) dummy = deprecated(version)(localDummyCallable) _appendToDocstring( localDummyCallable, _getDeprecationDocstring(version, '')) self.assertEqual(localDummyCallable.__doc__, dummy.__doc__)
def test_nestedDeprecation(self): """ L{callDeprecated} ignores all deprecations apart from the first. Multiple warnings are generated when a deprecated function calls another deprecated function. The first warning is the one generated by the explicitly called function. That's the warning that we care about. """ differentVersion = Version('Foo', 1, 2, 3) def nestedDeprecation(*args): return oldMethod(*args) nestedDeprecation = deprecated(differentVersion)(nestedDeprecation) self.callDeprecated(differentVersion, nestedDeprecation, 24) # The oldMethod deprecation should have been emitted too, not captured # by callDeprecated. Flush it now to make sure it did happen and to # prevent it from showing up on stdout. warningsShown = self.flushWarnings() self.assertEqual(len(warningsShown), 1)
def __call__(self, *args, **kw): """Asynchronously invoke a remote method. """ return self.obj.broker._sendMessage('',self.obj.perspective, self.obj.luid, self.name, args, kw) def noOperation(*args, **kw): """ Do nothing. Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit... """ noOperation = deprecated(Version("twisted", 8, 2, 0))(noOperation) class PBConnectionLost(Exception): pass def printTraceback(tb): """ Print a traceback (string) to the standard log. """ log.msg('Perspective Broker Traceback:' ) log.msg(tb) printTraceback = deprecated(Version("twisted", 8, 2, 0))(printTraceback)
self.oldMethod, 'foo') self.assertIn(getVersionString(self.version), str(exception)) self.assertIn(getVersionString(differentVersion), str(exception)) def test_nestedDeprecation(self): """ L{callDeprecated} ignores all deprecations apart from the first. Multiple warnings are generated when a deprecated function calls another deprecated function. The first warning is the one generated by the explicitly called function. That's the warning that we care about. """ differentVersion = Version('Foo', 1, 2, 3) def nestedDeprecation(*args): return self.oldMethod(*args) nestedDeprecation = deprecated(differentVersion)(nestedDeprecation) self.callDeprecated(differentVersion, nestedDeprecation, 24) # The oldMethod deprecation should have been emitted too, not captured # by callDeprecated. Flush it now to make sure it did happen and to # prevent it from showing up on stdout. warningsShown = self.flushWarnings() self.assertEqual(len(warningsShown), 1) TestCallDeprecated.oldMethod = deprecated(TestCallDeprecated.version)( TestCallDeprecated.oldMethod)
def _makeOptions(self, pattern, enums): options = super(RadioGroupInput, self)._makeOptions(pattern, enums) for o in options: o.fillSlots('name', self.name) yield o class ObjectRadioGroupInput(ObjectChoiceMixin, RadioGroupInput): """ Variant of L{RadioGroupInput} for arbitrary Python objects. Deprecated. Use L{RadioGroupInput} with L{methanal.enums.ObjectEnum}. """ ObjectRadioGroupInput.__init__ = deprecated(Version('methanal', 0, 2, 1))( ObjectRadioGroupInput.__init__) class MultiCheckboxInput(MultiChoiceInputMixin, ChoiceInput): """ Multiple-checkboxes input. """ fragmentName = 'methanal-multicheck-input' jsClass = u'Methanal.View.MultiCheckboxInput' class ObjectMultiCheckboxInput(ObjectMultiChoiceMixin, MultiCheckboxInput): """ Variant of L{MultiCheckboxInput} for arbitrary Python objects.
A basic ASN.1 parser. Deprecated since Twisted 9.0 in favor of PyASN1. Maintainer: Paul Swartz """ import itertools from pyasn1.type import univ from pyasn1.codec.ber import decoder, encoder from twisted.python.deprecate import deprecated from twisted.python import versions Twisted9point0 = versions.Version('Twisted', 9, 0, 0) def parse(data): return decoder.decode(data)[0] parse = deprecated(Twisted9point0)(parse) def pack(data): asn1Sequence = univ.Sequence() for index, value in itertools.izip(itertools.count(), data): try: valueAsInteger = univ.Integer(value) except TypeError: raise ValueError("cannot pack %r" % (value,)) asn1Sequence.setComponentByPosition(index, univ.Integer(value)) return encoder.encode(asn1Sequence) pack = deprecated(Twisted9point0)(pack)
m.update(pszRealm) m.update(":") m.update(pszPassword) HA1 = m.digest() if pszAlg == "md5-sess": m = md5() m.update(HA1) m.update(":") m.update(pszNonce) m.update(":") m.update(pszCNonce) HA1 = m.digest() return HA1.encode('hex') DigestCalcHA1 = deprecated(Version("Twisted", 9, 0, 0))(DigestCalcHA1) def DigestCalcResponse( HA1, pszNonce, pszNonceCount, pszCNonce, pszQop, pszMethod, pszDigestUri, pszHEntity, ): m = md5() m.update(pszMethod) m.update(":")
"""Asynchronously invoke a remote method. """ return self.obj.broker._sendMessage('', self.obj.perspective, self.obj.luid, self.name, args, kw) def noOperation(*args, **kw): """ Do nothing. Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit... """ noOperation = deprecated(Version("twisted", 8, 2, 0))(noOperation) class PBConnectionLost(Exception): pass def printTraceback(tb): """ Print a traceback (string) to the standard log. """ log.msg('Perspective Broker Traceback:') log.msg(tb) printTraceback = deprecated(Version("twisted", 8, 2, 0))(printTraceback)
else: hostHeader = host + b":" + intToBytes(port) self.requestHeaders.addRawHeader(b"host", hostHeader) def redirect(self, url): """ Utility function that does a redirect. The request should have finish() called after this. """ self.setResponseCode(FOUND) self.setHeader(b"location", url) DummyRequest.getClientIP = deprecated( Version('Twisted', 18, 4, 0, release_candidate=1), replacement="getClientAddress", )(DummyRequest.getClientIP) class DummyRequestTests(unittest.SynchronousTestCase): """ Tests for L{DummyRequest}. """ def test_getClientIPDeprecated(self): """ L{DummyRequest.getClientIP} is deprecated in favor of L{DummyRequest.getClientAddress} """ request = DummyRequest([]) request.getClientIP()
else: hostHeader = host + b":" + intToBytes(port) self.requestHeaders.addRawHeader(b"host", hostHeader) def redirect(self, url): """ Utility function that does a redirect. The request should have finish() called after this. """ self.setResponseCode(FOUND) self.setHeader(b"location", url) DummyRequest.getClientIP = deprecated( Version('Twisted', 18, 4, 0), replacement="getClientAddress", )(DummyRequest.getClientIP) class DummyRequestTests(unittest.SynchronousTestCase): """ Tests for L{DummyRequest}. """ def test_getClientIPDeprecated(self): """ L{DummyRequest.getClientIP} is deprecated in favor of L{DummyRequest.getClientAddress} """ request = DummyRequest([]) request.getClientIP()
# -*- test-case-name: twisted.test.test_enterprise -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import warnings, types from twisted.python.versions import Version, getVersionString from twisted.python.deprecate import deprecated from twisted.enterprise.adbapi import _safe # Common deprecation decorator used for all deprecations. _deprecatedVersion = Version("Twisted", 8, 0, 0) _releasedDeprecation = deprecated(_deprecatedVersion) warnings.warn( "twisted.enterprise.util is deprecated since %s." % ( getVersionString(_deprecatedVersion),), category=DeprecationWarning) NOQUOTE = 1 USEQUOTE = 2 dbTypeMap = { "bigint": NOQUOTE, "bool": USEQUOTE, "boolean": USEQUOTE, "bytea": USEQUOTE, "date": USEQUOTE, "int2": NOQUOTE, "int4": NOQUOTE,
notes = domhelpers.findElementsWithAttribute(document, "class", "note") notePrefix = dom.parseString('<strong>Note: </strong>').documentElement for note in notes: note.childNodes.insert(0, notePrefix) def compareMarkPos(a, b): """ Perform in every way identically to L{cmp} for valid inputs. """ linecmp = cmp(a[0], b[0]) if linecmp: return linecmp return cmp(a[1], b[1]) compareMarkPos = deprecated(Version('Twisted', 9, 0, 0))(compareMarkPos) def comparePosition(firstElement, secondElement): """ Compare the two elements given by their position in the document or documents they were parsed from. @type firstElement: C{dom.Element} @type secondElement: C{dom.Element} @return: C{-1}, C{0}, or C{1}, with the same meanings as the return value of L{cmp}. """ return cmp(firstElement._markpos, secondElement._markpos)
def run(runApp, ServerOptions): config = ServerOptions() try: config.parseOptions() except usage.error, ue: print config print "%s: %s" % (sys.argv[0], ue) else: runApp(config) def initialLog(): AppLogger({})._initialLog() initialLog = deprecated(Version("Twisted", 8, 2, 0))(initialLog) def convertStyle(filein, typein, passphrase, fileout, typeout, encrypt): application = service.loadApplication(filein, typein, passphrase) sob.IPersistable(application).setStyle(typeout) passphrase = getSavePassphrase(encrypt) if passphrase: fileout = None sob.IPersistable(application).save(filename=fileout, passphrase=passphrase) def startApplication(application, save): from twisted.internet import reactor
default = 80 if port == default: hostHeader = host else: hostHeader = host + b":" + intToBytes(port) self.requestHeaders.addRawHeader(b"host", hostHeader) def getClient(self): """ Get the client's IP address, if it has one. @return: The same value as C{getClientIP}. @rtype: L{bytes} """ return self.getClientIP() def redirect(self, url): """ Utility function that does a redirect. The request should have finish() called after this. """ self.setResponseCode(FOUND) self.setHeader(b"location", url) DummyRequest.getClient = deprecated( Version("Twisted", 15, 0, 0), "Twisted Names to resolve hostnames")(DummyRequest.getClient)
Cleans up my socket. @param reason: Ignored. Do not use this. """ log.msg('(Tuntap %s Closed)' % self.interface) abstract.FileDescriptor.connectionLost(self, reason) self.protocol.doStop() self.connected = 0 self._system.close(self._fileno) self._fileno = -1 def logPrefix(self): """ Returns the name of my class, to prefix log entries with. """ return self.logstr def getHost(self): """ Get the local address of this L{TuntapPort}. @return: A L{TunnelAddress} which describes the tunnel device to which this object is bound. @rtype: L{TunnelAddress} """ return TunnelAddress(self._mode, self.interface) TuntapPort.loseConnection = deprecated(Version( "Twisted", 14, 0, 0), TuntapPort.stopListening)(TuntapPort.loseConnection)
def _makeOptions(self, pattern, enums): options = super(RadioGroupInput, self)._makeOptions(pattern, enums) for o in options: o.fillSlots('name', self.name) yield o class ObjectRadioGroupInput(ObjectChoiceMixin, RadioGroupInput): """ Variant of L{RadioGroupInput} for arbitrary Python objects. Deprecated. Use L{RadioGroupInput} with L{methanal.enums.ObjectEnum}. """ ObjectRadioGroupInput.__init__ = deprecated(Version('methanal', 0, 2, 1))( ObjectRadioGroupInput.__init__) class MultiCheckboxInput(MultiChoiceInputMixin, ChoiceInput): """ Multiple-checkboxes input. """ fragmentName = 'methanal-multicheck-input' jsClass = u'Methanal.View.MultiCheckboxInput' class ObjectMultiCheckboxInput(ObjectMultiChoiceMixin, MultiCheckboxInput): """ Variant of L{MultiCheckboxInput} for arbitrary Python objects. Deprecated. Use L{MultiCheckboxInput} with L{methanal.enums.ObjectEnum}.
tprmm = tprm + '.' + macroname mymod = types.ModuleType(tprmm) sys.modules[tprmm] = mymod setattr(macros, macroname, mymod) dict = mymod.__dict__ # Before we go on, I guess I should explain why I just did that. Basically # it's a gross hack to get epydoc to work right, but the general idea is # that it will be a useful aid in debugging in _any_ app which expects # sys.modules to have the same globals as some function. For example, it # would be useful if you were foolishly trying to pickle a wrapped function # directly from a class that had been hooked. exec code in dict, dict return dict[name] macro = deprecated(Version("Twisted", 8, 2, 0))(macro) def _determineClass(x): try: return x.__class__ except: return type(x) def _determineClassName(x): c = _determineClass(x) try: return c.__name__
else: default = 80 if port == default: hostHeader = host else: hostHeader = host + b":" + intToBytes(port) self.requestHeaders.addRawHeader(b"host", hostHeader) def getClient(self): """ Get the client's IP address, if it has one. @return: The same value as C{getClientIP}. @rtype: L{bytes} """ return self.getClientIP() def redirect(self, url): """ Utility function that does a redirect. The request should have finish() called after this. """ self.setResponseCode(FOUND) self.setHeader(b"location", url) DummyRequest.getClient = deprecated(Version("Twisted", 15, 0, 0), "Twisted Names to resolve hostnames")( DummyRequest.getClient)
def f(): deprecated() deprecated()
m.update(pszRealm) m.update(":") m.update(pszPassword) HA1 = m.digest() if pszAlg == "md5-sess": m = md5() m.update(HA1) m.update(":") m.update(pszNonce) m.update(":") m.update(pszCNonce) HA1 = m.digest() return HA1.encode('hex') DigestCalcHA1 = deprecated(Version("Twisted", 9, 0, 0))(DigestCalcHA1) def DigestCalcResponse( HA1, pszNonce, pszNonceCount, pszCNonce, pszQop, pszMethod, pszDigestUri, pszHEntity, ): m = md5() m.update(pszMethod) m.update(":") m.update(pszDigestUri)
""" import itertools from pyasn1.type import univ from pyasn1.codec.ber import decoder, encoder from twisted.python.deprecate import deprecated from twisted.python import versions Twisted9point0 = versions.Version('Twisted', 9, 0, 0) def parse(data): return decoder.decode(data)[0] parse = deprecated(Twisted9point0)(parse) def pack(data): asn1Sequence = univ.Sequence() for index, value in itertools.izip(itertools.count(), data): try: valueAsInteger = univ.Integer(value) except TypeError: raise ValueError("cannot pack %r" % (value, )) asn1Sequence.setComponentByPosition(index, univ.Integer(value)) return encoder.encode(asn1Sequence) pack = deprecated(Twisted9point0)(pack)
""" log.msg('(Tuntap %s Closed)' % self.interface) abstract.FileDescriptor.connectionLost(self, reason) self.protocol.doStop() self.connected = 0 self._system.close(self._fileno) self._fileno = -1 def logPrefix(self): """ Returns the name of my class, to prefix log entries with. """ return self.logstr def getHost(self): """ Get the local address of this L{TuntapPort}. @return: A L{TunnelAddress} which describes the tunnel device to which this object is bound. @rtype: L{TunnelAddress} """ return TunnelAddress(self._mode, self.interface) TuntapPort.loseConnection = deprecated( Version("Twisted", 14, 0, 0), TuntapPort.stopListening)(TuntapPort.loseConnection)
else: hostHeader = host + b":" + intToBytes(port) self.requestHeaders.addRawHeader(b"host", hostHeader) def redirect(self, url): """ Utility function that does a redirect. The request should have finish() called after this. """ self.setResponseCode(FOUND) self.setHeader(b"location", url) DummyRequest.getClientIP = deprecated( Version("Twisted", "NEXT", 0, 0), replacement="getClientAddress", )(DummyRequest.getClientIP) class DummyRequestTests(unittest.SynchronousTestCase): """ Tests for L{DummyRequest}. """ def test_getClientIPDeprecated(self): """ L{DummyRequest.getClientIP} is deprecated in favor of L{DummyRequest.getClientAddress} """ request = DummyRequest([]) request.getClientIP()
class ThreadPool: """ This class (hopefully) generalizes the functionality of a pool of threads to which work can be dispatched. L{callInThread} and L{stop} should only be called from a single thread. @ivar started: Whether or not the thread pool is currently running. @type started: L{bool} @ivar threads: List of workers currently running in this thread pool. @type threads: L{list} @ivar _pool: A hook for testing. @type _pool: callable compatible with L{_pool} """ min = 5 max = 20 joined = False started = False name = None threadFactory = Thread currentThread = staticmethod( deprecated( version=Version("Twisted", 22, 1, 0), replacement="threading.current_thread", )(current_thread)) _pool = staticmethod(_pool) def __init__(self, minthreads=5, maxthreads=20, name=None): """ Create a new threadpool. @param minthreads: minimum number of threads in the pool @type minthreads: L{int} @param maxthreads: maximum number of threads in the pool @type maxthreads: L{int} @param name: The name to give this threadpool; visible in log messages. @type name: native L{str} """ assert minthreads >= 0, "minimum is negative" assert minthreads <= maxthreads, "minimum is greater than maximum" self.min = minthreads self.max = maxthreads self.name = name self.threads: List[Thread] = [] def trackingThreadFactory(*a, **kw): thread = self.threadFactory( # type: ignore[misc] *a, name=self._generateName(), **kw) self.threads.append(thread) return thread def currentLimit(): if not self.started: return 0 return self.max self._team = self._pool(currentLimit, trackingThreadFactory) @property def workers(self): """ For legacy compatibility purposes, return a total number of workers. @return: the current number of workers, both idle and busy (but not those that have been quit by L{ThreadPool.adjustPoolsize}) @rtype: L{int} """ stats = self._team.statistics() return stats.idleWorkerCount + stats.busyWorkerCount @property def working(self): """ For legacy compatibility purposes, return the number of busy workers as expressed by a list the length of that number. @return: the number of workers currently processing a work item. @rtype: L{list} of L{None} """ return [None] * self._team.statistics().busyWorkerCount @property def waiters(self): """ For legacy compatibility purposes, return the number of idle workers as expressed by a list the length of that number. @return: the number of workers currently alive (with an allocated thread) but waiting for new work. @rtype: L{list} of L{None} """ return [None] * self._team.statistics().idleWorkerCount @property def _queue(self): """ For legacy compatibility purposes, return an object with a C{qsize} method that indicates the amount of work not yet allocated to a worker. @return: an object with a C{qsize} method. """ class NotAQueue: def qsize(q): """ Pretend to be a Python threading Queue and return the number of as-yet-unconsumed tasks. @return: the amount of backlogged work not yet dispatched to a worker. @rtype: L{int} """ return self._team.statistics().backloggedWorkCount return NotAQueue() q = _queue # Yes, twistedchecker, I want a single-letter # attribute name. def start(self): """ Start the threadpool. """ self.joined = False self.started = True # Start some threads. self.adjustPoolsize() backlog = self._team.statistics().backloggedWorkCount if backlog: self._team.grow(backlog) def startAWorker(self): """ Increase the number of available workers for the thread pool by 1, up to the maximum allowed by L{ThreadPool.max}. """ self._team.grow(1) def _generateName(self): """ Generate a name for a new pool thread. @return: A distinctive name for the thread. @rtype: native L{str} """ return f"PoolThread-{self.name or id(self)}-{self.workers}" def stopAWorker(self): """ Decrease the number of available workers by 1, by quitting one as soon as it's idle. """ self._team.shrink(1) def __setstate__(self, state): setattr(self, "__dict__", state) ThreadPool.__init__(self, self.min, self.max) def __getstate__(self): state = {} state["min"] = self.min state["max"] = self.max return state def callInThread(self, func, *args, **kw): """ Call a callable object in a separate thread. @param func: callable object to be called in separate thread @param args: positional arguments to be passed to C{func} @param kw: keyword args to be passed to C{func} """ self.callInThreadWithCallback(None, func, *args, **kw) def callInThreadWithCallback(self, onResult, func, *args, **kw): """ Call a callable object in a separate thread and call C{onResult} with the return value, or a L{twisted.python.failure.Failure} if the callable raises an exception. The callable is allowed to block, but the C{onResult} function must not block and should perform as little work as possible. A typical action for C{onResult} for a threadpool used with a Twisted reactor would be to schedule a L{twisted.internet.defer.Deferred} to fire in the main reactor thread using C{.callFromThread}. Note that C{onResult} is called inside the separate thread, not inside the reactor thread. @param onResult: a callable with the signature C{(success, result)}. If the callable returns normally, C{onResult} is called with C{(True, result)} where C{result} is the return value of the callable. If the callable throws an exception, C{onResult} is called with C{(False, failure)}. Optionally, C{onResult} may be L{None}, in which case it is not called at all. @param func: callable object to be called in separate thread @param args: positional arguments to be passed to C{func} @param kw: keyword arguments to be passed to C{func} """ if self.joined: return ctx = context.theContextTracker.currentContext().contexts[-1] def inContext(): try: result = inContext.theWork() # type: ignore[attr-defined] ok = True except BaseException: result = Failure() ok = False inContext.theWork = None # type: ignore[attr-defined] if inContext.onResult is not None: # type: ignore[attr-defined] inContext.onResult(ok, result) # type: ignore[attr-defined] inContext.onResult = None # type: ignore[attr-defined] elif not ok: log.err(result) # Avoid closing over func, ctx, args, kw so that we can carefully # manage their lifecycle. See # test_threadCreationArgumentsCallInThreadWithCallback. inContext.theWork = lambda: context.call( # type: ignore[attr-defined] ctx, func, *args, **kw) inContext.onResult = onResult # type: ignore[attr-defined] self._team.do(inContext) def stop(self): """ Shutdown the threads in the threadpool. """ self.joined = True self.started = False self._team.quit() for thread in self.threads: thread.join() def adjustPoolsize(self, minthreads=None, maxthreads=None): """ Adjust the number of available threads by setting C{min} and C{max} to new values. @param minthreads: The new value for L{ThreadPool.min}. @param maxthreads: The new value for L{ThreadPool.max}. """ if minthreads is None: minthreads = self.min if maxthreads is None: maxthreads = self.max assert minthreads >= 0, "minimum is negative" assert minthreads <= maxthreads, "minimum is greater than maximum" self.min = minthreads self.max = maxthreads if not self.started: return # Kill of some threads if we have too many. if self.workers > self.max: self._team.shrink(self.workers - self.max) # Start some threads if we have too few. if self.workers < self.min: self._team.grow(self.min - self.workers) def dumpStats(self): """ Dump some plain-text informational messages to the log about the state of this L{ThreadPool}. """ log.msg(f"waiters: {self.waiters}") log.msg(f"workers: {self.working}") log.msg(f"total: {self.threads}")
class TestCallDeprecated(unittest.TestCase): """ Test the L{TestCase.callDeprecated} method. """ version = Version('Twisted', 8, 0, 0) def oldMethod(self, x): """ Deprecated method for testing. """ return x oldMethod = deprecated(version)(oldMethod) def test_callDeprecatedSuppressesWarning(self): """ callDeprecated calls a deprecated callable, suppressing the deprecation warning. """ warningsShown = [] def warnExplicit(*args): warningsShown.append(args) self.patch(warnings, 'warn_explicit', warnExplicit) self.callDeprecated(self.version, self.oldMethod, 'foo') self.assertEqual([], warningsShown, "No warnings should be shown") def test_callDeprecatedCallsFunction(self): """ L{callDeprecated} actually calls the callable passed to it. """ result = self.callDeprecated(self.version, self.oldMethod, 'foo') self.assertEqual('foo', result) def test_failsWithoutDeprecation(self): """ callDeprecated raises a test failure if the callable is not deprecated. """ def notDeprecated(): pass exception = self.assertRaises(self.failureException, self.callDeprecated, self.version, notDeprecated) self.assertEqual("%r is not deprecated." % notDeprecated, str(exception)) def test_failsWithIncorrectDeprecation(self): """ callDeprecated raises a test failure if the callable was deprecated at a different version to the one expected. """ differentVersion = Version('Foo', 1, 2, 3) exception = self.assertRaises(self.failureException, self.callDeprecated, differentVersion, self.oldMethod, 'foo') self.assertIn(getVersionString(self.version), str(exception)) self.assertIn(getVersionString(differentVersion), str(exception)) def test_nestedDeprecation(self): """ L{callDeprecated} ignores all deprecations apart from the first. Multiple warnings are generated when a deprecated function calls another deprecated function. The first warning is the one generated by the explicitly called function. That's the warning that we care about. """ differentVersion = Version('Foo', 1, 2, 3) def nestedDeprecation(*args): return self.oldMethod(*args) nestedDeprecation = deprecated(differentVersion)(nestedDeprecation) self.callDeprecated(differentVersion, nestedDeprecation, 24)
notePrefix = dom.parseString('<strong>Note: </strong>').documentElement for note in notes: note.childNodes.insert(0, notePrefix) def compareMarkPos(a, b): """ Perform in every way identically to L{cmp} for valid inputs. """ linecmp = cmp(a[0], b[0]) if linecmp: return linecmp return cmp(a[1], b[1]) compareMarkPos = deprecated(Version('Twisted', 9, 0, 0))(compareMarkPos) def comparePosition(firstElement, secondElement): """ Compare the two elements given by their position in the document or documents they were parsed from. @type firstElement: C{dom.Element} @type secondElement: C{dom.Element} @return: C{-1}, C{0}, or C{1}, with the same meanings as the return value of L{cmp}. """ return cmp(firstElement._markpos, secondElement._markpos)
'max': self.max, 'noisy': self.noisy, 'reconnect': self.reconnect, 'good_sql': self.good_sql, 'connargs': self.connargs, 'connkw': self.connkw } def __setstate__(self, state): self.__dict__ = state self.__init__(self.dbapiName, *self.connargs, **self.connkw) # Common deprecation decorator used for all deprecations. _unreleasedVersion = Version("Twisted", 8, 0, 0) _unreleasedDeprecation = deprecated(_unreleasedVersion) def _safe(text): """ Something really stupid that replaces quotes with escaped quotes. """ return text.replace("'", "''").replace("\\", "\\\\") def safe(text): """ Make a string safe to include in an SQL statement. """ return _safe(text)
self.callDeprecated, differentVersion, self.oldMethod, 'foo') self.assertIn(getVersionString(self.version), str(exception)) self.assertIn(getVersionString(differentVersion), str(exception)) def test_nestedDeprecation(self): """ L{callDeprecated} ignores all deprecations apart from the first. Multiple warnings are generated when a deprecated function calls another deprecated function. The first warning is the one generated by the explicitly called function. That's the warning that we care about. """ differentVersion = Version('Foo', 1, 2, 3) def nestedDeprecation(*args): return self.oldMethod(*args) nestedDeprecation = deprecated(differentVersion)(nestedDeprecation) self.callDeprecated(differentVersion, nestedDeprecation, 24) # The oldMethod deprecation should have been emitted too, not captured # by callDeprecated. Flush it now to make sure it did happen and to # prevent it from showing up on stdout. warningsShown = self.flushWarnings() self.assertEqual(len(warningsShown), 1) TestCallDeprecated.oldMethod = deprecated(TestCallDeprecated.version)( TestCallDeprecated.oldMethod)