From: <fwi...@gm...> - 2012-08-27 16:56:32
|
Hi Alan - there's no urgency on the following (and in fact it may make the most sense to wait for 3.x on it): In the 3.x future, I'd like to start making the Lib/* modifications we have pushable into CPython's Lib. That would mean that small modifications like the mods below in asyncore.py and select.py would get some kind of conditional treatment (ideally a check for the presence of some feature, but I'm sure it will often be "if is_jython" of some kind. I think 3.3 is growing a sys.implementation that we will be able to check. Some day I hope to get to the point where there is just one Lib/* shared among all the implementations. -Frank On Sat, Aug 25, 2012 at 1:49 PM, alan.kennedy <jyt...@py...> wrote: > http://hg.python.org/jython/rev/3aa3d5d67709 > changeset: 6854:3aa3d5d67709 > user: Alan Kennedy <al...@xh...> > date: Sat Aug 25 21:46:40 2012 +0100 > summary: > Jython customisations for asyncore > > files: > Lib/asyncore.py | 53 ++++++++++++++------------ > Lib/select.py | 4 +- > Lib/test/test_asyncore.py | 14 ++++++- > 3 files changed, 45 insertions(+), 26 deletions(-) > > > diff --git a/Lib/asyncore.py b/Lib/asyncore.py > --- a/Lib/asyncore.py > +++ b/Lib/asyncore.py > @@ -174,31 +174,34 @@ > if timeout is not None: > # timeout is in milliseconds > timeout = int(timeout*1000) > - pollster = select.poll() > if map: > - for fd, obj in map.items(): > - flags = 0 > - if obj.readable(): > - flags |= select.POLLIN | select.POLLPRI > - # accepting sockets should not be writable > - if obj.writable() and not obj.accepting: > - flags |= select.POLLOUT > - if flags: > - # Only check for exceptions if object was either readable > - # or writable. > - flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL > - pollster.register(fd, flags) > try: > - r = pollster.poll(timeout) > - except select.error, err: > - if err.args[0] != EINTR: > - raise > - r = [] > - for fd, flags in r: > - obj = map.get(fd) > - if obj is None: > - continue > - readwrite(obj, flags) > + pollster = select._poll_object_cache.get_poll_object() > + for fd, obj in map.items(): > + flags = 0 > + if obj.readable(): > + flags |= select.POLLIN | select.POLLPRI > + # accepting sockets should not be writable > + if obj.writable() and not obj.accepting: > + flags |= select.POLLOUT > + if flags: > + # Only check for exceptions if object was either readable > + # or writable. > + flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL > + pollster.register(obj, flags) > + try: > + r = pollster.poll(timeout) > + except select.error, err: > + if err.args[0] != EINTR: > + raise > + r = [] > + for obj, flags in r: > + # obj = map.get(fd) > + if obj is None: > + continue > + readwrite(obj, flags) > + finally: > + select._poll_object_cache.release_poll_object(pollster) > > poll3 = poll2 # Alias for backward compatibility > > @@ -210,6 +213,8 @@ > poll_fun = poll2 > else: > poll_fun = poll > + if sys.platform.startswith('java'): > + poll_fun = poll2 > > if count is None: > while map: > @@ -301,7 +306,7 @@ > def set_socket(self, sock, map=None): > self.socket = sock > ## self.__dict__['socket'] = sock > - self._fileno = sock.fileno() > + self._fileno = sock > self.add_channel(map) > > def set_reuse_addr(self): > diff --git a/Lib/select.py b/Lib/select.py > --- a/Lib/select.py > +++ b/Lib/select.py > @@ -1,5 +1,5 @@ > """ > -This is an select module for use on JVMs > 1.5. > +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 > """ > @@ -22,6 +22,8 @@ > > # (<javaexception>, <circumstance>) : lambda: <code that raises the python equivalent> > > +(java.nio.channels.ClosedChannelException, ALL) : error(errno.ENOTCONN, 'Socket is not connected'), > +(java.nio.channels.CancelledKeyException, ALL) : error(errno.ENOTCONN, 'Socket is not connected'), > (java.nio.channels.IllegalBlockingModeException, ALL) : error(errno.ESOCKISBLOCKING, 'socket must be in non-blocking mode'), > } > > diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py > --- a/Lib/test/test_asyncore.py > +++ b/Lib/test/test_asyncore.py > @@ -72,6 +72,7 @@ > else: > n = 200 > while n > 0: > + conn.setblocking(False) > r, w, e = select.select([conn], [], []) > if r: > data = conn.recv(10) > @@ -548,6 +549,8 @@ > client = BaseClient(server.address) > self.loop_waiting_for_flag(server) > > + @unittest.skipIf(sys.platform.startswith("java"), > + "FIXME: Currently not working on jython") > def test_handle_read(self): > # make sure handle_read is called on data received > > @@ -575,6 +578,8 @@ > client = TestClient(server.address) > self.loop_waiting_for_flag(client) > > + @unittest.skipIf(sys.platform.startswith("java"), > + "FIXME: Currently not working on jython") > def test_handle_close(self): > # make sure handle_close is called when the other end closes > # the connection > @@ -599,6 +604,8 @@ > client = TestClient(server.address) > self.loop_waiting_for_flag(client) > > + @unittest.skipIf(sys.platform.startswith("java"), > + "OOB not supported on java/jython") > @unittest.skipIf(sys.platform.startswith("sunos"), > "OOB support is broken on Solaris") > def test_handle_expt(self): > @@ -682,8 +689,13 @@ > > s2 = asyncore.dispatcher() > s2.create_socket(socket.AF_INET, socket.SOCK_STREAM) > + # On jython, binding is not enough to create a server socket. > + # Must first bind > + s2.bind((HOST, port)) > + # And then listen, which will cause the actual server socket to be created > + # and then to listen, and thus cause the error > # EADDRINUSE indicates the socket was correctly bound > - self.assertRaises(socket.error, s2.bind, (HOST, port)) > + self.assertRaises(socket.error, s2.listen, (5)) > > def test_set_reuse_addr(self): > sock = socket.socket() > > -- > Repository URL: http://hg.python.org/jython > > _______________________________________________ > Jython-checkins mailing list > Jyt...@py... > http://mail.python.org/mailman/listinfo/jython-checkins > |
From: Alan K. <jyt...@xh...> - 2012-08-27 18:27:13
|
HI Frank, Indeed, it was my intention that the any mods to jython libs be "pushable" upstream to cpython, by making the smallest possible changes and making it clear that they jython-specific. That said, I can see that I should really have just created a new "poll_jython" function in that checkin[1], rather than change the function that was already there: I will make that change. Alan. [1] Although it may look like a lot has changed in that function, it's really just wrapping the select.poll() creation and destruction in a try..finally clause: we unfortunately need more explicit control over frequent creation and destruction of poll objects. select() crashes with IOException http://bugs.jython.org/issue1291 On Mon, Aug 27, 2012 at 5:56 PM, fwi...@gm... <fwi...@gm...> wrote: > Hi Alan - there's no urgency on the following (and in fact it may make > the most sense to wait for 3.x on it): > > In the 3.x future, I'd like to start making the Lib/* modifications we > have pushable into CPython's Lib. That would mean that small > modifications like the mods below in asyncore.py and select.py would > get some kind of conditional treatment (ideally a check for the > presence of some feature, but I'm sure it will often be "if is_jython" > of some kind. I think 3.3 is growing a sys.implementation that we will > be able to check. > > Some day I hope to get to the point where there is just one Lib/* > shared among all the implementations. > > -Frank > > On Sat, Aug 25, 2012 at 1:49 PM, alan.kennedy > <jyt...@py...> wrote: >> http://hg.python.org/jython/rev/3aa3d5d67709 >> changeset: 6854:3aa3d5d67709 >> user: Alan Kennedy <al...@xh...> >> date: Sat Aug 25 21:46:40 2012 +0100 >> summary: >> Jython customisations for asyncore >> >> files: >> Lib/asyncore.py | 53 ++++++++++++++------------ >> Lib/select.py | 4 +- >> Lib/test/test_asyncore.py | 14 ++++++- >> 3 files changed, 45 insertions(+), 26 deletions(-) >> >> >> diff --git a/Lib/asyncore.py b/Lib/asyncore.py >> --- a/Lib/asyncore.py >> +++ b/Lib/asyncore.py >> @@ -174,31 +174,34 @@ >> if timeout is not None: >> # timeout is in milliseconds >> timeout = int(timeout*1000) >> - pollster = select.poll() >> if map: >> - for fd, obj in map.items(): >> - flags = 0 >> - if obj.readable(): >> - flags |= select.POLLIN | select.POLLPRI >> - # accepting sockets should not be writable >> - if obj.writable() and not obj.accepting: >> - flags |= select.POLLOUT >> - if flags: >> - # Only check for exceptions if object was either readable >> - # or writable. >> - flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL >> - pollster.register(fd, flags) >> try: >> - r = pollster.poll(timeout) >> - except select.error, err: >> - if err.args[0] != EINTR: >> - raise >> - r = [] >> - for fd, flags in r: >> - obj = map.get(fd) >> - if obj is None: >> - continue >> - readwrite(obj, flags) >> + pollster = select._poll_object_cache.get_poll_object() >> + for fd, obj in map.items(): >> + flags = 0 >> + if obj.readable(): >> + flags |= select.POLLIN | select.POLLPRI >> + # accepting sockets should not be writable >> + if obj.writable() and not obj.accepting: >> + flags |= select.POLLOUT >> + if flags: >> + # Only check for exceptions if object was either readable >> + # or writable. >> + flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL >> + pollster.register(obj, flags) >> + try: >> + r = pollster.poll(timeout) >> + except select.error, err: >> + if err.args[0] != EINTR: >> + raise >> + r = [] >> + for obj, flags in r: >> + # obj = map.get(fd) >> + if obj is None: >> + continue >> + readwrite(obj, flags) >> + finally: >> + select._poll_object_cache.release_poll_object(pollster) >> >> poll3 = poll2 # Alias for backward compatibility >> >> @@ -210,6 +213,8 @@ >> poll_fun = poll2 >> else: >> poll_fun = poll >> + if sys.platform.startswith('java'): >> + poll_fun = poll2 >> >> if count is None: >> while map: >> @@ -301,7 +306,7 @@ >> def set_socket(self, sock, map=None): >> self.socket = sock >> ## self.__dict__['socket'] = sock >> - self._fileno = sock.fileno() >> + self._fileno = sock >> self.add_channel(map) >> >> def set_reuse_addr(self): >> diff --git a/Lib/select.py b/Lib/select.py >> --- a/Lib/select.py >> +++ b/Lib/select.py >> @@ -1,5 +1,5 @@ >> """ >> -This is an select module for use on JVMs > 1.5. >> +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 >> """ >> @@ -22,6 +22,8 @@ >> >> # (<javaexception>, <circumstance>) : lambda: <code that raises the python equivalent> >> >> +(java.nio.channels.ClosedChannelException, ALL) : error(errno.ENOTCONN, 'Socket is not connected'), >> +(java.nio.channels.CancelledKeyException, ALL) : error(errno.ENOTCONN, 'Socket is not connected'), >> (java.nio.channels.IllegalBlockingModeException, ALL) : error(errno.ESOCKISBLOCKING, 'socket must be in non-blocking mode'), >> } >> >> diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py >> --- a/Lib/test/test_asyncore.py >> +++ b/Lib/test/test_asyncore.py >> @@ -72,6 +72,7 @@ >> else: >> n = 200 >> while n > 0: >> + conn.setblocking(False) >> r, w, e = select.select([conn], [], []) >> if r: >> data = conn.recv(10) >> @@ -548,6 +549,8 @@ >> client = BaseClient(server.address) >> self.loop_waiting_for_flag(server) >> >> + @unittest.skipIf(sys.platform.startswith("java"), >> + "FIXME: Currently not working on jython") >> def test_handle_read(self): >> # make sure handle_read is called on data received >> >> @@ -575,6 +578,8 @@ >> client = TestClient(server.address) >> self.loop_waiting_for_flag(client) >> >> + @unittest.skipIf(sys.platform.startswith("java"), >> + "FIXME: Currently not working on jython") >> def test_handle_close(self): >> # make sure handle_close is called when the other end closes >> # the connection >> @@ -599,6 +604,8 @@ >> client = TestClient(server.address) >> self.loop_waiting_for_flag(client) >> >> + @unittest.skipIf(sys.platform.startswith("java"), >> + "OOB not supported on java/jython") >> @unittest.skipIf(sys.platform.startswith("sunos"), >> "OOB support is broken on Solaris") >> def test_handle_expt(self): >> @@ -682,8 +689,13 @@ >> >> s2 = asyncore.dispatcher() >> s2.create_socket(socket.AF_INET, socket.SOCK_STREAM) >> + # On jython, binding is not enough to create a server socket. >> + # Must first bind >> + s2.bind((HOST, port)) >> + # And then listen, which will cause the actual server socket to be created >> + # and then to listen, and thus cause the error >> # EADDRINUSE indicates the socket was correctly bound >> - self.assertRaises(socket.error, s2.bind, (HOST, port)) >> + self.assertRaises(socket.error, s2.listen, (5)) >> >> def test_set_reuse_addr(self): >> sock = socket.socket() >> >> -- >> Repository URL: http://hg.python.org/jython >> >> _______________________________________________ >> Jython-checkins mailing list >> Jyt...@py... >> http://mail.python.org/mailman/listinfo/jython-checkins >> |
From: <fwi...@gm...> - 2012-08-27 22:43:02
|
On Mon, Aug 27, 2012 at 11:27 AM, Alan Kennedy <jyt...@xh...> wrote: > HI Frank, > > Indeed, it was my intention that the any mods to jython libs be > "pushable" upstream to cpython, by making the smallest possible > changes and making it clear that they jython-specific. > > That said, I can see that I should really have just created a new > "poll_jython" function in that checkin[1], rather than change the > function that was already there: I will make that change. Cool, thanks! -Frank |