Diff of /jython/Lib/select.py [03e8ea] .. [dfff18] Maximize Restore

  Switch to side-by-side view

--- a/jython/Lib/select.py
+++ b/jython/Lib/select.py
@@ -1,260 +1,262 @@
-"""
-AMAK: 20070515: New select implementation that uses java.nio
-"""
-
-import java.nio.channels.SelectableChannel
-import java.nio.channels.SelectionKey
-import java.nio.channels.Selector
-from java.nio.channels.SelectionKey import OP_ACCEPT, OP_CONNECT, OP_WRITE, OP_READ
-
-import errno
-import os
-import Queue
-import socket
-
-class error(Exception): pass
-
-ALL = None
-
-_exception_map = {
-
-# (<javaexception>, <circumstance>) : lambda: <code that raises the python equivalent>
-
-(java.nio.channels.IllegalBlockingModeException, ALL) : error(errno.ESOCKISBLOCKING, 'socket must be in non-blocking mode'),
-}
-
-def _map_exception(exc, circumstance=ALL):
-    try:
-        mapped_exception = _exception_map[(exc.__class__, circumstance)]
-        mapped_exception.java_exception = exc
-        return mapped_exception
-    except KeyError:
-        return error(-1, 'Unmapped java exception: <%s:%s>' % (exc.toString(), circumstance))
-
-POLLIN   = 1
-POLLOUT  = 2
-
-# The following event types are completely ignored on jython
-# Java does not support them, AFAICT
-# They are declared only to support code compatibility with cpython
-
-POLLPRI  = 4
-POLLERR  = 8
-POLLHUP  = 16
-POLLNVAL = 32
-
-def _getselectable(selectable_object):
-    try:
-        channel = selectable_object.getchannel()
-    except:
-        try:
-            channel = selectable_object.fileno().getChannel()
-        except:
-            raise TypeError("Object '%s' is not watchable" % selectable_object,
-                            errno.ENOTSOCK)
-    
-    if channel and not isinstance(channel, java.nio.channels.SelectableChannel):
-        raise TypeError("Object '%s' is not watchable" % selectable_object,
-                        errno.ENOTSOCK)
-    return channel
-
-class poll:
-
-    def __init__(self):
-        self.selector = java.nio.channels.Selector.open()
-        self.chanmap = {}
-        self.unconnected_sockets = []
-
-    def _register_channel(self, socket_object, channel, mask):
-        jmask = 0
-        if mask & POLLIN:
-            # Note that OP_READ is NOT a valid event on server socket channels.
-            if channel.validOps() & OP_ACCEPT:
-                jmask = OP_ACCEPT
-            else:
-                jmask = OP_READ
-        if mask & POLLOUT:
-            if channel.validOps() & OP_WRITE:
-                jmask |= OP_WRITE
-            if channel.validOps() & OP_CONNECT:
-                jmask |= OP_CONNECT
-        selectionkey = channel.register(self.selector, jmask)
-        self.chanmap[channel] = (socket_object, selectionkey)
-
-    def _check_unconnected_sockets(self):
-        temp_list = []
-        for socket_object, mask in self.unconnected_sockets:
-            channel = _getselectable(socket_object)
-            if channel is not None:
-                self._register_channel(socket_object, channel, mask)
-            else:
-                temp_list.append( (socket_object, mask) )
-        self.unconnected_sockets = temp_list
-
-    def register(self, socket_object, mask = POLLIN|POLLOUT|POLLPRI):
-        try:
-            channel = _getselectable(socket_object)
-            if channel is None:
-                # The socket is not yet connected, and thus has no channel
-                # Add it to a pending list, and return
-                self.unconnected_sockets.append( (socket_object, mask) )
-                return
-            self._register_channel(socket_object, channel, mask)
-        except java.lang.Exception, jlx:
-            raise _map_exception(jlx)
-
-    def unregister(self, socket_object):
-        try:
-            channel = _getselectable(socket_object)
-            self.chanmap[channel][1].cancel()
-            del self.chanmap[channel]
-        except java.lang.Exception, jlx:
-            raise _map_exception(jlx)
-
-    def _dopoll(self, timeout):
-        if timeout is None or timeout < 0:
-            self.selector.select()
-        else:
-            try:
-                timeout = int(timeout)
-                if not timeout:
-                    self.selector.selectNow()
-                else:
-                    # No multiplication required: both cpython and java use millisecond timeouts
-                    self.selector.select(timeout)
-            except ValueError, vx:
-                raise error("poll timeout must be a number of milliseconds or None", errno.EINVAL)
-        # The returned selectedKeys cannot be used from multiple threads!
-        return self.selector.selectedKeys()
-
-    def poll(self, timeout=None):
-        try:
-            self._check_unconnected_sockets()
-            selectedkeys = self._dopoll(timeout)
-            results = []
-            for k in selectedkeys.iterator():
-                jmask = k.readyOps()
-                pymask = 0
-                if jmask & OP_READ: pymask |= POLLIN
-                if jmask & OP_WRITE: pymask |= POLLOUT
-                if jmask & OP_ACCEPT: pymask |= POLLIN
-                if jmask & OP_CONNECT: pymask |= POLLOUT
-                # Now return the original userobject, and the return event mask
-                results.append( (self.chanmap[k.channel()][0], pymask) )
-            return results
-        except java.lang.Exception, jlx:
-            raise _map_exception(jlx)
-
-    def _deregister_all(self):
-        try:
-            for k in self.selector.keys():
-                k.cancel()
-            # Keys are not actually removed from the selector until the next select operation.
-            self.selector.selectNow()
-        except java.lang.Exception, jlx:
-            raise _map_exception(jlx)
-
-    def close(self):
-        try:
-            self._deregister_all()
-            self.selector.close()
-        except java.lang.Exception, jlx:
-            raise _map_exception(jlx)
-
-def _calcselecttimeoutvalue(value):
-    if value is None:
-        return None
-    try:
-        floatvalue = float(value)
-    except Exception, x:
-        raise TypeError("Select timeout value must be a number or None")
-    if value < 0:
-        raise error("Select timeout value cannot be negative", errno.EINVAL)
-    if floatvalue < 0.000001:
-        return 0
-    return int(floatvalue * 1000) # Convert to milliseconds
-
-# This cache for poll objects is required because of a bug in java on MS Windows
-# http://bugs.jython.org/issue1291
-
-class poll_object_cache:
-
-    def __init__(self):
-        self.is_windows = os._name == 'nt'
-        if self.is_windows:
-            self.poll_object_queue = Queue.Queue()
-        import atexit
-        atexit.register(self.finalize)
-
-    def get_poll_object(self):
-        if not self.is_windows:
-            return poll()
-        try:
-            return self.poll_object_queue.get(False)
-        except Queue.Empty:
-            return poll()
-
-    def release_poll_object(self, pobj):
-        if self.is_windows:
-            pobj._deregister_all()
-            self.poll_object_queue.put(pobj)
-        else:
-            pobj.close()
-
-    def finalize(self):
-        if self.is_windows:
-            while True:
-                try:
-                    p = self.poll_object_queue.get(False)
-                    p.close()
-                except Queue.Empty:
-                    return
-
-_poll_object_cache = poll_object_cache()
-
-def native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None):
-    timeout = _calcselecttimeoutvalue(timeout)
-    # First create a poll object to do the actual watching.
-    pobj = _poll_object_cache.get_poll_object()
-    try:
-        registered_for_read = {}
-        # Check the read list
-        for fd in read_fd_list:
-            pobj.register(fd, POLLIN)
-            registered_for_read[fd] = 1
-        # And now the write list
-        for fd in write_fd_list:
-            if fd in registered_for_read:
-                # registering a second time overwrites the first
-                pobj.register(fd, POLLIN|POLLOUT)
-            else:
-                pobj.register(fd, POLLOUT)
-        results = pobj.poll(timeout)
-        # Now start preparing the results
-        read_ready_list, write_ready_list, oob_ready_list = [], [], []
-        for fd, mask in results:
-            if mask & POLLIN:
-                read_ready_list.append(fd)
-            if mask & POLLOUT:
-                write_ready_list.append(fd)
-        return read_ready_list, write_ready_list, oob_ready_list
-    finally:
-        _poll_object_cache.release_poll_object(pobj)
-
-select = native_select
-
-def cpython_compatible_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None):
-    # First turn all sockets to non-blocking
-    # keeping track of which ones have changed
-    modified_channels = []
-    try:
-        for socket_list in [read_fd_list, write_fd_list, outofband_fd_list]:
-            for s in socket_list:
-                channel = _getselectable(s)
-                if channel.isBlocking():
-                    modified_channels.append(channel)
-                    channel.configureBlocking(0)
-        return native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout)
-    finally:
-        for channel in modified_channels:
-            channel.configureBlocking(1)
+"""
+This is an select module for use on JVMs > 1.5.
+It is documented, along with known issues and workarounds, on the jython wiki.
+http://wiki.python.org/jython/SelectModule
+"""
+
+import java.nio.channels.SelectableChannel
+import java.nio.channels.SelectionKey
+import java.nio.channels.Selector
+from java.nio.channels.SelectionKey import OP_ACCEPT, OP_CONNECT, OP_WRITE, OP_READ
+
+import errno
+import os
+import Queue
+import socket
+
+class error(Exception): pass
+
+ALL = None
+
+_exception_map = {
+
+# (<javaexception>, <circumstance>) : lambda: <code that raises the python equivalent>
+
+(java.nio.channels.IllegalBlockingModeException, ALL) : error(errno.ESOCKISBLOCKING, 'socket must be in non-blocking mode'),
+}
+
+def _map_exception(exc, circumstance=ALL):
+    try:
+        mapped_exception = _exception_map[(exc.__class__, circumstance)]
+        mapped_exception.java_exception = exc
+        return mapped_exception
+    except KeyError:
+        return error(-1, 'Unmapped java exception: <%s:%s>' % (exc.toString(), circumstance))
+
+POLLIN   = 1
+POLLOUT  = 2
+
+# The following event types are completely ignored on jython
+# Java does not support them, AFAICT
+# They are declared only to support code compatibility with cpython
+
+POLLPRI  = 4
+POLLERR  = 8
+POLLHUP  = 16
+POLLNVAL = 32
+
+def _getselectable(selectable_object):
+    try:
+        channel = selectable_object.getchannel()
+    except:
+        try:
+            channel = selectable_object.fileno().getChannel()
+        except:
+            raise TypeError("Object '%s' is not watchable" % selectable_object,
+                            errno.ENOTSOCK)
+    
+    if channel and not isinstance(channel, java.nio.channels.SelectableChannel):
+        raise TypeError("Object '%s' is not watchable" % selectable_object,
+                        errno.ENOTSOCK)
+    return channel
+
+class poll:
+
+    def __init__(self):
+        self.selector = java.nio.channels.Selector.open()
+        self.chanmap = {}
+        self.unconnected_sockets = []
+
+    def _register_channel(self, socket_object, channel, mask):
+        jmask = 0
+        if mask & POLLIN:
+            # Note that OP_READ is NOT a valid event on server socket channels.
+            if channel.validOps() & OP_ACCEPT:
+                jmask = OP_ACCEPT
+            else:
+                jmask = OP_READ
+        if mask & POLLOUT:
+            if channel.validOps() & OP_WRITE:
+                jmask |= OP_WRITE
+            if channel.validOps() & OP_CONNECT:
+                jmask |= OP_CONNECT
+        selectionkey = channel.register(self.selector, jmask)
+        self.chanmap[channel] = (socket_object, selectionkey)
+
+    def _check_unconnected_sockets(self):
+        temp_list = []
+        for socket_object, mask in self.unconnected_sockets:
+            channel = _getselectable(socket_object)
+            if channel is not None:
+                self._register_channel(socket_object, channel, mask)
+            else:
+                temp_list.append( (socket_object, mask) )
+        self.unconnected_sockets = temp_list
+
+    def register(self, socket_object, mask = POLLIN|POLLOUT|POLLPRI):
+        try:
+            channel = _getselectable(socket_object)
+            if channel is None:
+                # The socket is not yet connected, and thus has no channel
+                # Add it to a pending list, and return
+                self.unconnected_sockets.append( (socket_object, mask) )
+                return
+            self._register_channel(socket_object, channel, mask)
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def unregister(self, socket_object):
+        try:
+            channel = _getselectable(socket_object)
+            self.chanmap[channel][1].cancel()
+            del self.chanmap[channel]
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def _dopoll(self, timeout):
+        if timeout is None or timeout < 0:
+            self.selector.select()
+        else:
+            try:
+                timeout = int(timeout)
+                if not timeout:
+                    self.selector.selectNow()
+                else:
+                    # No multiplication required: both cpython and java use millisecond timeouts
+                    self.selector.select(timeout)
+            except ValueError, vx:
+                raise error("poll timeout must be a number of milliseconds or None", errno.EINVAL)
+        # The returned selectedKeys cannot be used from multiple threads!
+        return self.selector.selectedKeys()
+
+    def poll(self, timeout=None):
+        try:
+            self._check_unconnected_sockets()
+            selectedkeys = self._dopoll(timeout)
+            results = []
+            for k in selectedkeys.iterator():
+                jmask = k.readyOps()
+                pymask = 0
+                if jmask & OP_READ: pymask |= POLLIN
+                if jmask & OP_WRITE: pymask |= POLLOUT
+                if jmask & OP_ACCEPT: pymask |= POLLIN
+                if jmask & OP_CONNECT: pymask |= POLLOUT
+                # Now return the original userobject, and the return event mask
+                results.append( (self.chanmap[k.channel()][0], pymask) )
+            return results
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def _deregister_all(self):
+        try:
+            for k in self.selector.keys():
+                k.cancel()
+            # Keys are not actually removed from the selector until the next select operation.
+            self.selector.selectNow()
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def close(self):
+        try:
+            self._deregister_all()
+            self.selector.close()
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+def _calcselecttimeoutvalue(value):
+    if value is None:
+        return None
+    try:
+        floatvalue = float(value)
+    except Exception, x:
+        raise TypeError("Select timeout value must be a number or None")
+    if value < 0:
+        raise error("Select timeout value cannot be negative", errno.EINVAL)
+    if floatvalue < 0.000001:
+        return 0
+    return int(floatvalue * 1000) # Convert to milliseconds
+
+# This cache for poll objects is required because of a bug in java on MS Windows
+# http://bugs.jython.org/issue1291
+
+class poll_object_cache:
+
+    def __init__(self):
+        self.is_windows = os._name == 'nt'
+        if self.is_windows:
+            self.poll_object_queue = Queue.Queue()
+        import atexit
+        atexit.register(self.finalize)
+
+    def get_poll_object(self):
+        if not self.is_windows:
+            return poll()
+        try:
+            return self.poll_object_queue.get(False)
+        except Queue.Empty:
+            return poll()
+
+    def release_poll_object(self, pobj):
+        if self.is_windows:
+            pobj._deregister_all()
+            self.poll_object_queue.put(pobj)
+        else:
+            pobj.close()
+
+    def finalize(self):
+        if self.is_windows:
+            while True:
+                try:
+                    p = self.poll_object_queue.get(False)
+                    p.close()
+                except Queue.Empty:
+                    return
+
+_poll_object_cache = poll_object_cache()
+
+def native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None):
+    timeout = _calcselecttimeoutvalue(timeout)
+    # First create a poll object to do the actual watching.
+    pobj = _poll_object_cache.get_poll_object()
+    try:
+        registered_for_read = {}
+        # Check the read list
+        for fd in read_fd_list:
+            pobj.register(fd, POLLIN)
+            registered_for_read[fd] = 1
+        # And now the write list
+        for fd in write_fd_list:
+            if fd in registered_for_read:
+                # registering a second time overwrites the first
+                pobj.register(fd, POLLIN|POLLOUT)
+            else:
+                pobj.register(fd, POLLOUT)
+        results = pobj.poll(timeout)
+        # Now start preparing the results
+        read_ready_list, write_ready_list, oob_ready_list = [], [], []
+        for fd, mask in results:
+            if mask & POLLIN:
+                read_ready_list.append(fd)
+            if mask & POLLOUT:
+                write_ready_list.append(fd)
+        return read_ready_list, write_ready_list, oob_ready_list
+    finally:
+        _poll_object_cache.release_poll_object(pobj)
+
+select = native_select
+
+def cpython_compatible_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None):
+    # First turn all sockets to non-blocking
+    # keeping track of which ones have changed
+    modified_channels = []
+    try:
+        for socket_list in [read_fd_list, write_fd_list, outofband_fd_list]:
+            for s in socket_list:
+                channel = _getselectable(s)
+                if channel.isBlocking():
+                    modified_channels.append(channel)
+                    channel.configureBlocking(0)
+        return native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout)
+    finally:
+        for channel in modified_channels:
+            channel.configureBlocking(1)