Bug 1358540 - Change the *.lint files to be *.lint.py to better support editor integration & flake8 linting. r?smacleod draft
authorMark Banner <standard8@mozilla.com>
Fri, 21 Apr 2017 17:31:15 +0100
changeset 567569 b52e23757024ae120c4dd5cdb8e560ff8fd23f13
parent 567507 85932a5027c024900bb0e58cdbc52ecf9a32e1f5
child 625710 8086db327b355b6e260abc7fcdbb663038d1a0c1
push id55637
push usermbanner@mozilla.com
push dateTue, 25 Apr 2017 09:31:09 +0000
reviewerssmacleod
bugs1358540
milestone55.0a1
Bug 1358540 - Change the *.lint files to be *.lint.py to better support editor integration & flake8 linting. r?smacleod MozReview-Commit-ID: 4KK2GZK7xul
python/mozlint/mozlint/cli.py
python/mozlint/mozlint/parser.py
python/mozlint/mozlint/result.py
python/mozlint/test/conftest.py
python/mozlint/test/linters/badreturncode.lint
python/mozlint/test/linters/badreturncode.lint.py
python/mozlint/test/linters/explicit_path.lint
python/mozlint/test/linters/explicit_path.lint.py
python/mozlint/test/linters/external.lint
python/mozlint/test/linters/external.lint.py
python/mozlint/test/linters/invalid_exclude.lint
python/mozlint/test/linters/invalid_exclude.lint.py
python/mozlint/test/linters/invalid_include.lint
python/mozlint/test/linters/invalid_include.lint.py
python/mozlint/test/linters/invalid_type.lint
python/mozlint/test/linters/invalid_type.lint.py
python/mozlint/test/linters/missing_attrs.lint
python/mozlint/test/linters/missing_attrs.lint.py
python/mozlint/test/linters/missing_definition.lint
python/mozlint/test/linters/missing_definition.lint.py
python/mozlint/test/linters/raises.lint
python/mozlint/test/linters/raises.lint.py
python/mozlint/test/linters/regex.lint
python/mozlint/test/linters/regex.lint.py
python/mozlint/test/linters/string.lint
python/mozlint/test/linters/string.lint.py
python/mozlint/test/linters/structured.lint
python/mozlint/test/linters/structured.lint.py
python/mozlint/test/test_parser.py
python/mozlint/test/test_roller.py
python/mozlint/test/test_types.py
tools/lint/eslint.lint
tools/lint/eslint.lint.py
tools/lint/flake8.lint
tools/lint/flake8.lint.py
tools/lint/mach_commands.py
tools/lint/wpt.lint
tools/lint/wpt.lint.py
tools/lint/wpt_manifest.lint
tools/lint/wpt_manifest.lint.py
--- a/python/mozlint/mozlint/cli.py
+++ b/python/mozlint/mozlint/cli.py
@@ -81,20 +81,23 @@ class MozlintParser(ArgumentParser):
 def find_linters(linters=None):
     lints = []
     for search_path in SEARCH_PATHS:
         if not os.path.isdir(search_path):
             continue
 
         files = os.listdir(search_path)
         for f in files:
-            name, ext = os.path.splitext(f)
-            if ext != '.lint':
+            name = os.path.basename(f)
+
+            if not name.endswith('.lint.py'):
                 continue
 
+            name = name.rsplit('.', 2)[0]
+
             if linters and name not in linters:
                 continue
 
             lints.append(os.path.join(search_path, f))
     return lints
 
 
 def run(paths, linters, fmt, rev, outgoing, workdir, **lintargs):
--- a/python/mozlint/mozlint/parser.py
+++ b/python/mozlint/mozlint/parser.py
@@ -7,17 +7,17 @@ import os
 import sys
 import uuid
 
 from .types import supported_types
 from .errors import LinterNotFound, LinterParseError
 
 
 class Parser(object):
-    """Reads and validates `.lint` files."""
+    """Reads and validates `.lint.py` files."""
     required_attributes = (
         'name',
         'description',
         'type',
         'payload',
     )
 
     def __call__(self, path):
@@ -72,14 +72,14 @@ class Parser(object):
 
         :param path: Path to the linter.
         :returns: Linter definition (dict)
         :raises: LinterNotFound, LinterParseError
         """
         if not os.path.isfile(path):
             raise LinterNotFound(path)
 
-        if not path.endswith('.lint'):
-            raise LinterParseError(path, "Invalid filename, linters must end with '.lint'!")
+        if not path.endswith('.lint.py'):
+            raise LinterParseError(path, "Invalid filename, linters must end with '.lint.py'!")
 
         linter = self._load_linter(path)
         self._validate(linter)
         return linter
--- a/python/mozlint/mozlint/result.py
+++ b/python/mozlint/mozlint/result.py
@@ -66,17 +66,17 @@ class ResultEncoder(JSONEncoder):
 
 
 def from_linter(lintobj, **kwargs):
     """Create a :class:`~result.ResultContainer` from a LINTER definition.
 
     Convenience method that pulls defaults from a LINTER
     definition and forwards them.
 
-    :param lintobj: LINTER obj as defined in a .lint file
+    :param lintobj: LINTER obj as defined in a .lint.py file
     :param kwargs: same as :class:`~result.ResultContainer`
     :returns: :class:`~result.ResultContainer` object
     """
     attrs = {}
     for attr in ResultContainer.__slots__:
         attrs[attr] = kwargs.get(attr, lintobj.get(attr))
 
     if not attrs['linter']:
--- a/python/mozlint/test/conftest.py
+++ b/python/mozlint/test/conftest.py
@@ -32,11 +32,11 @@ def files(filedir, request):
 
 @pytest.fixture(scope='session')
 def lintdir():
     return os.path.join(here, 'linters')
 
 
 @pytest.fixture(scope='module')
 def linters(lintdir, request):
-    suffix_filter = getattr(request.module, 'linters', ['.lint'])
+    suffix_filter = getattr(request.module, 'linters', ['.lint.py'])
     return [os.path.join(lintdir, p) for p in os.listdir(lintdir)
             if any(p.endswith(suffix) for suffix in suffix_filter)]
rename from python/mozlint/test/linters/badreturncode.lint
rename to python/mozlint/test/linters/badreturncode.lint.py
rename from python/mozlint/test/linters/explicit_path.lint
rename to python/mozlint/test/linters/explicit_path.lint.py
rename from python/mozlint/test/linters/external.lint
rename to python/mozlint/test/linters/external.lint.py
rename from python/mozlint/test/linters/invalid_exclude.lint
rename to python/mozlint/test/linters/invalid_exclude.lint.py
rename from python/mozlint/test/linters/invalid_include.lint
rename to python/mozlint/test/linters/invalid_include.lint.py
rename from python/mozlint/test/linters/invalid_type.lint
rename to python/mozlint/test/linters/invalid_type.lint.py
rename from python/mozlint/test/linters/missing_attrs.lint
rename to python/mozlint/test/linters/missing_attrs.lint.py
rename from python/mozlint/test/linters/missing_definition.lint
rename to python/mozlint/test/linters/missing_definition.lint.py
rename from python/mozlint/test/linters/raises.lint
rename to python/mozlint/test/linters/raises.lint.py
rename from python/mozlint/test/linters/regex.lint
rename to python/mozlint/test/linters/regex.lint.py
rename from python/mozlint/test/linters/string.lint
rename to python/mozlint/test/linters/string.lint.py
rename from python/mozlint/test/linters/structured.lint
rename to python/mozlint/test/linters/structured.lint.py
--- a/python/mozlint/test/test_parser.py
+++ b/python/mozlint/test/test_parser.py
@@ -20,31 +20,31 @@ def parse(lintdir):
 
     def _parse(name):
         path = os.path.join(lintdir, name)
         return parser(path)
     return _parse
 
 
 def test_parse_valid_linter(parse):
-    lintobj = parse('string.lint')
+    lintobj = parse('string.lint.py')
     assert isinstance(lintobj, dict)
     assert 'name' in lintobj
     assert 'description' in lintobj
     assert 'type' in lintobj
     assert 'payload' in lintobj
 
 
 @pytest.mark.parametrize('linter', [
-    'invalid_type.lint',
+    'invalid_type.lint.py',
     'invalid_extension.lnt',
-    'invalid_include.lint',
-    'invalid_exclude.lint',
-    'missing_attrs.lint',
-    'missing_definition.lint',
+    'invalid_include.lint.py',
+    'invalid_exclude.lint.py',
+    'missing_attrs.lint.py',
+    'missing_definition.lint.py',
 ])
 def test_parse_invalid_linter(parse, linter):
     with pytest.raises(LinterParseError):
         parse(linter)
 
 
 def test_parse_non_existent_linter(parse):
     with pytest.raises(LinterNotFound):
--- a/python/mozlint/test/test_roller.py
+++ b/python/mozlint/test/test_roller.py
@@ -9,17 +9,17 @@ import pytest
 
 from mozlint import ResultContainer
 from mozlint.errors import LintersNotConfigured, LintException
 
 
 here = os.path.abspath(os.path.dirname(__file__))
 
 
-linters = ('string.lint', 'regex.lint', 'external.lint')
+linters = ('string.lint.py', 'regex.lint.py', 'external.lint.py')
 
 
 def test_roll_no_linters_configured(lint, files):
     with pytest.raises(LintersNotConfigured):
         lint.roll(files)
 
 
 def test_roll_successful(lint, linters, files):
@@ -37,17 +37,17 @@ def test_roll_successful(lint, linters, 
     assert len(errors) == 6
 
     container = errors[0]
     assert isinstance(container, ResultContainer)
     assert container.rule == 'no-foobar'
 
 
 def test_roll_catch_exception(lint, lintdir, files):
-    lint.read(os.path.join(lintdir, 'raises.lint'))
+    lint.read(os.path.join(lintdir, 'raises.lint.py'))
 
     # suppress printed traceback from test output
     old_stderr = sys.stderr
     sys.stderr = open(os.devnull, 'w')
     with pytest.raises(LintException):
         lint.roll(files)
     sys.stderr = old_stderr
 
@@ -58,24 +58,24 @@ def test_roll_with_excluded_path(lint, l
     lint.read(linters)
     result = lint.roll(files)
 
     assert len(result) == 0
     assert lint.failed == []
 
 
 def test_roll_with_invalid_extension(lint, lintdir, filedir):
-    lint.read(os.path.join(lintdir, 'external.lint'))
+    lint.read(os.path.join(lintdir, 'external.lint.py'))
     result = lint.roll(os.path.join(filedir, 'foobar.py'))
     assert len(result) == 0
     assert lint.failed == []
 
 
 def test_roll_with_failure_code(lint, lintdir, files):
-    lint.read(os.path.join(lintdir, 'badreturncode.lint'))
+    lint.read(os.path.join(lintdir, 'badreturncode.lint.py'))
 
     assert lint.failed is None
     result = lint.roll(files)
     assert len(result) == 0
     assert lint.failed == ['BadReturnCodeLinter']
 
 
 if __name__ == '__main__':
--- a/python/mozlint/test/test_types.py
+++ b/python/mozlint/test/test_types.py
@@ -12,17 +12,21 @@ from mozlint.result import ResultContain
 
 @pytest.fixture
 def path(filedir):
     def _path(name):
         return os.path.join(filedir, name)
     return _path
 
 
-@pytest.fixture(params=['string.lint', 'regex.lint', 'external.lint', 'structured.lint'])
+@pytest.fixture(params=[
+    'string.lint.py',
+    'regex.lint.py',
+    'external.lint.py',
+    'structured.lint.py'])
 def linter(lintdir, request):
     return os.path.join(lintdir, request.param)
 
 
 def test_linter_types(lint, linter, files, path):
     lint.read(linter)
     result = lint.roll(files)
     assert isinstance(result, dict)
@@ -32,17 +36,17 @@ def test_linter_types(lint, linter, file
     result = result[path('foobar.js')][0]
     assert isinstance(result, ResultContainer)
 
     name = os.path.basename(linter).split('.')[0]
     assert result.linter.lower().startswith(name)
 
 
 def test_no_filter(lint, lintdir, files):
-    lint.read(os.path.join(lintdir, 'explicit_path.lint'))
+    lint.read(os.path.join(lintdir, 'explicit_path.lint.py'))
     result = lint.roll(files)
     assert len(result) == 0
 
     lint.lintargs['use_filters'] = False
     result = lint.roll(files)
     assert len(result) == 2
 
 
rename from tools/lint/eslint.lint
rename to tools/lint/eslint.lint.py
--- a/tools/lint/eslint.lint
+++ b/tools/lint/eslint.lint.py
@@ -73,17 +73,17 @@ def eslint_setup():
     # npm sometimes fails to respect cwd when it is run using check_call so
     # we manually switch folders here instead.
     os.chdir(get_project_root())
 
     npm_path = get_node_or_npm_path("npm")
     if not npm_path:
         return 1
 
-    extra_parameters = [ "--loglevel=error" ]
+    extra_parameters = ["--loglevel=error"]
 
     # Install ESLint and external plugins
     cmd = [npm_path, "install"]
     cmd.extend(extra_parameters)
     print("Installing eslint for mach using \"%s\"..." % (" ".join(cmd)))
     if not call_process("eslint", cmd):
         return 1
 
rename from tools/lint/flake8.lint
rename to tools/lint/flake8.lint.py
--- a/tools/lint/flake8.lint
+++ b/tools/lint/flake8.lint.py
@@ -109,17 +109,17 @@ def get_flake8_binary():
 
 
 def _run_pip(*args):
     """
     Helper function that runs pip with subprocess
     """
     try:
         subprocess.check_output(['pip'] + list(args),
-                                      stderr=subprocess.STDOUT)
+                                stderr=subprocess.STDOUT)
         return True
     except subprocess.CalledProcessError as e:
         print(e.output)
         return False
 
 
 def reinstall_flake8():
     """
--- a/tools/lint/mach_commands.py
+++ b/tools/lint/mach_commands.py
@@ -41,17 +41,17 @@ class MachCommands(MachCommandBase):
         cli.SEARCH_PATHS.append(here)
         self._activate_virtualenv()
         return cli.run(*runargs, **lintargs)
 
     @Command('eslint', category='devenv',
              description='Run eslint or help configure eslint for optimal development.')
     @CommandArgument('paths', default=None, nargs='*',
                      help="Paths to file or directories to lint, like "
-                          "'browser/components/loop' Defaults to the "
+                          "'browser/' Defaults to the "
                           "current directory if not given.")
     @CommandArgument('-s', '--setup', default=False, action='store_true',
                      help='Configure eslint for optimal development.')
     @CommandArgument('-b', '--binary', default=None,
                      help='Path to eslint binary.')
     @CommandArgument('--fix', default=False, action='store_true',
                      help='Request that eslint automatically fix errors, where possible.')
     @CommandArgument('extra_args', nargs=argparse.REMAINDER,
rename from tools/lint/wpt.lint
rename to tools/lint/wpt.lint.py
rename from tools/lint/wpt_manifest.lint
rename to tools/lint/wpt_manifest.lint.py
--- a/tools/lint/wpt_manifest.lint
+++ b/tools/lint/wpt_manifest.lint.py
@@ -1,22 +1,16 @@
 # -*- Mode: python; 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 imp
-import json
 import os
-import sys
-
-from mozprocess import ProcessHandler
-
-from mozlint import result
 
 
 def lint(files, logger, **kwargs):
     wpt_dir = os.path.join(kwargs["root"], "testing", "web-platform")
     manifestupdate = imp.load_source("manifestupdate",
                                      os.path.join(wpt_dir, "manifestupdate.py"))
     manifestupdate.update(logger, wpt_dir, True)