From d690dd88e71b32300633721cba9fadd704766b01 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 07:44:48 +0200 Subject: [PATCH] Exempt parents with only annotations from `invalid-enum-extension` (#8834) (#8835) (cherry picked from commit 538a8fe19644b74cfb2b0f4c3d27273e8cef7a09) Co-authored-by: Jacob Walls --- doc/whatsnew/fragments/8830.false_positive | 4 +++ pylint/checkers/classes/class_checker.py | 21 ++++++++++----- .../i/invalid/invalid_enum_extension.py | 27 +++++++++++++++++++ .../i/invalid/invalid_enum_extension.txt | 1 + 4 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 doc/whatsnew/fragments/8830.false_positive diff --git a/doc/whatsnew/fragments/8830.false_positive b/doc/whatsnew/fragments/8830.false_positive new file mode 100644 index 0000000000..1d7edeeb4f --- /dev/null +++ b/doc/whatsnew/fragments/8830.false_positive @@ -0,0 +1,4 @@ +Exempt parents with only type annotations from the ``invalid-enum-extension`` +message. + +Closes #8830 diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index 9b0bd50b1d..995e3cfd90 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -891,12 +891,21 @@ def _check_consistent_mro(self, node: nodes.ClassDef) -> None: def _check_enum_base(self, node: nodes.ClassDef, ancestor: nodes.ClassDef) -> None: members = ancestor.getattr("__members__") if members and isinstance(members[0], nodes.Dict) and members[0].items: - self.add_message( - "invalid-enum-extension", - args=ancestor.name, - node=node, - confidence=INFERENCE, - ) + for _, name_node in members[0].items: + # Exempt type annotations without value assignments + if all( + isinstance(item.parent, nodes.AnnAssign) + and item.parent.value is None + for item in ancestor.getattr(name_node.name) + ): + continue + self.add_message( + "invalid-enum-extension", + args=ancestor.name, + node=node, + confidence=INFERENCE, + ) + break if ancestor.is_subtype_of("enum.IntFlag"): # Collect integer flag assignments present on the class diff --git a/tests/functional/i/invalid/invalid_enum_extension.py b/tests/functional/i/invalid/invalid_enum_extension.py index 5af11af387..9ccb458af3 100644 --- a/tests/functional/i/invalid/invalid_enum_extension.py +++ b/tests/functional/i/invalid/invalid_enum_extension.py @@ -21,6 +21,33 @@ class D(C): x = 3 +# Similarly, items that are only type annotations are okay. +class ColorEnum(Enum): + red: int + green: int + blue: int + + def __init__(self, red: int, green: int, blue: int) -> None: + self.red = red + self.green = green + self.blue = blue + + +class Pastel(ColorEnum): + SAGE = (170, 200, 167) + + +class IncorrectColorEnum(Enum): + red: None = None + + def __init__(self, red: None) -> None: + self.red = red + + +class IncorrectPastel(IncorrectColorEnum): # [invalid-enum-extension] + SOME_COLOR = 170 + + class CustomFlags(IntFlag): SUPPORT_OPEN = 1 SUPPORT_CLOSE = 2 diff --git a/tests/functional/i/invalid/invalid_enum_extension.txt b/tests/functional/i/invalid/invalid_enum_extension.txt index dbe799e08b..42f0deaf28 100644 --- a/tests/functional/i/invalid/invalid_enum_extension.txt +++ b/tests/functional/i/invalid/invalid_enum_extension.txt @@ -1 +1,2 @@ invalid-enum-extension:12:0:12:7:B:"Extending inherited Enum class ""A""":INFERENCE +invalid-enum-extension:47:0:47:21:IncorrectPastel:"Extending inherited Enum class ""IncorrectColorEnum""":INFERENCE