From e1da3c03d2b91f56b0977480856c2a2a6501758a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 31 Aug 2021 12:27:19 +0200 Subject: Fix false positive ``protected-access`` in typing (#4937) * Fix false positive ``protected-access`` in typing Class functions can return protected members which can then be passed as arguments to other functions. When using type hints in function definitions these raised a message which they shouldn't do. --- ChangeLog | 2 ++ doc/whatsnew/2.10.rst | 3 -- doc/whatsnew/2.11.rst | 10 +++++-- pylint/checkers/classes.py | 8 ++++-- .../a/access/access_to_protected_members_typing.py | 32 ++++++++++++++++++++++ .../a/access/access_to_protected_members_typing.rc | 2 ++ .../access/access_to_protected_members_typing.txt | 0 7 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 tests/functional/a/access/access_to_protected_members_typing.py create mode 100644 tests/functional/a/access/access_to_protected_members_typing.rc create mode 100644 tests/functional/a/access/access_to_protected_members_typing.txt diff --git a/ChangeLog b/ChangeLog index c0d6cb3a7..043639dc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,6 +43,8 @@ Release date: TBA Closes #4936 +* Fix false positive for ``protected-access`` if a protected member is used in type hints of function definitions + What's New in Pylint 2.10.3? ============================ diff --git a/doc/whatsnew/2.10.rst b/doc/whatsnew/2.10.rst index 09fc52870..85cba1c3f 100644 --- a/doc/whatsnew/2.10.rst +++ b/doc/whatsnew/2.10.rst @@ -82,9 +82,6 @@ Other Changes * ``consider-using-with`` is no longer triggered if a context manager is returned from a function. -* Fix false positive for ``consider-using-with`` if a context manager is assigned to a - variable in different paths of control flow (e. g. if-else clause). - * pylint does not crash with a traceback anymore when a file is problematic. It creates a template text file for opening an issue on the bug tracker instead. The linting can go on for other non problematic files instead of being impossible. diff --git a/doc/whatsnew/2.11.rst b/doc/whatsnew/2.11.rst index c2333911f..8524c0a90 100644 --- a/doc/whatsnew/2.11.rst +++ b/doc/whatsnew/2.11.rst @@ -20,13 +20,11 @@ New checkers Extensions ========== - * Added new extension ``SetMembershipChecker`` with ``use-set-for-membership`` check: Emitted when using an in-place defined ``list`` or ``tuple`` to do a membership test. ``sets`` are better optimized for that. Closes #4776 - * ``CodeStyleChecker`` * Added ``consider-using-assignment-expr``: Emitted when an assignment is directly followed by an if statement @@ -40,8 +38,16 @@ Other Changes * Added ``py-version`` config key (if ``[MASTER]`` section). Used for version dependant checks. Will default to whatever Python version pylint is executed with. + * The ``invalid-name`` message is now more detailed when using multiple naming style regexes. +* Fix false positive for ``consider-using-with`` if a context manager is assigned to a + variable in different paths of control flow (e. g. if-else clause). + + Closes #4751 + * Fix false positive for ``function-redefined`` for simple type annotations Closes #4936 + +* Fix false positive for ``protected-access`` if a protected member is used in type hints of function definitions diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index 3b18b7e00..0b37a9f53 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -52,7 +52,7 @@ from typing import List, Pattern, cast import astroid from astroid import nodes -from pylint.checkers import BaseChecker +from pylint.checkers import BaseChecker, utils from pylint.checkers.utils import ( PYMETHODS, SPECIAL_METHODS_PARAMS, @@ -1563,7 +1563,7 @@ a metaclass class method.", if any(method_name == member.name for member in parent_class.mymethods()): self.add_message(msg, node=node.targets[0]) - def _check_protected_attribute_access(self, node): + def _check_protected_attribute_access(self, node: nodes.Attribute): """Given an attribute access node (set or get), check if attribute access is legitimate. Call _check_first_attr with node before calling this method. Valid cases are: @@ -1586,6 +1586,10 @@ a metaclass class method.", # through the class object or through super callee = node.expr.as_string() + # Typing annotations in funciton definitions can include protected members + if utils.is_node_in_type_annotation_context(node): + return + # We are not in a class, no remaining valid case if klass is None: self.add_message("protected-access", node=node, args=attrname) diff --git a/tests/functional/a/access/access_to_protected_members_typing.py b/tests/functional/a/access/access_to_protected_members_typing.py new file mode 100644 index 000000000..4e5eee4c6 --- /dev/null +++ b/tests/functional/a/access/access_to_protected_members_typing.py @@ -0,0 +1,32 @@ +# pylint: disable=too-few-public-methods, invalid-name +"""Test typing with a protected member""" +from __future__ import annotations + + +class MyClass: + """Class with protected members.""" + + class _Inner_Class: + """Inner class with protected members.""" + + def __init__(self) -> None: + self.data = 1 + + def return_data(self) -> int: + """Return data""" + return self.data + + def return_private_class(self) -> MyClass._Inner_Class: + """Doing nothing.""" + return self._Inner_Class() + + +def access_protected_class(data: MyClass._Inner_Class) -> int: + """Function that always receives a protected class.""" + return data.return_data() + 1 + + +def pass_protected_class() -> None: + """Function that passes a protected class to another function.""" + data_value = access_protected_class(MyClass().return_private_class()) + print(data_value) diff --git a/tests/functional/a/access/access_to_protected_members_typing.rc b/tests/functional/a/access/access_to_protected_members_typing.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/a/access/access_to_protected_members_typing.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/a/access/access_to_protected_members_typing.txt b/tests/functional/a/access/access_to_protected_members_typing.txt new file mode 100644 index 000000000..e69de29bb -- cgit v1.2.1