From 23cab4e6943ff1a61f985dd67d2ebcf115ca9775 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sat, 24 Jan 2015 13:12:45 +0000 Subject: [PATCH] pylint: 10/10 with missing-docstring --- .pylintrc | 20 +++---- letsencrypt/client/apache/configurator.py | 12 ++--- letsencrypt/client/apache/obj.py | 4 +- letsencrypt/client/auth_handler.py | 4 +- letsencrypt/client/crypto_util.py | 2 +- letsencrypt/client/display.py | 29 +++++----- letsencrypt/client/interactive_challenge.py | 1 + .../client/recovery_contact_challenge.py | 6 +-- letsencrypt/client/revoker.py | 2 +- letsencrypt/client/tests/acme_test.py | 53 +++++++++---------- .../client/tests/apache/configurator_test.py | 25 +++------ letsencrypt/client/tests/apache/dvsni_test.py | 24 ++++----- .../client/tests/apache/parser_test.py | 21 ++++---- .../tests/apache/{config_util.py => util.py} | 22 ++++++++ letsencrypt/client/tests/auth_handler_test.py | 28 +++++----- letsencrypt/client/tests/crypto_util_test.py | 16 +++--- letsencrypt/client/tests/le_util_test.py | 6 ++- letsencrypt/scripts/main.py | 20 ++----- 18 files changed, 146 insertions(+), 149 deletions(-) rename letsencrypt/client/tests/apache/{config_util.py => util.py} (81%) diff --git a/.pylintrc b/.pylintrc index 2af1870c4..131fa64a8 100644 --- a/.pylintrc +++ b/.pylintrc @@ -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 # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__,__new__,setUp diff --git a/letsencrypt/client/apache/configurator.py b/letsencrypt/client/apache/configurator.py index c9c64da93..edffd7ef4 100644 --- a/letsencrypt/client/apache/configurator.py +++ b/letsencrypt/client/apache/configurator.py @@ -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"] @@ -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 diff --git a/letsencrypt/client/apache/obj.py b/letsencrypt/client/apache/obj.py index df2f36ec4..647724a48 100644 --- a/letsencrypt/client/apache/obj.py +++ b/letsencrypt/client/apache/obj.py @@ -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 diff --git a/letsencrypt/client/auth_handler.py b/letsencrypt/client/auth_handler.py index f33aede1c..b85996818 100644 --- a/letsencrypt/client/auth_handler.py +++ b/letsencrypt/client/auth_handler.py @@ -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 diff --git a/letsencrypt/client/crypto_util.py b/letsencrypt/client/crypto_util.py index c11719343..49ab25206 100644 --- a/letsencrypt/client/crypto_util.py +++ b/letsencrypt/client/crypto_util.py @@ -238,7 +238,7 @@ def get_cert_info(filename): try: san = cert.get_ext("subjectAltName").get_value() - except: + except LookupError: san = "" return { diff --git a/letsencrypt/client/display.py b/letsencrypt/client/display.py index b3b26a39e..30f9deaf7 100644 --- a/letsencrypt/client/display.py +++ b/letsencrypt/client/display.py @@ -10,8 +10,8 @@ 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): choices = [ @@ -41,7 +41,7 @@ class NcursesDisplay(CommonDisplayMixin): def generic_notification(self, message): self.dialog.msgbox(message, width=self.width) - def generic_menu(self, message, choices, input_text=""): + def generic_menu(self, message, choices, unused_input_text=""): # Can accept either tuples or just the actual choices if choices and isinstance(choices[0], tuple): code, selection = self.dialog.menu( @@ -57,9 +57,10 @@ class NcursesDisplay(CommonDisplayMixin): def generic_input(self, message): 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"): 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): choices = [(n, "", 0) for n in names] @@ -114,9 +115,8 @@ class FileDisplay(CommonDisplayMixin): def generic_notification(self, message): 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=""): @@ -139,7 +139,7 @@ class FileDisplay(CommonDisplayMixin): return code, (selection - 1) - def generic_input(self, message): + def generic_input(self, message): # pylint: disable=no-self-use ans = raw_input("%s (Enter c to cancel)\n" % message) if ans.startswith('c') or ans.startswith('C'): @@ -147,7 +147,7 @@ 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=""): self.outfile.write("\n%s\n" % textwrap.fill(message, 80)) ans = raw_input("y/n: ") return ans.startswith('y') or ans.startswith('Y') @@ -198,11 +198,10 @@ 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)) + 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): self.outfile.write("Are you sure you would like to revoke " diff --git a/letsencrypt/client/interactive_challenge.py b/letsencrypt/client/interactive_challenge.py index c802ca191..685d2d58f 100644 --- a/letsencrypt/client/interactive_challenge.py +++ b/letsencrypt/client/interactive_challenge.py @@ -1,3 +1,4 @@ +"""Interactive challenge.""" import textwrap import dialog diff --git a/letsencrypt/client/recovery_contact_challenge.py b/letsencrypt/client/recovery_contact_challenge.py index 6bafed829..c5ca404d9 100644 --- a/letsencrypt/client/recovery_contact_challenge.py +++ b/letsencrypt/client/recovery_contact_challenge.py @@ -31,7 +31,7 @@ class RecoveryContact(object): self.poll_delay = poll_delay def perform(self, quiet=True): - d = dialog.Dialog() + 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 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. diff --git a/letsencrypt/client/revoker.py b/letsencrypt/client/revoker.py index 073362501..8573868eb 100644 --- a/letsencrypt/client/revoker.py +++ b/letsencrypt/client/revoker.py @@ -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: diff --git a/letsencrypt/client/tests/acme_test.py b/letsencrypt/client/tests/acme_test.py index 808eefc1b..f3cf4a69a 100644 --- a/letsencrypt/client/tests/acme_test.py +++ b/letsencrypt/client/tests/acme_test.py @@ -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__': diff --git a/letsencrypt/client/tests/apache/configurator_test.py b/letsencrypt/client/tests/apache/configurator_test.py index e34fca832..749ecb9c0 100644 --- a/letsencrypt/client/tests/apache/configurator_test.py +++ b/letsencrypt/client/tests/apache/configurator_test.py @@ -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", diff --git a/letsencrypt/client/tests/apache/dvsni_test.py b/letsencrypt/client/tests/apache/dvsni_test.py index bd6838869..feaec124f 100644 --- a/letsencrypt/client/tests/apache/dvsni_test.py +++ b/letsencrypt/client/tests/apache/dvsni_test.py @@ -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() diff --git a/letsencrypt/client/tests/apache/parser_test.py b/letsencrypt/client/tests/apache/parser_test.py index 2acf6533e..df0046ff5 100644 --- a/letsencrypt/client/tests/apache/parser_test.py +++ b/letsencrypt/client/tests/apache/parser_test.py @@ -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() diff --git a/letsencrypt/client/tests/apache/config_util.py b/letsencrypt/client/tests/apache/util.py similarity index 81% rename from letsencrypt/client/tests/apache/config_util.py rename to letsencrypt/client/tests/apache/util.py index ad38818ab..d5a662924 100644 --- a/letsencrypt/client/tests/apache/config_util.py +++ b/letsencrypt/client/tests/apache/util.py @@ -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") diff --git a/letsencrypt/client/tests/auth_handler_test.py b/letsencrypt/client/tests/auth_handler_test.py index 2cb801efc..9b2caebeb 100644 --- a/letsencrypt/client/tests/auth_handler_test.py +++ b/letsencrypt/client/tests/auth_handler_test.py @@ -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): diff --git a/letsencrypt/client/tests/crypto_util_test.py b/letsencrypt/client/tests/crypto_util_test.py index e80988d83..49d7c02b1 100644 --- a/letsencrypt/client/tests/crypto_util_test.py +++ b/letsencrypt/client/tests/crypto_util_test.py @@ -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)) @@ -103,7 +106,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) @@ -120,7 +124,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']) diff --git a/letsencrypt/client/tests/le_util_test.py b/letsencrypt/client/tests/le_util_test.py index f6c58ac0b..f7ab1ab2b 100644 --- a/letsencrypt/client/tests/le_util_test.py +++ b/letsencrypt/client/tests/le_util_test.py @@ -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) diff --git a/letsencrypt/scripts/main.py b/letsencrypt/scripts/main.py index ff3c3c792..801e36121 100755 --- a/letsencrypt/scripts/main.py +++ b/letsencrypt/scripts/main.py @@ -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( @@ -163,22 +163,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):