import warnings
from eventlet.support import get_errno, six
-from eventlet.hubs import trampoline, notify_close, notify_opened, IOClosed
+from eventlet.hubs import trampoline, notify_opened, IOClosed
-__all__ = ['GreenSocket', 'GreenPipe', 'shutdown_safe']
+__all__ = [
+ 'GreenSocket', '_GLOBAL_DEFAULT_TIMEOUT', 'set_nonblocking',
+ 'SOCKET_CLOSED', 'CONNECT_ERR', 'CONNECT_SUCCESS',
+ 'shutdown_safe', 'SSL',
+]
BUFFER_SIZE = 4096
CONNECT_ERR = set((errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK))
if sys.platform[:3] == "win":
CONNECT_ERR.add(errno.WSAEINVAL) # Bug 67
-if six.PY3:
- from io import IOBase as file
- _fileobject = socket.SocketIO
-elif six.PY2:
- _fileobject = socket._fileobject
+if six.PY2:
+ _python2_fileobject = socket._fileobject
def socket_connect(descriptor, address):
else:
def makefile(self, *args, **kwargs):
dupped = self.dup()
- res = _fileobject(dupped, *args, **kwargs)
+ res = _python2_fileobject(dupped, *args, **kwargs)
if hasattr(dupped, "_drop"):
dupped._drop()
return res
getattr(self.fd, '_sock', self.fd)._drop()
-class _SocketDuckForFd(object):
- """Class implementing all socket method used by _fileobject
- in cooperative manner using low level os I/O calls.
- """
- _refcount = 0
-
- def __init__(self, fileno):
- self._fileno = fileno
- notify_opened(fileno)
- self._closed = False
-
- def _trampoline(self, fd, read=False, write=False, timeout=None, timeout_exc=None):
- if self._closed:
- # Don't trampoline if we're already closed.
- raise IOClosed()
- try:
- return trampoline(fd, read=read, write=write, timeout=timeout,
- timeout_exc=timeout_exc,
- mark_as_closed=self._mark_as_closed)
- except IOClosed:
- # Our fileno has been obsoleted. Defang ourselves to
- # prevent spurious closes.
- self._mark_as_closed()
- raise
-
- def _mark_as_closed(self):
- self._closed = True
-
- @property
- def _sock(self):
- return self
-
- def fileno(self):
- return self._fileno
-
- def recv(self, buflen):
- while True:
- try:
- data = os.read(self._fileno, buflen)
- return data
- except OSError as e:
- if get_errno(e) not in SOCKET_BLOCKING:
- raise IOError(*e.args)
- self._trampoline(self, read=True)
-
- def recv_into(self, buf, nbytes=0, flags=0):
- if nbytes == 0:
- nbytes = len(buf)
- data = self.recv(nbytes)
- buf[:nbytes] = data
- return len(data)
-
- def send(self, data):
- while True:
- try:
- return os.write(self._fileno, data)
- except OSError as e:
- if get_errno(e) not in SOCKET_BLOCKING:
- raise IOError(*e.args)
- else:
- trampoline(self, write=True)
-
- def sendall(self, data):
- len_data = len(data)
- os_write = os.write
- fileno = self._fileno
- try:
- total_sent = os_write(fileno, data)
- except OSError as e:
- if get_errno(e) != errno.EAGAIN:
- raise IOError(*e.args)
- total_sent = 0
- while total_sent < len_data:
- self._trampoline(self, write=True)
- try:
- total_sent += os_write(fileno, data[total_sent:])
- except OSError as e:
- if get_errno(e) != errno. EAGAIN:
- raise IOError(*e.args)
-
- def __del__(self):
- self._close()
-
- def _close(self):
- notify_close(self._fileno)
- self._mark_as_closed()
- try:
- os.close(self._fileno)
- except:
- # os.close may fail if __init__ didn't complete
- # (i.e file dscriptor passed to popen was invalid
- pass
-
- def __repr__(self):
- return "%s:%d" % (self.__class__.__name__, self._fileno)
-
- def _reuse(self):
- self._refcount += 1
-
- def _drop(self):
- self._refcount -= 1
- if self._refcount == 0:
- self._close()
- # Python3
- _decref_socketios = _drop
-
-
-def _operationOnClosedFile(*args, **kwargs):
+def _operation_on_closed_file(*args, **kwargs):
raise ValueError("I/O operation on closed file")
-class GreenPipe(_fileobject):
- """
+greenpipe_doc = """
GreenPipe is a cooperative replacement for file class.
It will cooperate on pipes. It will block on regular file.
Differneces from file class:
- file argument can be descriptor, file name or file object.
"""
- def __init__(self, f, mode='r', bufsize=-1):
- if not isinstance(f, six.string_types + (int, file)):
- raise TypeError('f(ile) should be int, str, unicode or file, not %r' % f)
-
- if isinstance(f, six.string_types):
- f = open(f, mode, 0)
-
- if isinstance(f, int):
- fileno = f
- self._name = "<fd:%d>" % fileno
- else:
- fileno = os.dup(f.fileno())
- self._name = f.name
- if f.mode != mode:
- raise ValueError('file.mode %r does not match mode parameter %r' % (f.mode, mode))
- self._name = f.name
- f.close()
-
- super(GreenPipe, self).__init__(_SocketDuckForFd(fileno), mode)
- set_nonblocking(self)
- self.softspace = 0
-
- @property
- def name(self):
- return self._name
-
- def __repr__(self):
- return "<%s %s %r, mode %r at 0x%x>" % (
- self.closed and 'closed' or 'open',
- self.__class__.__name__,
- self.name,
- self.mode,
- (id(self) < 0) and (sys.maxint + id(self)) or id(self))
-
- def close(self):
- super(GreenPipe, self).close()
- for method in [
- 'fileno', 'flush', 'isatty', 'next', 'read', 'readinto',
- 'readline', 'readlines', 'seek', 'tell', 'truncate',
- 'write', 'xreadlines', '__iter__', '__next__', 'writelines']:
- setattr(self, method, _operationOnClosedFile)
-
- def __enter__(self):
- return self
-
- def __exit__(self, *args):
- self.close()
-
- def _get_readahead_len(self):
- return len(self._rbuf.getvalue())
-
- def _clear_readahead_buf(self):
- len = self._get_readahead_len()
- if len > 0:
- self.read(len)
-
- def tell(self):
- self.flush()
- try:
- return os.lseek(self.fileno(), 0, 1) - self._get_readahead_len()
- except OSError as e:
- raise IOError(*e.args)
-
- def seek(self, offset, whence=0):
- self.flush()
- if whence == 1 and offset == 0: # tell synonym
- return self.tell()
- if whence == 1: # adjust offset by what is read ahead
- offset -= self._get_readahead_len()
- try:
- rv = os.lseek(self.fileno(), offset, whence)
- except OSError as e:
- raise IOError(*e.args)
- else:
- self._clear_readahead_buf()
- return rv
-
- if getattr(file, "truncate", None): # not all OSes implement truncate
- def truncate(self, size=-1):
- self.flush()
- if size == -1:
- size = self.tell()
- try:
- rv = os.ftruncate(self.fileno(), size)
- except OSError as e:
- raise IOError(*e.args)
- else:
- self.seek(size) # move position&clear buffer
- return rv
-
- def isatty(self):
- try:
- return os.isatty(self.fileno())
- except OSError as e:
- raise IOError(*e.args)
-
-
# import SSL module here so we can refer to greenio.SSL.exceptionclass
try:
from OpenSSL import SSL
except socket.error as e:
# we don't care if the socket is already closed;
# this will often be the case in an http server context
- if get_errno(e) != errno.ENOTCONN:
+ if get_errno(e) not in (errno.ENOTCONN, errno.EBADF):
raise