Hello community,

here is the log from the commit of package python-httplib2 for openSUSE:Factory 
checked in at 2020-04-09 23:14:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-httplib2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-httplib2.new.3248 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-httplib2"

Thu Apr  9 23:14:19 2020 rev:45 rq:791798 version:0.17.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-httplib2/python-httplib2.changes  
2019-11-04 17:04:44.780154718 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-httplib2.new.3248/python-httplib2.changes    
    2020-04-09 23:14:20.522205905 +0200
@@ -1,0 +2,14 @@
+Mon Apr  6 14:02:25 UTC 2020 - Marketa Calabkova <mcalabk...@suse.com>
+
+- Update to 0.17.1
+  * python3: no_proxy was not checked with https
+  * feature: Http().redirect_codes set, works after follow(_all)_redirects 
check
+    This allows one line workaround for old gcloud library that uses 308
+    response without redirect semantics.
+  * IMPORTANT cache invalidation change, fix 307 keep method, add 308 Redirects
+  * proxy: username/password as str compatible with pysocks
+  * python2: regression in connect() error handling
+  * add support for password protected certificate files
+  * feature: Http.close() to clean persistent connections and sensitive data
+
+-------------------------------------------------------------------

Old:
----
  httplib2-0.14.0.tar.gz

New:
----
  httplib2-0.17.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-httplib2.spec ++++++
--- /var/tmp/diff_new_pack.MrWjrw/_old  2020-04-09 23:14:21.166206277 +0200
+++ /var/tmp/diff_new_pack.MrWjrw/_new  2020-04-09 23:14:21.170206280 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-httplib2
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
 # Tests require network connection
 %bcond_with tests
 Name:           python-httplib2
-Version:        0.14.0
+Version:        0.17.1
 Release:        0
 Summary:        A Python HTTP client library
 License:        MIT AND Apache-2.0 AND (MPL-1.1 OR GPL-2.0-or-later OR 
LGPL-2.1-or-later)

++++++ httplib2-0.14.0.tar.gz -> httplib2-0.17.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/PKG-INFO new/httplib2-0.17.1/PKG-INFO
--- old/httplib2-0.14.0/PKG-INFO        2019-09-27 06:52:00.000000000 +0200
+++ new/httplib2-0.17.1/PKG-INFO        2020-04-02 20:28:49.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: httplib2
-Version: 0.14.0
+Version: 0.17.1
 Summary: A comprehensive HTTP client library.
 Home-page: https://github.com/httplib2/httplib2
 Author: Joe Gregorio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/python2/httplib2/__init__.py 
new/httplib2-0.17.1/python2/httplib2/__init__.py
--- old/httplib2-0.14.0/python2/httplib2/__init__.py    2019-09-27 
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python2/httplib2/__init__.py    2020-04-02 
20:28:24.000000000 +0200
@@ -19,7 +19,7 @@
     "Alex Yu",
 ]
 __license__ = "MIT"
-__version__ = '0.14.0'
+__version__ = '0.17.1'
 
 import base64
 import calendar
@@ -76,7 +76,7 @@
 
 
 def _ssl_wrap_socket(
-    sock, key_file, cert_file, disable_validation, ca_certs, ssl_version, 
hostname
+    sock, key_file, cert_file, disable_validation, ca_certs, ssl_version, 
hostname, key_password
 ):
     if disable_validation:
         cert_reqs = ssl.CERT_NONE
@@ -90,11 +90,16 @@
         context.verify_mode = cert_reqs
         context.check_hostname = cert_reqs != ssl.CERT_NONE
         if cert_file:
-            context.load_cert_chain(cert_file, key_file)
+            if key_password:
+                context.load_cert_chain(cert_file, key_file, key_password)
+            else:
+                context.load_cert_chain(cert_file, key_file)
         if ca_certs:
             context.load_verify_locations(ca_certs)
         return context.wrap_socket(sock, server_hostname=hostname)
     else:
+        if key_password:
+            raise NotSupportedOnThisPlatform("Certificate with password is not 
supported.")
         return ssl.wrap_socket(
             sock,
             keyfile=key_file,
@@ -106,7 +111,7 @@
 
 
 def _ssl_wrap_socket_unsupported(
-    sock, key_file, cert_file, disable_validation, ca_certs, ssl_version, 
hostname
+    sock, key_file, cert_file, disable_validation, ca_certs, ssl_version, 
hostname, key_password
 ):
     if not disable_validation:
         raise CertificateValidationUnsupported(
@@ -114,6 +119,8 @@
             "the ssl module installed. To avoid this error, install "
             "the ssl module, or explicity disable validation."
         )
+    if key_password:
+        raise NotSupportedOnThisPlatform("Certificate with password is not 
supported.")
     ssl_sock = socket.ssl(sock, key_file, cert_file)
     return httplib.FakeSocket(sock, ssl_sock)
 
@@ -284,6 +291,12 @@
     "upgrade",
 ]
 
+# https://tools.ietf.org/html/rfc7231#section-8.1.3
+SAFE_METHODS = ("GET", "HEAD")  # TODO add "OPTIONS", "TRACE"
+
+# To change, assign to `Http().redirect_codes`
+REDIRECT_CODES = frozenset((300, 301, 302, 303, 307, 308))
+
 
 def _get_end2end_headers(response):
     hopbyhop = list(HOP_BY_HOP)
@@ -978,8 +991,13 @@
 class KeyCerts(Credentials):
     """Identical to Credentials except that
     name/password are mapped to key/cert."""
+    def add(self, key, cert, domain, password):
+        self.credentials.append((domain.lower(), key, cert, password))
 
-    pass
+    def iter(self, domain):
+        for (cdomain, key, cert, password) in self.credentials:
+            if cdomain == "" or domain == cdomain:
+                yield (key, cert, password)
 
 
 class AllHosts(object):
@@ -1150,7 +1168,6 @@
             raise ProxiesUnavailableError(
                 "Proxy support missing but proxy use was requested!"
             )
-        msg = "getaddrinfo returns an empty list"
         if self.proxy_info and self.proxy_info.isgood():
             use_proxy = True
             proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, 
proxy_pass, proxy_headers = (
@@ -1165,6 +1182,8 @@
             host = self.host
             port = self.port
 
+        socket_err = None
+
         for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
             af, socktype, proto, canonname, sa = res
             try:
@@ -1206,7 +1225,8 @@
                     self.sock.connect((self.host, self.port) + sa[2:])
                 else:
                     self.sock.connect(sa)
-            except socket.error as msg:
+            except socket.error as e:
+                socket_err = e
                 if self.debuglevel > 0:
                     print("connect fail: (%s, %s)" % (self.host, self.port))
                     if use_proxy:
@@ -1229,7 +1249,7 @@
                 continue
             break
         if not self.sock:
-            raise socket.error(msg)
+            raise socket_err or socket.error("getaddrinfo returns an empty 
list")
 
 
 class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
@@ -1253,10 +1273,19 @@
         ca_certs=None,
         disable_ssl_certificate_validation=False,
         ssl_version=None,
+        key_password=None,
     ):
-        httplib.HTTPSConnection.__init__(
-            self, host, port=port, key_file=key_file, cert_file=cert_file, 
strict=strict
-        )
+        if key_password:
+            httplib.HTTPSConnection.__init__(self, host, port=port, 
strict=strict)
+            self._context.load_cert_chain(cert_file, key_file, key_password)
+            self.key_file = key_file
+            self.cert_file = cert_file
+            self.key_password = key_password
+        else:
+            httplib.HTTPSConnection.__init__(
+                self, host, port=port, key_file=key_file, cert_file=cert_file, 
strict=strict
+            )
+            self.key_password = None
         self.timeout = timeout
         self.proxy_info = proxy_info
         if ca_certs is None:
@@ -1317,7 +1346,6 @@
     def connect(self):
         "Connect to a host on a given (SSL) port."
 
-        msg = "getaddrinfo returns an empty list"
         if self.proxy_info and self.proxy_info.isgood():
             use_proxy = True
             proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, 
proxy_pass, proxy_headers = (
@@ -1332,6 +1360,8 @@
             host = self.host
             port = self.port
 
+        socket_err = None
+
         address_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
         for family, socktype, proto, canonname, sockaddr in address_info:
             try:
@@ -1366,6 +1396,7 @@
                     self.ca_certs,
                     self.ssl_version,
                     self.host,
+                    self.key_password,
                 )
                 if self.debuglevel > 0:
                     print("connect: (%s, %s)" % (self.host, self.port))
@@ -1413,7 +1444,8 @@
                     raise
             except (socket.timeout, socket.gaierror):
                 raise
-            except socket.error as msg:
+            except socket.error as e:
+                socket_err = e
                 if self.debuglevel > 0:
                     print("connect fail: (%s, %s)" % (self.host, self.port))
                     if use_proxy:
@@ -1436,7 +1468,7 @@
                 continue
             break
         if not self.sock:
-            raise socket.error(msg)
+            raise socket_err or socket.error("getaddrinfo returns an empty 
list")
 
 
 SCHEME_TO_CONNECTION = {
@@ -1515,7 +1547,10 @@
         ca_certs=None,
         disable_ssl_certificate_validation=False,
         ssl_version=None,
+        key_password=None,
     ):
+        if key_password:
+            raise NotSupportedOnThisPlatform("Certificate with password is not 
supported.")
         httplib.HTTPSConnection.__init__(
             self,
             host,
@@ -1632,10 +1667,14 @@
         # If set to False then no redirects are followed, even safe ones.
         self.follow_redirects = True
 
+        self.redirect_codes = REDIRECT_CODES
+
         # Which HTTP methods do we apply optimistic concurrency to, i.e.
         # which methods get an "if-match:" etag header added to them.
         self.optimistic_concurrency_methods = ["PUT", "PATCH"]
 
+        self.safe_methods = list(SAFE_METHODS)
+
         # If 'follow_redirects' is True, and this is set to True then
         # all redirecs are followed, including unsafe ones.
         self.follow_all_redirects = False
@@ -1649,6 +1688,16 @@
         # Keep Authorization: headers on a redirect.
         self.forward_authorization_headers = False
 
+    def close(self):
+        """Close persistent connections, clear sensitive data.
+        Not thread-safe, requires external synchronization against concurrent 
requests.
+        """
+        existing, self.connections = self.connections, {}
+        for _, c in existing.iteritems():
+            c.close()
+        self.certificates.clear()
+        self.clear_credentials()
+
     def __getstate__(self):
         state_dict = copy.copy(self.__dict__)
         # In case request is augmented by some foreign object such as
@@ -1680,10 +1729,10 @@
         any time a request requires authentication."""
         self.credentials.add(name, password, domain)
 
-    def add_certificate(self, key, cert, domain):
+    def add_certificate(self, key, cert, domain, password=None):
         """Add a key and cert that will be used
         any time a request requires authentication."""
-        self.certificates.add(key, cert, domain)
+        self.certificates.add(key, cert, domain, password)
 
     def clear_credentials(self):
         """Remove all the names and passwords
@@ -1819,10 +1868,10 @@
 
         if (
             self.follow_all_redirects
-            or (method in ["GET", "HEAD"])
-            or response.status == 303
+            or method in self.safe_methods
+            or response.status in (303, 308)
         ):
-            if self.follow_redirects and response.status in [300, 301, 302, 
303, 307]:
+            if self.follow_redirects and response.status in 
self.redirect_codes:
                 # Pick out the location header and basically start from the 
beginning
                 # remembering first to strip the ETag header and decrement our 
'depth'
                 if redirections:
@@ -1842,7 +1891,7 @@
                             response["location"] = urlparse.urljoin(
                                 absolute_uri, location
                             )
-                    if response.status == 301 and method in ["GET", "HEAD"]:
+                    if response.status == 308 or (response.status == 301 and 
method in self.safe_methods):
                         response["-x-permanent-redirect-url"] = 
response["location"]
                         if "content-location" not in response:
                             response["content-location"] = absolute_uri
@@ -1879,7 +1928,7 @@
                         response,
                         content,
                     )
-            elif response.status in [200, 203] and method in ["GET", "HEAD"]:
+            elif response.status in [200, 203] and method in self.safe_methods:
                 # Don't cache 206's since we aren't going to handle byte range 
requests
                 if "content-location" not in response:
                     response["content-location"] = absolute_uri
@@ -1925,7 +1974,7 @@
         a string that contains the response entity body.
         """
         conn_key = ''
-        
+
         try:
             if headers is None:
                 headers = {}
@@ -1958,6 +2007,7 @@
                             ca_certs=self.ca_certs,
                             
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation,
                             ssl_version=self.ssl_version,
+                            key_password=certs[0][2],
                         )
                     else:
                         conn = self.connections[conn_key] = connection_type(
@@ -1978,6 +2028,7 @@
                 headers["accept-encoding"] = "gzip, deflate"
 
             info = email.Message.Message()
+            cachekey = None
             cached_value = None
             if self.cache:
                 cachekey = defrag_uri.encode("utf-8")
@@ -1998,8 +2049,6 @@
                         self.cache.delete(cachekey)
                         cachekey = None
                         cached_value = None
-            else:
-                cachekey = None
 
             if (
                 method in self.optimistic_concurrency_methods
@@ -2011,13 +2060,15 @@
                 # http://www.w3.org/1999/04/Editing/
                 headers["if-match"] = info["etag"]
 
-            if method not in ["GET", "HEAD"] and self.cache and cachekey:
-                # RFC 2616 Section 13.10
+            # https://tools.ietf.org/html/rfc7234
+            # A cache MUST invalidate the effective Request URI as well as 
[...] Location and Content-Location
+            # when a non-error status code is received in response to an 
unsafe request method.
+            if self.cache and cachekey and method not in self.safe_methods:
                 self.cache.delete(cachekey)
 
             # Check the vary header in the cache to see if this request
             # matches what varies in the cache.
-            if method in ["GET", "HEAD"] and "vary" in info:
+            if method in self.safe_methods and "vary" in info:
                 vary = info["vary"]
                 vary_headers = vary.lower().replace(" ", "").split(",")
                 for header in vary_headers:
@@ -2028,11 +2079,14 @@
                         break
 
             if (
-                cached_value
-                and method in ["GET", "HEAD"]
-                and self.cache
+                self.cache
+                and cached_value
+                and (method in self.safe_methods or info["status"] == "308")
                 and "range" not in headers
             ):
+                redirect_method = method
+                if info["status"] not in ("307", "308"):
+                    redirect_method = "GET"
                 if "-x-permanent-redirect-url" in info:
                     # Should cached permanent redirects be counted in our 
redirection count? For now, yes.
                     if redirections <= 0:
@@ -2043,7 +2097,7 @@
                         )
                     (response, new_content) = self.request(
                         info["-x-permanent-redirect-url"],
-                        method="GET",
+                        method=redirect_method,
                         headers=headers,
                         redirections=redirections - 1,
                     )
@@ -2140,7 +2194,7 @@
                 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/python2/httplib2/socks.py 
new/httplib2-0.17.1/python2/httplib2/socks.py
--- old/httplib2-0.14.0/python2/httplib2/socks.py       2019-09-27 
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python2/httplib2/socks.py       2020-04-02 
20:28:24.000000000 +0200
@@ -238,7 +238,15 @@
         headers -     Additional or modified headers for the proxy connect
         request.
         """
-        self.__proxy = (proxytype, addr, port, rdns, username, password, 
headers)
+        self.__proxy = (
+            proxytype,
+            addr,
+            port,
+            rdns,
+            username.encode() if username else None,
+            password.encode() if password else None,
+            headers,
+        )
 
     def __negotiatesocks5(self, destaddr, destport):
         """__negotiatesocks5(self,destaddr,destport)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/python3/httplib2/__init__.py 
new/httplib2-0.17.1/python3/httplib2/__init__.py
--- old/httplib2-0.14.0/python3/httplib2/__init__.py    2019-09-27 
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python3/httplib2/__init__.py    2020-04-02 
20:28:24.000000000 +0200
@@ -15,7 +15,7 @@
     "Alex Yu",
 ]
 __license__ = "MIT"
-__version__ = '0.14.0'
+__version__ = '0.17.1'
 
 import base64
 import calendar
@@ -161,6 +161,13 @@
     "upgrade",
 ]
 
+# https://tools.ietf.org/html/rfc7231#section-8.1.3
+SAFE_METHODS = ("GET", "HEAD", "OPTIONS", "TRACE")
+
+# To change, assign to `Http().redirect_codes`
+REDIRECT_CODES = frozenset((300, 301, 302, 303, 307, 308))
+
+
 from httplib2 import certs
 CA_CERTS = certs.where()
 
@@ -175,7 +182,7 @@
 
 def _build_ssl_context(
     disable_ssl_certificate_validation, ca_certs, cert_file=None, 
key_file=None,
-    maximum_version=None, minimum_version=None,
+    maximum_version=None, minimum_version=None, key_password=None,
 ):
     if not hasattr(ssl, "SSLContext"):
         raise RuntimeError("httplib2 requires Python 3.2+ for ssl.SSLContext")
@@ -207,7 +214,7 @@
     context.load_verify_locations(ca_certs)
 
     if cert_file:
-        context.load_cert_chain(cert_file, key_file)
+        context.load_cert_chain(cert_file, key_file, key_password)
 
     return context
 
@@ -315,7 +322,7 @@
 # Whether to use a strict mode to parse WWW-Authenticate headers
 # Might lead to bad results in case of ill-formed header value,
 # so disabled by default, falling back to relaxed parsing.
-# Set to true to turn on, usefull for testing servers.
+# Set to true to turn on, useful for testing servers.
 USE_WWW_AUTH_STRICT_PARSING = 0
 
 # In regex below:
@@ -959,8 +966,13 @@
 class KeyCerts(Credentials):
     """Identical to Credentials except that
     name/password are mapped to key/cert."""
+    def add(self, key, cert, domain, password):
+        self.credentials.append((domain.lower(), key, cert, password))
 
-    pass
+    def iter(self, domain):
+        for (cdomain, key, cert, password) in self.credentials:
+            if cdomain == "" or domain == cdomain:
+                yield (key, cert, password)
 
 
 class AllHosts(object):
@@ -999,10 +1011,10 @@
           proxy_headers: Additional or modified headers for the proxy connect
           request.
         """
-        if isinstance(proxy_user, str):
-            proxy_user = proxy_user.encode()
-        if isinstance(proxy_pass, str):
-            proxy_pass = proxy_pass.encode()
+        if isinstance(proxy_user, bytes):
+            proxy_user = proxy_user.decode()
+        if isinstance(proxy_pass, bytes):
+            proxy_pass = proxy_pass.decode()
         self.proxy_type, self.proxy_host, self.proxy_port, self.proxy_rdns, 
self.proxy_user, self.proxy_pass, self.proxy_headers = (
             proxy_type,
             proxy_host,
@@ -1245,6 +1257,7 @@
         disable_ssl_certificate_validation=False,
         tls_maximum_version=None,
         tls_minimum_version=None,
+        key_password=None,
     ):
 
         self.disable_ssl_certificate_validation = 
disable_ssl_certificate_validation
@@ -1257,19 +1270,21 @@
         context = _build_ssl_context(
             self.disable_ssl_certificate_validation, self.ca_certs, cert_file, 
key_file,
             maximum_version=tls_maximum_version, 
minimum_version=tls_minimum_version,
+            key_password=key_password,
         )
         super(HTTPSConnectionWithTimeout, self).__init__(
             host,
             port=port,
-            key_file=key_file,
-            cert_file=cert_file,
             timeout=timeout,
             context=context,
         )
+        self.key_file = key_file
+        self.cert_file = cert_file
+        self.key_password = key_password
 
     def connect(self):
         """Connect to a host on a given (SSL) port."""
-        if self.proxy_info and self.proxy_info.isgood():
+        if self.proxy_info and self.proxy_info.isgood() and 
self.proxy_info.applies_to(self.host):
             use_proxy = True
             proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, 
proxy_pass, proxy_headers = (
                 self.proxy_info.astuple()
@@ -1459,10 +1474,14 @@
         # If set to False then no redirects are followed, even safe ones.
         self.follow_redirects = True
 
+        self.redirect_codes = REDIRECT_CODES
+
         # Which HTTP methods do we apply optimistic concurrency to, i.e.
         # which methods get an "if-match:" etag header added to them.
         self.optimistic_concurrency_methods = ["PUT", "PATCH"]
 
+        self.safe_methods = list(SAFE_METHODS)
+
         # If 'follow_redirects' is True, and this is set to True then
         # all redirecs are followed, including unsafe ones.
         self.follow_all_redirects = False
@@ -1476,6 +1495,16 @@
         # Keep Authorization: headers on a redirect.
         self.forward_authorization_headers = False
 
+    def close(self):
+        """Close persistent connections, clear sensitive data.
+        Not thread-safe, requires external synchronization against concurrent 
requests.
+        """
+        existing, self.connections = self.connections, {}
+        for _, c in existing.items():
+            c.close()
+        self.certificates.clear()
+        self.clear_credentials()
+
     def __getstate__(self):
         state_dict = copy.copy(self.__dict__)
         # In case request is augmented by some foreign object such as
@@ -1507,10 +1536,10 @@
         any time a request requires authentication."""
         self.credentials.add(name, password, domain)
 
-    def add_certificate(self, key, cert, domain):
+    def add_certificate(self, key, cert, domain, password=None):
         """Add a key and cert that will be used
         any time a request requires authentication."""
-        self.certificates.add(key, cert, domain)
+        self.certificates.add(key, cert, domain, password)
 
     def clear_credentials(self):
         """Remove all the names and passwords
@@ -1645,10 +1674,10 @@
 
         if (
             self.follow_all_redirects
-            or (method in ["GET", "HEAD"])
-            or response.status == 303
+            or method in self.safe_methods
+            or response.status in (303, 308)
         ):
-            if self.follow_redirects and response.status in [300, 301, 302, 
303, 307]:
+            if self.follow_redirects and response.status in 
self.redirect_codes:
                 # Pick out the location header and basically start from the 
beginning
                 # remembering first to strip the ETag header and decrement our 
'depth'
                 if redirections:
@@ -1668,7 +1697,7 @@
                             response["location"] = urllib.parse.urljoin(
                                 absolute_uri, location
                             )
-                    if response.status == 301 and method in ["GET", "HEAD"]:
+                    if response.status == 308 or (response.status == 301 and 
(method in self.safe_methods)):
                         response["-x-permanent-redirect-url"] = 
response["location"]
                         if "content-location" not in response:
                             response["content-location"] = absolute_uri
@@ -1705,7 +1734,7 @@
                         response,
                         content,
                     )
-            elif response.status in [200, 203] and method in ["GET", "HEAD"]:
+            elif response.status in [200, 203] and method in self.safe_methods:
                 # Don't cache 206's since we aren't going to handle byte range 
requests
                 if "content-location" not in response:
                     response["content-location"] = absolute_uri
@@ -1782,6 +1811,7 @@
                             
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation,
                             tls_maximum_version=self.tls_maximum_version,
                             tls_minimum_version=self.tls_minimum_version,
+                            key_password=certs[0][2],
                         )
                     else:
                         conn = self.connections[conn_key] = connection_type(
@@ -1803,6 +1833,7 @@
                 headers["accept-encoding"] = "gzip, deflate"
 
             info = email.message.Message()
+            cachekey = None
             cached_value = None
             if self.cache:
                 cachekey = defrag_uri
@@ -1820,8 +1851,6 @@
                         self.cache.delete(cachekey)
                         cachekey = None
                         cached_value = None
-            else:
-                cachekey = None
 
             if (
                 method in self.optimistic_concurrency_methods
@@ -1833,13 +1862,15 @@
                 # http://www.w3.org/1999/04/Editing/
                 headers["if-match"] = info["etag"]
 
-            if method not in ["GET", "HEAD"] and self.cache and cachekey:
-                # RFC 2616 Section 13.10
+            # https://tools.ietf.org/html/rfc7234
+            # A cache MUST invalidate the effective Request URI as well as 
[...] Location and Content-Location
+            # when a non-error status code is received in response to an 
unsafe request method.
+            if self.cache and cachekey and method not in self.safe_methods:
                 self.cache.delete(cachekey)
 
             # Check the vary header in the cache to see if this request
             # matches what varies in the cache.
-            if method in ["GET", "HEAD"] and "vary" in info:
+            if method in self.safe_methods and "vary" in info:
                 vary = info["vary"]
                 vary_headers = vary.lower().replace(" ", "").split(",")
                 for header in vary_headers:
@@ -1850,11 +1881,14 @@
                         break
 
             if (
-                cached_value
-                and method in ["GET", "HEAD"]
-                and self.cache
+                self.cache
+                and cached_value
+                and (method in self.safe_methods or info["status"] == "308")
                 and "range" not in headers
             ):
+                redirect_method = method
+                if info["status"] not in ("307", "308"):
+                    redirect_method = "GET"
                 if "-x-permanent-redirect-url" in info:
                     # Should cached permanent redirects be counted in our 
redirection count? For now, yes.
                     if redirections <= 0:
@@ -1865,7 +1899,7 @@
                         )
                     (response, new_content) = self.request(
                         info["-x-permanent-redirect-url"],
-                        method="GET",
+                        method=redirect_method,
                         headers=headers,
                         redirections=redirections - 1,
                     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/python3/httplib2/socks.py 
new/httplib2-0.17.1/python3/httplib2/socks.py
--- old/httplib2-0.14.0/python3/httplib2/socks.py       2019-09-27 
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python3/httplib2/socks.py       2020-04-02 
20:28:24.000000000 +0200
@@ -238,7 +238,15 @@
         headers -     Additional or modified headers for the proxy connect
         request.
         """
-        self.__proxy = (proxytype, addr, port, rdns, username, password, 
headers)
+        self.__proxy = (
+            proxytype,
+            addr,
+            port,
+            rdns,
+            username.encode() if username else None,
+            password.encode() if password else None,
+            headers,
+        )
 
     def __negotiatesocks5(self, destaddr, destport):
         """__negotiatesocks5(self,destaddr,destport)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/python3/httplib2.egg-info/PKG-INFO 
new/httplib2-0.17.1/python3/httplib2.egg-info/PKG-INFO
--- old/httplib2-0.14.0/python3/httplib2.egg-info/PKG-INFO      2019-09-27 
06:52:00.000000000 +0200
+++ new/httplib2-0.17.1/python3/httplib2.egg-info/PKG-INFO      2020-04-02 
20:28:48.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: httplib2
-Version: 0.14.0
+Version: 0.17.1
 Summary: A comprehensive HTTP client library.
 Home-page: https://github.com/httplib2/httplib2
 Author: Joe Gregorio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httplib2-0.14.0/setup.py new/httplib2-0.17.1/setup.py
--- old/httplib2-0.14.0/setup.py        2019-09-27 06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/setup.py        2020-04-02 20:28:24.000000000 +0200
@@ -4,7 +4,7 @@
 import sys
 
 pkgdir = {"": "python%s" % sys.version_info[0]}
-VERSION = '0.14.0'
+VERSION = '0.17.1'
 
 
 # `python setup.py test` uses existing Python environment, no virtualenv, no 
pip.


Reply via email to