Path 1: 2857 calls (0.97)

Attribute (2786) AssignAttr (71)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 2: 19 calls (0.01)

AssignAttr (10) Attribute (9)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 3: 10 calls (0.0)

Attribute (10)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 4: 10 calls (0.0)

AssignAttr (10)

None (10)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 5: 8 calls (0.0)

Attribute (8)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 6: 8 calls (0.0)

Attribute (6) AssignAttr (2)

None (8)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 7: 7 calls (0.0)

AssignAttr (6) Attribute (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 8: 6 calls (0.0)

Attribute (6)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 9: 5 calls (0.0)

Attribute (3) AssignAttr (2)

None (5)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 10: 3 calls (0.0)

Attribute (2) AssignAttr (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 11: 3 calls (0.0)

Attribute (3)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 12: 2 calls (0.0)

Attribute (2)

None (2)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 13: 2 calls (0.0)

AssignAttr (2)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 14: 2 calls (0.0)

Attribute (2)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 15: 2 calls (0.0)

Attribute (2)

None (2)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 16: 1 calls (0.0)

AssignAttr (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 17: 1 calls (0.0)

Attribute (1)

None (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 18: 1 calls (0.0)

Attribute (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 19: 1 calls (0.0)

Attribute (1)

None (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 20: 1 calls (0.0)

Attribute (1)

None (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 21: 1 calls (0.0)

Attribute (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 22: 1 calls (0.0)

Attribute (1)

None (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 23: 1 calls (0.0)

Attribute (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 24: 1 calls (0.0)

Attribute (1)

None (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)
            

Path 25: 1 calls (0.0)

Attribute (1)

1def _check_protected_attribute_access(
2        self, node: nodes.Attribute | nodes.AssignAttr
3    ) -> None:
4        """Given an attribute access node (set or get), check if attribute
5        access is legitimate.
6
7        Call _check_first_attr with node before calling
8        this method. Valid cases are:
9        * self._attr in a method or cls._attr in a classmethod. Checked by
10        _check_first_attr.
11        * Klass._attr inside "Klass" class.
12        * Klass2._attr inside "Klass" class when Klass2 is a base class of
13            Klass.
14        """
15        attrname = node.attrname
16        if (
17            is_attr_protected(attrname)
18            and attrname not in self.linter.config.exclude_protected
19        ):
20            klass = node_frame_class(node)
21
22            # In classes, check we are not getting a parent method
23            # through the class object or through super
24            callee = node.expr.as_string()
25
26            # Typing annotations in function definitions can include protected members
27            if utils.is_node_in_type_annotation_context(node):
28                return
29
30            # We are not in a class, no remaining valid case
31            if klass is None:
32                self.add_message("protected-access", node=node, args=attrname)
33                return
34
35            # If the expression begins with a call to super, that's ok.
36            if (
37                isinstance(node.expr, nodes.Call)
38                and isinstance(node.expr.func, nodes.Name)
39                and node.expr.func.name == "super"
40            ):
41                return
42
43            # If the expression begins with a call to type(self), that's ok.
44            if self._is_type_self_call(node.expr):
45                return
46
47            # Check if we are inside the scope of a class or nested inner class
48            inside_klass = True
49            outer_klass = klass
50            parents_callee = callee.split(".")
51            parents_callee.reverse()
52            for callee in parents_callee:
53                if not outer_klass or callee != outer_klass.name:
54                    inside_klass = False
55                    break
56
57                # Move up one level within the nested classes
58                outer_klass = get_outer_class(outer_klass)
59
60            # We are in a class, one remaining valid cases, Klass._attr inside
61            # Klass
62            if not (inside_klass or callee in klass.basenames):
63                # Detect property assignments in the body of the class.
64                # This is acceptable:
65                #
66                # class A:
67                #     b = property(lambda: self._b)
68
69                stmt = node.parent.statement(future=True)
70                if (
71                    isinstance(stmt, nodes.Assign)
72                    and len(stmt.targets) == 1
73                    and isinstance(stmt.targets[0], nodes.AssignName)
74                ):
75                    name = stmt.targets[0].name
76                    if _is_attribute_property(name, klass):
77                        return
78
79                if (
80                    self._is_classmethod(node.frame(future=True))
81                    and self._is_inferred_instance(node.expr, klass)
82                    and self._is_class_or_instance_attribute(attrname, klass)
83                ):
84                    return
85
86                licit_protected_member = not attrname.startswith("__")
87                if (
88                    not self.linter.config.check_protected_access_in_special_methods
89                    and licit_protected_member
90                    and self._is_called_inside_special_method(node)
91                ):
92                    return
93
94                self.add_message("protected-access", node=node, args=attrname)