Path 1: 608 calls (0.98)

Name (355) Attribute (67) Call (64) Const (57) Subscript (16) BinOp (15) List (10) Tuple (9) NamedExpr (7) Dict (3)

Const (395) Name (110) Attribute (24) Call (19) List (18) Dict (17) Tuple (7) Compare (4) BinOp (3) UnaryOp (3)

Compare (608)

False (504) True (104)

None (608)

1def _check_nan_comparison(
2        self,
3        left_value: nodes.NodeNG,
4        right_value: nodes.NodeNG,
5        root_node: nodes.Compare,
6        checking_for_absence: bool = False,
7    ) -> None:
8        def _is_float_nan(node: nodes.NodeNG) -> bool:
9            try:
10                if isinstance(node, nodes.Call) and len(node.args) == 1:
11                    if (
12                        node.args[0].value.lower() == "nan"
13                        and node.inferred()[0].pytype() == "builtins.float"
14                    ):
15                        return True
16                return False
17            except AttributeError:
18                return False
19
20        def _is_numpy_nan(node: nodes.NodeNG) -> bool:
21            if isinstance(node, nodes.Attribute) and node.attrname == "NaN":
22                if isinstance(node.expr, nodes.Name):
23                    return node.expr.name in {"numpy", "nmp", "np"}
24            return False
25
26        def _is_nan(node: nodes.NodeNG) -> bool:
27            return _is_float_nan(node) or _is_numpy_nan(node)
28
29        nan_left = _is_nan(left_value)
30        if not nan_left and not _is_nan(right_value):
31            return
32
33        absence_text = ""
34        if checking_for_absence:
35            absence_text = "not "
36        if nan_left:
37            suggestion = f"'{absence_text}math.isnan({right_value.as_string()})'"
38        else:
39            suggestion = f"'{absence_text}math.isnan({left_value.as_string()})'"
40        self.add_message(
41            "nan-comparison",
42            node=root_node,
43            args=(f"'{root_node.as_string()}'", suggestion),
44        )
            

Path 2: 7 calls (0.01)

Name (7)

Attribute (5) Call (2)

Compare (7)

False (7)

1def _check_nan_comparison(
2        self,
3        left_value: nodes.NodeNG,
4        right_value: nodes.NodeNG,
5        root_node: nodes.Compare,
6        checking_for_absence: bool = False,
7    ) -> None:
8        def _is_float_nan(node: nodes.NodeNG) -> bool:
9            try:
10                if isinstance(node, nodes.Call) and len(node.args) == 1:
11                    if (
12                        node.args[0].value.lower() == "nan"
13                        and node.inferred()[0].pytype() == "builtins.float"
14                    ):
15                        return True
16                return False
17            except AttributeError:
18                return False
19
20        def _is_numpy_nan(node: nodes.NodeNG) -> bool:
21            if isinstance(node, nodes.Attribute) and node.attrname == "NaN":
22                if isinstance(node.expr, nodes.Name):
23                    return node.expr.name in {"numpy", "nmp", "np"}
24            return False
25
26        def _is_nan(node: nodes.NodeNG) -> bool:
27            return _is_float_nan(node) or _is_numpy_nan(node)
28
29        nan_left = _is_nan(left_value)
30        if not nan_left and not _is_nan(right_value):
31            return
32
33        absence_text = ""
34        if checking_for_absence:
35            absence_text = "not "
36        if nan_left:
37            suggestion = f"'{absence_text}math.isnan({right_value.as_string()})'"
38        else:
39            suggestion = f"'{absence_text}math.isnan({left_value.as_string()})'"
40        self.add_message(
41            "nan-comparison",
42            node=root_node,
43            args=(f"'{root_node.as_string()}'", suggestion),
44        )
            

Path 3: 4 calls (0.01)

Name (4)

Attribute (2) Call (2)

Compare (4)

True (4)

1def _check_nan_comparison(
2        self,
3        left_value: nodes.NodeNG,
4        right_value: nodes.NodeNG,
5        root_node: nodes.Compare,
6        checking_for_absence: bool = False,
7    ) -> None:
8        def _is_float_nan(node: nodes.NodeNG) -> bool:
9            try:
10                if isinstance(node, nodes.Call) and len(node.args) == 1:
11                    if (
12                        node.args[0].value.lower() == "nan"
13                        and node.inferred()[0].pytype() == "builtins.float"
14                    ):
15                        return True
16                return False
17            except AttributeError:
18                return False
19
20        def _is_numpy_nan(node: nodes.NodeNG) -> bool:
21            if isinstance(node, nodes.Attribute) and node.attrname == "NaN":
22                if isinstance(node.expr, nodes.Name):
23                    return node.expr.name in {"numpy", "nmp", "np"}
24            return False
25
26        def _is_nan(node: nodes.NodeNG) -> bool:
27            return _is_float_nan(node) or _is_numpy_nan(node)
28
29        nan_left = _is_nan(left_value)
30        if not nan_left and not _is_nan(right_value):
31            return
32
33        absence_text = ""
34        if checking_for_absence:
35            absence_text = "not "
36        if nan_left:
37            suggestion = f"'{absence_text}math.isnan({right_value.as_string()})'"
38        else:
39            suggestion = f"'{absence_text}math.isnan({left_value.as_string()})'"
40        self.add_message(
41            "nan-comparison",
42            node=root_node,
43            args=(f"'{root_node.as_string()}'", suggestion),
44        )
            

Path 4: 2 calls (0.0)

Attribute (2)

Name (2)

Compare (2)

True (2)

1def _check_nan_comparison(
2        self,
3        left_value: nodes.NodeNG,
4        right_value: nodes.NodeNG,
5        root_node: nodes.Compare,
6        checking_for_absence: bool = False,
7    ) -> None:
8        def _is_float_nan(node: nodes.NodeNG) -> bool:
9            try:
10                if isinstance(node, nodes.Call) and len(node.args) == 1:
11                    if (
12                        node.args[0].value.lower() == "nan"
13                        and node.inferred()[0].pytype() == "builtins.float"
14                    ):
15                        return True
16                return False
17            except AttributeError:
18                return False
19
20        def _is_numpy_nan(node: nodes.NodeNG) -> bool:
21            if isinstance(node, nodes.Attribute) and node.attrname == "NaN":
22                if isinstance(node.expr, nodes.Name):
23                    return node.expr.name in {"numpy", "nmp", "np"}
24            return False
25
26        def _is_nan(node: nodes.NodeNG) -> bool:
27            return _is_float_nan(node) or _is_numpy_nan(node)
28
29        nan_left = _is_nan(left_value)
30        if not nan_left and not _is_nan(right_value):
31            return
32
33        absence_text = ""
34        if checking_for_absence:
35            absence_text = "not "
36        if nan_left:
37            suggestion = f"'{absence_text}math.isnan({right_value.as_string()})'"
38        else:
39            suggestion = f"'{absence_text}math.isnan({left_value.as_string()})'"
40        self.add_message(
41            "nan-comparison",
42            node=root_node,
43            args=(f"'{root_node.as_string()}'", suggestion),
44        )
            

Path 5: 1 calls (0.0)

Attribute (1)

Attribute (1)

Compare (1)

False (1)

1def _check_nan_comparison(
2        self,
3        left_value: nodes.NodeNG,
4        right_value: nodes.NodeNG,
5        root_node: nodes.Compare,
6        checking_for_absence: bool = False,
7    ) -> None:
8        def _is_float_nan(node: nodes.NodeNG) -> bool:
9            try:
10                if isinstance(node, nodes.Call) and len(node.args) == 1:
11                    if (
12                        node.args[0].value.lower() == "nan"
13                        and node.inferred()[0].pytype() == "builtins.float"
14                    ):
15                        return True
16                return False
17            except AttributeError:
18                return False
19
20        def _is_numpy_nan(node: nodes.NodeNG) -> bool:
21            if isinstance(node, nodes.Attribute) and node.attrname == "NaN":
22                if isinstance(node.expr, nodes.Name):
23                    return node.expr.name in {"numpy", "nmp", "np"}
24            return False
25
26        def _is_nan(node: nodes.NodeNG) -> bool:
27            return _is_float_nan(node) or _is_numpy_nan(node)
28
29        nan_left = _is_nan(left_value)
30        if not nan_left and not _is_nan(right_value):
31            return
32
33        absence_text = ""
34        if checking_for_absence:
35            absence_text = "not "
36        if nan_left:
37            suggestion = f"'{absence_text}math.isnan({right_value.as_string()})'"
38        else:
39            suggestion = f"'{absence_text}math.isnan({left_value.as_string()})'"
40        self.add_message(
41            "nan-comparison",
42            node=root_node,
43            args=(f"'{root_node.as_string()}'", suggestion),
44        )