new file mode 100644
--- /dev/null
+++ b/tools/lint/flake8.lint
@@ -0,0 +1,62 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import json
+import os
+import subprocess
+from collections import defaultdict
+
+from mozlint import result
+
+
+FLAKE8_NOT_FOUND = """
+Could not find flake8! Install flake8 and try again.
+""".strip()
+
+
+def lint(files, **lintargs):
+ import which
+
+ binary = os.environ.get('FLAKE8')
+ if not binary:
+ try:
+ binary = which.which('flake8')
+ except which.WhichError:
+ pass
+
+ if not binary:
+ print(FLAKE8_NOT_FOUND)
+ return 1
+
+ cmdargs = [
+ binary,
+ '--format',
+ '{"path":"%(path)s","lineno":%(row)s,"column":%(col)s,"rule":"%(code)s","message":"%(text)s"}',
+ ] + files
+
+ proc = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, env=os.environ)
+ output = proc.communicate()[0]
+
+ if not output:
+ return []
+
+ results = []
+ for line in output.splitlines():
+ res = json.loads(line)
+ if 'code' in res and res['code'].startswith('W'):
+ res['level'] = 'warning'
+ results.append(result.from_linter(LINTER, **res))
+
+ return results
+
+
+LINTER = {
+ 'name': "flake8",
+ 'description': "Python linter",
+ 'include': ['**/*.py'],
+ 'type': 'external',
+ 'payload': lint,
+}