diff --git a/doc/whatsnew/fragments/10019.false_positive b/doc/whatsnew/fragments/10019.false_positive new file mode 100644 index 0000000000..5d1ce7d0ce --- /dev/null +++ b/doc/whatsnew/fragments/10019.false_positive @@ -0,0 +1,3 @@ +Exclude ``__all__`` and ``__future__.annotations`` from ``unused-variable``. + +Closes #10019 diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 9d0c6ba6a6..ffda243fd2 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -3285,6 +3285,14 @@ def _check_globals(self, not_consumed: Consumption) -> None: continue if self._is_exception_binding_used_in_handler(node, name): continue + if isinstance(node, nodes.AssignName) and node.name == "__all__": + continue + if ( + isinstance(node, nodes.ImportFrom) + and name == "annotations" + and node.modname == "__future__" + ): + continue self.add_message("unused-variable", args=(name,), node=node) # pylint: disable = too-many-branches diff --git a/tests/functional/u/unused/unused_variable_future_and_annotations.py b/tests/functional/u/unused/unused_variable_future_and_annotations.py new file mode 100644 index 0000000000..d59f885e37 --- /dev/null +++ b/tests/functional/u/unused/unused_variable_future_and_annotations.py @@ -0,0 +1,11 @@ +"""Test `unused-variable` is not emitted for either case of `__future__.annotations` or `__all__`""" + + +from __future__ import annotations + + +__all__ = [ "apple" ] + + +def apple(): + """A public function""" diff --git a/tests/functional/u/unused/unused_variable_future_and_annotations.rc b/tests/functional/u/unused/unused_variable_future_and_annotations.rc new file mode 100644 index 0000000000..5dcd4a84c4 --- /dev/null +++ b/tests/functional/u/unused/unused_variable_future_and_annotations.rc @@ -0,0 +1,2 @@ +[variables] +allow-global-unused-variables=no