From 2622a700e0a83e0de0994c970929b624b98dad40 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 2 Apr 2021 16:19:30 -0700 Subject: [PATCH 01/21] Update a few type ignore comments (#8767) Some are no longer needed and other's comments are out of date. For the changes to the acme nonce errors, `Exception` doesn't take kwargs. The error message about this our own classes isn't super helpful: ``` In [2]: BadNonce('nonce', 'error', foo='bar') --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in ----> 1 BadNonce('nonce', 'error', foo='bar') TypeError: __init__() got an unexpected keyword argument 'foo' ``` but if you try this on `Exception` which these classes inherit from, you get: ``` In [4]: Exception(foo='bar') --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in ----> 1 Exception(foo='bar') TypeError: Exception() takes no keyword arguments ``` See https://github.com/python/typeshed/pull/2348 for more info. * remove outdated ignores * update locking ignore comment * don't accept kwargs --- acme/acme/errors.py | 14 ++++---------- certbot/certbot/_internal/lock.py | 14 ++++++-------- certbot/certbot/crypto_util.py | 3 +-- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/acme/acme/errors.py b/acme/acme/errors.py index 5ca5a4fa2..84b7704dc 100644 --- a/acme/acme/errors.py +++ b/acme/acme/errors.py @@ -28,13 +28,8 @@ class NonceError(ClientError): class BadNonce(NonceError): """Bad nonce error.""" - def __init__(self, nonce, error, *args, **kwargs): - # MyPy complains here that there is too many arguments for BaseException constructor. - # This is an error fixed in typeshed, see https://github.com/python/mypy/issues/4183 - # The fix is included in MyPy>=0.740, but upgrading it would bring dozen of errors due to - # new types definitions. So we ignore the error until the code base is fixed to match - # with MyPy>=0.740 referential. - super(BadNonce, self).__init__(*args, **kwargs) # type: ignore + def __init__(self, nonce, error, *args): + super(BadNonce, self).__init__(*args) self.nonce = nonce self.error = error @@ -52,9 +47,8 @@ class MissingNonce(NonceError): :ivar requests.Response ~.response: HTTP Response """ - def __init__(self, response, *args, **kwargs): - # See comment in BadNonce constructor above for an explanation of type: ignore here. - super(MissingNonce, self).__init__(*args, **kwargs) # type: ignore + def __init__(self, response, *args): + super(MissingNonce, self).__init__(*args) self.response = response def __str__(self): diff --git a/certbot/certbot/_internal/lock.py b/certbot/certbot/_internal/lock.py index d00302598..d0b66e5e2 100644 --- a/certbot/certbot/_internal/lock.py +++ b/certbot/certbot/_internal/lock.py @@ -205,10 +205,9 @@ class _WindowsLockMechanism(_BaseLockMechanism): # Under Windows, filesystem.open will raise directly an EACCES error # if the lock file is already locked. fd = filesystem.open(self._path, open_mode, 0o600) - # The need for this "type: ignore" was fixed in - # https://github.com/python/typeshed/pull/3607 and included in - # newer versions of mypy so it can be removed when mypy is - # upgraded. + # This "type: ignore" is currently needed because msvcrt methods + # are only defined on Windows. See + # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) # type: ignore except (IOError, OSError) as err: if fd: @@ -224,10 +223,9 @@ class _WindowsLockMechanism(_BaseLockMechanism): def release(self): """Release the lock.""" try: - # The need for this "type: ignore" was fixed in - # https://github.com/python/typeshed/pull/3607 and included in - # newer versions of mypy so it can be removed when mypy is - # upgraded. + # This "type: ignore" is currently needed because msvcrt methods + # are only defined on Windows. See + # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1) # type: ignore os.close(self._fd) diff --git a/certbot/certbot/crypto_util.py b/certbot/certbot/crypto_util.py index 445618ea0..5592722dd 100644 --- a/certbot/certbot/crypto_util.py +++ b/certbot/certbot/crypto_util.py @@ -301,8 +301,7 @@ def verify_signed_payload(public_key, signature, payload, signature_hash_algorit with warnings.catch_warnings(): warnings.simplefilter("ignore") if isinstance(public_key, RSAPublicKey): - # https://github.com/python/typeshed/blob/master/third_party/2/cryptography/hazmat/primitives/asymmetric/rsa.pyi - verifier = public_key.verifier( # type: ignore + verifier = public_key.verifier( signature, PKCS1v15(), signature_hash_algorithm ) verifier.update(payload) From 69479b72771fceabc3caa93152c8b2e1a7d1ae6b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 5 Apr 2021 10:42:18 -0700 Subject: [PATCH 02/21] use standard errno (#8768) We were originally using `socket.errno` with a `type: ignore` and a comment suggesting that this attribute needs to be included in the typeshed. This is incorrect. While it's true that [socket imports errno](https://github.com/python/cpython/blob/43682f1e39a3c61f0e8a638b887bcdcbfef766c5/Lib/socket.py#L58), it's not intended to be part of its API. https://docs.python.org/3/library/socket.html has no mention of it. Instead, we should be using the standard `errno` module and remove this `type: ignore`. --- .../certbot/_internal/plugins/standalone.py | 7 +++--- certbot/tests/plugins/standalone_test.py | 23 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/certbot/certbot/_internal/plugins/standalone.py b/certbot/certbot/_internal/plugins/standalone.py index 833651346..c75ba36a9 100644 --- a/certbot/certbot/_internal/plugins/standalone.py +++ b/certbot/certbot/_internal/plugins/standalone.py @@ -1,9 +1,8 @@ """Standalone Authenticator.""" import collections +import errno import logging import socket -# https://github.com/python/typeshed/blob/master/stdlib/2and3/socket.pyi -from socket import errno as socket_errors # type: ignore from typing import DefaultDict from typing import Dict from typing import Set @@ -187,13 +186,13 @@ class Authenticator(common.Plugin): def _handle_perform_error(error): - if error.socket_error.errno == socket_errors.EACCES: + if error.socket_error.errno == errno.EACCES: raise errors.PluginError( "Could not bind TCP port {0} because you don't have " "the appropriate permissions (for example, you " "aren't running this program as " "root).".format(error.port)) - if error.socket_error.errno == socket_errors.EADDRINUSE: + if error.socket_error.errno == errno.EADDRINUSE: display = zope.component.getUtility(interfaces.IDisplay) msg = ( "Could not bind TCP port {0} because it is already in " diff --git a/certbot/tests/plugins/standalone_test.py b/certbot/tests/plugins/standalone_test.py index 636b251de..5b3fffd9d 100644 --- a/certbot/tests/plugins/standalone_test.py +++ b/certbot/tests/plugins/standalone_test.py @@ -1,7 +1,6 @@ """Tests for certbot._internal.plugins.standalone.""" -# https://github.com/python/typeshed/blob/master/stdlib/2and3/socket.pyi +import errno import socket -from socket import errno as socket_errors # type: ignore import unittest from typing import Dict, Set, Tuple @@ -106,8 +105,8 @@ class AuthenticatorTest(unittest.TestCase): @test_util.patch_get_utility() def test_perform_eaddrinuse_retry(self, mock_get_utility): mock_utility = mock_get_utility() - errno = socket_errors.EADDRINUSE - error = errors.StandaloneBindError(mock.MagicMock(errno=errno), -1) + encountered_errno = errno.EADDRINUSE + error = errors.StandaloneBindError(mock.MagicMock(errno=encountered_errno), -1) self.auth.servers.run.side_effect = [error] + 2 * [mock.MagicMock()] mock_yesno = mock_utility.yesno mock_yesno.return_value = True @@ -121,8 +120,8 @@ class AuthenticatorTest(unittest.TestCase): mock_yesno = mock_utility.yesno mock_yesno.return_value = False - errno = socket_errors.EADDRINUSE - self.assertRaises(errors.PluginError, self._fail_perform, errno) + encountered_errno = errno.EADDRINUSE + self.assertRaises(errors.PluginError, self._fail_perform, encountered_errno) self._assert_correct_yesno_call(mock_yesno) def _assert_correct_yesno_call(self, mock_yesno): @@ -131,16 +130,16 @@ class AuthenticatorTest(unittest.TestCase): self.assertFalse(yesno_kwargs.get("default", True)) def test_perform_eacces(self): - errno = socket_errors.EACCES - self.assertRaises(errors.PluginError, self._fail_perform, errno) + encountered_errno = errno.EACCES + self.assertRaises(errors.PluginError, self._fail_perform, encountered_errno) def test_perform_unexpected_socket_error(self): - errno = socket_errors.ENOTCONN + encountered_errno = errno.ENOTCONN self.assertRaises( - errors.StandaloneBindError, self._fail_perform, errno) + errors.StandaloneBindError, self._fail_perform, encountered_errno) - def _fail_perform(self, errno): - error = errors.StandaloneBindError(mock.MagicMock(errno=errno), -1) + def _fail_perform(self, encountered_errno): + error = errors.StandaloneBindError(mock.MagicMock(errno=encountered_errno), -1) self.auth.servers.run.side_effect = error self.auth.perform(self._get_achalls()) From 33f177b361bfa5938da0c726dc3ee7582faf878e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 5 Apr 2021 11:15:09 -0700 Subject: [PATCH 03/21] Upgrade Python to 3.8.9. (#8775) Over the weekend, Python released new versions of Python 3.8 and Python 3.9 partially in response to the OpenSSL CVEs discussed at https://github.com/certbot/certbot/pull/8741#issuecomment-809644789. You can see this mentioned in their changelog at https://docs.python.org/release/3.8.9/whatsnew/changelog.html#build. This PR updates the windows installer to use that new release so all of our distribution methods that contain their own copy of OpenSSL are patched for the release tomorrow. You can see tests passing with this change at https://dev.azure.com/certbot/certbot/_build/results?buildId=3751&view=results. You can see Python 3.8.9 being downloaded instead of an older version at https://dev.azure.com/certbot/certbot/_build/results?buildId=3751&view=logs&j=ad29f110-3cce-5317-4ef2-0a692ae1dee7&t=901eeead-396c-5477-aba2-f402fdcfb885&l=1055. --- windows-installer/windows_installer/construct.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows-installer/windows_installer/construct.py b/windows-installer/windows_installer/construct.py index 983923049..91df6b714 100644 --- a/windows-installer/windows_installer/construct.py +++ b/windows-installer/windows_installer/construct.py @@ -7,7 +7,7 @@ import subprocess import sys import time -PYTHON_VERSION = (3, 8, 8) +PYTHON_VERSION = (3, 8, 9) PYTHON_BITNESS = 32 NSIS_VERSION = '3.06.1' From 0f9f902b6eb32bab609922cdcc78649d78c7b7c0 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Mon, 5 Apr 2021 20:53:57 +0200 Subject: [PATCH 04/21] Use typing-extensions to ensure certbot dev environment is compatible with Python 3.6/3.7 (#8776) Fixes #8773 I took option 2 from the issue mentionned above (importing `typing-extensions` on dev dependencies) to avoid modifying certbot runtime requirements given that what needs to be added is useful for mypy only. I did not change the Python version used to execute the linting and mypy on the standard tests, given that the tox `docker_dev` target already checks if the development environment is working for Python < 3.8. --- certbot/certbot/plugins/dns_test_common.py | 2 +- certbot/certbot/plugins/dns_test_common_lexicon.py | 2 +- certbot/setup.py | 3 +++ tools/requirements.txt | 12 ++++++------ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/certbot/certbot/plugins/dns_test_common.py b/certbot/certbot/plugins/dns_test_common.py index f6d7bdca8..7a8df9329 100644 --- a/certbot/certbot/plugins/dns_test_common.py +++ b/certbot/certbot/plugins/dns_test_common.py @@ -12,7 +12,7 @@ from certbot.tests import acme_util from certbot.tests import util as test_util if typing.TYPE_CHECKING: - from typing import Protocol + from typing_extensions import Protocol else: Protocol = object # type: ignore diff --git a/certbot/certbot/plugins/dns_test_common_lexicon.py b/certbot/certbot/plugins/dns_test_common_lexicon.py index 48261d395..5c6f09d20 100644 --- a/certbot/certbot/plugins/dns_test_common_lexicon.py +++ b/certbot/certbot/plugins/dns_test_common_lexicon.py @@ -18,7 +18,7 @@ try: except ImportError: # pragma: no cover from unittest import mock # type: ignore if typing.TYPE_CHECKING: - from typing import Protocol + from typing_extensions import Protocol else: Protocol = object # type: ignore diff --git a/certbot/setup.py b/certbot/setup.py index 8843a35a2..6913d8384 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -77,6 +77,9 @@ dev_extras = [ 'pytest', 'pytest-cov', 'pytest-xdist', + # typing-extensions is required to import typing.Protocol and make the mypy checks + # pass (along with pylint about non-existent objects) on Python 3.6 & 3.7 + 'typing-extensions', 'tox', 'twine', 'wheel', diff --git a/tools/requirements.txt b/tools/requirements.txt index 707cc64b9..e5a6d3be7 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -18,8 +18,8 @@ backcall==0.2.0 bcrypt==3.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" beautifulsoup4==4.9.3; python_version >= "3.6" and python_version < "4.0" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -boto3==1.17.42; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -botocore==1.20.42; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +boto3==1.17.44; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +botocore==1.20.44; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" cachecontrol==0.12.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" cached-property==1.5.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") @@ -36,7 +36,7 @@ configobj==5.0.6; python_version >= "3.6" coverage==4.5.4; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0" and python_version < "4") crashtest==0.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") cryptography==3.4.7; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" or python_full_version >= "3.5.0" and python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" -decorator==4.4.2; python_version == "3.6" and python_full_version < "3.0.0" or python_version == "3.6" and python_full_version >= "3.2.0" +decorator==5.0.5 deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" distlib==0.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" distro==1.5.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" @@ -99,7 +99,7 @@ ply==3.11; python_version >= "3.6" poetry-core==1.0.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" poetry==1.1.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" prompt-toolkit==3.0.3 -protobuf==3.15.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +protobuf==3.15.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" ptyprocess==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" @@ -124,7 +124,7 @@ pytest==3.2.5 python-augeas==0.5.0 python-dateutil==2.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" python-digitalocean==1.16.0; python_version >= "3.6" -python-dotenv==0.16.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +python-dotenv==0.17.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" pytz==2021.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.6.0" pywin32-ctypes==0.2.0; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "win32" pywin32==300; sys_platform == "win32" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") @@ -144,7 +144,7 @@ shellingham==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or six==1.15.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" snowballstemmer==2.1.0; python_version >= "3.6" soupsieve==2.2.1; python_version >= "3.6" -sphinx-rtd-theme==0.5.1; python_version >= "3.6" +sphinx-rtd-theme==0.5.2; python_version >= "3.6" sphinx==3.5.3; python_version >= "3.6" sphinxcontrib-applehelp==1.0.2; python_version >= "3.6" sphinxcontrib-devhelp==1.0.2; python_version >= "3.6" From c438a397a01659912060e2e4606cb9262f40d29d Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Tue, 6 Apr 2021 00:04:21 +0200 Subject: [PATCH 05/21] Enable mypy strict mode (#8766) Built on top of #8748, this PR reenables mypy strict mode and adds the appropriate corrections to pass the types checks. * Upgrade mypy * First step for acme * Cast for the rescue * Fixing types for certbot * Fix typing for certbot-nginx * Finalize type fixes, configure no optional strict check for mypy in tox * Align requirements * Isort * Pylint * Protocol for python 3.6 * Use Python 3.9 for mypy, make code compatible with Python 3.8< * Pylint and mypy * Pragma no cover * Pythonic NotImplemented constant * More type definitions * Add comments * Simplify typing logic * Use vararg tuple * Relax constraints on mypy * Add more type * Do not silence error if target is not defined * Conditionally import Protocol for type checking only * Clean up imports * Add comments * Align python version linting with mypy and coverage * Just ignore types in an unused module * Add comments * Fix lint * Work in progress * Finish type control * Isort * Fix pylint * Fix imports * Fix cli subparser * Some fixes * Coverage * Remove --no-strict-optional (obviously...) * Update certbot-apache/certbot_apache/_internal/configurator.py Co-authored-by: Brad Warren * Update certbot/certbot/_internal/display/completer.py Co-authored-by: Brad Warren * Cleanup dns_google * Improve lock controls and fix subparser * Use the expected interfaces * Fix code Co-authored-by: Brad Warren --- .../certbot_apache/_internal/configurator.py | 20 ++++++--- .../_internal/override_centos.py | 5 ++- .../certbot_apache/_internal/parser.py | 44 ++++++++++--------- certbot-apache/tests/parser_test.py | 2 +- .../rfc2136_tests/context.py | 2 - .../utils/dns_server.py | 6 ++- .../configurators/common.py | 6 ++- .../_internal/dns_cloudflare.py | 6 ++- .../_internal/dns_cloudxns.py | 6 ++- .../_internal/dns_digitalocean.py | 6 ++- .../_internal/dns_dnsimple.py | 6 ++- .../_internal/dns_dnsmadeeasy.py | 6 ++- .../_internal/dns_gehirn.py | 7 ++- .../_internal/dns_google.py | 4 -- .../_internal/dns_linode.py | 6 ++- .../_internal/dns_luadns.py | 6 ++- .../certbot_dns_nsone/_internal/dns_nsone.py | 6 ++- .../certbot_dns_ovh/_internal/dns_ovh.py | 6 ++- .../_internal/dns_rfc2136.py | 6 ++- .../_internal/dns_sakuracloud.py | 7 ++- .../certbot_nginx/_internal/configurator.py | 2 +- certbot/certbot/_internal/cli/subparsers.py | 3 +- certbot/certbot/_internal/client.py | 4 ++ .../certbot/_internal/display/completer.py | 7 ++- certbot/certbot/_internal/lock.py | 2 + certbot/certbot/_internal/plugins/disco.py | 36 +++++++++------ certbot/certbot/interfaces.py | 3 +- certbot/certbot/plugins/dns_common.py | 3 +- certbot/certbot/plugins/dns_common_lexicon.py | 4 +- certbot/certbot/plugins/storage.py | 4 +- certbot/tests/plugins/storage_test.py | 5 ++- tox.ini | 2 +- 32 files changed, 164 insertions(+), 74 deletions(-) diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index c24a646db..28f73b32d 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -12,6 +12,7 @@ from typing import cast from typing import DefaultDict from typing import Dict from typing import List +from typing import Optional from typing import Set from typing import Union @@ -36,6 +37,9 @@ from certbot_apache._internal import dualparser from certbot_apache._internal import http_01 from certbot_apache._internal import obj from certbot_apache._internal import parser +from certbot_apache._internal.dualparser import DualBlockNode +from certbot_apache._internal.obj import VirtualHost +from certbot_apache._internal.parser import ApacheParser try: import apacheconfig @@ -232,11 +236,11 @@ class ApacheConfigurator(common.Installer): self.parsed_paths: List[str] = [] # These will be set in the prepare function self._prepared = False - self.parser = None - self.parser_root = None + self.parser: ApacheParser + self.parser_root: Optional[DualBlockNode] = None self.version = version self._openssl_version = openssl_version - self.vhosts = None + self.vhosts: List[VirtualHost] self.options = copy.deepcopy(self.OS_DEFAULTS) self._enhance_func = {"redirect": self._enable_redirect, "ensure-http-header": self._set_http_header, @@ -345,8 +349,9 @@ class ApacheConfigurator(common.Installer): "augeaspath": self.parser.get_root_augpath(), "ac_ast": None} if self.USE_PARSERNODE: - self.parser_root = self.get_parsernode_root(pn_meta) - self.parsed_paths = self.parser_root.parsed_paths() + parser_root = self.get_parsernode_root(pn_meta) + self.parser_root = parser_root + self.parsed_paths = parser_root.parsed_paths() # Check for errors in parsing files with Augeas self.parser.check_parsing_errors("httpd.aug") @@ -408,7 +413,7 @@ class ApacheConfigurator(common.Installer): super(ApacheConfigurator, self).recovery_routine() # Reload configuration after these changes take effect if needed # ie. ApacheParser has been initialized. - if self.parser: + if hasattr(self, "parser"): # TODO: wrap into non-implementation specific parser interface self.parser.aug.load() @@ -1051,6 +1056,9 @@ class ApacheConfigurator(common.Installer): :rtype: list """ + if not self.parser_root: + raise errors.Error("This ApacheConfigurator instance is not" # pragma: no cover + " configured to use a node parser.") vhs = [] vhosts = self.parser_root.find_blocks("VirtualHost", exclude=False) for vhblock in vhosts: diff --git a/certbot-apache/certbot_apache/_internal/override_centos.py b/certbot-apache/certbot_apache/_internal/override_centos.py index fc77aaafc..bd9a47b52 100644 --- a/certbot-apache/certbot_apache/_internal/override_centos.py +++ b/certbot-apache/certbot_apache/_internal/override_centos.py @@ -119,8 +119,9 @@ class CentOSConfigurator(configurator.ApacheConfigurator): else: loadmod_args = path_args - if self.parser.not_modssl_ifmodule(noarg_path): # pylint: disable=no-member - if self.parser.loc["default"] in noarg_path: + centos_parser: CentOSParser = cast(CentOSParser, self.parser) + if centos_parser.not_modssl_ifmodule(noarg_path): + if centos_parser.loc["default"] in noarg_path: # LoadModule already in the main configuration file if ("ifmodule/" in noarg_path.lower() or "ifmodule[1]" in noarg_path.lower()): diff --git a/certbot-apache/certbot_apache/_internal/parser.py b/certbot-apache/certbot_apache/_internal/parser.py index 1a6af4c4b..ff7e90f3b 100644 --- a/certbot-apache/certbot_apache/_internal/parser.py +++ b/certbot-apache/certbot_apache/_internal/parser.py @@ -5,12 +5,18 @@ import logging import re from typing import Dict from typing import List +from typing import Optional from certbot import errors from certbot.compat import os from certbot_apache._internal import apache_util from certbot_apache._internal import constants +try: + from augeas import Augeas +except ImportError: # pragma: no cover + Augeas = None # type: ignore + logger = logging.getLogger(__name__) @@ -39,8 +45,7 @@ class ApacheParser: self.configurator = configurator # Initialize augeas - self.aug = None - self.init_augeas() + self.aug = init_augeas() if not self.check_aug_version(): raise errors.NotSupportedError( @@ -48,7 +53,7 @@ class ApacheParser: "version 1.2.0 or higher, please make sure you have you have " "those installed.") - self.modules: Dict[str, str] = {} + self.modules: Dict[str, Optional[str]] = {} self.parser_paths: Dict[str, List[str]] = {} self.variables: Dict[str, str] = {} @@ -83,23 +88,6 @@ class ApacheParser: if self.find_dir("Define", exclude=False): raise errors.PluginError("Error parsing runtime variables") - def init_augeas(self): - """ Initialize the actual Augeas instance """ - - try: - import augeas - except ImportError: # pragma: no cover - raise errors.NoInstallationError("Problem in Augeas installation") - - self.aug = augeas.Augeas( - # specify a directory to load our preferred lens from - loadpath=constants.AUGEAS_LENS_DIR, - # Do not save backup (we do it ourselves), do not load - # anything by default - flags=(augeas.Augeas.NONE | - augeas.Augeas.NO_MODL_AUTOLOAD | - augeas.Augeas.ENABLE_SPAN)) - def check_parsing_errors(self, lens): """Verify Augeas can parse all of the lens files. @@ -949,3 +937,19 @@ def get_aug_path(file_path): """ return "/files%s" % file_path + + +def init_augeas() -> Augeas: + """ Initialize the actual Augeas instance """ + + if not Augeas: # pragma: no cover + raise errors.NoInstallationError("Problem in Augeas installation") + + return Augeas( + # specify a directory to load our preferred lens from + loadpath=constants.AUGEAS_LENS_DIR, + # Do not save backup (we do it ourselves), do not load + # anything by default + flags=(Augeas.NONE | + Augeas.NO_MODL_AUTOLOAD | + Augeas.ENABLE_SPAN)) diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py index 7aedec31d..2eff9a9dd 100644 --- a/certbot-apache/tests/parser_test.py +++ b/certbot-apache/tests/parser_test.py @@ -339,7 +339,7 @@ class ParserInitTest(util.ApacheTest): shutil.rmtree(self.config_dir) shutil.rmtree(self.work_dir) - @mock.patch("certbot_apache._internal.parser.ApacheParser.init_augeas") + @mock.patch("certbot_apache._internal.parser.init_augeas") def test_prepare_no_augeas(self, mock_init_augeas): from certbot_apache._internal.parser import ApacheParser mock_init_augeas.side_effect = errors.NoInstallationError diff --git a/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py b/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py index 8df89f473..a4f62b5e4 100644 --- a/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py +++ b/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py @@ -17,7 +17,6 @@ class IntegrationTestsContext(certbot_context.IntegrationTestsContext): self.request = request - self._dns_xdist = None if hasattr(request.config, 'workerinput'): # Worker node self._dns_xdist = request.config.workerinput['dns_xdist'] else: # Primary node @@ -45,7 +44,6 @@ class IntegrationTestsContext(certbot_context.IntegrationTestsContext): src_file = resource_filename('certbot_integration_tests', 'assets/bind-config/rfc2136-credentials-{}.ini.tpl' .format(label)) - contents = None with open(src_file, 'r') as f: contents = f.read().format( diff --git a/certbot-ci/certbot_integration_tests/utils/dns_server.py b/certbot-ci/certbot_integration_tests/utils/dns_server.py index 31e7aee18..48f5a533e 100644 --- a/certbot-ci/certbot_integration_tests/utils/dns_server.py +++ b/certbot-ci/certbot_integration_tests/utils/dns_server.py @@ -8,6 +8,7 @@ import subprocess import sys import tempfile import time +from typing import Optional from pkg_resources import resource_filename @@ -38,7 +39,7 @@ class DNSServer: self.bind_root = tempfile.mkdtemp() - self.process: subprocess.Popen = None + self.process: Optional[subprocess.Popen] = None self.dns_xdist = {"address": BIND_BIND_ADDRESS[0], "port": BIND_BIND_ADDRESS[1]} @@ -119,6 +120,9 @@ class DNSServer: but otherwise the contents are ignored. :param int attempts: The number of attempts to make. """ + if not self.process: + raise ValueError("DNS server has not been started. Please run start() first.") + for _ in range(attempts): if self.process.poll(): raise ValueError("BIND9 server stopped unexpectedly") diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py index bf768f8f8..bf26291ea 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py @@ -33,7 +33,9 @@ class Proxy: self.args = args self.http_port = 80 self.https_port = 443 - self._configurator = self._all_names = self._test_names = None + self._configurator = None + self._all_names = None + self._test_names = None def __getattr__(self, name): """Wraps the configurator methods""" @@ -93,5 +95,7 @@ class Proxy: """Installs cert""" cert_path, key_path, chain_path = self.copy_certs_and_keys( cert_path, key_path, chain_path) + if not self._configurator: + raise ValueError("Configurator plugin is not set.") self._configurator.deploy_cert( domain, cert_path, key_path, chain_path, fullchain_path) diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py index 034d7bbb2..ceee39f86 100644 --- a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py +++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py @@ -3,6 +3,7 @@ import logging from typing import Any from typing import Dict from typing import List +from typing import Optional import CloudFlare import zope.interface @@ -10,6 +11,7 @@ import zope.interface from certbot import errors from certbot import interfaces from certbot.plugins import dns_common +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -30,7 +32,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -79,6 +81,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_cloudflare_client().del_txt_record(domain, validation_name, validation) def _get_cloudflare_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") if self.credentials.conf('api-token'): return _CloudflareClient(None, self.credentials.conf('api-token')) return _CloudflareClient(self.credentials.conf('email'), self.credentials.conf('api-key')) diff --git a/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py b/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py index 654c04c70..7fe52b618 100644 --- a/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py +++ b/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py @@ -1,5 +1,6 @@ """DNS Authenticator for CloudXNS DNS.""" import logging +from typing import Optional from lexicon.providers import cloudxns import zope.interface @@ -8,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +29,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -56,6 +58,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_cloudxns_client().del_txt_record(domain, validation_name, validation) def _get_cloudxns_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _CloudXNSLexiconClient(self.credentials.conf('api-key'), self.credentials.conf('secret-key'), self.ttl) diff --git a/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py b/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py index cb5012fb7..85eb1159e 100644 --- a/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py +++ b/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py @@ -1,5 +1,6 @@ """DNS Authenticator for DigitalOcean.""" import logging +from typing import Optional import digitalocean import zope.interface @@ -7,6 +8,7 @@ import zope.interface from certbot import errors from certbot import interfaces from certbot.plugins import dns_common +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -25,7 +27,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -53,6 +55,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_digitalocean_client().del_txt_record(domain, validation_name, validation) def _get_digitalocean_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _DigitalOceanClient(self.credentials.conf('token')) diff --git a/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py b/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py index 9f7f100d7..318bc25fb 100644 --- a/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py +++ b/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py @@ -1,5 +1,6 @@ """DNS Authenticator for DNSimple DNS.""" import logging +from typing import Optional from lexicon.providers import dnsimple import zope.interface @@ -8,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +29,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -54,6 +56,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_dnsimple_client().del_txt_record(domain, validation_name, validation) def _get_dnsimple_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _DNSimpleLexiconClient(self.credentials.conf('token'), self.ttl) diff --git a/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py b/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py index 4a1fcffc3..3a805f507 100644 --- a/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py +++ b/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py @@ -1,5 +1,6 @@ """DNS Authenticator for DNS Made Easy DNS.""" import logging +from typing import Optional from lexicon.providers import dnsmadeeasy import zope.interface @@ -8,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -28,7 +30,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -58,6 +60,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_dnsmadeeasy_client().del_txt_record(domain, validation_name, validation) def _get_dnsmadeeasy_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _DNSMadeEasyLexiconClient(self.credentials.conf('api-key'), self.credentials.conf('secret-key'), self.ttl) diff --git a/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py b/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py index 39deddae5..dd9665c2f 100644 --- a/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py +++ b/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py @@ -1,12 +1,15 @@ """DNS Authenticator for Gehirn Infrastructure Service DNS.""" import logging +from typing import Optional from lexicon.providers import gehirn import zope.interface +from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +30,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -57,6 +60,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_gehirn_client().del_txt_record(domain, validation_name, validation) def _get_gehirn_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _GehirnLexiconClient( self.credentials.conf('api-token'), self.credentials.conf('api-secret'), diff --git a/certbot-dns-google/certbot_dns_google/_internal/dns_google.py b/certbot-dns-google/certbot_dns_google/_internal/dns_google.py index 363c5e079..39f26c7d0 100644 --- a/certbot-dns-google/certbot_dns_google/_internal/dns_google.py +++ b/certbot-dns-google/certbot_dns_google/_internal/dns_google.py @@ -32,10 +32,6 @@ class Authenticator(dns_common.DNSAuthenticator): 'for DNS).') ttl = 60 - def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None - @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=60) diff --git a/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py b/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py index c1b5e066f..c9e6a42b5 100644 --- a/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py +++ b/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py @@ -1,6 +1,7 @@ """DNS Authenticator for Linode.""" import logging import re +from typing import Optional from lexicon.providers import linode from lexicon.providers import linode4 @@ -10,6 +11,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -28,7 +30,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -56,6 +58,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_linode_client().del_txt_record(domain, validation_name, validation) def _get_linode_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") api_key = self.credentials.conf('key') api_version = self.credentials.conf('version') if api_version == '': diff --git a/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py b/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py index d5b499c72..6595c3165 100644 --- a/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py +++ b/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py @@ -1,5 +1,6 @@ """DNS Authenticator for LuaDNS DNS.""" import logging +from typing import Optional from lexicon.providers import luadns import zope.interface @@ -8,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +29,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -55,6 +57,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_luadns_client().del_txt_record(domain, validation_name, validation) def _get_luadns_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _LuaDNSLexiconClient(self.credentials.conf('email'), self.credentials.conf('token'), self.ttl) diff --git a/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py b/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py index d328d80ce..dc4a0d0ee 100644 --- a/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py +++ b/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py @@ -1,5 +1,6 @@ """DNS Authenticator for NS1 DNS.""" import logging +from typing import Optional from lexicon.providers import nsone import zope.interface @@ -8,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +29,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -54,6 +56,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_nsone_client().del_txt_record(domain, validation_name, validation) def _get_nsone_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _NS1LexiconClient(self.credentials.conf('api-key'), self.ttl) diff --git a/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py b/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py index 11ae6b8f0..13f5b2805 100644 --- a/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py +++ b/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py @@ -1,5 +1,6 @@ """DNS Authenticator for OVH DNS.""" import logging +from typing import Optional from lexicon.providers import ovh import zope.interface @@ -8,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +29,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -60,6 +62,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_ovh_client().del_txt_record(domain, validation_name, validation) def _get_ovh_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _OVHLexiconClient( self.credentials.conf('endpoint'), self.credentials.conf('application-key'), diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py index adebdd963..a3ee1e0e3 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py @@ -1,5 +1,6 @@ """DNS Authenticator using RFC 2136 Dynamic Updates.""" import logging +from typing import Optional import dns.flags import dns.message @@ -15,6 +16,7 @@ import zope.interface from certbot import errors from certbot import interfaces from certbot.plugins import dns_common +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -44,7 +46,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -80,6 +82,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_rfc2136_client().del_txt_record(validation_name, validation) def _get_rfc2136_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _RFC2136Client(self.credentials.conf('server'), int(self.credentials.conf('port') or self.PORT), self.credentials.conf('name'), diff --git a/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py b/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py index 67cfb2e97..eb78735f5 100644 --- a/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py +++ b/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py @@ -1,12 +1,15 @@ """DNS Authenticator for Sakura Cloud DNS.""" import logging +from typing import Optional from lexicon.providers import sakuracloud import zope.interface +from certbot import errors from certbot import interfaces from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon +from certbot.plugins.dns_common import CredentialsConfiguration logger = logging.getLogger(__name__) @@ -27,7 +30,7 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ @@ -60,6 +63,8 @@ class Authenticator(dns_common.DNSAuthenticator): domain, validation_name, validation) def _get_sakuracloud_client(self): + if not self.credentials: # pragma: no cover + raise errors.Error("Plugin has not been prepared.") return _SakuraCloudLexiconClient( self.credentials.conf('api-token'), self.credentials.conf('api-secret'), diff --git a/certbot-nginx/certbot_nginx/_internal/configurator.py b/certbot-nginx/certbot_nginx/_internal/configurator.py index aab489315..c05ddceba 100644 --- a/certbot-nginx/certbot_nginx/_internal/configurator.py +++ b/certbot-nginx/certbot_nginx/_internal/configurator.py @@ -119,7 +119,6 @@ class NginxConfigurator(common.Installer): self._chall_out = 0 # These will be set in the prepare function - self.parser: Optional[parser.NginxParser] = None self.version = version self.openssl_version = openssl_version self._enhance_func = {"redirect": self._enable_redirect, @@ -127,6 +126,7 @@ class NginxConfigurator(common.Installer): "staple-ocsp": self._enable_ocsp_stapling} self.reverter.recovery_routine() + self.parser: parser.NginxParser @property def mod_ssl_conf_src(self): diff --git a/certbot/certbot/_internal/cli/subparsers.py b/certbot/certbot/_internal/cli/subparsers.py index 822381d21..dabb26661 100644 --- a/certbot/certbot/_internal/cli/subparsers.py +++ b/certbot/certbot/_internal/cli/subparsers.py @@ -32,8 +32,7 @@ def _create_subparsers(helpful): " Currently --csr only works with the 'certonly' subcommand.") helpful.add("revoke", "--reason", dest="reason", - choices=CaseInsensitiveList(sorted(constants.REVOCATION_REASONS, - key=constants.REVOCATION_REASONS.get)), + choices=CaseInsensitiveList(constants.REVOCATION_REASONS.keys()), action=_EncodeReasonAction, default=flag_default("reason"), help="Specify reason for revoking certificate. (default: unspecified)") helpful.add("revoke", diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py index 796f05599..0442febda 100644 --- a/certbot/certbot/_internal/client.py +++ b/certbot/certbot/_internal/client.py @@ -254,6 +254,7 @@ class Client: acme = acme_from_config_key(config, self.account.key, self.account.regr) self.acme = acme + self.auth_handler: Optional[auth_handler.AuthHandler] if auth is not None: self.auth_handler = auth_handler.AuthHandler( auth, self.acme, self.account, self.config.pref_challs) @@ -407,6 +408,9 @@ class Client: raise errors.Error("The currently selected ACME CA endpoint does" " not support issuing wildcard certificates.") + if not self.auth_handler: + raise errors.Error("No authorization handler has been set.") + # For a dry run, ensure we have an order with fresh authorizations if orderr and self.config.dry_run: deactivated, failed = self.auth_handler.deactivate_valid_authorizations(orderr) diff --git a/certbot/certbot/_internal/display/completer.py b/certbot/certbot/_internal/display/completer.py index a6c984195..b43859b19 100644 --- a/certbot/certbot/_internal/display/completer.py +++ b/certbot/certbot/_internal/display/completer.py @@ -1,5 +1,8 @@ """Provides Tab completion when prompting users for a path.""" import glob +from typing import Callable +from typing import Iterator +from typing import Optional # readline module is not available on all systems try: @@ -26,7 +29,9 @@ class Completer: """ def __init__(self): - self._iter = self._original_completer = self._original_delims = None + self._iter: Iterator[str] + self._original_completer: Optional[Callable] + self._original_delims: str def complete(self, text, state): """Provides path completion for use with readline. diff --git a/certbot/certbot/_internal/lock.py b/certbot/certbot/_internal/lock.py index d0b66e5e2..80b79d993 100644 --- a/certbot/certbot/_internal/lock.py +++ b/certbot/certbot/_internal/lock.py @@ -223,6 +223,8 @@ class _WindowsLockMechanism(_BaseLockMechanism): def release(self): """Release the lock.""" try: + if not self._fd: + raise errors.Error("The lock has not been acquired first.") # This "type: ignore" is currently needed because msvcrt methods # are only defined on Windows. See # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. diff --git a/certbot/certbot/_internal/plugins/disco.py b/certbot/certbot/_internal/plugins/disco.py index 4097544e8..744062968 100644 --- a/certbot/certbot/_internal/plugins/disco.py +++ b/certbot/certbot/_internal/plugins/disco.py @@ -1,18 +1,20 @@ """Utilities for plugins discovery and selection.""" -from collections.abc import Mapping import itertools import logging import sys +from collections.abc import Mapping from typing import Dict +from typing import Optional +from typing import Union import pkg_resources import zope.interface import zope.interface.verify - from certbot import errors from certbot import interfaces from certbot._internal import constants from certbot.compat import os +from certbot.errors import Error logger = logging.getLogger(__name__) @@ -44,15 +46,15 @@ class PluginEntryPoint: # this object is mutable, don't allow it to be hashed! __hash__ = None # type: ignore - def __init__(self, entry_point, with_prefix=False): + def __init__(self, entry_point: pkg_resources.EntryPoint, with_prefix=False): self.name = self.entry_point_to_plugin_name(entry_point, with_prefix) - self.plugin_cls = entry_point.load() + self.plugin_cls: interfaces.IPluginFactory = entry_point.load() self.entry_point = entry_point - self.warning_message = None - self._initialized = None - self._prepared = None + self.warning_message: Optional[str] = None + self._initialized: Optional[interfaces.IPlugin] = None + self._prepared: Optional[Union[bool, Error]] = None self._hidden = False - self._long_description = None + self._long_description: Optional[str] = None def check_name(self, name): """Check if the name refers to this plugin.""" @@ -118,12 +120,15 @@ class PluginEntryPoint: """Memoized plugin initialization.""" if not self.initialized: self.entry_point.require() # fetch extras! - self._initialized = self.plugin_cls(config, self.name) + # TODO: remove type ignore once the interface becomes a proper + # abstract class (using abc) that mypy understands. + self._initialized = self.plugin_cls(config, self.name) # type: ignore return self._initialized def verify(self, ifaces): """Verify that the plugin conforms to the specified interfaces.""" - assert self.initialized + if not self.initialized: + raise ValueError("Plugin is not initialized.") for iface in ifaces: # zope.interface.providedBy(plugin) try: zope.interface.verify.verifyObject(iface, self.init()) @@ -144,10 +149,13 @@ class PluginEntryPoint: def prepare(self): """Memoized plugin preparation.""" - assert self.initialized + if self._initialized is None: + raise ValueError("Plugin is not initialized.") if self._prepared is None: try: - self._initialized.prepare() + # TODO: remove type ignore once the interface becomes a proper + # abstract class (using abc) that mypy understands. + self._initialized.prepare() # type: ignore except errors.MisconfigurationError as error: logger.debug("Misconfigured %r: %s", self, error, exc_info=True) self._prepared = error @@ -247,8 +255,10 @@ class PluginsRegistry(Mapping): plugin_ep = PluginEntryPoint(entry_point, with_prefix) if plugin_ep.name in plugins: other_ep = plugins[plugin_ep.name] + plugin1 = plugin_ep.entry_point.dist.key if plugin_ep.entry_point.dist else "unknown" + plugin2 = other_ep.entry_point.dist.key if other_ep.entry_point.dist else "unknown" raise Exception("Duplicate plugin name {0} from {1} and {2}.".format( - plugin_ep.name, plugin_ep.entry_point.dist.key, other_ep.entry_point.dist.key)) + plugin_ep.name, plugin1, plugin2)) if interfaces.IPluginFactory.providedBy(plugin_ep.plugin_cls): plugins[plugin_ep.name] = plugin_ep else: # pragma: no cover diff --git a/certbot/certbot/interfaces.py b/certbot/certbot/interfaces.py index 3830e2849..de9175def 100644 --- a/certbot/certbot/interfaces.py +++ b/certbot/certbot/interfaces.py @@ -1,5 +1,6 @@ """Certbot client interfaces.""" import abc +from typing import Optional import zope.interface @@ -327,7 +328,7 @@ class IInstaller(IPlugin): """ - def save(title=None, temporary=False): + def save(title: Optional[str] = None, temporary: bool = False): """Saves all changes to the configuration files. Both title and temporary are needed because a save may be diff --git a/certbot/certbot/plugins/dns_common.py b/certbot/certbot/plugins/dns_common.py index 52328ad85..4b621ceac 100644 --- a/certbot/certbot/plugins/dns_common.py +++ b/certbot/certbot/plugins/dns_common.py @@ -142,7 +142,8 @@ class DNSAuthenticator(common.Plugin): setattr(self.config, self.dest(key), os.path.abspath(os.path.expanduser(new_value))) - def _configure_credentials(self, key, label, required_variables=None, validator=None): + def _configure_credentials(self, key, label, required_variables=None, + validator=None) -> 'CredentialsConfiguration': """ As `_configure_file`, but for a credential configuration file. diff --git a/certbot/certbot/plugins/dns_common_lexicon.py b/certbot/certbot/plugins/dns_common_lexicon.py index 10efa5f85..a4d46587e 100644 --- a/certbot/certbot/plugins/dns_common_lexicon.py +++ b/certbot/certbot/plugins/dns_common_lexicon.py @@ -17,8 +17,10 @@ from certbot.plugins import dns_common # if Lexicon is not available, obviously. try: from lexicon.config import ConfigResolver + from lexicon.providers.base import Provider except ImportError: ConfigResolver = None # type: ignore + Provider = None # type: ignore logger = logging.getLogger(__name__) @@ -29,7 +31,7 @@ class LexiconClient: """ def __init__(self): - self.provider = None + self.provider: Provider def add_txt_record(self, domain, record_name, record_content): """ diff --git a/certbot/certbot/plugins/storage.py b/certbot/certbot/plugins/storage.py index 0d32d6850..602c62d1e 100644 --- a/certbot/certbot/plugins/storage.py +++ b/certbot/certbot/plugins/storage.py @@ -26,8 +26,8 @@ class PluginStorage: self._config = config self._classkey = classkey self._initialized = False - self._data = None - self._storagepath = None + self._data: Dict + self._storagepath: str def _initialize_storage(self): """Initializes PluginStorage data and reads current state from the disk diff --git a/certbot/tests/plugins/storage_test.py b/certbot/tests/plugins/storage_test.py index 2999d306e..4eb5f0912 100644 --- a/certbot/tests/plugins/storage_test.py +++ b/certbot/tests/plugins/storage_test.py @@ -31,7 +31,7 @@ class PluginStorageTest(test_util.ConfigTestCase): # When unable to read file that exists mock_open = mock.mock_open() mock_open.side_effect = IOError - self.plugin.storage.storagepath = os.path.join(self.config.config_dir, + self.plugin.storage._storagepath = os.path.join(self.config.config_dir, ".pluginstorage.json") with mock.patch("builtins.open", mock_open): with mock.patch('certbot.compat.os.path.isfile', return_value=True): @@ -67,7 +67,7 @@ class PluginStorageTest(test_util.ConfigTestCase): with mock.patch("certbot.plugins.storage.logger.error") as mock_log: # Set data as something that can't be serialized self.plugin.storage._initialized = True # pylint: disable=protected-access - self.plugin.storage.storagepath = "/tmp/whatever" + self.plugin.storage._storagepath = "/tmp/whatever" self.plugin.storage._data = self.plugin_cls # pylint: disable=protected-access self.assertRaises(errors.PluginStorageError, self.plugin.storage.save) @@ -80,6 +80,7 @@ class PluginStorageTest(test_util.ConfigTestCase): with mock.patch("certbot.plugins.storage.logger.error") as mock_log: self.plugin.storage._data = {"valid": "data"} # pylint: disable=protected-access self.plugin.storage._initialized = True # pylint: disable=protected-access + self.plugin.storage._storagepath = "/tmp/whatever" self.assertRaises(errors.PluginStorageError, self.plugin.storage.save) self.assertTrue("Could not write" in mock_log.call_args[0][0]) diff --git a/tox.ini b/tox.ini index 18d0d7db3..ada7002da 100644 --- a/tox.ini +++ b/tox.ini @@ -156,7 +156,7 @@ commands = basepython = python3 commands = {[base]install_packages} - mypy --no-strict-optional {[base]source_paths} + mypy {[base]source_paths} [testenv:apacheconftest] commands = From a12d91aef6c48765b1783f0741f55202343d7a9b Mon Sep 17 00:00:00 2001 From: alexzorin Date: Tue, 6 Apr 2021 08:50:12 +1000 Subject: [PATCH 06/21] fix various fd leaks (#8747) * fix various fd leaks * use context manager for display provider --- certbot/certbot/_internal/main.py | 40 ++++++++++++++++++--------- certbot/tests/log_test.py | 3 +- certbot/tests/plugins/webroot_test.py | 3 +- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index ac4d18449..aed265ba3 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -4,6 +4,9 @@ import functools import logging.handlers import sys +from contextlib import contextmanager +from typing import Generator +from typing import IO from typing import Iterable from typing import List from typing import Optional @@ -1347,26 +1350,36 @@ def make_or_verify_needed_dirs(config): util.make_or_verify_dir(hook_dir, strict=config.strict_permissions) -def set_displayer(config): - """Set the displayer +@contextmanager +def make_displayer(config: configuration.NamespaceConfig + ) -> Generator[Union[display_util.NoninteractiveDisplay, + display_util.FileDisplay], None, None]: + """Creates a display object appropriate to the flags in the supplied config. :param config: Configuration object - :type config: interfaces.IConfig - :returns: `None` - :rtype: None + :returns: Display object implementing :class:`certbot.interfaces.IDisplay` """ + displayer: Union[None, display_util.NoninteractiveDisplay, + display_util.FileDisplay] = None + devnull: Optional[IO] = None + if config.quiet: config.noninteractive_mode = True - displayer: Union[None, display_util.NoninteractiveDisplay, display_util.FileDisplay] =\ - display_util.NoninteractiveDisplay(open(os.devnull, "w")) + devnull = open(os.devnull, "w") + displayer = display_util.NoninteractiveDisplay(devnull) elif config.noninteractive_mode: displayer = display_util.NoninteractiveDisplay(sys.stdout) else: - displayer = display_util.FileDisplay(sys.stdout, - config.force_interactive) - zope.component.provideUtility(displayer) + displayer = display_util.FileDisplay( + sys.stdout, config.force_interactive) + + try: + yield displayer + finally: + if devnull: + devnull.close() def main(cli_args=None): @@ -1411,11 +1424,12 @@ def main(cli_args=None): if config.func != plugins_cmd: # pylint: disable=comparison-with-callable raise - set_displayer(config) - # Reporter report = reporter.Reporter(config) zope.component.provideUtility(report) util.atexit_register(report.print_messages) - return config.func(config, plugins) + with make_displayer(config) as displayer: + zope.component.provideUtility(displayer) + + return config.func(config, plugins) diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 7b1aacd5c..5960b37cf 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -28,7 +28,8 @@ class PreArgParseSetupTest(unittest.TestCase): @classmethod def _call(cls, *args, **kwargs): # pylint: disable=unused-argument from certbot._internal.log import pre_arg_parse_setup - return pre_arg_parse_setup() + with mock.patch('builtins.open', mock.mock_open()): + return pre_arg_parse_setup() @mock.patch('certbot._internal.log.sys') @mock.patch('certbot._internal.log.pre_arg_parse_except_hook') diff --git a/certbot/tests/plugins/webroot_test.py b/certbot/tests/plugins/webroot_test.py index e6fbd8e88..5792924a9 100644 --- a/certbot/tests/plugins/webroot_test.py +++ b/certbot/tests/plugins/webroot_test.py @@ -141,7 +141,8 @@ class AuthenticatorTest(unittest.TestCase): f.write("thingimy") filesystem.chmod(self.path, 0o000) try: - open(permission_canary, "r") + with open(permission_canary, "r"): + pass print("Warning, running tests as root skips permissions tests...") except IOError: # ok, permissions work, test away... From f15d10abc827b59d06418926621cd26abfcf8534 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 5 Apr 2021 16:02:14 -0700 Subject: [PATCH 07/21] Update Dockerfile-dev (#8774) * switch Dockerfile-dev to Ubuntu Focal * Make apt noninteractive * add --no-install-recommends --- Dockerfile-dev | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile-dev b/Dockerfile-dev index 86847f8fd..895dbdc0b 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -1,5 +1,5 @@ # This Dockerfile builds an image for development. -FROM debian:buster +FROM ubuntu:focal # Note: this only exposes the port to other docker containers. EXPOSE 80 443 @@ -8,8 +8,9 @@ WORKDIR /opt/certbot/src COPY . . RUN apt-get update && \ - apt-get install apache2 git python3-dev python3-venv gcc libaugeas0 \ - libssl-dev libffi-dev ca-certificates openssl nginx-light -y && \ + DEBIAN_FRONTEND=noninteractive apt-get install apache2 git python3-dev \ + python3-venv gcc libaugeas0 libssl-dev libffi-dev ca-certificates \ + openssl nginx-light -y --no-install-recommends && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* \ /tmp/* \ From 1b6e4028dcc01ae8f23d83393626e8dbde85fd28 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 6 Apr 2021 10:17:01 -0700 Subject: [PATCH 08/21] Update changelog for 1.14.0 release --- certbot/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 9b37e9a1a..e0ebcfd81 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,7 +2,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). -## 1.14.0 - master +## 1.14.0 - 2021-04-06 ### Added From bf40b81b5abcc4fef0f61770310bd56b529fa27f Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 6 Apr 2021 10:24:32 -0700 Subject: [PATCH 09/21] Release 1.14.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-auto | 27 ++++++++++--------- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/certbot/__init__.py | 2 +- certbot/docs/cli-help.txt | 2 +- letsencrypt-auto | 27 ++++++++++--------- letsencrypt-auto-source/certbot-auto.asc | 16 +++++------ letsencrypt-auto-source/letsencrypt-auto | 26 +++++++++--------- letsencrypt-auto-source/letsencrypt-auto.sig | 4 +-- .../pieces/certbot-requirements.txt | 24 ++++++++--------- 26 files changed, 82 insertions(+), 82 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 90ab5c9f3..1170e7393 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 43165a9dd..eb5e59130 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-auto b/certbot-auto index 24af0b4c3..c37c45596 100755 --- a/certbot-auto +++ b/certbot-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.13.0" +LE_AUTO_VERSION="1.14.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -800,6 +800,7 @@ BootstrapMageiaCommon() { # packages BOOTSTRAP_VERSION is not set. if [ -f /etc/debian_version ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 @@ -1488,18 +1489,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.13.0 \ - --hash=sha256:082eb732e1318bb9605afa7aea8db2c2f4c5029d523c73f24c6aa98f03caff76 \ - --hash=sha256:64cf41b57df7667d9d849fcaa9031a4f151788246733d1f4c3f37a5aa5e2f458 -acme==1.13.0 \ - --hash=sha256:93b6365c9425de03497a6b8aee1107814501d2974499b42e9bcc9a7378771143 \ - --hash=sha256:6b4257dfd6a6d5f01e8cd4f0b10422c17836bed7c67e9c5b0a0ad6c7d651c088 -certbot-apache==1.13.0 \ - --hash=sha256:36ed02ac7d2d91febee8dd3181ae9095b3f06434c9ed8959fbc6db24ab4da2e8 \ - --hash=sha256:4b5a16e80c1418e2edc05fc2578f522fb24974b2c13eb747cdfeef69e5bd5ae1 -certbot-nginx==1.13.0 \ - --hash=sha256:3ff271f65321b25c77a868af21f76f58754a7d61529ad565a1d66e29c711120f \ - --hash=sha256:9e972cc19c0fa9e5b7863da0423b156fbfb5623fd30b558fd2fd6d21c24c0b08 +certbot==1.14.0 \ + --hash=sha256:67b4d26ceaea6c7f8325d0d45169e7a165a2cabc7122c84bc971ba068ca19cca \ + --hash=sha256:959ea90c6bb8dca38eab9772722cb940972ef6afcd5f15deef08b3c3636841eb +acme==1.14.0 \ + --hash=sha256:4f48c41261202f1a389ec2986b2580b58f53e0d5a1ae2463b34318d78b87fc66 \ + --hash=sha256:61daccfb0343628cbbca551a7fc4c82482113952c21db3fe0c585b7c98fa1c35 +certbot-apache==1.14.0 \ + --hash=sha256:b757038db23db707c44630fecb46e99172bd791f0db5a8e623c0842613c4d3d9 \ + --hash=sha256:887fe4a21af2de1e5c2c9428bacba6eb7c1219257bc70f1a1d8447c8a321adb0 +certbot-nginx==1.14.0 \ + --hash=sha256:8916a815437988d6c192df9f035bb7a176eab20eee0956677b335d0698d243fb \ + --hash=sha256:cc2a8a0de56d9bb6b2efbda6c80c647dad8db2bb90675cac03ade94bd5fc8597 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 3e9e6a7c2..f1e0b4425 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 2e5215f9c..f2daa8067 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 44bada6bc..c276beff2 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 106eb3cac..5f2b34ca3 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 99a3c92a3..fa2d2a53b 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index b126b4e8f..d1c26f6d1 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index cada7a85e..9c059a82c 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index e8b26eceb..6e059eef8 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 63da31df2..780eb3a58 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 61b9dfa78..9537d261a 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index d60412f27..4c7bba724 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 4d6131ff7..8d1dcab2a 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 18d006732..86eef3f3d 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index fdc931bbe..f52ba6e08 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 55f140d76..0ac3019cf 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 8b638f28e..217c59373 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.14.0.dev0' +version = '1.14.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 790443bcc..672b4ed1d 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,3 +1,3 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '1.14.0.dev0' +__version__ = '1.14.0' diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt index 27511777b..c5490c100 100644 --- a/certbot/docs/cli-help.txt +++ b/certbot/docs/cli-help.txt @@ -118,7 +118,7 @@ optional arguments: case, and to know when to deprecate support for past Python versions and flags. If you wish to hide this information from the Let's Encrypt server, set this to - "". (default: CertbotACMEClient/1.13.0 + "". (default: CertbotACMEClient/1.14.0 (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the diff --git a/letsencrypt-auto b/letsencrypt-auto index 24af0b4c3..c37c45596 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.13.0" +LE_AUTO_VERSION="1.14.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -800,6 +800,7 @@ BootstrapMageiaCommon() { # packages BOOTSTRAP_VERSION is not set. if [ -f /etc/debian_version ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 @@ -1488,18 +1489,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.13.0 \ - --hash=sha256:082eb732e1318bb9605afa7aea8db2c2f4c5029d523c73f24c6aa98f03caff76 \ - --hash=sha256:64cf41b57df7667d9d849fcaa9031a4f151788246733d1f4c3f37a5aa5e2f458 -acme==1.13.0 \ - --hash=sha256:93b6365c9425de03497a6b8aee1107814501d2974499b42e9bcc9a7378771143 \ - --hash=sha256:6b4257dfd6a6d5f01e8cd4f0b10422c17836bed7c67e9c5b0a0ad6c7d651c088 -certbot-apache==1.13.0 \ - --hash=sha256:36ed02ac7d2d91febee8dd3181ae9095b3f06434c9ed8959fbc6db24ab4da2e8 \ - --hash=sha256:4b5a16e80c1418e2edc05fc2578f522fb24974b2c13eb747cdfeef69e5bd5ae1 -certbot-nginx==1.13.0 \ - --hash=sha256:3ff271f65321b25c77a868af21f76f58754a7d61529ad565a1d66e29c711120f \ - --hash=sha256:9e972cc19c0fa9e5b7863da0423b156fbfb5623fd30b558fd2fd6d21c24c0b08 +certbot==1.14.0 \ + --hash=sha256:67b4d26ceaea6c7f8325d0d45169e7a165a2cabc7122c84bc971ba068ca19cca \ + --hash=sha256:959ea90c6bb8dca38eab9772722cb940972ef6afcd5f15deef08b3c3636841eb +acme==1.14.0 \ + --hash=sha256:4f48c41261202f1a389ec2986b2580b58f53e0d5a1ae2463b34318d78b87fc66 \ + --hash=sha256:61daccfb0343628cbbca551a7fc4c82482113952c21db3fe0c585b7c98fa1c35 +certbot-apache==1.14.0 \ + --hash=sha256:b757038db23db707c44630fecb46e99172bd791f0db5a8e623c0842613c4d3d9 \ + --hash=sha256:887fe4a21af2de1e5c2c9428bacba6eb7c1219257bc70f1a1d8447c8a321adb0 +certbot-nginx==1.14.0 \ + --hash=sha256:8916a815437988d6c192df9f035bb7a176eab20eee0956677b335d0698d243fb \ + --hash=sha256:cc2a8a0de56d9bb6b2efbda6c80c647dad8db2bb90675cac03ade94bd5fc8597 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index fbd16f2b0..c0cf63418 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAmA+sv4ACgkQTRfJlc2X -dfLG+ggAvwUCqy06UZd8jZhOZFUoi8nWHG2TMnm/4CW4G9PPCjsCoQplhaAaUCrR -PAv0vtsG1rBKWekICg6IBTzLVioH9xRPUkpfbVQhT1c1T/5CqMsFFXR5p9YAKRe7 -hlOb7VRN10bdCS4JThRPNhdWFdWKZXYKcIOObWA/FX2GacxMHuLwPpSsbt2NRffy -qz1ZOWxvr289aWEbZWfyBiI2bxQ7wlMEbZ/JLUXDe46ETDxzENu+c0x2109ha6m4 -wHmUS0r16ps/n9DueTZGJf3C26mU+cIB+LgNvOcibBo+0Ly7t+OiBHYbkFXS2KTQ -RbH4bPZrsduUOzhE8wIsSUIsVGDleQ== -=jYnL +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAmBsmUkACgkQTRfJlc2X +dfI7Bwf9FkNrf1HEh2G3uk1p+qLMd/s5kcVV2udK2FkRELee5nHlLZx2YmHA/8ID +gqsk8EsyRZNMX374nGrPm0syykdEsyVtMJTbHCEr+Ms3l54ZgE3HV6ywnhWSlAFo +Za50kdzhodBVTS5AEADbCKLKObVAWwO3fFKtKyv/iY29ykpHK0KSHCKRII3iQU7l +dnR6u35Z0wgfEmDxsH27K6uo0YepZaEL70qHHFk93MhCh9Z15rO17gRpsVzz7Z1j +YClI6h2K/VOfZtbkoQvoks7s+xd75Kjr3GNH+cznkJx8gNWSZLfkc1XX4Bjdm4GG +IWz3Ezy8tFg6PtITb7y+aIg75kWx4w== +=zEy4 -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index b0b25759f..c37c45596 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.14.0.dev0" +LE_AUTO_VERSION="1.14.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1489,18 +1489,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.13.0 \ - --hash=sha256:082eb732e1318bb9605afa7aea8db2c2f4c5029d523c73f24c6aa98f03caff76 \ - --hash=sha256:64cf41b57df7667d9d849fcaa9031a4f151788246733d1f4c3f37a5aa5e2f458 -acme==1.13.0 \ - --hash=sha256:93b6365c9425de03497a6b8aee1107814501d2974499b42e9bcc9a7378771143 \ - --hash=sha256:6b4257dfd6a6d5f01e8cd4f0b10422c17836bed7c67e9c5b0a0ad6c7d651c088 -certbot-apache==1.13.0 \ - --hash=sha256:36ed02ac7d2d91febee8dd3181ae9095b3f06434c9ed8959fbc6db24ab4da2e8 \ - --hash=sha256:4b5a16e80c1418e2edc05fc2578f522fb24974b2c13eb747cdfeef69e5bd5ae1 -certbot-nginx==1.13.0 \ - --hash=sha256:3ff271f65321b25c77a868af21f76f58754a7d61529ad565a1d66e29c711120f \ - --hash=sha256:9e972cc19c0fa9e5b7863da0423b156fbfb5623fd30b558fd2fd6d21c24c0b08 +certbot==1.14.0 \ + --hash=sha256:67b4d26ceaea6c7f8325d0d45169e7a165a2cabc7122c84bc971ba068ca19cca \ + --hash=sha256:959ea90c6bb8dca38eab9772722cb940972ef6afcd5f15deef08b3c3636841eb +acme==1.14.0 \ + --hash=sha256:4f48c41261202f1a389ec2986b2580b58f53e0d5a1ae2463b34318d78b87fc66 \ + --hash=sha256:61daccfb0343628cbbca551a7fc4c82482113952c21db3fe0c585b7c98fa1c35 +certbot-apache==1.14.0 \ + --hash=sha256:b757038db23db707c44630fecb46e99172bd791f0db5a8e623c0842613c4d3d9 \ + --hash=sha256:887fe4a21af2de1e5c2c9428bacba6eb7c1219257bc70f1a1d8447c8a321adb0 +certbot-nginx==1.14.0 \ + --hash=sha256:8916a815437988d6c192df9f035bb7a176eab20eee0956677b335d0698d243fb \ + --hash=sha256:cc2a8a0de56d9bb6b2efbda6c80c647dad8db2bb90675cac03ade94bd5fc8597 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index 3516f77b0..b297bdfb3 100644 --- a/letsencrypt-auto-source/letsencrypt-auto.sig +++ b/letsencrypt-auto-source/letsencrypt-auto.sig @@ -1,3 +1 @@ -_̊П‡åNþÌ*–¿”ŽšJsµ¤‰Q…j ÜS¢llªY3Q]Âê«x+/V`$4xM…ñïæ™¾èUăÚí«Sí³•Pl ¶Hbƒ a<£{p~`ÐŒó&a1E@²Ú;RNiL¬J¹@îpÌÏwk!Š ‡&Æ, Date: Tue, 6 Apr 2021 10:24:34 -0700 Subject: [PATCH 10/21] Add contents to certbot/CHANGELOG.md for next version --- certbot/CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index e0ebcfd81..7648d0ec3 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,6 +2,22 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). +## 1.15.0 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +More details about these changes can be found on our GitHub repo. + ## 1.14.0 - 2021-04-06 ### Added From 04a85742c1529167772e326ba904eca3d6aa7f4d Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 6 Apr 2021 10:24:35 -0700 Subject: [PATCH 11/21] Bump version to 1.15.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/certbot/__init__.py | 2 +- letsencrypt-auto-source/letsencrypt-auto | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 1170e7393..443aab6e8 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index eb5e59130..76ebbddfd 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index f1e0b4425..f1bf28596 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index f2daa8067..fcc7c3036 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index c276beff2..6452d325d 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 5f2b34ca3..33f16314e 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index fa2d2a53b..14fcd4a69 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index d1c26f6d1..dd02d96b5 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 9c059a82c..00ff0834a 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 6e059eef8..4933ffb0b 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 780eb3a58..55dad1d60 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 9537d261a..46c71c46b 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 4c7bba724..6d3218221 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 8d1dcab2a..e8e44db30 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 86eef3f3d..6b4648d91 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index f52ba6e08..30c45dc84 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 0ac3019cf..c328429c9 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 217c59373..11df5eddf 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.14.0' +version = '1.15.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 672b4ed1d..fbf8160fc 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,3 +1,3 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '1.14.0' +__version__ = '1.15.0.dev0' diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index c37c45596..9ddc7e076 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.14.0" +LE_AUTO_VERSION="1.15.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates From 459a254aea3a9a5a6ac9f069ba446d93ce307a5c Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 7 Apr 2021 14:52:15 -0700 Subject: [PATCH 12/21] Improve tools/snap/build_remote.py output (#8780) I think this PR improves tools/snap/build_remote.py's output in a number of ways such as: * Logs of snap builds were being deleted because they weren't being copied out of the temporary directory added in https://github.com/certbot/certbot/pull/8719. * The lock should now always be acquired before printing output when multiple processes are running which helps prevent processes mixing their output with each other. * Output is never buffered which ensures that repeated calls to `print` from the same process while it holds the output lock is kept together. * The case where we printed output about the "chroot problem" and stopped retrying the build has been deleted because with the fix in https://github.com/certbot/certbot/pull/8719, we should be able to recover in this case. * If the build failed for any reason, we dump as much output about the problem as we can. I think most times we won't need to read this output, but I personally prefer it being there in case we want it for some reason. Due to this change, I also simplified `_build_snap` and `_dump_results` a bit since `_build_snap` handles printing logs as needed. * print more output * lock when printing output * clarify purpose of lock * preserve logfiles * python better * consistently flush output * remove workspaces dict * rename variable * remove unused variable * don't use all which exits early * fix typo --- tools/snap/build_remote.py | 156 +++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 77 deletions(-) diff --git a/tools/snap/build_remote.py b/tools/snap/build_remote.py index b12799dc3..91854e9e0 100755 --- a/tools/snap/build_remote.py +++ b/tools/snap/build_remote.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse import datetime +import functools import glob from multiprocessing import Manager from multiprocessing import Pool @@ -28,21 +29,34 @@ CERTBOT_DIR = dirname(dirname(dirname(realpath(__file__)))) PLUGINS = [basename(path) for path in glob.glob(join(CERTBOT_DIR, 'certbot-dns-*'))] +# In Python, stdout and stderr are buffered in each process by default. When +# printing output from multiple processes, this can cause delays in printing +# output with lines from different processes being interleaved depending +# on when the output for that process is flushed. To prevent this, we override +# print so that it always flushes its output. Disabling output buffering can +# also be done through command line flags or environment variables set when the +# Python process starts, but this approach was taken instead to ensure +# consistent behavior regardless of how the script is invoked. +print = functools.partial(print, flush=True) + + +def _snap_log_name(target: str, arch: str): + return f'{target}_{arch}.txt' + + def _execute_build( target: str, archs: Set[str], status: Dict[str, Dict[str, str]], workspace: str) -> Tuple[int, List[str]]: - temp_workspace = None - try: - # Snapcraft remote-build has a recover feature, that will make it reconnect to an existing - # build on Launchpad if possible. However, the signature used to retrieve a potential - # build is not based on the content of the sources used to build a snap, but on a hash - # of the snapcraft current working directory (the path itself, not the content). - # It means that every build started from /my/path/to/certbot will always be considered - # as the same build, whatever the actual sources are. - # To circumvent this, we create a temporary folder and use it as a workspace to build - # the snap: this path is random, making the recover feature effectively noop. - temp_workspace = tempfile.mkdtemp() + # Snapcraft remote-build has a recover feature, that will make it reconnect to an existing + # build on Launchpad if possible. However, the signature used to retrieve a potential + # build is not based on the content of the sources used to build a snap, but on a hash + # of the snapcraft current working directory (the path itself, not the content). + # It means that every build started from /my/path/to/certbot will always be considered + # as the same build, whatever the actual sources are. + # To circumvent this, we create a temporary folder and use it as a workspace to build + # the snap: this path is random, making the recover feature effectively noop. + with tempfile.TemporaryDirectory() as temp_workspace: ignore = None if target == 'certbot': ignore = shutil.ignore_patterns(".git", "venv*", ".tox") @@ -71,20 +85,18 @@ def _execute_build( for path in glob.glob(join(temp_workspace, '*.snap')): shutil.copy(path, workspace) + for arch in archs: + log_name = _snap_log_name(target, arch) + log_path = join(temp_workspace, log_name) + if exists(log_path): + shutil.copy(log_path, workspace) return process_state, process_output - except BaseException as e: - print(e) - sys.stdout.flush() - raise e - finally: - if temp_workspace: - shutil.rmtree(temp_workspace, ignore_errors=True) def _build_snap( target: str, archs: Set[str], status: Dict[str, Dict[str, str]], - running: Dict[str, bool], lock: Lock) -> Dict[str, str]: + running: Dict[str, bool], output_lock: Lock) -> bool: status[target] = {arch: '...' for arch in archs} if target == 'certbot': @@ -92,24 +104,19 @@ def _build_snap( else: workspace = join(CERTBOT_DIR, target) + build_success = False retry = 3 while retry: exit_code, process_output = _execute_build(target, archs, status, workspace) + with output_lock: + print(f'Build {target} for {",".join(archs)} (attempt {4-retry}/3) ended with ' + f'exit code {exit_code}.') - print(f'Build {target} for {",".join(archs)} (attempt {4-retry}/3) ended with ' - f'exit code {exit_code}.') - sys.stdout.flush() - - with lock: - dump_output = exit_code != 0 failed_archs = [arch for arch in archs if status[target][arch] != 'Successfully built'] - if any(arch for arch in archs if status[target][arch] == 'Chroot problem'): - print('Some builds failed with the status "Chroot problem".') - print('This status is known to make any future build fail until either ' - 'the source code changes or the build on Launchpad is deleted.') - print('Please fix the build appropriately before trying a new one.') - # It is useless to retry in this situation. - retry = 0 + # If the command failed or any architecture wasn't built + # successfully, let's try to print all the output about the problem + # that we can. + dump_output = exit_code != 0 or failed_archs if exit_code == 0 and not failed_archs: # We expect to have all target snaps available, or something bad happened. snaps_list = glob.glob(join(workspace, '*.snap')) @@ -118,16 +125,12 @@ def _build_snap( f'(current list: {snaps_list}).') dump_output = True else: + build_success = True break - if failed_archs: - # We expect each failed build to have a log file, or something bad happened. - for arch in failed_archs: - if not exists(join(workspace, f'{target}_{arch}.txt')): - dump_output = True - print(f'Missing output on a failed build {target} for {arch}.') if dump_output: print(f'Dumping snapcraft remote-build output build for {target}:') print('\n'.join(process_output)) + _dump_failed_build_logs(target, archs, status, workspace) # Retry the remote build if it has been interrupted (non zero status code) # or if some builds have failed. @@ -135,7 +138,7 @@ def _build_snap( running[target] = False - return {target: workspace} + return build_success def _extract_state(project: str, output: str, status: Dict[str, Dict[str, str]]) -> None: @@ -167,53 +170,45 @@ def _dump_status_helper(archs: Set[str], status: Dict[str, Dict[str, str]]) -> N print(f'|{"-" * 26}' * len(headers)) print() - sys.stdout.flush() - def _dump_status( archs: Set[str], status: Dict[str, Dict[str, str]], - running: Dict[str, bool]) -> None: + running: Dict[str, bool], output_lock: Lock) -> None: while any(running.values()): - print(f'Remote build status at {datetime.datetime.now()}') - _dump_status_helper(archs, status) + with output_lock: + print(f'Remote build status at {datetime.datetime.now()}') + _dump_status_helper(archs, status) time.sleep(10) -def _dump_results( - targets: Set[str], archs: Set[str], status: Dict[str, Dict[str, str]], - workspaces: Dict[str, str]) -> bool: - failures = False - for target in targets: - for arch in archs: - result = status[target][arch] +def _dump_failed_build_logs( + target: str, archs: Set[str], status: Dict[str, Dict[str, str]], + workspace: str) -> None: + for arch in archs: + result = status[target][arch] - if result != 'Successfully built': - failures = True + if result != 'Successfully built': + failures = True - build_output_path = join(workspaces[target], f'{target}_{arch}.txt') - if not exists(build_output_path): - build_output = f'No output has been dumped by snapcraft remote-build.' - else: - with open(join(workspaces[target], f'{target}_{arch}.txt')) as file_h: - build_output = file_h.read() + build_output_name = _snap_log_name(target, arch) + build_output_path = join(workspace, build_output_name) + if not exists(build_output_path): + build_output = f'No output has been dumped by snapcraft remote-build.' + else: + with open(build_output_path) as file_h: + build_output = file_h.read() - print(f'Output for failed build target={target} arch={arch}') - print('-------------------------------------------') - print(build_output) - print('-------------------------------------------') - print() + print(f'Output for failed build target={target} arch={arch}') + print('-------------------------------------------') + print(build_output) + print('-------------------------------------------') + print() - if not failures: - print('All builds succeeded.') - else: - print('Some builds failed.') - print() +def _dump_results(archs: Set[str], status: Dict[str, Dict[str, str]]) -> None: print(f'Results for remote build finished at {datetime.datetime.now()}') _dump_status_helper(archs, status) - return failures - def main(): parser = argparse.ArgumentParser() @@ -252,12 +247,14 @@ def main(): with manager, pool: status: Dict[str, Dict[str, str]] = manager.dict() running = manager.dict({target: True for target in targets}) - lock = manager.Lock() + # While multiple processes are running, this lock should be acquired + # before printing output. + output_lock = manager.Lock() - async_results = [pool.apply_async(_build_snap, (target, archs, status, running, lock)) + async_results = [pool.apply_async(_build_snap, (target, archs, status, running, output_lock)) for target in targets] - process = Process(target=_dump_status, args=(archs, status, running)) + process = Process(target=_dump_status, args=(archs, status, running, output_lock)) process.start() try: @@ -266,11 +263,16 @@ def main(): if process.is_alive(): raise ValueError(f"Timeout out reached ({args.timeout} seconds) during the build!") - workspaces = {} + build_success = True for async_result in async_results: - workspaces.update(async_result.get()) + if not async_result.get(): + build_success = False - if _dump_results(targets, archs, status, workspaces): + _dump_results(archs, status) + if build_success: + print('All builds succeeded.') + else: + print('Some builds failed.') raise ValueError("There were failures during the build!") finally: process.terminate() From 7f9857a81b7064d767f694e033b29dc4bb942406 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 8 Apr 2021 13:04:51 -0700 Subject: [PATCH 13/21] Use Python 3 style super (#8777) This is one of the things that newer versions of `pylint` complains about. * git grep -l super\( | xargs sed -i 's/super([^)]*)/super()/g' * fix spacing --- acme/acme/challenges.py | 6 ++--- acme/acme/client.py | 6 ++--- acme/acme/errors.py | 12 +++++----- acme/acme/fields.py | 4 ++-- acme/acme/jws.py | 2 +- acme/acme/messages.py | 22 +++++++++---------- acme/acme/mixins.py | 10 ++++----- acme/tests/client_test.py | 6 ++--- .../certbot_apache/_internal/apacheparser.py | 8 +++---- .../certbot_apache/_internal/augeasparser.py | 8 +++---- .../certbot_apache/_internal/configurator.py | 6 ++--- .../certbot_apache/_internal/http_01.py | 2 +- .../certbot_apache/_internal/interfaces.py | 4 ++-- .../certbot_apache/_internal/obj.py | 2 +- .../_internal/override_centos.py | 12 +++++----- .../_internal/override_debian.py | 2 +- .../_internal/override_fedora.py | 10 ++++----- .../_internal/override_gentoo.py | 4 ++-- certbot-apache/tests/augeasnode_test.py | 2 +- certbot-apache/tests/autohsts_test.py | 2 +- certbot-apache/tests/centos6_test.py | 6 ++--- certbot-apache/tests/centos_test.py | 12 +++++----- certbot-apache/tests/complex_parsing_test.py | 2 +- .../tests/configurator_reverter_test.py | 2 +- certbot-apache/tests/configurator_test.py | 16 +++++++------- certbot-apache/tests/debian_test.py | 2 +- certbot-apache/tests/fedora_test.py | 12 +++++----- certbot-apache/tests/gentoo_test.py | 6 ++--- certbot-apache/tests/http_01_test.py | 2 +- certbot-apache/tests/parser_test.py | 4 ++-- .../tests/parsernode_configurator_test.py | 2 +- certbot-apache/tests/parsernode_test.py | 6 ++--- certbot-apache/tests/util.py | 2 +- .../nginx_tests/context.py | 4 ++-- .../rfc2136_tests/context.py | 2 +- .../configurators/apache/common.py | 6 ++--- .../configurators/nginx/common.py | 2 +- .../_internal/dns_cloudflare.py | 4 ++-- .../tests/dns_cloudflare_test.py | 2 +- .../_internal/dns_cloudxns.py | 6 ++--- .../tests/dns_cloudxns_test.py | 2 +- .../_internal/dns_digitalocean.py | 4 ++-- .../tests/dns_digitalocean_test.py | 2 +- .../_internal/dns_dnsimple.py | 6 ++--- .../tests/dns_dnsimple_test.py | 2 +- .../_internal/dns_dnsmadeeasy.py | 6 ++--- .../tests/dns_dnsmadeeasy_test.py | 2 +- .../_internal/dns_gehirn.py | 8 +++---- certbot-dns-gehirn/tests/dns_gehirn_test.py | 2 +- .../_internal/dns_google.py | 2 +- certbot-dns-google/tests/dns_google_test.py | 4 ++-- .../_internal/dns_linode.py | 6 ++--- certbot-dns-linode/tests/dns_linode_test.py | 2 +- .../_internal/dns_luadns.py | 6 ++--- certbot-dns-luadns/tests/dns_luadns_test.py | 2 +- .../certbot_dns_nsone/_internal/dns_nsone.py | 6 ++--- certbot-dns-nsone/tests/dns_nsone_test.py | 2 +- .../certbot_dns_ovh/_internal/dns_ovh.py | 8 +++---- certbot-dns-ovh/tests/dns_ovh_test.py | 2 +- .../_internal/dns_rfc2136.py | 4 ++-- certbot-dns-rfc2136/tests/dns_rfc2136_test.py | 2 +- .../_internal/dns_route53.py | 2 +- .../certbot_dns_route53/authenticator.py | 2 +- certbot-dns-route53/tests/dns_route53_test.py | 2 +- .../_internal/dns_sakuracloud.py | 8 +++---- .../tests/dns_sakuracloud_test.py | 2 +- .../certbot_nginx/_internal/configurator.py | 6 ++--- .../certbot_nginx/_internal/http_01.py | 2 +- certbot-nginx/certbot_nginx/_internal/obj.py | 6 ++--- .../certbot_nginx/_internal/parser_obj.py | 6 ++--- certbot-nginx/tests/configurator_test.py | 4 ++-- certbot-nginx/tests/display_ops_test.py | 2 +- certbot-nginx/tests/http_01_test.py | 2 +- certbot-nginx/tests/test_util.py | 2 +- certbot/certbot/_internal/cli/cli_utils.py | 2 +- certbot/certbot/_internal/log.py | 16 +++++++------- certbot/certbot/_internal/plugins/manual.py | 2 +- .../certbot/_internal/plugins/standalone.py | 2 +- certbot/certbot/_internal/plugins/webroot.py | 4 ++-- certbot/certbot/_internal/snap_config.py | 4 ++-- certbot/certbot/display/util.py | 4 ++-- certbot/certbot/errors.py | 4 ++-- certbot/certbot/plugins/common.py | 2 +- certbot/certbot/plugins/dns_common.py | 2 +- certbot/certbot/tests/util.py | 2 +- certbot/tests/account_test.py | 2 +- certbot/tests/cert_manager_test.py | 10 ++++----- certbot/tests/client_test.py | 8 +++---- certbot/tests/compat/filesystem_test.py | 10 ++++----- certbot/tests/configuration_test.py | 2 +- certbot/tests/crypto_util_test.py | 6 ++--- certbot/tests/display/completer_test.py | 2 +- certbot/tests/display/ops_test.py | 2 +- certbot/tests/display/util_test.py | 2 +- certbot/tests/eff_test.py | 2 +- certbot/tests/error_handler_test.py | 2 +- certbot/tests/hook_test.py | 16 +++++++------- certbot/tests/lock_test.py | 2 +- certbot/tests/log_test.py | 6 ++--- certbot/tests/main_test.py | 16 +++++++------- certbot/tests/plugins/common_test.py | 4 ++-- .../tests/plugins/dns_common_lexicon_test.py | 2 +- certbot/tests/plugins/dns_common_test.py | 4 ++-- certbot/tests/plugins/enhancements_test.py | 2 +- certbot/tests/plugins/manual_test.py | 2 +- certbot/tests/plugins/selection_test.py | 2 +- certbot/tests/plugins/storage_test.py | 2 +- certbot/tests/renewupdater_test.py | 2 +- certbot/tests/reverter_test.py | 4 ++-- certbot/tests/storage_test.py | 6 ++--- certbot/tests/util_test.py | 8 +++---- 111 files changed, 263 insertions(+), 263 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 4fad9a421..2c8190be5 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -30,7 +30,7 @@ class Challenge(jose.TypedJSONObjectWithFields): @classmethod def from_json(cls, jobj): try: - return super(Challenge, cls).from_json(jobj) + return super().from_json(jobj) except jose.UnrecognizedTypeError as error: logger.debug(error) return UnrecognizedChallenge.from_json(jobj) @@ -58,7 +58,7 @@ class UnrecognizedChallenge(Challenge): """ def __init__(self, jobj): - super(UnrecognizedChallenge, self).__init__() + super().__init__() object.__setattr__(self, "jobj", jobj) def to_partial_json(self): @@ -141,7 +141,7 @@ class KeyAuthorizationChallengeResponse(ChallengeResponse): return True def to_partial_json(self): - jobj = super(KeyAuthorizationChallengeResponse, self).to_partial_json() + jobj = super().to_partial_json() jobj.pop('keyAuthorization', None) return jobj diff --git a/acme/acme/client.py b/acme/acme/client.py index ae4a64b23..548c3d548 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -253,7 +253,7 @@ class Client(ClientBase): if isinstance(directory, str): directory = messages.Directory.from_json( net.get(directory).json()) - super(Client, self).__init__(directory=directory, + super().__init__(directory=directory, net=net, acme_version=1) def register(self, new_reg=None): @@ -577,7 +577,7 @@ class ClientV2(ClientBase): :param .messages.Directory directory: Directory Resource :param .ClientNetwork net: Client network. """ - super(ClientV2, self).__init__(directory=directory, + super().__init__(directory=directory, net=net, acme_version=2) def new_account(self, new_account): @@ -627,7 +627,7 @@ class ClientV2(ClientBase): """ # https://github.com/certbot/certbot/issues/6155 new_regr = self._get_v2_account(regr) - return super(ClientV2, self).update_registration(new_regr, update) + return super().update_registration(new_regr, update) def _get_v2_account(self, regr): self.net.account = None diff --git a/acme/acme/errors.py b/acme/acme/errors.py index 84b7704dc..b47ed88da 100644 --- a/acme/acme/errors.py +++ b/acme/acme/errors.py @@ -29,7 +29,7 @@ class NonceError(ClientError): class BadNonce(NonceError): """Bad nonce error.""" def __init__(self, nonce, error, *args): - super(BadNonce, self).__init__(*args) + super().__init__(*args) self.nonce = nonce self.error = error @@ -48,7 +48,7 @@ class MissingNonce(NonceError): """ def __init__(self, response, *args): - super(MissingNonce, self).__init__(*args) + super().__init__(*args) self.response = response def __str__(self): @@ -72,7 +72,7 @@ class PollError(ClientError): def __init__(self, exhausted, updated): self.exhausted = exhausted self.updated = updated - super(PollError, self).__init__() + super().__init__() @property def timeout(self): @@ -90,7 +90,7 @@ class ValidationError(Error): """ def __init__(self, failed_authzrs): self.failed_authzrs = failed_authzrs - super(ValidationError, self).__init__() + super().__init__() class TimeoutError(Error): # pylint: disable=redefined-builtin @@ -106,7 +106,7 @@ class IssuanceError(Error): :param messages.Error error: The error provided by the server. """ self.error = error - super(IssuanceError, self).__init__() + super().__init__() class ConflictError(ClientError): @@ -119,7 +119,7 @@ class ConflictError(ClientError): """ def __init__(self, location): self.location = location - super(ConflictError, self).__init__() + super().__init__() class WildcardUnsupportedError(Error): diff --git a/acme/acme/fields.py b/acme/acme/fields.py index 3b5672283..bd915e47d 100644 --- a/acme/acme/fields.py +++ b/acme/acme/fields.py @@ -12,7 +12,7 @@ class Fixed(jose.Field): def __init__(self, json_name, value): self.value = value - super(Fixed, self).__init__( + super().__init__( json_name=json_name, default=value, omitempty=False) def decode(self, value): @@ -53,7 +53,7 @@ class Resource(jose.Field): def __init__(self, resource_type, *args, **kwargs): self.resource_type = resource_type - super(Resource, self).__init__( + super().__init__( 'resource', default=resource_type, *args, **kwargs) def decode(self, value): diff --git a/acme/acme/jws.py b/acme/acme/jws.py index 7eccf0fdf..d9d3e12c3 100644 --- a/acme/acme/jws.py +++ b/acme/acme/jws.py @@ -50,7 +50,7 @@ class JWS(jose.JWS): # Per ACME spec, jwk and kid are mutually exclusive, so only include a # jwk field if kid is not provided. include_jwk = kid is None - return super(JWS, cls).sign(payload, key=key, alg=alg, + return super().sign(payload, key=key, alg=alg, protect=frozenset(['nonce', 'url', 'kid', 'jwk', 'alg']), nonce=nonce, url=url, kid=kid, include_jwk=include_jwk) diff --git a/acme/acme/messages.py b/acme/acme/messages.py index c8b971b8f..36207dba0 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -132,7 +132,7 @@ class _Constant(jose.JSONDeSerializable, Hashable): # type: ignore POSSIBLE_NAMES: Dict[str, '_Constant'] = NotImplemented def __init__(self, name): - super(_Constant, self).__init__() + super().__init__() self.POSSIBLE_NAMES[name] = self # pylint: disable=unsupported-assignment-operation self.name = name @@ -201,7 +201,7 @@ class Directory(jose.JSONDeSerializable): def __init__(self, **kwargs): kwargs = {self._internal_name(k): v for k, v in kwargs.items()} - super(Directory.Meta, self).__init__(**kwargs) + super().__init__(**kwargs) @property def terms_of_service(self): @@ -211,7 +211,7 @@ class Directory(jose.JSONDeSerializable): def __iter__(self): # When iterating over fields, use the external name 'terms_of_service' instead of # the internal '_terms_of_service'. - for name in super(Directory.Meta, self).__iter__(): + for name in super().__iter__(): yield name[1:] if name == '_terms_of_service' else name def _internal_name(self, name): @@ -357,7 +357,7 @@ class Registration(ResourceBody): if 'contact' in kwargs: # Avoid the __setattr__ used by jose.TypedJSONObjectWithFields object.__setattr__(self, '_add_contact', True) - super(Registration, self).__init__(**kwargs) + super().__init__(**kwargs) def _filter_contact(self, prefix): return tuple( @@ -383,12 +383,12 @@ class Registration(ResourceBody): def to_partial_json(self): """Modify josepy.JSONDeserializable.to_partial_json()""" - jobj = super(Registration, self).to_partial_json() + jobj = super().to_partial_json() return self._add_contact_if_appropriate(jobj) def fields_to_partial_json(self): """Modify josepy.JSONObjectWithFields.fields_to_partial_json()""" - jobj = super(Registration, self).fields_to_partial_json() + jobj = super().fields_to_partial_json() return self._add_contact_if_appropriate(jobj) @property @@ -460,19 +460,19 @@ class ChallengeBody(ResourceBody): def __init__(self, **kwargs): kwargs = {self._internal_name(k): v for k, v in kwargs.items()} - super(ChallengeBody, self).__init__(**kwargs) + super().__init__(**kwargs) def encode(self, name): - return super(ChallengeBody, self).encode(self._internal_name(name)) + return super().encode(self._internal_name(name)) def to_partial_json(self): - jobj = super(ChallengeBody, self).to_partial_json() + jobj = super().to_partial_json() jobj.update(self.chall.to_partial_json()) return jobj @classmethod def fields_from_json(cls, jobj): - jobj_fields = super(ChallengeBody, cls).fields_from_json(jobj) + jobj_fields = super().fields_from_json(jobj) jobj_fields['chall'] = challenges.Challenge.from_json(jobj) return jobj_fields @@ -487,7 +487,7 @@ class ChallengeBody(ResourceBody): def __iter__(self): # When iterating over fields, use the external name 'uri' instead of # the internal '_uri'. - for name in super(ChallengeBody, self).__iter__(): + for name in super().__iter__(): yield name[1:] if name == '_uri' else name def _internal_name(self, name): diff --git a/acme/acme/mixins.py b/acme/acme/mixins.py index 0e1e0977c..6d58e0889 100644 --- a/acme/acme/mixins.py +++ b/acme/acme/mixins.py @@ -20,7 +20,7 @@ class VersionedLEACMEMixin: # Required for @property to operate properly. See comment above. object.__setattr__(self, key, value) else: - super(VersionedLEACMEMixin, self).__setattr__(key, value) # pragma: no cover + super().__setattr__(key, value) # pragma: no cover class ResourceMixin(VersionedLEACMEMixin): @@ -30,12 +30,12 @@ class ResourceMixin(VersionedLEACMEMixin): """ def to_partial_json(self): """See josepy.JSONDeserializable.to_partial_json()""" - return _safe_jobj_compliance(super(ResourceMixin, self), + return _safe_jobj_compliance(super(), 'to_partial_json', 'resource') def fields_to_partial_json(self): """See josepy.JSONObjectWithFields.fields_to_partial_json()""" - return _safe_jobj_compliance(super(ResourceMixin, self), + return _safe_jobj_compliance(super(), 'fields_to_partial_json', 'resource') @@ -46,12 +46,12 @@ class TypeMixin(VersionedLEACMEMixin): """ def to_partial_json(self): """See josepy.JSONDeserializable.to_partial_json()""" - return _safe_jobj_compliance(super(TypeMixin, self), + return _safe_jobj_compliance(super(), 'to_partial_json', 'type') def fields_to_partial_json(self): """See josepy.JSONObjectWithFields.fields_to_partial_json()""" - return _safe_jobj_compliance(super(TypeMixin, self), + return _safe_jobj_compliance(super(), 'fields_to_partial_json', 'type') diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index 6addb09f3..89e66c6d6 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -90,7 +90,7 @@ class BackwardsCompatibleClientV2Test(ClientTestBase): """Tests for acme.client.BackwardsCompatibleClientV2.""" def setUp(self): - super(BackwardsCompatibleClientV2Test, self).setUp() + super().setUp() # contains a loaded cert self.certr = messages.CertificateResource( body=messages_test.CERT) @@ -319,7 +319,7 @@ class ClientTest(ClientTestBase): """Tests for acme.client.Client.""" def setUp(self): - super(ClientTest, self).setUp() + super().setUp() self.directory = DIRECTORY_V1 @@ -716,7 +716,7 @@ class ClientV2Test(ClientTestBase): """Tests for acme.client.ClientV2.""" def setUp(self): - super(ClientV2Test, self).setUp() + super().setUp() self.directory = DIRECTORY_V2 diff --git a/certbot-apache/certbot_apache/_internal/apacheparser.py b/certbot-apache/certbot_apache/_internal/apacheparser.py index adfbc4442..d3bd1a4bf 100644 --- a/certbot-apache/certbot_apache/_internal/apacheparser.py +++ b/certbot-apache/certbot_apache/_internal/apacheparser.py @@ -15,7 +15,7 @@ class ApacheParserNode(interfaces.ParserNode): def __init__(self, **kwargs): ancestor, dirty, filepath, metadata = util.parsernode_kwargs(kwargs) # pylint: disable=unused-variable - super(ApacheParserNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.ancestor = ancestor self.filepath = filepath self.dirty = dirty @@ -39,7 +39,7 @@ class ApacheCommentNode(ApacheParserNode): def __init__(self, **kwargs): comment, kwargs = util.commentnode_kwargs(kwargs) # pylint: disable=unused-variable - super(ApacheCommentNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.comment = comment def __eq__(self, other): # pragma: no cover @@ -57,7 +57,7 @@ class ApacheDirectiveNode(ApacheParserNode): def __init__(self, **kwargs): name, parameters, enabled, kwargs = util.directivenode_kwargs(kwargs) - super(ApacheDirectiveNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.name = name self.parameters = parameters self.enabled = enabled @@ -83,7 +83,7 @@ class ApacheBlockNode(ApacheDirectiveNode): """ apacheconfig implementation of BlockNode interface """ def __init__(self, **kwargs): - super(ApacheBlockNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.children: Tuple[ApacheParserNode, ...] = () def __eq__(self, other): # pragma: no cover diff --git a/certbot-apache/certbot_apache/_internal/augeasparser.py b/certbot-apache/certbot_apache/_internal/augeasparser.py index 4549e935a..896e17cf8 100644 --- a/certbot-apache/certbot_apache/_internal/augeasparser.py +++ b/certbot-apache/certbot_apache/_internal/augeasparser.py @@ -80,7 +80,7 @@ class AugeasParserNode(interfaces.ParserNode): def __init__(self, **kwargs): ancestor, dirty, filepath, metadata = util.parsernode_kwargs(kwargs) # pylint: disable=unused-variable - super(AugeasParserNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.ancestor = ancestor self.filepath = filepath self.dirty = dirty @@ -169,7 +169,7 @@ class AugeasCommentNode(AugeasParserNode): def __init__(self, **kwargs): comment, kwargs = util.commentnode_kwargs(kwargs) # pylint: disable=unused-variable - super(AugeasCommentNode, self).__init__(**kwargs) + super().__init__(**kwargs) # self.comment = comment self.comment = comment @@ -188,7 +188,7 @@ class AugeasDirectiveNode(AugeasParserNode): def __init__(self, **kwargs): name, parameters, enabled, kwargs = util.directivenode_kwargs(kwargs) - super(AugeasDirectiveNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.name = name self.enabled = enabled if parameters: @@ -245,7 +245,7 @@ class AugeasBlockNode(AugeasDirectiveNode): """ Augeas implementation of BlockNode interface """ def __init__(self, **kwargs): - super(AugeasBlockNode, self).__init__(**kwargs) + super().__init__(**kwargs) self.children = () def __eq__(self, other): diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index 28f73b32d..5ef9083e6 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -214,7 +214,7 @@ class ApacheConfigurator(common.Installer): version = kwargs.pop("version", None) use_parsernode = kwargs.pop("use_parsernode", False) openssl_version = kwargs.pop("openssl_version", None) - super(ApacheConfigurator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Add name_server association dict self.assoc: Dict[str, obj.VirtualHost] = {} @@ -410,7 +410,7 @@ class ApacheConfigurator(common.Installer): :raises .errors.PluginError: If unable to recover the configuration """ - super(ApacheConfigurator, self).recovery_routine() + super().recovery_routine() # Reload configuration after these changes take effect if needed # ie. ApacheParser has been initialized. if hasattr(self, "parser"): @@ -435,7 +435,7 @@ class ApacheConfigurator(common.Installer): the function is unable to correctly revert the configuration """ - super(ApacheConfigurator, self).rollback_checkpoints(rollback) + super().rollback_checkpoints(rollback) self.parser.aug.load() def _verify_exe_availability(self, exe): diff --git a/certbot-apache/certbot_apache/_internal/http_01.py b/certbot-apache/certbot_apache/_internal/http_01.py index 66d888e97..83a1a8e08 100644 --- a/certbot-apache/certbot_apache/_internal/http_01.py +++ b/certbot-apache/certbot_apache/_internal/http_01.py @@ -47,7 +47,7 @@ class ApacheHttp01(common.ChallengePerformer): """ def __init__(self, *args, **kwargs): - super(ApacheHttp01, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.challenge_conf_pre = os.path.join( self.configurator.conf("challenge-location"), "le_http_01_challenge_pre.conf") diff --git a/certbot-apache/certbot_apache/_internal/interfaces.py b/certbot-apache/certbot_apache/_internal/interfaces.py index 38c21b785..106e2778a 100644 --- a/certbot-apache/certbot_apache/_internal/interfaces.py +++ b/certbot-apache/certbot_apache/_internal/interfaces.py @@ -238,7 +238,7 @@ class CommentNode(ParserNode, metaclass=abc.ABCMeta): created or changed after the last save. Default: False. :type dirty: bool """ - super(CommentNode, self).__init__(ancestor=kwargs['ancestor'], + super().__init__(ancestor=kwargs['ancestor'], dirty=kwargs.get('dirty', False), filepath=kwargs['filepath'], metadata=kwargs.get('metadata', {})) # pragma: no cover @@ -302,7 +302,7 @@ class DirectiveNode(ParserNode, metaclass=abc.ABCMeta): :type enabled: bool """ - super(DirectiveNode, self).__init__(ancestor=kwargs['ancestor'], + super().__init__(ancestor=kwargs['ancestor'], dirty=kwargs.get('dirty', False), filepath=kwargs['filepath'], metadata=kwargs.get('metadata', {})) # pragma: no cover diff --git a/certbot-apache/certbot_apache/_internal/obj.py b/certbot-apache/certbot_apache/_internal/obj.py index 21fd042f6..9001a860d 100644 --- a/certbot-apache/certbot_apache/_internal/obj.py +++ b/certbot-apache/certbot_apache/_internal/obj.py @@ -26,7 +26,7 @@ class Addr(common.Addr): def __hash__(self): # pylint: disable=useless-super-delegation # Python 3 requires explicit overridden for __hash__ if __eq__ or # __cmp__ is overridden. See https://bugs.python.org/issue2235 - return super(Addr, self).__hash__() + return super().__hash__() def _addr_less_specific(self, addr): """Returns if addr.get_addr() is more specific than self.get_addr().""" diff --git a/certbot-apache/certbot_apache/_internal/override_centos.py b/certbot-apache/certbot_apache/_internal/override_centos.py index bd9a47b52..98dc80e0b 100644 --- a/certbot-apache/certbot_apache/_internal/override_centos.py +++ b/certbot-apache/certbot_apache/_internal/override_centos.py @@ -51,7 +51,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator): fedora = os_info[0].lower() == "fedora" try: - super(CentOSConfigurator, self).config_test() + super().config_test() except errors.MisconfigurationError: if fedora: self._try_restart_fedora() @@ -69,14 +69,14 @@ class CentOSConfigurator(configurator.ApacheConfigurator): raise errors.MisconfigurationError(str(err)) # Finish with actual config check to see if systemctl restart helped - super(CentOSConfigurator, self).config_test() + super().config_test() def _prepare_options(self): """ Override the options dictionary initialization in order to support alternative restart cmd used in CentOS. """ - super(CentOSConfigurator, self)._prepare_options() + super()._prepare_options() cast(List[str], self.options["restart_cmd_alt"])[0] = self.option("ctl") def get_parser(self): @@ -91,7 +91,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator): has "LoadModule ssl_module..." before parsing the VirtualHost configuration that was created by Certbot """ - super(CentOSConfigurator, self)._deploy_cert(*args, **kwargs) + super()._deploy_cert(*args, **kwargs) if self.version < (2, 4, 0): self._deploy_loadmodule_ssl_if_needed() @@ -169,12 +169,12 @@ class CentOSParser(parser.ApacheParser): def __init__(self, *args, **kwargs): # CentOS specific configuration file for Apache self.sysconfig_filep = "/etc/sysconfig/httpd" - super(CentOSParser, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def update_runtime_variables(self): """ Override for update_runtime_variables for custom parsing """ # Opportunistic, works if SELinux not enforced - super(CentOSParser, self).update_runtime_variables() + super().update_runtime_variables() self.parse_sysconfig_var() def parse_sysconfig_var(self): diff --git a/certbot-apache/certbot_apache/_internal/override_debian.py b/certbot-apache/certbot_apache/_internal/override_debian.py index 9f938046b..c5f3b6e1a 100644 --- a/certbot-apache/certbot_apache/_internal/override_debian.py +++ b/certbot-apache/certbot_apache/_internal/override_debian.py @@ -58,7 +58,7 @@ class DebianConfigurator(configurator.ApacheConfigurator): if not os.path.isdir(os.path.dirname(enabled_path)): # For some reason, sites-enabled / sites-available do not exist # Call the parent method - return super(DebianConfigurator, self).enable_site(vhost) + return super().enable_site(vhost) self.reverter.register_file_creation(False, enabled_path) try: os.symlink(vhost.filep, enabled_path) diff --git a/certbot-apache/certbot_apache/_internal/override_fedora.py b/certbot-apache/certbot_apache/_internal/override_fedora.py index 0dc3df66b..0f7970460 100644 --- a/certbot-apache/certbot_apache/_internal/override_fedora.py +++ b/certbot-apache/certbot_apache/_internal/override_fedora.py @@ -43,7 +43,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): during the first (re)start of httpd. """ try: - super(FedoraConfigurator, self).config_test() + super().config_test() except errors.MisconfigurationError: self._try_restart_fedora() @@ -63,7 +63,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): raise errors.MisconfigurationError(str(err)) # Finish with actual config check to see if systemctl restart helped - super(FedoraConfigurator, self).config_test() + super().config_test() def _prepare_options(self): """ @@ -71,7 +71,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): instead of httpd and so take advantages of this new bash script in newer versions of Fedora to restart httpd. """ - super(FedoraConfigurator, self)._prepare_options() + super()._prepare_options() cast(List[str], self.options["restart_cmd"])[0] = 'apachectl' cast(List[str], self.options["restart_cmd_alt"])[0] = 'apachectl' cast(List[str], self.options["conftest_cmd"])[0] = 'apachectl' @@ -82,12 +82,12 @@ class FedoraParser(parser.ApacheParser): def __init__(self, *args, **kwargs): # Fedora 29+ specific configuration file for Apache self.sysconfig_filep = "/etc/sysconfig/httpd" - super(FedoraParser, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def update_runtime_variables(self): """ Override for update_runtime_variables for custom parsing """ # Opportunistic, works if SELinux not enforced - super(FedoraParser, self).update_runtime_variables() + super().update_runtime_variables() self._parse_sysconfig_var() def _parse_sysconfig_var(self): diff --git a/certbot-apache/certbot_apache/_internal/override_gentoo.py b/certbot-apache/certbot_apache/_internal/override_gentoo.py index 773fdd568..484e15532 100644 --- a/certbot-apache/certbot_apache/_internal/override_gentoo.py +++ b/certbot-apache/certbot_apache/_internal/override_gentoo.py @@ -38,7 +38,7 @@ class GentooConfigurator(configurator.ApacheConfigurator): Override the options dictionary initialization in order to support alternative restart cmd used in Gentoo. """ - super(GentooConfigurator, self)._prepare_options() + super()._prepare_options() cast(List[str], self.options["restart_cmd_alt"])[0] = self.option("ctl") def get_parser(self): @@ -53,7 +53,7 @@ class GentooParser(parser.ApacheParser): def __init__(self, *args, **kwargs): # Gentoo specific configuration file for Apache2 self.apacheconfig_filep = "/etc/conf.d/apache2" - super(GentooParser, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def update_runtime_variables(self): """ Override for update_runtime_variables for custom parsing """ diff --git a/certbot-apache/tests/augeasnode_test.py b/certbot-apache/tests/augeasnode_test.py index 42126a5a9..85a17ab31 100644 --- a/certbot-apache/tests/augeasnode_test.py +++ b/certbot-apache/tests/augeasnode_test.py @@ -29,7 +29,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- """Test AugeasParserNode using available test configurations""" def setUp(self): # pylint: disable=arguments-differ - super(AugeasParserNodeTest, self).setUp() + super().setUp() with mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.get_parsernode_root") as mock_parsernode: mock_parsernode.side_effect = _get_augeasnode_mock( diff --git a/certbot-apache/tests/autohsts_test.py b/certbot-apache/tests/autohsts_test.py index db1c46b52..8c8ba4873 100644 --- a/certbot-apache/tests/autohsts_test.py +++ b/certbot-apache/tests/autohsts_test.py @@ -18,7 +18,7 @@ class AutoHSTSTest(util.ApacheTest): # pylint: disable=protected-access def setUp(self): # pylint: disable=arguments-differ - super(AutoHSTSTest, self).setUp() + super().setUp() self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir) diff --git a/certbot-apache/tests/centos6_test.py b/certbot-apache/tests/centos6_test.py index 27b4f8e80..bfbe22ad0 100644 --- a/certbot-apache/tests/centos6_test.py +++ b/certbot-apache/tests/centos6_test.py @@ -36,9 +36,9 @@ class CentOS6Tests(util.ApacheTest): test_dir = "centos6_apache/apache" config_root = "centos6_apache/apache/httpd" vhost_root = "centos6_apache/apache/httpd/conf.d" - super(CentOS6Tests, self).setUp(test_dir=test_dir, - config_root=config_root, - vhost_root=vhost_root) + super().setUp(test_dir=test_dir, + config_root=config_root, + vhost_root=vhost_root) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, diff --git a/certbot-apache/tests/centos_test.py b/certbot-apache/tests/centos_test.py index b7e9c1cb6..a92c37979 100644 --- a/certbot-apache/tests/centos_test.py +++ b/certbot-apache/tests/centos_test.py @@ -41,9 +41,9 @@ class FedoraRestartTest(util.ApacheTest): test_dir = "centos7_apache/apache" config_root = "centos7_apache/apache/httpd" vhost_root = "centos7_apache/apache/httpd/conf.d" - super(FedoraRestartTest, self).setUp(test_dir=test_dir, - config_root=config_root, - vhost_root=vhost_root) + super().setUp(test_dir=test_dir, + config_root=config_root, + vhost_root=vhost_root) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, os_info="fedora_old") @@ -96,9 +96,9 @@ class MultipleVhostsTestCentOS(util.ApacheTest): test_dir = "centos7_apache/apache" config_root = "centos7_apache/apache/httpd" vhost_root = "centos7_apache/apache/httpd/conf.d" - super(MultipleVhostsTestCentOS, self).setUp(test_dir=test_dir, - config_root=config_root, - vhost_root=vhost_root) + super().setUp(test_dir=test_dir, + config_root=config_root, + vhost_root=vhost_root) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, diff --git a/certbot-apache/tests/complex_parsing_test.py b/certbot-apache/tests/complex_parsing_test.py index 8b795b0b6..e36bd85d1 100644 --- a/certbot-apache/tests/complex_parsing_test.py +++ b/certbot-apache/tests/complex_parsing_test.py @@ -11,7 +11,7 @@ class ComplexParserTest(util.ParserTest): """Apache Parser Test.""" def setUp(self): # pylint: disable=arguments-differ - super(ComplexParserTest, self).setUp( + super().setUp( "complex_parsing", "complex_parsing") self.setup_variables() diff --git a/certbot-apache/tests/configurator_reverter_test.py b/certbot-apache/tests/configurator_reverter_test.py index 8596195d8..d8f5ddd05 100644 --- a/certbot-apache/tests/configurator_reverter_test.py +++ b/certbot-apache/tests/configurator_reverter_test.py @@ -16,7 +16,7 @@ class ConfiguratorReverterTest(util.ApacheTest): def setUp(self): # pylint: disable=arguments-differ - super(ConfiguratorReverterTest, self).setUp() + super().setUp() self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir) diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py index 302bf0023..ad1f5f04d 100644 --- a/certbot-apache/tests/configurator_test.py +++ b/certbot-apache/tests/configurator_test.py @@ -30,7 +30,7 @@ class MultipleVhostsTest(util.ApacheTest): """Test two standard well-configured HTTP vhosts.""" def setUp(self): # pylint: disable=arguments-differ - super(MultipleVhostsTest, self).setUp() + super().setUp() self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir) @@ -1477,9 +1477,9 @@ class AugeasVhostsTest(util.ApacheTest): td = "debian_apache_2_4/augeas_vhosts" cr = "debian_apache_2_4/augeas_vhosts/apache2" vr = "debian_apache_2_4/augeas_vhosts/apache2/sites-available" - super(AugeasVhostsTest, self).setUp(test_dir=td, - config_root=cr, - vhost_root=vr) + super().setUp(test_dir=td, + config_root=cr, + vhost_root=vr) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, @@ -1556,9 +1556,9 @@ class MultiVhostsTest(util.ApacheTest): td = "debian_apache_2_4/multi_vhosts" cr = "debian_apache_2_4/multi_vhosts/apache2" vr = "debian_apache_2_4/multi_vhosts/apache2/sites-available" - super(MultiVhostsTest, self).setUp(test_dir=td, - config_root=cr, - vhost_root=vr) + super().setUp(test_dir=td, + config_root=cr, + vhost_root=vr) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, @@ -1661,7 +1661,7 @@ class InstallSslOptionsConfTest(util.ApacheTest): """Test that the options-ssl-nginx.conf file is installed and updated properly.""" def setUp(self): # pylint: disable=arguments-differ - super(InstallSslOptionsConfTest, self).setUp() + super().setUp() self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir) diff --git a/certbot-apache/tests/debian_test.py b/certbot-apache/tests/debian_test.py index 192e3cba5..c72b8b6ae 100644 --- a/certbot-apache/tests/debian_test.py +++ b/certbot-apache/tests/debian_test.py @@ -20,7 +20,7 @@ class MultipleVhostsTestDebian(util.ApacheTest): _multiprocess_can_split_ = True def setUp(self): # pylint: disable=arguments-differ - super(MultipleVhostsTestDebian, self).setUp() + super().setUp() self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, os_info="debian") diff --git a/certbot-apache/tests/fedora_test.py b/certbot-apache/tests/fedora_test.py index 50831802b..d48559cee 100644 --- a/certbot-apache/tests/fedora_test.py +++ b/certbot-apache/tests/fedora_test.py @@ -46,9 +46,9 @@ class FedoraRestartTest(util.ApacheTest): test_dir = "centos7_apache/apache" config_root = "centos7_apache/apache/httpd" vhost_root = "centos7_apache/apache/httpd/conf.d" - super(FedoraRestartTest, self).setUp(test_dir=test_dir, - config_root=config_root, - vhost_root=vhost_root) + super().setUp(test_dir=test_dir, + config_root=config_root, + vhost_root=vhost_root) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, os_info="fedora") @@ -90,9 +90,9 @@ class MultipleVhostsTestFedora(util.ApacheTest): test_dir = "centos7_apache/apache" config_root = "centos7_apache/apache/httpd" vhost_root = "centos7_apache/apache/httpd/conf.d" - super(MultipleVhostsTestFedora, self).setUp(test_dir=test_dir, - config_root=config_root, - vhost_root=vhost_root) + super().setUp(test_dir=test_dir, + config_root=config_root, + vhost_root=vhost_root) self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, diff --git a/certbot-apache/tests/gentoo_test.py b/certbot-apache/tests/gentoo_test.py index 64f7d1062..cf39ff5cb 100644 --- a/certbot-apache/tests/gentoo_test.py +++ b/certbot-apache/tests/gentoo_test.py @@ -50,9 +50,9 @@ class MultipleVhostsTestGentoo(util.ApacheTest): test_dir = "gentoo_apache/apache" config_root = "gentoo_apache/apache/apache2" vhost_root = "gentoo_apache/apache/apache2/vhosts.d" - super(MultipleVhostsTestGentoo, self).setUp(test_dir=test_dir, - config_root=config_root, - vhost_root=vhost_root) + super().setUp(test_dir=test_dir, + config_root=config_root, + vhost_root=vhost_root) # pylint: disable=line-too-long with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_runtime_variables"): diff --git a/certbot-apache/tests/http_01_test.py b/certbot-apache/tests/http_01_test.py index 9d66c3aa0..71f2db500 100644 --- a/certbot-apache/tests/http_01_test.py +++ b/certbot-apache/tests/http_01_test.py @@ -24,7 +24,7 @@ class ApacheHttp01Test(util.ApacheTest): """Test for certbot_apache._internal.http_01.ApacheHttp01.""" def setUp(self, *args, **kwargs): # pylint: disable=arguments-differ - super(ApacheHttp01Test, self).setUp(*args, **kwargs) + super().setUp(*args, **kwargs) self.account_key = self.rsa512jwk self.achalls: List[achallenges.KeyAuthorizationAnnotatedChallenge] = [] diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py index 2eff9a9dd..37d4eb782 100644 --- a/certbot-apache/tests/parser_test.py +++ b/certbot-apache/tests/parser_test.py @@ -16,7 +16,7 @@ class BasicParserTest(util.ParserTest): """Apache Parser Test.""" def setUp(self): # pylint: disable=arguments-differ - super(BasicParserTest, self).setUp() + super().setUp() def tearDown(self): shutil.rmtree(self.temp_dir) @@ -332,7 +332,7 @@ class BasicParserTest(util.ParserTest): class ParserInitTest(util.ApacheTest): def setUp(self): # pylint: disable=arguments-differ - super(ParserInitTest, self).setUp() + super().setUp() def tearDown(self): shutil.rmtree(self.temp_dir) diff --git a/certbot-apache/tests/parsernode_configurator_test.py b/certbot-apache/tests/parsernode_configurator_test.py index 7fbec2540..411871a43 100644 --- a/certbot-apache/tests/parsernode_configurator_test.py +++ b/certbot-apache/tests/parsernode_configurator_test.py @@ -20,7 +20,7 @@ class ConfiguratorParserNodeTest(util.ApacheTest): # pylint: disable=too-many-p """Test AugeasParserNode using available test configurations""" def setUp(self): # pylint: disable=arguments-differ - super(ConfiguratorParserNodeTest, self).setUp() + super().setUp() self.config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, diff --git a/certbot-apache/tests/parsernode_test.py b/certbot-apache/tests/parsernode_test.py index a86952f53..4ea5f8415 100644 --- a/certbot-apache/tests/parsernode_test.py +++ b/certbot-apache/tests/parsernode_test.py @@ -18,7 +18,7 @@ class DummyParserNode(interfaces.ParserNode): self.dirty = dirty self.filepath = filepath self.metadata = metadata - super(DummyParserNode, self).__init__(**kwargs) + super().__init__(**kwargs) def save(self, msg): # pragma: no cover """Save""" @@ -38,7 +38,7 @@ class DummyCommentNode(DummyParserNode): """ comment, kwargs = util.commentnode_kwargs(kwargs) self.comment = comment - super(DummyCommentNode, self).__init__(**kwargs) + super().__init__(**kwargs) class DummyDirectiveNode(DummyParserNode): @@ -54,7 +54,7 @@ class DummyDirectiveNode(DummyParserNode): self.parameters = parameters self.enabled = enabled - super(DummyDirectiveNode, self).__init__(**kwargs) + super().__init__(**kwargs) def set_parameters(self, parameters): # pragma: no cover """Set parameters""" diff --git a/certbot-apache/tests/util.py b/certbot-apache/tests/util.py index 18c7e5aca..bd522d736 100644 --- a/certbot-apache/tests/util.py +++ b/certbot-apache/tests/util.py @@ -67,7 +67,7 @@ class ParserTest(ApacheTest): def setUp(self, test_dir="debian_apache_2_4/multiple_vhosts", config_root="debian_apache_2_4/multiple_vhosts/apache2", vhost_root="debian_apache_2_4/multiple_vhosts/apache2/sites-available"): - super(ParserTest, self).setUp(test_dir, config_root, vhost_root) + super().setUp(test_dir, config_root, vhost_root) zope.component.provideUtility(display_util.FileDisplay(sys.stdout, False)) diff --git a/certbot-ci/certbot_integration_tests/nginx_tests/context.py b/certbot-ci/certbot_integration_tests/nginx_tests/context.py index 6f0f833a0..3ee1766a1 100644 --- a/certbot-ci/certbot_integration_tests/nginx_tests/context.py +++ b/certbot-ci/certbot_integration_tests/nginx_tests/context.py @@ -11,7 +11,7 @@ from certbot_integration_tests.utils import misc class IntegrationTestsContext(certbot_context.IntegrationTestsContext): """General fixture describing a certbot-nginx integration tests context""" def __init__(self, request): - super(IntegrationTestsContext, self).__init__(request) + super().__init__(request) self.nginx_root = os.path.join(self.workspace, 'nginx') os.mkdir(self.nginx_root) @@ -29,7 +29,7 @@ class IntegrationTestsContext(certbot_context.IntegrationTestsContext): def cleanup(self): self._stop_nginx() - super(IntegrationTestsContext, self).cleanup() + super().cleanup() def certbot_test_nginx(self, args): """ diff --git a/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py b/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py index a4f62b5e4..3d4147313 100644 --- a/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py +++ b/certbot-ci/certbot_integration_tests/rfc2136_tests/context.py @@ -13,7 +13,7 @@ from certbot_integration_tests.utils import certbot_call class IntegrationTestsContext(certbot_context.IntegrationTestsContext): """Integration test context for certbot-dns-rfc2136""" def __init__(self, request): - super(IntegrationTestsContext, self).__init__(request) + super().__init__(request) self.request = request diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index 2b3f94581..f62635610 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -22,7 +22,7 @@ class Proxy(configurators_common.Proxy): def __init__(self, args): """Initializes the plugin with the given command line args""" - super(Proxy, self).__init__(args) + super().__init__(args) self.le_config.apache_le_vhost_ext = "-le-ssl.conf" self.modules = self.server_root = self.test_conf = self.version = None @@ -34,7 +34,7 @@ class Proxy(configurators_common.Proxy): def load_config(self): """Loads the next configuration for the plugin to test""" - config = super(Proxy, self).load_config() + config = super().load_config() self._all_names, self._test_names = _get_names(config) server_root = _get_server_root(config) @@ -65,7 +65,7 @@ class Proxy(configurators_common.Proxy): def cleanup_from_tests(self): """Performs any necessary cleanup from running plugin tests""" - super(Proxy, self).cleanup_from_tests() + super().cleanup_from_tests() mock.patch.stopall() diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index d7b7a120e..e209480e3 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -21,7 +21,7 @@ class Proxy(configurators_common.Proxy): def load_config(self): """Loads the next configuration for the plugin to test""" - config = super(Proxy, self).load_config() + config = super().load_config() self._all_names, self._test_names = _get_names(config) server_root = _get_server_root(config) diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py index ceee39f86..8f42b3ce9 100644 --- a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py +++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py @@ -31,12 +31,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 120 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add) + super().add_parser_arguments(add) add('credentials', help='Cloudflare credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring diff --git a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py index e9adf4ed9..d7075a84d 100644 --- a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py +++ b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py @@ -27,7 +27,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic def setUp(self): from certbot_dns_cloudflare._internal.dns_cloudflare import Authenticator - super(AuthenticatorTest, self).setUp() + super().setUp() path = os.path.join(self.tempdir, 'file.ini') dns_test_common.write({"cloudflare_email": EMAIL, "cloudflare_api_key": API_KEY}, path) diff --git a/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py b/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py index 7fe52b618..1ec5cb5ab 100644 --- a/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py +++ b/certbot-dns-cloudxns/certbot_dns_cloudxns/_internal/dns_cloudxns.py @@ -28,12 +28,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) + super().add_parser_arguments(add, default_propagation_seconds=30) add('credentials', help='CloudXNS credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -71,7 +71,7 @@ class _CloudXNSLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, api_key, secret_key, ttl): - super(_CloudXNSLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('cloudxns', { 'ttl': ttl, diff --git a/certbot-dns-cloudxns/tests/dns_cloudxns_test.py b/certbot-dns-cloudxns/tests/dns_cloudxns_test.py index 43c69790f..81dea5ca4 100644 --- a/certbot-dns-cloudxns/tests/dns_cloudxns_test.py +++ b/certbot-dns-cloudxns/tests/dns_cloudxns_test.py @@ -26,7 +26,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_cloudxns._internal.dns_cloudxns import Authenticator diff --git a/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py b/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py index 85eb1159e..23b669847 100644 --- a/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py +++ b/certbot-dns-digitalocean/certbot_dns_digitalocean/_internal/dns_digitalocean.py @@ -26,12 +26,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 30 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add) + super().add_parser_arguments(add) add('credentials', help='DigitalOcean credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring diff --git a/certbot-dns-digitalocean/tests/dns_digitalocean_test.py b/certbot-dns-digitalocean/tests/dns_digitalocean_test.py index 84bb35b1f..6088262ee 100644 --- a/certbot-dns-digitalocean/tests/dns_digitalocean_test.py +++ b/certbot-dns-digitalocean/tests/dns_digitalocean_test.py @@ -23,7 +23,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic def setUp(self): from certbot_dns_digitalocean._internal.dns_digitalocean import Authenticator - super(AuthenticatorTest, self).setUp() + super().setUp() path = os.path.join(self.tempdir, 'file.ini') dns_test_common.write({"digitalocean_token": TOKEN}, path) diff --git a/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py b/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py index 318bc25fb..858ee8925 100644 --- a/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py +++ b/certbot-dns-dnsimple/certbot_dns_dnsimple/_internal/dns_dnsimple.py @@ -28,12 +28,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) + super().add_parser_arguments(add, default_propagation_seconds=30) add('credentials', help='DNSimple credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -67,7 +67,7 @@ class _DNSimpleLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, token, ttl): - super(_DNSimpleLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('dnssimple', { 'ttl': ttl, diff --git a/certbot-dns-dnsimple/tests/dns_dnsimple_test.py b/certbot-dns-dnsimple/tests/dns_dnsimple_test.py index 40eba4754..fc3dc5b1f 100644 --- a/certbot-dns-dnsimple/tests/dns_dnsimple_test.py +++ b/certbot-dns-dnsimple/tests/dns_dnsimple_test.py @@ -20,7 +20,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_dnsimple._internal.dns_dnsimple import Authenticator diff --git a/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py b/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py index 3a805f507..67903e19d 100644 --- a/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py +++ b/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/_internal/dns_dnsmadeeasy.py @@ -29,12 +29,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=60) + super().add_parser_arguments(add, default_propagation_seconds=60) add('credentials', help='DNS Made Easy credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -73,7 +73,7 @@ class _DNSMadeEasyLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, api_key, secret_key, ttl): - super(_DNSMadeEasyLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('dnsmadeeasy', { 'ttl': ttl, diff --git a/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py b/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py index 4a69e977c..a04716d95 100644 --- a/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py +++ b/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py @@ -22,7 +22,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_dnsmadeeasy._internal.dns_dnsmadeeasy import Authenticator diff --git a/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py b/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py index dd9665c2f..57ff01671 100644 --- a/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py +++ b/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py @@ -29,12 +29,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) + super().add_parser_arguments(add, default_propagation_seconds=30) add('credentials', help='Gehirn Infrastructure Service credentials file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -75,7 +75,7 @@ class _GehirnLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, api_token, api_secret, ttl): - super(_GehirnLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('gehirn', { 'ttl': ttl, @@ -89,4 +89,4 @@ class _GehirnLexiconClient(dns_common_lexicon.LexiconClient): def _handle_http_error(self, e, domain_name): if domain_name in str(e) and (str(e).startswith('404 Client Error: Not Found for url:')): return None # Expected errors when zone name guess is wrong - return super(_GehirnLexiconClient, self)._handle_http_error(e, domain_name) + return super()._handle_http_error(e, domain_name) diff --git a/certbot-dns-gehirn/tests/dns_gehirn_test.py b/certbot-dns-gehirn/tests/dns_gehirn_test.py index 0598a5eb5..1310f74ca 100644 --- a/certbot-dns-gehirn/tests/dns_gehirn_test.py +++ b/certbot-dns-gehirn/tests/dns_gehirn_test.py @@ -21,7 +21,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_gehirn._internal.dns_gehirn import Authenticator diff --git a/certbot-dns-google/certbot_dns_google/_internal/dns_google.py b/certbot-dns-google/certbot_dns_google/_internal/dns_google.py index 39f26c7d0..3a2686a63 100644 --- a/certbot-dns-google/certbot_dns_google/_internal/dns_google.py +++ b/certbot-dns-google/certbot_dns_google/_internal/dns_google.py @@ -34,7 +34,7 @@ class Authenticator(dns_common.DNSAuthenticator): @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=60) + super().add_parser_arguments(add, default_propagation_seconds=60) add('credentials', help=('Path to Google Cloud DNS service account JSON file. (See {0} for' + 'information about creating a service account and {1} for information about the' + diff --git a/certbot-dns-google/tests/dns_google_test.py b/certbot-dns-google/tests/dns_google_test.py index 7de5f1d67..aa3ff35b5 100644 --- a/certbot-dns-google/tests/dns_google_test.py +++ b/certbot-dns-google/tests/dns_google_test.py @@ -26,14 +26,14 @@ PROJECT_ID = "test-test-1" class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_google._internal.dns_google import Authenticator path = os.path.join(self.tempdir, 'file.json') open(path, "wb").close() - super(AuthenticatorTest, self).setUp() + super().setUp() self.config = mock.MagicMock(google_credentials=path, google_propagation_seconds=0) # don't wait during tests diff --git a/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py b/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py index c9e6a42b5..b1649cf61 100644 --- a/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py +++ b/certbot-dns-linode/certbot_dns_linode/_internal/dns_linode.py @@ -29,12 +29,12 @@ class Authenticator(dns_common.DNSAuthenticator): description = 'Obtain certificates using a DNS TXT record (if you are using Linode for DNS).' def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=120) + super().add_parser_arguments(add, default_propagation_seconds=120) add('credentials', help='Linode credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -85,7 +85,7 @@ class _LinodeLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, api_key, api_version): - super(_LinodeLexiconClient, self).__init__() + super().__init__() self.api_version = api_version diff --git a/certbot-dns-linode/tests/dns_linode_test.py b/certbot-dns-linode/tests/dns_linode_test.py index fb9b1aa93..9861d2ab0 100644 --- a/certbot-dns-linode/tests/dns_linode_test.py +++ b/certbot-dns-linode/tests/dns_linode_test.py @@ -22,7 +22,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() path = os.path.join(self.tempdir, 'file.ini') dns_test_common.write({"linode_key": TOKEN}, path) diff --git a/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py b/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py index 6595c3165..ed90b63d9 100644 --- a/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py +++ b/certbot-dns-luadns/certbot_dns_luadns/_internal/dns_luadns.py @@ -28,12 +28,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) + super().add_parser_arguments(add, default_propagation_seconds=30) add('credentials', help='LuaDNS credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -70,7 +70,7 @@ class _LuaDNSLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, email, token, ttl): - super(_LuaDNSLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('luadns', { 'ttl': ttl, diff --git a/certbot-dns-luadns/tests/dns_luadns_test.py b/certbot-dns-luadns/tests/dns_luadns_test.py index a1242582f..7592e2323 100644 --- a/certbot-dns-luadns/tests/dns_luadns_test.py +++ b/certbot-dns-luadns/tests/dns_luadns_test.py @@ -21,7 +21,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_luadns._internal.dns_luadns import Authenticator diff --git a/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py b/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py index dc4a0d0ee..ce46ad835 100644 --- a/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py +++ b/certbot-dns-nsone/certbot_dns_nsone/_internal/dns_nsone.py @@ -28,12 +28,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) + super().add_parser_arguments(add, default_propagation_seconds=30) add('credentials', help='NS1 credentials file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -67,7 +67,7 @@ class _NS1LexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, api_key, ttl): - super(_NS1LexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('nsone', { 'ttl': ttl, diff --git a/certbot-dns-nsone/tests/dns_nsone_test.py b/certbot-dns-nsone/tests/dns_nsone_test.py index 83371252f..3754f9811 100644 --- a/certbot-dns-nsone/tests/dns_nsone_test.py +++ b/certbot-dns-nsone/tests/dns_nsone_test.py @@ -21,7 +21,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_nsone._internal.dns_nsone import Authenticator diff --git a/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py b/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py index 13f5b2805..54fd6d791 100644 --- a/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py +++ b/certbot-dns-ovh/certbot_dns_ovh/_internal/dns_ovh.py @@ -28,12 +28,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) + super().add_parser_arguments(add, default_propagation_seconds=30) add('credentials', help='OVH credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring @@ -79,7 +79,7 @@ class _OVHLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, endpoint, application_key, application_secret, consumer_key, ttl): - super(_OVHLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('ovh', { 'ttl': ttl, @@ -106,4 +106,4 @@ class _OVHLexiconClient(dns_common_lexicon.LexiconClient): if domain_name in str(e) and str(e).endswith('not found'): return - super(_OVHLexiconClient, self)._handle_general_error(e, domain_name) + super()._handle_general_error(e, domain_name) diff --git a/certbot-dns-ovh/tests/dns_ovh_test.py b/certbot-dns-ovh/tests/dns_ovh_test.py index dd0f3058b..7f93967eb 100644 --- a/certbot-dns-ovh/tests/dns_ovh_test.py +++ b/certbot-dns-ovh/tests/dns_ovh_test.py @@ -23,7 +23,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_ovh._internal.dns_ovh import Authenticator diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py index a3ee1e0e3..28fd27eec 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py @@ -45,12 +45,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 120 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=60) + super().add_parser_arguments(add, default_propagation_seconds=60) add('credentials', help='RFC 2136 credentials INI file.') def more_info(self): # pylint: disable=missing-function-docstring diff --git a/certbot-dns-rfc2136/tests/dns_rfc2136_test.py b/certbot-dns-rfc2136/tests/dns_rfc2136_test.py index dc4a73a04..c2b80defe 100644 --- a/certbot-dns-rfc2136/tests/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/tests/dns_rfc2136_test.py @@ -28,7 +28,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic def setUp(self): from certbot_dns_rfc2136._internal.dns_rfc2136 import Authenticator - super(AuthenticatorTest, self).setUp() + super().setUp() path = os.path.join(self.tempdir, 'file.ini') dns_test_common.write(VALID_CONFIG, path) diff --git a/certbot-dns-route53/certbot_dns_route53/_internal/dns_route53.py b/certbot-dns-route53/certbot_dns_route53/_internal/dns_route53.py index 4dda13f1d..9e470bdde 100644 --- a/certbot-dns-route53/certbot_dns_route53/_internal/dns_route53.py +++ b/certbot-dns-route53/certbot_dns_route53/_internal/dns_route53.py @@ -37,7 +37,7 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 10 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.r53 = boto3.client("route53") self._resource_records: DefaultDict[str, List[Dict[str, str]]] = collections.defaultdict(list) diff --git a/certbot-dns-route53/certbot_dns_route53/authenticator.py b/certbot-dns-route53/certbot_dns_route53/authenticator.py index 2987934a1..060d2fa38 100644 --- a/certbot-dns-route53/certbot_dns_route53/authenticator.py +++ b/certbot-dns-route53/certbot_dns_route53/authenticator.py @@ -18,4 +18,4 @@ class Authenticator(dns_route53.Authenticator): def __init__(self, *args, **kwargs): warnings.warn("The 'authenticator' module was renamed 'dns_route53'", DeprecationWarning) - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) diff --git a/certbot-dns-route53/tests/dns_route53_test.py b/certbot-dns-route53/tests/dns_route53_test.py index 1fd191c69..69b6b115d 100644 --- a/certbot-dns-route53/tests/dns_route53_test.py +++ b/certbot-dns-route53/tests/dns_route53_test.py @@ -21,7 +21,7 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest def setUp(self): from certbot_dns_route53._internal.dns_route53 import Authenticator - super(AuthenticatorTest, self).setUp() + super().setUp() self.config = mock.MagicMock() diff --git a/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py b/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py index eb78735f5..668c5e1f8 100644 --- a/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py +++ b/certbot-dns-sakuracloud/certbot_dns_sakuracloud/_internal/dns_sakuracloud.py @@ -29,12 +29,12 @@ class Authenticator(dns_common.DNSAuthenticator): ttl = 60 def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.credentials: Optional[CredentialsConfiguration] = None @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ - super(Authenticator, cls).add_parser_arguments( + super().add_parser_arguments( add, default_propagation_seconds=90) add('credentials', help='Sakura Cloud credentials file.') @@ -78,7 +78,7 @@ class _SakuraCloudLexiconClient(dns_common_lexicon.LexiconClient): """ def __init__(self, api_token, api_secret, ttl): - super(_SakuraCloudLexiconClient, self).__init__() + super().__init__() config = dns_common_lexicon.build_lexicon_config('sakuracloud', { 'ttl': ttl, @@ -92,4 +92,4 @@ class _SakuraCloudLexiconClient(dns_common_lexicon.LexiconClient): def _handle_http_error(self, e, domain_name): if domain_name in str(e) and (str(e).startswith('404 Client Error: Not Found for url:')): return None # Expected errors when zone name guess is wrong - return super(_SakuraCloudLexiconClient, self)._handle_http_error(e, domain_name) + return super()._handle_http_error(e, domain_name) diff --git a/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py b/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py index af94336b3..1c64df372 100644 --- a/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py +++ b/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py @@ -21,7 +21,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common_lexicon.BaseLexiconAuthenticatorTest): def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_sakuracloud._internal.dns_sakuracloud import Authenticator diff --git a/certbot-nginx/certbot_nginx/_internal/configurator.py b/certbot-nginx/certbot_nginx/_internal/configurator.py index c05ddceba..9fb81efaa 100644 --- a/certbot-nginx/certbot_nginx/_internal/configurator.py +++ b/certbot-nginx/certbot_nginx/_internal/configurator.py @@ -102,7 +102,7 @@ class NginxConfigurator(common.Installer): """ version = kwargs.pop("version", None) openssl_version = kwargs.pop("openssl_version", None) - super(NginxConfigurator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Files to save self.save_notes = "" @@ -1110,7 +1110,7 @@ class NginxConfigurator(common.Installer): :raises .errors.PluginError: If unable to recover the configuration """ - super(NginxConfigurator, self).recovery_routine() + super().recovery_routine() self.new_vhost = None self.parser.load() @@ -1133,7 +1133,7 @@ class NginxConfigurator(common.Installer): the function is unable to correctly revert the configuration """ - super(NginxConfigurator, self).rollback_checkpoints(rollback) + super().rollback_checkpoints(rollback) self.new_vhost = None self.parser.load() diff --git a/certbot-nginx/certbot_nginx/_internal/http_01.py b/certbot-nginx/certbot_nginx/_internal/http_01.py index abcdfbd53..716af0898 100644 --- a/certbot-nginx/certbot_nginx/_internal/http_01.py +++ b/certbot-nginx/certbot_nginx/_internal/http_01.py @@ -37,7 +37,7 @@ class NginxHttp01(common.ChallengePerformer): """ def __init__(self, configurator): - super(NginxHttp01, self).__init__(configurator) + super().__init__(configurator) self.challenge_conf = os.path.join( configurator.config.config_dir, "le_http_01_cert_challenge.conf") diff --git a/certbot-nginx/certbot_nginx/_internal/obj.py b/certbot-nginx/certbot_nginx/_internal/obj.py index f77e535ce..44be0e598 100644 --- a/certbot-nginx/certbot_nginx/_internal/obj.py +++ b/certbot-nginx/certbot_nginx/_internal/obj.py @@ -35,7 +35,7 @@ class Addr(common.Addr): CANONICAL_UNSPECIFIED_ADDRESS = UNSPECIFIED_IPV4_ADDRESSES[0] def __init__(self, host, port, ssl, default, ipv6, ipv6only): - super(Addr, self).__init__((host, port)) + super().__init__((host, port)) self.ssl = ssl self.default = default self.ipv6 = ipv6 @@ -120,7 +120,7 @@ class Addr(common.Addr): def __hash__(self): # pylint: disable=useless-super-delegation # Python 3 requires explicit overridden for __hash__ # See certbot-apache/certbot_apache/_internal/obj.py for more information - return super(Addr, self).__hash__() + return super().__hash__() def super_eq(self, other): """Check ip/port equality, with IPv6 support. @@ -132,7 +132,7 @@ class Addr(common.Addr): self.tup[1]), self.ipv6) == \ common.Addr((other.CANONICAL_UNSPECIFIED_ADDRESS, other.tup[1]), other.ipv6) - return super(Addr, self).__eq__(other) + return super().__eq__(other) def __eq__(self, other): if isinstance(other, self.__class__): diff --git a/certbot-nginx/certbot_nginx/_internal/parser_obj.py b/certbot-nginx/certbot_nginx/_internal/parser_obj.py index 838a2e382..d4d332c47 100644 --- a/certbot-nginx/certbot_nginx/_internal/parser_obj.py +++ b/certbot-nginx/certbot_nginx/_internal/parser_obj.py @@ -122,7 +122,7 @@ class Statements(Parsable): precede any more statements. """ def __init__(self, parent=None): - super(Statements, self).__init__(parent) + super().__init__(parent) self._trailing_whitespace = None # ======== Begin overridden functions @@ -167,7 +167,7 @@ class Statements(Parsable): def dump(self, include_spaces=False): """ Dumps this object by first dumping each statement, then appending its trailing whitespace (if `include_spaces` is set) """ - data = super(Statements, self).dump(include_spaces) + data = super().dump(include_spaces) if include_spaces and self._trailing_whitespace is not None: return data + [self._trailing_whitespace] return data @@ -271,7 +271,7 @@ class Block(Parsable): contents = [["\n ", "content", " ", "1"], ["\n ", "content", " ", "2"], "\n"] """ def __init__(self, parent=None): - super(Block, self).__init__(parent) + super().__init__(parent) self.names: Sentence = None self.contents: Block = None diff --git a/certbot-nginx/tests/configurator_test.py b/certbot-nginx/tests/configurator_test.py index 9ccc3fc9e..e6ceca344 100644 --- a/certbot-nginx/tests/configurator_test.py +++ b/certbot-nginx/tests/configurator_test.py @@ -26,7 +26,7 @@ class NginxConfiguratorTest(util.NginxTest): def setUp(self): - super(NginxConfiguratorTest, self).setUp() + super().setUp() self.config = self.get_nginx_configurator( self.config_path, self.config_dir, self.work_dir, self.logs_dir) @@ -954,7 +954,7 @@ class InstallSslOptionsConfTest(util.NginxTest): """Test that the options-ssl-nginx.conf file is installed and updated properly.""" def setUp(self): - super(InstallSslOptionsConfTest, self).setUp() + super().setUp() self.config = self.get_nginx_configurator( self.config_path, self.config_dir, self.work_dir, self.logs_dir) diff --git a/certbot-nginx/tests/display_ops_test.py b/certbot-nginx/tests/display_ops_test.py index 377255441..bcd455410 100644 --- a/certbot-nginx/tests/display_ops_test.py +++ b/certbot-nginx/tests/display_ops_test.py @@ -12,7 +12,7 @@ class SelectVhostMultiTest(util.NginxTest): """Tests for certbot_nginx._internal.display_ops.select_vhost_multiple.""" def setUp(self): - super(SelectVhostMultiTest, self).setUp() + super().setUp() nparser = parser.NginxParser(self.config_path) self.vhosts = nparser.get_vhosts() diff --git a/certbot-nginx/tests/http_01_test.py b/certbot-nginx/tests/http_01_test.py index d0e84fc83..f10e44859 100644 --- a/certbot-nginx/tests/http_01_test.py +++ b/certbot-nginx/tests/http_01_test.py @@ -51,7 +51,7 @@ class HttpPerformTest(util.NginxTest): ] def setUp(self): - super(HttpPerformTest, self).setUp() + super().setUp() config = self.get_nginx_configurator( self.config_path, self.config_dir, self.work_dir, self.logs_dir) diff --git a/certbot-nginx/tests/test_util.py b/certbot-nginx/tests/test_util.py index ee53e8e1e..383a15753 100644 --- a/certbot-nginx/tests/test_util.py +++ b/certbot-nginx/tests/test_util.py @@ -22,7 +22,7 @@ from certbot_nginx._internal import nginxparser class NginxTest(test_util.ConfigTestCase): def setUp(self): - super(NginxTest, self).setUp() + super().setUp() self.configuration = self.config self.config = None diff --git a/certbot/certbot/_internal/cli/cli_utils.py b/certbot/certbot/_internal/cli/cli_utils.py index 1f30261c1..8060b5e21 100644 --- a/certbot/certbot/_internal/cli/cli_utils.py +++ b/certbot/certbot/_internal/cli/cli_utils.py @@ -140,7 +140,7 @@ class CaseInsensitiveList(list): through the `helpful` wrapper. It is necessary due to special handling of command line arguments by `set_by_cli` in which the `type_func` is not applied.""" def __contains__(self, element): - return super(CaseInsensitiveList, self).__contains__(element.lower()) + return super().__contains__(element.lower()) def _user_agent_comment_type(value): diff --git a/certbot/certbot/_internal/log.py b/certbot/certbot/_internal/log.py index fb0a996f7..7338578a7 100644 --- a/certbot/certbot/_internal/log.py +++ b/certbot/certbot/_internal/log.py @@ -171,7 +171,7 @@ class ColoredStreamHandler(logging.StreamHandler): """ def __init__(self, stream=None): - super(ColoredStreamHandler, self).__init__(stream) + super().__init__(stream) self.colored = (sys.stderr.isatty() if stream is None else stream.isatty()) self.red_level = logging.WARNING @@ -185,7 +185,7 @@ class ColoredStreamHandler(logging.StreamHandler): :rtype: str """ - out = super(ColoredStreamHandler, self).format(record) + out = super().format(record) if self.colored and record.levelno >= self.red_level: return ''.join((util.ANSI_SGR_RED, out, util.ANSI_SGR_RESET)) return out @@ -200,14 +200,14 @@ class MemoryHandler(logging.handlers.MemoryHandler): """ def __init__(self, target=None, capacity=10000): # capacity doesn't matter because should_flush() is overridden - super(MemoryHandler, self).__init__(capacity, target=target) + super().__init__(capacity, target=target) def close(self): """Close the memory handler, but don't set the target to None.""" # This allows the logging module which may only have a weak # reference to the target handler to properly flush and close it. target = getattr(self, 'target') - super(MemoryHandler, self).close() + super().close() self.target = target def flush(self, force=False): # pylint: disable=arguments-differ @@ -221,7 +221,7 @@ class MemoryHandler(logging.handlers.MemoryHandler): # This method allows flush() calls in logging.shutdown to be a # noop so we can control when this handler is flushed. if force: - super(MemoryHandler, self).flush() + super().flush() def shouldFlush(self, record): """Should the buffer be automatically flushed? @@ -249,7 +249,7 @@ class TempHandler(logging.StreamHandler): self._workdir = tempfile.mkdtemp() self.path = os.path.join(self._workdir, 'log') stream = util.safe_open(self.path, mode='w', chmod=0o600) - super(TempHandler, self).__init__(stream) + super().__init__(stream) self._delete = True def emit(self, record): @@ -259,7 +259,7 @@ class TempHandler(logging.StreamHandler): """ self._delete = False - super(TempHandler, self).emit(record) + super().emit(record) def close(self): """Close the handler and the temporary log file. @@ -275,7 +275,7 @@ class TempHandler(logging.StreamHandler): if self._delete: shutil.rmtree(self._workdir) self._delete = False - super(TempHandler, self).close() + super().close() finally: self.release() diff --git a/certbot/certbot/_internal/plugins/manual.py b/certbot/certbot/_internal/plugins/manual.py index ed2e0559e..5423ec1d9 100644 --- a/certbot/certbot/_internal/plugins/manual.py +++ b/certbot/certbot/_internal/plugins/manual.py @@ -71,7 +71,7 @@ permitted by DNS standards.) """ def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.reverter = reverter.Reverter(self.config) self.reverter.recovery_routine() self.env: Dict[achallenges.KeyAuthorizationAnnotatedChallenge, Dict[str, str]] = {} diff --git a/certbot/certbot/_internal/plugins/standalone.py b/certbot/certbot/_internal/plugins/standalone.py index c75ba36a9..5fb29671f 100644 --- a/certbot/certbot/_internal/plugins/standalone.py +++ b/certbot/certbot/_internal/plugins/standalone.py @@ -119,7 +119,7 @@ class Authenticator(common.Plugin): description = "Spin up a temporary webserver" def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.served: ServedType = collections.defaultdict(set) diff --git a/certbot/certbot/_internal/plugins/webroot.py b/certbot/certbot/_internal/plugins/webroot.py index c5b436b65..3473d3c8e 100644 --- a/certbot/certbot/_internal/plugins/webroot.py +++ b/certbot/certbot/_internal/plugins/webroot.py @@ -66,7 +66,7 @@ to serve all files under specified web root ({0}).""" return [challenges.HTTP01] def __init__(self, *args, **kwargs): - super(Authenticator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.full_roots: Dict[str, str] = {} self.performed: DefaultDict[str, Set[AnnotatedChallenge]] = collections.defaultdict(set) # stack of dirs successfully created by this authenticator @@ -250,7 +250,7 @@ class _WebrootPathAction(argparse.Action): """Action class for parsing webroot_path.""" def __init__(self, *args, **kwargs): - super(_WebrootPathAction, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._domain_before_webroot = False def __call__(self, parser, namespace, webroot_path, option_string=None): diff --git a/certbot/certbot/_internal/snap_config.py b/certbot/certbot/_internal/snap_config.py index 1ba53cad4..f7832cd55 100644 --- a/certbot/certbot/_internal/snap_config.py +++ b/certbot/certbot/_internal/snap_config.py @@ -80,7 +80,7 @@ def prepare_env(cli_args: List[str]) -> List[str]: class _SnapdConnection(HTTPConnection): def __init__(self): - super(_SnapdConnection, self).__init__("localhost") + super().__init__("localhost") self.sock = None def connect(self): @@ -90,7 +90,7 @@ class _SnapdConnection(HTTPConnection): class _SnapdConnectionPool(HTTPConnectionPool): def __init__(self): - super(_SnapdConnectionPool, self).__init__("localhost") + super().__init__("localhost") def _new_conn(self): return _SnapdConnection() diff --git a/certbot/certbot/display/util.py b/certbot/certbot/display/util.py index 9443ae266..dc642586c 100644 --- a/certbot/certbot/display/util.py +++ b/certbot/certbot/display/util.py @@ -115,7 +115,7 @@ class FileDisplay: # see https://github.com/certbot/certbot/issues/3915 def __init__(self, outfile, force_interactive): - super(FileDisplay, self).__init__() + super().__init__() self.outfile = outfile self.force_interactive = force_interactive self.skipped_interaction = False @@ -481,7 +481,7 @@ class NoninteractiveDisplay: """An iDisplay implementation that never asks for interactive user input""" def __init__(self, outfile, *unused_args, **unused_kwargs): - super(NoninteractiveDisplay, self).__init__() + super().__init__() self.outfile = outfile def _interaction_fail(self, message, cli_flag, extra=""): diff --git a/certbot/certbot/errors.py b/certbot/certbot/errors.py index 48aebc267..cf0d3d283 100644 --- a/certbot/certbot/errors.py +++ b/certbot/certbot/errors.py @@ -53,7 +53,7 @@ class FailedChallenges(AuthorizationError): def __init__(self, failed_achalls): assert failed_achalls self.failed_achalls = failed_achalls - super(FailedChallenges, self).__init__() + super().__init__() def __str__(self): return "Failed authorization procedure. {0}".format( @@ -95,7 +95,7 @@ class StandaloneBindError(Error): """Standalone plugin bind error.""" def __init__(self, socket_error, port): - super(StandaloneBindError, self).__init__( + super().__init__( "Problem binding to port {0}: {1}".format(port, socket_error)) self.socket_error = socket_error self.port = port diff --git a/certbot/certbot/plugins/common.py b/certbot/certbot/plugins/common.py index 06acefc69..4c33acbab 100644 --- a/certbot/certbot/plugins/common.py +++ b/certbot/certbot/plugins/common.py @@ -105,7 +105,7 @@ class Installer(Plugin): """ def __init__(self, *args, **kwargs): - super(Installer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.storage = PluginStorage(self.config, self.name) self.reverter = reverter.Reverter(self.config) diff --git a/certbot/certbot/plugins/dns_common.py b/certbot/certbot/plugins/dns_common.py index 4b621ceac..4459ac0fa 100644 --- a/certbot/certbot/plugins/dns_common.py +++ b/certbot/certbot/plugins/dns_common.py @@ -25,7 +25,7 @@ class DNSAuthenticator(common.Plugin): """Base class for DNS Authenticators""" def __init__(self, config, name): - super(DNSAuthenticator, self).__init__(config, name) + super().__init__(config, name) self._attempt_cleanup = False diff --git a/certbot/certbot/tests/util.py b/certbot/certbot/tests/util.py index 78236fa06..b6a27a7c8 100644 --- a/certbot/certbot/tests/util.py +++ b/certbot/certbot/tests/util.py @@ -331,7 +331,7 @@ class TempDirTestCase(unittest.TestCase): class ConfigTestCase(TempDirTestCase): """Test class which sets up a NamespaceConfig object.""" def setUp(self): - super(ConfigTestCase, self).setUp() + super().setUp() self.config = configuration.NamespaceConfig( mock.MagicMock(**constants.CLI_DEFAULTS) ) diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index d0448a1db..7c8f52273 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -106,7 +106,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase): """Tests for certbot._internal.account.AccountFileStorage.""" def setUp(self): - super(AccountFileStorageTest, self).setUp() + super().setUp() from certbot._internal.account import AccountFileStorage self.storage = AccountFileStorage(self.config) diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index ba6cfddc3..918459256 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -26,7 +26,7 @@ class BaseCertManagerTest(test_util.ConfigTestCase): """Base class for setting up Cert Manager tests. """ def setUp(self): - super(BaseCertManagerTest, self).setUp() + super().setUp() self.config.quiet = False filesystem.makedirs(self.config.renewal_configs_dir) @@ -396,7 +396,7 @@ class RenameLineageTest(BaseCertManagerTest): """Tests for certbot._internal.cert_manager.rename_lineage""" def setUp(self): - super(RenameLineageTest, self).setUp() + super().setUp() self.config.certname = "example.org" self.config.new_certname = "after" @@ -483,7 +483,7 @@ class DuplicativeCertsTest(storage_test.BaseRenewableCertTest): """Test to avoid duplicate lineages.""" def setUp(self): - super(DuplicativeCertsTest, self).setUp() + super().setUp() self.config_file.write() self._write_out_ex_kinds() @@ -521,7 +521,7 @@ class CertPathToLineageTest(storage_test.BaseRenewableCertTest): """Tests for certbot._internal.cert_manager.cert_path_to_lineage""" def setUp(self): - super(CertPathToLineageTest, self).setUp() + super().setUp() self.config_file.write() self._write_out_ex_kinds() self.fullchain = os.path.join(self.config.config_dir, 'live', 'example.org', @@ -581,7 +581,7 @@ class MatchAndCheckOverlaps(storage_test.BaseRenewableCertTest): archive dirs.""" # A test with real overlapping archive dirs can be found in tests/boulder_integration.sh def setUp(self): - super(MatchAndCheckOverlaps, self).setUp() + super().setUp() self.config_file.write() self._write_out_ex_kinds() self.fullchain = os.path.join(self.config.config_dir, 'live', 'example.org', diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index f058cb658..2acaa71b1 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -58,7 +58,7 @@ class RegisterTest(test_util.ConfigTestCase): """Tests for certbot._internal.client.register.""" def setUp(self): - super(RegisterTest, self).setUp() + super().setUp() self.config.rsa_key_size = 1024 self.config.register_unsafely_without_email = False self.config.email = "alias@example.com" @@ -217,7 +217,7 @@ class ClientTestCommon(test_util.ConfigTestCase): """Common base class for certbot._internal.client.Client tests.""" def setUp(self): - super(ClientTestCommon, self).setUp() + super().setUp() self.config.no_verify_ssl = False self.config.allow_subset_of_names = False @@ -236,7 +236,7 @@ class ClientTest(ClientTestCommon): """Tests for certbot._internal.client.Client.""" def setUp(self): - super(ClientTest, self).setUp() + super().setUp() self.config.allow_subset_of_names = False self.config.dry_run = False @@ -582,7 +582,7 @@ class EnhanceConfigTest(ClientTestCommon): """Tests for certbot._internal.client.Client.enhance_config.""" def setUp(self): - super(EnhanceConfigTest, self).setUp() + super().setUp() self.config.hsts = False self.config.redirect = False diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index ea48c9d1c..47da2b415 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -34,7 +34,7 @@ ADMINS_SID = 'S-1-5-32-544' class WindowsChmodTests(TempDirTestCase): """Unit tests for Windows chmod function in filesystem module""" def setUp(self): - super(WindowsChmodTests, self).setUp() + super().setUp() self.probe_path = _create_probe(self.tempdir) def test_symlink_resolution(self): @@ -203,7 +203,7 @@ class UmaskTest(TempDirTestCase): class ComputePrivateKeyModeTest(TempDirTestCase): def setUp(self): - super(ComputePrivateKeyModeTest, self).setUp() + super().setUp() self.probe_path = _create_probe(self.tempdir) def test_compute_private_key_mode(self): @@ -351,7 +351,7 @@ class MakedirsTests(test_util.TempDirTestCase): class CopyOwnershipAndModeTest(test_util.TempDirTestCase): """Tests about copy_ownership_and_apply_mode, copy_ownership_and_mode and has_same_ownership""" def setUp(self): - super(CopyOwnershipAndModeTest, self).setUp() + super().setUp() self.probe_path = _create_probe(self.tempdir) @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') @@ -424,7 +424,7 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): class CheckPermissionsTest(test_util.TempDirTestCase): """Tests relative to functions that check modes.""" def setUp(self): - super(CheckPermissionsTest, self).setUp() + super().setUp() self.probe_path = _create_probe(self.tempdir) def test_check_mode(self): @@ -506,7 +506,7 @@ class OsReplaceTest(test_util.TempDirTestCase): class RealpathTest(test_util.TempDirTestCase): """Tests for realpath method""" def setUp(self): - super(RealpathTest, self).setUp() + super().setUp() self.probe_path = _create_probe(self.tempdir) def test_symlink_resolution(self): diff --git a/certbot/tests/configuration_test.py b/certbot/tests/configuration_test.py index 1f8a0e803..e23c50afb 100644 --- a/certbot/tests/configuration_test.py +++ b/certbot/tests/configuration_test.py @@ -17,7 +17,7 @@ class NamespaceConfigTest(test_util.ConfigTestCase): """Tests for certbot._internal.configuration.NamespaceConfig.""" def setUp(self): - super(NamespaceConfigTest, self).setUp() + super().setUp() self.config.foo = 'bar' # pylint: disable=blacklisted-name self.config.server = 'https://acme-server.org:443/new' self.config.https_port = 1234 diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index 3b9c973f7..a2b89ee17 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -36,7 +36,7 @@ CERT_ALT_ISSUER = test_util.load_vector('cert_intermediate_2.pem') class InitSaveKeyTest(test_util.TempDirTestCase): """Tests for certbot.crypto_util.init_save_key.""" def setUp(self): - super(InitSaveKeyTest, self).setUp() + super().setUp() self.workdir = os.path.join(self.tempdir, 'workdir') filesystem.mkdir(self.workdir, mode=0o700) @@ -46,7 +46,7 @@ class InitSaveKeyTest(test_util.TempDirTestCase): mock.Mock(strict_permissions=True), interfaces.IConfig) def tearDown(self): - super(InitSaveKeyTest, self).tearDown() + super().tearDown() logging.disable(logging.NOTSET) @@ -73,7 +73,7 @@ class InitSaveCSRTest(test_util.TempDirTestCase): """Tests for certbot.crypto_util.init_save_csr.""" def setUp(self): - super(InitSaveCSRTest, self).setUp() + super().setUp() zope.component.provideUtility( mock.Mock(strict_permissions=True), interfaces.IConfig) diff --git a/certbot/tests/display/completer_test.py b/certbot/tests/display/completer_test.py index 86f939491..087617310 100644 --- a/certbot/tests/display/completer_test.py +++ b/certbot/tests/display/completer_test.py @@ -25,7 +25,7 @@ class CompleterTest(test_util.TempDirTestCase): """Test certbot._internal.display.completer.Completer.""" def setUp(self): - super(CompleterTest, self).setUp() + super().setUp() # directories must end with os.sep for completer to # search inside the directory for possible completions diff --git a/certbot/tests/display/ops_test.py b/certbot/tests/display/ops_test.py index ce60a5f0b..1e50ba03b 100644 --- a/certbot/tests/display/ops_test.py +++ b/certbot/tests/display/ops_test.py @@ -90,7 +90,7 @@ class GetEmailTest(unittest.TestCase): class ChooseAccountTest(test_util.TempDirTestCase): """Tests for certbot.display.ops.choose_account.""" def setUp(self): - super(ChooseAccountTest, self).setUp() + super().setUp() zope.component.provideUtility(display_util.FileDisplay(sys.stdout, False)) diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 30b33bbc9..5f1fac8c0 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -65,7 +65,7 @@ class FileOutputDisplayTest(unittest.TestCase): """ def setUp(self): - super(FileOutputDisplayTest, self).setUp() + super().setUp() self.mock_stdout = mock.MagicMock() self.displayer = display_util.FileDisplay(self.mock_stdout, False) diff --git a/certbot/tests/eff_test.py b/certbot/tests/eff_test.py index dc6b6b944..5da1e6fb6 100644 --- a/certbot/tests/eff_test.py +++ b/certbot/tests/eff_test.py @@ -22,7 +22,7 @@ _KEY = josepy.JWKRSA.load(test_util.load_vector("rsa512_key.pem")) class SubscriptionTest(test_util.ConfigTestCase): """Abstract class for subscription tests.""" def setUp(self): - super(SubscriptionTest, self).setUp() + super().setUp() self.account = account.Account( regr=messages.RegistrationResource( uri=None, body=messages.Registration(), diff --git a/certbot/tests/error_handler_test.py b/certbot/tests/error_handler_test.py index 521b6976b..e04fe0742 100644 --- a/certbot/tests/error_handler_test.py +++ b/certbot/tests/error_handler_test.py @@ -136,7 +136,7 @@ class ExitHandlerTest(ErrorHandlerTest): def setUp(self): from certbot._internal import error_handler - super(ExitHandlerTest, self).setUp() + super().setUp() self.handler = error_handler.ExitHandler(self.init_func, *self.init_args, **self.init_kwargs) diff --git a/certbot/tests/hook_test.py b/certbot/tests/hook_test.py index b0522bd52..76d460ae9 100644 --- a/certbot/tests/hook_test.py +++ b/certbot/tests/hook_test.py @@ -93,7 +93,7 @@ class PreHookTest(HookTest): return pre_hook(*args, **kwargs) def setUp(self): - super(PreHookTest, self).setUp() + super().setUp() self.config.pre_hook = "foo" filesystem.makedirs(self.config.renewal_pre_hooks_dir) @@ -106,7 +106,7 @@ class PreHookTest(HookTest): def tearDown(self): # Reset this value so it's unmodified for future tests self._reset_pre_hook_already() - super(PreHookTest, self).tearDown() + super().tearDown() def _reset_pre_hook_already(self): from certbot._internal.hooks import executed_pre_hooks @@ -171,7 +171,7 @@ class PostHookTest(HookTest): return post_hook(*args, **kwargs) def setUp(self): - super(PostHookTest, self).setUp() + super().setUp() self.config.post_hook = "bar" filesystem.makedirs(self.config.renewal_post_hooks_dir) @@ -184,7 +184,7 @@ class PostHookTest(HookTest): def tearDown(self): # Reset this value so it's unmodified for future tests self._reset_post_hook_eventually() - super(PostHookTest, self).tearDown() + super().tearDown() def _reset_post_hook_eventually(self): from certbot._internal.hooks import post_hooks @@ -266,7 +266,7 @@ class RunSavedPostHooksTest(HookTest): return self._call_with_mock_execute(*args, **kwargs) def setUp(self): - super(RunSavedPostHooksTest, self).setUp() + super().setUp() self.eventually: List[str] = [] def test_empty(self): @@ -319,7 +319,7 @@ class RenewalHookTest(HookTest): return mock_execute def setUp(self): - super(RenewalHookTest, self).setUp() + super().setUp() self.vars_to_clear = set( var for var in ("RENEWED_DOMAINS", "RENEWED_LINEAGE",) if var not in os.environ) @@ -327,7 +327,7 @@ class RenewalHookTest(HookTest): def tearDown(self): for var in self.vars_to_clear: os.environ.pop(var, None) - super(RenewalHookTest, self).tearDown() + super().tearDown() class DeployHookTest(RenewalHookTest): @@ -373,7 +373,7 @@ class RenewHookTest(RenewalHookTest): return renew_hook(*args, **kwargs) def setUp(self): - super(RenewHookTest, self).setUp() + super().setUp() self.config.renew_hook = "foo" filesystem.makedirs(self.config.renewal_deploy_hooks_dir) diff --git a/certbot/tests/lock_test.py b/certbot/tests/lock_test.py index 2f887d33e..ac6b539a4 100644 --- a/certbot/tests/lock_test.py +++ b/certbot/tests/lock_test.py @@ -44,7 +44,7 @@ class LockFileTest(test_util.TempDirTestCase): return LockFile(*args, **kwargs) def setUp(self): - super(LockFileTest, self).setUp() + super().setUp() self.lock_path = os.path.join(self.tempdir, 'test.lock') def test_acquire_without_deletion(self): diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 5960b37cf..37660f51e 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -70,7 +70,7 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): return post_arg_parse_setup(*args, **kwargs) def setUp(self): - super(PostArgParseSetupTest, self).setUp() + super().setUp() self.config.debug = False self.config.max_log_backups = 1000 self.config.quiet = False @@ -91,7 +91,7 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): self.stream_handler.close() self.temp_handler.close() self.devnull.close() - super(PostArgParseSetupTest, self).tearDown() + super().tearDown() def test_common(self): with mock.patch('certbot._internal.log.logging.getLogger') as mock_get_logger: @@ -136,7 +136,7 @@ class SetupLogFileHandlerTest(test_util.ConfigTestCase): return setup_log_file_handler(*args, **kwargs) def setUp(self): - super(SetupLogFileHandlerTest, self).setUp() + super().setUp() self.config.max_log_backups = 42 @mock.patch('certbot._internal.main.logging.handlers.RotatingFileHandler') diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index e093edd20..7908cf804 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -101,7 +101,7 @@ class RunTest(test_util.ConfigTestCase): """Tests for certbot._internal.main.run.""" def setUp(self): - super(RunTest, self).setUp() + super().setUp() self.domain = 'example.org' patches = [ mock.patch('certbot._internal.main._get_and_save_cert'), @@ -283,7 +283,7 @@ class RevokeTest(test_util.TempDirTestCase): """Tests for certbot._internal.main.revoke.""" def setUp(self): - super(RevokeTest, self).setUp() + super().setUp() shutil.copy(CERT_PATH, self.tempdir) self.tmp_cert_path = os.path.abspath(os.path.join(self.tempdir, 'cert_512.pem')) @@ -512,7 +512,7 @@ class DetermineAccountTest(test_util.ConfigTestCase): """Tests for certbot._internal.main._determine_account.""" def setUp(self): - super(DetermineAccountTest, self).setUp() + super().setUp() self.config.account = None self.config.email = None self.config.register_unsafely_without_email = False @@ -584,7 +584,7 @@ class MainTest(test_util.ConfigTestCase): """Tests for different commands.""" def setUp(self): - super(MainTest, self).setUp() + super().setUp() filesystem.mkdir(self.config.logs_dir) self.standard_args = ['--config-dir', self.config.config_dir, @@ -597,7 +597,7 @@ class MainTest(test_util.ConfigTestCase): # Reset globals in cli reload_module(cli) - super(MainTest, self).tearDown() + super().tearDown() def _call(self, args, stdout=None, mockisfile=False): """Run the cli with output streams, actual client and optionally @@ -1576,7 +1576,7 @@ class EnhanceTest(test_util.ConfigTestCase): """Tests for certbot._internal.main.enhance.""" def setUp(self): - super(EnhanceTest, self).setUp() + super().setUp() self.get_utility_patch = test_util.patch_get_utility() self.mock_get_utility = self.get_utility_patch.start() self.mockinstaller = mock.MagicMock(spec=enhancements.AutoHSTSEnhancement) @@ -1720,7 +1720,7 @@ class InstallTest(test_util.ConfigTestCase): """Tests for certbot._internal.main.install.""" def setUp(self): - super(InstallTest, self).setUp() + super().setUp() self.mockinstaller = mock.MagicMock(spec=enhancements.AutoHSTSEnhancement) @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @@ -1765,7 +1765,7 @@ class UpdateAccountTest(test_util.ConfigTestCase): for patch in patches.values(): self.addCleanup(patch.stop) - return super(UpdateAccountTest, self).setUp() + return super().setUp() def _call(self, args): with mock.patch('certbot._internal.main.sys.stdout'), \ diff --git a/certbot/tests/plugins/common_test.py b/certbot/tests/plugins/common_test.py index bcd190e9b..7de3134fa 100644 --- a/certbot/tests/plugins/common_test.py +++ b/certbot/tests/plugins/common_test.py @@ -88,7 +88,7 @@ class InstallerTest(test_util.ConfigTestCase): """Tests for certbot.plugins.common.Installer.""" def setUp(self): - super(InstallerTest, self).setUp() + super().setUp() filesystem.mkdir(self.config.config_dir) from certbot.plugins.common import Installer @@ -282,7 +282,7 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): """Tests for certbot.plugins.common.install_version_controlled_file.""" def setUp(self): - super(InstallVersionControlledFileTest, self).setUp() + super().setUp() self.hashes = ["someotherhash"] self.dest_path = os.path.join(self.tempdir, "options-ssl-dest.conf") self.hash_path = os.path.join(self.tempdir, ".options-ssl-conf.txt") diff --git a/certbot/tests/plugins/dns_common_lexicon_test.py b/certbot/tests/plugins/dns_common_lexicon_test.py index a67430f3e..40afd107b 100644 --- a/certbot/tests/plugins/dns_common_lexicon_test.py +++ b/certbot/tests/plugins/dns_common_lexicon_test.py @@ -17,7 +17,7 @@ class LexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconCl pass def setUp(self): - super(LexiconClientTest, self).setUp() + super().setUp() self.client = LexiconClientTest._FakeLexiconClient() self.provider_mock = mock.MagicMock() diff --git a/certbot/tests/plugins/dns_common_test.py b/certbot/tests/plugins/dns_common_test.py index 31761e986..377244c4c 100644 --- a/certbot/tests/plugins/dns_common_test.py +++ b/certbot/tests/plugins/dns_common_test.py @@ -36,7 +36,7 @@ class DNSAuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthen fake_file_path = None def setUp(self): - super(DNSAuthenticatorTest, self).setUp() + super().setUp() self.config = DNSAuthenticatorTest._FakeConfig() @@ -164,7 +164,7 @@ class CredentialsConfigurationTest(test_util.TempDirTestCase): class CredentialsConfigurationRequireTest(test_util.TempDirTestCase): def setUp(self): - super(CredentialsConfigurationRequireTest, self).setUp() + super().setUp() self.path = os.path.join(self.tempdir, 'file.ini') diff --git a/certbot/tests/plugins/enhancements_test.py b/certbot/tests/plugins/enhancements_test.py index a20a6864f..0aa1512b4 100644 --- a/certbot/tests/plugins/enhancements_test.py +++ b/certbot/tests/plugins/enhancements_test.py @@ -15,7 +15,7 @@ class EnhancementTest(test_util.ConfigTestCase): """Tests for new style enhancements in certbot.plugins.enhancements""" def setUp(self): - super(EnhancementTest, self).setUp() + super().setUp() self.mockinstaller = mock.MagicMock(spec=enhancements.AutoHSTSEnhancement) diff --git a/certbot/tests/plugins/manual_test.py b/certbot/tests/plugins/manual_test.py index 0e552e0c5..08ab20456 100644 --- a/certbot/tests/plugins/manual_test.py +++ b/certbot/tests/plugins/manual_test.py @@ -19,7 +19,7 @@ class AuthenticatorTest(test_util.TempDirTestCase): """Tests for certbot._internal.plugins.manual.Authenticator.""" def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() self.http_achall = acme_util.HTTP01_A self.dns_achall = acme_util.DNS01_A self.dns_achall_2 = acme_util.DNS01_A_2 diff --git a/certbot/tests/plugins/selection_test.py b/certbot/tests/plugins/selection_test.py index eed07ae76..7fcd213a0 100644 --- a/certbot/tests/plugins/selection_test.py +++ b/certbot/tests/plugins/selection_test.py @@ -160,7 +160,7 @@ class GetUnpreparedInstallerTest(test_util.ConfigTestCase): """Tests for certbot._internal.plugins.selection.get_unprepared_installer.""" def setUp(self): - super(GetUnpreparedInstallerTest, self).setUp() + super().setUp() self.mock_apache_fail_ep = mock.Mock( description_with_name="afail") self.mock_apache_fail_ep.check_name = lambda name: name == "afail" diff --git a/certbot/tests/plugins/storage_test.py b/certbot/tests/plugins/storage_test.py index 4eb5f0912..36159e44f 100644 --- a/certbot/tests/plugins/storage_test.py +++ b/certbot/tests/plugins/storage_test.py @@ -18,7 +18,7 @@ class PluginStorageTest(test_util.ConfigTestCase): """Test for certbot.plugins.storage.PluginStorage""" def setUp(self): - super(PluginStorageTest, self).setUp() + super().setUp() self.plugin_cls = common.Installer filesystem.mkdir(self.config.config_dir) with mock.patch("certbot.reverter.util"): diff --git a/certbot/tests/renewupdater_test.py b/certbot/tests/renewupdater_test.py index b5ecddb5a..5137c81c3 100644 --- a/certbot/tests/renewupdater_test.py +++ b/certbot/tests/renewupdater_test.py @@ -17,7 +17,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): """Tests for interfaces.RenewDeployer and interfaces.GenericUpdater""" def setUp(self): - super(RenewUpdaterTest, self).setUp() + super().setUp() self.generic_updater = mock.MagicMock(spec=interfaces.GenericUpdater) self.generic_updater.restart = mock.MagicMock() self.renew_deployer = mock.MagicMock(spec=interfaces.RenewDeployer) diff --git a/certbot/tests/reverter_test.py b/certbot/tests/reverter_test.py index af01a9a1b..45479b16d 100644 --- a/certbot/tests/reverter_test.py +++ b/certbot/tests/reverter_test.py @@ -18,7 +18,7 @@ from certbot.tests import util as test_util class ReverterCheckpointLocalTest(test_util.ConfigTestCase): """Test the Reverter Class.""" def setUp(self): - super(ReverterCheckpointLocalTest, self).setUp() + super().setUp() from certbot.reverter import Reverter # Disable spurious errors... we are trying to test for them @@ -280,7 +280,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): class TestFullCheckpointsReverter(test_util.ConfigTestCase): """Tests functions having to deal with full checkpoints.""" def setUp(self): - super(TestFullCheckpointsReverter, self).setUp() + super().setUp() from certbot.reverter import Reverter # Disable spurious errors... logging.disable(logging.CRITICAL) diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 1e3a1ffd8..d7ef24b43 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -99,7 +99,7 @@ class BaseRenewableCertTest(test_util.ConfigTestCase): def setUp(self): from certbot._internal import storage - super(BaseRenewableCertTest, self).setUp() + super().setUp() # TODO: maybe provide NamespaceConfig.make_dirs? # TODO: main() should create those dirs, c.f. #902 @@ -846,7 +846,7 @@ class RenewableCertTests(BaseRenewableCertTest): class DeleteFilesTest(BaseRenewableCertTest): """Tests for certbot._internal.storage.delete_files""" def setUp(self): - super(DeleteFilesTest, self).setUp() + super().setUp() for kind in ALL_FOUR: kind_path = os.path.join(self.config.config_dir, "live", "example.org", @@ -936,7 +936,7 @@ class DeleteFilesTest(BaseRenewableCertTest): class CertPathForCertNameTest(BaseRenewableCertTest): """Test for certbot._internal.storage.cert_path_for_cert_name""" def setUp(self): - super(CertPathForCertNameTest, self).setUp() + super().setUp() self.config_file.write() self._write_out_ex_kinds() self.fullchain = os.path.join(self.config.config_dir, 'live', 'example.org', diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index 18947c342..e2f0218b8 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -108,7 +108,7 @@ class LockDirUntilExit(test_util.TempDirTestCase): return lock_dir_until_exit(*args, **kwargs) def setUp(self): - super(LockDirUntilExit, self).setUp() + super().setUp() # reset global state from other tests import certbot.util reload_module(certbot.util) @@ -164,7 +164,7 @@ class MakeOrVerifyDirTest(test_util.TempDirTestCase): """ def setUp(self): - super(MakeOrVerifyDirTest, self).setUp() + super().setUp() self.path = os.path.join(self.tempdir, "foo") filesystem.mkdir(self.path, 0o600) @@ -196,7 +196,7 @@ class UniqueFileTest(test_util.TempDirTestCase): """Tests for certbot.util.unique_file.""" def setUp(self): - super(UniqueFileTest, self).setUp() + super().setUp() self.default_name = os.path.join(self.tempdir, "foo.txt") @@ -284,7 +284,7 @@ class SafelyRemoveTest(test_util.TempDirTestCase): """Tests for certbot.util.safely_remove.""" def setUp(self): - super(SafelyRemoveTest, self).setUp() + super().setUp() self.path = os.path.join(self.tempdir, "foo") From 06bece36de0898c7cf22046ddc140c7dd5bcc8f5 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 9 Apr 2021 14:34:50 -0700 Subject: [PATCH 14/21] Ensure that mock is pinned (#8786) * List mock as a dependency in pyproject.toml * Add a code comment to help us remember to remove it when we can * Run pin.sh --- certbot/certbot/tests/util.py | 3 +++ tools/pinning/pyproject.toml | 7 +++++++ tools/requirements.txt | 11 ++++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/certbot/certbot/tests/util.py b/certbot/certbot/tests/util.py index b6a27a7c8..b892ad0a1 100644 --- a/certbot/certbot/tests/util.py +++ b/certbot/certbot/tests/util.py @@ -27,6 +27,9 @@ from certbot.compat import os from certbot.display import util as display_util try: + # When we remove this deprecated import, we should also remove the + # "external-mock" test environment and the mock dependency listed in + # tools/pinning/pyproject.toml. import mock warnings.warn( "The external mock module is being used for backwards compatibility " diff --git a/tools/pinning/pyproject.toml b/tools/pinning/pyproject.toml index 0107733d5..20a1f3bf2 100644 --- a/tools/pinning/pyproject.toml +++ b/tools/pinning/pyproject.toml @@ -35,6 +35,13 @@ acme = {path = "../../acme", extras = ["dev", "docs"]} windows-installer = {path = "../../windows-installer"} # Extra dependencies +# We install mock in our "external-mock" tox environment to test that we didn't +# break Certbot's test API which used to always use mock objects from the 3rd +# party mock library. We list the mock dependency here so that is pinned, but +# we don't depend on it in Certbot to avoid installing mock when it's not +# needed. This dependency can be removed here once Certbot's support for the +# 3rd party mock library has been dropped. +mock = "*" # Upgrading coverage, pylint, pytest, and some of pytest's plugins causes many # test failures so let's pin these packages back for now. coverage = "4.5.4" diff --git a/tools/requirements.txt b/tools/requirements.txt index e5a6d3be7..498c1e87a 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -18,8 +18,8 @@ backcall==0.2.0 bcrypt==3.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" beautifulsoup4==4.9.3; python_version >= "3.6" and python_version < "4.0" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -boto3==1.17.44; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -botocore==1.20.44; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +boto3==1.17.47; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +botocore==1.20.47; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" cachecontrol==0.12.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" cached-property==1.5.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") @@ -36,7 +36,7 @@ configobj==5.0.6; python_version >= "3.6" coverage==4.5.4; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0" and python_version < "4") crashtest==0.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") cryptography==3.4.7; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" or python_full_version >= "3.5.0" and python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" -decorator==5.0.5 +decorator==5.0.6 deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" distlib==0.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" distro==1.5.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" @@ -80,6 +80,7 @@ lazy-object-proxy==1.4.3; python_version >= "3.6" and python_full_version < "3.0 lockfile==0.12.2 markupsafe==1.1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" mccabe==0.6.1; python_version >= "3.6" +mock==4.0.3; python_version >= "3.6" msgpack==1.0.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" msrest==0.6.21; python_version >= "3.6" mypy-extensions==0.4.3; python_version >= "3.6" @@ -99,7 +100,7 @@ ply==3.11; python_version >= "3.6" poetry-core==1.0.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" poetry==1.1.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" prompt-toolkit==3.0.3 -protobuf==3.15.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +protobuf==3.15.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" ptyprocess==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" @@ -157,7 +158,7 @@ tldextract==3.1.0; python_version >= "3.6" and python_version < "4.0" toml==0.10.2; python_version == "3.6" and python_full_version < "3.0.0" or python_version > "3.6" and python_full_version < "3.0.0" or python_version == "3.6" and python_full_version >= "3.5.0" or python_version > "3.6" and python_full_version >= "3.5.0" tomlkit==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" tox==3.23.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -tqdm==4.59.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" +tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" traitlets==4.3.3 twine==3.3.0; python_version >= "3.6" typed-ast==1.4.2; implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.6" From e33090f2827558962984e0fa6cd16e653307f412 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 12 Apr 2021 13:36:38 -0700 Subject: [PATCH 15/21] Fix homebrew (#8791) The macOS tests run on this PR would fail without this change. * brew update * add link to upstream issue --- .azure-pipelines/templates/steps/tox-steps.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.azure-pipelines/templates/steps/tox-steps.yml b/.azure-pipelines/templates/steps/tox-steps.yml index ecf3d6032..3e5fb995d 100644 --- a/.azure-pipelines/templates/steps/tox-steps.yml +++ b/.azure-pipelines/templates/steps/tox-steps.yml @@ -1,6 +1,10 @@ steps: + # We run brew update because we've seen attempts to install an older version + # of a package fail. See + # https://github.com/actions/virtual-environments/issues/3165. - bash: | set -e + brew update brew install augeas condition: startswith(variables['IMAGE_NAME'], 'macOS') displayName: Install MacOS dependencies From 0dbe17bbd48b97d41754b9618c302ab3c4aa1421 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Tue, 13 Apr 2021 20:18:49 +0200 Subject: [PATCH 16/21] Define OS options by a dedicated object in Apache configurator (#8778) In https://github.com/certbot/certbot/pull/8748#discussion_r605457670 we discussed about changing the dict used to set OS options for Apache configurators into a dedicated object. * Create _OsOptions class to configure the os specific options of the Apache configurators * Fix tests * Clean imports * Fix naming * Fix compatibility tests * Rename a class * Ensure restart_cmd_alt is set for specific OSes. * Add docstring * Fix override * Fix coverage --- .../certbot_apache/_internal/configurator.py | 143 ++++++++++-------- .../certbot_apache/_internal/override_arch.py | 9 +- .../_internal/override_centos.py | 15 +- .../_internal/override_darwin.py | 11 +- .../_internal/override_debian.py | 20 +-- .../_internal/override_fedora.py | 22 +-- .../_internal/override_gentoo.py | 25 +-- .../certbot_apache/_internal/override_suse.py | 9 +- .../certbot_apache/_internal/parser.py | 8 +- certbot-apache/tests/configurator_test.py | 15 +- certbot-apache/tests/parser_test.py | 4 +- certbot-apache/tests/util.py | 4 +- .../configurators/apache/common.py | 4 +- 13 files changed, 129 insertions(+), 160 deletions(-) diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index 5ef9083e6..abf199793 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -8,7 +8,6 @@ import logging import re import socket import time -from typing import cast from typing import DefaultDict from typing import Dict from typing import List @@ -51,6 +50,47 @@ except ImportError: # pragma: no cover logger = logging.getLogger(__name__) +class OsOptions: + """ + Dedicated class to describe the OS specificities (eg. paths, binary names) + that the Apache configurator needs to be aware to operate properly. + """ + def __init__(self, + server_root="/etc/apache2", + vhost_root="/etc/apache2/sites-available", + vhost_files="*", + logs_root="/var/log/apache2", + ctl="apache2ctl", + version_cmd: Optional[List[str]] = None, + restart_cmd: Optional[List[str]] = None, + restart_cmd_alt: Optional[List[str]] = None, + conftest_cmd: Optional[List[str]] = None, + enmod: Optional[str] = None, + dismod: Optional[str] = None, + le_vhost_ext="-le-ssl.conf", + handle_modules=False, + handle_sites=False, + challenge_location="/etc/apache2", + apache_bin: Optional[str] = None, + ): + self.server_root = server_root + self.vhost_root = vhost_root + self.vhost_files = vhost_files + self.logs_root = logs_root + self.ctl = ctl + self.version_cmd = ['apache2ctl', '-v'] if not version_cmd else version_cmd + self.restart_cmd = ['apache2ctl', 'graceful'] if not restart_cmd else restart_cmd + self.restart_cmd_alt = restart_cmd_alt + self.conftest_cmd = ['apache2ctl', 'configtest'] if not conftest_cmd else conftest_cmd + self.enmod = enmod + self.dismod = dismod + self.le_vhost_ext = le_vhost_ext + self.handle_modules = handle_modules + self.handle_sites = handle_sites + self.challenge_location = challenge_location + self.bin = apache_bin + + # TODO: Augeas sections ie. , beginning and closing # tags need to be the same case, otherwise Augeas doesn't recognize them. # This is not able to be completely remedied by regular expressions because @@ -106,27 +146,7 @@ class ApacheConfigurator(common.Installer): " change depending on the operating system Certbot is run on.)" ) - OS_DEFAULTS = dict( - server_root="/etc/apache2", - vhost_root="/etc/apache2/sites-available", - vhost_files="*", - logs_root="/var/log/apache2", - ctl="apache2ctl", - version_cmd=['apache2ctl', '-v'], - restart_cmd=['apache2ctl', 'graceful'], - conftest_cmd=['apache2ctl', 'configtest'], - enmod=None, - dismod=None, - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, - challenge_location="/etc/apache2", - bin=None - ) - - def option(self, key): - """Get a value from options""" - return self.options.get(key) + OS_DEFAULTS = OsOptions() def pick_apache_config(self, warn_on_no_mod_ssl=True): """ @@ -156,14 +176,14 @@ class ApacheConfigurator(common.Installer): for o in opts: # Config options use dashes instead of underscores if self.conf(o.replace("_", "-")) is not None: - self.options[o] = self.conf(o.replace("_", "-")) + setattr(self.options, o, self.conf(o.replace("_", "-"))) else: - self.options[o] = self.OS_DEFAULTS[o] + setattr(self.options, o, getattr(self.OS_DEFAULTS, o)) # Special cases - cast(List[str], self.options["version_cmd"])[0] = self.option("ctl") - cast(List[str], self.options["restart_cmd"])[0] = self.option("ctl") - cast(List[str], self.options["conftest_cmd"])[0] = self.option("ctl") + self.options.version_cmd[0] = self.options.ctl + self.options.restart_cmd[0] = self.options.ctl + self.options.conftest_cmd[0] = self.options.ctl @classmethod def add_parser_arguments(cls, add): @@ -178,30 +198,30 @@ class ApacheConfigurator(common.Installer): else: # cls.OS_DEFAULTS can be distribution specific, see override classes DEFAULTS = cls.OS_DEFAULTS - add("enmod", default=DEFAULTS["enmod"], + add("enmod", default=DEFAULTS.enmod, help="Path to the Apache 'a2enmod' binary") - add("dismod", default=DEFAULTS["dismod"], + add("dismod", default=DEFAULTS.dismod, help="Path to the Apache 'a2dismod' binary") - add("le-vhost-ext", default=DEFAULTS["le_vhost_ext"], + add("le-vhost-ext", default=DEFAULTS.le_vhost_ext, help="SSL vhost configuration extension") - add("server-root", default=DEFAULTS["server_root"], + add("server-root", default=DEFAULTS.server_root, help="Apache server root directory") add("vhost-root", default=None, help="Apache server VirtualHost configuration root") - add("logs-root", default=DEFAULTS["logs_root"], + add("logs-root", default=DEFAULTS.logs_root, help="Apache server logs directory") add("challenge-location", - default=DEFAULTS["challenge_location"], + default=DEFAULTS.challenge_location, help="Directory path for challenge configuration") - add("handle-modules", default=DEFAULTS["handle_modules"], + add("handle-modules", default=DEFAULTS.handle_modules, help="Let installer handle enabling required modules for you " + "(Only Ubuntu/Debian currently)") - add("handle-sites", default=DEFAULTS["handle_sites"], + add("handle-sites", default=DEFAULTS.handle_sites, help="Let installer handle enabling sites for you " + "(Only Ubuntu/Debian currently)") - add("ctl", default=DEFAULTS["ctl"], + add("ctl", default=DEFAULTS.ctl, help="Full path to Apache control script") - add("bin", default=DEFAULTS["bin"], + add("bin", default=DEFAULTS.bin, help="Full path to apache2/httpd binary") def __init__(self, *args, **kwargs): @@ -290,8 +310,8 @@ class ApacheConfigurator(common.Installer): ssl_module_location = self.parser.standard_path_from_server_root(ssl_module_location) else: # Possibility B: ssl_module is statically linked into Apache - if self.option("bin"): - ssl_module_location = self.option("bin") + if self.options.bin: + ssl_module_location = self.options.bin else: logger.warning("ssl_module is statically linked but --apache-bin is " "missing; not disabling session tickets.") @@ -321,7 +341,7 @@ class ApacheConfigurator(common.Installer): self._prepare_options() # Verify Apache is installed - self._verify_exe_availability(self.option("ctl")) + self._verify_exe_availability(self.options.ctl) # Make sure configuration is valid self.config_test() @@ -361,20 +381,20 @@ class ApacheConfigurator(common.Installer): # We may try to enable mod_ssl later. If so, we shouldn't warn if we can't find it now. # This is currently only true for debian/ubuntu. - warn_on_no_mod_ssl = not self.option("handle_modules") + warn_on_no_mod_ssl = not self.options.handle_modules self.install_ssl_options_conf(self.mod_ssl_conf, self.updated_mod_ssl_conf_digest, warn_on_no_mod_ssl) # Prevent two Apache plugins from modifying a config at once try: - util.lock_dir_until_exit(self.option("server_root")) + util.lock_dir_until_exit(self.options.server_root) except (OSError, errors.LockError): logger.debug("Encountered error:", exc_info=True) raise errors.PluginError( "Unable to create a lock file in {0}. Are you running" " Certbot with sufficient privileges to modify your" - " Apache configuration?".format(self.option("server_root"))) + " Apache configuration?".format(self.options.server_root)) self._prepared = True def save(self, title=None, temporary=False): @@ -449,7 +469,7 @@ class ApacheConfigurator(common.Installer): """Initializes the ApacheParser""" # If user provided vhost_root value in command line, use it return parser.ApacheParser( - self.option("server_root"), self.conf("vhost-root"), + self.options.server_root, self.conf("vhost-root"), self.version, configurator=self) def get_parsernode_root(self, metadata): @@ -457,9 +477,9 @@ class ApacheConfigurator(common.Installer): if HAS_APACHECONFIG: apache_vars = {} - apache_vars["defines"] = apache_util.parse_defines(self.option("ctl")) - apache_vars["includes"] = apache_util.parse_includes(self.option("ctl")) - apache_vars["modules"] = apache_util.parse_modules(self.option("ctl")) + apache_vars["defines"] = apache_util.parse_defines(self.options.ctl) + apache_vars["includes"] = apache_util.parse_includes(self.options.ctl) + apache_vars["modules"] = apache_util.parse_modules(self.options.ctl) metadata["apache_vars"] = apache_vars with open(self.parser.loc["root"]) as f: @@ -1311,7 +1331,7 @@ class ApacheConfigurator(common.Installer): :param boolean temp: If the change is temporary """ - if self.option("handle_modules"): + if self.options.handle_modules: if self.version >= (2, 4) and ("socache_shmcb_module" not in self.parser.modules): self.enable_mod("socache_shmcb", temp=temp) @@ -1331,7 +1351,7 @@ class ApacheConfigurator(common.Installer): Duplicates vhost and adds default ssl options New vhost will reside as (nonssl_vhost.path) + - ``self.option("le_vhost_ext")`` + ``self.options.le_vhost_ext`` .. note:: This function saves the configuration @@ -1430,15 +1450,15 @@ class ApacheConfigurator(common.Installer): """ if self.conf("vhost-root") and os.path.exists(self.conf("vhost-root")): - fp = os.path.join(filesystem.realpath(self.option("vhost_root")), + fp = os.path.join(filesystem.realpath(self.options.vhost_root), os.path.basename(non_ssl_vh_fp)) else: # Use non-ssl filepath fp = filesystem.realpath(non_ssl_vh_fp) if fp.endswith(".conf"): - return fp[:-(len(".conf"))] + self.option("le_vhost_ext") - return fp + self.option("le_vhost_ext") + return fp[:-(len(".conf"))] + self.options.le_vhost_ext + return fp + self.options.le_vhost_ext def _sift_rewrite_rule(self, line): """Decides whether a line should be copied to a SSL vhost. @@ -2282,7 +2302,7 @@ class ApacheConfigurator(common.Installer): addr in self._get_proposed_addrs(ssl_vhost)), servername, serveralias, " ".join(rewrite_rule_args), - self.option("logs_root"))) + self.options.logs_root)) def _write_out_redirect(self, ssl_vhost, text): # This is the default name @@ -2294,7 +2314,7 @@ class ApacheConfigurator(common.Installer): if len(ssl_vhost.name) < (255 - (len(redirect_filename) + 1)): redirect_filename = "le-redirect-%s.conf" % ssl_vhost.name - redirect_filepath = os.path.join(self.option("vhost_root"), + redirect_filepath = os.path.join(self.options.vhost_root, redirect_filename) # Register the new file that will be created @@ -2414,19 +2434,18 @@ class ApacheConfigurator(common.Installer): """ try: - util.run_script(self.option("restart_cmd")) + util.run_script(self.options.restart_cmd) except errors.SubprocessError as err: logger.info("Unable to restart apache using %s", - self.option("restart_cmd")) - alt_restart = self.option("restart_cmd_alt") + self.options.restart_cmd) + alt_restart = self.options.restart_cmd_alt if alt_restart: logger.debug("Trying alternative restart command: %s", alt_restart) # There is an alternative restart command available # This usually is "restart" verb while original is "graceful" try: - util.run_script(self.option( - "restart_cmd_alt")) + util.run_script(self.options.restart_cmd_alt) return except errors.SubprocessError as secerr: error = str(secerr) @@ -2441,7 +2460,7 @@ class ApacheConfigurator(common.Installer): """ try: - util.run_script(self.option("conftest_cmd")) + util.run_script(self.options.conftest_cmd) except errors.SubprocessError as err: raise errors.MisconfigurationError(str(err)) @@ -2457,11 +2476,11 @@ class ApacheConfigurator(common.Installer): """ try: - stdout, _ = util.run_script(self.option("version_cmd")) + stdout, _ = util.run_script(self.options.version_cmd) except errors.SubprocessError: raise errors.PluginError( "Unable to run %s -v" % - self.option("version_cmd")) + self.options.version_cmd) regex = re.compile(r"Apache/([0-9\.]*)", re.IGNORECASE) matches = regex.findall(stdout) diff --git a/certbot-apache/certbot_apache/_internal/override_arch.py b/certbot-apache/certbot_apache/_internal/override_arch.py index 1c3aed1dc..30d161a4e 100644 --- a/certbot-apache/certbot_apache/_internal/override_arch.py +++ b/certbot-apache/certbot_apache/_internal/override_arch.py @@ -3,13 +3,14 @@ import zope.interface from certbot import interfaces from certbot_apache._internal import configurator +from certbot_apache._internal.configurator import OsOptions @zope.interface.provider(interfaces.IPluginFactory) class ArchConfigurator(configurator.ApacheConfigurator): """Arch Linux specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( + OS_DEFAULTS = OsOptions( server_root="/etc/httpd", vhost_root="/etc/httpd/conf", vhost_files="*.conf", @@ -18,11 +19,5 @@ class ArchConfigurator(configurator.ApacheConfigurator): version_cmd=['apachectl', '-v'], restart_cmd=['apachectl', 'graceful'], conftest_cmd=['apachectl', 'configtest'], - enmod=None, - dismod=None, - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, challenge_location="/etc/httpd/conf", - bin=None, ) diff --git a/certbot-apache/certbot_apache/_internal/override_centos.py b/certbot-apache/certbot_apache/_internal/override_centos.py index 98dc80e0b..c1a69885c 100644 --- a/certbot-apache/certbot_apache/_internal/override_centos.py +++ b/certbot-apache/certbot_apache/_internal/override_centos.py @@ -12,6 +12,7 @@ from certbot.errors import MisconfigurationError from certbot_apache._internal import apache_util from certbot_apache._internal import configurator from certbot_apache._internal import parser +from certbot_apache._internal.configurator import OsOptions logger = logging.getLogger(__name__) @@ -20,7 +21,7 @@ logger = logging.getLogger(__name__) class CentOSConfigurator(configurator.ApacheConfigurator): """CentOS specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( + OS_DEFAULTS = OsOptions( server_root="/etc/httpd", vhost_root="/etc/httpd/conf.d", vhost_files="*.conf", @@ -30,13 +31,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator): restart_cmd=['apachectl', 'graceful'], restart_cmd_alt=['apachectl', 'restart'], conftest_cmd=['apachectl', 'configtest'], - enmod=None, - dismod=None, - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, challenge_location="/etc/httpd/conf.d", - bin=None, ) def config_test(self): @@ -77,12 +72,14 @@ class CentOSConfigurator(configurator.ApacheConfigurator): alternative restart cmd used in CentOS. """ super()._prepare_options() - cast(List[str], self.options["restart_cmd_alt"])[0] = self.option("ctl") + if not self.options.restart_cmd_alt: # pragma: no cover + raise ValueError("OS option restart_cmd_alt must be set for CentOS.") + self.options.restart_cmd_alt[0] = self.options.ctl def get_parser(self): """Initializes the ApacheParser""" return CentOSParser( - self.option("server_root"), self.option("vhost_root"), + self.options.server_root, self.options.vhost_root, self.version, configurator=self) def _deploy_cert(self, *args, **kwargs): # pylint: disable=arguments-differ diff --git a/certbot-apache/certbot_apache/_internal/override_darwin.py b/certbot-apache/certbot_apache/_internal/override_darwin.py index 106f5fbab..e1dca7f5e 100644 --- a/certbot-apache/certbot_apache/_internal/override_darwin.py +++ b/certbot-apache/certbot_apache/_internal/override_darwin.py @@ -3,26 +3,19 @@ import zope.interface from certbot import interfaces from certbot_apache._internal import configurator +from certbot_apache._internal.configurator import OsOptions @zope.interface.provider(interfaces.IPluginFactory) class DarwinConfigurator(configurator.ApacheConfigurator): """macOS specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( - server_root="/etc/apache2", + OS_DEFAULTS = OsOptions( vhost_root="/etc/apache2/other", vhost_files="*.conf", - logs_root="/var/log/apache2", ctl="apachectl", version_cmd=['apachectl', '-v'], restart_cmd=['apachectl', 'graceful'], conftest_cmd=['apachectl', 'configtest'], - enmod=None, - dismod=None, - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, challenge_location="/etc/apache2/other", - bin=None, ) diff --git a/certbot-apache/certbot_apache/_internal/override_debian.py b/certbot-apache/certbot_apache/_internal/override_debian.py index c5f3b6e1a..7f12f4bbc 100644 --- a/certbot-apache/certbot_apache/_internal/override_debian.py +++ b/certbot-apache/certbot_apache/_internal/override_debian.py @@ -10,6 +10,7 @@ from certbot.compat import filesystem from certbot.compat import os from certbot_apache._internal import apache_util from certbot_apache._internal import configurator +from certbot_apache._internal.configurator import OsOptions logger = logging.getLogger(__name__) @@ -18,22 +19,11 @@ logger = logging.getLogger(__name__) class DebianConfigurator(configurator.ApacheConfigurator): """Debian specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( - server_root="/etc/apache2", - vhost_root="/etc/apache2/sites-available", - vhost_files="*", - logs_root="/var/log/apache2", - ctl="apache2ctl", - version_cmd=['apache2ctl', '-v'], - restart_cmd=['apache2ctl', 'graceful'], - conftest_cmd=['apache2ctl', 'configtest'], + OS_DEFAULTS = OsOptions( enmod="a2enmod", dismod="a2dismod", - le_vhost_ext="-le-ssl.conf", handle_modules=True, handle_sites=True, - challenge_location="/etc/apache2", - bin=None, ) def enable_site(self, vhost): @@ -132,11 +122,11 @@ class DebianConfigurator(configurator.ApacheConfigurator): # Generate reversal command. # Try to be safe here... check that we can probably reverse before # applying enmod command - if not util.exe_exists(self.option("dismod")): + if not util.exe_exists(self.options.dismod): raise errors.MisconfigurationError( "Unable to find a2dismod, please make sure a2enmod and " "a2dismod are configured correctly for certbot.") self.reverter.register_undo_command( - temp, [self.option("dismod"), "-f", mod_name]) - util.run_script([self.option("enmod"), mod_name]) + temp, [self.options.dismod, "-f", mod_name]) + util.run_script([self.options.enmod, mod_name]) diff --git a/certbot-apache/certbot_apache/_internal/override_fedora.py b/certbot-apache/certbot_apache/_internal/override_fedora.py index 0f7970460..3b947a823 100644 --- a/certbot-apache/certbot_apache/_internal/override_fedora.py +++ b/certbot-apache/certbot_apache/_internal/override_fedora.py @@ -1,7 +1,4 @@ """ Distribution specific override class for Fedora 29+ """ -from typing import cast -from typing import List - import zope.interface from certbot import errors @@ -10,13 +7,14 @@ from certbot import util from certbot_apache._internal import apache_util from certbot_apache._internal import configurator from certbot_apache._internal import parser +from certbot_apache._internal.configurator import OsOptions @zope.interface.provider(interfaces.IPluginFactory) class FedoraConfigurator(configurator.ApacheConfigurator): """Fedora 29+ specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( + OS_DEFAULTS = OsOptions( server_root="/etc/httpd", vhost_root="/etc/httpd/conf.d", vhost_files="*.conf", @@ -26,13 +24,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): restart_cmd=['apachectl', 'graceful'], restart_cmd_alt=['apachectl', 'restart'], conftest_cmd=['apachectl', 'configtest'], - enmod=None, - dismod=None, - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, challenge_location="/etc/httpd/conf.d", - bin=None, ) def config_test(self): @@ -50,7 +42,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): def get_parser(self): """Initializes the ApacheParser""" return FedoraParser( - self.option("server_root"), self.option("vhost_root"), + self.options.server_root, self.options.vhost_root, self.version, configurator=self) def _try_restart_fedora(self): @@ -72,9 +64,11 @@ class FedoraConfigurator(configurator.ApacheConfigurator): of Fedora to restart httpd. """ super()._prepare_options() - cast(List[str], self.options["restart_cmd"])[0] = 'apachectl' - cast(List[str], self.options["restart_cmd_alt"])[0] = 'apachectl' - cast(List[str], self.options["conftest_cmd"])[0] = 'apachectl' + self.options.restart_cmd[0] = 'apachectl' + if not self.options.restart_cmd_alt: # pragma: no cover + raise ValueError("OS option restart_cmd_alt must be set for Fedora.") + self.options.restart_cmd_alt[0] = 'apachectl' + self.options.conftest_cmd[0] = 'apachectl' class FedoraParser(parser.ApacheParser): diff --git a/certbot-apache/certbot_apache/_internal/override_gentoo.py b/certbot-apache/certbot_apache/_internal/override_gentoo.py index 484e15532..1b86c925e 100644 --- a/certbot-apache/certbot_apache/_internal/override_gentoo.py +++ b/certbot-apache/certbot_apache/_internal/override_gentoo.py @@ -1,36 +1,23 @@ """ Distribution specific override class for Gentoo Linux """ -from typing import cast -from typing import List - import zope.interface from certbot import interfaces from certbot_apache._internal import apache_util from certbot_apache._internal import configurator from certbot_apache._internal import parser +from certbot_apache._internal.configurator import OsOptions @zope.interface.provider(interfaces.IPluginFactory) class GentooConfigurator(configurator.ApacheConfigurator): """Gentoo specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( + OS_DEFAULTS = OsOptions( server_root="/etc/apache2", vhost_root="/etc/apache2/vhosts.d", vhost_files="*.conf", - logs_root="/var/log/apache2", - ctl="apache2ctl", - version_cmd=['apache2ctl', '-v'], - restart_cmd=['apache2ctl', 'graceful'], restart_cmd_alt=['apache2ctl', 'restart'], - conftest_cmd=['apache2ctl', 'configtest'], - enmod=None, - dismod=None, - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, challenge_location="/etc/apache2/vhosts.d", - bin=None, ) def _prepare_options(self): @@ -39,12 +26,14 @@ class GentooConfigurator(configurator.ApacheConfigurator): alternative restart cmd used in Gentoo. """ super()._prepare_options() - cast(List[str], self.options["restart_cmd_alt"])[0] = self.option("ctl") + if not self.options.restart_cmd_alt: # pragma: no cover + raise ValueError("OS option restart_cmd_alt must be set for Gentoo.") + self.options.restart_cmd_alt[0] = self.options.ctl def get_parser(self): """Initializes the ApacheParser""" return GentooParser( - self.option("server_root"), self.option("vhost_root"), + self.options.server_root, self.options.vhost_root, self.version, configurator=self) @@ -69,7 +58,7 @@ class GentooParser(parser.ApacheParser): def update_modules(self): """Get loaded modules from httpd process, and add them to DOM""" - mod_cmd = [self.configurator.option("ctl"), "modules"] + mod_cmd = [self.configurator.options.ctl, "modules"] matches = apache_util.parse_from_subprocess(mod_cmd, r"(.*)_module") for mod in matches: self.add_mod(mod.strip()) diff --git a/certbot-apache/certbot_apache/_internal/override_suse.py b/certbot-apache/certbot_apache/_internal/override_suse.py index afce98dfa..d692fd239 100644 --- a/certbot-apache/certbot_apache/_internal/override_suse.py +++ b/certbot-apache/certbot_apache/_internal/override_suse.py @@ -3,26 +3,21 @@ import zope.interface from certbot import interfaces from certbot_apache._internal import configurator +from certbot_apache._internal.configurator import OsOptions @zope.interface.provider(interfaces.IPluginFactory) class OpenSUSEConfigurator(configurator.ApacheConfigurator): """OpenSUSE specific ApacheConfigurator override class""" - OS_DEFAULTS = dict( - server_root="/etc/apache2", + OS_DEFAULTS = OsOptions( vhost_root="/etc/apache2/vhosts.d", vhost_files="*.conf", - logs_root="/var/log/apache2", ctl="apachectl", version_cmd=['apachectl', '-v'], restart_cmd=['apachectl', 'graceful'], conftest_cmd=['apachectl', 'configtest'], enmod="a2enmod", dismod="a2dismod", - le_vhost_ext="-le-ssl.conf", - handle_modules=False, - handle_sites=False, challenge_location="/etc/apache2/vhosts.d", - bin=None, ) diff --git a/certbot-apache/certbot_apache/_internal/parser.py b/certbot-apache/certbot_apache/_internal/parser.py index ff7e90f3b..141991ccc 100644 --- a/certbot-apache/certbot_apache/_internal/parser.py +++ b/certbot-apache/certbot_apache/_internal/parser.py @@ -81,7 +81,7 @@ class ApacheParser: # Must also attempt to parse additional virtual host root if vhostroot: self.parse_file(os.path.abspath(vhostroot) + "/" + - self.configurator.option("vhost_files")) + self.configurator.options.vhost_files) # check to see if there were unparsed define statements if version < (2, 4): @@ -282,7 +282,7 @@ class ApacheParser: def update_defines(self): """Updates the dictionary of known variables in the configuration""" - self.variables = apache_util.parse_defines(self.configurator.option("ctl")) + self.variables = apache_util.parse_defines(self.configurator.options.ctl) def update_includes(self): """Get includes from httpd process, and add them to DOM if needed""" @@ -292,7 +292,7 @@ class ApacheParser: # configuration files _ = self.find_dir("Include") - matches = apache_util.parse_includes(self.configurator.option("ctl")) + matches = apache_util.parse_includes(self.configurator.options.ctl) if matches: for i in matches: if not self.parsed_in_current(i): @@ -301,7 +301,7 @@ class ApacheParser: def update_modules(self): """Get loaded modules from httpd process, and add them to DOM""" - matches = apache_util.parse_modules(self.configurator.option("ctl")) + matches = apache_util.parse_modules(self.configurator.options.ctl) for mod in matches: self.add_mod(mod.strip()) diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py index ad1f5f04d..8620955aa 100644 --- a/certbot-apache/tests/configurator_test.py +++ b/certbot-apache/tests/configurator_test.py @@ -103,9 +103,9 @@ class MultipleVhostsTest(util.ApacheTest): "handle_modules", "handle_sites", "ctl"] exp = {} - for k in ApacheConfigurator.OS_DEFAULTS: + for k in ApacheConfigurator.OS_DEFAULTS.__dict__.keys(): if k in parserargs: - exp[k.replace("_", "-")] = ApacheConfigurator.OS_DEFAULTS[k] + exp[k.replace("_", "-")] = getattr(ApacheConfigurator.OS_DEFAULTS, k) # Special cases exp["vhost-root"] = None @@ -128,14 +128,13 @@ class MultipleVhostsTest(util.ApacheTest): def test_all_configurators_defaults_defined(self): from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES from certbot_apache._internal.configurator import ApacheConfigurator - parameters = set(ApacheConfigurator.OS_DEFAULTS.keys()) + parameters = set(ApacheConfigurator.OS_DEFAULTS.__dict__.keys()) for cls in OVERRIDE_CLASSES.values(): - self.assertTrue(parameters.issubset(set(cls.OS_DEFAULTS.keys()))) + self.assertTrue(parameters.issubset(set(cls.OS_DEFAULTS.__dict__.keys()))) def test_constant(self): self.assertTrue("debian_apache_2_4/multiple_vhosts/apache" in - self.config.option("server_root")) - self.assertEqual(self.config.option("nonexistent"), None) + self.config.options.server_root) @certbot_util.patch_get_utility() def test_get_all_names(self, mock_getutility): @@ -1774,7 +1773,7 @@ class InstallSslOptionsConfTest(util.ApacheTest): # ssl_module statically linked self.config._openssl_version = None self.config.parser.modules['ssl_module'] = None - self.config.options['bin'] = '/fake/path/to/httpd' + self.config.options.bin = '/fake/path/to/httpd' with mock.patch("certbot_apache._internal.configurator." "ApacheConfigurator._open_module_file") as mock_omf: mock_omf.return_value = some_string_contents @@ -1810,7 +1809,7 @@ class InstallSslOptionsConfTest(util.ApacheTest): # When ssl_module is statically linked but --apache-bin not provided self.config._openssl_version = None - self.config.options['bin'] = None + self.config.options.bin = None self.config.parser.modules['ssl_module'] = None with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: self.assertEqual(self.config.openssl_version(), None) diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py index 37d4eb782..e30eca153 100644 --- a/certbot-apache/tests/parser_test.py +++ b/certbot-apache/tests/parser_test.py @@ -305,11 +305,9 @@ class BasicParserTest(util.ParserTest): self.assertRaises( errors.PluginError, self.parser.update_runtime_variables) - @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.option") @mock.patch("certbot_apache._internal.apache_util.subprocess.Popen") - def test_update_runtime_vars_bad_ctl(self, mock_popen, mock_opt): + def test_update_runtime_vars_bad_ctl(self, mock_popen): mock_popen.side_effect = OSError - mock_opt.return_value = "nonexistent" self.assertRaises( errors.MisconfigurationError, self.parser.update_runtime_variables) diff --git a/certbot-apache/tests/util.py b/certbot-apache/tests/util.py index bd522d736..a0b44d188 100644 --- a/certbot-apache/tests/util.py +++ b/certbot-apache/tests/util.py @@ -123,11 +123,11 @@ def get_apache_configurator( version=version, use_parsernode=use_parsernode, openssl_version=openssl_version) if not conf_vhost_path: - config_class.OS_DEFAULTS["vhost_root"] = vhost_path + config_class.OS_DEFAULTS.vhost_root = vhost_path else: # Custom virtualhost path was requested config.config.apache_vhost_root = conf_vhost_path - config.config.apache_ctl = config_class.OS_DEFAULTS["ctl"] + config.config.apache_ctl = config_class.OS_DEFAULTS.ctl config.prepare() return config diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index f62635610..909a9d37c 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -54,9 +54,9 @@ class Proxy(configurators_common.Proxy): def _prepare_configurator(self): """Prepares the Apache plugin for testing""" - for k in entrypoint.ENTRYPOINT.OS_DEFAULTS: + for k in entrypoint.ENTRYPOINT.OS_DEFAULTS.__dict__.keys(): setattr(self.le_config, "apache_" + k, - entrypoint.ENTRYPOINT.OS_DEFAULTS[k]) + getattr(entrypoint.ENTRYPOINT.OS_DEFAULTS, k)) self._configurator = entrypoint.ENTRYPOINT( config=configuration.NamespaceConfig(self.le_config), From 4a404e2a4a251442240896cc985e311f13e283d5 Mon Sep 17 00:00:00 2001 From: osirisinferi Date: Thu, 15 Apr 2021 00:36:14 +0200 Subject: [PATCH 17/21] Expand manual DNS challenge instructions to include mention of propagation time and tool to check this (#8770) * Expand manual DNS challenge instructions * Less jargon Co-authored-by: ohemorange * Less is more Co-authored-by: ohemorange * Make more clear where to look at Googles Toolbox * Reshuffle text * Show verify instructions only on last dns-01 challenge * Swap domain and value * Remove '(also)' * Fix DNS verify message for mixed challenge types * Add a lengthy comment about why there's a full stop after `{domain}` * Typo Co-authored-by: ohemorange --- certbot/certbot/_internal/plugins/manual.py | 43 +++++++++++++++++---- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/certbot/certbot/_internal/plugins/manual.py b/certbot/certbot/_internal/plugins/manual.py index 5423ec1d9..dec73a1ed 100644 --- a/certbot/certbot/_internal/plugins/manual.py +++ b/certbot/certbot/_internal/plugins/manual.py @@ -43,13 +43,30 @@ class Authenticator(common.Plugin): '$CERTBOT_REMAINING_CHALLENGES will be equal to the number of challenges that ' 'remain after the current one, and $CERTBOT_ALL_DOMAINS contains a comma-separated ' 'list of all domains that are challenged for the current certificate.') + # Include the full stop at the end of the FQDN in the instructions below for the null + # label of the DNS root, as stated in section 3.1 of RFC 1035. While not necessary + # for most day to day usage of hostnames, when adding FQDNs to a DNS zone editor, this + # full stop is often mandatory. Without a full stop, the entered name is often seen as + # relative to the DNS zone origin, which could lead to entries for, e.g.: + # _acme-challenge.example.com.example.com. For users unaware of this subtle detail, + # including the trailing full stop in the DNS instructions below might avert this issue. _DNS_INSTRUCTIONS = """\ -Please deploy a DNS TXT record under the name -{domain} with the following value: +Please deploy a DNS TXT record under the name: + +{domain}. + +with the following value: {validation} - -Before continuing, verify the record is deployed.""" +""" + _DNS_VERIFY_INSTRUCTIONS = """ +Before continuing, verify the TXT record has been deployed. Depending on the DNS +provider, this may take some time, from a few seconds to multiple minutes. You can +check if it has finished deploying with aid of online tools, such as the Google +Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/{domain}. +Look for one or more bolded line(s) below the line ';ANSWER'. It should show the +value(s) you've just added. +""" _HTTP_INSTRUCTIONS = """\ Create a file containing just this data: @@ -114,11 +131,15 @@ permitted by DNS standards.) def perform(self, achalls): # pylint: disable=missing-function-docstring responses = [] - for achall in achalls: + last_dns_achall = 0 + for i, achall in enumerate(achalls): + if isinstance(achall.chall, challenges.DNS01): + last_dns_achall = i + for i, achall in enumerate(achalls): if self.conf('auth-hook'): self._perform_achall_with_script(achall, achalls) else: - self._perform_achall_manually(achall) + self._perform_achall_manually(achall, i == last_dns_achall) responses.append(achall.response(achall.account_key)) return responses @@ -136,7 +157,7 @@ permitted by DNS standards.) env['CERTBOT_AUTH_OUTPUT'] = out.strip() self.env[achall] = env - def _perform_achall_manually(self, achall): + def _perform_achall_manually(self, achall, last_dns_achall=False): validation = achall.validation(achall.account_key) if isinstance(achall.chall, challenges.HTTP01): msg = self._HTTP_INSTRUCTIONS.format( @@ -152,7 +173,15 @@ permitted by DNS standards.) if self.subsequent_dns_challenge: # 2nd or later dns-01 challenge msg += self._SUBSEQUENT_DNS_CHALLENGE_INSTRUCTIONS + elif self.subsequent_any_challenge: + # 1st dns-01 challenge, but 2nd or later *any* challenge, so + # instruct user not to remove any previous http-01 challenge + msg += self._SUBSEQUENT_CHALLENGE_INSTRUCTIONS self.subsequent_dns_challenge = True + if last_dns_achall: + # last dns-01 challenge + msg += self._DNS_VERIFY_INSTRUCTIONS.format( + domain=achall.validation_domain_name(achall.domain)) elif self.subsequent_any_challenge: # 2nd or later challenge of another type msg += self._SUBSEQUENT_CHALLENGE_INSTRUCTIONS From fb967fda1532222c555a550c88303f02026e0bb1 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 20 Apr 2021 12:12:45 -0700 Subject: [PATCH 18/21] pin cython (#8794) --- tools/pinning/pyproject.toml | 7 +++++++ tools/requirements.txt | 23 ++++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/pinning/pyproject.toml b/tools/pinning/pyproject.toml index 20a1f3bf2..34fea18a6 100644 --- a/tools/pinning/pyproject.toml +++ b/tools/pinning/pyproject.toml @@ -35,6 +35,13 @@ acme = {path = "../../acme", extras = ["dev", "docs"]} windows-installer = {path = "../../windows-installer"} # Extra dependencies +# As of writing this, cython is a build dependency of pyyaml. Since there +# doesn't appear to be a good way to automatically track down and pin build +# dependencies in Python (see +# https://discuss.python.org/t/how-to-pin-build-dependencies/8238), we list it +# as a dependency here to ensure a version of cython is pinned for extra +# stability. +cython = "*" # We install mock in our "external-mock" tox environment to test that we didn't # break Certbot's test API which used to always use mock objects from the 3rd # party mock library. We list the mock dependency here so that is pinned, but diff --git a/tools/requirements.txt b/tools/requirements.txt index 498c1e87a..b662744c6 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -18,8 +18,8 @@ backcall==0.2.0 bcrypt==3.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" beautifulsoup4==4.9.3; python_version >= "3.6" and python_version < "4.0" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -boto3==1.17.47; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -botocore==1.20.47; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +boto3==1.17.53; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +botocore==1.20.53; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" cachecontrol==0.12.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" cached-property==1.5.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") @@ -36,7 +36,8 @@ configobj==5.0.6; python_version >= "3.6" coverage==4.5.4; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0" and python_version < "4") crashtest==0.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") cryptography==3.4.7; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" or python_full_version >= "3.5.0" and python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" -decorator==5.0.6 +cython==0.29.23; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") +decorator==5.0.7 deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" distlib==0.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" distro==1.5.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" @@ -51,9 +52,9 @@ execnet==1.8.0; python_version >= "3.6" and python_full_version < "3.0.0" or pyt filelock==3.0.12; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "4.0" future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.3.0" google-api-core==1.26.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -google-api-python-client==2.1.0; python_version >= "3.6" +google-api-python-client==2.2.0; python_version >= "3.6" google-auth-httplib2==0.1.0; python_version >= "3.6" -google-auth==1.28.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +google-auth==1.29.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" googleapis-common-protos==1.53.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" html5lib==1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" httplib2==0.19.1; python_version >= "3.6" @@ -97,8 +98,8 @@ pickleshare==0.7.5 pkginfo==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" pluggy==0.13.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" ply==3.11; python_version >= "3.6" -poetry-core==1.0.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -poetry==1.1.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +poetry-core==1.0.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +poetry==1.1.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" prompt-toolkit==3.0.3 protobuf==3.15.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" ptyprocess==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" @@ -139,14 +140,14 @@ requests-toolbelt==0.9.1; python_version >= "3.6" and python_full_version < "3.0 requests==2.25.1; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.6.0" and python_version < "4.0" rfc3986==1.4.0; python_version >= "3.6" rsa==4.7.2; python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") -s3transfer==0.3.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +s3transfer==0.3.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" secretstorage==3.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" shellingham==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" six==1.15.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" snowballstemmer==2.1.0; python_version >= "3.6" soupsieve==2.2.1; python_version >= "3.6" sphinx-rtd-theme==0.5.2; python_version >= "3.6" -sphinx==3.5.3; python_version >= "3.6" +sphinx==3.5.4; python_version >= "3.6" sphinxcontrib-applehelp==1.0.2; python_version >= "3.6" sphinxcontrib-devhelp==1.0.2; python_version >= "3.6" sphinxcontrib-htmlhelp==1.0.3; python_version >= "3.6" @@ -161,7 +162,7 @@ tox==3.23.0; python_version >= "3.6" and python_full_version < "3.0.0" or python tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" traitlets==4.3.3 twine==3.3.0; python_version >= "3.6" -typed-ast==1.4.2; implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.6" +typed-ast==1.4.3; implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.6" typing-extensions==3.7.4.3; python_version >= "3.6" uritemplate==3.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6" @@ -175,7 +176,7 @@ zipp==3.4.1; python_version >= "3.6" and python_full_version < "3.0.0" and pytho zope.component==5.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" zope.event==4.5.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" zope.hookable==5.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -zope.interface==5.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +zope.interface==5.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pip==20.2.4 setuptools==54.1.2 wheel==0.35.1 From 9292666b28e0f4159dd4096265e69a58c9930677 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 21 Apr 2021 15:55:05 -0700 Subject: [PATCH 19/21] fix ciphers link (#8799) --- certbot/docs/ciphers.rst | 8 ++++++++ certbot/docs/conf.py | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/certbot/docs/ciphers.rst b/certbot/docs/ciphers.rst index 43f648898..b4ef5902a 100644 --- a/certbot/docs/ciphers.rst +++ b/certbot/docs/ciphers.rst @@ -1,3 +1,11 @@ +.. + Sphinx complains that this file isn't included in any toctree, however, we + currently link to it in the section about installing Certbot through Docker. + Setting :orphan: below suppresses this warning. See + https://www.sphinx-doc.org/en/master/usage/restructuredtext/field-lists.html#special-metadata-fields. + +:orphan: + ============ Ciphersuites ============ diff --git a/certbot/docs/conf.py b/certbot/docs/conf.py index 254bd3edd..5496c42a2 100644 --- a/certbot/docs/conf.py +++ b/certbot/docs/conf.py @@ -98,7 +98,6 @@ language = None exclude_patterns = [ '_build', 'challenges.rst', - 'ciphers.rst' ] # The reST default role (used for this markup: `text`) to use for all From e4f5aced1cfddaba4e6816fbafa345b4b6eb9992 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Fri, 23 Apr 2021 05:38:18 +1000 Subject: [PATCH 20/21] docs: add certbot-dns-azure third-party plugin (#8796) --- certbot/docs/using.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/certbot/docs/using.rst b/certbot/docs/using.rst index e38725ca3..cc061b622 100644 --- a/certbot/docs/using.rst +++ b/certbot/docs/using.rst @@ -284,6 +284,7 @@ dns-ispconfig_ Y N DNS Authentication using ISPConfig as DNS server dns-clouddns_ Y N DNS Authentication using CloudDNS API dns-lightsail_ Y N DNS Authentication using Amazon Lightsail DNS API dns-inwx_ Y Y DNS Authentication for INWX through the XML API +dns-azure_ Y N DNS Authentication using Azure DNS ================== ==== ==== =============================================================== .. _haproxy: https://github.com/greenhost/certbot-haproxy @@ -298,6 +299,7 @@ dns-inwx_ Y Y DNS Authentication for INWX through the XML API .. _dns-clouddns: https://github.com/vshosting/certbot-dns-clouddns .. _dns-lightsail: https://github.com/noi/certbot-dns-lightsail .. _dns-inwx: https://github.com/oGGy990/certbot-dns-inwx/ +.. _dns-azure: https://github.com/binkhq/certbot-dns-azure If you're interested, you can also :ref:`write your own plugin `. From 32247b3c89cb44b87f764a21e6deda9168431dec Mon Sep 17 00:00:00 2001 From: ohemorange Date: Thu, 22 Apr 2021 13:37:46 -0700 Subject: [PATCH 21/21] Remove modifications to certbot-auto from the release script (#8797) Fixes #8707. * Remove modifications to certbot-auto from the release script * Update tools/_release.sh * Delete tools/eff-pubkey.pem Co-authored-by: Brad Warren --- tools/_release.sh | 72 +++++--------------------------------------- tools/eff-pubkey.pem | 9 ------ 2 files changed, 7 insertions(+), 74 deletions(-) delete mode 100644 tools/eff-pubkey.pem diff --git a/tools/_release.sh b/tools/_release.sh index e9e0e49f0..5166753d2 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -30,9 +30,6 @@ echo Releasing production version "$version"... nextversion="$2" RELEASE_BRANCH="candidate-$version" -if [ "$RELEASE_OPENSSL_PUBKEY" = "" ] ; then - RELEASE_OPENSSL_PUBKEY="`realpath \`dirname $0\``/eff-pubkey.pem" -fi RELEASE_GPG_KEY=${RELEASE_GPG_KEY:-A2CFB51FA275A7286234E7B24D17C995CD9775F2} # Needed to fix problems with git signatures and pinentry export GPG_TTY=$(tty) @@ -40,14 +37,13 @@ export GPG_TTY=$(tty) # port for a local Python Package Index (used in testing) PORT=${PORT:-1234} -# subpackages to be released (the way developers think about them) -SUBPKGS_IN_AUTO_NO_CERTBOT="acme certbot-apache certbot-nginx" -SUBPKGS_NOT_IN_AUTO="certbot-dns-cloudflare certbot-dns-cloudxns certbot-dns-digitalocean certbot-dns-dnsimple certbot-dns-dnsmadeeasy certbot-dns-gehirn certbot-dns-google certbot-dns-linode certbot-dns-luadns certbot-dns-nsone certbot-dns-ovh certbot-dns-rfc2136 certbot-dns-route53 certbot-dns-sakuracloud" - # subpackages to be released (the way the script thinks about them) -SUBPKGS_IN_AUTO="certbot $SUBPKGS_IN_AUTO_NO_CERTBOT" -SUBPKGS_NO_CERTBOT="$SUBPKGS_IN_AUTO_NO_CERTBOT $SUBPKGS_NOT_IN_AUTO" -SUBPKGS="$SUBPKGS_IN_AUTO $SUBPKGS_NOT_IN_AUTO" +SUBPKGS_NO_CERTBOT="acme certbot-apache certbot-nginx certbot-dns-cloudflare certbot-dns-cloudxns \ + certbot-dns-digitalocean certbot-dns-dnsimple certbot-dns-dnsmadeeasy \ + certbot-dns-gehirn certbot-dns-google certbot-dns-linode certbot-dns-luadns \ + certbot-dns-nsone certbot-dns-ovh certbot-dns-rfc2136 certbot-dns-route53 \ + certbot-dns-sakuracloud" +SUBPKGS="certbot $SUBPKGS_NO_CERTBOT" # certbot_compatibility_test is not packaged because: # - it is not meant to be used by anyone else than Certbot devs # - it causes problems when running pytest - the latter tries to @@ -198,60 +194,10 @@ for module in $SUBPKGS ; do # use an empty configuration file rather than the one in the repo root pytest -c <(echo '') $module done - -# pin pip hashes of the things we just built -for pkg in $SUBPKGS_IN_AUTO ; do - echo $pkg==$version \\ - pip hash dist."$version/$pkg"/*.{whl,gz} | grep "^--hash" | python -c 'from sys import stdin; input = stdin.read(); print(" ", input.replace("\n--hash", " \\\n --hash"), end="")' -done > letsencrypt-auto-source/pieces/certbot-requirements.txt deactivate -# there should be one requirement specifier and two hashes for each subpackage -expected_count=$(expr $(echo $SUBPKGS_IN_AUTO | wc -w) \* 3) -if ! wc -l letsencrypt-auto-source/pieces/certbot-requirements.txt | grep -qE "^\s*$expected_count " ; then - echo Unexpected pip hash output - exit 1 -fi -# ensure we have the latest built version of leauto -letsencrypt-auto-source/build.py - -# Now we have to sign the built version of leauto. -SignLEAuto() { - yubico-piv-tool -a verify-pin --sign -s 9c -i letsencrypt-auto-source/letsencrypt-auto -o letsencrypt-auto-source/letsencrypt-auto.sig -} - -# Loop until letsencrypt-auto is signed correctly. -SignLEAuto || true -while ! openssl dgst -sha256 -verify $RELEASE_OPENSSL_PUBKEY -signature \ - letsencrypt-auto-source/letsencrypt-auto.sig \ - letsencrypt-auto-source/letsencrypt-auto ; do - echo "The signature on letsencrypt-auto is not correct." - read -p "Would you like this script to try and sign it again [Y/n]?" response - case $response in - [yY][eE][sS]|[yY]|"") - SignLEAuto || true;; - *) - ;; - esac -done - -# This signature is not quite as strong, but easier for people to verify out of band -while ! gpg2 -u "$RELEASE_GPG_KEY" --detach-sign --armor --sign --digest-algo sha256 letsencrypt-auto-source/letsencrypt-auto; do - echo "Unable to sign letsencrypt-auto using $RELEASE_KEY." - echo "Make sure your OpenPGP card is in your computer if you are using one." - echo "You may need to take the card out and put it back in again." - read -p "Press enter to try signing again." -done -# We can't rename the openssl letsencrypt-auto.sig for compatibility reasons, -# but we can use the right name for certbot-auto.asc from day one -mv letsencrypt-auto-source/letsencrypt-auto.asc letsencrypt-auto-source/certbot-auto.asc - -# copy leauto to the root, overwriting the previous release version -cp -p letsencrypt-auto-source/letsencrypt-auto certbot-auto -cp -p letsencrypt-auto-source/letsencrypt-auto letsencrypt-auto - -git add certbot-auto letsencrypt-auto letsencrypt-auto-source certbot/docs/cli-help.txt +git add certbot/docs/cli-help.txt while ! git commit --gpg-sign="$RELEASE_GPG_KEY" -m "Release $version"; do echo "Unable to sign the release commit using git." echo "You may have to configure git to use gpg2 by running:" @@ -283,15 +229,11 @@ git commit -m "Add contents to certbot/CHANGELOG.md for next version" echo "New root: $root" echo "Test commands (in the letstest repo):" -echo 'python multitester.py auto_targets.yaml $AWS_KEY $USERNAME scripts/test_leauto_upgrades.sh --alt_pip $YOUR_PIP_REPO --branch public-beta' -echo 'python multitester.py auto_targets.yaml $AWK_KEY $USERNAME scripts/test_letsencrypt_auto_certonly_standalone.sh --branch candidate-0.1.1' echo 'python multitester.py --saveinstances targets.yaml $AWS_KEY $USERNAME scripts/test_apache2.sh' echo "In order to upload packages run the following command:" echo twine upload "$root/dist.$version/*/*" if [ "$RELEASE_BRANCH" = candidate-"$version" ] ; then SetVersion "$nextversion".dev0 - letsencrypt-auto-source/build.py - git add letsencrypt-auto-source/letsencrypt-auto git commit -m "Bump version to $nextversion" fi diff --git a/tools/eff-pubkey.pem b/tools/eff-pubkey.pem deleted file mode 100644 index fe6c2f5bb..000000000 --- a/tools/eff-pubkey.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq -OzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18 -xUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp -9+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij -n9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH -cXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+ -CQIDAQAB ------END PUBLIC KEY-----