Adding proxy_info_from_* methods to Python3.

Reviewed in https://codereview.appspot.com/6588078/.
diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py
index de2cbd6..fe5eb38 100644
--- a/python3/httplib2/__init__.py
+++ b/python3/httplib2/__init__.py
@@ -732,6 +732,56 @@
     return socks and (self.proxy_host != None) and (self.proxy_port != None)
 
 
+def proxy_info_from_environment(method='http'):
+    """
+    Read proxy info from the environment variables.
+    """
+    if method not in ('http', 'https'):
+      return
+
+    env_var = method + '_proxy'
+    url = os.environ.get(env_var, os.environ.get(env_var.upper()))
+    if not url:
+      return
+    return proxy_info_from_url(url, method)
+
+
+def proxy_info_from_url(url, method='http'):
+    """
+    Construct a ProxyInfo from a URL (such as http_proxy env var)
+    """
+    url = urllib.parse.urlparse(url)
+    username = None
+    password = None
+    port = None
+    if '@' in url[1]:
+      ident, host_port = url[1].split('@', 1)
+      if ':' in ident:
+        username, password = ident.split(':', 1)
+      else:
+        password = ident
+    else:
+      host_port = url[1]
+    if ':' in host_port:
+      host, port = host_port.split(':', 1)
+    else:
+      host = host_port
+
+    if port:
+        port = int(port)
+    else:
+        port = dict(https=443, http=80)[method]
+
+    proxy_type = 3 # socks.PROXY_TYPE_HTTP
+    return ProxyInfo(
+        proxy_type = proxy_type,
+        proxy_host = host,
+        proxy_port = port,
+        proxy_user = username or None,
+        proxy_pass = password or None,
+    )
+
+
 class HTTPConnectionWithTimeout(http.client.HTTPConnection):
     """HTTPConnection subclass that supports timeouts
 
@@ -798,8 +848,9 @@
 
 and more.
     """
-    def __init__(self, cache=None, timeout=None, proxy_info=None,
-        ca_certs=None, disable_ssl_certificate_validation=False):
+    def __init__(self, cache=None, timeout=None,
+                 proxy_info=proxy_info_from_environment,
+                 ca_certs=None, disable_ssl_certificate_validation=False):
         """If 'cache' is a string then it is used as a directory name for
         a disk cache. Otherwise it must be an object that supports the
         same interface as FileCache.
@@ -812,7 +863,7 @@
         `proxy_info` may be:
           - a callable that takes the http scheme ('http' or 'https') and
             returns a ProxyInfo instance per request. By default, uses
-            ProxyInfo.from_environment.
+            proxy_info_from_environment.
           - a ProxyInfo instance (static proxy config).
           - None (proxy disabled).
 
diff --git a/python3/httplib2test.py b/python3/httplib2test.py
index a3e29b2..1a92726 100755
--- a/python3/httplib2test.py
+++ b/python3/httplib2test.py
@@ -1535,4 +1535,46 @@
         end2end = httplib2._get_end2end_headers(response)

         self.assertEqual(0, len(end2end))

 

-unittest.main()

+

+class TestProxyInfo(unittest.TestCase):

+    def setUp(self):

+        self.orig_env = dict(os.environ)

+

+    def tearDown(self):

+        os.environ.clear()

+        os.environ.update(self.orig_env)

+

+    def test_from_url(self):

+        pi = httplib2.proxy_info_from_url('http://myproxy.example.com')

+        self.assertEqual(pi.proxy_host, 'myproxy.example.com')

+        self.assertEqual(pi.proxy_port, 80)

+        self.assertEqual(pi.proxy_user, None)

+

+    def test_from_url_ident(self):

+        pi = httplib2.proxy_info_from_url('http://zoidberg:fish@someproxy:99')

+        self.assertEqual(pi.proxy_host, 'someproxy')

+        self.assertEqual(pi.proxy_port, 99)

+        self.assertEqual(pi.proxy_user, 'zoidberg')

+        self.assertEqual(pi.proxy_pass, 'fish')

+

+    def test_from_env(self):

+        os.environ['http_proxy'] = 'http://myproxy.example.com:8080'

+        pi = httplib2.proxy_info_from_environment()

+        self.assertEqual(pi.proxy_host, 'myproxy.example.com')

+        self.assertEqual(pi.proxy_port, 8080)

+

+    def test_from_env_no_proxy(self):

+        os.environ['http_proxy'] = 'http://myproxy.example.com:80'

+        os.environ['https_proxy'] = 'http://myproxy.example.com:81'

+        pi = httplib2.proxy_info_from_environment('https')

+        self.assertEqual(pi.proxy_host, 'myproxy.example.com')

+        self.assertEqual(pi.proxy_port, 81)

+

+    def test_from_env_none(self):

+        os.environ.clear()

+        pi = httplib2.proxy_info_from_environment()

+        self.assertEqual(pi, None)

+

+

+if __name__ == '__main__':

+    unittest.main()