[Python-checkins] r71635 - in python/branches/release26-maint: Doc/library/asyncore.rst Lib/asyncore.py Lib/test/test_asyncore.py Misc/NEWS

r.david.murray python-checkins at python.org
Thu Apr 16 01:00:41 CEST 2009


Author: r.david.murray
Date: Thu Apr 16 01:00:41 2009
New Revision: 71635

Log:
Merged revisions 70873,70904,70934,71490,71553,71579 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r70873 | josiah.carlson | 2009-03-31 15:32:34 -0400 (Tue, 31 Mar 2009) | 2 lines
  
  This resolves issue 1161031.  Tests pass.
........
  r70904 | josiah.carlson | 2009-03-31 17:49:36 -0400 (Tue, 31 Mar 2009) | 3 lines
  
  Made handle_expt_event() be called last, so that we don't accidentally read
  after closing the socket.
........
  r70934 | josiah.carlson | 2009-03-31 21:28:11 -0400 (Tue, 31 Mar 2009) | 2 lines
  
  Fix for failing asyncore tests.
........
  r71490 | r.david.murray | 2009-04-11 13:52:56 -0400 (Sat, 11 Apr 2009) | 4 lines
  
  Make test_asyncore tests match code changes introduced by the
  fix to Issue1161031, refactoring the test to simplify it in
  the process.
........
  r71553 | r.david.murray | 2009-04-12 21:06:46 -0400 (Sun, 12 Apr 2009) | 3 lines
  
  Adjust test_asyncore to account for intentional asyncore behavior change
  introduced by r70934 that was causing a test failure when run under -O.
........
  r71579 | r.david.murray | 2009-04-13 12:56:32 -0400 (Mon, 13 Apr 2009) | 2 lines
  
  Add missing NEWS item for issue1161031 fix.
........


Modified:
   python/branches/release26-maint/   (props changed)
   python/branches/release26-maint/Doc/library/asyncore.rst
   python/branches/release26-maint/Lib/asyncore.py
   python/branches/release26-maint/Lib/test/test_asyncore.py
   python/branches/release26-maint/Misc/NEWS

Modified: python/branches/release26-maint/Doc/library/asyncore.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/asyncore.rst	(original)
+++ python/branches/release26-maint/Doc/library/asyncore.rst	Thu Apr 16 01:00:41 2009
@@ -81,7 +81,8 @@
    +----------------------+----------------------------------------+
    | Event                | Description                            |
    +======================+========================================+
-   | ``handle_connect()`` | Implied by the first write event       |
+   | ``handle_connect()`` | Implied by the first read or write     |
+   |                      | event                                  |
    +----------------------+----------------------------------------+
    | ``handle_close()``   | Implied by a read event with no data   |
    |                      | available                              |

Modified: python/branches/release26-maint/Lib/asyncore.py
==============================================================================
--- python/branches/release26-maint/Lib/asyncore.py	(original)
+++ python/branches/release26-maint/Lib/asyncore.py	Thu Apr 16 01:00:41 2009
@@ -69,10 +69,12 @@
 class ExitNow(Exception):
     pass
 
+_reraised_exceptions = (ExitNow, KeyboardInterrupt, SystemExit)
+
 def read(obj):
     try:
         obj.handle_read_event()
-    except (ExitNow, KeyboardInterrupt, SystemExit):
+    except _reraised_exceptions:
         raise
     except:
         obj.handle_error()
@@ -80,7 +82,7 @@
 def write(obj):
     try:
         obj.handle_write_event()
-    except (ExitNow, KeyboardInterrupt, SystemExit):
+    except _reraised_exceptions:
         raise
     except:
         obj.handle_error()
@@ -88,22 +90,22 @@
 def _exception(obj):
     try:
         obj.handle_expt_event()
-    except (ExitNow, KeyboardInterrupt, SystemExit):
+    except _reraised_exceptions:
         raise
     except:
         obj.handle_error()
 
 def readwrite(obj, flags):
     try:
-        if flags & (select.POLLIN | select.POLLPRI):
+        if flags & select.POLLIN:
             obj.handle_read_event()
         if flags & select.POLLOUT:
             obj.handle_write_event()
-        if flags & (select.POLLERR | select.POLLNVAL):
-            obj.handle_expt_event()
-        if flags & select.POLLHUP:
+        if flags & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
             obj.handle_close()
-    except (ExitNow, KeyboardInterrupt, SystemExit):
+        if flags & select.POLLPRI:
+            obj.handle_expt_event()
+    except _reraised_exceptions:
         raise
     except:
         obj.handle_error()
@@ -211,6 +213,7 @@
     accepting = False
     closing = False
     addr = None
+    ignore_log_types = frozenset(['warning'])
 
     def __init__(self, sock=None, map=None):
         if map is None:
@@ -398,7 +401,7 @@
         sys.stderr.write('log: %s\n' % str(message))
 
     def log_info(self, message, type='info'):
-        if __debug__ or type != 'info':
+        if type not in self.ignore_log_types:
             print '%s: %s' % (type, message)
 
     def handle_read_event(self):
@@ -432,22 +435,17 @@
         self.handle_write()
 
     def handle_expt_event(self):
-        # if the handle_expt is the same default worthless method,
-        # we'll not even bother calling it, we'll instead generate
-        # a useful error
-        x = True
-        try:
-            y1 = self.__class__.handle_expt.im_func
-            y2 = dispatcher.handle_expt.im_func
-            x = y1 is y2
-        except AttributeError:
-            pass
-
-        if x:
-            err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
-            msg = _strerror(err)
-
-            raise socket.error(err, msg)
+        # handle_expt_event() is called if there might be an error on the
+        # socket, or if there is OOB data
+        # check for the error condition first
+        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
+        if err != 0:
+            # we can get here when select.select() says that there is an
+            # exceptional condition on the socket
+            # since there is an error, we'll go ahead and close the socket
+            # like we would in a subclassed handle_read() that received no
+            # data
+            self.handle_close()
         else:
             self.handle_expt()
 
@@ -472,7 +470,7 @@
         self.handle_close()
 
     def handle_expt(self):
-        self.log_info('unhandled exception', 'warning')
+        self.log_info('unhandled incoming priority event', 'warning')
 
     def handle_read(self):
         self.log_info('unhandled read event', 'warning')
@@ -553,7 +551,7 @@
                 pass
             elif not ignore_all:
                 raise
-        except (ExitNow, KeyboardInterrupt, SystemExit):
+        except _reraised_exceptions:
             raise
         except:
             if not ignore_all:

Modified: python/branches/release26-maint/Lib/test/test_asyncore.py
==============================================================================
--- python/branches/release26-maint/Lib/test/test_asyncore.py	(original)
+++ python/branches/release26-maint/Lib/test/test_asyncore.py	Thu Apr 16 01:00:41 2009
@@ -115,12 +115,24 @@
         def test_readwrite(self):
             # Check that correct methods are called by readwrite()
 
+            attributes = ('read', 'expt', 'write', 'closed', 'error_handled')
+
+            expected = (
+                (select.POLLIN, 'read'),
+                (select.POLLPRI, 'expt'),
+                (select.POLLOUT, 'write'),
+                (select.POLLERR, 'closed'),
+                (select.POLLHUP, 'closed'),
+                (select.POLLNVAL, 'closed'),
+                )
+
             class testobj:
                 def __init__(self):
                     self.read = False
                     self.write = False
                     self.closed = False
                     self.expt = False
+                    self.error_handled = False
 
                 def handle_read_event(self):
                     self.read = True
@@ -137,54 +149,25 @@
                 def handle_error(self):
                     self.error_handled = True
 
-            for flag in (select.POLLIN, select.POLLPRI):
+            for flag, expectedattr in expected:
                 tobj = testobj()
-                self.assertEqual(tobj.read, False)
+                self.assertEqual(getattr(tobj, expectedattr), False)
                 asyncore.readwrite(tobj, flag)
-                self.assertEqual(tobj.read, True)
-
-                # check that ExitNow exceptions in the object handler method
-                # bubbles all the way up through asyncore readwrite call
-                tr1 = exitingdummy()
-                self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag)
-
-                # check that an exception other than ExitNow in the object handler
-                # method causes the handle_error method to get called
-                tr2 = crashingdummy()
-                asyncore.readwrite(tr2, flag)
-                self.assertEqual(tr2.error_handled, True)
 
-            tobj = testobj()
-            self.assertEqual(tobj.write, False)
-            asyncore.readwrite(tobj, select.POLLOUT)
-            self.assertEqual(tobj.write, True)
-
-            # check that ExitNow exceptions in the object handler method
-            # bubbles all the way up through asyncore readwrite call
-            tr1 = exitingdummy()
-            self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1,
-                              select.POLLOUT)
-
-            # check that an exception other than ExitNow in the object handler
-            # method causes the handle_error method to get called
-            tr2 = crashingdummy()
-            asyncore.readwrite(tr2, select.POLLOUT)
-            self.assertEqual(tr2.error_handled, True)
-
-            for flag in (select.POLLERR, select.POLLHUP, select.POLLNVAL):
-                tobj = testobj()
-                self.assertEqual((tobj.expt, tobj.closed)[flag == select.POLLHUP], False)
-                asyncore.readwrite(tobj, flag)
-                self.assertEqual((tobj.expt, tobj.closed)[flag == select.POLLHUP], True)
+                # Only the attribute modified by the routine we expect to be
+                # called should be True.
+                for attr in attributes:
+                    self.assertEqual(getattr(tobj, attr), attr==expectedattr)
 
                 # check that ExitNow exceptions in the object handler method
-                # bubbles all the way up through asyncore readwrite calls
+                # bubbles all the way up through asyncore readwrite call
                 tr1 = exitingdummy()
                 self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag)
 
                 # check that an exception other than ExitNow in the object handler
                 # method causes the handle_error method to get called
                 tr2 = crashingdummy()
+                self.assertEqual(tr2.error_handled, False)
                 asyncore.readwrite(tr2, flag)
                 self.assertEqual(tr2.error_handled, True)
 
@@ -289,15 +272,13 @@
             sys.stdout = stdout
 
         lines = fp.getvalue().splitlines()
-        if __debug__:
-            expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3]
-        else:
-            expected = ['EGGS: %s' % l1, 'SPAM: %s' % l3]
+        expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3]
 
         self.assertEquals(lines, expected)
 
     def test_unhandled(self):
         d = asyncore.dispatcher()
+        d.ignore_log_types = ()
 
         # capture output of dispatcher.log_info() (to stdout via print)
         fp = StringIO()
@@ -313,7 +294,7 @@
             sys.stdout = stdout
 
         lines = fp.getvalue().splitlines()
-        expected = ['warning: unhandled exception',
+        expected = ['warning: unhandled incoming priority event',
                     'warning: unhandled read event',
                     'warning: unhandled write event',
                     'warning: unhandled connect event',

Modified: python/branches/release26-maint/Misc/NEWS
==============================================================================
--- python/branches/release26-maint/Misc/NEWS	(original)
+++ python/branches/release26-maint/Misc/NEWS	Thu Apr 16 01:00:41 2009
@@ -14,6 +14,15 @@
 
 - Issue #5759: float() didn't call __float__ on str subclasses.
 
+Library
+-------
+
+- Issue #1161031: fix readwrite select flag handling: POLLPRI now
+  results in a handle_expt_event call, not handle_read_event, and POLLERR
+  and POLLNVAL now call handle_close, not handle_expt_event.  Also,
+  dispatcher now has an 'ignore_log_types' attribute for suppressing
+  log messages, which is set to 'warning' by default.
+
 
 What's New in Python 2.6.2 rc 1
 ===============================


More information about the Python-checkins mailing list