Skip to content

Commit cdd0ed3

Browse files
authored
[Linter] Show command should use g.show_command or g.custom_show_command (#241)
1 parent 3420d39 commit cdd0ed3

7 files changed

Lines changed: 84 additions & 8 deletions

File tree

azdev/operations/linter/__init__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
from azdev.utilities import (
1717
heading, subheading, display, get_path_table, require_azure_cli, filter_by_git_diff)
1818
from azdev.utilities.path import get_cli_repo_path, get_ext_repo_paths
19+
from azdev.operations.style import run_pylint
1920

2021
from .linter import LinterManager, LinterScope, RuleError, LinterSeverity
2122
from .util import filter_modules, merge_exclusion
2223

2324

2425
logger = get_logger(__name__)
26+
CHECKERS_PATH = 'azdev.operations.linter.pylint_checkers'
2527

2628

2729
# pylint:disable=too-many-locals, too-many-statements, too-many-branches
@@ -158,8 +160,29 @@ def run_linter(modules=None, rule_types=None, rules=None, ci_exclusions=None,
158160
run_commands=not rule_types or 'commands' in rule_types,
159161
run_command_groups=not rule_types or 'command_groups' in rule_types,
160162
run_help_files_entries=not rule_types or 'help_entries' in rule_types)
163+
logger.info(os.linesep)
164+
logger.info('Run custom pylint rules.')
165+
exit_code += pylint_rules(selected_modules)
161166
sys.exit(exit_code)
162167

163168

169+
def pylint_rules(selected_modules):
170+
# TODO: support severity for pylint rules
171+
from importlib import import_module
172+
my_env = os.environ.copy()
173+
checker_path = import_module('{}'.format(CHECKERS_PATH)).__path__[0]
174+
my_env['PYTHONPATH'] = checker_path
175+
checkers = [os.path.splitext(f)[0] for f in os.listdir(checker_path) if
176+
os.path.isfile(os.path.join(checker_path, f)) and f != '__init__.py']
177+
enable = [s.replace('_', '-') for s in checkers]
178+
pylint_result = run_pylint(selected_modules, env=my_env, checkers=checkers, disable_all=True, enable=enable)
179+
if pylint_result and not pylint_result.error:
180+
display(os.linesep + 'No violations found for custom pylint rules.')
181+
if pylint_result and pylint_result.error:
182+
logger.info(pylint_result.error.output.decode('utf-8'))
183+
logger.info('Linter: FAILED\n')
184+
return pylint_result.exit_code
185+
186+
164187
def linter_severity_choices():
165188
return [str(severity.name).lower() for severity in LinterSeverity]

azdev/operations/linter/linter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def run(self, run_params=None, run_commands=None, run_command_groups=None, run_h
257257
self._run_rules('params')
258258

259259
if not self.exit_code:
260-
print(os.linesep + 'No violations found.')
260+
print(os.linesep + 'No violations found for linter rules.')
261261

262262
if self._update_global_exclusion is not None:
263263
if self._update_global_exclusion == 'CLI':
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -----------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License.txt in the project root for
4+
# license information.
5+
# -----------------------------------------------------------------------------
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# -----------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License.txt in the project root for
4+
# license information.
5+
# -----------------------------------------------------------------------------
6+
import astroid
7+
8+
from pylint.checkers import BaseChecker
9+
from pylint.interfaces import IAstroidChecker
10+
11+
12+
class ShowCommandChecker(BaseChecker):
13+
__implements__ = IAstroidChecker
14+
15+
name = 'show-command'
16+
priority = -1
17+
msgs = {
18+
'E5001': (
19+
'Show command must use show_command or custom_show_command.',
20+
'show-command',
21+
'Please use show_command or custom_show_command.'
22+
),
23+
}
24+
25+
def visit_call(self, node):
26+
try:
27+
if not (isinstance(node.args[0], astroid.node_classes.Const) and node.args[0].value == 'show'):
28+
return
29+
if node.func.attrname == 'command' or node.func.attrname == 'custom_command':
30+
self.add_message(
31+
'show-command', node=node,
32+
)
33+
except IndexError:
34+
return
35+
36+
37+
def register(linter):
38+
linter.register_checker(ShowCommandChecker(linter))

azdev/operations/style.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def check_style(modules=None, pylint=False, pep8=False, git_source=None, git_tar
7979
exit_code_sum += pep8_result.exit_code
8080

8181
if pylint:
82-
pylint_result = _run_pylint(selected_modules)
82+
pylint_result = run_pylint(selected_modules)
8383
exit_code_sum += pylint_result.exit_code
8484

8585
display('')
@@ -131,7 +131,7 @@ def apply_result(item):
131131
return final_result
132132

133133

134-
def _run_pylint(modules):
134+
def run_pylint(modules, checkers=None, env=None, disable_all=False, enable=None):
135135
def get_core_module_paths(modules):
136136
core_paths = []
137137
for p in modules["core"].values():
@@ -148,20 +148,29 @@ def get_core_module_paths(modules):
148148
glob_pattern = os.path.normcase(os.path.join("{}*".format(EXTENSION_PREFIX)))
149149
ext_paths.append(glob(os.path.join(path, glob_pattern))[0])
150150

151-
def run(paths, rcfile, desc):
151+
def run(paths, rcfile, desc, checkers=None, env=None, disable_all=False, enable=None):
152152
if not paths:
153153
return None
154154
logger.debug("Using rcfile file: %s", rcfile)
155155
logger.debug("Running on %s: %s", desc, "\n".join(paths))
156156
command = "pylint {} --ignore vendored_sdks,privates --rcfile={} -j {}".format(
157157
" ".join(paths), rcfile, multiprocessing.cpu_count()
158158
)
159-
return py_cmd(command, message="Running pylint on {}...".format(desc))
159+
if checkers is not None:
160+
command += ' --load-plugins {}'.format(",".join(checkers))
161+
if disable_all:
162+
command += ' --disable=all'
163+
if enable is not None:
164+
command += ' --enable {}'.format(",".join(enable))
165+
166+
return py_cmd(command, message="Running pylint on {}...".format(desc), env=env)
160167

161168
cli_pylintrc, ext_pylintrc = _config_file_path("pylint")
162169

163-
cli_result = run(cli_paths, cli_pylintrc, "modules")
164-
ext_result = run(ext_paths, ext_pylintrc, "extensions")
170+
cli_result = run(cli_paths, cli_pylintrc, "modules",
171+
checkers=checkers, env=env, disable_all=disable_all, enable=enable)
172+
ext_result = run(ext_paths, ext_pylintrc, "extensions",
173+
checkers=checkers, env=env, disable_all=disable_all, enable=enable)
165174
return _combine_command_result(cli_result, ext_result)
166175

167176

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ jobs:
240240
set -ev
241241
. scripts/ci/install.sh
242242
# verify azdev linter works
243-
azdev linter CLI
243+
azdev linter acr
244244
displayName: 'Test azdev linter'
245245
246246
- job: TestAzdevStyle

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
'azdev.operations.help.refdoc',
5656
'azdev.operations.linter',
5757
'azdev.operations.linter.rules',
58+
'azdev.operations.linter.pylint_checkers',
5859
'azdev.operations.testtool',
5960
'azdev.operations.extensions',
6061
'azdev.utilities',

0 commit comments

Comments
 (0)