From 11a12d6ca8cd5cc8e32071ff1737ec075fa502b2 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 12 Jan 2020 13:01:08 +0100 Subject: [PATCH] Refactor execute_operation a bit --- jedi/inference/base_value.py | 4 ++++ jedi/inference/compiled/value.py | 11 +++++++---- jedi/inference/syntax_tree.py | 12 +++++------- jedi/inference/value/iterable.py | 8 ++------ test/completion/arrays.py | 11 +++++++++++ test/completion/precedence.py | 6 ++++++ test/test_api/test_completion.py | 1 + 7 files changed, 36 insertions(+), 17 deletions(-) diff --git a/jedi/inference/base_value.py b/jedi/inference/base_value.py index 127bda6e..96f43395 100644 --- a/jedi/inference/base_value.py +++ b/jedi/inference/base_value.py @@ -225,6 +225,10 @@ class Value(HelperValueMixin, BaseValue): raise ValueError("There exists no safe value for value %s" % self) return default + def execute_operation(self, other, operator): + debug.warning("%s not possible between %s and %s", operator, self, other) + return NO_VALUES + def py__call__(self, arguments): debug.warning("no execution possible %s", self) return NO_VALUES diff --git a/jedi/inference/compiled/value.py b/jedi/inference/compiled/value.py index a98cd5cf..a396be1b 100644 --- a/jedi/inference/compiled/value.py +++ b/jedi/inference/compiled/value.py @@ -262,10 +262,13 @@ class CompiledObject(Value): return default def execute_operation(self, other, operator): - return create_from_access_path( - self.inference_state, - self.access_handle.execute_operation(other.access_handle, operator) - ) + try: + return ValueSet([create_from_access_path( + self.inference_state, + self.access_handle.execute_operation(other.access_handle, operator) + )]) + except TypeError: + return NO_VALUES def execute_annotation(self): if self.access_handle.get_repr() == 'None': diff --git a/jedi/inference/syntax_tree.py b/jedi/inference/syntax_tree.py index f9594acc..e790ed81 100644 --- a/jedi/inference/syntax_tree.py +++ b/jedi/inference/syntax_tree.py @@ -576,12 +576,12 @@ def _infer_comparison_part(inference_state, context, left, operator, right): return ValueSet([right]) elif str_operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): - return ValueSet([left.execute_operation(right, str_operator)]) + return left.execute_operation(right, str_operator) elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right): return ValueSet([iterable.MergedArray(inference_state, (left, right))]) elif str_operator == '-': if l_is_num and r_is_num: - return ValueSet([left.execute_operation(right, str_operator)]) + return left.execute_operation(right, str_operator) elif str_operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. @@ -589,11 +589,9 @@ def _infer_comparison_part(inference_state, context, left, operator, right): elif str_operator in COMPARISON_OPERATORS: if left.is_compiled() and right.is_compiled(): # Possible, because the return is not an option. Just compare. - try: - return ValueSet([left.execute_operation(right, str_operator)]) - except TypeError: - # Could be True or False. - pass + result = left.execute_operation(right, str_operator) + if result: + return result else: if str_operator in ('is', '!=', '==', 'is not'): operation = COMPARISON_OPERATORS[str_operator] diff --git a/jedi/inference/value/iterable.py b/jedi/inference/value/iterable.py index 02118cae..92f8c3cb 100644 --- a/jedi/inference/value/iterable.py +++ b/jedi/inference/value/iterable.py @@ -429,12 +429,8 @@ class DictLiteralValue(_DictMixin, SequenceLiteralValue, _DictKeyMixin): compiled_obj_index = compiled.create_simple_object(self.inference_state, index) for key, value in self.get_tree_entries(): for k in self._defining_context.infer_node(key): - try: - method = k.execute_operation - except AttributeError: - pass - else: - if method(compiled_obj_index, u'==').get_safe_value(): + for key_v in k.execute_operation(compiled_obj_index, u'=='): + if key_v.get_safe_value(): return self._defining_context.infer_node(value) raise SimpleGetItemNotFound('No key found in dictionary %s.' % self) diff --git a/test/completion/arrays.py b/test/completion/arrays.py index b1785436..9d3dcd2e 100644 --- a/test/completion/arrays.py +++ b/test/completion/arrays.py @@ -300,6 +300,17 @@ some_dct['b'] #? int() float() str() some_dct['c'] +class Foo: + pass + +objects = {object(): 1, Foo: '', Foo(): 3.0} +#? int() float() str() +objects[Foo] +#? int() float() str() +objects[Foo()] +#? int() float() str() +objects[''] + # ----------------- # with variable as index # ----------------- diff --git a/test/completion/precedence.py b/test/completion/precedence.py index 6e9c1eab..92c670eb 100644 --- a/test/completion/precedence.py +++ b/test/completion/precedence.py @@ -56,6 +56,12 @@ a (3 ** 3) #? int() str() (3 ** 'a') +#? int() str() +(3 + 'a') +#? bool() +(3 == 'a') +#? bool() +(3 >= 'a') class X(): foo = 2 diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 0057ae83..e573ee40 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -206,6 +206,7 @@ current_dirname = os.path.basename(dirname(dirname(dirname(__file__)))) ('example.py', '"test%scomp' % s, None, ['letion' + s]), ('example.py', 'r"comp"', None, []), ('example.py', 'r"tes"', None, []), + ('example.py', '1 + r"tes"', None, []), ('example.py', 'r"tes"', 5, ['t' + s]), ('example.py', 'r" tes"', 6, []), ('test%sexample.py' % se, 'r"tes"', 5, ['t' + s]),