summaryrefslogtreecommitdiff
path: root/venv/Lib/site-packages/pylint/lint.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/Lib/site-packages/pylint/lint.py')
-rw-r--r--venv/Lib/site-packages/pylint/lint.py1817
1 files changed, 0 insertions, 1817 deletions
diff --git a/venv/Lib/site-packages/pylint/lint.py b/venv/Lib/site-packages/pylint/lint.py
deleted file mode 100644
index a98970b..0000000
--- a/venv/Lib/site-packages/pylint/lint.py
+++ /dev/null
@@ -1,1817 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
-# Copyright (c) 2008 Fabrice Douchant <Fabrice.Douchant@logilab.fr>
-# Copyright (c) 2009 Vincent
-# Copyright (c) 2009 Mads Kiilerich <mads@kiilerich.com>
-# Copyright (c) 2011-2014 Google, Inc.
-# Copyright (c) 2012 David Pursehouse <david.pursehouse@sonymobile.com>
-# Copyright (c) 2012 Kevin Jing Qiu <kevin.jing.qiu@gmail.com>
-# Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
-# Copyright (c) 2012 JT Olds <jtolds@xnet5.com>
-# Copyright (c) 2014-2018 Claudiu Popa <pcmanticore@gmail.com>
-# Copyright (c) 2014-2015 Michal Nowikowski <godfryd@gmail.com>
-# Copyright (c) 2014 Brett Cannon <brett@python.org>
-# Copyright (c) 2014 Alexandru Coman <fcoman@bitdefender.com>
-# Copyright (c) 2014 Daniel Harding <dharding@living180.net>
-# Copyright (c) 2014 Arun Persaud <arun@nubati.net>
-# Copyright (c) 2014 Dan Goldsmith <djgoldsmith@googlemail.com>
-# Copyright (c) 2015-2016 Florian Bruhin <me@the-compiler.org>
-# Copyright (c) 2015 Aru Sahni <arusahni@gmail.com>
-# Copyright (c) 2015 Steven Myint <hg@stevenmyint.com>
-# Copyright (c) 2015 Simu Toni <simutoni@gmail.com>
-# Copyright (c) 2015 Mihai Balint <balint.mihai@gmail.com>
-# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
-# Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com>
-# Copyright (c) 2016 Glenn Matthews <glenn@e-dad.net>
-# Copyright (c) 2016 Alan Evangelista <alanoe@linux.vnet.ibm.com>
-# Copyright (c) 2017-2018 Ville Skyttä <ville.skytta@iki.fi>
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
-# Copyright (c) 2017 Daniel Miller <millerdev@gmail.com>
-# Copyright (c) 2017 Roman Ivanov <me@roivanov.com>
-# Copyright (c) 2017 Ned Batchelder <ned@nedbatchelder.com>
-# Copyright (c) 2018 Randall Leeds <randall@bleeds.info>
-# Copyright (c) 2018 Mike Frysinger <vapier@gmail.com>
-# Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
-# Copyright (c) 2018 Ville Skyttä <ville.skytta@upcloud.com>
-# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
-# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
-# Copyright (c) 2018 Jason Owen <jason.a.owen@gmail.com>
-# Copyright (c) 2018 Gary Tyler McLeod <mail@garytyler.com>
-# Copyright (c) 2018 Yuval Langer <yuvallanger@mail.tau.ac.il>
-# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
-# Copyright (c) 2018 kapsh <kapsh@kap.sh>
-
-# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
-
-# pylint: disable=broad-except
-
-""" pylint [options] modules_or_packages
-
- Check that module(s) satisfy a coding standard (and more !).
-
- pylint --help
-
- Display this help message and exit.
-
- pylint --help-msg <msg-id>[,<msg-id>]
-
- Display help messages about given message identifiers and exit.
-"""
-import collections
-import contextlib
-import operator
-import os
-import sys
-import tokenize
-import traceback
-import warnings
-from io import TextIOWrapper
-
-import astroid
-from astroid import modutils
-from astroid.__pkginfo__ import version as astroid_version
-from astroid.builder import AstroidBuilder
-
-from pylint import __pkginfo__, checkers, config, exceptions, interfaces, reporters
-from pylint.__pkginfo__ import version
-from pylint.constants import MAIN_CHECKER_NAME, MSG_TYPES, OPTION_RGX
-from pylint.message import Message, MessageDefinitionStore, MessagesHandlerMixIn
-from pylint.reporters.ureports import nodes as report_nodes
-from pylint.utils import ASTWalker, FileState, utils
-
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None # type: ignore
-
-
-MANAGER = astroid.MANAGER
-
-
-def _ast_from_string(data, filepath, modname):
- cached = MANAGER.astroid_cache.get(modname)
- if cached and cached.file == filepath:
- return cached
-
- return AstroidBuilder(MANAGER).string_build(data, modname, filepath)
-
-
-def _read_stdin():
- # https://mail.python.org/pipermail/python-list/2012-November/634424.html
- sys.stdin = TextIOWrapper(sys.stdin.detach(), encoding="utf-8")
- return sys.stdin.read()
-
-
-def _get_new_args(message):
- location = (
- message.abspath,
- message.path,
- message.module,
- message.obj,
- message.line,
- message.column,
- )
- return (message.msg_id, message.symbol, location, message.msg, message.confidence)
-
-
-def _get_python_path(filepath):
- dirname = os.path.realpath(os.path.expanduser(filepath))
- if not os.path.isdir(dirname):
- dirname = os.path.dirname(dirname)
- while True:
- if not os.path.exists(os.path.join(dirname, "__init__.py")):
- return dirname
- old_dirname = dirname
- dirname = os.path.dirname(dirname)
- if old_dirname == dirname:
- return os.getcwd()
- return None
-
-
-def _merge_stats(stats):
- merged = {}
- by_msg = collections.Counter()
- for stat in stats:
- message_stats = stat.pop("by_msg", {})
- by_msg.update(message_stats)
-
- for key, item in stat.items():
- if key not in merged:
- merged[key] = item
- else:
- if isinstance(item, dict):
- merged[key].update(item)
- else:
- merged[key] = merged[key] + item
-
- merged["by_msg"] = by_msg
- return merged
-
-
-# Python Linter class #########################################################
-
-MSGS = {
- "F0001": (
- "%s",
- "fatal",
- "Used when an error occurred preventing the analysis of a \
- module (unable to find it for instance).",
- ),
- "F0002": (
- "%s: %s",
- "astroid-error",
- "Used when an unexpected error occurred while building the "
- "Astroid representation. This is usually accompanied by a "
- "traceback. Please report such errors !",
- ),
- "F0010": (
- "error while code parsing: %s",
- "parse-error",
- "Used when an exception occurred while building the Astroid "
- "representation which could be handled by astroid.",
- ),
- "I0001": (
- "Unable to run raw checkers on built-in module %s",
- "raw-checker-failed",
- "Used to inform that a built-in module has not been checked "
- "using the raw checkers.",
- ),
- "I0010": (
- "Unable to consider inline option %r",
- "bad-inline-option",
- "Used when an inline option is either badly formatted or can't "
- "be used inside modules.",
- ),
- "I0011": (
- "Locally disabling %s (%s)",
- "locally-disabled",
- "Used when an inline option disables a message or a messages category.",
- ),
- "I0013": (
- "Ignoring entire file",
- "file-ignored",
- "Used to inform that the file will not be checked",
- ),
- "I0020": (
- "Suppressed %s (from line %d)",
- "suppressed-message",
- "A message was triggered on a line, but suppressed explicitly "
- "by a disable= comment in the file. This message is not "
- "generated for messages that are ignored due to configuration "
- "settings.",
- ),
- "I0021": (
- "Useless suppression of %s",
- "useless-suppression",
- "Reported when a message is explicitly disabled for a line or "
- "a block of code, but never triggered.",
- ),
- "I0022": (
- 'Pragma "%s" is deprecated, use "%s" instead',
- "deprecated-pragma",
- "Some inline pylint options have been renamed or reworked, "
- "only the most recent form should be used. "
- "NOTE:skip-all is only available with pylint >= 0.26",
- {"old_names": [("I0014", "deprecated-disable-all")]},
- ),
- "E0001": ("%s", "syntax-error", "Used when a syntax error is raised for a module."),
- "E0011": (
- "Unrecognized file option %r",
- "unrecognized-inline-option",
- "Used when an unknown inline option is encountered.",
- ),
- "E0012": (
- "Bad option value %r",
- "bad-option-value",
- "Used when a bad value for an inline option is encountered.",
- ),
-}
-
-
-def _cpu_count() -> int:
- """Use sched_affinity if available for virtualized or containerized environments."""
- sched_getaffinity = getattr(os, "sched_getaffinity", None)
- # pylint: disable=not-callable,using-constant-test
- if sched_getaffinity:
- return len(sched_getaffinity(0))
- if multiprocessing:
- return multiprocessing.cpu_count()
- return 1
-
-
-if multiprocessing is not None:
-
- class ChildLinter(multiprocessing.Process):
- def run(self):
- # pylint: disable=no-member, unbalanced-tuple-unpacking
- tasks_queue, results_queue, self._config = self._args
-
- self._config["jobs"] = 1 # Child does not parallelize any further.
- self._python3_porting_mode = self._config.pop("python3_porting_mode", None)
- self._plugins = self._config.pop("plugins", None)
-
- # Run linter for received files/modules.
- for file_or_module in iter(tasks_queue.get, "STOP"):
- try:
- result = self._run_linter(file_or_module[0])
- results_queue.put(result)
- except Exception as ex:
- print(
- "internal error with sending report for module %s"
- % file_or_module,
- file=sys.stderr,
- )
- print(ex, file=sys.stderr)
- results_queue.put({})
-
- def _run_linter(self, file_or_module):
- linter = PyLinter()
-
- # Register standard checkers.
- linter.load_default_plugins()
- # Load command line plugins.
- if self._plugins:
- linter.load_plugin_modules(self._plugins)
-
- linter.load_configuration_from_config(self._config)
-
- # Load plugin specific configuration
- linter.load_plugin_configuration()
-
- linter.set_reporter(reporters.CollectingReporter())
-
- # Enable the Python 3 checker mode. This option is
- # passed down from the parent linter up to here, since
- # the Python 3 porting flag belongs to the Run class,
- # instead of the Linter class.
- if self._python3_porting_mode:
- linter.python3_porting_mode()
-
- # Run the checks.
- linter.check(file_or_module)
-
- msgs = [_get_new_args(m) for m in linter.reporter.messages]
- return (
- file_or_module,
- linter.file_state.base_name,
- linter.current_name,
- msgs,
- linter.stats,
- linter.msg_status,
- )
-
-
-# pylint: disable=too-many-instance-attributes,too-many-public-methods
-class PyLinter(
- config.OptionsManagerMixIn,
- MessagesHandlerMixIn,
- reporters.ReportsHandlerMixIn,
- checkers.BaseTokenChecker,
-):
- """lint Python modules using external checkers.
-
- This is the main checker controlling the other ones and the reports
- generation. It is itself both a raw checker and an astroid checker in order
- to:
- * handle message activation / deactivation at the module level
- * handle some basic but necessary stats'data (number of classes, methods...)
-
- IDE plugin developers: you may have to call
- `astroid.builder.MANAGER.astroid_cache.clear()` across runs if you want
- to ensure the latest code version is actually checked.
- """
-
- __implements__ = (interfaces.ITokenChecker,)
-
- name = MAIN_CHECKER_NAME
- priority = 0
- level = 0
- msgs = MSGS
-
- @staticmethod
- def make_options():
- return (
- (
- "ignore",
- {
- "type": "csv",
- "metavar": "<file>[,<file>...]",
- "dest": "black_list",
- "default": ("CVS",),
- "help": "Add files or directories to the blacklist. "
- "They should be base names, not paths.",
- },
- ),
- (
- "ignore-patterns",
- {
- "type": "regexp_csv",
- "metavar": "<pattern>[,<pattern>...]",
- "dest": "black_list_re",
- "default": (),
- "help": "Add files or directories matching the regex patterns to the"
- " blacklist. The regex matches against base names, not paths.",
- },
- ),
- (
- "persistent",
- {
- "default": True,
- "type": "yn",
- "metavar": "<y_or_n>",
- "level": 1,
- "help": "Pickle collected data for later comparisons.",
- },
- ),
- (
- "load-plugins",
- {
- "type": "csv",
- "metavar": "<modules>",
- "default": (),
- "level": 1,
- "help": "List of plugins (as comma separated values of "
- "python module names) to load, usually to register "
- "additional checkers.",
- },
- ),
- (
- "output-format",
- {
- "default": "text",
- "type": "string",
- "metavar": "<format>",
- "short": "f",
- "group": "Reports",
- "help": "Set the output format. Available formats are text,"
- " parseable, colorized, json and msvs (visual studio)."
- " You can also give a reporter class, e.g. mypackage.mymodule."
- "MyReporterClass.",
- },
- ),
- (
- "reports",
- {
- "default": False,
- "type": "yn",
- "metavar": "<y_or_n>",
- "short": "r",
- "group": "Reports",
- "help": "Tells whether to display a full report or only the "
- "messages.",
- },
- ),
- (
- "evaluation",
- {
- "type": "string",
- "metavar": "<python_expression>",
- "group": "Reports",
- "level": 1,
- "default": "10.0 - ((float(5 * error + warning + refactor + "
- "convention) / statement) * 10)",
- "help": "Python expression which should return a score less "
- "than or equal to 10. You have access to the variables "
- "'error', 'warning', 'refactor', and 'convention' which "
- "contain the number of messages in each category, as well as "
- "'statement' which is the total number of statements "
- "analyzed. This score is used by the global "
- "evaluation report (RP0004).",
- },
- ),
- (
- "score",
- {
- "default": True,
- "type": "yn",
- "metavar": "<y_or_n>",
- "short": "s",
- "group": "Reports",
- "help": "Activate the evaluation score.",
- },
- ),
- (
- "confidence",
- {
- "type": "multiple_choice",
- "metavar": "<levels>",
- "default": "",
- "choices": [c.name for c in interfaces.CONFIDENCE_LEVELS],
- "group": "Messages control",
- "help": "Only show warnings with the listed confidence levels."
- " Leave empty to show all. Valid levels: %s."
- % (", ".join(c.name for c in interfaces.CONFIDENCE_LEVELS),),
- },
- ),
- (
- "enable",
- {
- "type": "csv",
- "metavar": "<msg ids>",
- "short": "e",
- "group": "Messages control",
- "help": "Enable the message, report, category or checker with the "
- "given id(s). You can either give multiple identifier "
- "separated by comma (,) or put this option multiple time "
- "(only on the command line, not in the configuration file "
- "where it should appear only once). "
- 'See also the "--disable" option for examples.',
- },
- ),
- (
- "disable",
- {
- "type": "csv",
- "metavar": "<msg ids>",
- "short": "d",
- "group": "Messages control",
- "help": "Disable the message, report, category or checker "
- "with the given id(s). You can either give multiple identifiers "
- "separated by comma (,) or put this option multiple times "
- "(only on the command line, not in the configuration file "
- "where it should appear only once). "
- 'You can also use "--disable=all" to disable everything first '
- "and then reenable specific checks. For example, if you want "
- "to run only the similarities checker, you can use "
- '"--disable=all --enable=similarities". '
- "If you want to run only the classes checker, but have no "
- "Warning level messages displayed, use "
- '"--disable=all --enable=classes --disable=W".',
- },
- ),
- (
- "msg-template",
- {
- "type": "string",
- "metavar": "<template>",
- "group": "Reports",
- "help": (
- "Template used to display messages. "
- "This is a python new-style format string "
- "used to format the message information. "
- "See doc for all details."
- ),
- },
- ),
- (
- "jobs",
- {
- "type": "int",
- "metavar": "<n-processes>",
- "short": "j",
- "default": 1,
- "help": "Use multiple processes to speed up Pylint. Specifying 0 will "
- "auto-detect the number of processors available to use.",
- },
- ),
- (
- "unsafe-load-any-extension",
- {
- "type": "yn",
- "metavar": "<yn>",
- "default": False,
- "hide": True,
- "help": (
- "Allow loading of arbitrary C extensions. Extensions"
- " are imported into the active Python interpreter and"
- " may run arbitrary code."
- ),
- },
- ),
- (
- "limit-inference-results",
- {
- "type": "int",
- "metavar": "<number-of-results>",
- "default": 100,
- "help": (
- "Control the amount of potential inferred values when inferring "
- "a single object. This can help the performance when dealing with "
- "large functions or complex, nested conditions. "
- ),
- },
- ),
- (
- "extension-pkg-whitelist",
- {
- "type": "csv",
- "metavar": "<pkg[,pkg]>",
- "default": [],
- "help": (
- "A comma-separated list of package or module names"
- " from where C extensions may be loaded. Extensions are"
- " loading into the active Python interpreter and may run"
- " arbitrary code."
- ),
- },
- ),
- (
- "suggestion-mode",
- {
- "type": "yn",
- "metavar": "<yn>",
- "default": True,
- "help": (
- "When enabled, pylint would attempt to guess common "
- "misconfiguration and emit user-friendly hints instead "
- "of false-positive error messages."
- ),
- },
- ),
- (
- "exit-zero",
- {
- "action": "store_true",
- "help": (
- "Always return a 0 (non-error) status code, even if "
- "lint errors are found. This is primarily useful in "
- "continuous integration scripts."
- ),
- },
- ),
- (
- "from-stdin",
- {
- "action": "store_true",
- "help": (
- "Interpret the stdin as a python script, whose filename "
- "needs to be passed as the module_or_package argument."
- ),
- },
- ),
- )
-
- option_groups = (
- ("Messages control", "Options controlling analysis messages"),
- ("Reports", "Options related to output formatting and reporting"),
- )
-
- def __init__(self, options=(), reporter=None, option_groups=(), pylintrc=None):
- # some stuff has to be done before ancestors initialization...
- #
- # messages store / checkers / reporter / astroid manager
- self.msgs_store = MessageDefinitionStore()
- self.reporter = None
- self._reporter_name = None
- self._reporters = {}
- self._checkers = collections.defaultdict(list)
- self._pragma_lineno = {}
- self._ignore_file = False
- # visit variables
- self.file_state = FileState()
- self.current_name = None
- self.current_file = None
- self.stats = None
- # init options
- self._external_opts = options
- self.options = options + PyLinter.make_options()
- self.option_groups = option_groups + PyLinter.option_groups
- self._options_methods = {"enable": self.enable, "disable": self.disable}
- self._bw_options_methods = {
- "disable-msg": self.disable,
- "enable-msg": self.enable,
- }
- full_version = "pylint %s\nastroid %s\nPython %s" % (
- version,
- astroid_version,
- sys.version,
- )
- MessagesHandlerMixIn.__init__(self)
- reporters.ReportsHandlerMixIn.__init__(self)
- super(PyLinter, self).__init__(
- usage=__doc__, version=full_version, config_file=pylintrc or config.PYLINTRC
- )
- checkers.BaseTokenChecker.__init__(self)
- # provided reports
- self.reports = (
- ("RP0001", "Messages by category", report_total_messages_stats),
- (
- "RP0002",
- "% errors / warnings by module",
- report_messages_by_module_stats,
- ),
- ("RP0003", "Messages", report_messages_stats),
- )
- self.register_checker(self)
- self._dynamic_plugins = set()
- self._python3_porting_mode = False
- self._error_mode = False
- self.load_provider_defaults()
- if reporter:
- self.set_reporter(reporter)
-
- def load_default_plugins(self):
- checkers.initialize(self)
- reporters.initialize(self)
- # Make sure to load the default reporter, because
- # the option has been set before the plugins had been loaded.
- if not self.reporter:
- self._load_reporter()
-
- def load_plugin_modules(self, modnames):
- """take a list of module names which are pylint plugins and load
- and register them
- """
- for modname in modnames:
- if modname in self._dynamic_plugins:
- continue
- self._dynamic_plugins.add(modname)
- module = modutils.load_module_from_name(modname)
- module.register(self)
-
- def load_plugin_configuration(self):
- """Call the configuration hook for plugins
-
- This walks through the list of plugins, grabs the "load_configuration"
- hook, if exposed, and calls it to allow plugins to configure specific
- settings.
- """
- for modname in self._dynamic_plugins:
- module = modutils.load_module_from_name(modname)
- if hasattr(module, "load_configuration"):
- module.load_configuration(self)
-
- def _load_reporter(self):
- name = self._reporter_name.lower()
- if name in self._reporters:
- self.set_reporter(self._reporters[name]())
- else:
- try:
- reporter_class = self._load_reporter_class()
- except (ImportError, AttributeError):
- raise exceptions.InvalidReporterError(name)
- else:
- self.set_reporter(reporter_class())
-
- def _load_reporter_class(self):
- qname = self._reporter_name
- module = modutils.load_module_from_name(modutils.get_module_part(qname))
- class_name = qname.split(".")[-1]
- reporter_class = getattr(module, class_name)
- return reporter_class
-
- def set_reporter(self, reporter):
- """set the reporter used to display messages and reports"""
- self.reporter = reporter
- reporter.linter = self
-
- def set_option(self, optname, value, action=None, optdict=None):
- """overridden from config.OptionsProviderMixin to handle some
- special options
- """
- if optname in self._options_methods or optname in self._bw_options_methods:
- if value:
- try:
- meth = self._options_methods[optname]
- except KeyError:
- meth = self._bw_options_methods[optname]
- warnings.warn(
- "%s is deprecated, replace it by %s"
- % (optname, optname.split("-")[0]),
- DeprecationWarning,
- )
- value = utils._check_csv(value)
- if isinstance(value, (list, tuple)):
- for _id in value:
- meth(_id, ignore_unknown=True)
- else:
- meth(value)
- return # no need to call set_option, disable/enable methods do it
- elif optname == "output-format":
- self._reporter_name = value
- # If the reporters are already available, load
- # the reporter class.
- if self._reporters:
- self._load_reporter()
-
- try:
- checkers.BaseTokenChecker.set_option(self, optname, value, action, optdict)
- except config.UnsupportedAction:
- print("option %s can't be read from config file" % optname, file=sys.stderr)
-
- def register_reporter(self, reporter_class):
- self._reporters[reporter_class.name] = reporter_class
-
- def report_order(self):
- reports = sorted(self._reports, key=lambda x: getattr(x, "name", ""))
- try:
- # Remove the current reporter and add it
- # at the end of the list.
- reports.pop(reports.index(self))
- except ValueError:
- pass
- else:
- reports.append(self)
- return reports
-
- # checkers manipulation methods ############################################
-
- def register_checker(self, checker):
- """register a new checker
-
- checker is an object implementing IRawChecker or / and IAstroidChecker
- """
- assert checker.priority <= 0, "checker priority can't be >= 0"
- self._checkers[checker.name].append(checker)
- for r_id, r_title, r_cb in checker.reports:
- self.register_report(r_id, r_title, r_cb, checker)
- self.register_options_provider(checker)
- if hasattr(checker, "msgs"):
- self.msgs_store.register_messages_from_checker(checker)
- checker.load_defaults()
-
- # Register the checker, but disable all of its messages.
- if not getattr(checker, "enabled", True):
- self.disable(checker.name)
-
- def disable_noerror_messages(self):
- for msgcat, msgids in self.msgs_store._msgs_by_category.items():
- # enable only messages with 'error' severity and above ('fatal')
- if msgcat in ["E", "F"]:
- for msgid in msgids:
- self.enable(msgid)
- else:
- for msgid in msgids:
- self.disable(msgid)
-
- def disable_reporters(self):
- """disable all reporters"""
- for _reporters in self._reports.values():
- for report_id, _, _ in _reporters:
- self.disable_report(report_id)
-
- def error_mode(self):
- """error mode: enable only errors; no reports, no persistent"""
- self._error_mode = True
- self.disable_noerror_messages()
- self.disable("miscellaneous")
- if self._python3_porting_mode:
- self.disable("all")
- for msg_id in self._checker_messages("python3"):
- if msg_id.startswith("E"):
- self.enable(msg_id)
- config_parser = self.cfgfile_parser
- if config_parser.has_option("MESSAGES CONTROL", "disable"):
- value = config_parser.get("MESSAGES CONTROL", "disable")
- self.global_set_option("disable", value)
- else:
- self.disable("python3")
- self.set_option("reports", False)
- self.set_option("persistent", False)
- self.set_option("score", False)
-
- def python3_porting_mode(self):
- """Disable all other checkers and enable Python 3 warnings."""
- self.disable("all")
- self.enable("python3")
- if self._error_mode:
- # The error mode was activated, using the -E flag.
- # So we'll need to enable only the errors from the
- # Python 3 porting checker.
- for msg_id in self._checker_messages("python3"):
- if msg_id.startswith("E"):
- self.enable(msg_id)
- else:
- self.disable(msg_id)
- config_parser = self.cfgfile_parser
- if config_parser.has_option("MESSAGES CONTROL", "disable"):
- value = config_parser.get("MESSAGES CONTROL", "disable")
- self.global_set_option("disable", value)
- self._python3_porting_mode = True
-
- def list_messages_enabled(self):
- enabled = [
- " %s (%s)" % (message.symbol, message.msgid)
- for message in self.msgs_store.messages
- if self.is_message_enabled(message.msgid)
- ]
- disabled = [
- " %s (%s)" % (message.symbol, message.msgid)
- for message in self.msgs_store.messages
- if not self.is_message_enabled(message.msgid)
- ]
- print("Enabled messages:")
- for msg in sorted(enabled):
- print(msg)
- print("\nDisabled messages:")
- for msg in sorted(disabled):
- print(msg)
- print("")
-
- # block level option handling #############################################
- #
- # see func_block_disable_msg.py test case for expected behaviour
-
- def process_tokens(self, tokens):
- """process tokens from the current module to search for module/block
- level options
- """
- control_pragmas = {"disable", "enable"}
- prev_line = None
- saw_newline = True
- seen_newline = True
- for (tok_type, content, start, _, _) in tokens:
- if prev_line and prev_line != start[0]:
- saw_newline = seen_newline
- seen_newline = False
-
- prev_line = start[0]
- if tok_type in (tokenize.NL, tokenize.NEWLINE):
- seen_newline = True
-
- if tok_type != tokenize.COMMENT:
- continue
- match = OPTION_RGX.search(content)
- if match is None:
- continue
-
- first_group = match.group(1)
- if (
- first_group.strip() == "disable-all"
- or first_group.strip() == "skip-file"
- ):
- if first_group.strip() == "disable-all":
- self.add_message(
- "deprecated-pragma",
- line=start[0],
- args=("disable-all", "skip-file"),
- )
- self.add_message("file-ignored", line=start[0])
- self._ignore_file = True
- return
- try:
- opt, value = first_group.split("=", 1)
- except ValueError:
- self.add_message(
- "bad-inline-option", args=first_group.strip(), line=start[0]
- )
- continue
- opt = opt.strip()
- if opt in self._options_methods or opt in self._bw_options_methods:
- try:
- meth = self._options_methods[opt]
- except KeyError:
- meth = self._bw_options_methods[opt]
- # found a "(dis|en)able-msg" pragma deprecated suppression
- self.add_message(
- "deprecated-pragma",
- line=start[0],
- args=(opt, opt.replace("-msg", "")),
- )
- for msgid in utils._splitstrip(value):
- # Add the line where a control pragma was encountered.
- if opt in control_pragmas:
- self._pragma_lineno[msgid] = start[0]
-
- try:
- if (opt, msgid) == ("disable", "all"):
- self.add_message(
- "deprecated-pragma",
- line=start[0],
- args=("disable=all", "skip-file"),
- )
- self.add_message("file-ignored", line=start[0])
- self._ignore_file = True
- return
- # If we did not see a newline between the previous line and now,
- # we saw a backslash so treat the two lines as one.
- if not saw_newline:
- meth(msgid, "module", start[0] - 1)
- meth(msgid, "module", start[0])
- except exceptions.UnknownMessageError:
- self.add_message("bad-option-value", args=msgid, line=start[0])
- else:
- self.add_message("unrecognized-inline-option", args=opt, line=start[0])
-
- # code checking methods ###################################################
-
- def get_checkers(self):
- """return all available checkers as a list"""
- return [self] + [
- c
- for _checkers in self._checkers.values()
- for c in _checkers
- if c is not self
- ]
-
- def get_checker_names(self):
- """Get all the checker names that this linter knows about."""
- current_checkers = self.get_checkers()
- return sorted(
- {
- checker.name
- for checker in current_checkers
- if checker.name != MAIN_CHECKER_NAME
- }
- )
-
- def prepare_checkers(self):
- """return checkers needed for activated messages and reports"""
- if not self.config.reports:
- self.disable_reporters()
- # get needed checkers
- needed_checkers = [self]
- for checker in self.get_checkers()[1:]:
- messages = {msg for msg in checker.msgs if self.is_message_enabled(msg)}
- if messages or any(self.report_is_enabled(r[0]) for r in checker.reports):
- needed_checkers.append(checker)
- # Sort checkers by priority
- needed_checkers = sorted(
- needed_checkers, key=operator.attrgetter("priority"), reverse=True
- )
- return needed_checkers
-
- # pylint: disable=unused-argument
- @staticmethod
- def should_analyze_file(modname, path, is_argument=False):
- """Returns whether or not a module should be checked.
-
- This implementation returns True for all python source file, indicating
- that all files should be linted.
-
- Subclasses may override this method to indicate that modules satisfying
- certain conditions should not be linted.
-
- :param str modname: The name of the module to be checked.
- :param str path: The full path to the source code of the module.
- :param bool is_argument: Whetter the file is an argument to pylint or not.
- Files which respect this property are always
- checked, since the user requested it explicitly.
- :returns: True if the module should be checked.
- :rtype: bool
- """
- if is_argument:
- return True
- return path.endswith(".py")
-
- # pylint: enable=unused-argument
-
- def check(self, files_or_modules):
- """main checking entry: check a list of files or modules from their
- name.
- """
- # initialize msgs_state now that all messages have been registered into
- # the store
- for msg in self.msgs_store.messages:
- if not msg.may_be_emitted():
- self._msgs_state[msg.msgid] = False
-
- if not isinstance(files_or_modules, (list, tuple)):
- files_or_modules = (files_or_modules,)
-
- if self.config.jobs == 1:
- self._do_check(files_or_modules)
- else:
- self._parallel_check(files_or_modules)
-
- def _get_jobs_config(self):
- child_config = collections.OrderedDict()
- filter_options = {"long-help"}
- filter_options.update((opt_name for opt_name, _ in self._external_opts))
- for opt_providers in self._all_options.values():
- for optname, optdict, val in opt_providers.options_and_values():
- if optdict.get("deprecated"):
- continue
-
- if optname not in filter_options:
- child_config[optname] = utils._format_option_value(optdict, val)
- child_config["python3_porting_mode"] = self._python3_porting_mode
- child_config["plugins"] = self._dynamic_plugins
- return child_config
-
- def _parallel_task(self, files_or_modules):
- # Prepare configuration for child linters.
- child_config = self._get_jobs_config()
-
- children = []
- manager = multiprocessing.Manager()
- tasks_queue = manager.Queue()
- results_queue = manager.Queue()
-
- # Send files to child linters.
- expanded_files = []
- for descr in self.expand_files(files_or_modules):
- modname, filepath, is_arg = descr["name"], descr["path"], descr["isarg"]
- if self.should_analyze_file(modname, filepath, is_argument=is_arg):
- expanded_files.append(descr)
-
- # do not start more jobs than needed
- for _ in range(min(self.config.jobs, len(expanded_files))):
- child_linter = ChildLinter(args=(tasks_queue, results_queue, child_config))
- child_linter.start()
- children.append(child_linter)
-
- for files_or_module in expanded_files:
- path = files_or_module["path"]
- tasks_queue.put([path])
-
- # collect results from child linters
- failed = False
- for _ in expanded_files:
- try:
- result = results_queue.get()
- except Exception as ex:
- print(
- "internal error while receiving results from child linter",
- file=sys.stderr,
- )
- print(ex, file=sys.stderr)
- failed = True
- break
- yield result
-
- # Stop child linters and wait for their completion.
- for _ in range(self.config.jobs):
- tasks_queue.put("STOP")
- for child in children:
- child.join()
-
- if failed:
- print("Error occurred, stopping the linter.", file=sys.stderr)
- sys.exit(32)
-
- def _parallel_check(self, files_or_modules):
- # Reset stats.
- self.open()
-
- all_stats = []
- module = None
- for result in self._parallel_task(files_or_modules):
- if not result:
- continue
- (_, self.file_state.base_name, module, messages, stats, msg_status) = result
-
- for msg in messages:
- msg = Message(*msg)
- self.set_current_module(module)
- self.reporter.handle_message(msg)
-
- all_stats.append(stats)
- self.msg_status |= msg_status
-
- self.stats = _merge_stats(all_stats)
- self.current_name = module
-
- # Insert stats data to local checkers.
- for checker in self.get_checkers():
- if checker is not self:
- checker.stats = self.stats
-
- def _do_check(self, files_or_modules):
- walker = ASTWalker(self)
- _checkers = self.prepare_checkers()
- tokencheckers = [
- c
- for c in _checkers
- if interfaces.implements(c, interfaces.ITokenChecker) and c is not self
- ]
- rawcheckers = [
- c for c in _checkers if interfaces.implements(c, interfaces.IRawChecker)
- ]
- # notify global begin
- for checker in _checkers:
- checker.open()
- if interfaces.implements(checker, interfaces.IAstroidChecker):
- walker.add_checker(checker)
- # build ast and check modules or packages
- if self.config.from_stdin:
- if len(files_or_modules) != 1:
- raise exceptions.InvalidArgsError(
- "Missing filename required for --from-stdin"
- )
-
- filepath = files_or_modules[0]
- try:
- # Note that this function does not really perform an
- # __import__ but may raise an ImportError exception, which
- # we want to catch here.
- modname = ".".join(modutils.modpath_from_file(filepath))
- except ImportError:
- modname = os.path.splitext(os.path.basename(filepath))[0]
-
- self.set_current_module(modname, filepath)
-
- # get the module representation
- ast_node = _ast_from_string(_read_stdin(), filepath, modname)
-
- if ast_node is not None:
- self.file_state = FileState(filepath)
- self.check_astroid_module(ast_node, walker, rawcheckers, tokencheckers)
- # warn about spurious inline messages handling
- spurious_messages = self.file_state.iter_spurious_suppression_messages(
- self.msgs_store
- )
- for msgid, line, args in spurious_messages:
- self.add_message(msgid, line, None, args)
- else:
- for descr in self.expand_files(files_or_modules):
- modname, filepath, is_arg = descr["name"], descr["path"], descr["isarg"]
- if not self.should_analyze_file(modname, filepath, is_argument=is_arg):
- continue
-
- self.set_current_module(modname, filepath)
- # get the module representation
- ast_node = self.get_ast(filepath, modname)
- if ast_node is None:
- continue
-
- self.file_state = FileState(descr["basename"])
- self._ignore_file = False
- # fix the current file (if the source file was not available or
- # if it's actually a c extension)
- self.current_file = ast_node.file # pylint: disable=maybe-no-member
- before_check_statements = walker.nbstatements
- self.check_astroid_module(ast_node, walker, rawcheckers, tokencheckers)
- self.stats["by_module"][modname]["statement"] = (
- walker.nbstatements - before_check_statements
- )
- # warn about spurious inline messages handling
- spurious_messages = self.file_state.iter_spurious_suppression_messages(
- self.msgs_store
- )
- for msgid, line, args in spurious_messages:
- self.add_message(msgid, line, None, args)
- # notify global end
- self.stats["statement"] = walker.nbstatements
- for checker in reversed(_checkers):
- checker.close()
-
- def expand_files(self, modules):
- """get modules and errors from a list of modules and handle errors
- """
- result, errors = utils.expand_modules(
- modules, self.config.black_list, self.config.black_list_re
- )
- for error in errors:
- message = modname = error["mod"]
- key = error["key"]
- self.set_current_module(modname)
- if key == "fatal":
- message = str(error["ex"]).replace(os.getcwd() + os.sep, "")
- self.add_message(key, args=message)
- return result
-
- def set_current_module(self, modname, filepath=None):
- """set the name of the currently analyzed module and
- init statistics for it
- """
- if not modname and filepath is None:
- return
- self.reporter.on_set_current_module(modname, filepath)
- self.current_name = modname
- self.current_file = filepath or modname
- self.stats["by_module"][modname] = {}
- self.stats["by_module"][modname]["statement"] = 0
- for msg_cat in MSG_TYPES.values():
- self.stats["by_module"][modname][msg_cat] = 0
-
- def get_ast(self, filepath, modname):
- """return an ast(roid) representation for a module"""
- try:
- return MANAGER.ast_from_file(filepath, modname, source=True)
- except astroid.AstroidSyntaxError as ex:
- # pylint: disable=no-member
- self.add_message(
- "syntax-error",
- line=getattr(ex.error, "lineno", 0),
- col_offset=getattr(ex.error, "offset", None),
- args=str(ex.error),
- )
- except astroid.AstroidBuildingException as ex:
- self.add_message("parse-error", args=ex)
- except Exception as ex:
- traceback.print_exc()
- self.add_message("astroid-error", args=(ex.__class__, ex))
-
- def check_astroid_module(self, ast_node, walker, rawcheckers, tokencheckers):
- """Check a module from its astroid representation."""
- try:
- tokens = utils.tokenize_module(ast_node)
- except tokenize.TokenError as ex:
- self.add_message("syntax-error", line=ex.args[1][0], args=ex.args[0])
- return None
-
- if not ast_node.pure_python:
- self.add_message("raw-checker-failed", args=ast_node.name)
- else:
- # assert astroid.file.endswith('.py')
- # invoke ITokenChecker interface on self to fetch module/block
- # level options
- self.process_tokens(tokens)
- if self._ignore_file:
- return False
- # walk ast to collect line numbers
- self.file_state.collect_block_lines(self.msgs_store, ast_node)
- # run raw and tokens checkers
- for checker in rawcheckers:
- checker.process_module(ast_node)
- for checker in tokencheckers:
- checker.process_tokens(tokens)
- # generate events to astroid checkers
- walker.walk(ast_node)
- return True
-
- # IAstroidChecker interface #################################################
-
- def open(self):
- """initialize counters"""
- self.stats = {"by_module": {}, "by_msg": {}}
- MANAGER.always_load_extensions = self.config.unsafe_load_any_extension
- MANAGER.max_inferable_values = self.config.limit_inference_results
- MANAGER.extension_package_whitelist.update(self.config.extension_pkg_whitelist)
- for msg_cat in MSG_TYPES.values():
- self.stats[msg_cat] = 0
-
- def generate_reports(self):
- """close the whole package /module, it's time to make reports !
-
- if persistent run, pickle results for later comparison
- """
- # Display whatever messages are left on the reporter.
- self.reporter.display_messages(report_nodes.Section())
-
- if self.file_state.base_name is not None:
- # load previous results if any
- previous_stats = config.load_results(self.file_state.base_name)
- self.reporter.on_close(self.stats, previous_stats)
- if self.config.reports:
- sect = self.make_reports(self.stats, previous_stats)
- else:
- sect = report_nodes.Section()
-
- if self.config.reports:
- self.reporter.display_reports(sect)
- self._report_evaluation()
- # save results if persistent run
- if self.config.persistent:
- config.save_results(self.stats, self.file_state.base_name)
- else:
- self.reporter.on_close(self.stats, {})
-
- def _report_evaluation(self):
- """make the global evaluation report"""
- # check with at least check 1 statements (usually 0 when there is a
- # syntax error preventing pylint from further processing)
- previous_stats = config.load_results(self.file_state.base_name)
- if self.stats["statement"] == 0:
- return
-
- # get a global note for the code
- evaluation = self.config.evaluation
- try:
- note = eval(evaluation, {}, self.stats) # pylint: disable=eval-used
- except Exception as ex:
- msg = "An exception occurred while rating: %s" % ex
- else:
- self.stats["global_note"] = note
- msg = "Your code has been rated at %.2f/10" % note
- pnote = previous_stats.get("global_note")
- if pnote is not None:
- msg += " (previous run: %.2f/10, %+.2f)" % (pnote, note - pnote)
-
- if self.config.score:
- sect = report_nodes.EvaluationSection(msg)
- self.reporter.display_reports(sect)
-
-
-# some reporting functions ####################################################
-
-
-def report_total_messages_stats(sect, stats, previous_stats):
- """make total errors / warnings report"""
- lines = ["type", "number", "previous", "difference"]
- lines += checkers.table_lines_from_stats(
- stats, previous_stats, ("convention", "refactor", "warning", "error")
- )
- sect.append(report_nodes.Table(children=lines, cols=4, rheaders=1))
-
-
-def report_messages_stats(sect, stats, _):
- """make messages type report"""
- if not stats["by_msg"]:
- # don't print this report when we didn't detected any errors
- raise exceptions.EmptyReportError()
- in_order = sorted(
- [
- (value, msg_id)
- for msg_id, value in stats["by_msg"].items()
- if not msg_id.startswith("I")
- ]
- )
- in_order.reverse()
- lines = ("message id", "occurrences")
- for value, msg_id in in_order:
- lines += (msg_id, str(value))
- sect.append(report_nodes.Table(children=lines, cols=2, rheaders=1))
-
-
-def report_messages_by_module_stats(sect, stats, _):
- """make errors / warnings by modules report"""
- if len(stats["by_module"]) == 1:
- # don't print this report when we are analysing a single module
- raise exceptions.EmptyReportError()
- by_mod = collections.defaultdict(dict)
- for m_type in ("fatal", "error", "warning", "refactor", "convention"):
- total = stats[m_type]
- for module in stats["by_module"].keys():
- mod_total = stats["by_module"][module][m_type]
- if total == 0:
- percent = 0
- else:
- percent = float((mod_total) * 100) / total
- by_mod[module][m_type] = percent
- sorted_result = []
- for module, mod_info in by_mod.items():
- sorted_result.append(
- (
- mod_info["error"],
- mod_info["warning"],
- mod_info["refactor"],
- mod_info["convention"],
- module,
- )
- )
- sorted_result.sort()
- sorted_result.reverse()
- lines = ["module", "error", "warning", "refactor", "convention"]
- for line in sorted_result:
- # Don't report clean modules.
- if all(entry == 0 for entry in line[:-1]):
- continue
- lines.append(line[-1])
- for val in line[:-1]:
- lines.append("%.2f" % val)
- if len(lines) == 5:
- raise exceptions.EmptyReportError()
- sect.append(report_nodes.Table(children=lines, cols=5, rheaders=1))
-
-
-# utilities ###################################################################
-
-
-class ArgumentPreprocessingError(Exception):
- """Raised if an error occurs during argument preprocessing."""
-
-
-def preprocess_options(args, search_for):
- """look for some options (keys of <search_for>) which have to be processed
- before others
-
- values of <search_for> are callback functions to call when the option is
- found
- """
- i = 0
- while i < len(args):
- arg = args[i]
- if arg.startswith("--"):
- try:
- option, val = arg[2:].split("=", 1)
- except ValueError:
- option, val = arg[2:], None
- try:
- cb, takearg = search_for[option]
- except KeyError:
- i += 1
- else:
- del args[i]
- if takearg and val is None:
- if i >= len(args) or args[i].startswith("-"):
- msg = "Option %s expects a value" % option
- raise ArgumentPreprocessingError(msg)
- val = args[i]
- del args[i]
- elif not takearg and val is not None:
- msg = "Option %s doesn't expects a value" % option
- raise ArgumentPreprocessingError(msg)
- cb(option, val)
- else:
- i += 1
-
-
-@contextlib.contextmanager
-def fix_import_path(args):
- """Prepare sys.path for running the linter checks.
-
- Within this context, each of the given arguments is importable.
- Paths are added to sys.path in corresponding order to the arguments.
- We avoid adding duplicate directories to sys.path.
- `sys.path` is reset to its original value upon exiting this context.
- """
- orig = list(sys.path)
- changes = []
- for arg in args:
- path = _get_python_path(arg)
- if path not in changes:
- changes.append(path)
- sys.path[:] = changes + ["."] + sys.path
- try:
- yield
- finally:
- sys.path[:] = orig
-
-
-class Run:
- """helper class to use as main for pylint :
-
- run(*sys.argv[1:])
- """
-
- LinterClass = PyLinter
- option_groups = (
- (
- "Commands",
- "Options which are actually commands. Options in this \
-group are mutually exclusive.",
- ),
- )
-
- def __init__(self, args, reporter=None, do_exit=True):
- self._rcfile = None
- self._plugins = []
- self.verbose = None
- try:
- preprocess_options(
- args,
- {
- # option: (callback, takearg)
- "init-hook": (cb_init_hook, True),
- "rcfile": (self.cb_set_rcfile, True),
- "load-plugins": (self.cb_add_plugins, True),
- "verbose": (self.cb_verbose_mode, False),
- },
- )
- except ArgumentPreprocessingError as ex:
- print(ex, file=sys.stderr)
- sys.exit(32)
-
- self.linter = linter = self.LinterClass(
- (
- (
- "rcfile",
- {
- "action": "callback",
- "callback": lambda *args: 1,
- "type": "string",
- "metavar": "<file>",
- "help": "Specify a configuration file.",
- },
- ),
- (
- "init-hook",
- {
- "action": "callback",
- "callback": lambda *args: 1,
- "type": "string",
- "metavar": "<code>",
- "level": 1,
- "help": "Python code to execute, usually for sys.path "
- "manipulation such as pygtk.require().",
- },
- ),
- (
- "help-msg",
- {
- "action": "callback",
- "type": "string",
- "metavar": "<msg-id>",
- "callback": self.cb_help_message,
- "group": "Commands",
- "help": "Display a help message for the given message id and "
- "exit. The value may be a comma separated list of message ids.",
- },
- ),
- (
- "list-msgs",
- {
- "action": "callback",
- "metavar": "<msg-id>",
- "callback": self.cb_list_messages,
- "group": "Commands",
- "level": 1,
- "help": "Generate pylint's messages.",
- },
- ),
- (
- "list-msgs-enabled",
- {
- "action": "callback",
- "metavar": "<msg-id>",
- "callback": self.cb_list_messages_enabled,
- "group": "Commands",
- "level": 1,
- "help": "Display a list of what messages are enabled "
- "and disabled with the given configuration.",
- },
- ),
- (
- "list-groups",
- {
- "action": "callback",
- "metavar": "<msg-id>",
- "callback": self.cb_list_groups,
- "group": "Commands",
- "level": 1,
- "help": "List pylint's message groups.",
- },
- ),
- (
- "list-conf-levels",
- {
- "action": "callback",
- "callback": cb_list_confidence_levels,
- "group": "Commands",
- "level": 1,
- "help": "Generate pylint's confidence levels.",
- },
- ),
- (
- "full-documentation",
- {
- "action": "callback",
- "metavar": "<msg-id>",
- "callback": self.cb_full_documentation,
- "group": "Commands",
- "level": 1,
- "help": "Generate pylint's full documentation.",
- },
- ),
- (
- "generate-rcfile",
- {
- "action": "callback",
- "callback": self.cb_generate_config,
- "group": "Commands",
- "help": "Generate a sample configuration file according to "
- "the current configuration. You can put other options "
- "before this one to get them in the generated "
- "configuration.",
- },
- ),
- (
- "generate-man",
- {
- "action": "callback",
- "callback": self.cb_generate_manpage,
- "group": "Commands",
- "help": "Generate pylint's man page.",
- "hide": True,
- },
- ),
- (
- "errors-only",
- {
- "action": "callback",
- "callback": self.cb_error_mode,
- "short": "E",
- "help": "In error mode, checkers without error messages are "
- "disabled and for others, only the ERROR messages are "
- "displayed, and no reports are done by default.",
- },
- ),
- (
- "py3k",
- {
- "action": "callback",
- "callback": self.cb_python3_porting_mode,
- "help": "In Python 3 porting mode, all checkers will be "
- "disabled and only messages emitted by the porting "
- "checker will be displayed.",
- },
- ),
- (
- "verbose",
- {
- "action": "callback",
- "callback": self.cb_verbose_mode,
- "short": "v",
- "help": "In verbose mode, extra non-checker-related info "
- "will be displayed.",
- },
- ),
- ),
- option_groups=self.option_groups,
- pylintrc=self._rcfile,
- )
- # register standard checkers
- linter.load_default_plugins()
- # load command line plugins
- linter.load_plugin_modules(self._plugins)
- # add some help section
- linter.add_help_section("Environment variables", config.ENV_HELP, level=1)
- # pylint: disable=bad-continuation
- linter.add_help_section(
- "Output",
- "Using the default text output, the message format is : \n"
- " \n"
- " MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE \n"
- " \n"
- "There are 5 kind of message types : \n"
- " * (C) convention, for programming standard violation \n"
- " * (R) refactor, for bad code smell \n"
- " * (W) warning, for python specific problems \n"
- " * (E) error, for probable bugs in the code \n"
- " * (F) fatal, if an error occurred which prevented pylint from doing further\n"
- "processing.\n",
- level=1,
- )
- linter.add_help_section(
- "Output status code",
- "Pylint should leave with following status code: \n"
- " * 0 if everything went fine \n"
- " * 1 if a fatal message was issued \n"
- " * 2 if an error message was issued \n"
- " * 4 if a warning message was issued \n"
- " * 8 if a refactor message was issued \n"
- " * 16 if a convention message was issued \n"
- " * 32 on usage error \n"
- " \n"
- "status 1 to 16 will be bit-ORed so you can know which different categories has\n"
- "been issued by analysing pylint output status code\n",
- level=1,
- )
- # read configuration
- linter.disable("I")
- linter.enable("c-extension-no-member")
- linter.read_config_file(verbose=self.verbose)
- config_parser = linter.cfgfile_parser
- # run init hook, if present, before loading plugins
- if config_parser.has_option("MASTER", "init-hook"):
- cb_init_hook(
- "init-hook", utils._unquote(config_parser.get("MASTER", "init-hook"))
- )
- # is there some additional plugins in the file configuration, in
- if config_parser.has_option("MASTER", "load-plugins"):
- plugins = utils._splitstrip(config_parser.get("MASTER", "load-plugins"))
- linter.load_plugin_modules(plugins)
- # now we can load file config and command line, plugins (which can
- # provide options) have been registered
- linter.load_config_file()
-
- if reporter:
- # if a custom reporter is provided as argument, it may be overridden
- # by file parameters, so re-set it here, but before command line
- # parsing so it's still overrideable by command line option
- linter.set_reporter(reporter)
- try:
- args = linter.load_command_line_configuration(args)
- except SystemExit as exc:
- if exc.code == 2: # bad options
- exc.code = 32
- raise
- if not args:
- print(linter.help())
- sys.exit(32)
-
- if linter.config.jobs < 0:
- print(
- "Jobs number (%d) should be greater than or equal to 0"
- % linter.config.jobs,
- file=sys.stderr,
- )
- sys.exit(32)
- if linter.config.jobs > 1 or linter.config.jobs == 0:
- if multiprocessing is None:
- print(
- "Multiprocessing library is missing, " "fallback to single process",
- file=sys.stderr,
- )
- linter.set_option("jobs", 1)
- else:
- if linter.config.jobs == 0:
- linter.config.jobs = _cpu_count()
-
- # We have loaded configuration from config file and command line. Now, we can
- # load plugin specific configuration.
- linter.load_plugin_configuration()
-
- # insert current working directory to the python path to have a correct
- # behaviour
- with fix_import_path(args):
- linter.check(args)
- linter.generate_reports()
- if do_exit:
- if linter.config.exit_zero:
- sys.exit(0)
- else:
- sys.exit(self.linter.msg_status)
-
- def cb_set_rcfile(self, name, value):
- """callback for option preprocessing (i.e. before option parsing)"""
- self._rcfile = value
-
- def cb_add_plugins(self, name, value):
- """callback for option preprocessing (i.e. before option parsing)"""
- self._plugins.extend(utils._splitstrip(value))
-
- def cb_error_mode(self, *args, **kwargs):
- """error mode:
- * disable all but error messages
- * disable the 'miscellaneous' checker which can be safely deactivated in
- debug
- * disable reports
- * do not save execution information
- """
- self.linter.error_mode()
-
- def cb_generate_config(self, *args, **kwargs):
- """optik callback for sample config file generation"""
- self.linter.generate_config(skipsections=("COMMANDS",))
- sys.exit(0)
-
- def cb_generate_manpage(self, *args, **kwargs):
- """optik callback for sample config file generation"""
- self.linter.generate_manpage(__pkginfo__)
- sys.exit(0)
-
- def cb_help_message(self, option, optname, value, parser):
- """optik callback for printing some help about a particular message"""
- self.linter.msgs_store.help_message(utils._splitstrip(value))
- sys.exit(0)
-
- def cb_full_documentation(self, option, optname, value, parser):
- """optik callback for printing full documentation"""
- self.linter.print_full_documentation()
- sys.exit(0)
-
- def cb_list_messages(self, option, optname, value, parser):
- """optik callback for printing available messages"""
- self.linter.msgs_store.list_messages()
- sys.exit(0)
-
- def cb_list_messages_enabled(self, option, optname, value, parser):
- """optik callback for printing available messages"""
- self.linter.list_messages_enabled()
- sys.exit(0)
-
- def cb_list_groups(self, *args, **kwargs):
- """List all the check groups that pylint knows about
-
- These should be useful to know what check groups someone can disable
- or enable.
- """
- for check in self.linter.get_checker_names():
- print(check)
- sys.exit(0)
-
- def cb_python3_porting_mode(self, *args, **kwargs):
- """Activate only the python3 porting checker."""
- self.linter.python3_porting_mode()
-
- def cb_verbose_mode(self, *args, **kwargs):
- self.verbose = True
-
-
-def cb_list_confidence_levels(option, optname, value, parser):
- for level in interfaces.CONFIDENCE_LEVELS:
- print("%-18s: %s" % level)
- sys.exit(0)
-
-
-def cb_init_hook(optname, value):
- """exec arbitrary code to set sys.path for instance"""
- exec(value) # pylint: disable=exec-used
-
-
-if __name__ == "__main__":
- Run(sys.argv[1:])