File: use_max.py

package info (click to toggle)
python-refurb 1.27.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,700 kB
  • sloc: python: 9,468; makefile: 40; sh: 6
file content (85 lines) | stat: -rw-r--r-- 1,994 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from dataclasses import dataclass

from mypy.nodes import ComparisonExpr, ConditionalExpr

from refurb.checks.common import is_equivalent
from refurb.error import Error


@dataclass
class ErrorInfo(Error):
    """
    Certain ternary expressions can be written more succinctly using the
    builtin `min`/`max` functions:

    Bad:

    ```
    score1 = 90
    score2 = 99

    highest_score = score1 if score1 > score2 else score2
    ```

    Good:

    ```
    score1 = 90
    score2 = 99

    highest_score = max(score1, score2)
    ```
    """

    name = "use-min-max"
    code = 136
    categories = ("builtin", "logical", "readability")


FUNC_TABLE = {
    "<": "min",
    "<=": "min",
    ">": "max",
    ">=": "max",
}


def flip_comparison_oper(oper: str) -> str:
    return {
        "<": ">",
        "<=": ">=",
        ">": "<",
        ">=": "<=",
    }.get(oper, oper)


def check(node: ConditionalExpr, errors: list[Error]) -> None:
    match node:
        case ConditionalExpr(
            if_expr=if_expr,
            cond=ComparisonExpr(operators=[oper], operands=[lhs, rhs]),
            else_expr=else_expr,
        ):
            if (
                is_equivalent(if_expr, lhs)
                and is_equivalent(rhs, else_expr)
                and (func := FUNC_TABLE.get(oper))
            ):
                errors.append(
                    ErrorInfo.from_node(
                        node,
                        f"Replace `x if x {oper} y else y` with `{func}(x, y)`",  # noqa: E501
                    )
                )

            if (
                is_equivalent(if_expr, rhs)
                and is_equivalent(lhs, else_expr)
                and (func := FUNC_TABLE.get(flip_comparison_oper(oper)))
            ):
                errors.append(
                    ErrorInfo.from_node(
                        node,
                        f"Replace `x if y {oper} x else y` with `{func}(y, x)`",  # noqa: E501
                    )
                )