[Checkins] SVN: zc.authorizedotnet/trunk/src/zc/authorizedotnet/ Made connection timeouts work, added a coupe of simple unit tests.

Albertas Agejevas alga at pov.lt
Mon Oct 9 10:40:37 EDT 2006


Log message for revision 70586:
  Made connection timeouts work, added a coupe of simple unit tests.
  

Changed:
  U   zc.authorizedotnet/trunk/src/zc/authorizedotnet/processing.py
  U   zc.authorizedotnet/trunk/src/zc/authorizedotnet/tests.py

-=-
Modified: zc.authorizedotnet/trunk/src/zc/authorizedotnet/processing.py
===================================================================
--- zc.authorizedotnet/trunk/src/zc/authorizedotnet/processing.py	2006-10-09 12:48:50 UTC (rev 70585)
+++ zc.authorizedotnet/trunk/src/zc/authorizedotnet/processing.py	2006-10-09 14:40:36 UTC (rev 70586)
@@ -12,13 +12,43 @@
 #
 ##############################################################################
 
-import socket
-import httplib
 from M2Crypto import httpslib, SSL
 import urllib
 import md5
 
 class HTTPSConnection(httpslib.HTTPSConnection):
+    """HTTPS connection with a timeout
+
+    We'll need a connection stub:
+
+        >>> class StubConnection(object):
+        ...     def set_socket_read_timeout(self, tm):
+        ...          print 'Read timeout set to %d seconds, %d microseconds' % (tm.sec, tm.microsec)
+        ...     def set_socket_write_timeout(self, tm):
+        ...          print 'Write timeout set to %d seconds, %d microseconds' % (tm.sec, tm.microsec)
+        ...     def connect(self, address):
+        ...          print 'Connecting to %s' % (address, )
+
+    Now, let's create a HTTPS connection with this stub SSL connection:
+
+        >>> conn = HTTPSConnection('localhost')
+        >>> conn._createConnection = lambda: StubConnection()
+
+        >>> conn.connect()
+        Connecting to ('localhost', 443)
+
+    If the timeout keyword attribute is provided, it is passed to the
+    SSL connection:
+
+        >>> conn = HTTPSConnection('localhost', timeout=4.5)
+        >>> conn._createConnection = lambda: StubConnection()
+
+        >>> conn.connect()
+        Read timeout set to 4 seconds, 500000000 microseconds
+        Write timeout set to 4 seconds, 500000000 microseconds
+        Connecting to ('localhost', 443)
+
+    """
     # why do we use the HTTPS connection in the MCrypto2 httpslib module
     # rather than the one in the standard library's httplib module?  Answer
     # (gathered from Benji): the version in MCrypto2 verifies certificates,
@@ -29,45 +59,44 @@
         self.timeout = timeout
         httpslib.HTTPSConnection.__init__(self, host, port, strict)
 
-    def connect(self):
-        self.sock = SSL.Connection(self.ssl_ctx)
-        self.sock.socket.settimeout(self.timeout)
-        self.sock.connect((self.host, self.port))
+    def _createConnection(self):
+        return SSL.Connection(self.ssl_ctx)
 
+    def _getTimeout(self, timeout):
+        """Create an SSL.timeout object out of a float of seconds
 
-class HTTPConnection(httplib.HTTPConnection):
+            >>> conn = HTTPSConnection('localhost')
+            >>> tm = conn._getTimeout(1.85)
+            >>> tm
+            <M2Crypto.SSL.timeout.timeout instance at ...>
+            >>> tm.sec
+            1
+            >>> tm.microsec
+            850000000
 
-    def __init__(self, host, port=None, strict=None, timeout=None):
-        # timeout is None or float
-        self.timeout = timeout
-        httplib.HTTPConnection.__init__(self, host, port, strict)
+            >>> tm = conn._getTimeout(2.1)
+            >>> tm.sec
+            2
+            >>> tm.microsec
+            100000000
 
+        """
+        seconds = int(timeout)
+        useconds = int((timeout - seconds) * 10 ** 9)
+        return SSL.timeout(seconds, useconds)
+
     def connect(self):
-        """Connect to the host and port specified in __init__."""
-        # !!! This is a copy of the method from the standard library except for
-        # one line marked as "!!!" below
-        msg = "getaddrinfo returns an empty list"
-        for res in socket.getaddrinfo(self.host, self.port, 0,
-                                      socket.SOCK_STREAM):
-            af, socktype, proto, canonname, sa = res
-            try:
-                self.sock = socket.socket(af, socktype, proto)
-                self.sock.settimeout(self.timeout) # !!!
-                if self.debuglevel > 0:
-                    print "connect: (%s, %s)" % (self.host, self.port)
-                self.sock.connect(sa)
-            except socket.error, msg:
-                if self.debuglevel > 0:
-                    print 'connect fail:', (self.host, self.port)
-                if self.sock:
-                    self.sock.close()
-                self.sock = None
-                continue
-            break
-        if not self.sock:
-            raise socket.error, msg
+        self.sock = self._createConnection()
 
+        if self.timeout:
+            timeout = self._getTimeout(self.timeout)
+            self.sock.set_socket_read_timeout(timeout)
+            self.sock.set_socket_write_timeout(timeout)
+            self.sock.blocking = True
 
+        self.sock.connect((self.host, self.port))
+
+
 class TransactionResult(object):
     def __init__(self, fields):
         self.response_code = fields[0]
@@ -120,7 +149,7 @@
 
         if self.server.startswith('localhost:'):
             server, port = self.server.split(':')
-            conn = HTTPConnection(server, port, timeout=self.timeout)
+            conn = httpslib.HTTPConnection(server, port)
         else:
             conn = HTTPSConnection(self.server, timeout=self.timeout)
         conn.putrequest('POST', '/gateway/transact.dll')

Modified: zc.authorizedotnet/trunk/src/zc/authorizedotnet/tests.py
===================================================================
--- zc.authorizedotnet/trunk/src/zc/authorizedotnet/tests.py	2006-10-09 12:48:50 UTC (rev 70585)
+++ zc.authorizedotnet/trunk/src/zc/authorizedotnet/tests.py	2006-10-09 14:40:36 UTC (rev 70586)
@@ -293,7 +293,9 @@
             setUp = localSetUp,
             tearDown = localTearDown,
             )
-    return unittest.TestSuite((remote, local))
+    unit = doctest.DocTestSuite('zc.authorizedotnet.processing',
+                                optionflags=doctest.ELLIPSIS)
+    return unittest.TestSuite((remote, local, unit))
 
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list