diff --git a/pyls/config/config.py b/pyls/config/config.py index 65696d81..3425703c 100644 --- a/pyls/config/config.py +++ b/pyls/config/config.py @@ -13,7 +13,7 @@ log = logging.getLogger(__name__) # Sources of config, first source overrides next source -DEFAULT_CONFIG_SOURCES = ['pycodestyle'] +DEFAULT_CONFIG_SOURCES = ['pycodestyle', 'pylint'] class Config(object): @@ -39,6 +39,11 @@ def __init__(self, root_uri, init_opts, process_id, capabilities): self._config_sources['pycodestyle'] = PyCodeStyleConfig(self._root_path) except ImportError: pass + try: + from .pylint_conf import PylintConfig + self._config_sources['pylint'] = PylintConfig(self._root_path) + except ImportError: + pass self._pm = pluggy.PluginManager(PYLS) self._pm.trace.root.setwriter(log.debug) diff --git a/pyls/config/pylint_conf.py b/pyls/config/pylint_conf.py new file mode 100644 index 00000000..2c918b64 --- /dev/null +++ b/pyls/config/pylint_conf.py @@ -0,0 +1,53 @@ +# Copyright 2019 Palantir Technologies, Inc. +import logging +import os +from pyls._utils import find_parents +from .source import ConfigSource, _get_opt, _set_opt + +log = logging.getLogger(__name__) + +PROJECT_CONFIGS = ['.pylintrc', 'pylintrc'] + +CONFIG_KEYS = { # 'option': 'section key' + 'disable': 'MESSAGES CONTROL', + 'ignore': 'MASTER', + 'max-line-length': 'FORMAT', +} + +OPTIONS = [ + ('disable', 'plugins.pylint.disable', list), + ('ignore', 'plugins.pylint.ignore', list), + ('max-line-length', 'plugins.pylint.maxLineLength', int), +] + + +class PylintConfig(ConfigSource): + """Parse pylint configurations.""" + + def user_config(self): + config_file = self._user_config_file() + config = self.read_config_from_files([config_file]) + return self.parse_config_multi_keys(config, CONFIG_KEYS, OPTIONS) + + def _user_config_file(self): + if self.is_windows: + return os.path.expanduser('~\\.pylintrc') + return os.path.expanduser('~/.pylintrc') + + def project_config(self, document_path): + files = find_parents(self.root_path, document_path, PROJECT_CONFIGS) + config = self.read_config_from_files(files) + return self.parse_config_multi_keys(config, CONFIG_KEYS, OPTIONS) + + @staticmethod + def parse_config_multi_keys(config, keys, options): + """Parse the config with the given options. + This method use multiple keys depending on the value we want to get. + """ + conf = {} + for source, destination, opt_type in options: + key = keys[source] + opt_value = _get_opt(config, key, source, opt_type) + if opt_value is not None: + _set_opt(conf, destination, opt_value) + return conf diff --git a/pyls/plugins/pylint_lint.py b/pyls/plugins/pylint_lint.py index c07ade55..d1fa0948 100644 --- a/pyls/plugins/pylint_lint.py +++ b/pyls/plugins/pylint_lint.py @@ -11,6 +11,12 @@ log = logging.getLogger(__name__) +ARGS = { # 'argument_name': 'name_under_plugin_conf' + 'disable': 'disable', + 'ignore': 'ignore', + 'max-line-length': 'maxLineLength', +} + class PylintLinter(object): last_diags = collections.defaultdict(list) @@ -140,10 +146,24 @@ def lint(cls, document, is_saved, flags=''): def _build_pylint_flags(settings): - """Build arguments for calling pylint.""" + """Build arguments for calling pylint. + If args is found then it's the arguments used, otherwise, + we build arguments from the plugin config. + """ pylint_args = settings.get('args') if pylint_args is None: - return '' + # Build args from plugin config + pylint_args = list() + for arg_name in ARGS: + arg_val = settings.get(ARGS[arg_name]) + arg = None + if isinstance(arg_val, list): + arg = '--{}={}'.format(arg_name, ','.join(arg_val)) + elif isinstance(arg_val, int): + arg = '--{}={}'.format(arg_name, arg_val) + if arg: + pylint_args.append(arg) + return ' '.join(pylint_args) diff --git a/vscode-client/package.json b/vscode-client/package.json index a5798ec2..ca9584ed 100644 --- a/vscode-client/package.json +++ b/vscode-client/package.json @@ -27,7 +27,7 @@ }, "pyls.configurationSources": { "type": "array", - "default": ["pycodestyle"], + "default": ["pycodestyle", "pylint"], "description": "List of configuration sources to use.", "items": { "type": "string",