• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pyta-uoft / pyta / 7197426845

13 Dec 2023 03:28PM UTC coverage: 94.779% (-0.03%) from 94.804%
7197426845

Pull #992

github

web-flow
Merge 13cd66646 into e4503ec27
Pull Request #992: Do not infer variables in invalid-range-index check

3 of 3 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

3431 of 3620 relevant lines covered (94.78%)

7.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.44
/python_ta/checkers/invalid_range_index_checker.py
1
"""Checker for index ranges"""
5✔
2
from astroid import nodes
5✔
3
from pylint.checkers import BaseChecker, utils
5✔
4
from pylint.checkers.utils import only_required_for_messages
5✔
5
from pylint.lint import PyLinter
5✔
6

7

8
class InvalidRangeIndexChecker(BaseChecker):
5✔
9
    """A checker class that reports the usage of an invalid index range."""
5✔
10

11
    name = "invalid_range_index"
10✔
12
    msgs = {
10✔
13
        "E9993": (
5✔
14
            "You should not use invalid range index on line %s",
15
            "invalid-range-index",
16
            "Used when you use invalid index range",
17
        )
18
    }
19

20
    @only_required_for_messages("invalid-range-index")
10✔
21
    def visit_call(self, node: nodes.Call) -> None:
10✔
22
        if isinstance(node.func, nodes.Name):
10✔
23
            name = node.func.name
10✔
24
            # ignore the name if it's not a builtin (i.e. not defined in the
25
            # locals nor globals scope)
26
            if not (name in node.frame() or name in node.root()) and name == "range":
10✔
27
                args = node.args  # the arguments of 'range' call
10✔
28

29
                # ignore calls involving variables; these cannot be inferred properly
30
                if any(any(arg.nodes_of_class(nodes.Name)) for arg in args):
10✔
31
                    return
10✔
32

33
                inferred_params = [utils.safe_infer(arg) for arg in args]
10✔
34
                # Check whether every inference was successful
35
                if not all(isinstance(node, nodes.Const) for node in inferred_params):
10✔
UNCOV
36
                    return
×
37

38
                eval_params = [const.value for const in inferred_params]
10✔
39

40
                if (
7✔
41
                    len(args) == 0
5✔
42
                    or len(args) > 3
5✔
43
                    or not all([isinstance(c, int) for c in eval_params])
5✔
44
                ):
45
                    self.add_message("invalid-range-index", node=node, args=str(node.lineno))
10✔
46
                    return
10✔
47

48
                # set positional and default arguments of range
49
                start = eval_params[0] if len(args) > 1 else 0
10✔
50
                stop = eval_params[0] if len(args) == 1 else eval_params[1]
10✔
51
                step = eval_params[2] if len(args) == 3 else 1
10✔
52

53
                if not is_valid_range(start, stop, step):
10✔
54
                    self.add_message("invalid-range-index", node=node, args=str(node.lineno))
10✔
55

56

57
def is_valid_range(start: int, stop: int, step: int) -> bool:
10✔
58
    """Returns True if a range call with three arguments is valid.
59
    We consider a range to be valid if it has more than one element."""
60
    if step == 0:
10✔
61
        return False
10✔
62
    return (stop - start) / step > 1
10✔
63

64

65
def register(linter: PyLinter) -> None:
10✔
66
    """Required method to auto-register this checker to the linter"""
67
    linter.register_checker(InvalidRangeIndexChecker(linter))
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc