Skip to content

Commit

Permalink
Fix crash in refactoring checker from unaryop with variable
Browse files Browse the repository at this point in the history
Fixes:
```
  File "python3.10/site-packages/pylint/utils/ast_walker.py", line 91, in walk
    callback(astroid)
  File "python3.10/site-packages/pylint/checkers/refactoring/refactoring_checker.py", line 700, in visit_for
    self._check_unnecessary_list_index_lookup(node)
  File "python3.10/site-packages/pylint/checkers/refactoring/refactoring_checker.py", line 2227, in _check_unnecessary_list_index_lookup
    has_start_arg, confidence = self._enumerate_with_start(node)
  File "python3.10/site-packages/pylint/checkers/refactoring/refactoring_checker.py", line 2352, in _enumerate_with_start
    start_val, confidence = self._get_start_value(keyword.value)
  File "python3.10/site-packages/pylint/checkers/refactoring/refactoring_checker.py", line 2369, in _get_start_value
    return node.operand.value, HIGH
AttributeError: 'Name' object has no attribute 'value'
```

Crash is reproducible if you have something like this:

```python
x=5
for _ in enumerate(range, start=-x):
    ...
```

As a workaround, remove the unary op before `for` loop (i.e. change the
variable used).

Closes pylint-dev#9074
  • Loading branch information
Hnasar committed Sep 26, 2023
1 parent b8a7cc5 commit ab3e0f1
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 1 deletion.
3 changes: 3 additions & 0 deletions doc/whatsnew/fragments/9074.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix crash in refactoring checker when unary operand used with variable in for loop.

Closes #9074
2 changes: 1 addition & 1 deletion pylint/checkers/refactoring/refactoring_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2362,7 +2362,7 @@ def _get_start_value(self, node: nodes.NodeNG) -> tuple[int | None, Confidence]:
if (
isinstance(node, (nodes.Name, nodes.Call, nodes.Attribute))
or isinstance(node, nodes.UnaryOp)
and isinstance(node.operand, nodes.Attribute)
and isinstance(node.operand, (nodes.Attribute, nodes.Name))
):
inferred = utils.safe_infer(node)
start_val = inferred.value if inferred else None
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Regression test."""
def crash_on_unary_op_with_name():
"""Should not crash with -idx."""
mylist = []
idx = 5
for _i, _val in enumerate(mylist, start=-idx):
pass
Empty file.

0 comments on commit ab3e0f1

Please sign in to comment.