Merge pull request #752 from kuba/lint

pep8 love
This commit is contained in:
James Kasten
2015-09-11 03:37:28 -04:00
58 changed files with 167 additions and 118 deletions
+4
View File
@@ -0,0 +1,4 @@
[pep8]
# E265 block comment should start with '# '
# E501 line too long (X > 79 characters)
ignore = E265,E501
+1 -1
View File
@@ -218,7 +218,7 @@ ignore-long-lines=^\s*(# )?<?https?://\S+>?$
single-line-if-stmt=no
# List of optional constructs for which whitespace checking is disabled
no-space-check=trailing-comma,dict-separator
no-space-check=trailing-comma
# Maximum number of lines in a module
max-module-lines=1250
+5 -5
View File
@@ -136,7 +136,7 @@ class SimpleHTTPResponseTest(unittest.TestCase):
jose.JWS.sign(payload=bad_resource.json_dumps().encode('utf-8'),
alg=jose.RS256, key=account_key)
for bad_resource in (resource.update(tls=True),
resource.update(token=b'x'*20))
resource.update(token=(b'x' * 20)))
)
for validation in validations:
self.assertFalse(self.resp_http.check_validation(
@@ -320,7 +320,7 @@ class DVSNIResponseTest(unittest.TestCase):
def test_simple_verify_wrong_token(self):
msg = self.msg.update(validation=jose.JWS.sign(
payload=self.chall.update(token=b'b'*20).json_dumps().encode(),
payload=self.chall.update(token=(b'b' * 20)).json_dumps().encode(),
key=self.key, alg=jose.RS256))
self.assertFalse(msg.simple_verify(
self.chall, self.domain, self.key.public_key()))
@@ -350,9 +350,9 @@ class RecoveryContactTest(unittest.TestCase):
contact='c********n@example.com')
self.jmsg = {
'type': 'recoveryContact',
'activationURL' : 'https://example.ca/sendrecovery/a5bd99383fb0',
'successURL' : 'https://example.ca/confirmrecovery/bb1b9928932',
'contact' : 'c********n@example.com',
'activationURL': 'https://example.ca/sendrecovery/a5bd99383fb0',
'successURL': 'https://example.ca/confirmrecovery/bb1b9928932',
'contact': 'c********n@example.com',
}
def test_to_partial_json(self):
+4
View File
@@ -390,11 +390,14 @@ class ClientNetworkTest(unittest.TestCase):
# pylint: disable=missing-docstring
def __init__(self, value):
self.value = value
def to_partial_json(self):
return {'foo': self.value}
@classmethod
def from_json(cls, value):
pass # pragma: no cover
# pylint: disable=protected-access
jws_dump = self.net._wrap_in_jws(
MockJSONDeSerializable('foo'), nonce=b'Tg')
@@ -498,6 +501,7 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase):
self.all_nonces = [jose.b64encode(b'Nonce'), jose.b64encode(b'Nonce2')]
self.available_nonces = self.all_nonces[:]
def send_request(*args, **kwargs):
# pylint: disable=unused-argument,missing-docstring
if self.available_nonces:
+11 -4
View File
@@ -307,6 +307,7 @@ def encode_b64jose(data):
# b64encode produces ASCII characters only
return b64.b64encode(data).decode('ascii')
def decode_b64jose(data, size=None, minimum=False):
"""Decode JOSE Base-64 field.
@@ -324,13 +325,14 @@ def decode_b64jose(data, size=None, minimum=False):
except error_cls as error:
raise errors.DeserializationError(error)
if size is not None and ((not minimum and len(decoded) != size)
or (minimum and len(decoded) < size)):
if size is not None and ((not minimum and len(decoded) != size) or
(minimum and len(decoded) < size)):
raise errors.DeserializationError(
"Expected at least or exactly {0} bytes".format(size))
return decoded
def encode_hex16(value):
"""Hexlify.
@@ -340,6 +342,7 @@ def encode_hex16(value):
"""
return binascii.hexlify(value).decode()
def decode_hex16(value, size=None, minimum=False):
"""Decode hexlified field.
@@ -352,8 +355,8 @@ def decode_hex16(value, size=None, minimum=False):
"""
value = value.encode()
if size is not None and ((not minimum and len(value) != size * 2)
or (minimum and len(value) < size * 2)):
if size is not None and ((not minimum and len(value) != size * 2) or
(minimum and len(value) < size * 2)):
raise errors.DeserializationError()
error_cls = TypeError if six.PY2 else binascii.Error
try:
@@ -361,6 +364,7 @@ def decode_hex16(value, size=None, minimum=False):
except error_cls as error:
raise errors.DeserializationError(error)
def encode_cert(cert):
"""Encode certificate as JOSE Base-64 DER.
@@ -371,6 +375,7 @@ def encode_cert(cert):
return encode_b64jose(OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_ASN1, cert))
def decode_cert(b64der):
"""Decode JOSE Base-64 DER-encoded certificate.
@@ -384,6 +389,7 @@ def decode_cert(b64der):
except OpenSSL.crypto.Error as error:
raise errors.DeserializationError(error)
def encode_csr(csr):
"""Encode CSR as JOSE Base-64 DER.
@@ -394,6 +400,7 @@ def encode_csr(csr):
return encode_b64jose(OpenSSL.crypto.dump_certificate_request(
OpenSSL.crypto.FILETYPE_ASN1, csr))
def decode_csr(b64der):
"""Decode JOSE Base-64 DER-encoded CSR.
+5
View File
@@ -52,6 +52,7 @@ class FieldTest(unittest.TestCase):
# pylint: disable=missing-docstring
def to_partial_json(self):
return 'foo' # pragma: no cover
@classmethod
def from_json(cls, jobj):
pass # pragma: no cover
@@ -93,14 +94,18 @@ class JSONObjectWithFieldsMetaTest(unittest.TestCase):
self.field2 = Field('Baz2')
# pylint: disable=invalid-name,missing-docstring,too-few-public-methods
# pylint: disable=blacklisted-name
@six.add_metaclass(JSONObjectWithFieldsMeta)
class A(object):
__slots__ = ('bar',)
baz = self.field
class B(A):
pass
class C(A):
baz = self.field2
self.a_cls = A
self.b_cls = B
self.c_cls = C
+2 -2
View File
@@ -21,7 +21,7 @@ from acme.jose import jwk
logger = logging.getLogger(__name__)
class JWA(interfaces.JSONDeSerializable): # pylint: disable=abstract-method
class JWA(interfaces.JSONDeSerializable): # pylint: disable=abstract-method
# pylint: disable=too-few-public-methods
# for some reason disable=abstract-method has to be on the line
# above...
@@ -159,7 +159,7 @@ class _JWAES(JWASignature): # pylint: disable=abstract-class-not-used
def sign(self, key, msg): # pragma: no cover
raise NotImplementedError()
def verify(self, key, msg, sig): # pragma: no cover
def verify(self, key, msg, sig): # pragma: no cover
raise NotImplementedError()
+1 -1
View File
@@ -231,7 +231,7 @@ class JWKRSA(JWK):
'n': numbers.n,
'e': numbers.e,
}
else: # rsa.RSAPrivateKey
else: # rsa.RSAPrivateKey
private = self.key.private_numbers()
public = self.key.public_key().public_numbers()
params = {
+5 -4
View File
@@ -294,10 +294,10 @@ class JWS(json_util.JSONObjectWithFields):
# ... it must be in protected
return (
b64.b64encode(self.signature.protected.encode('utf-8'))
+ b'.' +
b64.b64encode(self.payload)
+ b'.' +
b64.b64encode(self.signature.protected.encode('utf-8')) +
b'.' +
b64.b64encode(self.payload) +
b'.' +
b64.b64encode(self.signature.signature))
@classmethod
@@ -345,6 +345,7 @@ class JWS(json_util.JSONObjectWithFields):
signatures=tuple(cls.signature_cls.from_json(sig)
for sig in jobj['signatures']))
class CLI(object):
"""JWS CLI."""
+5
View File
@@ -265,17 +265,20 @@ class Registration(ResourceBody):
"""All emails found in the ``contact`` field."""
return self._filter_contact(self.email_prefix)
@Directory.register
class NewRegistration(Registration):
"""New registration."""
resource_type = 'new-reg'
resource = fields.Resource(resource_type)
class UpdateRegistration(Registration):
"""Update registration."""
resource_type = 'reg'
resource = fields.Resource(resource_type)
class RegistrationResource(ResourceWithURI):
"""Registration Resource.
@@ -378,12 +381,14 @@ class Authorization(ResourceBody):
return tuple(tuple(self.challenges[idx] for idx in combo)
for combo in self.combinations)
@Directory.register
class NewAuthorization(Authorization):
"""New authorization."""
resource_type = 'new-authz'
resource = fields.Resource(resource_type)
class AuthorizationResource(ResourceWithURI):
"""Authorization Resource.
+1 -1
View File
@@ -60,6 +60,7 @@ class ConstantTest(unittest.TestCase):
def setUp(self):
from acme.messages import _Constant
class MockConstant(_Constant): # pylint: disable=missing-docstring
POSSIBLE_NAMES = {}
@@ -250,7 +251,6 @@ class ChallengeBodyTest(unittest.TestCase):
'detail': 'Unable to communicate with DNS server',
}
def test_to_partial_json(self):
self.assertEqual(self.jobj_to, self.challb.to_partial_json())
+6
View File
@@ -20,12 +20,14 @@ def vector_path(*names):
return pkg_resources.resource_filename(
__name__, os.path.join('testdata', *names))
def load_vector(*names):
"""Load contents of a test vector."""
# luckily, resource_string opens file in binary mode
return pkg_resources.resource_string(
__name__, os.path.join('testdata', *names))
def _guess_loader(filename, loader_pem, loader_der):
_, ext = os.path.splitext(filename)
if ext.lower() == '.pem':
@@ -35,6 +37,7 @@ def _guess_loader(filename, loader_pem, loader_der):
else: # pragma: no cover
raise ValueError("Loader could not be recognized based on extension")
def load_cert(*names):
"""Load certificate."""
loader = _guess_loader(
@@ -42,6 +45,7 @@ def load_cert(*names):
return jose.ComparableX509(OpenSSL.crypto.load_certificate(
loader, load_vector(*names)))
def load_csr(*names):
"""Load certificate request."""
loader = _guess_loader(
@@ -49,6 +53,7 @@ def load_csr(*names):
return jose.ComparableX509(OpenSSL.crypto.load_certificate_request(
loader, load_vector(*names)))
def load_rsa_private_key(*names):
"""Load RSA private key."""
loader = _guess_loader(names[-1], serialization.load_pem_private_key,
@@ -56,6 +61,7 @@ def load_rsa_private_key(*names):
return jose.ComparableRSAKey(loader(
load_vector(*names), password=None, backend=default_backend()))
def load_pyopenssl_private_key(*names):
"""Load pyOpenSSL private key."""
loader = _guess_loader(
@@ -84,7 +84,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
description = "Apache Web Server - Alpha"
@classmethod
def add_parser_arguments(cls, add):
add("ctl", default=constants.CLI_DEFAULTS["ctl"],
@@ -283,7 +282,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
self.assoc[target_name] = vhost
return vhost
def _find_best_vhost(self, target_name):
"""Finds the best vhost for a target_name.
@@ -582,7 +580,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
ssl_vhost = self._create_vhost(vh_p)
self.vhosts.append(ssl_vhost)
# NOTE: Searches through Augeas seem to ruin changes to directives
# The configuration must also be saved before being searched
# for the new directives; For these reasons... this is tacked
@@ -793,7 +790,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
raise errors.PluginError(
"Let's Encrypt has already enabled redirection")
def _create_redirect_vhost(self, ssl_vhost):
"""Creates an http_vhost specifically to redirect for the ssl_vhost.
@@ -996,9 +992,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
"""
# Support Debian specific setup
if (not os.path.isdir(os.path.join(self.parser.root, "mods-available"))
or not os.path.isdir(
os.path.join(self.parser.root, "mods-enabled"))):
avail_path = os.path.join(self.parser.root, "mods-available")
enabled_path = os.path.join(self.parser.root, "mods-enabled")
if not os.path.isdir(avail_path) or not os.path.isdir(enabled_path):
raise errors.NotSupportedError(
"Unsupported directory layout. You may try to enable mod %s "
"and try again." % mod_name)
+2 -2
View File
@@ -14,8 +14,8 @@ class Addr(common.Addr):
"""
if isinstance(other, self.__class__):
return ((self.tup == other.tup) or
(self.tup[0] == other.tup[0]
and self.is_wildcard() and other.is_wildcard()))
(self.tup[0] == other.tup[0] and
self.is_wildcard() and other.is_wildcard()))
return False
def __ne__(self, other):
@@ -195,8 +195,7 @@ class ApacheParser(object):
self.aug.set(nvh_path + "/arg", args[0])
else:
for i, arg in enumerate(args):
self.aug.set("%s/arg[%d]" % (nvh_path, i+1), arg)
self.aug.set("%s/arg[%d]" % (nvh_path, i + 1), arg)
def _get_ifmod(self, aug_conf_path, mod):
"""Returns the path to <IfMod mod> and creates one if it doesn't exist.
@@ -568,7 +567,7 @@ def case_i(string):
:param str string: string to make case i regex
"""
return "".join(["["+c.upper()+c.lower()+"]"
return "".join(["[" + c.upper() + c.lower() + "]"
if c.isalpha() else c for c in re.escape(string)])
@@ -56,7 +56,6 @@ class ComplexParserTest(util.ParserTest):
self.assertRaises(
errors.PluginError, self.parser.get_arg, matches[0])
def test_basic_ifdefine(self):
self.assertEqual(len(self.parser.find_dir("VAR_DIRECTIVE")), 2)
self.assertEqual(len(self.parser.find_dir("INVALID_VAR_DIRECTIVE")), 0)
@@ -71,7 +70,6 @@ class ComplexParserTest(util.ParserTest):
self.assertEqual(
len(self.parser.find_dir("INVALID_NESTED_DIRECTIVE")), 0)
def test_load_modules(self):
"""If only first is found, there is bad variable parsing."""
self.assertTrue("status_module" in self.parser.modules)
@@ -551,6 +551,7 @@ class TwoVhost80Test(util.ApacheTest):
self.assertRaises(
errors.PluginError,
self.config.enhance, "letsencrypt.demo", "redirect")
def test_unknown_rewrite2(self):
# Skip the enable mod
self.config.parser.modules.add("rewrite_module")
@@ -143,7 +143,7 @@ class BasicParserTest(util.ParserTest):
'Group: name="www-data" id=33 not_used\n'
)
expected_vars = {"TEST": "", "U_MICH": "", "TLS": "443",
"example_path":"Documents/path"}
"example_path": "Documents/path"}
self.parser.update_runtime_variables("ctl")
self.assertEqual(self.parser.variables, expected_vars)
+1 -1
View File
@@ -18,7 +18,7 @@ setup(
entry_points={
'letsencrypt.plugins': [
'apache = letsencrypt_apache.configurator:ApacheConfigurator',
],
],
},
include_package_data=True,
)
@@ -11,7 +11,7 @@ from letsencrypt_compatibility_test.configurators.apache import common as apache
# config uses mod_heartbeat or mod_heartmonitor (which aren't installed and
# therefore the config won't be loaded), I believe this isn't a problem
# http://httpd.apache.org/docs/2.4/mod/mod_watchdog.html
STATIC_MODULES = {"core", "so", "http", "mpm_event", "watchdog",}
STATIC_MODULES = set(["core", "so", "http", "mpm_event", "watchdog"])
SHARED_MODULES = {
@@ -31,7 +31,7 @@ SHARED_MODULES = {
"session_cookie", "session_crypto", "session_dbd", "setenvif",
"slotmem_shm", "socache_dbm", "socache_memcache", "socache_shmcb",
"speling", "ssl", "status", "substitute", "unique_id", "userdir",
"vhost_alias",}
"vhost_alias"}
class Proxy(apache_common.Proxy):
@@ -72,11 +72,10 @@ class Proxy(object):
logger.debug(line)
host_config = docker.utils.create_host_config(
binds={
self._temp_dir : {"bind" : self._temp_dir, "mode" : "rw"}},
binds={self._temp_dir: {"bind": self._temp_dir, "mode": "rw"}},
port_bindings={
80 : ("127.0.0.1", self.http_port),
443 : ("127.0.0.1", self.https_port)},)
80: ("127.0.0.1", self.http_port),
443: ("127.0.0.1", self.https_port)},)
container = self._docker_client.create_container(
image_name, command, ports=[80, 443], volumes=self._temp_dir,
host_config=host_config)
@@ -30,7 +30,7 @@ tests that the plugin supports are performed.
"""
PLUGINS = {"apache" : apache24.Proxy}
PLUGINS = {"apache": apache24.Proxy}
logger = logging.getLogger(__name__)
@@ -191,7 +191,7 @@ def test_enhancements(plugin, domains):
success = True
for domain in domains:
verify = functools.partial(validator.Validator().redirect, "localhost",
plugin.http_port, headers={"Host" : domain})
plugin.http_port, headers={"Host": domain})
if not _try_until_true(verify):
logger.error("Improper redirect for domain %s", domain)
success = False
@@ -34,7 +34,7 @@ def create_le_config(parent_dir):
os.mkdir(config["work_dir"])
os.mkdir(config["logs_dir"])
return argparse.Namespace(**config) # pylint: disable=star-args
return argparse.Namespace(**config) # pylint: disable=star-args
def extract_configs(configs, parent_dir):
@@ -7,6 +7,7 @@ from pyparsing import (
from pyparsing import stringEnd
from pyparsing import restOfLine
class RawNginxParser(object):
# pylint: disable=expression-not-assigned
"""A class that parses nginx configuration with pyparsing."""
@@ -32,10 +33,10 @@ class RawNginxParser(object):
block = Forward()
block << Group(
(Group(key + location_statement) ^ Group(if_statement))
+ left_bracket
+ Group(ZeroOrMore(Group(comment | assignment) | block))
+ right_bracket)
(Group(key + location_statement) ^ Group(if_statement)) +
left_bracket +
Group(ZeroOrMore(Group(comment | assignment) | block)) +
right_bracket)
script = OneOrMore(Group(comment | assignment) ^ block) + stringEnd
@@ -41,7 +41,6 @@ class DvsniPerformTest(util.NginxTest):
domain="www.example.org", account_key=account_key),
]
def setUp(self):
super(DvsniPerformTest, self).setUp()
+1 -1
View File
@@ -18,7 +18,7 @@ setup(
entry_points={
'letsencrypt.plugins': [
'nginx = letsencrypt_nginx.configurator:NginxConfigurator',
],
],
},
include_package_data=True,
)
+9 -8
View File
@@ -244,7 +244,7 @@ class AuthHandler(object):
"""
for authzr_challb in authzr.body.challenges:
if type(authzr_challb.chall) is type(achall.challb.chall):
if type(authzr_challb.chall) is type(achall.challb.chall): # noqa
return authzr_challb
raise errors.AuthorizationError(
"Target challenge not found in authorization resource")
@@ -493,26 +493,27 @@ _ERROR_HELP_COMMON = (
_ERROR_HELP = {
"connection" :
"connection":
_ERROR_HELP_COMMON + " Additionally, please check that your computer "
"has publicly routable IP address and no firewalls are preventing the "
"server from communicating with the client.",
"dnssec" :
"dnssec":
_ERROR_HELP_COMMON + " Additionally, if you have DNSSEC enabled for "
"your domain, please ensure the signature is valid.",
"malformed" :
"malformed":
"To fix these errors, please make sure that you did not provide any "
"invalid information to the client and try running Let's Encrypt "
"again.",
"serverInternal" :
"serverInternal":
"Unfortunately, an error on the ACME server prevented you from completing "
"authorization. Please try again later.",
"tls" :
"tls":
_ERROR_HELP_COMMON + " Additionally, please check that you have an up "
"to date TLS configuration that allows the server to communicate with "
"the Let's Encrypt client.",
"unauthorized" : _ERROR_HELP_COMMON,
"unknownHost" : _ERROR_HELP_COMMON,}
"unauthorized": _ERROR_HELP_COMMON,
"unknownHost": _ERROR_HELP_COMMON,
}
def _report_failed_challs(failed_achalls):
+6 -4
View File
@@ -73,7 +73,7 @@ Choice of server for authentication/installation:
More detailed help:
-h, --help [topic] print this message, or detailed help on a topic;
-h, --help [topic] print this message, or detailed help on a topic;
the available topics are:
all, apache, automation, nginx, paths, security, testing, or any of the
@@ -342,6 +342,7 @@ class SilentParser(object): # pylint: disable=too-few-public-methods
"""
def __init__(self, parser):
self.parser = parser
def add_argument(self, *args, **kwargs):
"""Wrap, but silence help"""
kwargs["help"] = argparse.SUPPRESS
@@ -370,14 +371,14 @@ class HelpfulArgumentParser(object):
default_config_files=flag_default("config_files"))
# This is the only way to turn off overly verbose config flag documentation
self.parser._add_config_file_help = False # pylint: disable=protected-access
self.parser._add_config_file_help = False # pylint: disable=protected-access
self.silent_parser = SilentParser(self.parser)
help1 = self.prescan_for_flag("-h", self.help_topics)
help2 = self.prescan_for_flag("--help", self.help_topics)
assert max(True, "a") == "a", "Gravity changed direction"
help_arg = max(help1, help2)
if help_arg == True:
if help_arg:
# just --help with no topic; avoid argparse altogether
print USAGE
sys.exit(0)
@@ -554,6 +555,7 @@ def create_parser(plugins, args):
def _create_subparsers(helpful):
subparsers = helpful.parser.add_subparsers(metavar="SUBCOMMAND")
def add_subparser(name, func): # pylint: disable=missing-docstring
subparser = subparsers.add_parser(
name, help=func.__doc__.splitlines()[0], description=func.__doc__)
@@ -711,7 +713,7 @@ def _handle_exception(exc_type, exc_value, trace, args):
with open(logfile, "w") as logfd:
traceback.print_exception(
exc_type, exc_value, trace, file=logfd)
except: # pylint: disable=bare-except
except: # pylint: disable=bare-except
sys.exit("".join(
traceback.format_exception(exc_type, exc_value, trace)))
+2 -2
View File
@@ -279,8 +279,8 @@ class Client(object):
:param .RenewableCert cert: Newly issued certificate
"""
if ("autorenew" not in cert.configuration
or cert.configuration.as_bool("autorenew")):
if ("autorenew" not in cert.configuration or
cert.configuration.as_bool("autorenew")):
if ("autodeploy" not in cert.configuration or
cert.configuration.as_bool("autodeploy")):
msg = "Automatic renewal and deployment has "
+1 -1
View File
@@ -45,7 +45,7 @@ class NamespaceConfig(object):
return (parsed.netloc + parsed.path).replace('/', os.path.sep)
@property
def accounts_dir(self): #pylint: disable=missing-docstring
def accounts_dir(self): # pylint: disable=missing-docstring
return os.path.join(
self.namespace.config_dir, constants.ACCOUNTS_DIR, self.server_path)
+1
View File
@@ -205,6 +205,7 @@ def _pyopenssl_load(data, method, types=(
raise errors.Error("Unable to load: {0}".format(",".join(
str(error) for error in openssl_errors)))
def pyopenssl_load_certificate(data):
"""Load PEM/DER certificate.
+2 -2
View File
@@ -25,8 +25,8 @@ def choose_plugin(prepared, question):
:rtype: `~.PluginEntryPoint`
"""
opts = [plugin_ep.description_with_name
+ (" [Misconfigured]" if plugin_ep.misconfigured else "")
opts = [plugin_ep.description_with_name +
(" [Misconfigured]" if plugin_ep.misconfigured else "")
for plugin_ep in prepared]
while True:
+2 -2
View File
@@ -76,7 +76,7 @@ class NcursesDisplay(object):
"help_label": help_label,
"width": self.width,
"height": self.height,
"menu_height": self.height-6,
"menu_height": self.height - 6,
}
# Can accept either tuples or just the actual choices
@@ -315,7 +315,7 @@ class FileDisplay(object):
if index < 1 or index > len(tags):
return []
# Transform indices to appropriate tags
return [tags[index-1] for index in indices]
return [tags[index - 1] for index in indices]
def _print_menu(self, message, choices):
"""Print a menu on the screen.
+1
View File
@@ -73,6 +73,7 @@ class NoInstallationError(PluginError):
class MisconfigurationError(PluginError):
"""Let's Encrypt Misconfiguration error."""
class NotSupportedError(PluginError):
"""Let's Encrypt Plugin function not supported error."""
-1
View File
@@ -439,7 +439,6 @@ class IValidator(zope.interface.Interface):
"""
def hsts(name):
"""Verify HSTS header is enabled
+2
View File
@@ -196,6 +196,8 @@ def safely_remove(path):
# start with a period or have two consecutive periods <- this needs to
# be done in addition to the regex
EMAIL_REGEX = re.compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+$")
def safe_email(email):
"""Scrub email address before using it."""
if EMAIL_REGEX.match(email) is not None:
+2
View File
@@ -18,6 +18,7 @@ def option_namespace(name):
"""ArgumentParser options namespace (prefix of all options)."""
return name + "-"
def dest_namespace(name):
"""ArgumentParser dest namespace (prefix of all destinations)."""
return name.replace("-", "_") + "_"
@@ -86,6 +87,7 @@ class Plugin(object):
# other
class Addr(object):
r"""Represents an virtual host address.
+1
View File
@@ -101,6 +101,7 @@ class PluginEntryPointTest(unittest.TestCase):
with mock.patch("letsencrypt.plugins."
"disco.zope.interface") as mock_zope:
mock_zope.exceptions = exceptions
def verify_object(iface, obj): # pylint: disable=missing-docstring
assert obj is plugin
assert iface is iface1 or iface is iface2 or iface is iface3
+1 -2
View File
@@ -80,8 +80,7 @@ $(command -v python2 || command -v python2.7 || command -v python2.6) -c \\
"import BaseHTTPServer, SimpleHTTPServer; \\
SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map = {\'\': \'application/jose+json\'}; \\
s = BaseHTTPServer.HTTPServer((\'\', 4430), SimpleHTTPServer.SimpleHTTPRequestHandler); \\
s.serve_forever()"
""")
s.serve_forever()" \n""")
#self.assertTrue(validation in message)
mock_verify.return_value = False
@@ -321,10 +321,8 @@ class PerformTest(unittest.TestCase):
self.authenticator.already_listening = mock.Mock(return_value=False)
result = self.authenticator.perform(self.achalls)
self.assertEqual(len(self.authenticator.tasks), 2)
self.assertTrue(
self.authenticator.tasks.has_key(self.achall1.token))
self.assertTrue(
self.authenticator.tasks.has_key(self.achall2.token))
self.assertTrue(self.achall1.token in self.authenticator.tasks)
self.assertTrue(self.achall2.token in self.authenticator.tasks)
self.assertTrue(isinstance(result, list))
self.assertEqual(len(result), 3)
self.assertTrue(isinstance(result[0], challenges.ChallengeResponse))
@@ -340,10 +338,8 @@ class PerformTest(unittest.TestCase):
self.authenticator.already_listening = mock.Mock(return_value=False)
result = self.authenticator.perform(self.achalls)
self.assertEqual(len(self.authenticator.tasks), 2)
self.assertTrue(
self.authenticator.tasks.has_key(self.achall1.token))
self.assertTrue(
self.authenticator.tasks.has_key(self.achall2.token))
self.assertTrue(self.achall1.token in self.authenticator.tasks)
self.assertTrue(self.achall2.token in self.authenticator.tasks)
self.assertTrue(isinstance(result, list))
self.assertEqual(len(result), 3)
self.assertEqual(result, [None, None, False])
+2 -2
View File
@@ -17,7 +17,7 @@ from letsencrypt.display import util as display_util
logger = logging.getLogger(__name__)
class ProofOfPossession(object): # pylint: disable=too-few-public-methods
class ProofOfPossession(object): # pylint: disable=too-few-public-methods
"""Proof of Possession Identifier Validation Challenge.
Based on draft-barnes-acme, section 6.5.
@@ -71,7 +71,7 @@ class ProofOfPossession(object): # pylint: disable=too-few-public-methods
# If we get here, the key wasn't found
return False
def _gen_response(self, achall, key_path): # pylint: disable=no-self-use
def _gen_response(self, achall, key_path): # pylint: disable=no-self-use
"""Create the response to the Proof of Possession Challenge.
:param achall: Proof of Possession Challenge
+2 -3
View File
@@ -486,8 +486,8 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
:rtype: bool
"""
if ("autorenew" not in self.configuration
or self.configuration.as_bool("autorenew")):
if ("autorenew" not in self.configuration or
self.configuration.as_bool("autorenew")):
# Consider whether to attempt to autorenew this cert now
# Renewals on the basis of revocation
@@ -603,7 +603,6 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
new_config.write()
return cls(new_config, config, cli_config)
def save_successor(self, prior_version, new_cert, new_privkey, new_chain):
"""Save new cert and chain as a successor of a prior version.
+1 -1
View File
@@ -30,7 +30,7 @@ POP = challenges.ProofOfPossession(
"16d95b7b63f1972b980b14c20291f3c0d1855d95",
"48b46570d9fc6358108af43ad1649484def0debf"
),
certs=(), # TODO
certs=(), # TODO
subject_key_identifiers=("d0083162dcc4c8a23ecb8aecbd86120e56fd24e5"),
serial_numbers=(34234239832, 23993939911, 17),
issuers=(
+15 -11
View File
@@ -37,7 +37,7 @@ class ChallengeFactoryTest(unittest.TestCase):
self.dom = "test"
self.handler.authzr[self.dom] = acme_util.gen_authzr(
messages.STATUS_PENDING, self.dom, acme_util.CHALLENGES,
[messages.STATUS_PENDING]*6, False)
[messages.STATUS_PENDING] * 6, False)
def test_all(self):
cont_c, dv_c = self.handler._challenge_factory(
@@ -163,7 +163,7 @@ class GetAuthorizationsTest(unittest.TestCase):
messages.STATUS_VALID,
dom,
[challb.chall for challb in azr.body.challenges],
[messages.STATUS_VALID]*len(azr.body.challenges),
[messages.STATUS_VALID] * len(azr.body.challenges),
azr.body.combinations)
@@ -183,15 +183,15 @@ class PollChallengesTest(unittest.TestCase):
self.doms = ["0", "1", "2"]
self.handler.authzr[self.doms[0]] = acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[0],
acme_util.DV_CHALLENGES, [messages.STATUS_PENDING]*3, False)
acme_util.DV_CHALLENGES, [messages.STATUS_PENDING] * 3, False)
self.handler.authzr[self.doms[1]] = acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[1],
acme_util.DV_CHALLENGES, [messages.STATUS_PENDING]*3, False)
acme_util.DV_CHALLENGES, [messages.STATUS_PENDING] * 3, False)
self.handler.authzr[self.doms[2]] = acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[2],
acme_util.DV_CHALLENGES, [messages.STATUS_PENDING]*3, False)
acme_util.DV_CHALLENGES, [messages.STATUS_PENDING] * 3, False)
self.chall_update = {}
for dom in self.doms:
@@ -282,6 +282,7 @@ class PollChallengesTest(unittest.TestCase):
)
return (new_authzr, "response")
class GenChallengePathTest(unittest.TestCase):
"""Tests for letsencrypt.auth_handler.gen_challenge_path.
@@ -321,7 +322,7 @@ class GenChallengePathTest(unittest.TestCase):
combos = acme_util.gen_combos(challbs)
self.assertEqual(self._call(challbs, prefs, combos), (0, 2))
# dumb_path() trivial test
# dumb_path() trivial test
self.assertTrue(self._call(challbs, prefs, None))
def test_full_cont_server(self):
@@ -427,26 +428,29 @@ class ReportFailedChallsTest(unittest.TestCase):
from letsencrypt import achallenges
kwargs = {
"chall" : acme_util.SIMPLE_HTTP,
"chall": acme_util.SIMPLE_HTTP,
"uri": "uri",
"status": messages.STATUS_INVALID,
"error": messages.Error(typ="tls", detail="detail"),
}
self.simple_http = achallenges.SimpleHTTP(
challb=messages.ChallengeBody(**kwargs),# pylint: disable=star-args
# pylint: disable=star-args
challb=messages.ChallengeBody(**kwargs),
domain="example.com",
account_key="key")
kwargs["chall"] = acme_util.DVSNI
self.dvsni_same = achallenges.DVSNI(
challb=messages.ChallengeBody(**kwargs),# pylint: disable=star-args
# pylint: disable=star-args
challb=messages.ChallengeBody(**kwargs),
domain="example.com",
account_key="key")
kwargs["error"] = messages.Error(typ="dnssec", detail="detail")
self.dvsni_diff = achallenges.DVSNI(
challb=messages.ChallengeBody(**kwargs),# pylint: disable=star-args
# pylint: disable=star-args
challb=messages.ChallengeBody(**kwargs),
domain="foo.bar",
account_key="key")
@@ -477,7 +481,7 @@ def gen_dom_authzr(domain, unused_new_authzr_uri, challs):
"""Generates new authzr for domains."""
return acme_util.gen_authzr(
messages.STATUS_PENDING, domain, challs,
[messages.STATUS_PENDING]*len(challs))
[messages.STATUS_PENDING] * len(challs))
if __name__ == "__main__":
+1 -1
View File
@@ -60,7 +60,7 @@ class CLITest(unittest.TestCase):
for args in itertools.chain(
*(itertools.combinations(flags, r)
for r in xrange(len(flags)))):
self._call(['plugins',] + list(args))
self._call(['plugins'] + list(args))
@mock.patch("letsencrypt.cli.sys")
def test_handle_exception(self, mock_sys):
+1 -1
View File
@@ -166,7 +166,7 @@ class RollbackTest(unittest.TestCase):
self.assertEqual(self.m_install().restart.call_count, 1)
def test_no_installer(self):
self._call(1, None) # Just make sure no exceptions are raised
self._call(1, None) # Just make sure no exceptions are raised
if __name__ == "__main__":
+1 -1
View File
@@ -35,7 +35,7 @@ class PerformTest(unittest.TestCase):
self.assertRaises(
errors.ContAuthError, self.auth.perform, [
achallenges.DVSNI(
challb=None, domain="0", account_key="invalid_key"),])
challb=None, domain="0", account_key="invalid_key")])
def test_chall_pref(self):
self.assertEqual(
+1
View File
@@ -250,6 +250,7 @@ class GenSSLLabURLs(unittest.TestCase):
self.assertTrue("eff.org" in urls[0])
self.assertTrue("umich.edu" in urls[1])
class GenHttpsNamesTest(unittest.TestCase):
"""Test _gen_https_names."""
def setUp(self):
+1 -1
View File
@@ -35,7 +35,7 @@ class NcursesDisplayTest(unittest.TestCase):
"help_label": "",
"width": display_util.WIDTH,
"height": display_util.HEIGHT,
"menu_height": display_util.HEIGHT-6,
"menu_height": display_util.HEIGHT - 6,
}
@mock.patch("letsencrypt.display.util.dialog.Dialog.msgbox")
+3 -2
View File
@@ -1,9 +1,10 @@
"""Tests for letsencrypt.notify."""
import mock
import socket
import unittest
import mock
class NotifyTests(unittest.TestCase):
"""Tests for the notifier."""
@@ -80,4 +80,4 @@ class ProofOfPossessionTest(unittest.TestCase):
if __name__ == "__main__":
unittest.main() # pragma: no cover
unittest.main() # pragma: no cover
+2 -2
View File
@@ -24,6 +24,7 @@ def unlink_all(rc_object):
for kind in ALL_FOUR:
os.unlink(getattr(rc_object, kind))
def fill_with_sample_data(rc_object):
"""Put dummy data into all four files of this RenewableCert."""
for kind in ALL_FOUR:
@@ -97,7 +98,7 @@ class RenewableCertTests(unittest.TestCase):
self.assertRaises(
errors.CertStorageError, storage.RenewableCert, config, defaults)
def test_consistent(self): # pylint: disable=too-many-statements
def test_consistent(self): # pylint: disable=too-many-statements
oldcert = self.test_rc.cert
self.test_rc.cert = "relative/path"
# Absolute path for item requirement
@@ -608,7 +609,6 @@ class RenewableCertTests(unittest.TestCase):
# This should fail because the renewal itself appears to fail
self.assertFalse(renewer.renew(self.test_rc, 1))
@mock.patch("letsencrypt.renewer.notify")
@mock.patch("letsencrypt.storage.RenewableCert")
@mock.patch("letsencrypt.renewer.renew")
+7 -6
View File
@@ -38,15 +38,15 @@ class ValidatorTest(unittest.TestCase):
@mock.patch("letsencrypt.validator.requests.get")
def test_succesful_redirect(self, mock_get_request):
mock_get_request.return_value = create_response(
301, {"location" : "https://test.com"})
301, {"location": "https://test.com"})
self.assertTrue(self.validator.redirect("test.com"))
@mock.patch("letsencrypt.validator.requests.get")
def test_redirect_with_headers(self, mock_get_request):
mock_get_request.return_value = create_response(
301, {"location" : "https://test.com"})
301, {"location": "https://test.com"})
self.assertTrue(self.validator.redirect(
"test.com", headers={"Host" : "test.com"}))
"test.com", headers={"Host": "test.com"}))
@mock.patch("letsencrypt.validator.requests.get")
def test_redirect_missing_location(self, mock_get_request):
@@ -56,13 +56,13 @@ class ValidatorTest(unittest.TestCase):
@mock.patch("letsencrypt.validator.requests.get")
def test_redirect_wrong_status_code(self, mock_get_request):
mock_get_request.return_value = create_response(
201, {"location" : "https://test.com"})
201, {"location": "https://test.com"})
self.assertFalse(self.validator.redirect("test.com"))
@mock.patch("letsencrypt.validator.requests.get")
def test_redirect_wrong_redirect_code(self, mock_get_request):
mock_get_request.return_value = create_response(
303, {"location" : "https://test.com"})
303, {"location": "https://test.com"})
self.assertFalse(self.validator.redirect("test.com"))
@mock.patch("letsencrypt.validator.requests.get")
@@ -106,6 +106,7 @@ class ValidatorTest(unittest.TestCase):
self.assertRaises(
NotImplementedError, self.validator.ocsp_stapling, "test.com")
def create_response(status_code=200, headers=None):
"""Creates a requests.Response object for testing"""
response = requests.Response()
@@ -118,4 +119,4 @@ def create_response(status_code=200, headers=None):
if __name__ == '__main__':
unittest.main() # pragma: no cover
unittest.main() # pragma: no cover
@@ -87,7 +87,7 @@ def copy_config(server_root, temp_dir):
dir_len = len(os.path.dirname(server_root))
for config_path, config_dirs, config_files in os.walk(server_root):
temp_path = os.path.join(temp_dir, config_path[dir_len+1:])
temp_path = os.path.join(temp_dir, config_path[dir_len + 1:])
os.mkdir(temp_path)
copied_all = True
@@ -151,7 +151,7 @@ def safe_config_file(config_file):
empty_or_all_comments = False
if line.startswith("-----BEGIN"):
return False
elif not ":" in line:
elif ":" 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
@@ -234,9 +234,9 @@ def locate_config(apache_ctl):
for line in output.splitlines():
# Relevant output lines are of the form: -D DIRECTIVE="VALUE"
if "HTTPD_ROOT" in line:
server_root = line[line.find('"')+1:-1]
server_root = line[line.find('"') + 1:-1]
elif "SERVER_CONFIG_FILE" in line:
config_file = line[line.find('"')+1:-1]
config_file = line[line.find('"') + 1:-1]
if not (server_root and config_file):
sys.exit("Unable to locate Apache configuration. Please run this "
@@ -272,7 +272,7 @@ def get_args():
args.config_file = os.path.abspath(args.config_file)
if args.config_file.startswith(args.server_root):
args.config_file = args.config_file[len(args.server_root)+1:]
args.config_file = args.config_file[len(args.server_root) + 1:]
else:
sys.exit("This script expects the Apache configuration file to be "
"inside the server root")
@@ -300,4 +300,4 @@ def main():
if __name__ == "__main__":
main() # pragma: no cover
main() # pragma: no cover
@@ -141,7 +141,7 @@ class LetsHelpApacheTest(unittest.TestCase):
@mock.patch(_MODULE_NAME + ".subprocess.Popen")
def test_locate_config(self, mock_popen):
mock_popen().communicate.side_effect = [
OSError, ("bad_output", None), (_COMPILE_SETTINGS, None),]
OSError, ("bad_output", None), (_COMPILE_SETTINGS, None)]
self.assertRaises(
SystemExit, letshelp_le_apache.locate_config, "ctl")
Executable
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
pep8 \
setup.py \
acme \
letsencrypt \
letsencrypt-apache \
letsencrypt-nginx \
letsencrypt-compatibility-test \
letshelp-letsencrypt \
|| echo "PEP8 checking failed, but it's ignored in Travis"
# echo exits with 0
+1
View File
@@ -68,6 +68,7 @@ testing_extras = [
'coverage',
'nose',
'nosexcover',
'pep8',
'tox',
]
+1
View File
@@ -47,6 +47,7 @@ basepython = python2.7
# continue, but tox return code will reflect previous error
commands =
pip install -r requirements.txt -e acme -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt
./pep8.travis.sh
pylint --rcfile=.pylintrc letsencrypt
pylint --rcfile=.pylintrc acme/acme
pylint --rcfile=.pylintrc letsencrypt-apache/letsencrypt_apache