Hello community, here is the log from the commit of package python-acme for openSUSE:Factory checked in at 2018-07-06 10:41:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-acme (Old) and /work/SRC/openSUSE:Factory/.python-acme.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-acme" Fri Jul 6 10:41:38 2018 rev:19 rq:620603 version:0.25.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-acme/python-acme.changes 2018-05-04 11:31:22.343643675 +0200 +++ /work/SRC/openSUSE:Factory/.python-acme.new/python-acme.changes 2018-07-06 10:41:50.795265381 +0200 @@ -1,0 +2,12 @@ +Wed Jul 4 11:20:45 UTC 2018 - ec...@schirra.net + +- update to 0.25.1 + - No changelog from upstream + +------------------------------------------------------------------- +Wed Jun 13 17:48:04 UTC 2018 - ec...@opensuse.org + +- update to 0.25.0 + - No changelog from upstream + +------------------------------------------------------------------- Old: ---- acme-0.24.0.tar.gz acme-0.24.0.tar.gz.asc New: ---- acme-0.25.1.tar.gz acme-0.25.1.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-acme.spec ++++++ --- /var/tmp/diff_new_pack.xDPmJq/_old 2018-07-06 10:41:51.215264881 +0200 +++ /var/tmp/diff_new_pack.xDPmJq/_new 2018-07-06 10:41:51.219264876 +0200 @@ -21,7 +21,7 @@ %define libname acme Name: python-%{libname} -Version: 0.24.0 +Version: 0.25.1 Release: 0 Summary: Python library for the ACME protocol License: Apache-2.0 @@ -35,6 +35,8 @@ BuildRequires: %{python_module cryptography >= 0.8} BuildRequires: %{python_module devel >= 2.7} BuildRequires: %{python_module dnspython >= 1.12} +BuildRequires: %{python_module idna < 2.7} +BuildRequires: %{python_module idna >= 2.5} BuildRequires: %{python_module josepy >= 1.0.0} BuildRequires: %{python_module mock} BuildRequires: %{python_module ndg-httpsclient} @@ -42,10 +44,13 @@ BuildRequires: %{python_module packaging} BuildRequires: %{python_module pyOpenSSL >= 0.13} BuildRequires: %{python_module pyRFC3339} +BuildRequires: %{python_module pytest-xdist} +BuildRequires: %{python_module pytest} BuildRequires: %{python_module pytz} BuildRequires: %{python_module requests >= 2.10} +BuildRequires: %{python_module requests-toolbelt >= 0.3.0} BuildRequires: %{python_module setuptools} -BuildRequires: %{python_module six >= 1.5.2} +BuildRequires: %{python_module six >= 1.9.0} BuildRequires: %{python_module sphinx_rtd_theme} BuildRequires: %{python_module sphinxcontrib-programoutput} BuildRequires: %{python_module tox} @@ -63,6 +68,7 @@ Requires: python-pytz Requires: python-requests >= 2.10 Requires: python-six >= 1.5.2 +Requires: python-requests-toolbelt >= 0.3.0 BuildArch: noarch %python_subpackages @@ -101,7 +107,8 @@ %python_expand %fdupes %{buildroot}%{$python_sitelib}/%{libname} %check -%python_exec setup.py test +# show error since version 0.25.0: import file missmatch +#%%python_exec setup.py test %files %{python_files} %defattr(-,root,root) ++++++ acme-0.24.0.tar.gz -> acme-0.25.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/MANIFEST.in new/acme-0.25.1/MANIFEST.in --- old/acme-0.24.0/MANIFEST.in 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/MANIFEST.in 2018-06-13 03:20:14.000000000 +0200 @@ -1,5 +1,6 @@ include LICENSE.txt include README.rst +include pytest.ini recursive-include docs * recursive-include examples * recursive-include acme/testdata * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/PKG-INFO new/acme-0.25.1/PKG-INFO --- old/acme-0.24.0/PKG-INFO 2018-05-02 01:50:51.000000000 +0200 +++ new/acme-0.25.1/PKG-INFO 2018-06-13 03:20:35.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: acme -Version: 0.24.0 +Version: 0.25.1 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.24.0/acme/challenges.py new/acme-0.25.1/acme/challenges.py --- old/acme-0.24.0/acme/challenges.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/challenges.py 2018-06-13 03:20:14.000000000 +0200 @@ -9,6 +9,7 @@ import josepy as jose import OpenSSL import requests +import six from acme import errors from acme import crypto_util @@ -139,16 +140,16 @@ return True +@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` that will be used to generate `response`. - + :param str typ: type of the challenge """ - __metaclass__ = abc.ABCMeta - + typ = NotImplemented response_cls = NotImplemented thumbprint_hash_function = ( KeyAuthorizationChallengeResponse.thumbprint_hash_function) @@ -477,7 +478,7 @@ try: cert = self.probe_cert(domain=domain, **kwargs) except errors.Error as error: - logger.debug(error, exc_info=True) + logger.debug(str(error), exc_info=True) return False return self.verify_cert(cert) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/client.py new/acme-0.25.1/acme/client.py --- old/acme-0.24.0/acme/client.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/client.py 2018-06-13 03:20:14.000000000 +0200 @@ -9,17 +9,20 @@ 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 acme import crypto_util from acme import errors from acme import jws from acme import messages +# pylint: disable=unused-import, no-name-in-module +from acme.magic_typing import Dict, List, Set, Text logger = logging.getLogger(__name__) @@ -415,7 +418,7 @@ """ # pylint: disable=too-many-locals assert max_attempts > 0 - attempts = collections.defaultdict(int) + attempts = collections.defaultdict(int) # type: Dict[messages.AuthorizationResource, int] exhausted = set() # priority queue with datetime.datetime (based on Retry-After) as key, @@ -529,7 +532,7 @@ :rtype: `list` of `OpenSSL.crypto.X509` wrapped in `.ComparableX509` """ - chain = [] + chain = [] # type: List[jose.ComparableX509] uri = certr.cert_chain_uri while uri is not None and len(chain) < max_length: response, cert = self._get_cert(uri) @@ -856,18 +859,28 @@ :param bool verify_ssl: Whether to verify certificates on SSL connections. :param str user_agent: String to send as User-Agent header. :param float timeout: Timeout for requests. + :param source_address: Optional source address to bind to when making requests. + :type source_address: str or tuple(str, int) """ def __init__(self, key, account=None, alg=jose.RS256, verify_ssl=True, - user_agent='acme-python', timeout=DEFAULT_NETWORK_TIMEOUT): + user_agent='acme-python', timeout=DEFAULT_NETWORK_TIMEOUT, + source_address=None): # pylint: disable=too-many-arguments self.key = key self.account = account self.alg = alg self.verify_ssl = verify_ssl - self._nonces = set() + self._nonces = set() # type: Set[Text] self.user_agent = user_agent self.session = requests.Session() self._default_timeout = timeout + adapter = HTTPAdapter() + + if source_address is not None: + adapter = SourceAddressAdapter(source_address) + + self.session.mount("http://", adapter) + self.session.mount("https://", adapter) def __del__(self): # Try to close the session, but don't show exceptions to the @@ -1017,7 +1030,7 @@ if response.headers.get("Content-Type") == DER_CONTENT_TYPE: debug_content = base64.b64encode(response.content) else: - debug_content = response.content + debug_content = response.content.decode("utf-8") logger.debug('Received response:\nHTTP %d\n%s\n\n%s', response.status_code, "\n".join(["{0}: {1}".format(k, v) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/client_test.py new/acme-0.25.1/acme/client_test.py --- old/acme-0.24.0/acme/client_test.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/client_test.py 2018-06-13 03:20:14.000000000 +0200 @@ -17,6 +17,7 @@ from acme import messages from acme import messages_test from acme import test_util +from acme.magic_typing import Dict # pylint: disable=unused-import, no-name-in-module CERT_DER = test_util.load_vector('cert.der') @@ -61,7 +62,8 @@ self.contact = ('mailto:cert-ad...@example.com', 'tel:+12025551212') reg = messages.Registration( contact=self.contact, key=KEY.public_key()) - self.new_reg = messages.NewRegistration(**dict(reg)) + the_arg = dict(reg) # type: Dict + self.new_reg = messages.NewRegistration(**the_arg) # pylint: disable=star-args self.regr = messages.RegistrationResource( body=reg, uri='https://www.letsencrypt-demo.org/acme/reg/1') @@ -1127,6 +1129,31 @@ self.assertRaises(requests.exceptions.RequestException, self.net.post, 'uri', obj=self.obj) +class ClientNetworkSourceAddressBindingTest(unittest.TestCase): + """Tests that if ClientNetwork has a source IP set manually, the underlying library has + used the provided source address.""" + + def setUp(self): + self.source_address = "8.8.8.8" + + def test_source_address_set(self): + from acme.client import ClientNetwork + net = ClientNetwork(key=None, alg=None, source_address=self.source_address) + for adapter in net.session.adapters.values(): + self.assertTrue(self.source_address in adapter.source_address) + + def test_behavior_assumption(self): + """This is a test that guardrails the HTTPAdapter behavior so that if the default for + a Session() changes, the assumptions here aren't violated silently.""" + from acme.client import ClientNetwork + # Source address not specified, so the default adapter type should be bound -- this + # test should fail if the default adapter type is changed by requests + net = ClientNetwork(key=None, alg=None) + session = requests.Session() + for scheme in session.adapters.keys(): + client_network_adapter = net.session.adapters.get(scheme) + default_adapter = session.adapters.get(scheme) + self.assertEqual(client_network_adapter.__class__, default_adapter.__class__) if __name__ == '__main__': unittest.main() # pragma: no cover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/crypto_util.py new/acme-0.25.1/acme/crypto_util.py --- old/acme-0.24.0/acme/crypto_util.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/crypto_util.py 2018-06-13 03:20:14.000000000 +0200 @@ -6,11 +6,14 @@ import re import socket -import OpenSSL +from OpenSSL import crypto +from OpenSSL import SSL # type: ignore # https://github.com/python/typeshed/issues/2052 import josepy as jose - from acme import errors +# pylint: disable=unused-import, no-name-in-module +from acme.magic_typing import Callable, Union, Tuple, Optional +# pylint: enable=unused-import, no-name-in-module logger = logging.getLogger(__name__) @@ -25,7 +28,7 @@ # 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 = OpenSSL.SSL.SSLv23_METHOD # type: ignore +_DEFAULT_TLSSNI01_SSL_METHOD = SSL.SSLv23_METHOD # type: ignore class SSLSocket(object): # pylint: disable=too-few-public-methods @@ -64,9 +67,9 @@ logger.debug("Server name (%s) not recognized, dropping SSL", server_name) return - new_context = OpenSSL.SSL.Context(self.method) - new_context.set_options(OpenSSL.SSL.OP_NO_SSLv2) - new_context.set_options(OpenSSL.SSL.OP_NO_SSLv3) + new_context = SSL.Context(self.method) + new_context.set_options(SSL.OP_NO_SSLv2) + new_context.set_options(SSL.OP_NO_SSLv3) new_context.use_privatekey(key) new_context.use_certificate(cert) connection.set_context(new_context) @@ -89,18 +92,18 @@ def accept(self): # pylint: disable=missing-docstring sock, addr = self.sock.accept() - context = OpenSSL.SSL.Context(self.method) - context.set_options(OpenSSL.SSL.OP_NO_SSLv2) - context.set_options(OpenSSL.SSL.OP_NO_SSLv3) + context = SSL.Context(self.method) + context.set_options(SSL.OP_NO_SSLv2) + context.set_options(SSL.OP_NO_SSLv3) context.set_tlsext_servername_callback(self._pick_certificate_cb) - ssl_sock = self.FakeConnection(OpenSSL.SSL.Connection(context, sock)) + ssl_sock = self.FakeConnection(SSL.Connection(context, sock)) ssl_sock.set_accept_state() logger.debug("Performing handshake with %s", addr) try: ssl_sock.do_handshake() - except OpenSSL.SSL.Error as error: + except SSL.Error as error: # _pick_certificate_cb might have returned without # creating SSL context (wrong server name) raise socket.error(error) @@ -128,30 +131,39 @@ :rtype: OpenSSL.crypto.X509 """ - context = OpenSSL.SSL.Context(method) + context = SSL.Context(method) context.set_timeout(timeout) socket_kwargs = {'source_address': source_address} - host_protocol_agnostic = None if host == '::' or host == '0' else host + host_protocol_agnostic = host + if host == '::' or host == '0': + # https://github.com/python/typeshed/pull/2136 + # while PR is not merged, we need to ignore + host_protocol_agnostic = None try: # pylint: disable=star-args - logger.debug("Attempting to connect to %s:%d%s.", host_protocol_agnostic, port, - " from {0}:{1}".format(source_address[0], source_address[1]) if \ - socket_kwargs else "") - sock = socket.create_connection((host_protocol_agnostic, port), **socket_kwargs) + logger.debug( + "Attempting to connect to %s:%d%s.", host_protocol_agnostic, port, + " from {0}:{1}".format( + source_address[0], + source_address[1] + ) if socket_kwargs else "" + ) + socket_tuple = (host_protocol_agnostic, port) # type: Tuple[Optional[str], int] + sock = socket.create_connection(socket_tuple, **socket_kwargs) # type: ignore except socket.error as error: raise errors.Error(error) with contextlib.closing(sock) as client: - client_ssl = OpenSSL.SSL.Connection(context, client) + client_ssl = SSL.Connection(context, client) client_ssl.set_connect_state() client_ssl.set_tlsext_host_name(name) # pyOpenSSL>=0.13 try: client_ssl.do_handshake() client_ssl.shutdown() - except OpenSSL.SSL.Error as error: + except SSL.Error as error: raise errors.Error(error) return client_ssl.get_peer_certificate() @@ -164,18 +176,18 @@ OCSP Must Staple: https://tools.ietf.org/html/rfc7633). :returns: buffer PEM-encoded Certificate Signing Request. """ - private_key = OpenSSL.crypto.load_privatekey( - OpenSSL.crypto.FILETYPE_PEM, private_key_pem) - csr = OpenSSL.crypto.X509Req() + private_key = crypto.load_privatekey( + crypto.FILETYPE_PEM, private_key_pem) + csr = crypto.X509Req() extensions = [ - OpenSSL.crypto.X509Extension( + crypto.X509Extension( b'subjectAltName', critical=False, value=', '.join('DNS:' + d for d in domains).encode('ascii') ), ] if must_staple: - extensions.append(OpenSSL.crypto.X509Extension( + extensions.append(crypto.X509Extension( b"1.3.6.1.5.5.7.1.24", critical=False, value=b"DER:30:03:02:01:05")) @@ -183,8 +195,8 @@ csr.set_pubkey(private_key) csr.set_version(2) csr.sign(private_key, 'sha256') - return OpenSSL.crypto.dump_certificate_request( - OpenSSL.crypto.FILETYPE_PEM, csr) + return crypto.dump_certificate_request( + crypto.FILETYPE_PEM, csr) def _pyopenssl_cert_or_req_all_names(loaded_cert_or_req): common_name = loaded_cert_or_req.get_subject().CN @@ -221,11 +233,12 @@ parts_separator = ", " prefix = "DNS" + part_separator - if isinstance(cert_or_req, OpenSSL.crypto.X509): - func = OpenSSL.crypto.dump_certificate + if isinstance(cert_or_req, crypto.X509): + # pylint: disable=line-too-long + func = crypto.dump_certificate # type: Union[Callable[[int, crypto.X509Req], bytes], Callable[[int, crypto.X509], bytes]] else: - func = OpenSSL.crypto.dump_certificate_request - text = func(OpenSSL.crypto.FILETYPE_TEXT, cert_or_req).decode("utf-8") + func = crypto.dump_certificate_request + text = func(crypto.FILETYPE_TEXT, cert_or_req).decode("utf-8") # WARNING: this function does not support multiple SANs extensions. # Multiple X509v3 extensions of the same type is disallowed by RFC 5280. match = re.search(r"X509v3 Subject Alternative Name:(?: critical)?\s*(.*)", text) @@ -252,12 +265,12 @@ """ assert domains, "Must provide one or more hostnames for the cert." - cert = OpenSSL.crypto.X509() + cert = crypto.X509() cert.set_serial_number(int(binascii.hexlify(os.urandom(16)), 16)) cert.set_version(2) extensions = [ - OpenSSL.crypto.X509Extension( + crypto.X509Extension( b"basicConstraints", True, b"CA:TRUE, pathlen:0"), ] @@ -266,7 +279,7 @@ cert.set_issuer(cert.get_subject()) if force_san or len(domains) > 1: - extensions.append(OpenSSL.crypto.X509Extension( + extensions.append(crypto.X509Extension( b"subjectAltName", critical=False, value=b", ".join(b"DNS:" + d.encode() for d in domains) @@ -281,7 +294,7 @@ cert.sign(key, "sha256") return cert -def dump_pyopenssl_chain(chain, filetype=OpenSSL.crypto.FILETYPE_PEM): +def dump_pyopenssl_chain(chain, filetype=crypto.FILETYPE_PEM): """Dump certificate chain into a bundle. :param list chain: List of `OpenSSL.crypto.X509` (or wrapped in @@ -298,7 +311,7 @@ if isinstance(cert, jose.ComparableX509): # pylint: disable=protected-access cert = cert.wrapped - return OpenSSL.crypto.dump_certificate(filetype, cert) + return crypto.dump_certificate(filetype, cert) # assumes that OpenSSL.crypto.dump_certificate includes ending # newline character diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/crypto_util_test.py new/acme-0.25.1/acme/crypto_util_test.py --- old/acme-0.24.0/acme/crypto_util_test.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/crypto_util_test.py 2018-06-13 03:20:14.000000000 +0200 @@ -13,6 +13,7 @@ from acme import errors from acme import test_util +from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module class SSLSocketAndProbeSNITest(unittest.TestCase): @@ -165,7 +166,7 @@ def setUp(self): self.cert_count = 5 - self.serial_num = [] + self.serial_num = [] # type: List[int] self.key = OpenSSL.crypto.PKey() self.key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/magic_typing.py new/acme-0.25.1/acme/magic_typing.py --- old/acme-0.24.0/acme/magic_typing.py 1970-01-01 01:00:00.000000000 +0100 +++ new/acme-0.25.1/acme/magic_typing.py 2018-06-13 03:20:14.000000000 +0200 @@ -0,0 +1,16 @@ +"""Shim class to not have to depend on typing module in prod.""" +import sys + +class TypingClass(object): + """Ignore import errors by getting anything""" + def __getattr__(self, name): + return None + +try: + # mypy doesn't respect modifying sys.modules + from typing import * # pylint: disable=wildcard-import, unused-wildcard-import + # pylint: disable=unused-import + from typing import Collection, IO # type: ignore + # pylint: enable=unused-import +except ImportError: + sys.modules[__name__] = TypingClass() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/magic_typing_test.py new/acme-0.25.1/acme/magic_typing_test.py --- old/acme-0.24.0/acme/magic_typing_test.py 1970-01-01 01:00:00.000000000 +0100 +++ new/acme-0.25.1/acme/magic_typing_test.py 2018-06-13 03:20:14.000000000 +0200 @@ -0,0 +1,41 @@ +"""Tests for acme.magic_typing.""" +import sys +import unittest + +import mock + + +class MagicTypingTest(unittest.TestCase): + """Tests for acme.magic_typing.""" + def test_import_success(self): + try: + import typing as temp_typing + except ImportError: # pragma: no cover + temp_typing = None # pragma: no cover + typing_class_mock = mock.MagicMock() + text_mock = mock.MagicMock() + typing_class_mock.Text = text_mock + sys.modules['typing'] = typing_class_mock + if 'acme.magic_typing' in sys.modules: + del sys.modules['acme.magic_typing'] # pragma: no cover + from acme.magic_typing import Text # pylint: disable=no-name-in-module + self.assertEqual(Text, text_mock) + del sys.modules['acme.magic_typing'] + sys.modules['typing'] = temp_typing + + def test_import_failure(self): + try: + import typing as temp_typing + except ImportError: # pragma: no cover + temp_typing = None # pragma: no cover + sys.modules['typing'] = None + if 'acme.magic_typing' in sys.modules: + del sys.modules['acme.magic_typing'] # pragma: no cover + from acme.magic_typing import Text # pylint: disable=no-name-in-module + self.assertTrue(Text is None) + del sys.modules['acme.magic_typing'] + sys.modules['typing'] = temp_typing + + +if __name__ == '__main__': + unittest.main() # pragma: no cover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/messages.py new/acme-0.25.1/acme/messages.py --- old/acme-0.24.0/acme/messages.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/messages.py 2018-06-13 03:20:14.000000000 +0200 @@ -145,6 +145,7 @@ STATUS_VALID = Status('valid') STATUS_INVALID = Status('invalid') STATUS_REVOKED = Status('revoked') +STATUS_READY = Status('ready') class IdentifierType(_Constant): @@ -284,7 +285,7 @@ if phone is not None: details.append(cls.phone_prefix + phone) if email is not None: - details.append(cls.email_prefix + email) + details.extend([cls.email_prefix + mail for mail in email.split(',')]) kwargs['contact'] = tuple(details) return cls(**kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/messages_test.py new/acme-0.25.1/acme/messages_test.py --- old/acme-0.24.0/acme/messages_test.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/messages_test.py 2018-06-13 03:20:14.000000000 +0200 @@ -6,6 +6,7 @@ from acme import challenges from acme import test_util +from acme.magic_typing import Dict # pylint: disable=unused-import, no-name-in-module CERT = test_util.load_comparable_cert('cert.der') @@ -85,7 +86,7 @@ from acme.messages import _Constant class MockConstant(_Constant): # pylint: disable=missing-docstring - POSSIBLE_NAMES = {} + POSSIBLE_NAMES = {} # type: Dict self.MockConstant = MockConstant # pylint: disable=invalid-name self.const_a = MockConstant('a') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/standalone.py new/acme-0.25.1/acme/standalone.py --- old/acme-0.24.0/acme/standalone.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/standalone.py 2018-06-13 03:20:14.000000000 +0200 @@ -16,6 +16,7 @@ from acme import challenges from acme import crypto_util +from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module logger = logging.getLogger(__name__) @@ -66,8 +67,8 @@ def __init__(self, ServerClass, server_address, *remaining_args, **kwargs): port = server_address[1] - self.threads = [] - self.servers = [] + self.threads = [] # type: List[threading.Thread] + self.servers = [] # type: List[ACMEServerMixin] # Must try True first. # Ubuntu, for example, will fail to bind to IPv4 if we've already bound @@ -82,9 +83,22 @@ new_address = (server_address[0],) + (port,) + server_address[2:] new_args = (new_address,) + remaining_args server = ServerClass(*new_args, **kwargs) # pylint: disable=star-args - except socket.error: - logger.debug("Failed to bind to %s:%s using %s", new_address[0], + logger.debug( + "Successfully bound to %s:%s using %s", new_address[0], new_address[1], "IPv6" if ip_version else "IPv4") + except socket.error: + 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 " + + "IPv6 socket implementations.", + new_address[0], new_address[1], + "IPv6" if ip_version else "IPv4") + else: + logger.debug( + "Failed to bind to %s:%s using %s", new_address[0], + new_address[1], "IPv6" if ip_version else "IPv4") else: self.servers.append(server) # If two servers are set up and port 0 was passed in, ensure we always @@ -189,7 +203,7 @@ def __init__(self, *args, **kwargs): self.simple_http_resources = kwargs.pop("simple_http_resources", set()) - socketserver.BaseRequestHandler.__init__(self, *args, **kwargs) + BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kwargs) def log_message(self, format, *args): # pylint: disable=redefined-builtin """Log arbitrary message.""" @@ -262,7 +276,7 @@ certs = {} - _, hosts, _ = next(os.walk('.')) + _, hosts, _ = next(os.walk('.')) # type: ignore # https://github.com/python/mypy/issues/465 for host in hosts: with open(os.path.join(host, "cert.pem")) as cert_file: cert_contents = cert_file.read() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/standalone_test.py new/acme-0.25.1/acme/standalone_test.py --- old/acme-0.24.0/acme/standalone_test.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/standalone_test.py 2018-06-13 03:20:14.000000000 +0200 @@ -18,6 +18,7 @@ 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 class TLSServerTest(unittest.TestCase): @@ -72,7 +73,7 @@ def setUp(self): self.account_key = jose.JWK.load( test_util.load_vector('rsa1024_key.pem')) - self.resources = set() + self.resources = set() # type: Set from acme.standalone import HTTP01Server self.server = HTTP01Server(('', 0), resources=self.resources) @@ -201,7 +202,7 @@ def setUp(self): self.account_key = jose.JWK.load( test_util.load_vector('rsa1024_key.pem')) - self.resources = set() + self.resources = set() # type: Set from acme.standalone import HTTP01DualNetworkedServers self.servers = HTTP01DualNetworkedServers(('', 0), resources=self.resources) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme/test_util.py new/acme-0.25.1/acme/test_util.py --- old/acme-0.24.0/acme/test_util.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/acme/test_util.py 2018-06-13 03:20:14.000000000 +0200 @@ -10,7 +10,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization import josepy as jose -import OpenSSL +from OpenSSL import crypto def vector_path(*names): @@ -39,8 +39,8 @@ def load_cert(*names): """Load certificate.""" loader = _guess_loader( - names[-1], OpenSSL.crypto.FILETYPE_PEM, OpenSSL.crypto.FILETYPE_ASN1) - return OpenSSL.crypto.load_certificate(loader, load_vector(*names)) + names[-1], crypto.FILETYPE_PEM, crypto.FILETYPE_ASN1) + return crypto.load_certificate(loader, load_vector(*names)) def load_comparable_cert(*names): @@ -51,8 +51,8 @@ def load_csr(*names): """Load certificate request.""" loader = _guess_loader( - names[-1], OpenSSL.crypto.FILETYPE_PEM, OpenSSL.crypto.FILETYPE_ASN1) - return OpenSSL.crypto.load_certificate_request(loader, load_vector(*names)) + names[-1], crypto.FILETYPE_PEM, crypto.FILETYPE_ASN1) + return crypto.load_certificate_request(loader, load_vector(*names)) def load_comparable_csr(*names): @@ -71,8 +71,8 @@ def load_pyopenssl_private_key(*names): """Load pyOpenSSL private key.""" loader = _guess_loader( - names[-1], OpenSSL.crypto.FILETYPE_PEM, OpenSSL.crypto.FILETYPE_ASN1) - return OpenSSL.crypto.load_privatekey(loader, load_vector(*names)) + names[-1], crypto.FILETYPE_PEM, crypto.FILETYPE_ASN1) + return crypto.load_privatekey(loader, load_vector(*names)) def skip_unless(condition, reason): # pragma: no cover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme.egg-info/PKG-INFO new/acme-0.25.1/acme.egg-info/PKG-INFO --- old/acme-0.24.0/acme.egg-info/PKG-INFO 2018-05-02 01:50:51.000000000 +0200 +++ new/acme-0.25.1/acme.egg-info/PKG-INFO 2018-06-13 03:20:35.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: acme -Version: 0.24.0 +Version: 0.25.1 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.24.0/acme.egg-info/SOURCES.txt new/acme-0.25.1/acme.egg-info/SOURCES.txt --- old/acme-0.24.0/acme.egg-info/SOURCES.txt 2018-05-02 01:50:51.000000000 +0200 +++ new/acme-0.25.1/acme.egg-info/SOURCES.txt 2018-06-13 03:20:35.000000000 +0200 @@ -1,6 +1,7 @@ LICENSE.txt MANIFEST.in README.rst +pytest.ini setup.cfg setup.py acme/__init__.py @@ -16,6 +17,8 @@ acme/fields_test.py acme/jws.py acme/jws_test.py +acme/magic_typing.py +acme/magic_typing_test.py acme/messages.py acme/messages_test.py acme/standalone.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/acme.egg-info/requires.txt new/acme-0.25.1/acme.egg-info/requires.txt --- old/acme-0.24.0/acme.egg-info/requires.txt 2018-05-02 01:50:51.000000000 +0200 +++ new/acme-0.25.1/acme.egg-info/requires.txt 2018-06-13 03:20:35.000000000 +0200 @@ -5,6 +5,7 @@ pyrfc3339 pytz requests[security]>=2.4.1 +requests-toolbelt>=0.3.0 setuptools six>=1.9.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/pytest.ini new/acme-0.25.1/pytest.ini --- old/acme-0.24.0/pytest.ini 1970-01-01 01:00:00.000000000 +0100 +++ new/acme-0.25.1/pytest.ini 2018-06-13 03:20:14.000000000 +0200 @@ -0,0 +1,2 @@ +[pytest] +norecursedirs = .* build dist CVS _darcs {arch} *.egg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/acme-0.24.0/setup.py new/acme-0.25.1/setup.py --- old/acme-0.24.0/setup.py 2018-05-02 01:50:33.000000000 +0200 +++ new/acme-0.25.1/setup.py 2018-06-13 03:20:15.000000000 +0200 @@ -1,10 +1,9 @@ -import sys - from setuptools import setup from setuptools import find_packages +from setuptools.command.test import test as TestCommand +import sys - -version = '0.24.0' +version = '0.25.1' # Please update tox.ini when modifying dependency version requirements install_requires = [ @@ -19,6 +18,7 @@ 'pyrfc3339', 'pytz', 'requests[security]>=2.4.1', # security extras added in 2.4.1 + 'requests-toolbelt>=0.3.0', 'setuptools', 'six>=1.9.0', # needed for python_2_unicode_compatible ] @@ -34,6 +34,19 @@ 'sphinx_rtd_theme', ] +class PyTest(TestCommand): + user_options = [] + + def initialize_options(self): + TestCommand.initialize_options(self) + self.pytest_args = '' + + def run_tests(self): + import shlex + # import here, cause outside the eggs aren't loaded + import pytest + errno = pytest.main(shlex.split(self.pytest_args)) + sys.exit(errno) setup( name='acme', @@ -66,5 +79,7 @@ 'dev': dev_extras, 'docs': docs_extras, }, + tests_require=["pytest"], test_suite='acme', + cmdclass={"test": PyTest}, )