diff options
Diffstat (limited to 'venv/Lib/site-packages/pylint/lint.py')
-rw-r--r-- | venv/Lib/site-packages/pylint/lint.py | 1817 |
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:]) |