[Checkins] SVN: zc.ngi/trunk/ Bug Fixed:

Jim Fulton jim at zope.com
Tue Jul 27 10:42:39 EDT 2010


Log message for revision 115124:
  Bug Fixed:
  
  When using zc.ngi.testing and a server sent input and closed a
  connection before set_handler was called on the client, the input
  sent by the server was lost.
  

Changed:
  U   zc.ngi/trunk/README.txt
  U   zc.ngi/trunk/src/zc/ngi/testing.py
  U   zc.ngi/trunk/src/zc/ngi/tests.py

-=-
Modified: zc.ngi/trunk/README.txt
===================================================================
--- zc.ngi/trunk/README.txt	2010-07-27 14:33:09 UTC (rev 115123)
+++ zc.ngi/trunk/README.txt	2010-07-27 14:42:39 UTC (rev 115124)
@@ -20,6 +20,16 @@
 *******
 
 ====================
+2.0.0a4 (2010-07-27)
+====================
+
+Bugs Fixed:
+
+- When using zc.ngi.testing and a server sent input and closed a
+  connection before set_handler was called on the client, the input
+  sent by the server was lost.
+
+====================
 2.0.0a3 (2010-07-22)
 ====================
 

Modified: zc.ngi/trunk/src/zc/ngi/testing.py
===================================================================
--- zc.ngi/trunk/src/zc/ngi/testing.py	2010-07-27 14:33:09 UTC (rev 115123)
+++ zc.ngi/trunk/src/zc/ngi/testing.py	2010-07-27 14:42:39 UTC (rev 115124)
@@ -50,10 +50,9 @@
 
     def __init__(self, peer=None, handler=PrintingHandler):
         self.handler = None
-        self.closed = False
-        self.input = ''
-        self.exception = None
+        self.handler_queue = []
         self.control = None
+        self.closed = None
         if peer is None:
             peer = Connection(self)
             handler(peer)
@@ -63,12 +62,26 @@
         return not self.closed
 
     queue = None
-    def _callHandler(self, method, *args):
+    def _callHandler(self, method, arg):
+        if self.handler is None:
+            queue = self.handler_queue
+            if (method == 'handle_input' and queue and queue[-1][0] == method):
+                # combine inputs
+                queue[-1] = method, queue[-1][1]+arg
+            else:
+                queue.append((method, arg))
+            return
+
         if self.queue is None:
-            self.queue = [(method, args)]
-            while self.queue:
-                method, args = self.queue.pop(0)
-                if self.closed and method != 'handle_close':
+            self.queue = queue = [(method, arg)]
+            while queue:
+                method, arg = queue.pop(0)
+
+                if method == 'handle_close':
+                    if self.control is not None:
+                        self.control.closed(self)
+                    self.closed = arg
+                elif self.closed:
                     break
 
                 try:
@@ -84,11 +97,11 @@
                                               None)
                             if handler is None:
                                 return
-                            args = self, 'unhandled exception'
+                            arg = 'unhandled exception'
                         else:
                             raise
 
-                    handler(self, *args)
+                    handler(self, arg)
                 except:
                     print "Error test connection calling connection handler:"
                     traceback.print_exc(file=sys.stdout)
@@ -98,7 +111,7 @@
 
             self.queue = None
         else:
-            self.queue.append((method, args))
+            self.queue.append((method, arg))
 
     def close(self):
         self.peer.test_close('closed')
@@ -111,37 +124,23 @@
 
     def set_handler(self, handler):
         self.handler = handler
-        if self.exception:
-            exception = self.exception
-            self.exception = None
-            self._callHandler('handle_exception', exception)
-        if self.input:
-            self._callHandler('handle_input', self.input)
-            self.input = ''
+        while self.handler_queue:
+            self._callHandler(*self.handler_queue.pop(0))
 
-        # Note is self.closed is True, we self closed and we
-        # don't want to call handle_close.
-        if self.closed and isinstance(self.closed, str):
-            self._callHandler('handle_close', self.closed)
-
     def setHandler(self, handler):
         warnings.warn("setHandler is deprecated. Use set_handler,",
                       DeprecationWarning, stacklevel=2)
         self.set_handler(handler)
 
     def test_input(self, data):
-        if self.handler is not None:
-            self._callHandler('handle_input', data)
-        else:
-            self.input += data
+        self._callHandler('handle_input', data)
 
     def test_close(self, reason):
-        if self.control is not None:
-            self.control.closed(self)
-        self.closed = reason
-        if self.handler is not None:
-            self._callHandler('handle_close', reason)
+        self._callHandler('handle_close', reason)
 
+    def _exception(self, exception):
+        self._callHandler('handle_exception', exception)
+
     def write(self, data):
         if data is zc.ngi.END_OF_DATA:
             return self.close()
@@ -162,12 +161,6 @@
         except Exception, v:
             self._exception(v)
 
-    def _exception(self, exception):
-        if self.handler is None:
-            self.exception = exception
-        else:
-            self._callHandler('handle_exception', exception)
-
 class _ServerConnection(Connection):
     zc.ngi.interfaces.implements(zc.ngi.interfaces.IServerConnection)
 

Modified: zc.ngi/trunk/src/zc/ngi/tests.py
===================================================================
--- zc.ngi/trunk/src/zc/ngi/tests.py	2010-07-27 14:33:09 UTC (rev 115123)
+++ zc.ngi/trunk/src/zc/ngi/tests.py	2010-07-27 14:42:39 UTC (rev 115124)
@@ -23,6 +23,7 @@
 import time
 import unittest
 import warnings
+import zc.ngi.adapters
 import zc.ngi.async
 import zc.ngi.generator
 import zc.ngi.testing
@@ -577,7 +578,29 @@
     >>> listener.close()
     """
 
+def testing_connection_processes_close_and_input_before_set_handler_in_order():
+    r"""
+If we are using test connections and the server sends input and closes
+the connection before the client handler is set, the client must see the input:
 
+    >>> @zc.ngi.adapters.Lines.handler
+    ... def server(c):
+    ...     c.write((yield).upper()+'\n')
+
+    >>> listener = zc.ngi.testing.listener('x', server)
+
+    >>> @zc.ngi.adapters.Lines.handler
+    ... def client(c):
+    ...     c.write('test\n')
+    ...     print (yield)
+
+    >>> zc.ngi.testing.connect('x', client)
+    TEST
+
+    >>> listener.close()
+"""
+
+
 if sys.version_info < (2, 6):
     del setHandler_compatibility
 



More information about the checkins mailing list