diff --git a/.pylintrc b/.pylintrc index c2d8ff85e..0e78828bd 100644 --- a/.pylintrc +++ b/.pylintrc @@ -24,6 +24,11 @@ persistent=yes # usually to register additional checkers. load-plugins=linter_plugin +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-whitelist=pywintypes,win32api,win32file,win32security + [MESSAGES CONTROL] @@ -41,10 +46,14 @@ load-plugins=linter_plugin # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=fixme,locally-disabled,locally-enabled,abstract-class-not-used,abstract-class-little-used,bad-continuation,no-self-use,invalid-name,cyclic-import,duplicate-code,design -# abstract-class-not-used cannot be disabled locally (at least in -# pylint 1.4.1), same for abstract-class-little-used - +# CERTBOT COMMENT +# 1) Once certbot codebase is claimed to be compatible exclusively with Python 3, +# the useless-object-inheritance check can be enabled again, and code fixed accordingly. +# 2) Check unsubscriptable-object tends to create a lot of false positives. Let's disable it. +# See https://github.com/PyCQA/pylint/issues/1498. +# 3) Same as point 2 for no-value-for-parameter. +# See https://github.com/PyCQA/pylint/issues/2820. +disable=fixme,locally-disabled,locally-enabled,bad-continuation,no-self-use,invalid-name,cyclic-import,duplicate-code,design,import-outside-toplevel,useless-object-inheritance,unsubscriptable-object,no-value-for-parameter,no-else-return,no-else-raise,no-else-break,no-else-continue [REPORTS] diff --git a/.travis.yml b/.travis.yml index 22391c84f..59cc8630a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,12 +46,9 @@ matrix: - python: "2.7" env: TOXENV=py27-cover FYI="py27 tests + code coverage" - - python: "2.7" + - python: "3.7" env: TOXENV=lint <<: *not-on-master - - python: "3.4" - env: TOXENV=mypy - <<: *not-on-master - python: "3.5" env: TOXENV=mypy <<: *not-on-master diff --git a/Dockerfile-dev b/Dockerfile-dev index 86f5f04e7..ae197b1cb 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -6,16 +6,15 @@ EXPOSE 80 443 WORKDIR /opt/certbot/src -# TODO: Install Apache/Nginx for plugin development. COPY . . RUN apt-get update && \ - apt-get install apache2 git nginx-light -y && \ - letsencrypt-auto-source/letsencrypt-auto --os-packages-only && \ + apt-get install apache2 git python3-dev python3-venv gcc libaugeas0 \ + libssl-dev libffi-dev ca-certificates openssl nginx-light -y && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* \ /tmp/* \ /var/tmp/* -RUN VENV_NAME="../venv" python tools/venv.py +RUN VENV_NAME="../venv3" python3 tools/venv3.py -ENV PATH /opt/certbot/venv/bin:$PATH +ENV PATH /opt/certbot/venv3/bin:$PATH diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index d9d529810..8a0366301 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -54,8 +54,7 @@ class UnrecognizedChallenge(Challenge): object.__setattr__(self, "jobj", jobj) def to_partial_json(self): - # pylint: disable=no-member - return self.jobj + return self.jobj # pylint: disable=no-member @classmethod def from_json(cls, jobj): @@ -113,7 +112,7 @@ class KeyAuthorizationChallengeResponse(ChallengeResponse): :rtype: bool """ - parts = self.key_authorization.split('.') # pylint: disable=no-member + parts = self.key_authorization.split('.') if len(parts) != 2: logger.debug("Key authorization (%r) is not well formed", self.key_authorization) diff --git a/acme/acme/client.py b/acme/acme/client.py index 928b86d03..aabcbe312 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -34,7 +34,6 @@ logger = logging.getLogger(__name__) # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning if sys.version_info < (2, 7, 9): # pragma: no cover try: - # pylint: disable=no-member requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3() # type: ignore except AttributeError: import urllib3.contrib.pyopenssl # pylint: disable=import-error @@ -280,7 +279,6 @@ class Client(ClientBase): assert response.status_code == http_client.CREATED # "Instance of 'Field' has no key/contact member" bug: - # pylint: disable=no-member return self._regr_from_response(response) def query_registration(self, regr): @@ -465,7 +463,6 @@ class Client(ClientBase): updated[authzr] = updated_authzr attempts[authzr] += 1 - # pylint: disable=no-member if updated_authzr.body.status not in ( messages.STATUS_VALID, messages.STATUS_INVALID): if attempts[authzr] < max_attempts: @@ -606,7 +603,6 @@ class ClientV2(ClientBase): if response.status_code == 200 and 'Location' in response.headers: raise errors.ConflictError(response.headers.get('Location')) # "Instance of 'Field' has no key/contact member" bug: - # pylint: disable=no-member regr = self._regr_from_response(response) self.net.account = regr return regr @@ -730,7 +726,7 @@ class ClientV2(ClientBase): for authzr in responses: if authzr.body.status != messages.STATUS_VALID: for chall in authzr.body.challenges: - if chall.error != None: + if chall.error is not None: failed.append(authzr) if failed: raise errors.ValidationError(failed) @@ -1125,10 +1121,9 @@ class ClientNetwork(object): err_regex = r".*host='(\S*)'.*Max retries exceeded with url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" m = re.match(err_regex, str(e)) if m is None: - raise # pragma: no cover - else: - host, path, _err_no, err_msg = m.groups() - raise ValueError("Requesting {0}{1}:{2}".format(host, path, err_msg)) + raise # pragma: no cover + host, path, _err_no, err_msg = m.groups() + raise ValueError("Requesting {0}{1}:{2}".format(host, path, err_msg)) # If content is DER, log the base64 of it instead of raw bytes, to keep # binary data out of the logs. @@ -1194,8 +1189,7 @@ class ClientNetwork(object): if error.code == 'badNonce': logger.debug('Retrying request after error:\n%s', error) return self._post_once(*args, **kwargs) - else: - raise + raise def _post_once(self, url, obj, content_type=JOSE_CONTENT_TYPE, acme_version=1, **kwargs): diff --git a/acme/acme/errors.py b/acme/acme/errors.py index 3a0f8c596..806657940 100644 --- a/acme/acme/errors.py +++ b/acme/acme/errors.py @@ -29,7 +29,12 @@ class NonceError(ClientError): class BadNonce(NonceError): """Bad nonce error.""" def __init__(self, nonce, error, *args, **kwargs): - super(BadNonce, self).__init__(*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 self.nonce = nonce self.error = error @@ -48,7 +53,8 @@ class MissingNonce(NonceError): """ def __init__(self, response, *args, **kwargs): - super(MissingNonce, self).__init__(*args, **kwargs) + # See comment in BadNonce constructor above for an explanation of type: ignore here. + super(MissingNonce, self).__init__(*args, **kwargs) # type: ignore self.response = response def __str__(self): @@ -83,6 +89,7 @@ class PollError(ClientError): return '{0}(exhausted={1!r}, updated={2!r})'.format( self.__class__.__name__, self.exhausted, self.updated) + class ValidationError(Error): """Error for authorization failures. Contains a list of authorization resources, each of which is invalid and should have an error field. @@ -91,9 +98,11 @@ class ValidationError(Error): self.failed_authzrs = failed_authzrs super(ValidationError, self).__init__() -class TimeoutError(Error): + +class TimeoutError(Error): # pylint: disable=redefined-builtin """Error for when polling an authorization or an order times out.""" + class IssuanceError(Error): """Error sent by the server after requesting issuance of a certificate.""" @@ -105,6 +114,7 @@ class IssuanceError(Error): self.error = error super(IssuanceError, self).__init__() + class ConflictError(ClientError): """Error for when the server returns a 409 (Conflict) HTTP status. diff --git a/acme/acme/jws.py b/acme/acme/jws.py index ff8070d0b..894e69f3d 100644 --- a/acme/acme/jws.py +++ b/acme/acme/jws.py @@ -40,7 +40,7 @@ class Signature(jose.Signature): class JWS(jose.JWS): """ACME-specific JWS. Includes none, url, and kid in protected header.""" signature_cls = Signature - __slots__ = jose.JWS._orig_slots # pylint: disable=no-member + __slots__ = jose.JWS._orig_slots @classmethod # pylint: disable=arguments-differ diff --git a/acme/acme/messages.py b/acme/acme/messages.py index a87abdb91..96a1ed7c0 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -146,7 +146,7 @@ class _Constant(jose.JSONDeSerializable, Hashable): # type: ignore if jobj not in cls.POSSIBLE_NAMES: # pylint: disable=unsupported-membership-test raise jose.DeserializationError( '{0} not recognized'.format(cls.__name__)) - return cls.POSSIBLE_NAMES[jobj] # pylint: disable=unsubscriptable-object + return cls.POSSIBLE_NAMES[jobj] def __repr__(self): return '{0}({1})'.format(self.__class__.__name__, self.name) diff --git a/acme/acme/standalone.py b/acme/acme/standalone.py index 0b66976e4..cf0da4e86 100644 --- a/acme/acme/standalone.py +++ b/acme/acme/standalone.py @@ -44,7 +44,7 @@ class TLSServer(socketserver.TCPServer): return socketserver.TCPServer.server_bind(self) -class ACMEServerMixin: # pylint: disable=old-style-class +class ACMEServerMixin: """ACME server common settings mixin.""" # TODO: c.f. #858 server_version = "ACME client standalone challenge solver" @@ -105,7 +105,6 @@ class BaseDualNetworkedServers(object): """Wraps socketserver.TCPServer.serve_forever""" for server in self.servers: thread = threading.Thread( - # pylint: disable=no-member target=server.serve_forever) thread.start() self.threads.append(thread) diff --git a/acme/tests/challenges_test.py b/acme/tests/challenges_test.py index f8a503b3c..490caadc2 100644 --- a/acme/tests/challenges_test.py +++ b/acme/tests/challenges_test.py @@ -4,7 +4,7 @@ import unittest import josepy as jose import mock import requests -from six.moves.urllib import parse as urllib_parse # pylint: disable=relative-import +from six.moves.urllib import parse as urllib_parse import test_util @@ -18,7 +18,6 @@ class ChallengeTest(unittest.TestCase): from acme.challenges import Challenge from acme.challenges import UnrecognizedChallenge chall = UnrecognizedChallenge({"type": "foo"}) - # pylint: disable=no-member self.assertEqual(chall, Challenge.from_json(chall.jobj)) diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index 7c1d9f68e..192cd2949 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -61,7 +61,7 @@ class ClientTestBase(unittest.TestCase): self.contact = ('mailto:cert-admin@example.com', 'tel:+12025551212') reg = messages.Registration( contact=self.contact, key=KEY.public_key()) - the_arg = dict(reg) # type: Dict + the_arg = dict(reg) # type: Dict self.new_reg = messages.NewRegistration(**the_arg) self.regr = messages.RegistrationResource( body=reg, uri='https://www.letsencrypt-demo.org/acme/reg/1') @@ -963,8 +963,8 @@ class ClientNetworkTest(unittest.TestCase): def test_check_response_not_ok_jobj_error(self): self.response.ok = False - self.response.json.return_value = messages.Error( - detail='foo', typ='serverInternal', title='some title').to_json() + self.response.json.return_value = messages.Error.with_code( + 'serverInternal', detail='foo', title='some title').to_json() # pylint: disable=protected-access self.assertRaises( messages.Error, self.net._check_response, self.response) @@ -989,7 +989,7 @@ class ClientNetworkTest(unittest.TestCase): self.response.json.side_effect = ValueError for response_ct in [self.net.JSON_CONTENT_TYPE, 'foo']: self.response.headers['Content-Type'] = response_ct - # pylint: disable=protected-access,no-value-for-parameter + # pylint: disable=protected-access self.assertEqual( self.response, self.net._check_response(self.response)) @@ -1003,7 +1003,7 @@ class ClientNetworkTest(unittest.TestCase): self.response.json.return_value = {} for response_ct in [self.net.JSON_CONTENT_TYPE, 'foo']: self.response.headers['Content-Type'] = response_ct - # pylint: disable=protected-access,no-value-for-parameter + # pylint: disable=protected-access self.assertEqual( self.response, self.net._check_response(self.response)) @@ -1128,8 +1128,8 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): self.response.headers = {} self.response.links = {} self.response.checked = False - self.acmev1_nonce_response = mock.MagicMock(ok=False, - status_code=http_client.METHOD_NOT_ALLOWED) + self.acmev1_nonce_response = mock.MagicMock( + ok=False, status_code=http_client.METHOD_NOT_ALLOWED) self.acmev1_nonce_response.headers = {} self.obj = mock.MagicMock() self.wrapped_obj = mock.MagicMock() diff --git a/acme/tests/crypto_util_test.py b/acme/tests/crypto_util_test.py index a7ce51f92..41640ed60 100644 --- a/acme/tests/crypto_util_test.py +++ b/acme/tests/crypto_util_test.py @@ -38,7 +38,6 @@ class SSLSocketAndProbeSNITest(unittest.TestCase): self.server = _TestServer(('', 0), socketserver.BaseRequestHandler) self.port = self.server.socket.getsockname()[1] self.server_thread = threading.Thread( - # pylint: disable=no-member target=self.server.handle_request) def tearDown(self): @@ -65,7 +64,7 @@ class SSLSocketAndProbeSNITest(unittest.TestCase): def test_probe_connection_error(self): # pylint has a hard time with six - self.server.server_close() # pylint: disable=no-member + self.server.server_close() original_timeout = socket.getdefaulttimeout() try: socket.setdefaulttimeout(1) diff --git a/acme/tests/jose_test.py b/acme/tests/jose_test.py index 899ad7074..e008cb6fc 100644 --- a/acme/tests/jose_test.py +++ b/acme/tests/jose_test.py @@ -21,11 +21,10 @@ class JoseTest(unittest.TestCase): # We use the imports below with eval, but pylint doesn't # understand that. - # pylint: disable=eval-used,unused-variable - import acme - import josepy - acme_jose_mod = eval(acme_jose_path) - josepy_mod = eval(josepy_path) + import acme # pylint: disable=unused-import + import josepy # pylint: disable=unused-import + acme_jose_mod = eval(acme_jose_path) # pylint: disable=eval-used + josepy_mod = eval(josepy_path) # pylint: disable=eval-used self.assertIs(acme_jose_mod, josepy_mod) self.assertIs(getattr(acme_jose_mod, attribute), getattr(josepy_mod, attribute)) diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 2700fc23b..b9b70266b 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -18,8 +18,7 @@ class ErrorTest(unittest.TestCase): def setUp(self): from acme.messages import Error, ERROR_PREFIX - self.error = Error( - detail='foo', typ=ERROR_PREFIX + 'malformed', title='title') + self.error = Error.with_code('malformed', detail='foo', title='title') self.jobj = { 'detail': 'foo', 'title': 'some title', @@ -27,7 +26,6 @@ class ErrorTest(unittest.TestCase): } self.error_custom = Error(typ='custom', detail='bar') self.empty_error = Error() - self.jobj_custom = {'type': 'custom', 'detail': 'bar'} def test_default_typ(self): from acme.messages import Error @@ -42,8 +40,7 @@ class ErrorTest(unittest.TestCase): hash(Error.from_json(self.error.to_json())) def test_description(self): - self.assertEqual( - 'The request message was malformed', self.error.description) + self.assertEqual('The request message was malformed', self.error.description) self.assertTrue(self.error_custom.description is None) def test_code(self): @@ -53,17 +50,17 @@ class ErrorTest(unittest.TestCase): self.assertEqual(None, Error().code) def test_is_acme_error(self): - from acme.messages import is_acme_error + from acme.messages import is_acme_error, Error self.assertTrue(is_acme_error(self.error)) self.assertFalse(is_acme_error(self.error_custom)) + self.assertFalse(is_acme_error(Error())) self.assertFalse(is_acme_error(self.empty_error)) self.assertFalse(is_acme_error("must pet all the {dogs|rabbits}")) def test_unicode_error(self): - from acme.messages import Error, ERROR_PREFIX, is_acme_error - arabic_error = Error( - detail=u'\u0639\u062f\u0627\u0644\u0629', typ=ERROR_PREFIX + 'malformed', - title='title') + from acme.messages import Error, is_acme_error + arabic_error = Error.with_code( + 'malformed', detail=u'\u0639\u062f\u0627\u0644\u0629', title='title') self.assertTrue(is_acme_error(arabic_error)) def test_with_code(self): @@ -304,8 +301,7 @@ class ChallengeBodyTest(unittest.TestCase): from acme.messages import Error from acme.messages import STATUS_INVALID self.status = STATUS_INVALID - error = Error(typ='urn:ietf:params:acme:error:serverInternal', - detail='Unable to communicate with DNS server') + error = Error.with_code('serverInternal', detail='Unable to communicate with DNS server') self.challb = ChallengeBody( uri='http://challb', chall=self.chall, status=self.status, error=error) diff --git a/acme/tests/test_util.py b/acme/tests/test_util.py index 6525f3af5..d4a45272d 100644 --- a/acme/tests/test_util.py +++ b/acme/tests/test_util.py @@ -25,8 +25,7 @@ def _guess_loader(filename, loader_pem, loader_der): return loader_pem elif ext.lower() == '.der': return loader_der - else: # pragma: no cover - raise ValueError("Loader could not be recognized based on extension") + raise ValueError("Loader could not be recognized based on extension") # pragma: no cover def load_cert(*names): diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index f1035aa33..20c225e04 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -449,7 +449,7 @@ class ApacheConfigurator(common.Installer): filtered_vhosts[name] = vhost # Only unique VHost objects - dialog_input = set([vhost for vhost in filtered_vhosts.values()]) + dialog_input = set(filtered_vhosts.values()) # Ask the user which of names to enable, expect list of names back dialog_output = display_ops.select_vhost_multiple(list(dialog_input)) @@ -600,9 +600,9 @@ class ApacheConfigurator(common.Installer): "in the Apache config.", target_name) raise errors.PluginError("No vhost selected") - elif temp: + if temp: return vhost - elif not vhost.ssl: + if not vhost.ssl: addrs = self._get_proposed_addrs(vhost, "443") # TODO: Conflicts is too conservative if not any(vhost.enabled and vhost.conflicts(addrs) for @@ -951,13 +951,12 @@ class ApacheConfigurator(common.Installer): loc = parser.get_aug_path(self.parser.loc["name"]) if addr.get_port() == "443": - path = self.parser.add_dir_to_ifmodssl( + self.parser.add_dir_to_ifmodssl( loc, "NameVirtualHost", [str(addr)]) else: - path = self.parser.add_dir(loc, "NameVirtualHost", [str(addr)]) + self.parser.add_dir(loc, "NameVirtualHost", [str(addr)]) - msg = ("Setting %s to be NameBasedVirtualHost\n" - "\tDirective added to %s\n" % (addr, path)) + msg = "Setting {0} to be NameBasedVirtualHost\n".format(addr) logger.debug(msg) self.save_notes += msg @@ -1365,12 +1364,9 @@ class ApacheConfigurator(common.Installer): result.append(comment) sift = True - result.append('\n'.join( - ['# ' + l for l in chunk])) - continue + result.append('\n'.join(['# ' + l for l in chunk])) else: result.append('\n'.join(chunk)) - continue return result, sift def _get_vhost_block(self, vhost): @@ -2513,4 +2509,4 @@ class ApacheConfigurator(common.Installer): self._autohsts_save_state() -AutoHSTSEnhancement.register(ApacheConfigurator) # pylint: disable=no-member +AutoHSTSEnhancement.register(ApacheConfigurator) diff --git a/certbot-apache/certbot_apache/_internal/http_01.py b/certbot-apache/certbot_apache/_internal/http_01.py index 62c6db272..c34abc2b4 100644 --- a/certbot-apache/certbot_apache/_internal/http_01.py +++ b/certbot-apache/certbot_apache/_internal/http_01.py @@ -194,8 +194,8 @@ class ApacheHttp01(common.ChallengePerformer): if vhost not in self.moded_vhosts: logger.debug( - "Adding a temporary challenge validation Include for name: %s " + - "in: %s", vhost.name, vhost.filep) + "Adding a temporary challenge validation Include for name: %s in: %s", + vhost.name, vhost.filep) self.configurator.parser.add_dir_beginning( vhost.path, "Include", self.challenge_conf_pre) self.configurator.parser.add_dir( diff --git a/certbot-apache/certbot_apache/_internal/override_debian.py b/certbot-apache/certbot_apache/_internal/override_debian.py index aefc4c6d4..77ced6a3f 100644 --- a/certbot-apache/certbot_apache/_internal/override_debian.py +++ b/certbot-apache/certbot_apache/_internal/override_debian.py @@ -70,15 +70,14 @@ class DebianConfigurator(configurator.ApacheConfigurator): # Already in shape vhost.enabled = True return None - else: - logger.warning( - "Could not symlink %s to %s, got error: %s", enabled_path, - vhost.filep, err.strerror) - errstring = ("Encountered error while trying to enable a " + - "newly created VirtualHost located at {0} by " + - "linking to it from {1}") - raise errors.NotSupportedError(errstring.format(vhost.filep, - enabled_path)) + logger.warning( + "Could not symlink %s to %s, got error: %s", enabled_path, + vhost.filep, err.strerror) + errstring = ("Encountered error while trying to enable a " + + "newly created VirtualHost located at {0} by " + + "linking to it from {1}") + raise errors.NotSupportedError(errstring.format(vhost.filep, + enabled_path)) vhost.enabled = True logger.info("Enabling available site: %s", vhost.filep) self.save_notes += "Enabled site %s\n" % vhost.filep diff --git a/certbot-apache/certbot_apache/_internal/parser.py b/certbot-apache/certbot_apache/_internal/parser.py index 5c447ed27..e4073ee16 100644 --- a/certbot-apache/certbot_apache/_internal/parser.py +++ b/certbot-apache/certbot_apache/_internal/parser.py @@ -284,8 +284,8 @@ class ApacheParser(object): mods.add(mod_name) mods.add(os.path.basename(mod_filename)[:-2] + "c") else: - logger.debug("Could not read LoadModule directive from " + - "Augeas path: %s", match_name[6:]) + logger.debug("Could not read LoadModule directive from Augeas path: %s", + match_name[6:]) self.modules.update(mods) def update_runtime_variables(self): @@ -625,7 +625,7 @@ class ApacheParser(object): # https://httpd.apache.org/docs/2.4/mod/core.html#include for match in matches: dir_ = self.aug.get(match).lower() - if dir_ == "include" or dir_ == "includeoptional": + if dir_ in ("include", "includeoptional"): ordered_matches.extend(self.find_dir( directive, arg, self._get_include_path(self.get_arg(match + "/arg")), @@ -665,8 +665,7 @@ class ApacheParser(object): # e.g. strip now, not later if not value: return None - else: - value = value.strip("'\"") + value = value.strip("'\"") variables = ApacheParser.arg_var_interpreter.findall(value) diff --git a/certbot-apache/local-oldest-requirements.txt b/certbot-apache/local-oldest-requirements.txt index 1ee716cd6..3fce6f83b 100644 --- a/certbot-apache/local-oldest-requirements.txt +++ b/certbot-apache/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index f043e8857..204d01620 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'mock', 'python-augeas', 'setuptools', diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py index c35aa4ba5..b592d6288 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py @@ -43,8 +43,7 @@ class Proxy(object): method = getattr(self._configurator, name, None) if callable(method): return method - else: - raise AttributeError() + raise AttributeError() def has_more_configs(self): """Returns true if there are more configs to test""" @@ -82,8 +81,7 @@ class Proxy(object): """Returns the set of domain names that the plugin should find""" if self._all_names: return self._all_names - else: - raise errors.Error("No configuration file loaded") + raise errors.Error("No configuration file loaded") def get_testable_domain_names(self): """Returns the set of domain names that can be tested against""" diff --git a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py index 03e1283c6..2c3f880e0 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py +++ b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py @@ -10,7 +10,6 @@ import tempfile import time import OpenSSL -from six.moves import xrange # pylint: disable=import-error,redefined-builtin from urllib3.util import connection from acme import challenges @@ -57,26 +56,27 @@ def test_authenticator(plugin, config, temp_dir): return False success = True - for i in xrange(len(responses)): - if not responses[i]: + for i, response in enumerate(responses): + achall = achalls[i] + if not response: logger.error( "Plugin failed to complete %s for %s in %s", - type(achalls[i]), achalls[i].domain, config) + type(achall), achall.domain, config) success = False - elif isinstance(responses[i], challenges.HTTP01Response): + elif isinstance(response, challenges.HTTP01Response): # We fake the DNS resolution to ensure that any domain is resolved # to the local HTTP server setup for the compatibility tests with _fake_dns_resolution("127.0.0.1"): - verified = responses[i].simple_verify( - achalls[i].chall, achalls[i].domain, + verified = response.simple_verify( + achall.chall, achall.domain, util.JWK.public_key(), port=plugin.http_port) if verified: logger.info( - "http-01 verification for %s succeeded", achalls[i].domain) + "http-01 verification for %s succeeded", achall.domain) else: logger.error( "**** http-01 verification for %s in %s failed", - achalls[i].domain, config) + achall.domain, config) success = False if success: @@ -89,8 +89,7 @@ def test_authenticator(plugin, config, temp_dir): if _dirs_are_unequal(config, backup): logger.error("Challenge cleanup failed for %s", config) return False - else: - logger.info("Challenge cleanup succeeded") + logger.info("Challenge cleanup succeeded") return success @@ -305,7 +304,7 @@ def get_args(): "-e", "--enhance", action="store_true", help="tests the enhancements " "the plugin supports (implicitly includes installer tests)") - for plugin in PLUGINS.itervalues(): + for plugin in PLUGINS.values(): plugin.add_parser_arguments(parser) args = parser.parse_args() diff --git a/certbot-dns-cloudflare/local-oldest-requirements.txt b/certbot-dns-cloudflare/local-oldest-requirements.txt index 1ee716cd6..3fce6f83b 100644 --- a/certbot-dns-cloudflare/local-oldest-requirements.txt +++ b/certbot-dns-cloudflare/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index d1c761d19..b3fd81223 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'cloudflare>=1.5.1', 'mock', 'setuptools', diff --git a/certbot-dns-cloudxns/local-oldest-requirements.txt b/certbot-dns-cloudxns/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-cloudxns/local-oldest-requirements.txt +++ b/certbot-dns-cloudxns/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 33afdfb60..288a6d115 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', diff --git a/certbot-dns-digitalocean/local-oldest-requirements.txt b/certbot-dns-digitalocean/local-oldest-requirements.txt index 1ee716cd6..3fce6f83b 100644 --- a/certbot-dns-digitalocean/local-oldest-requirements.txt +++ b/certbot-dns-digitalocean/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 21c31d803..ba3190567 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'mock', 'python-digitalocean>=1.11', 'setuptools', diff --git a/certbot-dns-dnsimple/local-oldest-requirements.txt b/certbot-dns-dnsimple/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-dnsimple/local-oldest-requirements.txt +++ b/certbot-dns-dnsimple/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index fbdcea142..5729bd789 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -11,7 +11,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'mock', 'setuptools', 'zope.interface', diff --git a/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt b/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt +++ b/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index c25a49c59..6fc756389 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', diff --git a/certbot-dns-gehirn/local-oldest-requirements.txt b/certbot-dns-gehirn/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-gehirn/local-oldest-requirements.txt +++ b/certbot-dns-gehirn/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 746df1b62..7c4da556d 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -9,7 +9,7 @@ version = '1.1.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.1.22', 'mock', 'setuptools', 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 f603a2dc3..3aa910b52 100644 --- a/certbot-dns-google/certbot_dns_google/_internal/dns_google.py +++ b/certbot-dns-google/certbot_dns_google/_internal/dns_google.py @@ -235,7 +235,7 @@ class _GoogleClient(object): :rtype: `list` of `string` or `None` """ - rrs_request = self.dns.resourceRecordSets() # pylint: disable=no-member + rrs_request = self.dns.resourceRecordSets() request = rrs_request.list(managedZone=zone_id, project=self.project_id) # Add dot as the API returns absolute domains record_name += "." diff --git a/certbot-dns-google/local-oldest-requirements.txt b/certbot-dns-google/local-oldest-requirements.txt index 1ee716cd6..3fce6f83b 100644 --- a/certbot-dns-google/local-oldest-requirements.txt +++ b/certbot-dns-google/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index f42e4d13d..a0dc1c386 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'google-api-python-client>=1.5.5', 'mock', 'oauth2client>=4.0', diff --git a/certbot-dns-google/tests/dns_google_test.py b/certbot-dns-google/tests/dns_google_test.py index ddb0da813..647a75b05 100644 --- a/certbot-dns-google/tests/dns_google_test.py +++ b/certbot-dns-google/tests/dns_google_test.py @@ -288,7 +288,6 @@ class GoogleClientTest(unittest.TestCase): def test_get_existing_fallback(self, unused_credential_mock): client, unused_changes = self._setUp_client_with_mock( [{'managedZones': [{'id': self.zone}]}]) - # pylint: disable=no-member mock_execute = client.dns.resourceRecordSets.return_value.list.return_value.execute mock_execute.side_effect = API_ERROR diff --git a/certbot-dns-linode/local-oldest-requirements.txt b/certbot-dns-linode/local-oldest-requirements.txt index 838e70c69..1829f7eb2 100644 --- a/certbot-dns-linode/local-oldest-requirements.txt +++ b/certbot-dns-linode/local-oldest-requirements.txt @@ -1,4 +1,4 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] dns-lexicon==2.2.3 diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 8bbcfd3af..f772dc26a 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -9,7 +9,7 @@ version = '1.1.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.2.3', 'mock', 'setuptools', diff --git a/certbot-dns-luadns/local-oldest-requirements.txt b/certbot-dns-luadns/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-luadns/local-oldest-requirements.txt +++ b/certbot-dns-luadns/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 43a865b93..18ba8cacc 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', diff --git a/certbot-dns-nsone/local-oldest-requirements.txt b/certbot-dns-nsone/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-nsone/local-oldest-requirements.txt +++ b/certbot-dns-nsone/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index bb8cbe5b0..3894f01cd 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', diff --git a/certbot-dns-ovh/local-oldest-requirements.txt b/certbot-dns-ovh/local-oldest-requirements.txt index 1116b6dfc..2e11550d6 100644 --- a/certbot-dns-ovh/local-oldest-requirements.txt +++ b/certbot-dns-ovh/local-oldest-requirements.txt @@ -1,4 +1,4 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] dns-lexicon==2.7.14 diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 3d0df5026..2fccf17c2 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.7.14', # Correct proxy use on OVH provider 'mock', 'setuptools', diff --git a/certbot-dns-rfc2136/local-oldest-requirements.txt b/certbot-dns-rfc2136/local-oldest-requirements.txt index 1ee716cd6..3fce6f83b 100644 --- a/certbot-dns-rfc2136/local-oldest-requirements.txt +++ b/certbot-dns-rfc2136/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index c17610366..47167fa2b 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dnspython', 'mock', 'setuptools', diff --git a/certbot-dns-route53/local-oldest-requirements.txt b/certbot-dns-route53/local-oldest-requirements.txt index 1ee716cd6..3fce6f83b 100644 --- a/certbot-dns-route53/local-oldest-requirements.txt +++ b/certbot-dns-route53/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index c0f69fb4f..b4dcc58c1 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'boto3', 'mock', 'setuptools', diff --git a/certbot-dns-sakuracloud/local-oldest-requirements.txt b/certbot-dns-sakuracloud/local-oldest-requirements.txt index aefe03f90..67d4cc53b 100644 --- a/certbot-dns-sakuracloud/local-oldest-requirements.txt +++ b/certbot-dns-sakuracloud/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 -certbot[dev]==0.39.0 +-e certbot[dev] diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 68795cd2b..56c209a90 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -9,7 +9,7 @@ version = '1.1.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'acme>=0.31.0', - 'certbot>=0.39.0', + 'certbot>=1.0.0.dev0', 'dns-lexicon>=2.1.23', 'mock', 'setuptools', diff --git a/certbot-nginx/certbot_nginx/_internal/configurator.py b/certbot-nginx/certbot_nginx/_internal/configurator.py index 6802df421..70d9d87f8 100644 --- a/certbot-nginx/certbot_nginx/_internal/configurator.py +++ b/certbot-nginx/certbot_nginx/_internal/configurator.py @@ -283,7 +283,7 @@ class NginxConfigurator(common.Installer): filtered_vhosts[name] = vhost # Only unique VHost objects - dialog_input = set([vhost for vhost in filtered_vhosts.values()]) + dialog_input = set(filtered_vhosts.values()) # Ask the user which of names to enable, expect list of names back return_vhosts = display_ops.select_vhost_multiple(list(dialog_input)) diff --git a/certbot-nginx/certbot_nginx/_internal/nginxparser.py b/certbot-nginx/certbot_nginx/_internal/nginxparser.py index 04b1ffa01..4fa1362a0 100644 --- a/certbot-nginx/certbot_nginx/_internal/nginxparser.py +++ b/certbot-nginx/certbot_nginx/_internal/nginxparser.py @@ -186,12 +186,11 @@ class UnspacedList(list): """ if not isinstance(inbound, list): # str or None - return (inbound, inbound) + return inbound, inbound else: if not hasattr(inbound, "spaced"): inbound = UnspacedList(inbound) - return (inbound, inbound.spaced) - + return inbound, inbound.spaced def insert(self, i, x): item, spaced_item = self._coerce(x) diff --git a/certbot-nginx/certbot_nginx/_internal/parser.py b/certbot-nginx/certbot_nginx/_internal/parser.py index 0b1eb1682..edb77a1c1 100644 --- a/certbot-nginx/certbot_nginx/_internal/parser.py +++ b/certbot-nginx/certbot_nginx/_internal/parser.py @@ -275,7 +275,7 @@ class NginxParser(object): for directive in server: if not directive: continue - elif _is_ssl_on_directive(directive): + if _is_ssl_on_directive(directive): return True return False @@ -489,7 +489,7 @@ def get_best_match(target_name, names): def _exact_match(target_name, name): - return target_name == name or '.' + target_name == name + return name in (target_name, '.' + target_name) def _wildcard_match(target_name, name, start): @@ -507,7 +507,7 @@ def _wildcard_match(target_name, name, start): # The first part must be a wildcard or blank, e.g. '.eff.org' first = match_parts.pop(0) - if first != '*' and first != '': + if first not in ('*', ''): return False target_name = '.'.join(parts) @@ -585,7 +585,7 @@ def comment_directive(block, location): if isinstance(next_entry, list) and next_entry: if len(next_entry) >= 2 and next_entry[-2] == "#" and COMMENT in next_entry[-1]: return - elif isinstance(next_entry, nginxparser.UnspacedList): + if isinstance(next_entry, nginxparser.UnspacedList): next_entry = next_entry.spaced[0] else: next_entry = next_entry[0] @@ -661,13 +661,12 @@ def _add_directive(block, directive, insert_at_top): for included_directive in included_directives: included_dir_loc = _find_location(block, included_directive[0]) included_dir_name = included_directive[0] - if not _is_whitespace_or_comment(included_directive) \ - and not can_append(included_dir_loc, included_dir_name): + if (not _is_whitespace_or_comment(included_directive) + and not can_append(included_dir_loc, included_dir_name)): if block[included_dir_loc] != included_directive: raise errors.MisconfigurationError(err_fmt.format(included_directive, block[included_dir_loc])) - else: - _comment_out_directive(block, included_dir_loc, directive[1]) + _comment_out_directive(block, included_dir_loc, directive[1]) if can_append(location, directive_name): if insert_at_top: diff --git a/certbot-nginx/local-oldest-requirements.txt b/certbot-nginx/local-oldest-requirements.txt index 0e30f44eb..37532aabf 100644 --- a/certbot-nginx/local-oldest-requirements.txt +++ b/certbot-nginx/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==1.0.0 -certbot[dev]==1.0.0 +-e certbot[dev] diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index c844c85f5..96bf32d3e 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -10,7 +10,7 @@ version = '1.1.0.dev0' # acme/certbot version. install_requires = [ 'acme>=1.0.0', - 'certbot>=1.0.0', + 'certbot>=1.0.0.dev0', 'mock', 'PyOpenSSL', 'pyparsing>=1.5.5', # Python3 support; perhaps unnecessary? diff --git a/certbot-nginx/tests/configurator_test.py b/certbot-nginx/tests/configurator_test.py index afa28befb..ef5593395 100644 --- a/certbot-nginx/tests/configurator_test.py +++ b/certbot-nginx/tests/configurator_test.py @@ -1091,7 +1091,7 @@ class DetermineDefaultServerRootTest(certbot_test_util.ConfigTestCase): self.assertIn("/usr/local/etc/nginx", server_root) self.assertIn("/etc/nginx", server_root) else: - self.assertTrue(server_root == "/etc/nginx" or server_root == "/usr/local/etc/nginx") + self.assertTrue(server_root in ("/etc/nginx", "/usr/local/etc/nginx")) if __name__ == "__main__": diff --git a/certbot-nginx/tests/parser_test.py b/certbot-nginx/tests/parser_test.py index 5beee1111..2f3b260ca 100644 --- a/certbot-nginx/tests/parser_test.py +++ b/certbot-nginx/tests/parser_test.py @@ -49,16 +49,16 @@ class NginxParserTest(util.NginxTest): """ nparser = parser.NginxParser(self.config_path) nparser.load() - self.assertEqual(set([nparser.abs_path(x) for x in - ['foo.conf', 'nginx.conf', 'server.conf', - 'sites-enabled/default', - 'sites-enabled/example.com', - 'sites-enabled/headers.com', - 'sites-enabled/migration.com', - 'sites-enabled/sslon.com', - 'sites-enabled/globalssl.com', - 'sites-enabled/ipv6.com', - 'sites-enabled/ipv6ssl.com']]), + self.assertEqual({nparser.abs_path(x) for x in + ['foo.conf', 'nginx.conf', 'server.conf', + 'sites-enabled/default', + 'sites-enabled/example.com', + 'sites-enabled/headers.com', + 'sites-enabled/migration.com', + 'sites-enabled/sslon.com', + 'sites-enabled/globalssl.com', + 'sites-enabled/ipv6.com', + 'sites-enabled/ipv6ssl.com']}, set(nparser.parsed.keys())) self.assertEqual([['server_name', 'somename', 'alias', 'another.alias']], nparser.parsed[nparser.abs_path('server.conf')]) diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py index d33aa6d0c..c4ea6ef35 100644 --- a/certbot/certbot/_internal/account.py +++ b/certbot/certbot/_internal/account.py @@ -216,9 +216,8 @@ class AccountFileStorage(interfaces.AccountStorage): else: self._symlink_to_accounts_dir(prev_server_path, server_path) return prev_loaded_account - else: - raise errors.AccountNotFound( - "Account at %s does not exist" % account_dir_path) + raise errors.AccountNotFound( + "Account at %s does not exist" % account_dir_path) try: with open(self._regr_path(account_dir_path)) as regr_file: diff --git a/certbot/certbot/_internal/auth_handler.py b/certbot/certbot/_internal/auth_handler.py index 55415b46d..e4ad91247 100644 --- a/certbot/certbot/_internal/auth_handler.py +++ b/certbot/certbot/_internal/auth_handler.py @@ -285,9 +285,8 @@ def challb_to_achall(challb, account_key, domain): challb=challb, domain=domain, account_key=account_key) elif isinstance(chall, challenges.DNS): return achallenges.DNS(challb=challb, domain=domain) - else: - raise errors.Error( - "Received unsupported challenge of type: {0}".format(chall.typ)) + raise errors.Error( + "Received unsupported challenge of type: {0}".format(chall.typ)) def gen_challenge_path(challbs, preferences, combinations): diff --git a/certbot/certbot/_internal/cert_manager.py b/certbot/certbot/_internal/cert_manager.py index da7b7a190..1def76a3d 100644 --- a/certbot/certbot/_internal/cert_manager.py +++ b/certbot/certbot/_internal/cert_manager.py @@ -242,8 +242,8 @@ def match_and_check_overlaps(cli_config, acceptable_matches, match_func, rv_func raise errors.Error("No match found for cert-path {0}!".format(cli_config.cert_path[0])) elif len(matched) > 1: raise errors.OverlappingMatchFound() - else: - return matched + return matched + def human_readable_cert_info(config, cert, skip_filter_checks=False): """ Returns a human readable description of info about a RenewableCert object""" diff --git a/certbot/certbot/_internal/cli.py b/certbot/certbot/_internal/cli.py index 886904c0a..fb3010a4e 100644 --- a/certbot/certbot/_internal/cli.py +++ b/certbot/certbot/_internal/cli.py @@ -287,10 +287,9 @@ def flag_default(name): def config_help(name, hidden=False): """Extract the help message for an `.IConfig` attribute.""" - # pylint: disable=no-member if hidden: return argparse.SUPPRESS - field = interfaces.IConfig.__getitem__(name) # type: zope.interface.interface.Attribute # pylint: disable=no-value-for-parameter + field = interfaces.IConfig.__getitem__(name) # type: zope.interface.interface.Attribute return field.__doc__ @@ -674,7 +673,7 @@ class HelpfulArgumentParser(object): parsed_args.actual_csr = (csr, typ) - csr_domains = set([d.lower() for d in domains]) + csr_domains = {d.lower() for d in domains} config_domains = set(parsed_args.domains) if csr_domains != config_domains: raise errors.ConfigurationError( @@ -847,11 +846,11 @@ class HelpfulArgumentParser(object): chosen_topic = "run" if chosen_topic == "all": # Addition of condition closes #6209 (removal of duplicate route53 option). - return dict([(t, True) if t != 'certbot-route53:auth' else (t, False) - for t in self.help_topics]) + return {t: t != 'certbot-route53:auth' for t in self.help_topics} elif not chosen_topic: - return dict([(t, False) for t in self.help_topics]) - return dict([(t, t == chosen_topic) for t in self.help_topics]) + return {t: False for t in self.help_topics} + return {t: t == chosen_topic for t in self.help_topics} + def _add_all_groups(helpful): helpful.add_group("automation", description="Flags for automating execution & other tweaks") diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py index c9977d4d7..9ce741e38 100644 --- a/certbot/certbot/_internal/client.py +++ b/certbot/certbot/_internal/client.py @@ -224,11 +224,9 @@ def perform_registration(acme, config, tos_cb): "Please ensure it is a valid email and attempt " "registration again." % config.email) raise errors.Error(msg) - else: - config.email = display_ops.get_email(invalid=True) - return perform_registration(acme, config, tos_cb) - else: - raise + config.email = display_ops.get_email(invalid=True) + return perform_registration(acme, config, tos_cb) + raise class Client(object): @@ -360,7 +358,6 @@ class Client(object): return self.obtain_certificate(successful_domains) else: cert, chain = self.obtain_certificate_from_csr(csr, orderr) - return cert, chain, key, csr def _get_order_and_authorizations(self, csr_pem, best_effort): @@ -393,8 +390,6 @@ class Client(object): authzr = self.auth_handler.handle_authorizations(orderr, best_effort) return orderr.update(authorizations=authzr) - - # pylint: disable=no-member def obtain_and_enroll_certificate(self, domains, certname): """Obtain and enroll certificate. diff --git a/certbot/certbot/_internal/configuration.py b/certbot/certbot/_internal/configuration.py index 6e9c185f4..f3db207db 100644 --- a/certbot/certbot/_internal/configuration.py +++ b/certbot/certbot/_internal/configuration.py @@ -1,7 +1,7 @@ """Certbot user-supplied configuration.""" import copy -from six.moves.urllib import parse # pylint: disable=relative-import +from six.moves.urllib import parse import zope.interface from certbot import errors diff --git a/certbot/certbot/_internal/error_handler.py b/certbot/certbot/_internal/error_handler.py index a2f9a3dc6..5ca3cc57e 100644 --- a/certbot/certbot/_internal/error_handler.py +++ b/certbot/certbot/_internal/error_handler.py @@ -93,7 +93,7 @@ class ErrorHandler(object): # SystemExit is ignored to properly handle forks that don't exec if exec_type is SystemExit: return retval - elif exec_type is None: + if exec_type is None: if not self.call_on_regular_exit: return retval elif exec_type is errors.SignalExit: diff --git a/certbot/certbot/_internal/log.py b/certbot/certbot/_internal/log.py index 56ac2c3fe..0a492ba55 100644 --- a/certbot/certbot/_internal/log.py +++ b/certbot/certbot/_internal/log.py @@ -102,9 +102,9 @@ def post_arg_parse_setup(config): root_logger.addHandler(file_handler) root_logger.removeHandler(memory_handler) - temp_handler = memory_handler.target - memory_handler.setTarget(file_handler) - memory_handler.flush(force=True) + temp_handler = memory_handler.target # pylint: disable=no-member + memory_handler.setTarget(file_handler) # pylint: disable=no-member + memory_handler.flush(force=True) # pylint: disable=unexpected-keyword-arg memory_handler.close() temp_handler.close() diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index f87b7c571..72fcfca71 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -121,7 +121,7 @@ def _get_and_save_cert(le_client, config, domains=None, certname=None, lineage=N lineage = le_client.obtain_and_enroll_certificate(domains, certname) if lineage is False: raise errors.Error("Certificate could not be obtained") - elif lineage is not None: + if lineage is not None: hooks.deploy_hook(config, lineage.names(), lineage.live_dir) finally: hooks.post_hook(config) @@ -162,19 +162,18 @@ def _handle_subset_cert_request(config, domains, cert): cli_flag="--expand", force_interactive=True): return "renew", cert - else: - reporter_util = zope.component.getUtility(interfaces.IReporter) - reporter_util.add_message( - "To obtain a new certificate that contains these names without " - "replacing your existing certificate for {0}, you must use the " - "--duplicate option.{br}{br}" - "For example:{br}{br}{1} --duplicate {2}".format( - existing, - sys.argv[0], " ".join(sys.argv[1:]), - br=os.linesep - ), - reporter_util.HIGH_PRIORITY) - raise errors.Error(USER_CANCELLED) + reporter_util = zope.component.getUtility(interfaces.IReporter) + reporter_util.add_message( + "To obtain a new certificate that contains these names without " + "replacing your existing certificate for {0}, you must use the " + "--duplicate option.{br}{br}" + "For example:{br}{br}{1} --duplicate {2}".format( + existing, + sys.argv[0], " ".join(sys.argv[1:]), + br=os.linesep + ), + reporter_util.HIGH_PRIORITY) + raise errors.Error(USER_CANCELLED) def _handle_identical_cert_request(config, lineage): @@ -220,7 +219,7 @@ def _handle_identical_cert_request(config, lineage): # skipping the menu for this case. raise errors.Error( "Operation canceled. You may re-run the client.") - elif response[1] == 0: + if response[1] == 0: return "reinstall", lineage elif response[1] == 1: return "renew", lineage @@ -312,23 +311,20 @@ def _find_lineage_for_domains_and_certname(config, domains, certname): """ if not certname: return _find_lineage_for_domains(config, domains) - else: - lineage = cert_manager.lineage_for_certname(config, certname) - if lineage: - if domains: - if set(cert_manager.domains_for_certname(config, certname)) != set(domains): - _ask_user_to_confirm_new_names(config, domains, certname, - lineage.names()) # raises if no - return "renew", lineage - # unnecessarily specified domains or no domains specified - return _handle_identical_cert_request(config, lineage) - else: - if domains: - return "newcert", None - else: - raise errors.ConfigurationError("No certificate with name {0} found. " - "Use -d to specify domains, or run certbot certificates to see " - "possible certificate names.".format(certname)) + lineage = cert_manager.lineage_for_certname(config, certname) + if lineage: + if domains: + if set(cert_manager.domains_for_certname(config, certname)) != set(domains): + _ask_user_to_confirm_new_names(config, domains, certname, + lineage.names()) # raises if no + return "renew", lineage + # unnecessarily specified domains or no domains specified + return _handle_identical_cert_request(config, lineage) + elif domains: + return "newcert", None + raise errors.ConfigurationError("No certificate with name {0} found. " + "Use -d to specify domains, or run certbot certificates to see " + "possible certificate names.".format(certname)) def _get_added_removed(after, before): """Get lists of items removed from `before` @@ -1338,7 +1334,7 @@ def main(cli_args=None): make_or_verify_needed_dirs(config) except errors.Error: # Let plugins_cmd be run as un-privileged user. - if config.func != plugins_cmd: + if config.func != plugins_cmd: # pylint: disable=comparison-with-callable raise set_displayer(config) diff --git a/certbot/certbot/_internal/ocsp.py b/certbot/certbot/_internal/ocsp.py index 8312d7fe0..65a6d5c17 100644 --- a/certbot/certbot/_internal/ocsp.py +++ b/certbot/certbot/_internal/ocsp.py @@ -296,5 +296,5 @@ def _translate_ocsp_query(cert_path, ocsp_output, ocsp_errors): return True else: logger.warning("Unable to properly parse OCSP output: %s\nstderr:%s", - ocsp_output, ocsp_errors) + ocsp_output, ocsp_errors) return False diff --git a/certbot/certbot/_internal/plugins/selection.py b/certbot/certbot/_internal/plugins/selection.py index de1d27227..6d87e4b07 100644 --- a/certbot/certbot/_internal/plugins/selection.py +++ b/certbot/certbot/_internal/plugins/selection.py @@ -64,9 +64,8 @@ def get_unprepared_installer(config, plugins): inst = list(installers.values())[0] logger.debug("Selecting plugin: %s", inst) return inst.init(config) - else: - raise errors.PluginSelectionError( - "Could not select or initialize the requested installer %s." % req_inst) + raise errors.PluginSelectionError( + "Could not select or initialize the requested installer %s." % req_inst) def pick_plugin(config, default, plugins, question, ifaces): """Pick plugin. @@ -209,7 +208,7 @@ def choose_configurator_plugins(config, plugins, verb): need_inst = need_auth = False if verb == "certonly": need_auth = True - if verb == "install" or verb == "enhance": + elif verb in ("install", "enhance"): need_inst = True if config.authenticator: logger.warning("Specifying an authenticator doesn't make sense when " diff --git a/certbot/certbot/_internal/plugins/standalone.py b/certbot/certbot/_internal/plugins/standalone.py index bb816cd46..80421299e 100644 --- a/certbot/certbot/_internal/plugins/standalone.py +++ b/certbot/certbot/_internal/plugins/standalone.py @@ -76,7 +76,6 @@ class ServerManager(object): servers.serve_forever() # if port == 0, then random free port on OS is taken - # pylint: disable=no-member # both servers, if they exist, have the same port real_port = servers.getsocknames()[0][1] self._instances[real_port] = servers @@ -196,7 +195,7 @@ def _handle_perform_error(error): "the appropriate permissions (for example, you " "aren't running this program as " "root).".format(error.port)) - elif error.socket_error.errno == socket_errors.EADDRINUSE: + if error.socket_error.errno == socket_errors.EADDRINUSE: display = zope.component.getUtility(interfaces.IDisplay) msg = ( "Could not bind TCP port {0} because it is already in " diff --git a/certbot/certbot/_internal/plugins/webroot.py b/certbot/certbot/_internal/plugins/webroot.py index 837918345..c7737e0d1 100644 --- a/certbot/certbot/_internal/plugins/webroot.py +++ b/certbot/certbot/_internal/plugins/webroot.py @@ -135,8 +135,7 @@ to serve all files under specified web root ({0}).""" raise errors.PluginError( "Every requested domain must have a " "webroot when using the webroot plugin.") - else: # code == display_util.OK - return None if index == 0 else known_webroots[index - 1] + return None if index == 0 else known_webroots[index - 1] # code == display_util.OK def _prompt_for_new_webroot(self, domain, allowraise=False): code, webroot = ops.validated_directory( @@ -146,12 +145,10 @@ to serve all files under specified web root ({0}).""" if code == display_util.CANCEL: if not allowraise: return None - else: - raise errors.PluginError( - "Every requested domain must have a " - "webroot when using the webroot plugin.") - else: # code == display_util.OK - return _validate_webroot(webroot) + raise errors.PluginError( + "Every requested domain must have a " + "webroot when using the webroot plugin.") + return _validate_webroot(webroot) # code == display_util.OK def _create_challenge_dirs(self): path_map = self.conf("map") diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py index 4947ca067..0426b2e2d 100644 --- a/certbot/certbot/_internal/renewal.py +++ b/certbot/certbot/_internal/renewal.py @@ -471,5 +471,4 @@ def handle_renewal_request(config): if renew_failures or parse_failures: raise errors.Error("{0} renew failure(s), {1} parse failure(s)".format( len(renew_failures), len(parse_failures))) - else: - logger.debug("no renewal failures") + logger.debug("no renewal failures") diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index b632e9d52..964515eee 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -1014,10 +1014,8 @@ class RenewableCert(interfaces.RenewableCert): "directory %s created.", archive, live_dir) # Put the data into the appropriate files on disk - target = dict([(kind, os.path.join(live_dir, kind + ".pem")) - for kind in ALL_FOUR]) - archive_target = dict([(kind, os.path.join(archive, kind + "1.pem")) - for kind in ALL_FOUR]) + target = {kind: os.path.join(live_dir, kind + ".pem") for kind in ALL_FOUR} + archive_target = {kind: os.path.join(archive, kind + "1.pem") for kind in ALL_FOUR} for kind in ALL_FOUR: os.symlink(_relpath_from_file(archive_target[kind], target[kind]), target[kind]) with open(target["cert"], "wb") as f: @@ -1082,10 +1080,8 @@ class RenewableCert(interfaces.RenewableCert): self.cli_config = cli_config target_version = self.next_free_version() - target = dict( - [(kind, - os.path.join(self.archive_dir, "{0}{1}.pem".format(kind, target_version))) - for kind in ALL_FOUR]) + target = {kind: os.path.join(self.archive_dir, "{0}{1}.pem".format(kind, target_version)) + for kind in ALL_FOUR} old_privkey = os.path.join( self.archive_dir, "privkey{0}.pem".format(prior_version)) diff --git a/certbot/certbot/compat/filesystem.py b/certbot/certbot/compat/filesystem.py index b7a4683df..ba4a155e8 100644 --- a/certbot/certbot/compat/filesystem.py +++ b/certbot/certbot/compat/filesystem.py @@ -71,6 +71,9 @@ def copy_ownership_and_apply_mode(src, dst, mode, copy_user, copy_group): stats = os.stat(src) user_id = stats.st_uid if copy_user else -1 group_id = stats.st_gid if copy_group else -1 + # On Windows, os.chown does not exist. This is checked through POSIX_MODE value, + # but MyPy/PyLint does not know it and raises an error here on Windows. + # We disable specifically the check to fix the issue. os.chown(dst, user_id, group_id) elif copy_user: # There is no group handling in Windows @@ -105,7 +108,10 @@ def check_owner(file_path): :return: True if given file is owned by current user, False otherwise. """ if POSIX_MODE: - return os.stat(file_path).st_uid == os.getuid() + # On Windows, os.getuid does not exist. This is checked through POSIX_MODE value, + # but MyPy/PyLint does not know it and raises an error here on Windows. + # We disable specifically the check to fix the issue. + return os.stat(file_path).st_uid == os.getuid() # type: ignore # Get owner sid of the file security = win32security.GetFileSecurity(file_path, win32security.OWNER_SECURITY_INFORMATION) diff --git a/certbot/certbot/display/ops.py b/certbot/certbot/display/ops.py index 185c21b58..92b09d6a1 100644 --- a/certbot/certbot/display/ops.py +++ b/certbot/certbot/display/ops.py @@ -60,11 +60,10 @@ def get_email(invalid=False, optional=True): raise errors.Error( "An e-mail address or " "--register-unsafely-without-email must be provided.") - else: - raise errors.Error("An e-mail address must be provided.") - elif util.safe_email(email): + raise errors.Error("An e-mail address must be provided.") + if util.safe_email(email): return email - elif suggest_unsafe: + if suggest_unsafe: msg += unsafe_suggestion suggest_unsafe = False # add this message at most once diff --git a/certbot/certbot/display/util.py b/certbot/certbot/display/util.py index 05b69e539..ba2dd4ecf 100644 --- a/certbot/certbot/display/util.py +++ b/certbot/certbot/display/util.py @@ -177,7 +177,7 @@ class FileDisplay(object): message = _wrap_lines("%s (Enter 'c' to cancel):" % message) + " " ans = input_with_timeout(message) - if ans == "c" or ans == "C": + if ans in ("c", "C"): return CANCEL, "-1" return OK, ans @@ -258,10 +258,9 @@ class FileDisplay(object): selected_tags = self._scrub_checklist_input(indices, tags) if selected_tags: return code, selected_tags - else: - self.outfile.write( - "** Error - Invalid selection **%s" % os.linesep) - self.outfile.flush() + self.outfile.write( + "** Error - Invalid selection **%s" % os.linesep) + self.outfile.flush() else: return code, [] @@ -282,18 +281,17 @@ class FileDisplay(object): # assert_valid_call(prompt, default, cli_flag, force_interactive) if self._can_interact(force_interactive): return False - elif default is None: + if default is None: msg = "Unable to get an answer for the question:\n{0}".format(prompt) if cli_flag: msg += ( "\nYou can provide an answer on the " "command line with the {0} flag.".format(cli_flag)) raise errors.Error(msg) - else: - logger.debug( - "Falling back to default %s for the prompt:\n%s", - default, prompt) - return True + logger.debug( + "Falling back to default %s for the prompt:\n%s", + default, prompt) + return True def _can_interact(self, force_interactive): """Can we safely interact with the user? @@ -308,7 +306,7 @@ class FileDisplay(object): if (self.force_interactive or force_interactive or sys.stdin.isatty() and self.outfile.isatty()): return True - elif not self.skipped_interaction: + if not self.skipped_interaction: logger.warning( "Skipped user interaction because Certbot doesn't appear to " "be running in a terminal. You should probably include " diff --git a/certbot/certbot/plugins/common.py b/certbot/certbot/plugins/common.py index b56559c0e..6fa1e76f8 100644 --- a/certbot/certbot/plugins/common.py +++ b/certbot/certbot/plugins/common.py @@ -33,6 +33,7 @@ def dest_namespace(name): """ArgumentParser dest namespace (prefix of all destinations).""" return name.replace("-", "_") + "_" + private_ips_regex = re.compile( r"(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|" r"(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)") @@ -294,7 +295,7 @@ class Addr(object): # appended to the end append_to_end = True continue - elif len(block) > 1: + if len(block) > 1: # remove leading zeros block = block.lstrip("0") if not append_to_end: @@ -373,9 +374,9 @@ def install_version_controlled_file(dest_path, digest_path, src_path, all_hashes active_file_digest = crypto_util.sha256sum(dest_path) if active_file_digest == current_hash: # already up to date return - elif active_file_digest in all_hashes: # safe to update + if active_file_digest in all_hashes: # safe to update _install_current_file() - else: # has been manually modified, not safe to update + else: # has been manually modified, not safe to update # did they modify the current version or an old version? if os.path.isfile(digest_path): with open(digest_path, "r") as f: diff --git a/certbot/certbot/plugins/dns_common.py b/certbot/certbot/plugins/dns_common.py index 10d5010f2..d31266434 100644 --- a/certbot/certbot/plugins/dns_common.py +++ b/certbot/certbot/plugins/dns_common.py @@ -197,8 +197,7 @@ class DNSAuthenticator(common.Plugin): if code == display_util.OK: return response - else: - raise errors.PluginError('{0} required to proceed.'.format(label)) + raise errors.PluginError('{0} required to proceed.'.format(label)) @staticmethod def _prompt_for_file(label, validator=None): @@ -231,8 +230,7 @@ class DNSAuthenticator(common.Plugin): if code == display_util.OK: return response - else: - raise errors.PluginError('{0} required to proceed.'.format(label)) + raise errors.PluginError('{0} required to proceed.'.format(label)) class CredentialsConfiguration(object): diff --git a/certbot/certbot/plugins/dns_common_lexicon.py b/certbot/certbot/plugins/dns_common_lexicon.py index 71bba76d8..3e28a291b 100644 --- a/certbot/certbot/plugins/dns_common_lexicon.py +++ b/certbot/certbot/plugins/dns_common_lexicon.py @@ -100,7 +100,7 @@ class LexiconClient(object): result = self._handle_general_error(e, domain_name) if result: - raise result + raise result # pylint: disable=raising-bad-type raise errors.PluginError('Unable to determine zone identifier for {0} using zone names: {1}' .format(domain, domain_name_guesses)) diff --git a/certbot/certbot/plugins/dns_test_common.py b/certbot/certbot/plugins/dns_test_common.py index 3f269c99c..9ef76c2c3 100644 --- a/certbot/certbot/plugins/dns_test_common.py +++ b/certbot/certbot/plugins/dns_test_common.py @@ -28,18 +28,14 @@ class BaseAuthenticatorTest(object): challb=acme_util.DNS01, domain=DOMAIN, account_key=KEY) def test_more_info(self): - # pylint: disable=no-member - self.assertTrue(isinstance(self.auth.more_info(), six.string_types)) + self.assertTrue(isinstance(self.auth.more_info(), six.string_types)) # pylint: disable=no-member def test_get_chall_pref(self): - # pylint: disable=no-member - self.assertEqual(self.auth.get_chall_pref(None), [challenges.DNS01]) + self.assertEqual(self.auth.get_chall_pref(None), [challenges.DNS01]) # pylint: disable=no-member def test_parser_arguments(self): m = mock.MagicMock() - - # pylint: disable=no-member - self.auth.add_parser_arguments(m) + self.auth.add_parser_arguments(m) # pylint: disable=no-member m.assert_any_call('propagation-seconds', type=int, default=mock.ANY, help=mock.ANY) diff --git a/certbot/certbot/tests/util.py b/certbot/certbot/tests/util.py index d757ab05a..02abe0a31 100644 --- a/certbot/certbot/tests/util.py +++ b/certbot/certbot/tests/util.py @@ -57,8 +57,7 @@ def _guess_loader(filename, loader_pem, loader_der): return loader_pem elif ext.lower() == '.der': return loader_der - else: # pragma: no cover - raise ValueError("Loader could not be recognized based on extension") + raise ValueError("Loader could not be recognized based on extension") # pragma: no cover def load_cert(*names): @@ -235,8 +234,7 @@ class FreezableMock(object): if self._frozen: if name in self._frozen_set: raise AttributeError('Cannot change frozen attribute ' + name) - else: - return setattr(self._mock, name, value) + return setattr(self._mock, name, value) if name != '_frozen_set': self._frozen_set.add(name) @@ -250,7 +248,7 @@ class FreezableMock(object): def _create_get_utility_mock(): display = FreezableMock() # Use pylint code for disable to keep on single line under line length limit - for name in interfaces.IDisplay.names(): # pylint: disable=no-member,E1120 + for name in interfaces.IDisplay.names(): # pylint: E1120 if name != 'notification': frozen_mock = FreezableMock(frozen=True, func=_assert_valid_call) setattr(display, name, frozen_mock) @@ -275,7 +273,7 @@ def _create_get_utility_mock_with_stdout(stdout): display = FreezableMock() # Use pylint code for disable to keep on single line under line length limit - for name in interfaces.IDisplay.names(): # pylint: disable=no-member,E1120 + for name in interfaces.IDisplay.names(): # pylint: E1120 if name == 'notification': frozen_mock = FreezableMock(frozen=True, func=_write_msg) diff --git a/certbot/certbot/util.py b/certbot/certbot/util.py index d56fe6845..0a47cd87a 100644 --- a/certbot/certbot/util.py +++ b/certbot/certbot/util.py @@ -26,7 +26,7 @@ from certbot.compat import filesystem from certbot.compat import os if sys.platform.startswith('linux'): - import distro + import distro # pylint: disable=import-error _USE_DISTRO = True else: _USE_DISTRO = False @@ -105,10 +105,9 @@ def exe_exists(exe): path, _ = os.path.split(exe) if path: return filesystem.is_executable(exe) - else: - for path in os.environ["PATH"].split(os.pathsep): - if filesystem.is_executable(os.path.join(path, exe)): - return True + for path in os.environ["PATH"].split(os.pathsep): + if filesystem.is_executable(os.path.join(path, exe)): + return True return False @@ -436,7 +435,6 @@ def add_deprecated_argument(add_argument, argument_name, nargs): # In version 0.12.0 ACTION_TYPES_THAT_DONT_NEED_A_VALUE was # changed from a set to a tuple. if isinstance(configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE, set): - # pylint: disable=no-member configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE.add( _ShowWarning) else: @@ -537,7 +535,7 @@ def enforce_domain_sanity(domain): for l in labels: if not l: raise errors.ConfigurationError("{0} it contains an empty label.".format(msg)) - elif len(l) > 63: + if len(l) > 63: raise errors.ConfigurationError("{0} label {1} is too long.".format(msg, l)) return domain @@ -571,7 +569,6 @@ def get_strict_version(normalized): """ # strict version ending with "a" and a number designates a pre-release - # pylint: disable=no-member return distutils.version.StrictVersion(normalized.replace(".dev", "a")) diff --git a/certbot/setup.py b/certbot/setup.py index d76494a84..0026ef8e9 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -74,21 +74,21 @@ elif os.name == 'nt': install_requires.append(pywin32_req) dev_extras = [ - 'astroid==1.6.5', 'coverage', 'ipdb', 'pytest', 'pytest-cov', 'pytest-xdist', - 'pylint==1.9.4', 'tox', 'twine', 'wheel', ] dev3_extras = [ + 'astroid', 'mypy', - 'typing', # for python3.4 + 'pylint', + 'typing', # for python3.4 ] docs_extras = [ diff --git a/certbot/tests/auth_handler_test.py b/certbot/tests/auth_handler_test.py index b38618daf..7ab3a2baa 100644 --- a/certbot/tests/auth_handler_test.py +++ b/certbot/tests/auth_handler_test.py @@ -494,7 +494,7 @@ class ReportFailedAuthzrsTest(unittest.TestCase): self.authzr1.body.identifier.value = 'example.com' self.authzr1.body.challenges = [http_01, http_01] - kwargs["error"] = messages.Error(typ="dnssec", detail="detail") + kwargs["error"] = messages.Error.with_code("dnssec", detail="detail") http_01_diff = messages.ChallengeBody(**kwargs) self.authzr2 = mock.MagicMock() diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 2c838214e..81134f02f 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -178,7 +178,7 @@ class CertificatesTest(BaseCertManagerTest): mock_verifier.return_value = None mock_report.return_value = "" self._certificates(self.config) - self.assertFalse(mock_logger.warning.called) #pylint: disable=no-member + self.assertFalse(mock_logger.warning.called) self.assertTrue(mock_report.called) self.assertTrue(mock_utility.called) self.assertTrue(mock_renewable_cert.called) @@ -196,7 +196,7 @@ class CertificatesTest(BaseCertManagerTest): filesystem.makedirs(empty_config.renewal_configs_dir) self._certificates(empty_config) - self.assertFalse(mock_logger.warning.called) #pylint: disable=no-member + self.assertFalse(mock_logger.warning.called) self.assertTrue(mock_utility.called) shutil.rmtree(empty_tempdir) @@ -240,7 +240,7 @@ class CertificatesTest(BaseCertManagerTest): # pylint: disable=protected-access out = get_report() self.assertTrue('3 days' in out) - self.assertTrue('VALID' in out and 'INVALID' not in out) + self.assertTrue('VALID' in out and 'INVALID' not in out) cert.is_test_cert = True mock_revoked.return_value = True diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index bc3727043..7232ed84b 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -205,7 +205,7 @@ class RegisterTest(test_util.ConfigTestCase): def test_unsupported_error(self): from acme import messages msg = "Test" - mx_err = messages.Error(detail=msg, typ="malformed", title="title") + mx_err = messages.Error.with_code("malformed", detail=msg, title="title") with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client: mock_client().client.directory.__getitem__ = mock.Mock( side_effect=self._new_acct_dir_mock diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index f700e0908..e721bbd48 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -363,6 +363,8 @@ class CheckPermissionsTest(test_util.TempDirTestCase): self.assertTrue(filesystem.check_owner(self.probe_path)) import os as std_os # pylint: disable=os-module-forbidden + # See related inline comment in certbot.compat.filesystem.check_owner method + # that explains why MyPy/PyLint check disable is needed here. uid = std_os.getuid() with mock.patch('os.getuid') as mock_uid: diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index ca9f1e382..615f33406 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -311,12 +311,12 @@ class FileOutputDisplayTest(unittest.TestCase): def test_methods_take_force_interactive(self): # Every IDisplay method implemented by FileDisplay must take # force_interactive to prevent workflow regressions. - for name in interfaces.IDisplay.names(): # pylint: disable=no-member,no-value-for-parameter + for name in interfaces.IDisplay.names(): if six.PY2: - getargspec = inspect.getargspec # pylint: disable=no-member + getargspec = inspect.getargspec else: - getargspec = inspect.getfullargspec # pylint: disable=no-member - arg_spec = getargspec(getattr(self.displayer, name)) + getargspec = inspect.getfullargspec + arg_spec = getargspec(getattr(self.displayer, name)) # pylint: disable=deprecated-method self.assertTrue("force_interactive" in arg_spec.args) @@ -372,14 +372,14 @@ class NoninteractiveDisplayTest(unittest.TestCase): # NoninteractiveDisplay. # Use pylint code for disable to keep on single line under line length limit - for name in interfaces.IDisplay.names(): # pylint: disable=no-member,E1120 + for name in interfaces.IDisplay.names(): # pylint: disable=E1120 method = getattr(self.displayer, name) # asserts method accepts arbitrary keyword arguments if six.PY2: - result = inspect.getargspec(method).keywords # pylint: disable=no-member + result = inspect.getargspec(method).keywords # pylint:deprecated-method self.assertFalse(result is None) else: - result = inspect.getfullargspec(method).varkw # pylint: disable=no-member + result = inspect.getfullargspec(method).varkw self.assertFalse(result is None) diff --git a/certbot/tests/eff_test.py b/certbot/tests/eff_test.py index b53187f47..cdd7908a3 100644 --- a/certbot/tests/eff_test.py +++ b/certbot/tests/eff_test.py @@ -111,7 +111,7 @@ class SubscribeTest(unittest.TestCase): @test_util.patch_get_utility() def test_bad_status(self, mock_get_utility): self.json['status'] = False - self._call() # pylint: disable=no-value-for-parameter + self._call() actual = self._get_reported_message(mock_get_utility) expected_part = 'because your e-mail address appears to be invalid.' self.assertTrue(expected_part in actual) @@ -120,7 +120,7 @@ class SubscribeTest(unittest.TestCase): def test_not_ok(self, mock_get_utility): self.response.ok = False self.response.raise_for_status.side_effect = requests.exceptions.HTTPError - self._call() # pylint: disable=no-value-for-parameter + self._call() actual = self._get_reported_message(mock_get_utility) unexpected_part = 'because' self.assertFalse(unexpected_part in actual) @@ -128,7 +128,7 @@ class SubscribeTest(unittest.TestCase): @test_util.patch_get_utility() def test_response_not_json(self, mock_get_utility): self.response.json.side_effect = ValueError() - self._call() # pylint: disable=no-value-for-parameter + self._call() actual = self._get_reported_message(mock_get_utility) expected_part = 'problem' self.assertTrue(expected_part in actual) @@ -136,7 +136,7 @@ class SubscribeTest(unittest.TestCase): @test_util.patch_get_utility() def test_response_json_missing_status_element(self, mock_get_utility): self.json.clear() - self._call() # pylint: disable=no-value-for-parameter + self._call() actual = self._get_reported_message(mock_get_utility) expected_part = 'problem' self.assertTrue(expected_part in actual) @@ -147,7 +147,7 @@ class SubscribeTest(unittest.TestCase): @test_util.patch_get_utility() def test_subscribe(self, mock_get_utility): - self._call() # pylint: disable=no-value-for-parameter + self._call() self.assertFalse(mock_get_utility.called) diff --git a/certbot/tests/errors_test.py b/certbot/tests/errors_test.py index b7951284f..d6c829322 100644 --- a/certbot/tests/errors_test.py +++ b/certbot/tests/errors_test.py @@ -13,25 +13,27 @@ class FailedChallengesTest(unittest.TestCase): def setUp(self): from certbot.errors import FailedChallenges - self.error = FailedChallenges(set([achallenges.DNS( + self.error = FailedChallenges({achallenges.DNS( domain="example.com", challb=messages.ChallengeBody( chall=acme_util.DNS01, uri=None, - error=messages.Error(typ="tls", detail="detail")))])) + error=messages.Error.with_code("tls", detail="detail")))}) def test_str(self): self.assertTrue(str(self.error).startswith( - "Failed authorization procedure. example.com (dns-01): tls")) + "Failed authorization procedure. example.com (dns-01): " + "urn:ietf:params:acme:error:tls")) def test_unicode(self): from certbot.errors import FailedChallenges arabic_detail = u'\u0639\u062f\u0627\u0644\u0629' - arabic_error = FailedChallenges(set([achallenges.DNS( + arabic_error = FailedChallenges({achallenges.DNS( domain="example.com", challb=messages.ChallengeBody( chall=acme_util.DNS01, uri=None, - error=messages.Error(typ="tls", detail=arabic_detail)))])) + error=messages.Error.with_code("tls", detail=arabic_detail)))}) self.assertTrue(str(arabic_error).startswith( - "Failed authorization procedure. example.com (dns-01): tls")) + "Failed authorization procedure. example.com (dns-01): " + "urn:ietf:params:acme:error:tls")) class StandaloneBindErrorTest(unittest.TestCase): diff --git a/certbot/tests/plugins/enhancements_test.py b/certbot/tests/plugins/enhancements_test.py index 3ecda2019..05fbc5028 100644 --- a/certbot/tests/plugins/enhancements_test.py +++ b/certbot/tests/plugins/enhancements_test.py @@ -37,12 +37,10 @@ class EnhancementTest(test_util.ConfigTestCase): self.assertTrue([i for i in enabled if i["name"] == "somethingelse"]) def test_are_requested(self): - self.assertEqual( - len([i for i in enhancements.enabled_enhancements(self.config)]), 0) + self.assertEqual(len(list(enhancements.enabled_enhancements(self.config))), 0) self.assertFalse(enhancements.are_requested(self.config)) self.config.auto_hsts = True - self.assertEqual( - len([i for i in enhancements.enabled_enhancements(self.config)]), 1) + self.assertEqual(len(list(enhancements.enabled_enhancements(self.config))), 1) self.assertTrue(enhancements.are_requested(self.config)) def test_are_supported(self): diff --git a/certbot/tests/plugins/standalone_test.py b/certbot/tests/plugins/standalone_test.py index afca48bd9..5d9ff5244 100644 --- a/certbot/tests/plugins/standalone_test.py +++ b/certbot/tests/plugins/standalone_test.py @@ -37,7 +37,7 @@ class ServerManagerTest(unittest.TestCase): def _test_run_stop(self, challenge_type): server = self.mgr.run(port=0, challenge_type=challenge_type) - port = server.getsocknames()[0][1] # pylint: disable=no-member + port = server.getsocknames()[0][1] self.assertEqual(self.mgr.running(), {port: server}) self.mgr.stop(port=port) self.assertEqual(self.mgr.running(), {}) @@ -47,7 +47,7 @@ class ServerManagerTest(unittest.TestCase): def test_run_idempotent(self): server = self.mgr.run(port=0, challenge_type=challenges.HTTP01) - port = server.getsocknames()[0][1] # pylint: disable=no-member + port = server.getsocknames()[0][1] server2 = self.mgr.run(port=port, challenge_type=challenges.HTTP01) self.assertEqual(self.mgr.running(), {port: server}) self.assertTrue(server is server2) diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 8e127b21d..6208974ec 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -356,8 +356,7 @@ class RenewableCertTests(BaseRenewableCertTest): basename = os.path.basename(path) if "fullchain" in basename and basename.startswith("prev"): raise ValueError - else: - real_unlink(path) + real_unlink(path) self._write_out_ex_kinds() with mock.patch("certbot._internal.storage.os.unlink") as mock_unlink: @@ -372,8 +371,7 @@ class RenewableCertTests(BaseRenewableCertTest): # pylint: disable=missing-docstring if "fullchain" in os.path.basename(path): raise ValueError - else: - real_unlink(path) + real_unlink(path) self._write_out_ex_kinds() with mock.patch("certbot._internal.storage.os.unlink") as mock_unlink: diff --git a/letshelp-certbot/letshelp_certbot/apache.py b/letshelp-certbot/letshelp_certbot/apache.py index 50f3c5ef6..ebe4e3671 100755 --- a/letshelp-certbot/letshelp_certbot/apache.py +++ b/letshelp-certbot/letshelp_certbot/apache.py @@ -74,7 +74,7 @@ def make_and_verify_selection(server_root, temp_dir): ans = six.moves.input("(Y)es/(N)o: ").lower() if ans.startswith("y"): return - elif ans.startswith("n"): + if ans.startswith("n"): sys.exit("Your files were not submitted") @@ -159,7 +159,7 @@ def safe_config_file(config_file): empty_or_all_comments = False if line.startswith("-----BEGIN"): return False - elif ":" not in line: + if ":" not in line: possible_password_file = False # If file isn't empty or commented out and could be a password file, # don't include it in selection. It is safe to include the file if diff --git a/tests/lock_test.py b/tests/lock_test.py index e6481941f..29a77ae17 100644 --- a/tests/lock_test.py +++ b/tests/lock_test.py @@ -173,7 +173,7 @@ def setup_certificate(workspace): key_path = os.path.join(workspace, 'cert.key') with open(key_path, 'wb') as file_handle: - file_handle.write(private_key.private_bytes( + file_handle.write(private_key.private_bytes( # type: ignore encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index dd5a97600..a4c877ba8 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -6,7 +6,7 @@ alabaster==0.7.10 apipkg==1.4 appnope==0.1.0 asn1crypto==0.22.0 -astroid==1.6.5 +astroid==2.3.3 attrs==17.3.0 Babel==2.5.1 backports.functools-lru-cache==1.5 @@ -33,17 +33,18 @@ importlib-metadata==0.23 ipdb==0.10.2 ipython==5.5.0 ipython-genutils==0.2.0 -isort==4.2.5 +isort==4.3.21 Jinja2==2.9.6 jmespath==0.9.3 josepy==1.1.0 -lazy-object-proxy==1.3.1 +lazy-object-proxy==1.4.3 logger==1.4 logilab-common==1.4.1 MarkupSafe==1.0 mccabe==0.6.1 more-itertools==5.0.0 -mypy==0.600 +mypy==0.710 +mypy-extensions==0.4.3 ndg-httpsclient==0.3.2 oauth2client==4.0.0 packaging==19.2 @@ -58,7 +59,7 @@ py==1.8.0 pyasn1==0.1.9 pyasn1-modules==0.0.10 Pygments==2.2.0 -pylint==1.9.4 +pylint==2.4.3 # If pynsist version is upgraded, our NSIS template windows-installer/template.nsi # must be upgraded if necessary using the new built-in one from pynsist. pynsist==2.4 @@ -90,10 +91,10 @@ tox==3.14.0 tqdm==4.19.4 traitlets==4.3.2 twine==1.11.0 -typed-ast==1.1.0 +typed-ast==1.4.0 typing==3.6.4 uritemplate==3.0.0 virtualenv==16.6.2 wcwidth==0.1.7 -wrapt==1.11.1 +wrapt==1.11.2 zipp==0.6.0 diff --git a/tox.ini b/tox.ini index 10f8ec914..5f1a9a426 100644 --- a/tox.ini +++ b/tox.ini @@ -122,12 +122,13 @@ commands = python tox.cover.py [testenv:lint] -basepython = python2.7 +basepython = python3 # separating into multiple invocations disables cross package # duplicate code checking; if one of the commands fails, others will # continue, but tox return code will reflect previous error commands = {[base]install_packages} + {[base]pip_install} certbot[dev3] python -m pylint --reports=n --rcfile=.pylintrc {[base]source_paths} [testenv:mypy]