From 3afa971f70a18e063fbcb05c5a35e8d36840c038 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 12 Oct 2023 13:57:06 +0200 Subject: [PATCH] [configuration] Create a data structure to store breaking changes (#9088) In order to be able to automate the fix later in #5462 --- pylint/config/_breaking_changes.py | 97 ++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 pylint/config/_breaking_changes.py diff --git a/pylint/config/_breaking_changes.py b/pylint/config/_breaking_changes.py new file mode 100644 index 0000000000..943f708aa8 --- /dev/null +++ b/pylint/config/_breaking_changes.py @@ -0,0 +1,97 @@ +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE +# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt + +"""List the breaking changes in configuration files and their solutions.""" + +from __future__ import annotations + +import enum +from typing import NamedTuple + + +class BreakingChange(enum.Enum): + MESSAGE_MADE_DISABLED_BY_DEFAULT = "{symbol} ({msgid}) was disabled by default" + MESSAGE_MADE_ENABLED_BY_DEFAULT = "{symbol} ({msgid}) was enabled by default" + MESSAGE_MOVED_TO_EXTENSION = "{symbol} ({msgid}) was moved to {extension}" + EXTENSION_REMOVED = "{extension} was removed" + # This kind of upgrade is non-breaking but if we want to automatically upgrade it, + # then we should use the message store and old_names values instead of duplicating + # MESSAGE_RENAMED= "{symbol} ({msgid}) was renamed" + + +class Condition(enum.Enum): + MESSAGE_IS_ENABLED = "{symbol} ({msgid}) is enabled" + MESSAGE_IS_NOT_ENABLED = "{symbol} ({msgid}) is not enabled" + MESSAGE_IS_DISABLED = "{symbol} ({msgid}) is disabled" + MESSAGE_IS_NOT_DISABLED = "{symbol} ({msgid}) is not disabled" + EXTENSION_IS_LOADED = "{extension} is loaded" + EXTENSION_IS_NOT_LOADED = "{extension} is not loaded" + + +class Information(NamedTuple): + msgid_or_symbol: str + extension: str | None + + +class Solution(enum.Enum): + ADD_EXTENSION = "Add {extension} in 'load-plugins' option" + REMOVE_EXTENSION = "Remove {extension} from the 'load-plugins' option" + ENABLE_MESSAGE_EXPLICITLY = ( + "{symbol} ({msgid}) should be added in the 'enable' option" + ) + ENABLE_MESSAGE_IMPLICITLY = ( + "{symbol} ({msgid}) should be removed from the 'disable' option" + ) + DISABLE_MESSAGE_EXPLICITLY = ( + "{symbol} ({msgid}) should be added in the 'disable' option" + ) + DISABLE_MESSAGE_IMPLICITLY = ( + "{symbol} ({msgid}) should be removed from the 'enable' option" + ) + + +ConditionsToBeAffected = list[Condition] +# A solution to a breaking change might imply multiple actions +MultipleActionSolution = list[Solution] +# Sometimes there's multiple solutions and the user needs to choose +Solutions = list[MultipleActionSolution] +BreakingChangeWithSolution = tuple[ + BreakingChange, Information, ConditionsToBeAffected, Solutions +] + +NO_SELF_USE = Information( + msgid_or_symbol="no-self-use", extension="pylint.extensions.no_self_use" +) +COMPARE_TO_ZERO = Information( + msgid_or_symbol="compare-to-zero", extension="pylint.extensions.comparetozero" +) +COMPARE_TO_EMPTY_STRING = Information( + msgid_or_symbol="compare-to-empty-string", + extension="pylint.extensions.emptystring", +) + +CONFIGURATION_BREAKING_CHANGES: dict[str, list[BreakingChangeWithSolution]] = { + "2.14.0": [ + ( + BreakingChange.MESSAGE_MOVED_TO_EXTENSION, + NO_SELF_USE, + [Condition.MESSAGE_IS_ENABLED, Condition.EXTENSION_IS_NOT_LOADED], + [[Solution.ADD_EXTENSION], [Solution.DISABLE_MESSAGE_IMPLICITLY]], + ), + ], + "3.0.0": [ + ( + BreakingChange.EXTENSION_REMOVED, + COMPARE_TO_ZERO, + [Condition.MESSAGE_IS_NOT_DISABLED, Condition.EXTENSION_IS_LOADED], + [[Solution.REMOVE_EXTENSION, Solution.ENABLE_MESSAGE_EXPLICITLY]], + ), + ( + BreakingChange.EXTENSION_REMOVED, + COMPARE_TO_EMPTY_STRING, + [Condition.MESSAGE_IS_NOT_DISABLED, Condition.EXTENSION_IS_LOADED], + [[Solution.REMOVE_EXTENSION, Solution.ENABLE_MESSAGE_EXPLICITLY]], + ), + ], +}