From 164e37c50b9a13a26b21ff9fec2b20fe32d2e657 Mon Sep 17 00:00:00 2001 From: Aivar Annamaa Date: Thu, 23 Jul 2020 15:11:32 +0300 Subject: [PATCH] FIXED: Simplify jedi_utils by dropping support for older versions #1281 --- requirements.txt | 1 + thonny/jedi_utils.py | 110 +++--------------------------- thonny/plugins/highlight_names.py | 41 ++++++----- thonny/plugins/locals_marker.py | 9 +-- thonny/plugins/statement_boxes.py | 4 +- 5 files changed, 36 insertions(+), 129 deletions(-) diff --git a/requirements.txt b/requirements.txt index 337e28f2d..384a9ea95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ jedi>=0.13 +parso>=0.3 setuptools>=33.1 pyserial>=3.4 pylint>=1.9 diff --git a/thonny/jedi_utils.py b/thonny/jedi_utils.py index f6fd9aaed..a4d95241a 100644 --- a/thonny/jedi_utils.py +++ b/thonny/jedi_utils.py @@ -1,58 +1,18 @@ -"""Utils to handle different jedi versions - -Because of Debian Stretch, Thonny needs to support jedi 0.10, -which doesn't use separate parso """ - - -def import_python_tree(): - # pylint: disable=import-error,no-name-in-module - - if get_version_tuple() < (0, 11, 0): - # make sure not to import parso in this case, even if it exits - from jedi.parser import tree # @UnresolvedImport @UnusedImport - else: - # assume older versions, which use parso - from parso.python import tree # @UnresolvedImport @UnusedImport @Reimport - - return tree - - -def get_params(func_node): - if hasattr(func_node, "get_params"): - # parso - return func_node.get_params() - else: - # older jedi - return func_node.params - - -def get_parent_scope(node): - try: - # jedi 0.11 - from jedi import parser_utils - - return parser_utils.get_parent_scope(node) - except ImportError: - # Older versions - return node.get_parent_scope() +Utils to handle different jedi versions +""" def get_statement_of_position(node, pos): - try: - # jedi 0.11 - # pylint: disable=redefined-outer-name - import jedi.parser_utils + import jedi.parser_utils - func = getattr( - jedi.parser_utils, "get_statement_of_position", _copy_of_get_statement_of_position - ) - return func(node, pos) - except ImportError: - # Older versions - return node.get_statement_for_position(pos) + func = getattr( + jedi.parser_utils, "get_statement_of_position", _copy_of_get_statement_of_position + ) + return func(node, pos) +# TODO: try to get rid of this def _copy_of_get_statement_of_position(node, pos): # https://github.com/davidhalter/jedi/commit/9f3a2f93c48eda24e2dcc25e54eb7cc10aa73848 from parso.python import tree @@ -75,57 +35,7 @@ def _copy_of_get_statement_of_position(node, pos): return None -def get_module_node(script): - if hasattr(script, "_module_node"): # Jedi 0.12 - return script._module_node - elif hasattr(script, "_get_module_node"): # Jedi 0.10 - 0.11 - return script._get_module_node() - elif hasattr(script, "_get_module"): - return script._get_module() - else: - return script._parser.module() - - -def is_scope(node): - try: - # jedi 0.11 and older - from jedi import parser_utils - - return parser_utils.is_scope(node) - except ImportError: - # Older versions - return node.is_scope() - - -def get_name_of_position(obj, position): - if hasattr(obj, "get_name_of_position"): - # parso - return obj.get_name_of_position(position) - else: - # older jedi - return obj.name_for_position(position) - - def parse_source(source): - try: - import parso - - return parso.parse(source) - except ImportError: - import jedi - - script = jedi.Script(source) - return get_module_node(script) - - -def get_version_tuple(): - import jedi - - nums = [] - for item in jedi.__version__.split("."): - try: - nums.append(int(item)) - except Exception: - nums.append(0) + import parso - return tuple(nums) + return parso.parse(source) diff --git a/thonny/plugins/highlight_names.py b/thonny/plugins/highlight_names.py index d6624877f..5becede07 100644 --- a/thonny/plugins/highlight_names.py +++ b/thonny/plugins/highlight_names.py @@ -73,7 +73,7 @@ def _is_name_function_definition(self, name): ) def _get_def_from_function_params(self, func_node, name): - params = jedi_utils.get_params(func_node) + params = func_node.get_params() for param in params: if param.children[0].value == name.value: return param.children[0] @@ -107,6 +107,7 @@ def _is_global_stmt_with_name(self, node, name_str): ) def _find_definition(self, scope, name): + from jedi import parser_utils # if the name is the name of a function definition if isinstance(scope, tree.Function): @@ -130,13 +131,13 @@ def _find_definition(self, scope, name): if ( isinstance(c, tree.Function) and c.children[1].value == name.value - and not isinstance(jedi_utils.get_parent_scope(c), tree.Class) + and not isinstance(parser_utils.get_parent_scope(c), tree.Class) ): return c.children[1] if isinstance(c, tree.BaseNode) and c.type == "suite": for x in c.children: if self._is_global_stmt_with_name(x, name.value): - return self._find_definition(jedi_utils.get_parent_scope(scope), name) + return self._find_definition(parser_utils.get_parent_scope(scope), name) if isinstance(x, tree.Name) and x.is_definition() and x.value == name.value: return x def_candidate = self._find_def_in_simple_node(x, name) @@ -144,7 +145,7 @@ def _find_definition(self, scope, name): return def_candidate if not isinstance(scope, tree.Module): - return self._find_definition(jedi_utils.get_parent_scope(scope), name) + return self._find_definition(parser_utils.get_parent_scope(scope), name) # if name itself is the left side of an assignment statement, then the name is the definition if name.is_definition(): @@ -169,13 +170,15 @@ def _get_dot_names(self, stmt): return () def _find_usages(self, name, stmt): + from jedi import parser_utils + # check if stmt is dot qualified, disregard these dot_names = self._get_dot_names(stmt) if len(dot_names) > 1 and dot_names[1].value == name.value: return set() # search for definition - definition = self._find_definition(jedi_utils.get_parent_scope(name), name) + definition = self._find_definition(parser_utils.get_parent_scope(name), name) searched_scopes = set() @@ -186,7 +189,7 @@ def _find_usages(self, name, stmt): def find_usages_in_node(node, global_encountered=False): names = [] if isinstance(node, tree.BaseNode): - if jedi_utils.is_scope(node): + if parser_utils.is_scope(node): global_encountered = False if node in searched_scopes: return names @@ -203,10 +206,10 @@ def find_usages_in_node(node, global_encountered=False): sub_result = find_usages_in_node(c, global_encountered=global_encountered) if sub_result is None: - if not jedi_utils.is_scope(node): + if not parser_utils.is_scope(node): return ( None - if definition and node != jedi_utils.get_parent_scope(definition) + if definition and node != parser_utils.get_parent_scope(definition) else [definition] ) else: @@ -218,7 +221,7 @@ def find_usages_in_node(node, global_encountered=False): if definition and definition != node: if self._is_name_function_definition(node): if isinstance( - jedi_utils.get_parent_scope(jedi_utils.get_parent_scope(node)), + parser_utils.get_parent_scope(parser_utils.get_parent_scope(node)), tree.Class, ): return [] @@ -229,13 +232,13 @@ def find_usages_in_node(node, global_encountered=False): and not global_encountered and ( is_function_definition - or jedi_utils.get_parent_scope(node) - != jedi_utils.get_parent_scope(definition) + or parser_utils.get_parent_scope(node) + != parser_utils.get_parent_scope(definition) ) ): return None if self._is_name_function_definition(definition) and isinstance( - jedi_utils.get_parent_scope(jedi_utils.get_parent_scope(definition)), + parser_utils.get_parent_scope(parser_utils.get_parent_scope(definition)), tree.Class, ): return None @@ -244,11 +247,11 @@ def find_usages_in_node(node, global_encountered=False): if definition: if self._is_name_function_definition(definition): - scope = jedi_utils.get_parent_scope(jedi_utils.get_parent_scope(definition)) + scope = parser_utils.get_parent_scope(parser_utils.get_parent_scope(definition)) else: - scope = jedi_utils.get_parent_scope(definition) + scope = parser_utils.get_parent_scope(definition) else: - scope = jedi_utils.get_parent_scope(name) + scope = parser_utils.get_parent_scope(name) usages = find_usages_in_node(scope) return usages @@ -262,7 +265,7 @@ def get_positions_for(self, source, line, column): if isinstance(stmt, tree.Name): name = stmt elif isinstance(stmt, tree.BaseNode): - name = jedi_utils.get_name_of_position(stmt, pos) + name = stmt.get_name_of_position(pos) if not name: return set() @@ -319,14 +322,10 @@ def update_highlighting(event): # don't slow down loading process return - if jedi_utils.get_version_tuple() < (0, 9): - logging.warning("Jedi version is too old. Disabling name highlighter") - return - global tree if not tree: # using lazy importing to speed up Thonny loading - tree = jedi_utils.import_python_tree() + from parso.python import tree assert isinstance(event.widget, tk.Text) text = event.widget diff --git a/thonny/plugins/locals_marker.py b/thonny/plugins/locals_marker.py index e6b9e9e20..a143b8bd4 100644 --- a/thonny/plugins/locals_marker.py +++ b/thonny/plugins/locals_marker.py @@ -11,7 +11,8 @@ def __init__(self, text): self._update_scheduled = False def get_positions(self): - tree = jedi_utils.import_python_tree() + from parso.python import tree + from jedi import parser_utils locs = [] @@ -60,7 +61,7 @@ def process_node(node, local_names, global_names): source = self.text.get("1.0", "end") module = jedi_utils.parse_source(source) for child in module.children: - if isinstance(child, tree.BaseNode) and jedi_utils.is_scope(child): + if isinstance(child, tree.BaseNode) and parser_utils.is_scope(child): process_scope(child) loc_pos = set( @@ -105,10 +106,6 @@ def update_highlighting(event): # don't slow down loading process return - if jedi_utils.get_version_tuple() < (0, 9): - logging.warning("Jedi version is too old. Disabling locals marker") - return - assert isinstance(event.widget, tk.Text) text = event.widget diff --git a/thonny/plugins/statement_boxes.py b/thonny/plugins/statement_boxes.py index d9a67fefa..5ba7135c5 100644 --- a/thonny/plugins/statement_boxes.py +++ b/thonny/plugins/statement_boxes.py @@ -125,7 +125,7 @@ def predicate( def print_tree(node, level=0): - python_tree = jedi_utils.import_python_tree() + from parso.python import tree as python_tree indent = " " * level # if (isinstance(node, python_tree.PythonNode) and node.type == "sim" if node.type in ("simple_stmt",) or isinstance(node, python_tree.Flow): @@ -154,7 +154,7 @@ def add_tags(text): def tag_tree(node): nonlocal last_line, last_col - python_tree = jedi_utils.import_python_tree() + from parso.python import tree as python_tree if node.type == "simple_stmt" or isinstance(node, (python_tree.Flow, python_tree.Scope)):