Hello community,

here is the log from the commit of package python-acme for openSUSE:Factory 
checked in at 2019-06-03 18:49:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-acme (Old)
 and      /work/SRC/openSUSE:Factory/.python-acme.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-acme"

Mon Jun  3 18:49:56 2019 rev:29 rq:705621 version:0.34.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-acme/python-acme.changes  2019-03-19 
09:59:26.960077495 +0100
+++ /work/SRC/openSUSE:Factory/.python-acme.new.5148/python-acme.changes        
2019-06-03 18:49:58.996545150 +0200
@@ -1,0 +2,6 @@
+Sat May 18 23:13:13 UTC 2019 - Dirk Mueller <[email protected]>
+
+- update to 0.34.2:
+  * sync with main certbot package
+
+-------------------------------------------------------------------

Old:
----
  acme-0.32.0.tar.gz
  acme-0.32.0.tar.gz.asc

New:
----
  acme-0.34.2.tar.gz
  acme-0.34.2.tar.gz.asc

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

Other differences:
------------------
++++++ python-acme.spec ++++++
--- /var/tmp/diff_new_pack.BZfc92/_old  2019-06-03 18:49:59.960544819 +0200
+++ /var/tmp/diff_new_pack.BZfc92/_new  2019-06-03 18:49:59.960544819 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define libname acme
 Name:           python-%{libname}
-Version:        0.32.0
+Version:        0.34.2
 Release:        0
 Summary:        Python library for the ACME protocol
 License:        Apache-2.0

++++++ acme-0.32.0.tar.gz -> acme-0.34.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/PKG-INFO new/acme-0.34.2/PKG-INFO
--- old/acme-0.32.0/PKG-INFO    2019-03-06 21:18:19.000000000 +0100
+++ new/acme-0.34.2/PKG-INFO    2019-05-07 21:17:38.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: acme
-Version: 0.32.0
+Version: 0.34.2
 Summary: ACME protocol implementation in Python
 Home-page: https://github.com/letsencrypt/letsencrypt
 Author: Certbot Project
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/__init__.py 
new/acme-0.34.2/acme/__init__.py
--- old/acme-0.32.0/acme/__init__.py    2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/__init__.py    2019-05-07 21:17:32.000000000 +0200
@@ -6,6 +6,7 @@
 
 """
 import sys
+import warnings
 
 # This code exists to keep backwards compatibility with people using acme.jose
 # before it became the standalone josepy package.
@@ -20,3 +21,30 @@
     # preserved (acme.jose.* is josepy.*)
     if mod == 'josepy' or mod.startswith('josepy.'):
         sys.modules['acme.' + mod.replace('josepy', 'jose', 1)] = 
sys.modules[mod]
+
+
+# This class takes a similar approach to the cryptography project to deprecate 
attributes
+# in public modules. See the _ModuleWithDeprecation class here:
+# 
https://github.com/pyca/cryptography/blob/91105952739442a74582d3e62b3d2111365b0dc7/src/cryptography/utils.py#L129
+class _TLSSNI01DeprecationModule(object):
+    """
+    Internal class delegating to a module, and displaying warnings when
+    attributes related to TLS-SNI-01 are accessed.
+    """
+    def __init__(self, module):
+        self.__dict__['_module'] = module
+
+    def __getattr__(self, attr):
+        if 'TLSSNI01' in attr:
+            warnings.warn('{0} attribute is deprecated, and will be removed 
soon.'.format(attr),
+                          DeprecationWarning, stacklevel=2)
+        return getattr(self._module, attr)
+
+    def __setattr__(self, attr, value):  # pragma: no cover
+        setattr(self._module, attr, value)
+
+    def __delattr__(self, attr):  # pragma: no cover
+        delattr(self._module, attr)
+
+    def __dir__(self):  # pragma: no cover
+        return ['_module'] + dir(self._module)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/challenges.py 
new/acme-0.34.2/acme/challenges.py
--- old/acme-0.32.0/acme/challenges.py  2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/challenges.py  2019-05-07 21:17:32.000000000 +0200
@@ -4,7 +4,7 @@
 import hashlib
 import logging
 import socket
-import warnings
+import sys
 
 from cryptography.hazmat.primitives import hashes  # type: ignore
 import josepy as jose
@@ -15,15 +15,13 @@
 from acme import errors
 from acme import crypto_util
 from acme import fields
+from acme import _TLSSNI01DeprecationModule
 
 logger = logging.getLogger(__name__)
 
 
-# pylint: disable=too-few-public-methods
-
-
 class Challenge(jose.TypedJSONObjectWithFields):
-    # _fields_to_partial_json | pylint: disable=abstract-method
+    # _fields_to_partial_json
     """ACME challenge."""
     TYPES = {}  # type: dict
 
@@ -37,7 +35,7 @@
 
 
 class ChallengeResponse(jose.TypedJSONObjectWithFields):
-    # _fields_to_partial_json | pylint: disable=abstract-method
+    # _fields_to_partial_json
     """ACME challenge response."""
     TYPES = {}  # type: dict
     resource_type = 'challenge'
@@ -96,6 +94,7 @@
         """
         # TODO: check that path combined with uri does not go above
         # URI_ROOT_PATH!
+        # pylint: disable=unsupported-membership-test
         return b'..' not in self.token and b'/' not in self.token
 
 
@@ -108,10 +107,6 @@
     key_authorization = jose.Field("keyAuthorization")
     thumbprint_hash_function = hashes.SHA256
 
-    def __init__(self, *args, **kwargs):
-        super(KeyAuthorizationChallengeResponse, self).__init__(*args, 
**kwargs)
-        self._dump_authorization_key(False)
-
     def verify(self, chall, account_public_key):
         """Verify the key authorization.
 
@@ -144,26 +139,14 @@
 
         return True
 
-    def _dump_authorization_key(self, dump):
-        # type: (bool) -> None
-        """
-        Set if keyAuthorization is dumped in the JSON representation of this 
ChallengeResponse.
-        NB: This method is declared as private because it will eventually be 
removed.
-        :param bool dump: True to dump the keyAuthorization, False otherwise
-        """
-        object.__setattr__(self, '_dump_auth_key', dump)
-
     def to_partial_json(self):
         jobj = super(KeyAuthorizationChallengeResponse, self).to_partial_json()
-        if not self._dump_auth_key:  # pylint: disable=no-member
-            jobj.pop('keyAuthorization', None)
-
+        jobj.pop('keyAuthorization', None)
         return jobj
 
 
 @six.add_metaclass(abc.ABCMeta)
 class KeyAuthorizationChallenge(_TokenChallenge):
-    # pylint: disable=abstract-class-little-used,too-many-ancestors
     """Challenge based on Key Authorization.
 
     :param response_cls: Subclass of `KeyAuthorizationChallengeResponse`
@@ -195,7 +178,7 @@
         :rtype: KeyAuthorizationChallengeResponse
 
         """
-        return self.response_cls(
+        return self.response_cls(  # pylint: disable=not-callable
             key_authorization=self.key_authorization(account_key))
 
     @abc.abstractmethod
@@ -232,7 +215,7 @@
     """ACME dns-01 challenge response."""
     typ = "dns-01"
 
-    def simple_verify(self, chall, domain, account_public_key):
+    def simple_verify(self, chall, domain, account_public_key):  # pylint: 
disable=unused-argument
         """Simple verify.
 
         This method no longer checks DNS records and is a simple wrapper
@@ -248,7 +231,6 @@
         :rtype: bool
 
         """
-        # pylint: disable=unused-argument
         verified = self.verify(chall, account_public_key)
         if not verified:
             logger.debug("Verification of key authorization in response 
failed")
@@ -453,7 +435,6 @@
         kwargs.setdefault("port", self.PORT)
         kwargs["name"] = self.z_domain
         # TODO: try different methods?
-        # pylint: disable=protected-access
         return crypto_util.probe_sni(**kwargs)
 
     def verify_cert(self, cert):
@@ -514,11 +495,6 @@
     # boulder#962, ietf-wg-acme#22
     #n = jose.Field("n", encoder=int, decoder=int)
 
-    def __init__(self, *args, **kwargs):
-        warnings.warn("TLS-SNI-01 is deprecated, and will stop working soon.",
-            DeprecationWarning, stacklevel=2)
-        super(TLSSNI01, self).__init__(*args, **kwargs)
-
     def validation(self, account_key, **kwargs):
         """Generate validation.
 
@@ -560,7 +536,7 @@
         raise NotImplementedError()
 
 
[email protected]  # pylint: disable=too-many-ancestors
[email protected]
 class DNS(_TokenChallenge):
     """ACME "dns" challenge."""
     typ = "dns"
@@ -641,3 +617,7 @@
 
         """
         return chall.check_validation(self.validation, account_public_key)
+
+
+# Patching ourselves to warn about TLS-SNI challenge deprecation and removal.
+sys.modules[__name__] = _TLSSNI01DeprecationModule(sys.modules[__name__])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/challenges_test.py 
new/acme-0.34.2/acme/challenges_test.py
--- old/acme-0.32.0/acme/challenges_test.py     2019-03-06 21:18:08.000000000 
+0100
+++ new/acme-0.34.2/acme/challenges_test.py     2019-05-07 21:17:32.000000000 
+0200
@@ -1,13 +1,12 @@
 """Tests for acme.challenges."""
 import unittest
-import warnings
 
 import josepy as jose
 import mock
 import OpenSSL
 import requests
 
-from six.moves.urllib import parse as urllib_parse  # pylint: 
disable=import-error
+from six.moves.urllib import parse as urllib_parse  # pylint: 
disable=relative-import
 
 from acme import errors
 from acme import test_util
@@ -96,8 +95,6 @@
     def test_to_partial_json(self):
         self.assertEqual({k: v for k, v in self.jmsg.items() if k != 
'keyAuthorization'},
                          self.msg.to_partial_json())
-        self.msg._dump_authorization_key(True)  # pylint: 
disable=protected-access
-        self.assertEqual(self.jmsg, self.msg.to_partial_json())
 
     def test_from_json(self):
         from acme.challenges import DNS01Response
@@ -170,8 +167,6 @@
     def test_to_partial_json(self):
         self.assertEqual({k: v for k, v in self.jmsg.items() if k != 
'keyAuthorization'},
                          self.msg.to_partial_json())
-        self.msg._dump_authorization_key(True)  # pylint: 
disable=protected-access
-        self.assertEqual(self.jmsg, self.msg.to_partial_json())
 
     def test_from_json(self):
         from acme.challenges import HTTP01Response
@@ -293,8 +288,6 @@
     def test_to_partial_json(self):
         self.assertEqual({k: v for k, v in self.jmsg.items() if k != 
'keyAuthorization'},
                          self.response.to_partial_json())
-        self.response._dump_authorization_key(True)  # pylint: 
disable=protected-access
-        self.assertEqual(self.jmsg, self.response.to_partial_json())
 
     def test_from_json(self):
         from acme.challenges import TLSSNI01Response
@@ -374,25 +367,16 @@
             'type': 'tls-sni-01',
             'token': 'a82d5ff8ef740d12881f6d3c2277ab2e',
         }
-
-    def _msg(self):
         from acme.challenges import TLSSNI01
-        with warnings.catch_warnings(record=True) as warn:
-            warnings.simplefilter("always")
-            msg = TLSSNI01(
-                token=jose.b64decode('a82d5ff8ef740d12881f6d3c2277ab2e'))
-            assert warn is not None # using a raw assert for mypy
-            self.assertTrue(len(warn) == 1)
-            self.assertTrue(issubclass(warn[-1].category, DeprecationWarning))
-            self.assertTrue('deprecated' in str(warn[-1].message))
-        return msg
+        self.msg = TLSSNI01(
+            token=jose.b64decode('a82d5ff8ef740d12881f6d3c2277ab2e'))
 
     def test_to_partial_json(self):
-        self.assertEqual(self.jmsg, self._msg().to_partial_json())
+        self.assertEqual(self.jmsg, self.msg.to_partial_json())
 
     def test_from_json(self):
         from acme.challenges import TLSSNI01
-        self.assertEqual(self._msg(), TLSSNI01.from_json(self.jmsg))
+        self.assertEqual(self.msg, TLSSNI01.from_json(self.jmsg))
 
     def test_from_json_hashable(self):
         from acme.challenges import TLSSNI01
@@ -407,10 +391,18 @@
     @mock.patch('acme.challenges.TLSSNI01Response.gen_cert')
     def test_validation(self, mock_gen_cert):
         mock_gen_cert.return_value = ('cert', 'key')
-        self.assertEqual(('cert', 'key'), self._msg().validation(
+        self.assertEqual(('cert', 'key'), self.msg.validation(
             KEY, cert_key=mock.sentinel.cert_key))
         mock_gen_cert.assert_called_once_with(key=mock.sentinel.cert_key)
 
+    def test_deprecation_message(self):
+        with mock.patch('acme.warnings.warn') as mock_warn:
+            from acme.challenges import TLSSNI01
+            assert TLSSNI01
+        self.assertEqual(mock_warn.call_count, 1)
+        self.assertTrue('deprecated' in mock_warn.call_args[0][0])
+
+
 class TLSALPN01ResponseTest(unittest.TestCase):
     # pylint: disable=too-many-instance-attributes
 
@@ -430,8 +422,6 @@
     def test_to_partial_json(self):
         self.assertEqual({k: v for k, v in self.jmsg.items() if k != 
'keyAuthorization'},
                          self.msg.to_partial_json())
-        self.msg._dump_authorization_key(True)  # pylint: 
disable=protected-access
-        self.assertEqual(self.jmsg, self.msg.to_partial_json())
 
     def test_from_json(self):
         from acme.challenges import TLSALPN01Response
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/client.py 
new/acme-0.34.2/acme/client.py
--- old/acme-0.32.0/acme/client.py      2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/client.py      2019-05-07 21:17:32.000000000 +0200
@@ -6,18 +6,17 @@
 import heapq
 import logging
 import time
+import re
+import sys
 
 import six
 from six.moves import http_client  # pylint: disable=import-error
 import josepy as jose
 import OpenSSL
-import re
-from requests_toolbelt.adapters.source import SourceAddressAdapter
 import requests
 from requests.adapters import HTTPAdapter
-import sys
+from requests_toolbelt.adapters.source import SourceAddressAdapter
 
-from acme import challenges
 from acme import crypto_util
 from acme import errors
 from acme import jws
@@ -124,15 +123,6 @@
         """
         return self.update_registration(regr, update={'status': 'deactivated'})
 
-    def query_registration(self, regr):
-        """Query server about registration.
-
-        :param messages.RegistrationResource: Existing Registration
-            Resource.
-
-        """
-        return self._send_recv_regr(regr, messages.UpdateRegistration())
-
     def _authzr_from_response(self, response, identifier=None, uri=None):
         authzr = messages.AuthorizationResource(
             body=messages.Authorization.from_json(response.json()),
@@ -156,23 +146,7 @@
         :raises .UnexpectedUpdate:
 
         """
-        # Because sending keyAuthorization in a response challenge has been 
removed from the ACME
-        # spec, it is not included in the KeyAuthorizationResponseChallenge 
JSON by default.
-        # However as a migration path, we temporarily expect a malformed error 
from the server,
-        # and fallback by resending the challenge response with the 
keyAuthorization field.
-        # TODO: Remove this fallback for Certbot 0.34.0
-        try:
-            response = self._post(challb.uri, response)
-        except messages.Error as error:
-            if (error.code == 'malformed'
-                    and isinstance(response, 
challenges.KeyAuthorizationChallengeResponse)):
-                logger.debug('Error while responding to a challenge without 
keyAuthorization '
-                             'in the JWS, your ACME CA server may not support 
it:\n%s', error)
-                logger.debug('Retrying request with keyAuthorization set.')
-                response._dump_authorization_key(True)  # pylint: 
disable=protected-access
-                response = self._post(challb.uri, response)
-            else:
-                raise
+        response = self._post(challb.uri, response)
         try:
             authzr_uri = response.links['up']['url']
         except KeyError:
@@ -293,6 +267,15 @@
         # pylint: disable=no-member
         return self._regr_from_response(response)
 
+    def query_registration(self, regr):
+        """Query server about registration.
+
+        :param messages.RegistrationResource: Existing Registration
+            Resource.
+
+        """
+        return self._send_recv_regr(regr, messages.UpdateRegistration())
+
     def agree_to_tos(self, regr):
         """Agree to the terms-of-service.
 
@@ -620,10 +603,13 @@
             Resource.
 
         """
-        self.net.account = regr
-        updated_regr = super(ClientV2, self).query_registration(regr)
-        self.net.account = updated_regr
-        return updated_regr
+        self.net.account = regr  # See certbot/certbot#6258
+        # ACME v2 requires to use a POST-as-GET request (POST an empty JWS) 
here.
+        # This is done by passing None instead of an empty UpdateRegistration 
to _post().
+        response = self._post(regr.uri, None)
+        self.net.account = self._regr_from_response(response, uri=regr.uri,
+                                                    
terms_of_service=regr.terms_of_service)
+        return self.net.account
 
     def update_registration(self, regr, update=None):
         """Update registration.
@@ -669,7 +655,7 @@
         response = self._post(self.directory['newOrder'], order)
         body = messages.Order.from_json(response.json())
         authorizations = []
-        for url in body.authorizations:
+        for url in body.authorizations:  # pylint: disable=not-an-iterable
             
authorizations.append(self._authzr_from_response(self._post_as_get(url), 
uri=url))
         return messages.OrderResource(
             body=body,
@@ -731,7 +717,7 @@
                 for chall in authzr.body.challenges:
                     if chall.error != None:
                         failed.append(authzr)
-        if len(failed) > 0:
+        if failed:
             raise errors.ValidationError(failed)
         return orderr.update(authorizations=responses)
 
@@ -775,10 +761,7 @@
 
     def external_account_required(self):
         """Checks if ACME server requires External Account Binding 
authentication."""
-        if hasattr(self.directory, 'meta') and 
self.directory.meta.external_account_required:
-            return True
-        else:
-            return False
+        return hasattr(self.directory, 'meta') and 
self.directory.meta.external_account_required
 
     def _post_as_get(self, *args, **kwargs):
         """
@@ -794,7 +777,7 @@
             # We add an empty payload for POST-as-GET requests
             new_args = args[:1] + (None,) + args[1:]
             try:
-                return self._post(*new_args, **kwargs)  # pylint: 
disable=star-args
+                return self._post(*new_args, **kwargs)
             except messages.Error as error:
                 if error.code == 'malformed':
                     logger.debug('Error during a POST-as-GET request, '
@@ -882,8 +865,7 @@
             for domain in dnsNames:
                 
authorizations.append(self.client.request_domain_challenges(domain))
             return messages.OrderResource(authorizations=authorizations, 
csr_pem=csr_pem)
-        else:
-            return self.client.new_order(csr_pem)
+        return self.client.new_order(csr_pem)
 
     def finalize_order(self, orderr, deadline):
         """Finalize an order and obtain a certificate.
@@ -920,8 +902,7 @@
             chain = crypto_util.dump_pyopenssl_chain(chain).decode()
 
             return orderr.update(fullchain_pem=(cert + chain))
-        else:
-            return self.client.finalize_order(orderr, deadline)
+        return self.client.finalize_order(orderr, deadline)
 
     def revoke(self, cert, rsn):
         """Revoke certificate.
@@ -939,8 +920,7 @@
     def _acme_version_from_directory(self, directory):
         if hasattr(directory, 'newNonce'):
             return 2
-        else:
-            return 1
+        return 1
 
     def external_account_required(self):
         """Checks if the server requires an external account for ACMEv2 
servers.
@@ -948,8 +928,7 @@
         Always return False for ACMEv1 servers, as it doesn't use External 
Account Binding."""
         if self.acme_version == 1:
             return False
-        else:
-            return self.client.external_account_required()
+        return self.client.external_account_required()
 
 
 class ClientNetwork(object):  # pylint: disable=too-many-instance-attributes
@@ -1027,7 +1006,6 @@
             if self.account is not None:
                 kwargs["kid"] = self.account["uri"]
         kwargs["key"] = self.key
-        # pylint: disable=star-args
         return jws.JWS.sign(jobj, **kwargs).json_dumps(indent=2)
 
     @classmethod
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/client_test.py 
new/acme-0.34.2/acme/client_test.py
--- old/acme-0.32.0/acme/client_test.py 2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/client_test.py 2019-05-07 21:17:32.000000000 +0200
@@ -64,7 +64,7 @@
         reg = messages.Registration(
             contact=self.contact, key=KEY.public_key())
         the_arg = dict(reg) # type: Dict
-        self.new_reg = messages.NewRegistration(**the_arg) # pylint: 
disable=star-args
+        self.new_reg = messages.NewRegistration(**the_arg)
         self.regr = messages.RegistrationResource(
             body=reg, uri='https://www.letsencrypt-demo.org/acme/reg/1')
 
@@ -358,7 +358,6 @@
 
     def test_register(self):
         # "Instance of 'Field' has no to_json/update member" bug:
-        # pylint: disable=no-member
         self.response.status_code = http_client.CREATED
         self.response.json.return_value = self.regr.body.to_json()
         self.response.headers['Location'] = self.regr.uri
@@ -371,7 +370,6 @@
 
     def test_update_registration(self):
         # "Instance of 'Field' has no to_json/update member" bug:
-        # pylint: disable=no-member
         self.response.headers['Location'] = self.regr.uri
         self.response.json.return_value = self.regr.body.to_json()
         self.assertEqual(self.regr, self.client.update_registration(self.regr))
@@ -463,34 +461,6 @@
             errors.ClientError, self.client.answer_challenge,
             self.challr.body, challenges.DNSResponse(validation=None))
 
-    def test_answer_challenge_key_authorization_fallback(self):
-        self.response.links['up'] = {'url': self.challr.authzr_uri}
-        self.response.json.return_value = self.challr.body.to_json()
-
-        def _wrapper_post(url, obj, *args, **kwargs):  # pylint: 
disable=unused-argument
-            """
-            Simulate an old ACME CA server, that would respond a 'malformed'
-            error if keyAuthorization is missing.
-            """
-            jobj = obj.to_partial_json()
-            if 'keyAuthorization' not in jobj:
-                raise messages.Error.with_code('malformed')
-            return self.response
-        self.net.post.side_effect = _wrapper_post
-
-        # This challenge response is of type 
KeyAuthorizationChallengeResponse, so the fallback
-        # should be triggered, and avoid an exception.
-        http_chall_response = 
challenges.HTTP01Response(key_authorization='test',
-                                                        
resource=mock.MagicMock())
-        self.client.answer_challenge(self.challr.body, http_chall_response)
-
-        # This challenge response is not of type 
KeyAuthorizationChallengeResponse, so the fallback
-        # should not be triggered, leading to an exception.
-        dns_chall_response = challenges.DNSResponse(validation=None)
-        self.assertRaises(
-            errors.Error, self.client.answer_challenge,
-            self.challr.body, dns_chall_response)
-
     def test_retry_after_date(self):
         self.response.headers['Retry-After'] = 'Fri, 31 Dec 1999 23:59:59 GMT'
         self.assertEqual(
@@ -872,7 +842,6 @@
 
     def test_update_registration(self):
         # "Instance of 'Field' has no to_json/update member" bug:
-        # pylint: disable=no-member
         self.response.headers['Location'] = self.regr.uri
         self.response.json.return_value = self.regr.body.to_json()
         self.assertEqual(self.regr, self.client.update_registration(self.regr))
@@ -934,7 +903,7 @@
         return {'foo': self.value}
 
     @classmethod
-    def from_json(cls, value):
+    def from_json(cls, jobj):
         pass  # pragma: no cover
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/crypto_util.py 
new/acme-0.34.2/acme/crypto_util.py
--- old/acme-0.32.0/acme/crypto_util.py 2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/crypto_util.py 2019-05-07 21:17:32.000000000 +0200
@@ -18,17 +18,14 @@
 
 logger = logging.getLogger(__name__)
 
-# TLSSNI01 certificate serving and probing is not affected by SSL
-# vulnerabilities: prober needs to check certificate for expected
-# contents anyway. Working SNI is the only thing that's necessary for
-# the challenge and thus scoping down SSL/TLS method (version) would
-# cause interoperability issues: TLSv1_METHOD is only compatible with
+# Default SSL method selected here is the most compatible, while secure
+# SSL method: TLSv1_METHOD is only compatible with
 # TLSv1_METHOD, while SSLv23_METHOD is compatible with all other
 # methods, including TLSv2_METHOD (read more at
 # https://www.openssl.org/docs/ssl/SSLv23_method.html). _serve_sni
 # should be changed to use "set_options" to disable SSLv2 and SSLv3,
 # in case it's used for things other than probing/serving!
-_DEFAULT_TLSSNI01_SSL_METHOD = SSL.SSLv23_METHOD  # type: ignore
+_DEFAULT_SSL_METHOD = SSL.SSLv23_METHOD  # type: ignore
 
 
 class SSLSocket(object):  # pylint: disable=too-few-public-methods
@@ -40,7 +37,7 @@
     :ivar method: See `OpenSSL.SSL.Context` for allowed values.
 
     """
-    def __init__(self, sock, certs, method=_DEFAULT_TLSSNI01_SSL_METHOD):
+    def __init__(self, sock, certs, method=_DEFAULT_SSL_METHOD):
         self.sock = sock
         self.certs = certs
         self.method = method
@@ -112,7 +109,7 @@
 
 
 def probe_sni(name, host, port=443, timeout=300,
-              method=_DEFAULT_TLSSNI01_SSL_METHOD, source_address=('', 0)):
+              method=_DEFAULT_SSL_METHOD, source_address=('', 0)):
     """Probe SNI server for SSL certificate.
 
     :param bytes name: Byte string to send as the server name in the
@@ -137,7 +134,6 @@
     socket_kwargs = {'source_address': source_address}
 
     try:
-        # pylint: disable=star-args
         logger.debug(
             "Attempting to connect to %s:%d%s.", host, port,
             " from {0}:{1}".format(
@@ -198,8 +194,7 @@
 
     if common_name is None:
         return sans
-    else:
-        return [common_name] + [d for d in sans if d != common_name]
+    return [common_name] + [d for d in sans if d != common_name]
 
 def _pyopenssl_cert_or_req_san(cert_or_req):
     """Get Subject Alternative Names from certificate or CSR using pyOpenSSL.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/messages.py 
new/acme-0.34.2/acme/messages.py
--- old/acme-0.32.0/acme/messages.py    2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/messages.py    2019-05-07 21:17:32.000000000 +0200
@@ -1,9 +1,9 @@
 """ACME protocol messages."""
-import six
 import json
+import six
 try:
     from collections.abc import Hashable  # pylint: disable=no-name-in-module
-except ImportError:
+except ImportError:  # pragma: no cover
     from collections import Hashable
 
 import josepy as jose
@@ -46,8 +46,7 @@
     """Check if argument is an ACME error."""
     if isinstance(err, Error) and (err.typ is not None):
         return (ERROR_PREFIX in err.typ) or (OLD_ERROR_PREFIX in err.typ)
-    else:
-        return False
+    return False
 
 
 @six.python_2_unicode_compatible
@@ -102,6 +101,7 @@
         code = str(self.typ).split(':')[-1]
         if code in ERROR_CODES:
             return code
+        return None
 
     def __str__(self):
         return b' :: '.join(
@@ -116,18 +116,19 @@
     POSSIBLE_NAMES = NotImplemented
 
     def __init__(self, name):
-        self.POSSIBLE_NAMES[name] = self
+        super(_Constant, self).__init__()
+        self.POSSIBLE_NAMES[name] = self  # pylint: 
disable=unsupported-assignment-operation
         self.name = name
 
     def to_partial_json(self):
         return self.name
 
     @classmethod
-    def from_json(cls, value):
-        if value not in cls.POSSIBLE_NAMES:
+    def from_json(cls, jobj):
+        if jobj not in cls.POSSIBLE_NAMES:  # pylint: 
disable=unsupported-membership-test
             raise jose.DeserializationError(
                 '{0} not recognized'.format(cls.__name__))
-        return cls.POSSIBLE_NAMES[value]
+        return cls.POSSIBLE_NAMES[jobj]  # pylint: 
disable=unsubscriptable-object
 
     def __repr__(self):
         return '{0}({1})'.format(self.__class__.__name__, self.name)
@@ -186,7 +187,6 @@
 
         def __init__(self, **kwargs):
             kwargs = dict((self._internal_name(k), v) for k, v in 
kwargs.items())
-            # pylint: disable=star-args
             super(Directory.Meta, self).__init__(**kwargs)
 
         @property
@@ -322,7 +322,7 @@
 
     def _filter_contact(self, prefix):
         return tuple(
-            detail[len(prefix):] for detail in self.contact
+            detail[len(prefix):] for detail in self.contact  # pylint: 
disable=not-an-iterable
             if detail.startswith(prefix))
 
     @property
@@ -394,7 +394,6 @@
 
     def __init__(self, **kwargs):
         kwargs = dict((self._internal_name(k), v) for k, v in kwargs.items())
-        # pylint: disable=star-args
         super(ChallengeBody, self).__init__(**kwargs)
 
     def encode(self, name):
@@ -477,7 +476,7 @@
     def resolved_combinations(self):
         """Combinations with challenges instead of indices."""
         return tuple(tuple(self.challenges[idx] for idx in combo)
-                     for combo in self.combinations)
+                     for combo in self.combinations)  # pylint: 
disable=not-an-iterable
 
 
 @Directory.register
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/standalone.py 
new/acme-0.34.2/acme/standalone.py
--- old/acme-0.32.0/acme/standalone.py  2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/standalone.py  2019-05-07 21:17:32.000000000 +0200
@@ -17,6 +17,7 @@
 from acme import challenges
 from acme import crypto_util
 from acme.magic_typing import List # pylint: disable=unused-import, 
no-name-in-module
+from acme import _TLSSNI01DeprecationModule
 
 
 logger = logging.getLogger(__name__)
@@ -37,7 +38,7 @@
         self.certs = kwargs.pop("certs", {})
         self.method = kwargs.pop(
             # pylint: disable=protected-access
-            "method", crypto_util._DEFAULT_TLSSNI01_SSL_METHOD)
+            "method", crypto_util._DEFAULT_SSL_METHOD)
         self.allow_reuse_address = kwargs.pop("allow_reuse_address", True)
         socketserver.TCPServer.__init__(self, *args, **kwargs)
 
@@ -82,7 +83,7 @@
                 kwargs["ipv6"] = ip_version
                 new_address = (server_address[0],) + (port,) + 
server_address[2:]
                 new_args = (new_address,) + remaining_args
-                server = ServerClass(*new_args, **kwargs) # pylint: 
disable=star-args
+                server = ServerClass(*new_args, **kwargs)
                 logger.debug(
                     "Successfully bound to %s:%s using %s", new_address[0],
                     new_address[1], "IPv6" if ip_version else "IPv4")
@@ -90,8 +91,8 @@
                 if self.servers:
                     # Already bound using IPv6.
                     logger.debug(
-                        "Certbot wasn't able to bind to %s:%s using %s, this " 
+
-                        "is often expected due to the dual stack nature of " +
+                        "Certbot wasn't able to bind to %s:%s using %s, this "
+                        "is often expected due to the dual stack nature of "
                         "IPv6 socket implementations.",
                         new_address[0], new_address[1],
                         "IPv6" if ip_version else "IPv4")
@@ -104,7 +105,7 @@
                 # If two servers are set up and port 0 was passed in, ensure 
we always
                 # bind to the same port for both servers.
                 port = server.socket.getsockname()[1]
-        if len(self.servers) == 0:
+        if not self.servers:
             raise socket.error("Could not bind to IPv4 or IPv6.")
 
     def serve_forever(self):
@@ -296,5 +297,9 @@
         server.handle_request()
 
 
+# Patching ourselves to warn about TLS-SNI challenge deprecation and removal.
+sys.modules[__name__] = _TLSSNI01DeprecationModule(sys.modules[__name__])
+
+
 if __name__ == "__main__":
     sys.exit(simple_tls_sni_01_server(sys.argv))  # pragma: no cover
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/standalone_test.py 
new/acme-0.34.2/acme/standalone_test.py
--- old/acme-0.32.0/acme/standalone_test.py     2019-03-06 21:18:08.000000000 
+0100
+++ new/acme-0.34.2/acme/standalone_test.py     2019-05-07 21:17:32.000000000 
+0200
@@ -1,13 +1,15 @@
 """Tests for acme.standalone."""
+import multiprocessing
 import os
 import shutil
 import socket
 import threading
 import tempfile
 import unittest
+import time
+from contextlib import closing
 
 from six.moves import http_client  # pylint: disable=import-error
-from six.moves import queue  # pylint: disable=import-error
 from six.moves import socketserver  # type: ignore  # pylint: 
disable=import-error
 
 import josepy as jose
@@ -16,6 +18,7 @@
 
 from acme import challenges
 from acme import crypto_util
+from acme import errors
 from acme import test_util
 from acme.magic_typing import Set # pylint: disable=unused-import, 
no-name-in-module
 
@@ -28,14 +31,14 @@
         from acme.standalone import TLSServer
         server = TLSServer(
             ('', 0), socketserver.BaseRequestHandler, bind_and_activate=True)
-        server.server_close()  # pylint: disable=no-member
+        server.server_close()
 
     def test_ipv6(self):
         if socket.has_ipv6:
             from acme.standalone import TLSServer
             server = TLSServer(
                 ('', 0), socketserver.BaseRequestHandler, 
bind_and_activate=True, ipv6=True)
-            server.server_close()  # pylint: disable=no-member
+            server.server_close()
 
 
 class TLSSNI01ServerTest(unittest.TestCase):
@@ -49,12 +52,11 @@
         )}
         from acme.standalone import TLSSNI01Server
         self.server = TLSSNI01Server(('localhost', 0), certs=self.certs)
-        # pylint: disable=no-member
         self.thread = threading.Thread(target=self.server.serve_forever)
         self.thread.start()
 
     def tearDown(self):
-        self.server.shutdown()  # pylint: disable=no-member
+        self.server.shutdown()
         self.thread.join()
 
     def test_it(self):
@@ -77,13 +79,12 @@
         from acme.standalone import HTTP01Server
         self.server = HTTP01Server(('', 0), resources=self.resources)
 
-        # pylint: disable=no-member
         self.port = self.server.socket.getsockname()[1]
         self.thread = threading.Thread(target=self.server.serve_forever)
         self.thread.start()
 
     def tearDown(self):
-        self.server.shutdown()  # pylint: disable=no-member
+        self.server.shutdown()
         self.thread.join()
 
     def test_index(self):
@@ -136,7 +137,6 @@
                 # NB: On Windows, socket.IPPROTO_IPV6 constant may be missing.
                 # We use the corresponding value (41) instead.
                 level = getattr(socket, "IPPROTO_IPV6", 41)
-                # pylint: disable=no-member
                 self.socket.setsockopt(level, socket.IPV6_V6ONLY, 1)
                 try:
                     self.server_bind()
@@ -209,7 +209,6 @@
         from acme.standalone import HTTP01DualNetworkedServers
         self.servers = HTTP01DualNetworkedServers(('', 0), 
resources=self.resources)
 
-        # pylint: disable=no-member
         self.port = self.servers.getsocknames()[0][1]
         self.servers.serve_forever()
 
@@ -248,7 +247,6 @@
         self.assertFalse(self._test_http01(add=False))
 
 
-@test_util.broken_on_windows
 class TestSimpleTLSSNI01Server(unittest.TestCase):
     """Tests for acme.standalone.simple_tls_sni_01_server."""
 
@@ -263,35 +261,45 @@
         shutil.copy(test_util.vector_path('rsa2048_key.pem'),
                     os.path.join(localhost_dir, 'key.pem'))
 
+        with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as 
sock:
+            sock.bind(('', 0))
+            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+            self.port = sock.getsockname()[1]
+
         from acme.standalone import simple_tls_sni_01_server
-        self.thread = threading.Thread(
-            target=simple_tls_sni_01_server, kwargs={
-                'cli_args': ('filename',),
-                'forever': False,
-            },
-        )
+        self.process = multiprocessing.Process(target=simple_tls_sni_01_server,
+                                               args=(['path', '-p', 
str(self.port)],))
         self.old_cwd = os.getcwd()
         os.chdir(self.test_cwd)
 
     def tearDown(self):
         os.chdir(self.old_cwd)
-        self.thread.join()
+        if self.process.is_alive():
+            self.process.terminate()
+            self.process.join(timeout=5)
+            # Check that we didn't timeout waiting for the process to
+            # terminate.
+            self.assertNotEqual(self.process.exitcode, None)
         shutil.rmtree(self.test_cwd)
 
-    @mock.patch('acme.standalone.logger')
-    def test_it(self, mock_logger):
-        # Use a Queue because mock objects aren't thread safe.
-        q = queue.Queue()  # type: queue.Queue[int]
-        # Add port number to the queue.
-        mock_logger.info.side_effect = lambda *args: q.put(args[-1])
-        self.thread.start()
+    @mock.patch('acme.standalone.TLSSNI01Server.handle_request')
+    def test_mock(self, handle):
+        from acme.standalone import simple_tls_sni_01_server
+        simple_tls_sni_01_server(cli_args=['path', '-p', str(self.port)], 
forever=False)
+        self.assertEqual(handle.call_count, 1)
 
-        # After the timeout, an exception is raised if the queue is empty.
-        port = q.get(timeout=5)
-        cert = crypto_util.probe_sni(b'localhost', b'0.0.0.0', port)
+    def test_live(self):
+        self.process.start()
+        cert = None
+        for _ in range(50):
+            time.sleep(0.1)
+            try:
+                cert = crypto_util.probe_sni(b'localhost', b'127.0.0.1', 
self.port)
+                break
+            except errors.Error:  # pragma: no cover
+                pass
         self.assertEqual(jose.ComparableX509(cert),
-                         test_util.load_comparable_cert(
-                             'rsa2048_cert.pem'))
+                         test_util.load_comparable_cert('rsa2048_cert.pem'))
 
 
 if __name__ == "__main__":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme/test_util.py 
new/acme-0.34.2/acme/test_util.py
--- old/acme-0.32.0/acme/test_util.py   2019-03-06 21:18:08.000000000 +0100
+++ new/acme-0.34.2/acme/test_util.py   2019-05-07 21:17:32.000000000 +0200
@@ -4,9 +4,8 @@
 
 """
 import os
-import sys
-import pkg_resources
 import unittest
+import pkg_resources
 
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import serialization
@@ -93,13 +92,4 @@
         return unittest.skipUnless(condition, reason)
     elif condition:
         return lambda cls: cls
-    else:
-        return lambda cls: None
-
-def broken_on_windows(function):
-    """Decorator to skip temporarily a broken test on Windows."""
-    reason = 'Test is broken and ignored on windows but should be fixed.'
-    return unittest.skipIf(
-        sys.platform == 'win32'
-        and os.environ.get('SKIP_BROKEN_TESTS_ON_WINDOWS', 'true') == 'true',
-        reason)(function)
+    return lambda cls: None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/acme.egg-info/PKG-INFO 
new/acme-0.34.2/acme.egg-info/PKG-INFO
--- old/acme-0.32.0/acme.egg-info/PKG-INFO      2019-03-06 21:18:19.000000000 
+0100
+++ new/acme-0.34.2/acme.egg-info/PKG-INFO      2019-05-07 21:17:38.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: acme
-Version: 0.32.0
+Version: 0.34.2
 Summary: ACME protocol implementation in Python
 Home-page: https://github.com/letsencrypt/letsencrypt
 Author: Certbot Project
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/acme-0.32.0/setup.py new/acme-0.34.2/setup.py
--- old/acme-0.32.0/setup.py    2019-03-06 21:18:09.000000000 +0100
+++ new/acme-0.34.2/setup.py    2019-05-07 21:17:33.000000000 +0200
@@ -3,7 +3,7 @@
 from setuptools.command.test import test as TestCommand
 import sys
 
-version = '0.32.0'
+version = '0.34.2'
 
 # Please update tox.ini when modifying dependency version requirements
 install_requires = [



Reply via email to