rope
rope copied to clipboard
patched_ast will set region[0] to None when unmatched parenthesis inside string
Describe the bug A clear and concise description of what the bug is.
To Reproduce Steps to reproduce the behavior:
- Code before refactoring:
class A:
def __init__(self):
pass
def _unmatched_inside_f_string(self, val):
if val < 0:
raise IndexError(
(
f"{val})"
)
)
def other_func(self):
pass
-
Rename class A to B
-
Expected code after refactoring:
class B:
def __init__(self):
pass
def _unmatched_inside_f_string(self, val):
if val < 0:
raise IndexError(
(
f"{val})"
)
)
def other_func(self):
pass
- Describe the error or unexpected result that you are getting
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/eivind/Projects/ropemode/src/ropemode/decorators.py", line 54, in newfunc
return func(*args, **kwds)
File "/home/eivind/Projects/ropemode/src/ropemode/interface.py", line 52, in do_refactor
refactoring(self, self.env).show(initial_asking=initial_asking)
File "/home/eivind/Projects/ropemode/src/ropemode/refactor.py", line 33, in show
self._create_refactoring()
File "/home/eivind/Projects/ropemode/src/ropemode/refactor.py", line 119, in _create_refactoring
self.renamer = rope.refactor.rename.Rename(
File "/home/eivind/Projects/rope/rope/refactor/rename.py", line 32, in __init__
self.old_instance, self.old_pyname = evaluate.eval_location2(
File "/home/eivind/Projects/rope/rope/base/evaluate.py", line 21, in eval_location2
return pyname_finder.get_primary_and_pyname_at(offset)
File "/home/eivind/Projects/rope/rope/base/evaluate.py", line 87, in get_primary_and_pyname_at
holding_scope = self.module_scope.get_inner_scope_for_offset(offset)
File "/home/eivind/Projects/rope/rope/base/pyscopes.py", line 160, in get_inner_scope_for_offset
return self._scope_finder.get_holding_scope_for_offset(self, offset)
File "/home/eivind/Projects/rope/rope/base/pyscopes.py", line 317, in get_holding_scope_for_offset
if inner_scope.in_region(offset):
File "/home/eivind/Projects/rope/rope/base/pyscopes.py", line 118, in in_region
return region[0] < offset < region[1]
TypeError: '<' not supported between instances of 'NoneType' and 'int'
Additional context The problem seems to be that under certain conditions, a region tuple gets its first value assigned to 0 when there is an unmatched parenthesis inside a string. The following test can be used to reproduce:
def test_works_with_unmatched_parens_inside_string(self):
source = """
class A:
def __init__(self):
pass
def _unmatched_inside_f_string(self, val):
if val < 0:
raise IndexError(
(
f"{val})"
)
)
def other_func(self):
pass
"""
ast_frag = patchedast.get_patched_ast(source, True)
assert ast_frag.body[-1].region[0] != None
@eivindjahren Thank you for writing detailed bug report with great reproduction scenario.