From 2fcc3f13e9be2cc94de70674468ff765fc110e8c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 13 Apr 2019 21:25:19 +0200 Subject: [PATCH 01/31] Test - Add unittest for MessageStore format help --- tests/message/unittest_message_store.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/message/unittest_message_store.py b/tests/message/unittest_message_store.py index 053bfca500..1012894d8d 100644 --- a/tests/message/unittest_message_store.py +++ b/tests/message/unittest_message_store.py @@ -38,6 +38,31 @@ class Checker(BaseChecker): return store +def test_format_help(capsys, store): + store.help_message([]) + captured = capsys.readouterr() + assert captured.out == "" + store.help_message(["W1234", "E1234"]) + captured = capsys.readouterr() + assert ( + captured.out + == """:msg-symbol (W1234): *message* + msg description. This message belongs to the achecker checker. + +:duplicate-keyword-arg (E1234): *Duplicate keyword argument %r in %s call* + Used when a function call passes the same keyword argument multiple times. + This message belongs to the achecker checker. It can't be emitted when using + Python >= 2.6. + +""" + ) + + +def test_get_msg_display_string(store): + assert store.get_msg_display_string("W1234") == "'msg-symbol'" + assert store.get_msg_display_string("E1234") == "'duplicate-keyword-arg'" + + class TestMessagesStore(object): def _compare_messages(self, desc, msg, checkerref=False): assert desc == msg.format_help(checkerref=checkerref) From d16493d2df6d5747e0d98d4bf74e9a625fb5fbe1 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 13 Apr 2019 21:57:04 +0200 Subject: [PATCH 02/31] Test - Handle the case where the msgid does not exist --- tests/message/unittest_message_store.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/message/unittest_message_store.py b/tests/message/unittest_message_store.py index 1012894d8d..732cb7872a 100644 --- a/tests/message/unittest_message_store.py +++ b/tests/message/unittest_message_store.py @@ -42,7 +42,7 @@ def test_format_help(capsys, store): store.help_message([]) captured = capsys.readouterr() assert captured.out == "" - store.help_message(["W1234", "E1234"]) + store.help_message(["W1234", "E1234", "C1234"]) captured = capsys.readouterr() assert ( captured.out @@ -54,6 +54,8 @@ def test_format_help(capsys, store): This message belongs to the achecker checker. It can't be emitted when using Python >= 2.6. +No such message id or symbol 'C1234'. + """ ) From 770a2a91c9d22551ba072bc7e7130485c3f1f957 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Mar 2019 14:05:50 +0100 Subject: [PATCH 03/31] Style - Less verbose print with triple quote strings --- pylint/message/message_handler_mix_in.py | 41 ++++++++++++++---------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 53eb86870a..9013b6856a 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -349,12 +349,15 @@ def print_full_documentation(self, stream=None): """output a full documentation in ReST format""" if not stream: stream = sys.stdout - - print("Pylint global options and switches", file=stream) - print("----------------------------------", file=stream) - print("", file=stream) - print("Pylint provides global options and switches.", file=stream) - print("", file=stream) + print( + """\ +Pylint global options and switches +---------------------------------- + +Pylint provides global options and switches. +""", + file=stream, + ) by_checker = {} for checker in self.get_checkers(): @@ -382,17 +385,21 @@ def print_full_documentation(self, stream=None): "reports": list(checker.reports), } - print("Pylint checkers' options and switches", file=stream) - print("-------------------------------------", file=stream) - print("", file=stream) - print("Pylint checkers can provide three set of features:", file=stream) - print("", file=stream) - print("* options that control their execution,", file=stream) - print("* messages that they can raise,", file=stream) - print("* reports that they can generate.", file=stream) - print("", file=stream) - print("Below is a list of all checkers and their features.", file=stream) - print("", file=stream) + print( + """\ +Pylint checkers' options and switches +------------------------------------- + +Pylint checkers can provide three set of features: + +* options that control their execution, +* messages that they can raise, +* reports that they can generate. + +Below is a list of all checkers and their features. +""", + file=stream, + ) for checker, info in sorted(by_checker.items()): self._print_checker_doc(checker, info, stream=stream) From 92f06b4241725ee85a6e9b1d0d0efbc5fed006f9 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Mar 2019 18:21:45 +0100 Subject: [PATCH 04/31] Feat - Add a __repr__ and __gt__ function for BaseCheckers Permit pylint's developper to see what is inside a sorted list of checkers. --- pylint/checkers/base_checker.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 6ce8ecf9f1..55d2737f8b 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -43,6 +43,17 @@ def __init__(self, linter=None): OptionsProviderMixIn.__init__(self) self.linter = linter + def __gt__(self, other): + """Permit to sort a list of Checker by name.""" + return "{}{}".format(self.name, self.msgs).__gt__( + "{}{}".format(other.name, other.msgs) + ) + + def __repr__(self): + status = "Checker" if self.enabled else "Disabled checker" + msgids = [id for id in self.msgs] + return "{} '{}' responsible for {}".format(status, self.name, ", ".join(msgids)) + def add_message( self, msgid, From b7aa7b78a7e11ba3b2d0bcef549c95cc83c7a9fd Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 9 Jun 2019 18:20:21 +0200 Subject: [PATCH 05/31] Feat - Permit to get message definition by msgid in Checkers --- pylint/checkers/base_checker.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 55d2737f8b..cb177ef647 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -98,6 +98,14 @@ def messages(self) -> list: # dummy methods implementing the IChecker interface + def get_message_definition(self, msgid): + for message_definition in self.messages: + if message_definition.msgid == msgid: + return message_definition + error_msg = "MessageDefinition for '{}' does not exists".format(msgid) + error_msg += "Choose from {}".format([m.msgid for m in self.messages]) + raise InvalidMessageError(error_msg) + def open(self): """called before visiting project (i.e set of modules)""" From 1232088ef9fecdd0e9bfbffd168f5f3f07a3bcd8 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 9 Jun 2019 22:39:48 +0200 Subject: [PATCH 06/31] Refactor - Put a checker instance in informations --- pylint/message/message_handler_mix_in.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 9013b6856a..a19284305a 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -375,11 +375,13 @@ def print_full_documentation(self, stream=None): else: name = checker.name try: + by_checker[name]["checker"] = checker by_checker[name]["options"] += checker.options_and_values() by_checker[name]["msgs"].update(checker.msgs) by_checker[name]["reports"] += checker.reports except KeyError: by_checker[name] = { + "checker": checker, "options": list(checker.options_and_values()), "msgs": dict(checker.msgs), "reports": list(checker.reports), @@ -412,14 +414,14 @@ def _print_checker_doc(checker_name, info, stream=None): """ if not stream: stream = sys.stdout - + checker = info.get("checker") doc = info.get("doc") module = info.get("module") msgs = info.get("msgs") options = info.get("options") reports = info.get("reports") - checker_title = "%s checker" % (checker_name.replace("_", " ").title()) + checker_title = "%s checker" % (checker.name.replace("_", " ").title()) if module: # Provide anchor to link against @@ -429,7 +431,7 @@ def _print_checker_doc(checker_name, info, stream=None): print("", file=stream) if module: print("This checker is provided by ``%s``." % module, file=stream) - print("Verbatim name of the checker is ``%s``." % checker_name, file=stream) + print("Verbatim name of the checker is ``%s``." % checker.name, file=stream) print("", file=stream) if doc: # Provide anchor to link against @@ -451,7 +453,7 @@ def _print_checker_doc(checker_name, info, stream=None): for msgid, msg in sorted( msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) ): - msg = build_message_definition(checker_name, msgid, msg) + msg = build_message_definition(checker.name, msgid, msg) print(msg.format_help(checkerref=False), file=stream) print("", file=stream) if reports: From 1c4d386ca28d04ebe64853ef36aeddb45f314b22 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 9 Jun 2019 23:01:01 +0200 Subject: [PATCH 07/31] Refactor - Give a checker instead of a string to _print_checker_doc Will permit to move functions in the BaseChecker class later. --- doc/exts/pylint_extensions.py | 30 +++++++++++------------- pylint/message/message_handler_mix_in.py | 8 +++---- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index dd660767c9..016ba6f54e 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -65,14 +65,13 @@ def builder_inited(app): "\n load-plugins=pylint.extensions.docparams," "pylint.extensions.docstyle\n\n" ) - by_module = get_plugins_info(linter, doc_files) - for module, info in sorted(by_module.items()): - linter._print_checker_doc(info["name"], info, stream=stream) + by_checker = get_plugins_info(linter, doc_files) + for checker, info in sorted(by_checker.items()): + linter._print_checker_doc(checker, info, stream=stream) def get_plugins_info(linter, doc_files): - by_module = {} - + by_checker = {} for checker in linter.get_checkers(): if checker.name == "master": continue @@ -80,23 +79,23 @@ def get_plugins_info(linter, doc_files): # Plugins only - skip over core checkers if re.match("pylint.checkers", module): continue - # Find any .rst documentation associated with this plugin doc = "" doc_file = doc_files.get(module) if doc_file: with open(doc_file, "r") as f: doc = f.read() - try: - by_module[module]["options"] += checker.options_and_values() - by_module[module]["msgs"].update(checker.msgs) - by_module[module]["reports"] += checker.reports - by_module[module]["doc"] += doc - by_module[module]["name"] += checker.name - by_module[module]["module"] += module + by_checker[checker]["checker"] = checker + by_checker[checker]["options"] += checker.options_and_values() + by_checker[checker]["msgs"].update(checker.msgs) + by_checker[checker]["reports"] += checker.reports + by_checker[checker]["doc"] += doc + by_checker[checker]["name"] += checker.name + by_checker[checker]["module"] += module except KeyError: - by_module[module] = { + by_checker[checker] = { + "checker": checker, "options": list(checker.options_and_values()), "msgs": dict(checker.msgs), "reports": list(checker.reports), @@ -104,8 +103,7 @@ def get_plugins_info(linter, doc_files): "name": checker.name, "module": module, } - - return by_module + return by_checker def setup(app): diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index a19284305a..f007e8edef 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -361,6 +361,7 @@ def print_full_documentation(self, stream=None): by_checker = {} for checker in self.get_checkers(): + name = checker.name if checker.name == "master": if checker.options: for section, options in checker.options_by_section(): @@ -373,7 +374,6 @@ def print_full_documentation(self, stream=None): _rest_format_section(stream, None, options) print("", file=stream) else: - name = checker.name try: by_checker[name]["checker"] = checker by_checker[name]["options"] += checker.options_and_values() @@ -403,11 +403,11 @@ def print_full_documentation(self, stream=None): file=stream, ) - for checker, info in sorted(by_checker.items()): - self._print_checker_doc(checker, info, stream=stream) + for checker, information in sorted(by_checker.items()): + self._print_checker_doc(checker, information, stream=stream) @staticmethod - def _print_checker_doc(checker_name, info, stream=None): + def _print_checker_doc(checker, info, stream=None): """Helper method for print_full_documentation. Also used by doc/exts/pylint_extensions.py. From 0e315ac75975951857e85c2611b9c1950b608aeb Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 9 Jun 2019 23:02:34 +0200 Subject: [PATCH 08/31] Fix - better error msg for getmessagedefinition (sqsuash) --- pylint/checkers/base_checker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index cb177ef647..5c3d529099 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -102,8 +102,8 @@ def get_message_definition(self, msgid): for message_definition in self.messages: if message_definition.msgid == msgid: return message_definition - error_msg = "MessageDefinition for '{}' does not exists".format(msgid) - error_msg += "Choose from {}".format([m.msgid for m in self.messages]) + error_msg = "MessageDefinition for '{}' does not exists. ".format(msgid) + error_msg += "Choose from {}.".format([m.msgid for m in self.messages]) raise InvalidMessageError(error_msg) def open(self): From 3d395896fa8b1fb6628bfb3da5ee583e23cf953d Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Mar 2019 14:51:41 +0100 Subject: [PATCH 09/31] Refactor - Separate string creation and display in rest_format_section This will permit to get the string without printing it at the same time. Print add an implicit \n so if this look convuluted remember that. We had to change step by step in order to be able to not have too much complexity at once. --- pylint/message/message_handler_mix_in.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index f007e8edef..3e36edaac8 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -30,23 +30,24 @@ ) -def _rest_format_section(stream, section, options, doc=None): +def _rest_format_section(section, options, doc=None) -> str: """format an options section using as ReST formatted output""" + result = "" if section: - print("%s\n%s" % (section, "'" * len(section)), file=stream) + result += "%s\n%s\n" % (section, "'" * len(section)) if doc: - print(normalize_text(doc, line_len=79, indent=""), file=stream) - print(file=stream) + formatted_doc = normalize_text(doc, line_len=79, indent="") + result += "%s\n\n" % formatted_doc for optname, optdict, value in options: help_opt = optdict.get("help") - print(":%s:" % optname, file=stream) + result += ":%s:\n" % optname if help_opt: - help_opt = normalize_text(help_opt, line_len=79, indent=" ") - print(help_opt, file=stream) + formatted_help = normalize_text(help_opt, line_len=79, indent=" ") + result += "%s\n" % formatted_help if value: value = str(_format_option_value(optdict, value)) - print(file=stream) - print(" Default: ``%s``" % value.replace("`` ", "```` ``"), file=stream) + result += "\n Default: ``%s``\n" % value.replace("`` ", "```` ``") + return result class MessagesHandlerMixIn: @@ -371,7 +372,7 @@ def print_full_documentation(self, stream=None): title = "%s options" % section.capitalize() print(title, file=stream) print("~" * len(title), file=stream) - _rest_format_section(stream, None, options) + print(_rest_format_section(None, options)[:-1], file=stream) print("", file=stream) else: try: @@ -444,7 +445,7 @@ def _print_checker_doc(checker, info, stream=None): title = "{} Options".format(checker_title) print(title, file=stream) print("^" * len(title), file=stream) - _rest_format_section(stream, None, options) + print(_rest_format_section(None, options)[:-1], file=stream) print("", file=stream) if msgs: title = "{} Messages".format(checker_title) From 91d8eb7da1ce1f562f7902aa668be1e827c6a202 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 9 Jun 2019 23:37:16 +0200 Subject: [PATCH 10/31] Refactor - Separate string creation and display in _print_checker_doc This will permit to get the string without printing it at the same time. This will also permit to move this to BaseChecker. --- pylint/message/message_handler_mix_in.py | 109 +++++++++++------------ 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 3e36edaac8..ccbd7cf8c4 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -30,11 +30,16 @@ ) +def get_rest_title(title, character): + """Permit to get a rest title underlined with a choosen character.""" + return "%s\n%s\n" % (title, character * len(title)) + + def _rest_format_section(section, options, doc=None) -> str: """format an options section using as ReST formatted output""" result = "" if section: - result += "%s\n%s\n" % (section, "'" * len(section)) + result += get_rest_title(section, "'") if doc: formatted_doc = normalize_text(doc, line_len=79, indent="") result += "%s\n\n" % formatted_doc @@ -346,6 +351,25 @@ def add_one_message( ) ) + def _get_checkers_infos(self) -> dict: + by_checker = {} + for checker in self.get_checkers(): + name = checker.name + if name != "master": + try: + by_checker[name]["checker"] = checker + by_checker[name]["options"] += checker.options_and_values() + by_checker[name]["msgs"].update(checker.msgs) + by_checker[name]["reports"] += checker.reports + except KeyError: + by_checker[name] = { + "checker": checker, + "options": list(checker.options_and_values()), + "msgs": dict(checker.msgs), + "reports": list(checker.reports), + } + return by_checker + def print_full_documentation(self, stream=None): """output a full documentation in ReST format""" if not stream: @@ -359,8 +383,6 @@ def print_full_documentation(self, stream=None): """, file=stream, ) - - by_checker = {} for checker in self.get_checkers(): name = checker.name if checker.name == "master": @@ -374,20 +396,6 @@ def print_full_documentation(self, stream=None): print("~" * len(title), file=stream) print(_rest_format_section(None, options)[:-1], file=stream) print("", file=stream) - else: - try: - by_checker[name]["checker"] = checker - by_checker[name]["options"] += checker.options_and_values() - by_checker[name]["msgs"].update(checker.msgs) - by_checker[name]["reports"] += checker.reports - except KeyError: - by_checker[name] = { - "checker": checker, - "options": list(checker.options_and_values()), - "msgs": dict(checker.msgs), - "reports": list(checker.reports), - } - print( """\ Pylint checkers' options and switches @@ -403,65 +411,56 @@ def print_full_documentation(self, stream=None): """, file=stream, ) - + by_checker = self._get_checkers_infos() for checker, information in sorted(by_checker.items()): self._print_checker_doc(checker, information, stream=stream) @staticmethod - def _print_checker_doc(checker, info, stream=None): - """Helper method for print_full_documentation. - - Also used by doc/exts/pylint_extensions.py. - """ - if not stream: - stream = sys.stdout + def _get_checker_doc(checker, info) -> str: + result = "" checker = info.get("checker") doc = info.get("doc") module = info.get("module") msgs = info.get("msgs") options = info.get("options") reports = info.get("reports") - checker_title = "%s checker" % (checker.name.replace("_", " ").title()) - if module: # Provide anchor to link against - print(".. _%s:\n" % module, file=stream) - print(checker_title, file=stream) - print("~" * len(checker_title), file=stream) - print("", file=stream) + result += ".. _%s:\n\n" % module + result += "%s\n" % get_rest_title(checker_title, "~") if module: - print("This checker is provided by ``%s``." % module, file=stream) - print("Verbatim name of the checker is ``%s``." % checker.name, file=stream) - print("", file=stream) + result += "This checker is provided by ``%s``.\n" % module + result += "Verbatim name of the checker is ``%s``.\n\n" % checker.name if doc: # Provide anchor to link against - title = "{} Documentation".format(checker_title) - print(title, file=stream) - print("^" * len(title), file=stream) - print(cleandoc(doc), file=stream) - print("", file=stream) + result += get_rest_title("{} Documentation".format(checker_title), "^") + result += "%s\n\n" % cleandoc(doc) if options: - title = "{} Options".format(checker_title) - print(title, file=stream) - print("^" * len(title), file=stream) - print(_rest_format_section(None, options)[:-1], file=stream) - print("", file=stream) + result += get_rest_title("{} Options".format(checker_title), "^") + result += "%s\n" % _rest_format_section(None, options) if msgs: - title = "{} Messages".format(checker_title) - print(title, file=stream) - print("^" * len(title), file=stream) + result += get_rest_title("{} Messages".format(checker_title), "^") for msgid, msg in sorted( msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) ): msg = build_message_definition(checker.name, msgid, msg) - print(msg.format_help(checkerref=False), file=stream) - print("", file=stream) + result += "%s\n" % msg.format_help(checkerref=False) + result += "\n" if reports: - title = "{} Reports".format(checker_title) - print(title, file=stream) - print("^" * len(title), file=stream) + result += get_rest_title("{} Reports".format(checker_title), "^") for report in reports: - print(":%s: %s" % report[:2], file=stream) - print("", file=stream) - print("", file=stream) + result += ":%s: %s\n" % report[:2] + result += "\n" + result += "\n" + return result + + @staticmethod + def _print_checker_doc(checker, info, stream=None): + """Helper method for print_full_documentation. + + Also used by doc/exts/pylint_extensions.py. + """ + if not stream: + stream = sys.stdout + print(MessagesHandlerMixIn._get_checker_doc(checker, info)[:-1], file=stream) From 409079580d4079b1f5bf3b4bc0487fe70ee14f18 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 24 Mar 2019 17:21:10 +0100 Subject: [PATCH 11/31] Fix - Add type annotation for mypy --- pylint/message/message_handler_mix_in.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index ccbd7cf8c4..d3a3da5176 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -352,7 +352,7 @@ def add_one_message( ) def _get_checkers_infos(self) -> dict: - by_checker = {} + by_checker: dict = {} for checker in self.get_checkers(): name = checker.name if name != "master": From d49f9bb1ac1d2cb4b9fbedcb7596d65ec667c4a5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Mar 2019 18:09:35 +0100 Subject: [PATCH 12/31] Refactor - Separate string creation and display in _print_full_documentation This will permit to get the string without printing it at the same time. --- pylint/message/message_handler_mix_in.py | 36 +++++++++++------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index d3a3da5176..942b5ec4be 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -370,19 +370,14 @@ def _get_checkers_infos(self) -> dict: } return by_checker - def print_full_documentation(self, stream=None): - """output a full documentation in ReST format""" - if not stream: - stream = sys.stdout - print( - """\ + def get_full_documentation(self) -> str: + result = """\ Pylint global options and switches ---------------------------------- Pylint provides global options and switches. -""", - file=stream, - ) + +""" for checker in self.get_checkers(): name = checker.name if checker.name == "master": @@ -392,12 +387,9 @@ def print_full_documentation(self, stream=None): title = "General options" else: title = "%s options" % section.capitalize() - print(title, file=stream) - print("~" * len(title), file=stream) - print(_rest_format_section(None, options)[:-1], file=stream) - print("", file=stream) - print( - """\ + result += get_rest_title(title, "~") + result += "%s\n" % _rest_format_section(None, options) + result += """\ Pylint checkers' options and switches ------------------------------------- @@ -408,12 +400,18 @@ def print_full_documentation(self, stream=None): * reports that they can generate. Below is a list of all checkers and their features. -""", - file=stream, - ) + +""" by_checker = self._get_checkers_infos() for checker, information in sorted(by_checker.items()): - self._print_checker_doc(checker, information, stream=stream) + result += self._get_checker_doc(checker, information) + return result + + def print_full_documentation(self, stream=None) -> None: + """output a full documentation in ReST format""" + if not stream: + stream = sys.stdout + print(self.get_full_documentation()[:-1], file=stream) @staticmethod def _get_checker_doc(checker, info) -> str: From 5dfc12676eac317a3945dc281fdec87b9ad74682 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 23 Mar 2019 10:48:20 +0100 Subject: [PATCH 13/31] Refactor - Move build_message_definition to the BaseChecker class --- pylint/checkers/base_checker.py | 41 ++++++++++++++++------ pylint/message/__init__.py | 1 - pylint/message/build_message_definition.py | 34 ------------------ pylint/message/message_handler_mix_in.py | 3 +- 4 files changed, 32 insertions(+), 47 deletions(-) delete mode 100644 pylint/message/build_message_definition.py diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 5c3d529099..809694398d 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -14,9 +14,10 @@ from typing import Any from pylint.config import OptionsProviderMixIn +from pylint.constants import WarningScope from pylint.exceptions import InvalidMessageError -from pylint.interfaces import UNDEFINED -from pylint.message import build_message_definition +from pylint.interfaces import UNDEFINED, IRawChecker, ITokenChecker, implements +from pylint.message.message_definition import MessageDefinition class BaseChecker(OptionsProviderMixIn): @@ -55,14 +56,10 @@ def __repr__(self): return "{} '{}' responsible for {}".format(status, self.name, ", ".join(msgids)) def add_message( - self, - msgid, - line=None, - node=None, - args=None, - confidence=UNDEFINED, - col_offset=None, + self, msgid, line=None, node=None, args=None, confidence=None, col_offset=None ): + if not confidence: + confidence = UNDEFINED self.linter.add_message(msgid, line, node, args, confidence, col_offset) def check_consistency(self) -> None: @@ -89,10 +86,34 @@ def check_consistency(self) -> None: checker_id = message.msgid[1:3] existing_ids.append(message.msgid) + def create_message_definition_from_tuple(self, msgid, msg_tuple): + if implements(self, (IRawChecker, ITokenChecker)): + default_scope = WarningScope.LINE + else: + default_scope = WarningScope.NODE + options = {} + if len(msg_tuple) > 3: + (msg, symbol, descr, options) = msg_tuple + elif len(msg_tuple) > 2: + (msg, symbol, descr) = msg_tuple + else: + error_msg = """Messages should have a msgid and a symbol. Something like this : + +"W1234": ( + "message", + "message-symbol", + "Message description with detail.", + ... +), +""" + raise InvalidMessageError(error_msg) + options.setdefault("scope", default_scope) + return MessageDefinition(self, msgid, msg, descr, symbol, **options) + @property def messages(self) -> list: return [ - build_message_definition(self, msgid, msg_tuple) + self.create_message_definition_from_tuple(msgid, msg_tuple) for msgid, msg_tuple in sorted(self.msgs.items()) ] diff --git a/pylint/message/__init__.py b/pylint/message/__init__.py index 430d066539..1616eeea0c 100644 --- a/pylint/message/__init__.py +++ b/pylint/message/__init__.py @@ -39,7 +39,6 @@ """All the classes related to Message handling.""" -from pylint.message.build_message_definition import build_message_definition from pylint.message.message import Message from pylint.message.message_definition import MessageDefinition from pylint.message.message_handler_mix_in import MessagesHandlerMixIn diff --git a/pylint/message/build_message_definition.py b/pylint/message/build_message_definition.py deleted file mode 100644 index 4de204d048..0000000000 --- a/pylint/message/build_message_definition.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- - -# 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 - -import warnings - -from pylint.constants import WarningScope -from pylint.interfaces import IRawChecker, ITokenChecker, implements -from pylint.message.message_definition import MessageDefinition - - -def build_message_definition(checker, msgid, msg_tuple): - if implements(checker, (IRawChecker, ITokenChecker)): - default_scope = WarningScope.LINE - else: - default_scope = WarningScope.NODE - options = {} - if len(msg_tuple) > 3: - (msg, symbol, descr, options) = msg_tuple - elif len(msg_tuple) > 2: - (msg, symbol, descr) = msg_tuple - else: - # messages should have a symbol, but for backward compatibility - # they may not. - (msg, descr) = msg_tuple - warnings.warn( - "[pylint 0.26] description of message %s doesn't include " - "a symbolic name" % msgid, - DeprecationWarning, - ) - symbol = None - options.setdefault("scope", default_scope) - return MessageDefinition(checker, msgid, msg, descr, symbol, **options) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 942b5ec4be..388054897b 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -20,7 +20,6 @@ ) from pylint.exceptions import InvalidMessageError, UnknownMessageError from pylint.interfaces import UNDEFINED -from pylint.message.build_message_definition import build_message_definition from pylint.message.message import Message from pylint.utils.utils import ( _format_option_value, @@ -442,7 +441,7 @@ def _get_checker_doc(checker, info) -> str: for msgid, msg in sorted( msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) ): - msg = build_message_definition(checker.name, msgid, msg) + msg = checker.create_message_definition_from_tuple(msgid, msg) result += "%s\n" % msg.format_help(checkerref=False) result += "\n" if reports: From 20571f56299f04ad20b433f6acab075dce34291c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 19 May 2019 12:10:25 +0200 Subject: [PATCH 14/31] Refactor - Use a constant for the main checker name Following review see : https://github.com/PyCQA/pylint/pull/2844#discussion_r281014968 --- doc/exts/pylint_extensions.py | 3 ++- pylint/constants.py | 2 ++ pylint/lint.py | 10 +++++++--- pylint/message/message_handler_mix_in.py | 3 ++- tests/test_self.py | 5 ++++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index 016ba6f54e..6f2eaa5c47 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -11,6 +11,7 @@ import pkg_resources import sphinx +from pylint.constants import MAIN_CHECKER_NAME from pylint.lint import PyLinter # Some modules have been renamed and deprecated under their old names. @@ -73,7 +74,7 @@ def builder_inited(app): def get_plugins_info(linter, doc_files): by_checker = {} for checker in linter.get_checkers(): - if checker.name == "master": + if checker.name == MAIN_CHECKER_NAME: continue module = checker.__module__ # Plugins only - skip over core checkers diff --git a/pylint/constants.py b/pylint/constants.py index 07d1727ab2..a2e2b79777 100644 --- a/pylint/constants.py +++ b/pylint/constants.py @@ -32,6 +32,8 @@ MSG_TYPES_STATUS = {"I": 0, "C": 16, "R": 8, "W": 4, "E": 2, "F": 1} +MAIN_CHECKER_NAME = "main-pylint-checker" + class WarningScope: LINE = "line-based-msg" diff --git a/pylint/lint.py b/pylint/lint.py index f599196490..a19865343d 100644 --- a/pylint/lint.py +++ b/pylint/lint.py @@ -77,7 +77,7 @@ from pylint import checkers, config, exceptions, interfaces, reporters from pylint.__pkginfo__ import version -from pylint.constants import MSG_TYPES, OPTION_RGX +from pylint.constants import MAIN_CHECKER_NAME, MSG_TYPES, OPTION_RGX from pylint.message import Message, MessagesHandlerMixIn, MessagesStore from pylint.reporters.ureports import nodes as report_nodes from pylint.utils import ASTWalker, FileState, utils @@ -326,7 +326,7 @@ class PyLinter( __implements__ = (interfaces.ITokenChecker,) - name = "master" + name = MAIN_CHECKER_NAME priority = 0 level = 0 msgs = MSGS @@ -922,7 +922,11 @@ def get_checker_names(self): """Get all the checker names that this linter knows about.""" current_checkers = self.get_checkers() return sorted( - {check.name for check in current_checkers if check.name != "master"} + { + checker.name + for checker in current_checkers + if checker.name != MAIN_CHECKER_NAME + } ) def prepare_checkers(self): diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 388054897b..f34ba5a4cc 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -11,6 +11,7 @@ from pylint.constants import ( _MSG_ORDER, _SCOPE_EXEMPT, + MAIN_CHECKER_NAME, MSG_STATE_CONFIDENCE, MSG_STATE_SCOPE_CONFIG, MSG_STATE_SCOPE_MODULE, @@ -379,7 +380,7 @@ def get_full_documentation(self) -> str: """ for checker in self.get_checkers(): name = checker.name - if checker.name == "master": + if name == MAIN_CHECKER_NAME: if checker.options: for section, options in checker.options_by_section(): if section is None: diff --git a/tests/test_self.py b/tests/test_self.py index 3cf11ad6b3..a1e3bb4465 100644 --- a/tests/test_self.py +++ b/tests/test_self.py @@ -34,6 +34,7 @@ import pytest +from pylint.constants import MAIN_CHECKER_NAME from pylint.lint import Run from pylint.reporters import JSONReporter from pylint.reporters.text import * @@ -183,7 +184,9 @@ def test_generate_config_disable_symbolic_names(self): output = out.getvalue() # Get rid of the pesky messages that pylint emits if the # configuration file is not found. - master = re.search(r"\[MASTER", output) + pattern = r"\[{}".format(MAIN_CHECKER_NAME.upper()) + master = re.search(pattern, output) + assert master is not None, "{} not found in {}".format(pattern, output) out = StringIO(output[master.start() :]) parser = configparser.RawConfigParser() parser.read_file(out) From 0c8477f55c95128c2a5fc0aa23a0bf94c1b6e7c7 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 19 May 2019 12:44:42 +0200 Subject: [PATCH 15/31] Doc - Retrocompatibility with the main checker name --- pylint/constants.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pylint/constants.py b/pylint/constants.py index a2e2b79777..852fc15108 100644 --- a/pylint/constants.py +++ b/pylint/constants.py @@ -32,7 +32,10 @@ MSG_TYPES_STATUS = {"I": 0, "C": 16, "R": 8, "W": 4, "E": 2, "F": 1} -MAIN_CHECKER_NAME = "main-pylint-checker" +# You probably don't want to change the MAIN_CHECKER_NAME +# This would affect rcfile generation and retro-compatibility +# on all project using [MASTER] in their rcfile. +MAIN_CHECKER_NAME = "master" class WarningScope: From 3d05ca8193482d0eea0e5b44b5371d8607eb494a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 19 May 2019 13:29:59 +0200 Subject: [PATCH 16/31] Refactor - Simplify the Checker.__repr__ function Following review see : https://github.com/PyCQA/pylint/pull/2844#discussion_r281015055 --- pylint/checkers/base_checker.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 809694398d..1aa83d6d9e 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -52,8 +52,9 @@ def __gt__(self, other): def __repr__(self): status = "Checker" if self.enabled else "Disabled checker" - msgids = [id for id in self.msgs] - return "{} '{}' responsible for {}".format(status, self.name, ", ".join(msgids)) + return "{} '{}' responsible for {}".format( + status, self.name, ", ".join(self.msgs.keys()) + ) def add_message( self, msgid, line=None, node=None, args=None, confidence=None, col_offset=None From ce5b9461638041493f6030a7c5b925ea81d18b2b Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 9 Jun 2019 17:14:10 +0200 Subject: [PATCH 17/31] Fix - A typo in base_checker.py --- pylint/checkers/base_checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 1aa83d6d9e..d4f38886ed 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -26,7 +26,7 @@ class BaseChecker(OptionsProviderMixIn): name = None # type: str # options level (0 will be displaying in --help, 1 in --long-help) level = 1 - # ordered list of options to control the ckecker behaviour + # ordered list of options to control the checker behaviour options = () # type: Any # messages issued by this checker msgs = {} # type: Any From 51b74680fc7de2e88ca1c2905784ad71b409c470 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 08:29:09 +0200 Subject: [PATCH 18/31] Refactor - Remove syntax specific to python 3.6 Following review see here : https://github.com/PyCQA/pylint/pull/2844#discussion_r281014957 --- pylint/message/message_handler_mix_in.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index f34ba5a4cc..2dd863513e 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -35,7 +35,7 @@ def get_rest_title(title, character): return "%s\n%s\n" % (title, character * len(title)) -def _rest_format_section(section, options, doc=None) -> str: +def _rest_format_section(section, options, doc=None): """format an options section using as ReST formatted output""" result = "" if section: @@ -351,7 +351,7 @@ def add_one_message( ) ) - def _get_checkers_infos(self) -> dict: + def _get_checkers_infos(self): by_checker: dict = {} for checker in self.get_checkers(): name = checker.name @@ -370,7 +370,7 @@ def _get_checkers_infos(self) -> dict: } return by_checker - def get_full_documentation(self) -> str: + def get_full_documentation(self): result = """\ Pylint global options and switches ---------------------------------- @@ -407,14 +407,14 @@ def get_full_documentation(self) -> str: result += self._get_checker_doc(checker, information) return result - def print_full_documentation(self, stream=None) -> None: + def print_full_documentation(self, stream=None): """output a full documentation in ReST format""" if not stream: stream = sys.stdout print(self.get_full_documentation()[:-1], file=stream) @staticmethod - def _get_checker_doc(checker, info) -> str: + def _get_checker_doc(checker, info): result = "" checker = info.get("checker") doc = info.get("doc") From dab75539b3deab776c9ff5b63525703afbf6d953 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 08:33:18 +0200 Subject: [PATCH 19/31] Refactor - Remove _ in _rest_format_section Because we want to make it a public function. --- pylint/message/message_handler_mix_in.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 2dd863513e..7676a7f507 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -35,7 +35,7 @@ def get_rest_title(title, character): return "%s\n%s\n" % (title, character * len(title)) -def _rest_format_section(section, options, doc=None): +def rest_format_section(section, options, doc=None): """format an options section using as ReST formatted output""" result = "" if section: @@ -388,7 +388,7 @@ def get_full_documentation(self): else: title = "%s options" % section.capitalize() result += get_rest_title(title, "~") - result += "%s\n" % _rest_format_section(None, options) + result += "%s\n" % rest_format_section(None, options) result += """\ Pylint checkers' options and switches ------------------------------------- @@ -436,7 +436,7 @@ def _get_checker_doc(checker, info): result += "%s\n\n" % cleandoc(doc) if options: result += get_rest_title("{} Options".format(checker_title), "^") - result += "%s\n" % _rest_format_section(None, options) + result += "%s\n" % rest_format_section(None, options) if msgs: result += get_rest_title("{} Messages".format(checker_title), "^") for msgid, msg in sorted( From 2c39d0d34037788d0836ce53ac2ba5dcb096f660 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 08:35:57 +0200 Subject: [PATCH 20/31] Refactor - Move utility function to utils We want to use them in Checker too. --- pylint/message/message_handler_mix_in.py | 31 +++--------------------- pylint/utils/__init__.py | 2 ++ pylint/utils/utils.py | 25 +++++++++++++++++++ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 7676a7f507..c6bdd14acc 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -22,39 +22,14 @@ from pylint.exceptions import InvalidMessageError, UnknownMessageError from pylint.interfaces import UNDEFINED from pylint.message.message import Message -from pylint.utils.utils import ( - _format_option_value, +from pylint.utils import ( category_id, get_module_and_frameid, - normalize_text, + get_rest_title, + rest_format_section, ) -def get_rest_title(title, character): - """Permit to get a rest title underlined with a choosen character.""" - return "%s\n%s\n" % (title, character * len(title)) - - -def rest_format_section(section, options, doc=None): - """format an options section using as ReST formatted output""" - result = "" - if section: - result += get_rest_title(section, "'") - if doc: - formatted_doc = normalize_text(doc, line_len=79, indent="") - result += "%s\n\n" % formatted_doc - for optname, optdict, value in options: - help_opt = optdict.get("help") - result += ":%s:\n" % optname - if help_opt: - formatted_help = normalize_text(help_opt, line_len=79, indent=" ") - result += "%s\n" % formatted_help - if value: - value = str(_format_option_value(optdict, value)) - result += "\n Default: ``%s``\n" % value.replace("`` ", "```` ``") - return result - - class MessagesHandlerMixIn: """a mix-in class containing all the messages related methods for the main lint class diff --git a/pylint/utils/__init__.py b/pylint/utils/__init__.py index 67b56db3a8..8f1a8e4d65 100644 --- a/pylint/utils/__init__.py +++ b/pylint/utils/__init__.py @@ -56,8 +56,10 @@ format_section, get_global_option, get_module_and_frameid, + get_rest_title, normalize_text, register_plugins, + rest_format_section, safe_decode, tokenize_module, ) diff --git a/pylint/utils/utils.py b/pylint/utils/utils.py index ab28a07b5b..c2216575f0 100644 --- a/pylint/utils/utils.py +++ b/pylint/utils/utils.py @@ -51,6 +51,31 @@ def category_id(cid): return MSG_TYPES_LONG.get(cid) +def get_rest_title(title, character): + """Permit to get a rest title underlined with a choosen character.""" + return "%s\n%s\n" % (title, character * len(title)) + + +def rest_format_section(section, options, doc=None): + """format an options section using as ReST formatted output""" + result = "" + if section: + result += get_rest_title(section, "'") + if doc: + formatted_doc = normalize_text(doc, line_len=79, indent="") + result += "%s\n\n" % formatted_doc + for optname, optdict, value in options: + help_opt = optdict.get("help") + result += ":%s:\n" % optname + if help_opt: + formatted_help = normalize_text(help_opt, line_len=79, indent=" ") + result += "%s\n" % formatted_help + if value: + value = str(_format_option_value(optdict, value)) + result += "\n Default: ``%s``\n" % value.replace("`` ", "```` ``") + return result + + def safe_decode(line, encoding, *args, **kwargs): """return decoded line from encoding or decode with default encoding""" try: From 5d4d0bf3ad855020b725a73c670fefedc0d9de8c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 08:52:48 +0200 Subject: [PATCH 21/31] Refactor - Use get_rest_title where it could be --- doc/exts/pylint_extensions.py | 7 ++++--- pylint/message/message_handler_mix_in.py | 9 +++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index 6f2eaa5c47..f740ac5ce8 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -8,11 +8,11 @@ import re import sys -import pkg_resources import sphinx from pylint.constants import MAIN_CHECKER_NAME from pylint.lint import PyLinter +from pylint.utils import get_rest_title # Some modules have been renamed and deprecated under their old names. # Skip documenting these modules since: @@ -51,8 +51,9 @@ def builder_inited(app): base_path, "doc", "technical_reference", "extensions.rst" ) with open(extensions_doc, "w") as stream: - stream.write("Optional Pylint checkers in the extensions module\n") - stream.write("=================================================\n\n") + stream.write( + get_rest_title("Optional Pylint checkers in the extensions module", "=") + ) stream.write("Pylint provides the following optional plugins:\n\n") for module in modules: stream.write("- :ref:`{}`\n".format(module)) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index c6bdd14acc..4ef49c551e 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -346,10 +346,8 @@ def _get_checkers_infos(self): return by_checker def get_full_documentation(self): - result = """\ -Pylint global options and switches ----------------------------------- - + result = get_rest_title("Pylint global options and switches", "-") + result += """ Pylint provides global options and switches. """ @@ -364,9 +362,8 @@ def get_full_documentation(self): title = "%s options" % section.capitalize() result += get_rest_title(title, "~") result += "%s\n" % rest_format_section(None, options) + result += get_rest_title("Pylint checkers' options and switches", "-") result += """\ -Pylint checkers' options and switches -------------------------------------- Pylint checkers can provide three set of features: From e571f90a4c442d655bc3b1494eb1e157d64dc7eb Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 09:01:15 +0200 Subject: [PATCH 22/31] Refactor - Move doc for checkers in BaseChecker At long last. --- pylint/checkers/base_checker.py | 44 +++++++++++++++++++- pylint/message/message_handler_mix_in.py | 52 +++--------------------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index d4f38886ed..f73f946285 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -11,13 +11,15 @@ # 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 +from inspect import cleandoc from typing import Any from pylint.config import OptionsProviderMixIn -from pylint.constants import WarningScope +from pylint.constants import _MSG_ORDER, WarningScope from pylint.exceptions import InvalidMessageError from pylint.interfaces import UNDEFINED, IRawChecker, ITokenChecker, implements from pylint.message.message_definition import MessageDefinition +from pylint.utils import get_rest_title, rest_format_section class BaseChecker(OptionsProviderMixIn): @@ -56,6 +58,46 @@ def __repr__(self): status, self.name, ", ".join(self.msgs.keys()) ) + @staticmethod + def get_full_documentation(info): + result = "" + checker = info.get("checker") + doc = info.get("doc") + module = info.get("module") + msgs = info.get("msgs") + options = info.get("options") + reports = info.get("reports") + checker_title = "%s checker" % (checker.name.replace("_", " ").title()) + if module: + # Provide anchor to link against + result += ".. _%s:\n\n" % module + result += "%s\n" % get_rest_title(checker_title, "~") + if module: + result += "This checker is provided by ``%s``.\n" % module + result += "Verbatim name of the checker is ``%s``.\n\n" % checker.name + if doc: + # Provide anchor to link against + result += get_rest_title("{} Documentation".format(checker_title), "^") + result += "%s\n\n" % cleandoc(doc) + if options: + result += get_rest_title("{} Options".format(checker_title), "^") + result += "%s\n" % rest_format_section(None, options) + if msgs: + result += get_rest_title("{} Messages".format(checker_title), "^") + for msgid, msg in sorted( + msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) + ): + msg = checker.create_message_definition_from_tuple(msgid, msg) + result += "%s\n" % msg.format_help(checkerref=False) + result += "\n" + if reports: + result += get_rest_title("{} Reports".format(checker_title), "^") + for report in reports: + result += ":%s: %s\n" % report[:2] + result += "\n" + result += "\n" + return result + def add_message( self, msgid, line=None, node=None, args=None, confidence=None, col_offset=None ): diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 4ef49c551e..32b04112cc 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -6,10 +6,8 @@ from __future__ import print_function import sys -from inspect import cleandoc from pylint.constants import ( - _MSG_ORDER, _SCOPE_EXEMPT, MAIN_CHECKER_NAME, MSG_STATE_CONFIDENCE, @@ -375,8 +373,9 @@ def get_full_documentation(self): """ by_checker = self._get_checkers_infos() - for checker, information in sorted(by_checker.items()): - result += self._get_checker_doc(checker, information) + for checker_name, information in sorted(by_checker.items()): + checker = information["checker"] + result += checker.get_full_documentation(information) return result def print_full_documentation(self, stream=None): @@ -386,51 +385,12 @@ def print_full_documentation(self, stream=None): print(self.get_full_documentation()[:-1], file=stream) @staticmethod - def _get_checker_doc(checker, info): - result = "" - checker = info.get("checker") - doc = info.get("doc") - module = info.get("module") - msgs = info.get("msgs") - options = info.get("options") - reports = info.get("reports") - checker_title = "%s checker" % (checker.name.replace("_", " ").title()) - if module: - # Provide anchor to link against - result += ".. _%s:\n\n" % module - result += "%s\n" % get_rest_title(checker_title, "~") - if module: - result += "This checker is provided by ``%s``.\n" % module - result += "Verbatim name of the checker is ``%s``.\n\n" % checker.name - if doc: - # Provide anchor to link against - result += get_rest_title("{} Documentation".format(checker_title), "^") - result += "%s\n\n" % cleandoc(doc) - if options: - result += get_rest_title("{} Options".format(checker_title), "^") - result += "%s\n" % rest_format_section(None, options) - if msgs: - result += get_rest_title("{} Messages".format(checker_title), "^") - for msgid, msg in sorted( - msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) - ): - msg = checker.create_message_definition_from_tuple(msgid, msg) - result += "%s\n" % msg.format_help(checkerref=False) - result += "\n" - if reports: - result += get_rest_title("{} Reports".format(checker_title), "^") - for report in reports: - result += ":%s: %s\n" % report[:2] - result += "\n" - result += "\n" - return result - - @staticmethod - def _print_checker_doc(checker, info, stream=None): + def _print_checker_doc(checker, information, stream=None): """Helper method for print_full_documentation. Also used by doc/exts/pylint_extensions.py. """ if not stream: stream = sys.stdout - print(MessagesHandlerMixIn._get_checker_doc(checker, info)[:-1], file=stream) + checker = information["checker"] + print(checker.get_full_documentation(information)[:-1], file=stream) From d7c7e6156a9c460cd7694442669cacf38fa1580f Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 09:22:49 +0200 Subject: [PATCH 23/31] Refactor - Remove useless parameter in print_checker_doc --- doc/exts/pylint_extensions.py | 4 ++-- pylint/message/message_handler_mix_in.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index f740ac5ce8..01ba8a2b1c 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -68,8 +68,8 @@ def builder_inited(app): "pylint.extensions.docstyle\n\n" ) by_checker = get_plugins_info(linter, doc_files) - for checker, info in sorted(by_checker.items()): - linter._print_checker_doc(checker, info, stream=stream) + for checker, information in sorted(by_checker.items()): + linter._print_checker_doc(information, stream=stream) def get_plugins_info(linter, doc_files): diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 32b04112cc..c34aceee05 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -385,7 +385,7 @@ def print_full_documentation(self, stream=None): print(self.get_full_documentation()[:-1], file=stream) @staticmethod - def _print_checker_doc(checker, information, stream=None): + def _print_checker_doc(information, stream=None): """Helper method for print_full_documentation. Also used by doc/exts/pylint_extensions.py. From 3ebeef180ef376a5058e23cdd30ef08168748f77 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 09:25:17 +0200 Subject: [PATCH 24/31] Fix - W0612: Unused variable 'checker_name' --- pylint/message/message_handler_mix_in.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index c34aceee05..1c8ab400ba 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -373,7 +373,8 @@ def get_full_documentation(self): """ by_checker = self._get_checkers_infos() - for checker_name, information in sorted(by_checker.items()): + for checker in sorted(by_checker): + information = by_checker[checker] checker = information["checker"] result += checker.get_full_documentation(information) return result From 13a69ca2cd14ddb0216e53eb731333c4f3519a8d Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 10:10:44 +0200 Subject: [PATCH 25/31] Fix - Remove invalid syntax in python 3.4 Mypy requirements and python 3.4 seem incompatible. --- pylint/checkers/base_checker.py | 2 +- pylint/message/message_handler_mix_in.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index f73f946285..ca5f88082b 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -105,7 +105,7 @@ def add_message( confidence = UNDEFINED self.linter.add_message(msgid, line, node, args, confidence, col_offset) - def check_consistency(self) -> None: + def check_consistency(self): """Check the consistency of msgid. msg ids for a checker should be a string of len 4, where the two first diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 1c8ab400ba..25f862f9e6 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -325,7 +325,7 @@ def add_one_message( ) def _get_checkers_infos(self): - by_checker: dict = {} + by_checker = {} for checker in self.get_checkers(): name = checker.name if name != "master": From 33d8586bda87cc7430d8806036e1dc03221c88ee Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 10:37:32 +0200 Subject: [PATCH 26/31] Refactor - Clearer function name ('rest' -> 'rst') in utils I used the old name but there was probably a typo in it, as the format is called rst. --- doc/exts/pylint_extensions.py | 4 ++-- pylint/checkers/base_checker.py | 14 +++++++------- pylint/message/message_handler_mix_in.py | 12 ++++++------ pylint/utils/__init__.py | 4 ++-- pylint/utils/utils.py | 10 +++++----- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index 01ba8a2b1c..c12c4fcdd7 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -12,7 +12,7 @@ from pylint.constants import MAIN_CHECKER_NAME from pylint.lint import PyLinter -from pylint.utils import get_rest_title +from pylint.utils import get_rst_title # Some modules have been renamed and deprecated under their old names. # Skip documenting these modules since: @@ -52,7 +52,7 @@ def builder_inited(app): ) with open(extensions_doc, "w") as stream: stream.write( - get_rest_title("Optional Pylint checkers in the extensions module", "=") + get_rst_title("Optional Pylint checkers in the extensions module", "=") ) stream.write("Pylint provides the following optional plugins:\n\n") for module in modules: diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index ca5f88082b..fcc5fb7af3 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -19,7 +19,7 @@ from pylint.exceptions import InvalidMessageError from pylint.interfaces import UNDEFINED, IRawChecker, ITokenChecker, implements from pylint.message.message_definition import MessageDefinition -from pylint.utils import get_rest_title, rest_format_section +from pylint.utils import get_rst_section, get_rst_title class BaseChecker(OptionsProviderMixIn): @@ -71,19 +71,19 @@ def get_full_documentation(info): if module: # Provide anchor to link against result += ".. _%s:\n\n" % module - result += "%s\n" % get_rest_title(checker_title, "~") + result += "%s\n" % get_rst_title(checker_title, "~") if module: result += "This checker is provided by ``%s``.\n" % module result += "Verbatim name of the checker is ``%s``.\n\n" % checker.name if doc: # Provide anchor to link against - result += get_rest_title("{} Documentation".format(checker_title), "^") + result += get_rst_title("{} Documentation".format(checker_title), "^") result += "%s\n\n" % cleandoc(doc) if options: - result += get_rest_title("{} Options".format(checker_title), "^") - result += "%s\n" % rest_format_section(None, options) + result += get_rst_title("{} Options".format(checker_title), "^") + result += "%s\n" % get_rst_section(None, options) if msgs: - result += get_rest_title("{} Messages".format(checker_title), "^") + result += get_rst_title("{} Messages".format(checker_title), "^") for msgid, msg in sorted( msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) ): @@ -91,7 +91,7 @@ def get_full_documentation(info): result += "%s\n" % msg.format_help(checkerref=False) result += "\n" if reports: - result += get_rest_title("{} Reports".format(checker_title), "^") + result += get_rst_title("{} Reports".format(checker_title), "^") for report in reports: result += ":%s: %s\n" % report[:2] result += "\n" diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 25f862f9e6..220efb2ad2 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -23,8 +23,8 @@ from pylint.utils import ( category_id, get_module_and_frameid, - get_rest_title, - rest_format_section, + get_rst_section, + get_rst_title, ) @@ -344,7 +344,7 @@ def _get_checkers_infos(self): return by_checker def get_full_documentation(self): - result = get_rest_title("Pylint global options and switches", "-") + result = get_rst_title("Pylint global options and switches", "-") result += """ Pylint provides global options and switches. @@ -358,9 +358,9 @@ def get_full_documentation(self): title = "General options" else: title = "%s options" % section.capitalize() - result += get_rest_title(title, "~") - result += "%s\n" % rest_format_section(None, options) - result += get_rest_title("Pylint checkers' options and switches", "-") + result += get_rst_title(title, "~") + result += "%s\n" % get_rst_section(None, options) + result += get_rst_title("Pylint checkers' options and switches", "-") result += """\ Pylint checkers can provide three set of features: diff --git a/pylint/utils/__init__.py b/pylint/utils/__init__.py index 8f1a8e4d65..afde963925 100644 --- a/pylint/utils/__init__.py +++ b/pylint/utils/__init__.py @@ -56,10 +56,10 @@ format_section, get_global_option, get_module_and_frameid, - get_rest_title, + get_rst_section, + get_rst_title, normalize_text, register_plugins, - rest_format_section, safe_decode, tokenize_module, ) diff --git a/pylint/utils/utils.py b/pylint/utils/utils.py index c2216575f0..81cbc34484 100644 --- a/pylint/utils/utils.py +++ b/pylint/utils/utils.py @@ -51,16 +51,16 @@ def category_id(cid): return MSG_TYPES_LONG.get(cid) -def get_rest_title(title, character): - """Permit to get a rest title underlined with a choosen character.""" +def get_rst_title(title, character): + """Permit to get a title formatted as ReStructuredText test (underlined with a chosen character).""" return "%s\n%s\n" % (title, character * len(title)) -def rest_format_section(section, options, doc=None): - """format an options section using as ReST formatted output""" +def get_rst_section(section, options, doc=None): + """format an options section using as a ReStructuredText formatted output""" result = "" if section: - result += get_rest_title(section, "'") + result += get_rst_title(section, "'") if doc: formatted_doc = normalize_text(doc, line_len=79, indent="") result += "%s\n\n" % formatted_doc From dc1652e89942e6dd56e459bc2b371001d98081c6 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 10 Jun 2019 21:49:16 +0200 Subject: [PATCH 27/31] Refactor - Use self directly in checker get_full_documentation --- pylint/checkers/base_checker.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index fcc5fb7af3..2e9c027347 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -58,23 +58,21 @@ def __repr__(self): status, self.name, ", ".join(self.msgs.keys()) ) - @staticmethod - def get_full_documentation(info): + def get_full_documentation(self, info): result = "" - checker = info.get("checker") doc = info.get("doc") module = info.get("module") msgs = info.get("msgs") options = info.get("options") reports = info.get("reports") - checker_title = "%s checker" % (checker.name.replace("_", " ").title()) + checker_title = "%s checker" % (self.name.replace("_", " ").title()) if module: # Provide anchor to link against result += ".. _%s:\n\n" % module result += "%s\n" % get_rst_title(checker_title, "~") if module: result += "This checker is provided by ``%s``.\n" % module - result += "Verbatim name of the checker is ``%s``.\n\n" % checker.name + result += "Verbatim name of the checker is ``%s``.\n\n" % self.name if doc: # Provide anchor to link against result += get_rst_title("{} Documentation".format(checker_title), "^") @@ -87,7 +85,7 @@ def get_full_documentation(info): for msgid, msg in sorted( msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1]) ): - msg = checker.create_message_definition_from_tuple(msgid, msg) + msg = self.create_message_definition_from_tuple(msgid, msg) result += "%s\n" % msg.format_help(checkerref=False) result += "\n" if reports: From f720432042cd73afc501b227f78146ad61a727fc Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 12 Jun 2019 20:28:23 +0200 Subject: [PATCH 28/31] Refactor - Giving multiple parameters instead of a dict This make the understanding of the function easier. --- pylint/checkers/base_checker.py | 7 +------ pylint/message/message_handler_mix_in.py | 6 ++++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 2e9c027347..f308f15574 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -58,13 +58,8 @@ def __repr__(self): status, self.name, ", ".join(self.msgs.keys()) ) - def get_full_documentation(self, info): + def get_full_documentation(self, msgs, options, reports, doc=None, module=None): result = "" - doc = info.get("doc") - module = info.get("module") - msgs = info.get("msgs") - options = info.get("options") - reports = info.get("reports") checker_title = "%s checker" % (self.name.replace("_", " ").title()) if module: # Provide anchor to link against diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 220efb2ad2..8f1375b1e0 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -376,7 +376,8 @@ def get_full_documentation(self): for checker in sorted(by_checker): information = by_checker[checker] checker = information["checker"] - result += checker.get_full_documentation(information) + del information["checker"] + result += checker.get_full_documentation(**information) return result def print_full_documentation(self, stream=None): @@ -394,4 +395,5 @@ def _print_checker_doc(information, stream=None): if not stream: stream = sys.stdout checker = information["checker"] - print(checker.get_full_documentation(information)[:-1], file=stream) + del information["checker"] + print(checker.get_full_documentation(**information)[:-1], file=stream) From e322bc5f1e33fbde5571c02d23bd274e9dbda0b0 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 12 Jun 2019 21:20:59 +0200 Subject: [PATCH 29/31] Feat - Add a __str__ function to BaseChecker --- pylint/checkers/base_checker.py | 9 +++++ tests/unittest_checker_base.py | 62 ++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index f308f15574..8229aab056 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -58,6 +58,13 @@ def __repr__(self): status, self.name, ", ".join(self.msgs.keys()) ) + def __str__(self): + """This might be incomplete because multiple class inheriting BaseChecker + can have the same name. Cf MessageHandlerMixIn.get_full_documentation()""" + return self.get_full_documentation( + msgs=self.msgs, options=self.options_and_values(), reports=self.reports + ) + def get_full_documentation(self, msgs, options, reports, doc=None, module=None): result = "" checker_title = "%s checker" % (self.name.replace("_", " ").title()) @@ -72,6 +79,8 @@ def get_full_documentation(self, msgs, options, reports, doc=None, module=None): # Provide anchor to link against result += get_rst_title("{} Documentation".format(checker_title), "^") result += "%s\n\n" % cleandoc(doc) + # options might be an empty generator and not be False when casted to boolean + options = list(options) if options: result += get_rst_title("{} Options".format(checker_title), "^") result += "%s\n" % get_rst_section(None, options) diff --git a/tests/unittest_checker_base.py b/tests/unittest_checker_base.py index 1feae5b7ac..b50fbf1a65 100644 --- a/tests/unittest_checker_base.py +++ b/tests/unittest_checker_base.py @@ -23,7 +23,7 @@ import astroid -from pylint.checkers import base +from pylint.checkers import BaseChecker, base from pylint.testutils import CheckerTestCase, Message, set_config @@ -526,3 +526,63 @@ def test_pascal_case(self): self._test_name_is_incorrect_for_all_name_types(naming_style, name) self._test_should_always_pass(naming_style) + + +class TestBaseChecker(unittest.TestCase): + def test_doc(self): + class OtherBasicChecker(BaseChecker): + name = "basic" + msgs = { + "W0001": ( + "Basic checker has an example.", + "basic-checker-example", + "Used nowhere and serves no purpose.", + ) + } + + class LessBasicChecker(OtherBasicChecker): + options = ( + ( + "example-args", + { + "default": 42, + "type": "int", + "metavar": "", + "help": "Example of integer argument for the checker.", + }, + ), + ) + + basic = OtherBasicChecker() + expected_beginning = """\ +Basic checker +~~~~~~~~~~~~~ + +Verbatim name of the checker is ``basic``. + +""" + expected_middle = """\ +Basic checker Options +^^^^^^^^^^^^^^^^^^^^^ +:example-args: + Example of integer argument for the checker. + + Default: ``42`` + +""" + expected_end = """\ +Basic checker Messages +^^^^^^^^^^^^^^^^^^^^^^ +:basic-checker-example (W0001): *Basic checker has an example.* + Used nowhere and serves no purpose. + + +""" + self.assertEqual(str(basic), expected_beginning + expected_end) + self.assertEqual(repr(basic), "Checker 'basic' responsible for W0001") + less_basic = LessBasicChecker() + + self.assertEqual( + str(less_basic), expected_beginning + expected_middle + expected_end + ) + self.assertEqual(repr(less_basic), repr(basic)) From 1208b381a999e0c9da4ff71e8042ee939b0c0dbf Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 20 Jun 2019 13:00:51 +0200 Subject: [PATCH 30/31] Refactor - Remove unused argument 'name' --- doc/exts/pylint_extensions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index c12c4fcdd7..157850837b 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -93,7 +93,6 @@ def get_plugins_info(linter, doc_files): by_checker[checker]["msgs"].update(checker.msgs) by_checker[checker]["reports"] += checker.reports by_checker[checker]["doc"] += doc - by_checker[checker]["name"] += checker.name by_checker[checker]["module"] += module except KeyError: by_checker[checker] = { @@ -102,7 +101,6 @@ def get_plugins_info(linter, doc_files): "msgs": dict(checker.msgs), "reports": list(checker.reports), "doc": doc, - "name": checker.name, "module": module, } return by_checker From 0918e02a243d59121536abe0cf9f87d11fee8800 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 20 Jun 2019 13:04:46 +0200 Subject: [PATCH 31/31] Refactor - Rename an overlapsing function in MessageHandlerMixIn BaseChecker and MessageHandlerMixIn can be the same instance. --- pylint/message/message_handler_mix_in.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylint/message/message_handler_mix_in.py b/pylint/message/message_handler_mix_in.py index 8f1375b1e0..06e1368bac 100644 --- a/pylint/message/message_handler_mix_in.py +++ b/pylint/message/message_handler_mix_in.py @@ -343,7 +343,7 @@ def _get_checkers_infos(self): } return by_checker - def get_full_documentation(self): + def get_checkers_documentation(self): result = get_rst_title("Pylint global options and switches", "-") result += """ Pylint provides global options and switches. @@ -384,7 +384,7 @@ def print_full_documentation(self, stream=None): """output a full documentation in ReST format""" if not stream: stream = sys.stdout - print(self.get_full_documentation()[:-1], file=stream) + print(self.get_checkers_documentation()[:-1], file=stream) @staticmethod def _print_checker_doc(information, stream=None):