From: <am...@us...> - 2011-02-15 21:39:51
|
Revision: 7202 http://jython.svn.sourceforge.net/jython/?rev=7202&view=rev Author: amak Date: 2011-02-15 21:39:44 +0000 (Tue, 15 Feb 2011) Log Message: ----------- Some simple docstring and line-endings changes Modified Paths: -------------- trunk/jython/Lib/select.py trunk/jython/Lib/socket.py Modified: trunk/jython/Lib/select.py =================================================================== --- trunk/jython/Lib/select.py 2011-02-14 23:40:19 UTC (rev 7201) +++ trunk/jython/Lib/select.py 2011-02-15 21:39:44 UTC (rev 7202) @@ -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) Modified: trunk/jython/Lib/socket.py =================================================================== --- trunk/jython/Lib/socket.py 2011-02-14 23:40:19 UTC (rev 7201) +++ trunk/jython/Lib/socket.py 2011-02-15 21:39:44 UTC (rev 7202) @@ -1,16 +1,7 @@ """ -This is an updated socket module for use on JVMs > 1.4; it is derived from the -old jython socket module. -The primary extra it provides is non-blocking support. - -XXX Restrictions: - -- Only INET sockets -- Can't do a very good gethostbyaddr() right... -AMAK: 20050527: added socket timeouts -AMAK: 20070515: Added non-blocking (asynchronous) support -AMAK: 20070515: Added client-side SSL support -AMAK: 20080513: Added support for options +This is an updated socket module for use on JVMs > 1.5; it is derived from the old jython socket module. +It is documented, along with known issues and workarounds, on the jython wiki. +http://wiki.python.org/jython/NewSocketModule """ _defaulttimeout = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |