FIX: TypeError exception when running on Google App Engine. (#12)

* Fix TypeError exception “__init__() got an unexpected keyword argument 'ssl_version’”
* Add additional Google App Engine environment checks
* Fix broken App Engine test cases
diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py
index dd8f239..1bc30d5 100644
--- a/python2/httplib2/__init__.py
+++ b/python2/httplib2/__init__.py
@@ -163,6 +163,8 @@
         self.host = host
         self.cert = cert
 
+class NotRunningAppEngineEnvironment(HttpLib2Error): pass
+
 # Open Items:
 # -----------
 # Proxy support
@@ -1083,8 +1085,61 @@
     'https': HTTPSConnectionWithTimeout
 }
 
+
+def _new_fixed_fetch(validate_certificate):
+    def fixed_fetch(url, payload=None, method="GET", headers={},
+                    allow_truncated=False, follow_redirects=True,
+                    deadline=None):
+        if deadline is None:
+            deadline = socket.getdefaulttimeout()
+        return fetch(url, payload=payload, method=method, headers=headers,
+                     allow_truncated=allow_truncated,
+                     follow_redirects=follow_redirects, deadline=deadline,
+                     validate_certificate=validate_certificate)
+    return fixed_fetch
+
+
+class AppEngineHttpConnection(httplib.HTTPConnection):
+    """Use httplib on App Engine, but compensate for its weirdness.
+
+    The parameters key_file, cert_file, proxy_info, ca_certs,
+    disable_ssl_certificate_validation, and ssl_version are all dropped on
+    the ground.
+    """
+    def __init__(self, host, port=None, key_file=None, cert_file=None,
+                 strict=None, timeout=None, proxy_info=None, ca_certs=None,
+                 disable_ssl_certificate_validation=False,
+                 ssl_version=None):
+        httplib.HTTPConnection.__init__(self, host, port=port,
+                                        strict=strict, timeout=timeout)
+
+
+class AppEngineHttpsConnection(httplib.HTTPSConnection):
+    """Same as AppEngineHttpConnection, but for HTTPS URIs.
+
+    The parameters proxy_info, ca_certs, disable_ssl_certificate_validation,
+    and ssl_version are all dropped on the ground.
+    """
+    def __init__(self, host, port=None, key_file=None, cert_file=None,
+                 strict=None, timeout=None, proxy_info=None, ca_certs=None,
+                 disable_ssl_certificate_validation=False,
+                 ssl_version=None):
+        httplib.HTTPSConnection.__init__(self, host, port=port,
+                                         key_file=key_file,
+                                         cert_file=cert_file, strict=strict,
+                                         timeout=timeout)
+        self._fetch = _new_fixed_fetch(
+                not disable_ssl_certificate_validation)
+
 # Use a different connection object for Google App Engine
 try:
+    server_software = os.environ.get('SERVER_SOFTWARE')
+    if not server_software:
+        raise NotRunningAppEngineEnvironment()
+    elif not (server_software.startswith('Google App Engine/') or
+              server_software.startswith('Development/')):
+        raise NotRunningAppEngineEnvironment()
+
     try:
         from google.appengine.api import apiproxy_stub_map
         if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None:
@@ -1098,48 +1153,12 @@
         from google3.apphosting.api.urlfetch import fetch
         from google3.apphosting.api.urlfetch import InvalidURLError
 
-    def _new_fixed_fetch(validate_certificate):
-        def fixed_fetch(url, payload=None, method="GET", headers={},
-                        allow_truncated=False, follow_redirects=True,
-                        deadline=None):
-            if deadline is None:
-                deadline = socket.getdefaulttimeout()
-            return fetch(url, payload=payload, method=method, headers=headers,
-                         allow_truncated=allow_truncated,
-                         follow_redirects=follow_redirects, deadline=deadline,
-                         validate_certificate=validate_certificate)
-        return fixed_fetch
-
-    class AppEngineHttpConnection(httplib.HTTPConnection):
-        """Use httplib on App Engine, but compensate for its weirdness.
-
-        The parameters key_file, cert_file, proxy_info, ca_certs, and
-        disable_ssl_certificate_validation are all dropped on the ground.
-        """
-        def __init__(self, host, port=None, key_file=None, cert_file=None,
-                     strict=None, timeout=None, proxy_info=None, ca_certs=None,
-                     disable_ssl_certificate_validation=False):
-            httplib.HTTPConnection.__init__(self, host, port=port,
-                                            strict=strict, timeout=timeout)
-
-    class AppEngineHttpsConnection(httplib.HTTPSConnection):
-        """Same as AppEngineHttpConnection, but for HTTPS URIs."""
-        def __init__(self, host, port=None, key_file=None, cert_file=None,
-                     strict=None, timeout=None, proxy_info=None, ca_certs=None,
-                     disable_ssl_certificate_validation=False):
-            httplib.HTTPSConnection.__init__(self, host, port=port,
-                                             key_file=key_file,
-                                             cert_file=cert_file, strict=strict,
-                                             timeout=timeout)
-            self._fetch = _new_fixed_fetch(
-                    not disable_ssl_certificate_validation)
-
     # Update the connection classes to use the Googel App Engine specific ones.
     SCHEME_TO_CONNECTION = {
         'http': AppEngineHttpConnection,
         'https': AppEngineHttpsConnection
     }
-except (ImportError, AttributeError):
+except (ImportError, AttributeError, NotRunningAppEngineEnvironment):
     pass
 
 
diff --git a/python2/httplib2test_appengine.py b/python2/httplib2test_appengine.py
old mode 100644
new mode 100755
index 0c0bdc2..9fad05a
--- a/python2/httplib2test_appengine.py
+++ b/python2/httplib2test_appengine.py
@@ -1,22 +1,11 @@
-"""
-httplib2test_appengine
+"""Tests for httplib2 on Google App Engine."""
 
-A set of unit tests for httplib2.py on Google App Engine
-
-"""
-
-__author__ = "Joe Gregorio (joe@bitworking.org)"
-__copyright__ = "Copyright 2011, Joe Gregorio"
-
+import mock
 import os
 import sys
 import unittest
 
-# The test resources base uri
-base = 'http://bitworking.org/projects/httplib2/test/'
-#base = 'http://localhost/projects/httplib2/test/'
-cacheDirName = ".cache"
-APP_ENGINE_PATH='../../google_appengine'
+APP_ENGINE_PATH='/usr/local/google_appengine'
 
 sys.path.insert(0, APP_ENGINE_PATH)
 
@@ -24,71 +13,66 @@
 dev_appserver.fix_sys_path()
 
 from google.appengine.ext import testbed
-testbed = testbed.Testbed()
-testbed.activate()
-testbed.init_urlfetch_stub()
 
-import google.appengine.api
-
-import httplib2
-
-class AppEngineHttpTest(unittest.TestCase):
-    def setUp(self):
-        if os.path.exists(cacheDirName):
-            [os.remove(os.path.join(cacheDirName, file)) for file in os.listdir(cacheDirName)]
-
-    def test(self):
-        h = httplib2.Http()
-        response, content = h.request("http://bitworking.org")
-        self.assertEqual(httplib2.SCHEME_TO_CONNECTION['https'],
-                         httplib2.AppEngineHttpsConnection)
-        self.assertEquals(1, len(h.connections))
-        self.assertEquals(response.status, 200)
-        self.assertEquals(response['status'], '200')
-
-    # It would be great to run the test below, but it really tests the
-    # aberrant behavior of httplib on App Engine, but that special aberrant
-    # httplib only appears when actually running on App Engine and not when
-    # running via the SDK. When running via the SDK the httplib in std lib is
-    # loaded, which throws a different error when a timeout occurs.
-    #
-    #def test_timeout(self):
-    #    # The script waits 3 seconds, so a timeout of more than that should succeed.
-    #    h = httplib2.Http(timeout=7)
-    #    r, c = h.request('http://bitworking.org/projects/httplib2/test/timeout/timeout.cgi')
-    #
-    #    import httplib
-    #    print httplib.__file__
-    #    h = httplib2.Http(timeout=1)
-    #    try:
-    #      r, c = h.request('http://bitworking.org/projects/httplib2/test/timeout/timeout.cgi')
-    #      self.fail('Timeout should have raised an exception.')
-    #    except DeadlineExceededError:
-    #      pass
-
-    def test_proxy_info_ignored(self):
-        h = httplib2.Http(proxy_info='foo.txt')
-        response, content = h.request("http://bitworking.org")
-        self.assertEquals(response.status, 200)
+# Ensure that we are not loading the httplib2 version included in the Google
+# App Engine SDK.
+sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
 
 
 class AberrationsTest(unittest.TestCase):
-    def setUp(self):
-        self.orig_apiproxy_stub_map = google.appengine.api.apiproxy_stub_map
 
-        # Force apiproxy_stub_map to None to trigger the test condition.
-        google.appengine.api.apiproxy_stub_map = None
-        reload(httplib2)
+  def setUp(self):
+    self.testbed = testbed.Testbed()
+    self.testbed.activate()
+    self.testbed.init_urlfetch_stub()
 
-    def tearDown(self):
-        google.appengine.api.apiproxy_stub_map = self.orig_apiproxy_stub_map
-        reload(httplib2)
+  def tearDown(self):
+    self.testbed.deactivate()
 
-    def test(self):
-        self.assertNotEqual(httplib2.SCHEME_TO_CONNECTION['https'],
-                            httplib2.AppEngineHttpsConnection)
-        self.assertNotEqual(httplib2.SCHEME_TO_CONNECTION['http'],
-                            httplib2.AppEngineHttpConnection)
+  @mock.patch.dict('os.environ', {'SERVER_SOFTWARE': ''})
+  def testConnectionInit(self):
+    global httplib2
+    import httplib2
+    self.assertNotEqual(
+      httplib2.SCHEME_TO_CONNECTION['https'], httplib2.AppEngineHttpsConnection)
+    self.assertNotEqual(
+      httplib2.SCHEME_TO_CONNECTION['http'], httplib2.AppEngineHttpConnection)
+    del globals()['httplib2']
+
+
+class AppEngineHttpTest(unittest.TestCase):
+
+  def setUp(self):
+    self.testbed = testbed.Testbed()
+    self.testbed.activate()
+    self.testbed.init_urlfetch_stub()
+    global httplib2
+    import httplib2
+    reload(httplib2)
+
+  def tearDown(self):
+    self.testbed.deactivate()
+    del globals()['httplib2']
+
+  def testConnectionInit(self):
+    self.assertEqual(
+      httplib2.SCHEME_TO_CONNECTION['https'], httplib2.AppEngineHttpsConnection)
+    self.assertEqual(
+      httplib2.SCHEME_TO_CONNECTION['http'], httplib2.AppEngineHttpConnection)
+
+  def testGet(self):
+    http = httplib2.Http()
+    response, content = http.request("http://www.google.com")
+    self.assertEqual(httplib2.SCHEME_TO_CONNECTION['https'],
+                     httplib2.AppEngineHttpsConnection)
+    self.assertEquals(1, len(http.connections))
+    self.assertEquals(response.status, 200)
+    self.assertEquals(response['status'], '200')
+
+  def testProxyInfoIgnored(self):
+    http = httplib2.Http(proxy_info=mock.MagicMock())
+    response, content = http.request("http://www.google.com")
+    self.assertEquals(response.status, 200)
 
 
 if __name__ == '__main__':