diff options
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/abstract.py')
-rwxr-xr-x | lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/abstract.py | 517 |
1 files changed, 0 insertions, 517 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/abstract.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/abstract.py deleted file mode 100755 index 08dd4d5d..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/abstract.py +++ /dev/null @@ -1,517 +0,0 @@ -# -*- test-case-name: twisted.test.test_abstract -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Support for generic select()able objects. -""" - -from socket import AF_INET6, inet_pton, error - -from zope.interface import implements - -# Twisted Imports -from twisted.python import reflect, failure -from twisted.internet import interfaces, main - - -class _ConsumerMixin(object): - """ - L{IConsumer} implementations can mix this in to get C{registerProducer} and - C{unregisterProducer} methods which take care of keeping track of a - producer's state. - - Subclasses must provide three attributes which L{_ConsumerMixin} will read - but not write: - - - connected: A C{bool} which is C{True} as long as the the consumer has - someplace to send bytes (for example, a TCP connection), and then - C{False} when it no longer does. - - - disconnecting: A C{bool} which is C{False} until something like - L{ITransport.loseConnection} is called, indicating that the send buffer - should be flushed and the connection lost afterwards. Afterwards, - C{True}. - - - disconnected: A C{bool} which is C{False} until the consumer no longer - has a place to send bytes, then C{True}. - - Subclasses must also override the C{startWriting} method. - - @ivar producer: C{None} if no producer is registered, otherwise the - registered producer. - - @ivar producerPaused: A flag indicating whether the producer is currently - paused. - @type producerPaused: C{bool} or C{int} - - @ivar streamingProducer: A flag indicating whether the producer was - registered as a streaming (ie push) producer or not (ie a pull - producer). This will determine whether the consumer may ever need to - pause and resume it, or if it can merely call C{resumeProducing} on it - when buffer space is available. - @ivar streamingProducer: C{bool} or C{int} - - """ - producer = None - producerPaused = False - streamingProducer = False - - def startWriting(self): - """ - Override in a subclass to cause the reactor to monitor this selectable - for write events. This will be called once in C{unregisterProducer} if - C{loseConnection} has previously been called, so that the connection can - actually close. - """ - raise NotImplementedError("%r did not implement startWriting") - - - def registerProducer(self, producer, streaming): - """ - Register to receive data from a producer. - - This sets this selectable to be a consumer for a producer. When this - selectable runs out of data on a write() call, it will ask the producer - to resumeProducing(). When the FileDescriptor's internal data buffer is - filled, it will ask the producer to pauseProducing(). If the connection - is lost, FileDescriptor calls producer's stopProducing() method. - - If streaming is true, the producer should provide the IPushProducer - interface. Otherwise, it is assumed that producer provides the - IPullProducer interface. In this case, the producer won't be asked to - pauseProducing(), but it has to be careful to write() data only when its - resumeProducing() method is called. - """ - if self.producer is not None: - raise RuntimeError( - "Cannot register producer %s, because producer %s was never " - "unregistered." % (producer, self.producer)) - if self.disconnected: - producer.stopProducing() - else: - self.producer = producer - self.streamingProducer = streaming - if not streaming: - producer.resumeProducing() - - - def unregisterProducer(self): - """ - Stop consuming data from a producer, without disconnecting. - """ - self.producer = None - if self.connected and self.disconnecting: - self.startWriting() - - - -class _LogOwner(object): - """ - Mixin to help implement L{interfaces.ILoggingContext} for transports which - have a protocol, the log prefix of which should also appear in the - transport's log prefix. - """ - implements(interfaces.ILoggingContext) - - def _getLogPrefix(self, applicationObject): - """ - Determine the log prefix to use for messages related to - C{applicationObject}, which may or may not be an - L{interfaces.ILoggingContext} provider. - - @return: A C{str} giving the log prefix to use. - """ - if interfaces.ILoggingContext.providedBy(applicationObject): - return applicationObject.logPrefix() - return applicationObject.__class__.__name__ - - - def logPrefix(self): - """ - Override this method to insert custom logging behavior. Its - return value will be inserted in front of every line. It may - be called more times than the number of output lines. - """ - return "-" - - - -class FileDescriptor(_ConsumerMixin, _LogOwner): - """An object which can be operated on by select(). - - This is an abstract superclass of all objects which may be notified when - they are readable or writable; e.g. they have a file-descriptor that is - valid to be passed to select(2). - """ - connected = 0 - disconnected = 0 - disconnecting = 0 - _writeDisconnecting = False - _writeDisconnected = False - dataBuffer = "" - offset = 0 - - SEND_LIMIT = 128*1024 - - implements(interfaces.IPushProducer, interfaces.IReadWriteDescriptor, - interfaces.IConsumer, interfaces.ITransport, interfaces.IHalfCloseableDescriptor) - - def __init__(self, reactor=None): - if not reactor: - from twisted.internet import reactor - self.reactor = reactor - self._tempDataBuffer = [] # will be added to dataBuffer in doWrite - self._tempDataLen = 0 - - - def connectionLost(self, reason): - """The connection was lost. - - This is called when the connection on a selectable object has been - lost. It will be called whether the connection was closed explicitly, - an exception occurred in an event handler, or the other end of the - connection closed it first. - - Clean up state here, but make sure to call back up to FileDescriptor. - """ - self.disconnected = 1 - self.connected = 0 - if self.producer is not None: - self.producer.stopProducing() - self.producer = None - self.stopReading() - self.stopWriting() - - - 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 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 doWrite(self): - """ - Called when data can be written. - - A result that is true (which will be a negative number or an - exception instance) indicates that the connection was lost. A false - result implies the connection is still there; a result of 0 - indicates no write was done, and a result of None indicates that a - write was done. - """ - if len(self.dataBuffer) - self.offset < self.SEND_LIMIT: - # If there is currently less than SEND_LIMIT bytes left to send - # in the string, extend it with the array data. - self.dataBuffer = buffer(self.dataBuffer, self.offset) + "".join(self._tempDataBuffer) - self.offset = 0 - self._tempDataBuffer = [] - self._tempDataLen = 0 - - # Send as much data as you can. - if self.offset: - l = self.writeSomeData(buffer(self.dataBuffer, self.offset)) - else: - l = self.writeSomeData(self.dataBuffer) - - # There is no writeSomeData implementation in Twisted which returns - # < 0, but the documentation for writeSomeData used to claim negative - # integers meant connection lost. Keep supporting this here, - # although it may be worth deprecating and removing at some point. - if l < 0 or isinstance(l, Exception): - return l - if l == 0 and self.dataBuffer: - result = 0 - else: - result = None - self.offset += l - # If there is nothing left to send, - if self.offset == len(self.dataBuffer) and not self._tempDataLen: - self.dataBuffer = "" - self.offset = 0 - # stop writing. - self.stopWriting() - # If I've got a producer who is supposed to supply me with data, - if self.producer is not None and ((not self.streamingProducer) - or self.producerPaused): - # tell them to supply some more. - self.producerPaused = 0 - self.producer.resumeProducing() - elif self.disconnecting: - # But if I was previously asked to let the connection die, do - # so. - return self._postLoseConnection() - elif self._writeDisconnecting: - # I was previously asked to half-close the connection. We - # set _writeDisconnected before calling handler, in case the - # handler calls loseConnection(), which will want to check for - # this attribute. - self._writeDisconnected = True - result = self._closeWriteConnection() - return result - return result - - def _postLoseConnection(self): - """Called after a loseConnection(), when all data has been written. - - Whatever this returns is then returned by doWrite. - """ - # default implementation, telling reactor we're finished - return main.CONNECTION_DONE - - def _closeWriteConnection(self): - # override in subclasses - pass - - def writeConnectionLost(self, reason): - # in current code should never be called - self.connectionLost(reason) - - def readConnectionLost(self, reason): - # override in subclasses - self.connectionLost(reason) - - - def _isSendBufferFull(self): - """ - Determine whether the user-space send buffer for this transport is full - or not. - - When the buffer contains more than C{self.bufferSize} bytes, it is - considered full. This might be improved by considering the size of the - kernel send buffer and how much of it is free. - - @return: C{True} if it is full, C{False} otherwise. - """ - return len(self.dataBuffer) + self._tempDataLen > self.bufferSize - - - def _maybePauseProducer(self): - """ - Possibly pause a producer, if there is one and the send buffer is full. - """ - # If we are responsible for pausing our producer, - if self.producer is not None and self.streamingProducer: - # and our buffer is full, - if self._isSendBufferFull(): - # pause it. - self.producerPaused = 1 - self.producer.pauseProducing() - - - def write(self, data): - """Reliably write some data. - - The data is buffered until the underlying file descriptor is ready - for writing. If there is more than C{self.bufferSize} data in the - buffer and this descriptor has a registered streaming producer, its - C{pauseProducing()} method will be called. - """ - if isinstance(data, unicode): # no, really, I mean it - raise TypeError("Data must not be unicode") - if not self.connected or self._writeDisconnected: - return - if data: - self._tempDataBuffer.append(data) - self._tempDataLen += len(data) - self._maybePauseProducer() - self.startWriting() - - - def writeSequence(self, iovec): - """ - Reliably write a sequence of data. - - Currently, this is a convenience method roughly equivalent to:: - - for chunk in iovec: - fd.write(chunk) - - It may have a more efficient implementation at a later time or in a - different reactor. - - As with the C{write()} method, if a buffer size limit is reached and a - streaming producer is registered, it will be paused until the buffered - data is written to the underlying file descriptor. - """ - for i in iovec: - if isinstance(i, unicode): # no, really, I mean it - raise TypeError("Data must not be unicode") - if not self.connected or not iovec or self._writeDisconnected: - return - self._tempDataBuffer.extend(iovec) - for i in iovec: - self._tempDataLen += len(i) - self._maybePauseProducer() - self.startWriting() - - - def loseConnection(self, _connDone=failure.Failure(main.CONNECTION_DONE)): - """Close the connection at the next available opportunity. - - Call this to cause this FileDescriptor to lose its connection. It will - first write any data that it has buffered. - - If there is data buffered yet to be written, this method will cause the - transport to lose its connection as soon as it's done flushing its - write buffer. If you have a producer registered, the connection won't - be closed until the producer is finished. Therefore, make sure you - unregister your producer when it's finished, or the connection will - never close. - """ - - if self.connected and not self.disconnecting: - if self._writeDisconnected: - # doWrite won't trigger the connection close anymore - self.stopReading() - self.stopWriting() - self.connectionLost(_connDone) - else: - self.stopReading() - self.startWriting() - self.disconnecting = 1 - - def loseWriteConnection(self): - self._writeDisconnecting = True - self.startWriting() - - def stopReading(self): - """Stop waiting for read availability. - - Call this to remove this selectable from being notified when it is - ready for reading. - """ - self.reactor.removeReader(self) - - def stopWriting(self): - """Stop waiting for write availability. - - Call this to remove this selectable from being notified when it is ready - for writing. - """ - self.reactor.removeWriter(self) - - def startReading(self): - """Start waiting for read availability. - """ - self.reactor.addReader(self) - - def startWriting(self): - """Start waiting for write availability. - - Call this to have this FileDescriptor be notified whenever it is ready for - writing. - """ - self.reactor.addWriter(self) - - # Producer/consumer implementation - - # first, the consumer stuff. This requires no additional work, as - # any object you can write to can be a consumer, really. - - producer = None - bufferSize = 2**2**2**2 - - def stopConsuming(self): - """Stop consuming data. - - This is called when a producer has lost its connection, to tell the - consumer to go lose its connection (and break potential circular - references). - """ - self.unregisterProducer() - self.loseConnection() - - # producer interface implementation - - def resumeProducing(self): - assert self.connected and not self.disconnecting - self.startReading() - - def pauseProducing(self): - self.stopReading() - - def stopProducing(self): - self.loseConnection() - - - def fileno(self): - """File Descriptor number for select(). - - This method must be overridden or assigned in subclasses to - indicate a valid file descriptor for the operating system. - """ - return -1 - - -def isIPAddress(addr): - """ - Determine whether the given string represents an IPv4 address. - - @type addr: C{str} - @param addr: A string which may or may not be the decimal dotted - representation of an IPv4 address. - - @rtype: C{bool} - @return: C{True} if C{addr} represents an IPv4 address, C{False} - otherwise. - """ - dottedParts = addr.split('.') - if len(dottedParts) == 4: - for octet in dottedParts: - try: - value = int(octet) - except ValueError: - return False - else: - if value < 0 or value > 255: - return False - return True - return False - - -def isIPv6Address(addr): - """ - Determine whether the given string represents an IPv6 address. - - @param addr: A string which may or may not be the hex - representation of an IPv6 address. - @type addr: C{str} - - @return: C{True} if C{addr} represents an IPv6 address, C{False} - otherwise. - @rtype: C{bool} - """ - if '%' in addr: - addr = addr.split('%', 1)[0] - if not addr: - return False - try: - # This might be a native implementation or the one from - # twisted.python.compat. - inet_pton(AF_INET6, addr) - except (ValueError, error): - return False - return True - - -__all__ = ["FileDescriptor", "isIPAddress", "isIPv6Address"] |