Refactor execute_operation a bit

This commit is contained in:
Dave Halter
2020-01-12 13:01:08 +01:00
parent bd2ed8dbbd
commit 11a12d6ca8
7 changed files with 36 additions and 17 deletions

View File

@@ -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

View File

@@ -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':

View File

@@ -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]

View File

@@ -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)

View File

@@ -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
# -----------------

View File

@@ -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

View File

@@ -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]),