From e83c419fdccd6b63b65b5bf58257e66c1394d5a7 Mon Sep 17 00:00:00 2001 From: climbus Date: Wed, 6 Oct 2021 14:33:44 +0200 Subject: [PATCH 1/5] fixed some issues with getting scope regions --- rope/base/pyscopes.py | 16 ++++++++++---- rope/refactor/patchedast.py | 11 +++------- ropetest/pyscopestest.py | 42 +++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/rope/base/pyscopes.py b/rope/base/pyscopes.py index 25a850696..d7ef36698 100644 --- a/rope/base/pyscopes.py +++ b/rope/base/pyscopes.py @@ -101,11 +101,9 @@ def get_logical_end(self): def get_kind(self): pass - @utils.saveit def get_region(self): - node = patchedast.patch_ast( - self.pyobject.get_ast(), self.pyobject.get_module().source_code - ) + self.pyobject.get_module().get_scope().get_region() + node = self.pyobject.get_ast() region = patchedast.node_region(node) return region @@ -135,6 +133,16 @@ def get_name(self, name): return self.builtin_names[name] raise exceptions.NameNotFoundError("name %s not found" % name) + @utils.saveit + def get_region(self): + source = self._get_source() + node = patchedast.patch_ast(self.pyobject.get_ast(), source) + region = patchedast.node_region(node) + return region + + def _get_source(self): + return self.pyobject.source_code + def get_names(self): if self.names.get() is None: result = dict(self.builtin_names) diff --git a/rope/refactor/patchedast.py b/rope/refactor/patchedast.py index 36ce4a3a6..5a8c59dd7 100644 --- a/rope/refactor/patchedast.py +++ b/rope/refactor/patchedast.py @@ -97,14 +97,6 @@ def __call__(self, node): node.sorted_children = ast.get_children(node) def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): - if hasattr(node, "region"): - # ???: The same node was seen twice; what should we do? - warnings.warn( - "Node <%s> has been already patched; please report!" - % node.__class__.__name__, - RuntimeWarning, - ) - return base_children = collections.deque(base_children) self.children_stack.append(base_children) children = collections.deque() @@ -884,6 +876,9 @@ def _With(self, node): children.extend(node.body) self._handle(node, children) + def _AsyncWith(self, node): + return self._With(node) + def _child_nodes(self, nodes, separator): children = [] for index, child in enumerate(nodes): diff --git a/ropetest/pyscopestest.py b/ropetest/pyscopestest.py index 0003be260..b38059c83 100644 --- a/ropetest/pyscopestest.py +++ b/ropetest/pyscopestest.py @@ -3,6 +3,8 @@ except ImportError: import unittest +from textwrap import dedent + from rope.base import libutils from rope.base.pyobjects import get_base_type from ropetest import testutils @@ -328,6 +330,14 @@ def test_get_scope_for_offset_for_scope_with_indent(self): inner_scope = scope.get_scopes()[0] self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(10)) + def test_get_scope_for_offset_for_function_scope_and_async_with_statement(self): + scope = libutils.get_string_scope( + self.project, + "async def func():\n async with a_func() as var:\n print(var)\n", + ) + inner_scope = scope.get_scopes()[0] + self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(27)) + def test_getting_overwritten_scopes(self): scope = libutils.get_string_scope( self.project, "def f():\n pass\ndef f():\n pass\n" @@ -414,3 +424,35 @@ def test_get_inner_scope_for_nested_list_comprhension(self): self.assertEqual(len(scope.get_scopes()[0].get_scopes()), 1) self.assertIn("j", scope.get_scopes()[0].get_scopes()[0]) self.assertIn("i", scope.get_scopes()[0].get_scopes()[0]) + + def test_get_scope_region(self): + scope = libutils.get_string_scope( + self.project, + dedent( + """ + def func1(ala): + pass + + def func2(o): + pass""" + ), + ) + + self.assertEqual(scope.get_region(), (0, 47)) + self.assertEqual(scope.get_scopes()[0].get_region(), (1, 24)) + self.assertEqual(scope.get_scopes()[1].get_region(), (26, 47)) + + def test_only_get_inner_scope_region(self): + scope = libutils.get_string_scope( + self.project, + dedent( + """ + def func1(ala): + pass + + def func2(o): + pass""" + ), + ) + + self.assertEqual(scope.get_scopes()[1].get_region(), (26, 47)) From 7356fe6f9b44e97ee2e318f93d0c9358ca3c464b Mon Sep 17 00:00:00 2001 From: climbus Date: Wed, 6 Oct 2021 14:56:04 +0200 Subject: [PATCH 2/5] some refactorings --- rope/base/pyscopes.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rope/base/pyscopes.py b/rope/base/pyscopes.py index d7ef36698..2d2a5d93d 100644 --- a/rope/base/pyscopes.py +++ b/rope/base/pyscopes.py @@ -102,11 +102,14 @@ def get_kind(self): pass def get_region(self): - self.pyobject.get_module().get_scope().get_region() + self._calculate_scope_regions_for_module() node = self.pyobject.get_ast() region = patchedast.node_region(node) return region + def _calculate_scope_regions_for_module(self): + self._get_global_scope().calculate_scope_regions() + def in_region(self, offset): """Checks if offset is in scope region""" @@ -134,11 +137,9 @@ def get_name(self, name): raise exceptions.NameNotFoundError("name %s not found" % name) @utils.saveit - def get_region(self): + def calculate_scope_regions(self): source = self._get_source() - node = patchedast.patch_ast(self.pyobject.get_ast(), source) - region = patchedast.node_region(node) - return region + patchedast.patch_ast(self.pyobject.get_ast(), source) def _get_source(self): return self.pyobject.source_code From 6c1c50b110e29dc45aa9c87b802065b0d7393083 Mon Sep 17 00:00:00 2001 From: climbus Date: Wed, 6 Oct 2021 14:59:34 +0200 Subject: [PATCH 3/5] exclude async with test for python < 3.5 --- ropetest/pyscopestest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ropetest/pyscopestest.py b/ropetest/pyscopestest.py index b38059c83..52434660f 100644 --- a/ropetest/pyscopestest.py +++ b/ropetest/pyscopestest.py @@ -330,6 +330,7 @@ def test_get_scope_for_offset_for_scope_with_indent(self): inner_scope = scope.get_scopes()[0] self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(10)) + @testutils.only_for("3.5") def test_get_scope_for_offset_for_function_scope_and_async_with_statement(self): scope = libutils.get_string_scope( self.project, From 5ebec85ff59c5f3b01d827d793004f0ebee2e61d Mon Sep 17 00:00:00 2001 From: climbus Date: Fri, 8 Oct 2021 11:54:23 +0200 Subject: [PATCH 4/5] fixed code formating --- ropetest/pyscopestest.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ropetest/pyscopestest.py b/ropetest/pyscopestest.py index 52434660f..9c21f66b3 100644 --- a/ropetest/pyscopestest.py +++ b/ropetest/pyscopestest.py @@ -334,7 +334,11 @@ def test_get_scope_for_offset_for_scope_with_indent(self): def test_get_scope_for_offset_for_function_scope_and_async_with_statement(self): scope = libutils.get_string_scope( self.project, - "async def func():\n async with a_func() as var:\n print(var)\n", + dedent("""\ + async def func(): + async with a_func() as var: + print(var) + """) ) inner_scope = scope.get_scopes()[0] self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(27)) From dfc1e5548024dae02526c099274aca0c4c51a92a Mon Sep 17 00:00:00 2001 From: climbus Date: Fri, 8 Oct 2021 12:01:01 +0200 Subject: [PATCH 5/5] changed calculations method name --- rope/base/pyscopes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rope/base/pyscopes.py b/rope/base/pyscopes.py index 2d2a5d93d..c6050d19b 100644 --- a/rope/base/pyscopes.py +++ b/rope/base/pyscopes.py @@ -108,7 +108,7 @@ def get_region(self): return region def _calculate_scope_regions_for_module(self): - self._get_global_scope().calculate_scope_regions() + self._get_global_scope()._calculate_scope_regions() def in_region(self, offset): """Checks if offset is in scope region""" @@ -137,7 +137,7 @@ def get_name(self, name): raise exceptions.NameNotFoundError("name %s not found" % name) @utils.saveit - def calculate_scope_regions(self): + def _calculate_scope_regions(self): source = self._get_source() patchedast.patch_ast(self.pyobject.get_ast(), source)