Merge pull request #186 from kuba/pylint

Pylint 10/10
This commit is contained in:
James Kasten 2015-01-24 19:17:57 -08:00
commit ca0ea80192
26 changed files with 187 additions and 182 deletions

View file

@ -38,7 +38,7 @@ load-plugins=
# --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=
disable=fixme,locally-disabled
[REPORTS]
@ -81,7 +81,7 @@ required-attributes=
bad-functions=map,filter,apply,input,file
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
good-names=i,j,k,ex,Run,_,fd
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
@ -94,10 +94,10 @@ name-group=
include-naming-hint=no
# Regular expression matching correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
function-rgx=[a-z_][a-z0-9_]{2,40}$
# Naming hint for function names
function-name-hint=[a-z_][a-z0-9_]{2,30}$
function-name-hint=[a-z_][a-z0-9_]{2,40}$
# Regular expression matching correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
@ -148,14 +148,14 @@ module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
method-rgx=[a-z_][a-z0-9_]{2,40}$
# Naming hint for method names
method-name-hint=[a-z_][a-z0-9_]{2,30}$
method-name-hint=[a-z_][a-z0-9_]{2,40}$
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=(__.*__)|(test_[A-Za-z0-9_]*)|(_.*)
no-docstring-rgx=(__.*__)|(test_[A-Za-z0-9_]*)|(_.*)|(.*Test$)
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
@ -182,7 +182,7 @@ init-import=no
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_$|dummy
dummy-variables-rgx=(unused)?_.*|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
@ -278,8 +278,8 @@ int-import-graph=
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# instance to not check methods defined in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by,implementedBy,providedBy
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp

View file

@ -77,7 +77,7 @@ In order to generate the sphinx documentation, run the following commands.
```
./venv/bin/python setup.py docs
cd docs
make html SPHINXBUILD='../venv/bin/python ../venv/bin/sphinx-build'
make clean html SPHINXBUILD=../venv/bin/sphinx-build
```
This should generate documentation in the /lets-encrypt-preview/docs/_build/html

0
docs/_static/.gitignore vendored Normal file
View file

View file

@ -1,5 +1,5 @@
:mod:`letsencrypt.client.auth_handler`
--------------------------------
--------------------------------------
.. automodule:: letsencrypt.client.auth_handler
:members:

View file

@ -1,5 +1,5 @@
:mod:`letsencrypt.client.client_authenticator`
--------------------------------
----------------------------------------------
.. automodule:: letsencrypt.client.client_authenticator
:members:

View file

@ -427,7 +427,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
"based virtual host", addr)
self.add_name_vhost(addr)
def make_vhost_ssl(self, nonssl_vhost):
def make_vhost_ssl(self, nonssl_vhost): # pylint: disable=too-many-locals
"""Makes an ssl_vhost version of a nonssl_vhost.
Duplicates vhost and adds default ssl options
@ -523,7 +523,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
return ssl_vhost
def supported_enhancements():
def supported_enhancements(self): # pylint: disable=no-self-use
"""Returns currently supported enhancements."""
return ["redirect"]
@ -532,7 +532,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
:param str domain: domain to enhance
:param str enhancement: enhancement type defined in
:class:`letsencrypt.client.CONFIG.ENHANCEMENTS
:class:`letsencrypt.client.CONFIG.ENHANCEMENTS`
:param options: options for the enhancement
:type options: See :class:`letsencrypt.client.CONFIG.ENHANCEMENTS`
documentation for appropriate parameter.
@ -547,7 +547,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
except errors.LetsEncryptConfiguratorError:
logging.warn("Failed %s for %s", enhancement, domain)
def _enable_redirect(self, ssl_vhost, options):
def _enable_redirect(self, ssl_vhost, unused_options):
"""Redirect all equivalent HTTP traffic to ssl_vhost.
.. todo:: This enhancement should be rewritten and will unfortunately
@ -562,8 +562,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
:param ssl_vhost: Destination of traffic, an ssl enabled vhost
:type ssl_vhost: :class:`letsencrypt.client.apache.obj.VirtualHost`
:param options: Not currently used
:type options: Not Available
:param unused_options: Not currently used
:type unused_options: Not Available
:returns: Success, general_vhost (HTTP vhost)
:rtype: (bool, :class:`letsencrypt.client.apache.obj.VirtualHost`)
@ -889,7 +889,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
"""
return apache_restart()
def config_test(self):
def config_test(self): # pylint: disable=no-self-use
"""Check the configuration of Apache for errors.
:returns: Success
@ -979,7 +979,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
fulfilled by configurator.
:returns: list of responses. All responses are returned in the same
order as received by the perform function. A None response
order as received by the perform function. A None response
indicates the challenge was not perfromed.
:rtype: list

View file

@ -17,7 +17,7 @@ class ApacheDvsni(object):
:ivar dvsni_chall: Data required for challenges.
where DvsniChall tuples have the following fields
`domain` (`str`), `r_b64` (base64 `str`), `nonce` (hex `str`)
`key` (:class:`letsencrypt.client.client.Client.Key`)
`key` (:class:`letsencrypt.client.client.Client.Key`)
:type dvsni_chall: `list` of
:class:`letsencrypt.client.challenge_util.DvsniChall`

View file

@ -2,7 +2,7 @@
class Addr(object):
"""Represents an Apache VirtualHost address.
r"""Represents an Apache VirtualHost address.
:param str addr: addr part of vhost address
:param str port: port number or \*, or ""
@ -58,7 +58,7 @@ class VirtualHost(object):
"""
def __init__(self, filep, path, addrs, ssl, enabled, names=None):
def __init__(self, filep, path, addrs, ssl, enabled, names=None): # pylint: disable=too-many-arguments
"""Initialize a VH."""
self.filep = filep
self.path = path

View file

@ -8,7 +8,7 @@ from letsencrypt.client import challenge_util
from letsencrypt.client import errors
class AuthHandler(object):
class AuthHandler(object): # pylint: disable=too-many-instance-attributes
"""ACME Authorization Handler for a client.
:ivar dv_auth: Authenticator capable of solving CONFIG.DV_CHALLENGES
@ -286,7 +286,7 @@ class AuthHandler(object):
raise errors.LetsEncryptClientError(
"Unimplemented Auth Challenge: %s" % chall["type"])
def _construct_client_chall(self, chall, domain):
def _construct_client_chall(self, chall, domain): # pylint: disable=no-self-use
"""Construct Client Type Challenges.
:param dict chall: Single challenge

View file

@ -342,7 +342,8 @@ def init_key(key_size):
key_pem = crypto_util.make_key(key_size)
except ValueError as err:
logging.fatal(str(err))
logging.info("Note: The default RSA key size is %d bits.", CONFIG.RSA_KEY_SIZE)
logging.info("Note: The default RSA key size is %d bits.",
CONFIG.RSA_KEY_SIZE)
sys.exit(1)
# Save file

View file

@ -238,7 +238,7 @@ def get_cert_info(filename):
try:
san = cert.get_ext("subjectAltName").get_value()
except:
except LookupError:
san = ""
return {
@ -255,5 +255,6 @@ def get_cert_info(filename):
def b64_cert_to_pem(b64_der_cert):
"""Convert JOSE Base-64 encoded DER cert to PEM."""
return M2Crypto.X509.load_cert_der_string(
le_util.jose_b64decode(b64_der_cert)).as_pem()

View file

@ -1,3 +1,4 @@
"""Lets Encrypt display."""
import textwrap
import dialog
@ -10,10 +11,10 @@ WIDTH = 72
HEIGHT = 20
class CommonDisplayMixin(object):
"""methods common to both NcursesDisplay and FileDisplay"""
class CommonDisplayMixin(object): # pylint: disable=too-few-public-methods
"""Mixin with methods common to classes implementing IDisplay."""
def redirect_by_default(self):
def redirect_by_default(self): # pylint: disable=missing-docstring
choices = [
("Easy", "Allow both HTTP and HTTPS access to these sites"),
("Secure", "Make all requests redirect to secure HTTPS access")]
@ -30,6 +31,8 @@ class CommonDisplayMixin(object):
class NcursesDisplay(CommonDisplayMixin):
"""Ncurses-based display."""
zope.interface.implements(interfaces.IDisplay)
def __init__(self, width=WIDTH, height=HEIGHT):
@ -38,10 +41,10 @@ class NcursesDisplay(CommonDisplayMixin):
self.width = width
self.height = height
def generic_notification(self, message):
def generic_notification(self, message): # pylint: disable=missing-docstring
self.dialog.msgbox(message, width=self.width)
def generic_menu(self, message, choices, input_text=""):
def generic_menu(self, message, choices, unused_input_text=""): # pylint: disable=missing-docstring
# Can accept either tuples or just the actual choices
if choices and isinstance(choices[0], tuple):
code, selection = self.dialog.menu(
@ -54,26 +57,27 @@ class NcursesDisplay(CommonDisplayMixin):
return code(int(tag) - 1)
def generic_input(self, message):
def generic_input(self, message): # pylint: disable=missing-docstring
return self.dialog.inputbox(message)
def generic_yesno(self, message, yes="Yes", no="No"):
def generic_yesno(self, message, yes_label="Yes", no_label="No"): # pylint: disable=missing-docstring
return self.dialog.DIALOG_OK == self.dialog.yesno(
message, self.height, self.width, yes_label=yes, no_label=no)
message, self.height, self.width,
yes_label=yes_label, no_label=no_label)
def filter_names(self, names):
def filter_names(self, names): # pylint: disable=missing-docstring
choices = [(n, "", 0) for n in names]
code, names = self.dialog.checklist(
"Which names would you like to activate HTTPS for?",
choices=choices)
return code, [str(s) for s in names]
def success_installation(self, domains):
def success_installation(self, domains): # pylint: disable=missing-docstring
self.dialog.msgbox(
"\nCongratulations! You have successfully enabled "
+ gen_https_names(domains) + "!", width=self.width)
def display_certs(self, certs):
def display_certs(self, certs): # pylint: disable=missing-docstring
list_choices = [
(str(i+1), "%s | %s | %s" %
(str(c["cn"].ljust(self.width - 39)),
@ -90,7 +94,7 @@ class NcursesDisplay(CommonDisplayMixin):
tag = -1
return code, (int(tag) - 1)
def confirm_revocation(self, cert):
def confirm_revocation(self, cert): # pylint: disable=missing-docstring
text = ("Are you sure you would like to revoke the following "
"certificate:\n")
text += cert_info_frame(cert)
@ -98,7 +102,7 @@ class NcursesDisplay(CommonDisplayMixin):
return self.dialog.DIALOG_OK == self.dialog.yesno(
text, width=self.width, height=self.height)
def more_info_cert(self, cert):
def more_info_cert(self, cert): # pylint: disable=missing-docstring
text = "Certificate Information:\n"
text += cert_info_frame(cert)
print text
@ -106,20 +110,21 @@ class NcursesDisplay(CommonDisplayMixin):
class FileDisplay(CommonDisplayMixin):
"""File-based display."""
zope.interface.implements(interfaces.IDisplay)
def __init__(self, outfile):
super(FileDisplay, self).__init__()
self.outfile = outfile
def generic_notification(self, message):
def generic_notification(self, message): # pylint: disable=missing-docstring
side_frame = '-' * 79
wm = textwrap.fill(message, 80)
text = "\n%s\n%s\n%s\n" % (side_frame, wm, side_frame)
self.outfile.write(text)
msg = textwrap.fill(message, 80)
self.outfile.write("\n%s\n%s\n%s\n" % (side_frame, msg, side_frame))
raw_input("Press Enter to Continue")
def generic_menu(self, message, choices, input_text=""):
def generic_menu(self, message, choices, input_text=""): # pylint: disable=missing-docstring
# Can take either tuples or single items in choices list
if choices and isinstance(choices[0], tuple):
choices = ["%s - %s" % (c[0], c[1]) for c in choices]
@ -139,7 +144,7 @@ class FileDisplay(CommonDisplayMixin):
return code, (selection - 1)
def generic_input(self, message):
def generic_input(self, message): # pylint: disable=no-self-use,missing-docstring
ans = raw_input("%s (Enter c to cancel)\n" % message)
if ans.startswith('c') or ans.startswith('C'):
@ -147,12 +152,12 @@ class FileDisplay(CommonDisplayMixin):
else:
return OK, ans
def generic_yesno(self, message, yes_label="Yes", no_label="No"):
def generic_yesno(self, message, unused_yes_label="", unused_no_label=""): # pylint: disable=missing-docstring
self.outfile.write("\n%s\n" % textwrap.fill(message, 80))
ans = raw_input("y/n: ")
return ans.startswith('y') or ans.startswith('Y')
def filter_names(self, names):
def filter_names(self, names): # pylint: disable=missing-docstring
code, tag = self.generic_menu(
"Choose the names would you like to upgrade to HTTPS?",
names, "Select the number of the name: ")
@ -160,7 +165,7 @@ class FileDisplay(CommonDisplayMixin):
# Make sure to return a list...
return code, [names[tag]]
def display_certs(self, certs):
def display_certs(self, certs): # pylint: disable=missing-docstring
menu_choices = [(str(i+1), str(c["cn"]) + " - " + c["pub_key"] +
" - " + str(c["not_before"])[:-6])
for i, c in enumerate(certs)]
@ -197,14 +202,13 @@ class FileDisplay(CommonDisplayMixin):
return code, selection
def success_installation(self, domains):
s_f = '*' * 79
wm = textwrap.fill(("Congratulations! You have successfully " +
"enabled %s!") % gen_https_names(domains))
msg = "%s\n%s\n%s\n"
self.outfile.write(msg % (s_f, wm, s_f))
def success_installation(self, domains): # pylint: disable=missing-docstring
side_frame = '*' * 79
msg = textwrap.fill("Congratulations! You have successfully "
"enabled %s!" % gen_https_names(domains))
self.outfile.write("%s\n%s\n%s\n" % (side_frame, msg, side_frame))
def confirm_revocation(self, cert):
def confirm_revocation(self, cert): # pylint: disable=missing-docstring
self.outfile.write("Are you sure you would like to revoke "
"the following certificate:\n")
self.outfile.write(cert_info_frame(cert))
@ -212,7 +216,7 @@ class FileDisplay(CommonDisplayMixin):
ans = raw_input("y/n")
return ans.startswith('y') or ans.startswith('Y')
def more_info_cert(self, cert):
def more_info_cert(self, cert): # pylint: disable=missing-docstring
self.outfile.write("\nCertificate Information:\n")
self.outfile.write(cert_info_frame(cert))
@ -221,14 +225,14 @@ CANCEL = "cancel"
HELP = "help"
def cert_info_frame(cert):
def cert_info_frame(cert): # pylint: disable=missing-docstring
text = "-" * (WIDTH - 4) + "\n"
text += cert_info_string(cert)
text += "-" * (WIDTH - 4)
return text
def cert_info_string(cert):
def cert_info_string(cert): # pylint: disable=missing-docstring
text = "Subject: %s\n" % cert["subject"]
text += "SAN: %s\n" % cert["san"]
text += "Issuer: %s\n" % cert["issuer"]

View file

@ -1,3 +1,4 @@
"""Interactive challenge."""
import textwrap
import dialog
@ -23,7 +24,7 @@ class InteractiveChallenge(object):
super(InteractiveChallenge, self).__init__()
self.string = string
def perform(self, quiet=True):
def perform(self, quiet=True): # pylint: disable=missing-docstring
if quiet:
dialog.Dialog().msgbox(
self.get_display_string(), width=self.BOX_SIZE)
@ -33,7 +34,7 @@ class InteractiveChallenge(object):
return True
def get_display_string(self):
def get_display_string(self): # pylint: disable=missing-docstring
return (textwrap.fill(self.string, width=self.BOX_SIZE) +
"\n\nPlease Press Enter to Continue")

View file

@ -30,8 +30,8 @@ class RecoveryContact(object):
self.contact = contact
self.poll_delay = poll_delay
def perform(self, quiet=True):
d = dialog.Dialog()
def perform(self, quiet=True): # pylint: disable=missing-docstring
d = dialog.Dialog() # pylint: disable=invalid-name
if quiet:
if self.success_url:
d.infobox(self.get_display_string())
@ -50,7 +50,7 @@ class RecoveryContact(object):
return True
def cleanup(self):
def cleanup(self): # pylint: disable=no-self-use,missing-docstring
return
def get_display_string(self):
@ -91,7 +91,7 @@ class RecoveryContact(object):
else:
return False
def prompt_continue(self, quiet=True):
def prompt_continue(self, quiet=True): # pylint: disable=no-self-use
"""Prompt user for continuation.
:param bool quiet: Display dialog box if True, raw prompt otherwise.
@ -109,7 +109,7 @@ class RecoveryContact(object):
return ans.startswith('y') or ans.startswith('Y')
def generate_response(self):
def generate_response(self): # pylint: disable=missing-docstring
if not self.token:
return {"type": "recoveryContact"}
return {

View file

@ -61,7 +61,7 @@ class Revoker(object):
try:
c_sha1_vh[M2Crypto.X509.load_cert(
cert).get_fingerprint(md='sha1')] = path
except:
except M2Crypto.X509.X509Error:
continue
with open(list_file, 'rb') as csvfile:

View file

@ -45,7 +45,8 @@ class ACMEObjectValidateTest(unittest.TestCase):
class PrettyTest(unittest.TestCase):
"""Tests for letsencrypt.client.acme.pretty."""
def _call(self, json_string):
@classmethod
def _call(cls, json_string):
from letsencrypt.client.acme import pretty
return pretty(json_string)
@ -64,31 +65,19 @@ class MessageFactoriesTest(unittest.TestCase):
self.nonce = '\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9'
self.b64nonce = '7Nbyb1lI6xPVI3Hg3aKSqQ'
def _validate(self, msg):
@classmethod
def _validate(cls, msg):
from letsencrypt.client.acme import SCHEMATA
jsonschema.validate(msg, SCHEMATA[msg['type']])
def _signature(self, sig):
return {
'nonce': self.b64nonce,
'alg': 'RS256',
'jwk': {
'kty': 'RSA',
'e': 'AQAB',
'n': 'rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp5'
'80rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q',
},
'sig': sig,
}
def test_challenge_request(self):
from letsencrypt.client.acme import challenge_request
msg = challenge_request('example.com')
self._validate(msg)
self.assertEqual(msg, {
'type': 'challengeRequest',
'identifier': 'example.com',
})
self._validate(msg)
def test_authorization_request(self):
from letsencrypt.client.acme import authorization_request
@ -112,51 +101,57 @@ class MessageFactoriesTest(unittest.TestCase):
self.nonce,
)
self._validate(msg)
self.assertEqual(
msg.pop('signature')['sig'],
'VkpReso87ogwGul2MGck96TkYs4QoblIgNthgrm9O7EBGlzCRCnTHnx'
'bj6loqaC4f5bn1rgS927Gp1Kvbqnmqg'
)
self.assertEqual(msg, {
'type': 'authorizationRequest',
'sessionID': 'aefoGaavieG9Wihuk2aufai3aeZ5EeW4',
'nonce': 'czpsrF0KMH6dgajig3TGHw',
'signature': self._signature(
'VkpReso87ogwGul2MGck96TkYs4QoblIgNthgrm9O7EBGlzCRCnTHnx'
'bj6loqaC4f5bn1rgS927Gp1Kvbqnmqg'),
'responses': responses,
})
self._validate(msg)
def test_certificate_request(self):
from letsencrypt.client.acme import certificate_request
msg = certificate_request(
'TODO: real DER CSR?', self.privkey, self.nonce)
self._validate(msg)
self.assertEqual(
msg.pop('signature')['sig'],
'HEQVN4MU1yDrArP2T7WZQ12XlHCn5DgTPgb5eWT5_vjRPppLSNe6uWE'
'x9SFwG9d9umqn49nZCSW7uskA2lcW6Q'
)
self.assertEqual(msg, {
'type': 'certificateRequest',
'csr': 'VE9ETzogcmVhbCBERVIgQ1NSPw',
'signature': self._signature(
'HEQVN4MU1yDrArP2T7WZQ12XlHCn5DgTPgb5eWT5_vjRPppLSNe6uWE'
'x9SFwG9d9umqn49nZCSW7uskA2lcW6Q'),
})
self._validate(msg)
def test_revocation_request(self):
from letsencrypt.client.acme import revocation_request
msg = revocation_request(
'TODO: real DER cert?', self.privkey, self.nonce)
self._validate(msg)
self.assertEqual(
msg.pop('signature')['sig'],
'ABXA1IsyTalTXIojxmGnIUGyZASmvqEvTQ98jJ5KFs2FTswLEmsoqFX'
'fU6l5_fous-tsbXOfLN-7PjfZ5XWPvg'
)
self.assertEqual(msg, {
'type': 'revocationRequest',
'certificate': 'VE9ETzogcmVhbCBERVIgY2VydD8',
'signature': self._signature(
'ABXA1IsyTalTXIojxmGnIUGyZASmvqEvTQ98jJ5KFs2FTswLEmsoqFX'
'fU6l5_fous-tsbXOfLN-7PjfZ5XWPvg'),
})
self._validate(msg)
def test_status_request(self):
from letsencrypt.client.acme import status_request
msg = status_request(u'O7-s9MNq1siZHlgrMzi9_A')
self._validate(msg)
self.assertEqual(msg, {
'type': 'statusRequest',
'token': u'O7-s9MNq1siZHlgrMzi9_A',
})
self._validate(msg)
if __name__ == '__main__':

View file

@ -1,6 +1,5 @@
"""Test for letsencrypt.client.apache.configurator."""
import os
import pkg_resources
import re
import shutil
import unittest
@ -15,26 +14,19 @@ from letsencrypt.client.apache import configurator
from letsencrypt.client.apache import obj
from letsencrypt.client.apache import parser
from letsencrypt.client.tests.apache import config_util
from letsencrypt.client.tests.apache import util
class TwoVhost80Test(unittest.TestCase):
class TwoVhost80Test(util.ApacheTest):
"""Test two standard well configured HTTP vhosts."""
def setUp(self):
self.temp_dir, self.config_dir, self.work_dir = config_util.dir_setup(
"debian_apache_2_4/two_vhost_80")
super(TwoVhost80Test, self).setUp()
self.ssl_options = config_util.setup_apache_ssl_options(self.config_dir)
# Final slash is currently important
self.config_path = os.path.join(
self.temp_dir, "debian_apache_2_4/two_vhost_80/apache2/")
self.config = config_util.get_apache_configurator(
self.config = util.get_apache_configurator(
self.config_path, self.config_dir, self.work_dir, self.ssl_options)
self.vh_truth = config_util.get_vh_truth(
self.vh_truth = util.get_vh_truth(
self.temp_dir, "debian_apache_2_4/two_vhost_80")
def tearDown(self):
@ -168,12 +160,7 @@ class TwoVhost80Test(unittest.TestCase):
def test_perform(self, mock_restart, mock_dvsni_perform):
# Only tests functionality specific to configurator.perform
# Note: As more challenges are offered this will have to be expanded
rsa256_file = pkg_resources.resource_filename(
"letsencrypt.client.tests", 'testdata/rsa256_key.pem')
rsa256_pem = pkg_resources.resource_string(
"letsencrypt.client.tests", 'testdata/rsa256_key.pem')
auth_key = client.Client.Key(rsa256_file, rsa256_pem)
auth_key = client.Client.Key(self.rsa256_file, self.rsa256_pem)
chall1 = challenge_util.DvsniChall(
"encryption-example.demo",
"jIq_Xy1mXGN37tb4L6Xj_es58fW571ZNyXekdZzhh7Q",

View file

@ -1,5 +1,4 @@
"""Test for letsencrypt.client.apache.dvsni."""
import os
import pkg_resources
import unittest
import shutil
@ -10,26 +9,19 @@ from letsencrypt.client import challenge_util
from letsencrypt.client import client
from letsencrypt.client import CONFIG
from letsencrypt.client.tests.apache import config_util
from letsencrypt.client.tests.apache import util
class DvsniPerformTest(unittest.TestCase):
class DvsniPerformTest(util.ApacheTest):
"""Test the ApacheDVSNI challenge."""
def setUp(self):
from letsencrypt.client.apache import dvsni
super(DvsniPerformTest, self).setUp()
self.temp_dir, self.config_dir, self.work_dir = config_util.dir_setup(
"debian_apache_2_4/two_vhost_80")
self.ssl_options = config_util.setup_apache_ssl_options(self.config_dir)
# Final slash is currently important
self.config_path = os.path.join(
self.temp_dir, "debian_apache_2_4/two_vhost_80/apache2/")
config = config_util.get_apache_configurator(
config = util.get_apache_configurator(
self.config_path, self.config_dir, self.work_dir, self.ssl_options)
from letsencrypt.client.apache import dvsni
self.sni = dvsni.ApacheDvsni(config)
rsa256_file = pkg_resources.resource_filename(
@ -144,3 +136,7 @@ class DvsniPerformTest(unittest.TestCase):
self.assertEqual(
vhost.names,
set([str(self.challs[1].nonce + CONFIG.INVALID_EXT)]))
if __name__ == '__main__':
unittest.main()

View file

@ -11,23 +11,18 @@ import zope.component
from letsencrypt.client import display
from letsencrypt.client import errors
from letsencrypt.client.apache import parser
from letsencrypt.client.tests.apache import config_util
from letsencrypt.client.tests.apache import util
class ApacheParserTest(unittest.TestCase):
class ApacheParserTest(util.ApacheTest):
"""Apache Parser Test."""
def setUp(self):
super(ApacheParserTest, self).setUp()
zope.component.provideUtility(display.FileDisplay(sys.stdout))
self.temp_dir, self.config_dir, self.work_dir = config_util.dir_setup(
"debian_apache_2_4/two_vhost_80")
self.ssl_options = config_util.setup_apache_ssl_options(self.config_dir)
# Final slash is currently important
self.config_path = os.path.join(
self.temp_dir, "debian_apache_2_4/two_vhost_80/apache2/")
self.parser = parser.ApacheParser(
augeas.Augeas(flags=augeas.Augeas.NONE),
self.config_path, self.ssl_options)
@ -112,3 +107,7 @@ class ApacheParserTest(unittest.TestCase):
self.assertEqual(results["default"], results["listen"])
self.assertEqual(results["default"], results["name"])
if __name__ == '__main__':
unittest.main()

View file

@ -1,7 +1,9 @@
"""Common utilities for letsencrypt.client.apache."""
import os
import pkg_resources
import shutil
import tempfile
import unittest
import mock
@ -10,6 +12,26 @@ from letsencrypt.client.apache import configurator
from letsencrypt.client.apache import obj
class ApacheTest(unittest.TestCase):
def setUp(self):
super(ApacheTest, self).setUp()
self.temp_dir, self.config_dir, self.work_dir = dir_setup(
"debian_apache_2_4/two_vhost_80")
self.ssl_options = setup_apache_ssl_options(self.config_dir)
# Final slash is currently important
self.config_path = os.path.join(
self.temp_dir, "debian_apache_2_4/two_vhost_80/apache2/")
self.rsa256_file = pkg_resources.resource_filename(
"letsencrypt.client.tests", 'testdata/rsa256_key.pem')
self.rsa256_pem = pkg_resources.resource_string(
"letsencrypt.client.tests", 'testdata/rsa256_key.pem')
def dir_setup(test_dir="debian_apache_2_4/two_vhost_80"):
"""Setup the directories necessary for the configurator."""
temp_dir = tempfile.mkdtemp("temp")

View file

@ -1,21 +1,26 @@
"""Test auth_handler.py."""
"""Tests for letsencrypt.client.auth_handler."""
import unittest
import mock
from letsencrypt.client import errors
from letsencrypt.client.tests import acme_util
TRANSLATE = {"dvsni": "DvsniChall",
"simpleHttps": "SimpleHttpsChall",
"dns": "DnsChall",
"recoveryToken": "RecTokenChall",
"recoveryContact": "RecContactChall",
"proofOfPossession": "PopChall"}
TRANSLATE = {
"dvsni": "DvsniChall",
"simpleHttps": "SimpleHttpsChall",
"dns": "DnsChall",
"recoveryToken": "RecTokenChall",
"recoveryContact": "RecContactChall",
"proofOfPossession": "PopChall",
}
# pylint: disable=protected-access
class SatisfyChallengesTest(unittest.TestCase):
"""verify_identities test."""
def setUp(self):
from letsencrypt.client.auth_handler import AuthHandler
@ -225,7 +230,7 @@ class SatisfyChallengesTest(unittest.TestCase):
self.assertEqual(
type(self.handler.client_c["4"][0].chall).__name__, "RecTokenChall")
def _get_exp_response(self, domain, path, challenges):
def _get_exp_response(self, domain, path, challenges): # pylint: disable=no-self-use
exp_resp = ["null"] * len(challenges)
for i in path:
exp_resp[i] = TRANSLATE[challenges[i]["type"]] + str(domain)
@ -283,7 +288,6 @@ class GetAuthorizationsTest(unittest.TestCase):
self.handler.dv_c[dom], self.handler.client_c[dom] = dv_c, c_c
def test_progress_failure(self):
from letsencrypt.client.errors import LetsEncryptAuthHandlerError
challenges = acme_util.get_challenges()
self.handler.add_chall_msg(
"0",
@ -294,7 +298,7 @@ class GetAuthorizationsTest(unittest.TestCase):
self.mock_sat_chall.side_effect = self._sat_failure
self.assertRaises(
LetsEncryptAuthHandlerError, self.handler.get_authorizations)
errors.LetsEncryptAuthHandlerError, self.handler.get_authorizations)
# Check to make sure program didn't loop
self.assertEqual(self.mock_sat_chall.call_count, 1)
@ -327,8 +331,6 @@ class GetAuthorizationsTest(unittest.TestCase):
[mock.call("1"), mock.call("0")])
def _sat_incremental(self):
from letsencrypt.client.errors import LetsEncryptAuthHandlerError
# Exact responses don't matter, just path/response match
if self.iteration == 0:
# Only solve one of "0" required challs
@ -353,7 +355,7 @@ class GetAuthorizationsTest(unittest.TestCase):
self.handler.responses["0"][3] = "finally!"
else:
raise LetsEncryptAuthHandlerError(
raise errors.LetsEncryptAuthHandlerError(
"Failed incremental test: too many invocations")
def _test_finished(self):
@ -408,12 +410,12 @@ class PathSatisfiedTest(unittest.TestCase):
self.assertFalse(self.handler._path_satisfied(dom[i]))
def gen_auth_resp(chall_list):
def gen_auth_resp(chall_list): # pylint: disable=missing-docstring
return ["%s%s" % (type(chall).__name__, chall.domain)
for chall in chall_list]
def gen_path(str_list, challenges):
def gen_path(str_list, challenges): # pylint: disable=missing-docstring
path = []
for i, chall in enumerate(challenges):
for str_chall in str_list:

View file

@ -30,7 +30,8 @@ class CreateSigTest(unittest.TestCase):
'AX9AFJHk-bCMQPJbSzXKjG6H1IWbvxjS2Ew',
}
def _call(self, *args, **kwargs):
@classmethod
def _call(cls, *args, **kwargs):
from letsencrypt.client.crypto_util import create_sig
return create_sig(*args, **kwargs)
@ -50,7 +51,8 @@ class CreateSigTest(unittest.TestCase):
class ValidCSRTest(unittest.TestCase):
"""Tests for letsencrypt.client.crypto_util.valid_csr."""
def _call(self, csr):
@classmethod
def _call(cls, csr):
from letsencrypt.client.crypto_util import valid_csr
return valid_csr(csr)
@ -80,7 +82,8 @@ class ValidCSRTest(unittest.TestCase):
class CSRMatchesPubkeyTest(unittest.TestCase):
"""Tests for letsencrypt.client.crypto_util.csr_matches_pubkey."""
def _call_testdata(self, name, privkey):
@classmethod
def _call_testdata(cls, name, privkey):
from letsencrypt.client.crypto_util import csr_matches_pubkey
return csr_matches_pubkey(pkg_resources.resource_string(
__name__, os.path.join('testdata', name)), privkey)
@ -95,7 +98,7 @@ class CSRMatchesPubkeyTest(unittest.TestCase):
class MakeKeyTest(unittest.TestCase):
"""Tests for letsencrypt.client.crypto_util.make_key."""
def test_it(self):
def test_it(self): # pylint: disable=no-self-use
from letsencrypt.client.crypto_util import make_key
M2Crypto.RSA.load_key_string(make_key(1024))
M2Crypto.RSA.load_key_string(make_key(2048))
@ -105,7 +108,8 @@ class MakeKeyTest(unittest.TestCase):
class ValidPrivkeyTest(unittest.TestCase):
"""Tests for letsencrypt.client.crypto_util.valid_privkey."""
def _call(self, privkey):
@classmethod
def _call(cls, privkey):
from letsencrypt.client.crypto_util import valid_privkey
return valid_privkey(privkey)
@ -122,7 +126,7 @@ class ValidPrivkeyTest(unittest.TestCase):
class MakeSSCertTest(unittest.TestCase):
"""Tests for letsencrypt.client.crypto_util.make_ss_cert."""
def test_it(self):
def test_it(self): # pylint: disable=no-self-use
from letsencrypt.client.crypto_util import make_ss_cert
make_ss_cert(RSA256_KEY, ['example.com', 'www.example.com'])

View file

@ -141,7 +141,8 @@ B64_URL_UNSAFE_EXAMPLES = {
class JOSEB64EncodeTest(unittest.TestCase):
"""Tests for letsencrypt.client.le_util.jose_b64encode."""
def _call(self, data):
@classmethod
def _call(cls, data):
from letsencrypt.client.le_util import jose_b64encode
return jose_b64encode(data)
@ -160,7 +161,8 @@ class JOSEB64EncodeTest(unittest.TestCase):
class JOSEB64DecodeTest(unittest.TestCase):
"""Tests for letsencrypt.client.le_util.jose_b64decode."""
def _call(self, data):
@classmethod
def _call(cls, data):
from letsencrypt.client.le_util import jose_b64decode
return jose_b64decode(data)

View file

@ -6,18 +6,18 @@ import os
import sys
import zope.component
import zope.interface
from letsencrypt.client import CONFIG
from letsencrypt.client import client
from letsencrypt.client import display
from letsencrypt.client import interfaces
from letsencrypt.client import errors
from letsencrypt.client import log
from letsencrypt.client import revoker
from letsencrypt.client.apache import configurator
def main():
def main(): # pylint: disable=too-many-statements
"""Command line argument parsing and main script execution."""
if not os.geteuid() == 0:
sys.exit(
@ -40,7 +40,7 @@ def main():
help="Revert configuration N number of checkpoints.")
parser.add_argument("-B", "--keysize", dest="key_size", type=int,
default=CONFIG.RSA_KEY_SIZE, metavar="N",
help="RSA key shall be sized N bits. [%d]" % CONFIG.RSA_KEY_SIZE)
help="RSA key shall be sized N bits. [%(default)d]")
parser.add_argument("-k", "--revoke", dest="revoke", action="store_true",
help="Revoke a certificate.")
parser.add_argument("-v", "--view-config-changes",
@ -94,7 +94,7 @@ def main():
display_eula()
# Use the same object if possible
if interfaces.IAuthenticator.providedBy(installer):
if interfaces.IAuthenticator.providedBy(installer): # pylint: disable=no-member
auth = installer
else:
auth = determine_authenticator()
@ -166,22 +166,12 @@ def get_all_names(installer):
# This should be controlled by commandline parameters
def determine_authenticator():
"""Returns a valid IAuthenticator."""
try:
if interfaces.IAuthenticator.implementedBy(
configurator.ApacheConfigurator):
return configurator.ApacheConfigurator()
except errors.LetsEncryptConfiguratorError:
logging.info("Unable to determine a way to authenticate the server")
return configurator.ApacheConfigurator()
def determine_installer():
"""Returns a valid installer if one exists."""
try:
if interfaces.IInstaller.implementedBy(
configurator.ApacheConfigurator):
return configurator.ApacheConfigurator()
except errors.LetsEncryptConfiguratorError:
logging.info("Unable to find a way to install the certificate.")
"""Returns a valid IInstaller."""
return configurator.ApacheConfigurator()
def read_file(filename):

View file

@ -24,6 +24,7 @@ testing_extras = [
'nose',
'nosexcover',
'pylint<1.4', # py2.6 compat, c.f #97
'astroid<1.3.0', # py2.6 compat, c.f. #187
'tox',
]

View file

@ -14,7 +14,7 @@ commands =
[testenv:cover]
commands =
python setup.py dev
python setup.py nosetests --with-coverage --cover-min-percentage=59
python setup.py nosetests --with-coverage --cover-min-percentage=61
[testenv:lint]
commands =