mirror of
https://github.com/certbot/certbot.git
synced 2026-07-28 00:35:50 +02:00
Prepare certbot module for mypy check untyped defs (#6005)
* Prepare certbot module for mypy check untyped defs * Fix #5952 * Bump mypy to version 0.600 and fix associated bugs * Fix pylint bugs after introducing mypy * Implement Brad's suggestions * Reenabling pylint and adding nginx mypy back
This commit is contained in:
committed by
Brad Warren
parent
250c0d6691
commit
36dfd06503
@@ -11,6 +11,8 @@ import zope.interface
|
||||
|
||||
from josepy import util as jose_util
|
||||
|
||||
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
|
||||
from certbot import achallenges # pylint: disable=unused-import
|
||||
from certbot import constants
|
||||
from certbot import crypto_util
|
||||
from certbot import errors
|
||||
@@ -331,8 +333,8 @@ class ChallengePerformer(object):
|
||||
|
||||
def __init__(self, configurator):
|
||||
self.configurator = configurator
|
||||
self.achalls = []
|
||||
self.indices = []
|
||||
self.achalls = [] # type: List[achallenges.KeyAuthorizationAnnotatedChallenge]
|
||||
self.indices = [] # type: List[int]
|
||||
|
||||
def add_chall(self, achall, idx=None):
|
||||
"""Store challenge to be performed when perform() is called.
|
||||
|
||||
@@ -10,6 +10,7 @@ from collections import OrderedDict
|
||||
import zope.interface
|
||||
import zope.interface.verify
|
||||
|
||||
from acme.magic_typing import Dict # pylint: disable=unused-import, no-name-in-module
|
||||
from certbot import constants
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
@@ -189,7 +190,7 @@ class PluginsRegistry(collections.Mapping):
|
||||
@classmethod
|
||||
def find_all(cls):
|
||||
"""Find plugins using setuptools entry points."""
|
||||
plugins = {}
|
||||
plugins = {} # type: Dict[str, PluginEntryPoint]
|
||||
# pylint: disable=not-callable
|
||||
entry_points = itertools.chain(
|
||||
pkg_resources.iter_entry_points(
|
||||
|
||||
@@ -8,6 +8,7 @@ import pkg_resources
|
||||
import six
|
||||
import zope.interface
|
||||
|
||||
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
|
||||
@@ -250,7 +251,7 @@ class PluginsRegistryTest(unittest.TestCase):
|
||||
self.plugin_ep.prepare.assert_called_once_with()
|
||||
|
||||
def test_prepare_order(self):
|
||||
order = []
|
||||
order = [] # type: List[str]
|
||||
plugins = dict(
|
||||
(c, mock.MagicMock(prepare=functools.partial(order.append, c)))
|
||||
for c in string.ascii_letters)
|
||||
|
||||
@@ -5,7 +5,9 @@ import zope.component
|
||||
import zope.interface
|
||||
|
||||
from acme import challenges
|
||||
from acme.magic_typing import Dict # pylint: disable=unused-import, no-name-in-module
|
||||
|
||||
from certbot import achallenges # pylint: disable=unused-import
|
||||
from certbot import interfaces
|
||||
from certbot import errors
|
||||
from certbot import hooks
|
||||
@@ -98,7 +100,8 @@ when it receives a TLS ClientHello with the SNI extension set to
|
||||
super(Authenticator, self).__init__(*args, **kwargs)
|
||||
self.reverter = reverter.Reverter(self.config)
|
||||
self.reverter.recovery_routine()
|
||||
self.env = dict()
|
||||
self.env = dict() \
|
||||
# type: Dict[achallenges.KeyAuthorizationAnnotatedChallenge, Dict[str, str]]
|
||||
self.tls_sni_01 = None
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -6,6 +6,7 @@ import unittest
|
||||
import mock
|
||||
import zope.component
|
||||
|
||||
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
|
||||
from certbot.display import util as display_util
|
||||
from certbot.tests import util as test_util
|
||||
from certbot import interfaces
|
||||
@@ -47,7 +48,7 @@ class PickPluginTest(unittest.TestCase):
|
||||
self.default = None
|
||||
self.reg = mock.MagicMock()
|
||||
self.question = "Question?"
|
||||
self.ifaces = []
|
||||
self.ifaces = [] # type: List[interfaces.IPlugin]
|
||||
|
||||
def _call(self):
|
||||
from certbot.plugins.selection import pick_plugin
|
||||
|
||||
@@ -3,6 +3,8 @@ import argparse
|
||||
import collections
|
||||
import logging
|
||||
import socket
|
||||
# https://github.com/python/typeshed/blob/master/stdlib/2and3/socket.pyi
|
||||
from socket import errno as socket_errors # type: ignore
|
||||
|
||||
import OpenSSL
|
||||
import six
|
||||
@@ -10,7 +12,10 @@ import zope.interface
|
||||
|
||||
from acme import challenges
|
||||
from acme import standalone as acme_standalone
|
||||
# pylint: disable=unused-import, no-name-in-module
|
||||
from acme.magic_typing import DefaultDict, Dict, Set, Tuple, List, Type, TYPE_CHECKING
|
||||
|
||||
from certbot import achallenges # pylint: disable=unused-import
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
|
||||
@@ -18,6 +23,11 @@ from certbot.plugins import common
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ServedType = DefaultDict[
|
||||
acme_standalone.BaseDualNetworkedServers,
|
||||
Set[achallenges.KeyAuthorizationAnnotatedChallenge]
|
||||
]
|
||||
|
||||
class ServerManager(object):
|
||||
"""Standalone servers manager.
|
||||
@@ -33,7 +43,7 @@ class ServerManager(object):
|
||||
|
||||
"""
|
||||
def __init__(self, certs, http_01_resources):
|
||||
self._instances = {}
|
||||
self._instances = {} # type: Dict[int, acme_standalone.BaseDualNetworkedServers]
|
||||
self.certs = certs
|
||||
self.http_01_resources = http_01_resources
|
||||
|
||||
@@ -59,7 +69,8 @@ class ServerManager(object):
|
||||
address = (listenaddr, port)
|
||||
try:
|
||||
if challenge_type is challenges.TLSSNI01:
|
||||
servers = acme_standalone.TLSSNI01DualNetworkedServers(address, self.certs)
|
||||
servers = acme_standalone.TLSSNI01DualNetworkedServers(
|
||||
address, self.certs) # type: acme_standalone.BaseDualNetworkedServers
|
||||
else: # challenges.HTTP01
|
||||
servers = acme_standalone.HTTP01DualNetworkedServers(
|
||||
address, self.http_01_resources)
|
||||
@@ -103,7 +114,8 @@ class ServerManager(object):
|
||||
return self._instances.copy()
|
||||
|
||||
|
||||
SUPPORTED_CHALLENGES = [challenges.TLSSNI01, challenges.HTTP01]
|
||||
SUPPORTED_CHALLENGES = [challenges.TLSSNI01, challenges.HTTP01] \
|
||||
# type: List[Type[challenges.KeyAuthorizationChallenge]]
|
||||
|
||||
|
||||
class SupportedChallengesAction(argparse.Action):
|
||||
@@ -179,14 +191,15 @@ class Authenticator(common.Plugin):
|
||||
self.key = OpenSSL.crypto.PKey()
|
||||
self.key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
|
||||
|
||||
self.served = collections.defaultdict(set)
|
||||
self.served = collections.defaultdict(set) # type: ServedType
|
||||
|
||||
# Stuff below is shared across threads (i.e. servers read
|
||||
# values, main thread writes). Due to the nature of CPython's
|
||||
# GIL, the operations are safe, c.f.
|
||||
# https://docs.python.org/2/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe
|
||||
self.certs = {}
|
||||
self.http_01_resources = set()
|
||||
self.certs = {} # type: Dict[bytes, Tuple[OpenSSL.crypto.PKey, OpenSSL.crypto.X509]]
|
||||
self.http_01_resources = set() \
|
||||
# type: Set[acme_standalone.HTTP01RequestHandler.HTTP01Resource]
|
||||
|
||||
self.servers = ServerManager(self.certs, self.http_01_resources)
|
||||
|
||||
@@ -265,13 +278,13 @@ class Authenticator(common.Plugin):
|
||||
|
||||
|
||||
def _handle_perform_error(error):
|
||||
if error.socket_error.errno == socket.errno.EACCES:
|
||||
if error.socket_error.errno == socket_errors.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))
|
||||
elif error.socket_error.errno == socket.errno.EADDRINUSE:
|
||||
elif 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 "
|
||||
|
||||
@@ -2,12 +2,18 @@
|
||||
import argparse
|
||||
import socket
|
||||
import unittest
|
||||
# https://github.com/python/typeshed/blob/master/stdlib/2and3/socket.pyi
|
||||
from socket import errno as socket_errors # type: ignore
|
||||
|
||||
import josepy as jose
|
||||
import mock
|
||||
import six
|
||||
|
||||
import OpenSSL.crypto # pylint: disable=unused-import
|
||||
|
||||
from acme import challenges
|
||||
from acme import standalone as acme_standalone # pylint: disable=unused-import
|
||||
from acme.magic_typing import Dict, Tuple, Set # pylint: disable=unused-import, no-name-in-module
|
||||
|
||||
from certbot import achallenges
|
||||
from certbot import errors
|
||||
@@ -21,8 +27,9 @@ class ServerManagerTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
from certbot.plugins.standalone import ServerManager
|
||||
self.certs = {}
|
||||
self.http_01_resources = {}
|
||||
self.certs = {} # type: Dict[bytes, Tuple[OpenSSL.crypto.PKey, OpenSSL.crypto.X509]]
|
||||
self.http_01_resources = {} \
|
||||
# type: Set[acme_standalone.HTTP01RequestHandler.HTTP01Resource]
|
||||
self.mgr = ServerManager(self.certs, self.http_01_resources)
|
||||
|
||||
def test_init(self):
|
||||
@@ -159,7 +166,7 @@ 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.errno.EADDRINUSE
|
||||
errno = socket_errors.EADDRINUSE
|
||||
error = errors.StandaloneBindError(mock.MagicMock(errno=errno), -1)
|
||||
self.auth.servers.run.side_effect = [error] + 2 * [mock.MagicMock()]
|
||||
mock_yesno = mock_utility.yesno
|
||||
@@ -174,7 +181,7 @@ class AuthenticatorTest(unittest.TestCase):
|
||||
mock_yesno = mock_utility.yesno
|
||||
mock_yesno.return_value = False
|
||||
|
||||
errno = socket.errno.EADDRINUSE
|
||||
errno = socket_errors.EADDRINUSE
|
||||
self.assertRaises(errors.PluginError, self._fail_perform, errno)
|
||||
self._assert_correct_yesno_call(mock_yesno)
|
||||
|
||||
@@ -184,11 +191,11 @@ class AuthenticatorTest(unittest.TestCase):
|
||||
self.assertFalse(yesno_kwargs.get("default", True))
|
||||
|
||||
def test_perform_eacces(self):
|
||||
errno = socket.errno.EACCES
|
||||
errno = socket_errors.EACCES
|
||||
self.assertRaises(errors.PluginError, self._fail_perform, errno)
|
||||
|
||||
def test_perform_unexpected_socket_error(self):
|
||||
errno = socket.errno.ENOTCONN
|
||||
errno = socket_errors.ENOTCONN
|
||||
self.assertRaises(
|
||||
errors.StandaloneBindError, self._fail_perform, errno)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from acme.magic_typing import Any, Dict # pylint: disable=unused-import, no-name-in-module
|
||||
from certbot import errors
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -38,7 +39,7 @@ class PluginStorage(object):
|
||||
|
||||
:raises .errors.PluginStorageError: when unable to open or read the file
|
||||
"""
|
||||
data = dict()
|
||||
data = dict() # type: Dict[str, Any]
|
||||
filedata = ""
|
||||
try:
|
||||
with open(self._storagepath, 'r') as fh:
|
||||
|
||||
@@ -10,8 +10,12 @@ import six
|
||||
import zope.component
|
||||
import zope.interface
|
||||
|
||||
from acme import challenges
|
||||
from acme import challenges # pylint: disable=unused-import
|
||||
# pylint: disable=unused-import, no-name-in-module
|
||||
from acme.magic_typing import Dict, Set, DefaultDict, List
|
||||
# pylint: enable=unused-import, no-name-in-module
|
||||
|
||||
from certbot import achallenges # pylint: disable=unused-import
|
||||
from certbot import cli
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
@@ -64,10 +68,11 @@ to serve all files under specified web root ({0})."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Authenticator, self).__init__(*args, **kwargs)
|
||||
self.full_roots = {}
|
||||
self.performed = collections.defaultdict(set)
|
||||
self.full_roots = {} # type: Dict[str, str]
|
||||
self.performed = collections.defaultdict(set) \
|
||||
# type: DefaultDict[str, Set[achallenges.KeyAuthorizationAnnotatedChallenge]]
|
||||
# stack of dirs successfully created by this authenticator
|
||||
self._created_dirs = []
|
||||
self._created_dirs = [] # type: List[str]
|
||||
|
||||
def prepare(self): # pylint: disable=missing-docstring
|
||||
pass
|
||||
@@ -156,7 +161,6 @@ to serve all files under specified web root ({0})."""
|
||||
" --help webroot for examples.")
|
||||
for name, path in path_map.items():
|
||||
self.full_roots[name] = os.path.join(path, challenges.HTTP01.URI_ROOT_PATH)
|
||||
|
||||
logger.debug("Creating root challenges validation dir at %s",
|
||||
self.full_roots[name])
|
||||
|
||||
@@ -207,7 +211,6 @@ to serve all files under specified web root ({0})."""
|
||||
os.umask(old_umask)
|
||||
|
||||
self.performed[root_path].add(achall)
|
||||
|
||||
return response
|
||||
|
||||
def cleanup(self, achalls): # pylint: disable=missing-docstring
|
||||
@@ -219,7 +222,7 @@ to serve all files under specified web root ({0})."""
|
||||
os.remove(validation_path)
|
||||
self.performed[root_path].remove(achall)
|
||||
|
||||
not_removed = []
|
||||
not_removed = [] # type: List[str]
|
||||
while len(self._created_dirs) > 0:
|
||||
path = self._created_dirs.pop()
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user