Snap for 5339364 from 2f4eea998dae784f2c66396a73d525ba3f53bfb0 to qt-release

Change-Id: I44270cdff9aa8b1ff656307ea2c58ff373b51ebd
diff --git a/.travis.yml b/.travis.yml
index 8e0a165..57991d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
-sudo: false
 language: python
+dist: xenial
 
 cache:
   apt: true
@@ -16,7 +16,7 @@
   - 3.4
   - 3.5
   - 3.6
-  - pypy
+  - 3.7
 matrix:
   fast_finish: true
 install: pip install $pip_install_common 'codecov>=2.0.15' -r requirements-test.txt
@@ -28,6 +28,11 @@
 jobs:
   include:
     - stage: test
+      python: pypy
+      dist: trusty
+      install: pip install $pip_install_common 'codecov>=2.0.15' -r requirements-test.txt
+      script: script/test -sv && codecov
+    - stage: test
       env: _=py2-pep8
       python: 2.7
       install: pip install -r requirements-test.txt
diff --git a/CHANGELOG b/CHANGELOG
index fd29f9f..fc9ef77 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,12 @@
+0.12.1
+
+  Catch socket timeouts and clear dead connection
+  https://github.com/httplib2/httplib2/issues/18
+  https://github.com/httplib2/httplib2/pull/111
+
+  Officially support Python 3.7 (package metadata)
+  https://github.com/httplib2/httplib2/issues/123
+
 0.12.0
 
   Drop support for Python 3.3
diff --git a/METADATA b/METADATA
index 367afc4..d8f0f8a 100644
--- a/METADATA
+++ b/METADATA
@@ -7,12 +7,12 @@
   }
   url {
     type: GIT
-    value: "https://github.com/httplib2/httplib2/"
+    value: "https://github.com/httplib2/httplib2.git"
   }
-  version: "v0.12.0"
+  version: "v0.12.1"
   last_upgrade_date {
     year: 2019
     month: 2
-    day: 1
+    day: 21
   }
 }
diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py
index b89f2fe..fee091d 100644
--- a/python2/httplib2/__init__.py
+++ b/python2/httplib2/__init__.py
@@ -19,7 +19,7 @@
     "Alex Yu",
 ]
 __license__ = "MIT"
-__version__ = '0.12.0'
+__version__ = '0.12.1'
 
 import base64
 import calendar
@@ -1924,6 +1924,8 @@
         being and instance of the 'Response' class, the second being
         a string that contains the response entity body.
         """
+        conn_key = ''
+        
         try:
             if headers is None:
                 headers = {}
@@ -2133,13 +2135,19 @@
                         cachekey,
                     )
         except Exception as e:
+            is_timeout = isinstance(e, socket.timeout)
+            if is_timeout:
+                conn = self.connections.pop(conn_key, None)
+                if conn:
+                    conn.close()
+                    
             if self.force_exception_to_status_code:
                 if isinstance(e, HttpLib2ErrorWithResponse):
                     response = e.response
                     content = e.content
                     response.status = 500
                     response.reason = str(e)
-                elif isinstance(e, socket.timeout):
+                elif is_timeout:
                     content = "Request Timeout"
                     response = Response(
                         {
diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py
index b1b86f4..8b64c41 100644
--- a/python3/httplib2/__init__.py
+++ b/python3/httplib2/__init__.py
@@ -15,7 +15,7 @@
     "Alex Yu",
 ]
 __license__ = "MIT"
-__version__ = '0.12.0'
+__version__ = '0.12.1'
 
 import base64
 import calendar
@@ -1722,6 +1722,8 @@
 being and instance of the 'Response' class, the second being
 a string that contains the response entity body.
         """
+        conn_key = ''
+
         try:
             if headers is None:
                 headers = {}
@@ -1924,6 +1926,12 @@
                         cachekey,
                     )
         except Exception as e:
+            is_timeout = isinstance(e, socket.timeout)
+            if is_timeout:
+                conn = self.connections.pop(conn_key, None)
+                if conn:
+                    conn.close()
+
             if self.force_exception_to_status_code:
                 if isinstance(e, HttpLib2ErrorWithResponse):
                     response = e.response
diff --git a/setup.py b/setup.py
index 3ac0729..7001022 100755
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@
 import sys
 
 pkgdir = {"": "python%s" % sys.version_info[0]}
-VERSION = '0.12.0'
+VERSION = '0.12.1'
 
 
 # `python setup.py test` uses existing Python environment, no virtualenv, no pip.
@@ -87,7 +87,7 @@
     package_data={"httplib2": ["*.txt"]},
     tests_require=read_requirements("requirements-test.txt"),
     cmdclass={"test": TestCommand},
-    classifiers=(
+    classifiers=[
         "Development Status :: 4 - Beta",
         "Environment :: Web Environment",
         "Intended Audience :: Developers",
@@ -100,7 +100,8 @@
         "Programming Language :: Python :: 3.4",
         "Programming Language :: Python :: 3.5",
         "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
         "Topic :: Internet :: WWW/HTTP",
         "Topic :: Software Development :: Libraries",
-    ),
+    ],
 )
diff --git a/tests/test_other.py b/tests/test_other.py
index f714c61..f87cfbd 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -108,6 +108,32 @@
         assert response.reason.startswith("Request Timeout")
 
 
+def test_timeout_subsequent():
+    class Handler(object):
+        number = 0
+
+        @classmethod
+        def handle(cls, request):
+            # request.number is always 1 because of
+            # the new socket connection each time
+            cls.number += 1
+            if cls.number % 2 != 0:
+                time.sleep(0.6)
+                return tests.http_response_bytes(status=500)
+            return tests.http_response_bytes(status=200)
+
+    http = httplib2.Http(timeout=0.5)
+    http.force_exception_to_status_code = True
+
+    with tests.server_request(Handler.handle, request_count=2) as uri:
+        response, _ = http.request(uri)
+        assert response.status == 408
+        assert response.reason.startswith("Request Timeout")
+
+        response, _ = http.request(uri)
+        assert response.status == 200
+
+
 def test_timeout_https():
     c = httplib2.HTTPSConnectionWithTimeout("localhost", 80, timeout=47)
     assert 47 == c.timeout