diff --git a/pegleg/engine/lint.py b/pegleg/engine/lint.py
index c0706ce4..7b2f7259 100644
--- a/pegleg/engine/lint.py
+++ b/pegleg/engine/lint.py
@@ -216,7 +216,7 @@ def _verify_file_contents(*, sitename=None):
 
 def _verify_single_file(filename, schemas):
     errors = []
-    LOG.debug("Validating file %s." % filename)
+    LOG.debug("Validating file %s.", filename)
     with open(filename) as f:
         if not f.read(4) == '---\n':
             errors.append((FILE_MISSING_YAML_DOCUMENT_HEADER,
diff --git a/pegleg/engine/repository.py b/pegleg/engine/repository.py
index 52d7285e..7c8bdfda 100644
--- a/pegleg/engine/repository.py
+++ b/pegleg/engine/repository.py
@@ -196,7 +196,7 @@ def _get_and_validate_site_repositories(site_name, site_data):
         LOG.info("The repository for site_name: %s does not contain a "
                  "site-definition.yaml with a 'repositories' key. Ensure "
                  "your repository is self-contained and doesn't require "
-                 "extra repositories for correct rendering." % site_name)
+                 "extra repositories for correct rendering.", site_name)
     return site_data.get('repositories', {})
 
 
diff --git a/pegleg/engine/secrets.py b/pegleg/engine/secrets.py
index 08688bcc..19afb598 100644
--- a/pegleg/engine/secrets.py
+++ b/pegleg/engine/secrets.py
@@ -15,9 +15,9 @@
 import logging
 import os
 
-from pegleg.engine.util.pegleg_secret_management import PeglegSecretManagement
-from pegleg.engine.util import files
 from pegleg.engine.util import definition
+from pegleg.engine.util import files
+from pegleg.engine.util.pegleg_secret_management import PeglegSecretManagement
 
 __all__ = ('encrypt', 'decrypt')
 
diff --git a/pegleg/engine/site.py b/pegleg/engine/site.py
index 2a03074f..390ea50d 100644
--- a/pegleg/engine/site.py
+++ b/pegleg/engine/site.py
@@ -67,7 +67,7 @@ def _collect_to_file(site_name, save_location):
             save_file = os.path.join(save_location, repo_name + '.yaml')
             if repo_name not in save_files:
                 save_files[repo_name] = open(save_file, "w")
-            LOG.debug("Collecting file %s to file %s" % (filename, save_file))
+            LOG.debug("Collecting file %s to file %s", filename, save_file)
             save_files[repo_name].writelines(_read_and_format_yaml(filename))
     except Exception as ex:
         raise click.ClickException("Error saving output: %s" % str(ex))
diff --git a/pegleg/engine/util/deckhand.py b/pegleg/engine/util/deckhand.py
index afb3e57e..c1d42fd7 100644
--- a/pegleg/engine/util/deckhand.py
+++ b/pegleg/engine/util/deckhand.py
@@ -12,11 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from pegleg.engine.errorcodes import DECKHAND_DUPLICATE_SCHEMA
-from pegleg.engine.errorcodes import DECKHAND_RENDER_EXCEPTION
+
 from deckhand.engine import layering
 from deckhand import errors as dh_errors
 
+from pegleg.engine.errorcodes import DECKHAND_DUPLICATE_SCHEMA
+from pegleg.engine.errorcodes import DECKHAND_RENDER_EXCEPTION
+
 
 def load_schemas_from_docs(documents):
     '''
diff --git a/pegleg/engine/util/encryption.py b/pegleg/engine/util/encryption.py
index c84f61d5..626a1518 100644
--- a/pegleg/engine/util/encryption.py
+++ b/pegleg/engine/util/encryption.py
@@ -12,13 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
 import base64
+import logging
+
+from cryptography.exceptions import InvalidSignature
 from cryptography.fernet import Fernet
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
-from cryptography.exceptions import InvalidSignature
 
 KEY_LENGTH = 32
 ITERATIONS = 10000
diff --git a/pegleg/engine/util/files.py b/pegleg/engine/util/files.py
index 7a182851..02cb33ed 100644
--- a/pegleg/engine/util/files.py
+++ b/pegleg/engine/util/files.py
@@ -12,11 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import click
 import collections
-import os
-import yaml
 import logging
+import os
+
+import click
+import yaml
 
 from pegleg import config
 from pegleg.engine import util
@@ -330,7 +331,7 @@ def search(search_paths):
         search_paths = [search_paths]
 
     for search_path in search_paths:
-        LOG.debug("Recursively collecting YAMLs from %s" % search_path)
+        LOG.debug("Recursively collecting YAMLs from %s", search_path)
         for root, _, filenames in os.walk(search_path):
 
             # Ignore hidden folders like .tox or .git for faster processing.
@@ -372,7 +373,7 @@ def check_file_save_location(save_location):
 
 
 def collect_files_by_repo(site_name):
-    """ Collects file by repo name in memory."""
+    """Collects file by repo name in memory."""
 
     collected_files_by_repo = collections.defaultdict(list)
     for repo_base, filename in util.definition.site_files_by_repo(
diff --git a/pegleg/engine/util/pegleg_managed_document.py b/pegleg/engine/util/pegleg_managed_document.py
index 94527be8..1cfd5049 100644
--- a/pegleg/engine/util/pegleg_managed_document.py
+++ b/pegleg/engine/util/pegleg_managed_document.py
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
 from datetime import datetime
+import logging
 
 PEGLEG_MANAGED_SCHEMA = 'pegleg/PeglegManagedDocument/v1'
 ENCRYPTED = 'encrypted'
@@ -22,7 +22,7 @@ METADATA = 'metadata'
 LOG = logging.getLogger(__name__)
 
 
-class PeglegManagedSecretsDocument():
+class PeglegManagedSecretsDocument(object):
     """Object representing one Pegleg managed secret document."""
 
     def __init__(self, secrets_document):
diff --git a/pegleg/engine/util/pegleg_secret_management.py b/pegleg/engine/util/pegleg_secret_management.py
index a939f2d9..364fab4b 100644
--- a/pegleg/engine/util/pegleg_secret_management.py
+++ b/pegleg/engine/util/pegleg_secret_management.py
@@ -14,16 +14,17 @@
 
 import logging
 import os
-import yaml
-import sys
 import re
-import click
+import sys
+
+import click
+import yaml
 
-from pegleg.engine.util.encryption import encrypt
 from pegleg.engine.util.encryption import decrypt
+from pegleg.engine.util.encryption import encrypt
+from pegleg.engine.util import files
 from pegleg.engine.util.pegleg_managed_document import \
     PeglegManagedSecretsDocument as PeglegManagedSecret
-from pegleg.engine.util import files
 
 LOG = logging.getLogger(__name__)
 PASSPHRASE_PATTERN = '^.{24,}$'
@@ -31,7 +32,7 @@ ENV_PASSPHRASE = 'PEGLEG_PASSPHRASE'
 ENV_SALT = 'PEGLEG_SALT'
 
 
-class PeglegSecretManagement():
+class PeglegSecretManagement(object):
     """An object to handle operations on of a pegleg managed file."""
 
     def __init__(self, file_path=None, docs=None):
diff --git a/pegleg/engine/util/shipyard_helper.py b/pegleg/engine/util/shipyard_helper.py
index 4c58580e..07de7ea9 100644
--- a/pegleg/engine/util/shipyard_helper.py
+++ b/pegleg/engine/util/shipyard_helper.py
@@ -18,8 +18,8 @@ import uuid
 
 import yaml
 
-from pegleg.engine.util import files
 from pegleg.engine.exceptions import PeglegBaseException
+from pegleg.engine.util import files
 
 from shipyard_client.api_client.shipyard_api_client import ShipyardClient
 from shipyard_client.api_client.shipyardclient_context import \
@@ -36,7 +36,7 @@ class AuthValuesError(PeglegBaseException):
 
 
 class DocumentUploadError(PeglegBaseException):
-    """ Exception occurs while uploading documents"""
+    """Exception occurs while uploading documents"""
 
     def __init__(self, message):
         self.message = message
@@ -65,18 +65,18 @@ class ShipyardHelper(object):
         self.context_marker = self.ctx.obj['context_marker']
         if self.context_marker is None:
             self.context_marker = str(uuid.uuid4())
-            LOG.debug("context_marker is %s" % self.context_marker)
+            LOG.debug("context_marker is %s", self.context_marker)
         self.site_name = self.ctx.obj['site_name']
         self.client_context = ShipyardClientContext(
             self.auth_vars, self.context_marker)
         self.api_client = ShipyardClient(self.client_context)
 
     def upload_documents(self):
-        """ Uploads documents to Shipyard """
+        """Uploads documents to Shipyard """
 
         collected_documents = files.collect_files_by_repo(self.site_name)
 
-        LOG.info("Uploading %s collection(s) " % len(collected_documents))
+        LOG.info("Uploading %d collection(s) ", len(collected_documents))
         for idx, document in enumerate(collected_documents):
             # Append flag is not required for the first
             # collection being uploaded to Shipyard. It
@@ -129,7 +129,7 @@ class ShipyardHelper(object):
                     raise DocumentUploadError(resp_text)
             else:
                 output = self.formatted_response_handler(resp_text)
-                LOG.info("Uploaded document in buffer %s " % output)
+                LOG.info("Uploaded document in buffer %s ", output)
 
         # Commit in the last iteration of the loop when all the documents
         # have been pushed to Shipyard buffer.
@@ -137,7 +137,7 @@ class ShipyardHelper(object):
             return self.commit_documents()
 
     def commit_documents(self):
-        """ Commit Shipyard buffer documents """
+        """Commit Shipyard buffer documents """
 
         LOG.info("Commiting Shipyard buffer documents")
 
diff --git a/test-requirements.txt b/test-requirements.txt
index 010aa6db..1f282300 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -7,7 +7,7 @@ mock==2.0.0
 yapf==0.20.0
 
 # Linting
-flake8==3.3.0
+hacking>=1.1.0,<1.2.0 # Apache-2.0
 
 # Security
 bandit>=1.5.0
diff --git a/tests/unit/engine/test_site_repository.py b/tests/unit/engine/test_site_repository.py
index 27df345e..2dd8bdcd 100644
--- a/tests/unit/engine/test_site_repository.py
+++ b/tests/unit/engine/test_site_repository.py
@@ -455,8 +455,7 @@ def test_process_repositories_without_repositories_key_in_site_definition(
         _test_process_repositories_inner(
             site_name=mock.sentinel.site, expected_extra_repos={})
     msg = ("The repository for site_name: %s does not contain a "
-           "site-definition.yaml with a 'repositories' key" % str(
-               mock.sentinel.site))
+           "site-definition.yaml with a 'repositories' key")
     assert any(msg in x[1][0] for x in m_log.info.mock_calls)
 
 
diff --git a/tox.ini b/tox.ini
index 53f825b8..75efc851 100644
--- a/tox.ini
+++ b/tox.ini
@@ -74,6 +74,14 @@ commands = {posargs}
 [flake8]
 filename = *.py
 show-source = true
-ignore =
+# [H106] Don't put vim configuration in source files.
+# [H210] Require 'autospec', 'spec', or 'spec_set' in mock.patch/mock.patch.object calls
+# [H904] Delay string interpolations at logging calls.
+enable-extensions = H106,H201,H904
+# TODO(lamt) Clean up these docstring violations if possible
+# [H403] multi line docstrings should end on a new line
+# [H404] multi line docstring should start without a leading new line
+# [H405] multi line docstring summary not separated with an empty line
+ignore = H403,H404,H405
 exclude=.venv,.git,.tox,build,dist,*lib/python*,*egg,tools,*.ini,*.po,*.pot
 max-complexity = 24