From 9d34df2fed6b25bb1ae7ab8a0ab49dfc6e0b8910 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Wed, 21 Aug 2019 09:51:47 +0200 Subject: [PATCH] Make Slice a proper LazyValueWrapper --- jedi/inference/base_value.py | 19 ++++--------------- jedi/inference/value/iterable.py | 27 +++++++++++++-------------- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/jedi/inference/base_value.py b/jedi/inference/base_value.py index ed20ddfb..a8744379 100644 --- a/jedi/inference/base_value.py +++ b/jedi/inference/base_value.py @@ -19,7 +19,7 @@ from jedi.inference.utils import safe_property from jedi.inference.cache import inference_state_as_method_param_cache from jedi.cache import memoize_method -_sentinel = object() +sentinel = object() class HelperValueMixin(object): @@ -205,8 +205,8 @@ class Value(HelperValueMixin, BaseValue): return clean_scope_docstring(self.tree_node) return None - def get_safe_value(self, default=_sentinel): - if default is _sentinel: + def get_safe_value(self, default=sentinel): + if default is sentinel: raise ValueError("There exists no safe value for value %s" % self) return default @@ -360,8 +360,6 @@ class ContextualizedName(ContextualizedNode): def _getitem(value, index_values, contextualized_node): - from jedi.inference.value.iterable import Slice - # The actual getitem call. simple_getitem = getattr(value, 'py__simple_getitem__', None) @@ -369,17 +367,8 @@ def _getitem(value, index_values, contextualized_node): unused_values = set() for index_value in index_values: if simple_getitem is not None: - index = index_value - if isinstance(index_value, Slice): - index = index.obj - - try: - method = index.get_safe_value - except AttributeError: - pass - else: - index = method(default=None) + index = index_value.get_safe_value(default=None) if type(index) in (float, int, str, unicode, slice, bytes): try: result |= simple_getitem(index) diff --git a/jedi/inference/value/iterable.py b/jedi/inference/value/iterable.py index d4fabc75..b0118b7b 100644 --- a/jedi/inference/value/iterable.py +++ b/jedi/inference/value/iterable.py @@ -37,7 +37,8 @@ from jedi.inference.utils import safe_property, to_list from jedi.inference.cache import inference_state_method_cache from jedi.inference.filters import LazyAttributeOverwrite, publish_method from jedi.inference.base_value import ValueSet, Value, NO_VALUES, \ - ContextualizedNode, iterate_values, HelperValueMixin, _sentinel + ContextualizedNode, iterate_values, HelperValueMixin, sentinel, \ + LazyValueWrapper from jedi.parser_utils import get_sync_comp_fors from jedi.inference.context import CompForContext @@ -54,8 +55,8 @@ class IterableMixin(object): # typeshed. if sys.version_info[0] == 2: # Python 2........... - def get_safe_value(self, default=_sentinel): - if default is _sentinel: + def get_safe_value(self, default=sentinel): + if default is sentinel: raise ValueError("There exists no safe value for value %s" % self) return default else: @@ -771,23 +772,21 @@ class _ArrayInstance(HelperValueMixin): return self.py__iter__(contextualized_node) -class Slice(object): +class Slice(LazyValueWrapper): def __init__(self, python_context, start, stop, step): - self._python_context = python_context - self._slice_object = None + self.inference_state = python_context.inference_state + self._context = python_context # All of them are either a Precedence or None. self._start = start self._stop = stop self._step = step - def __getattr__(self, name): - if self._slice_object is None: - value = compiled.builtin_from_name(self._python_context.inference_state, 'slice') - self._slice_object, = value.execute_with_values() - return getattr(self._slice_object, name) + def _get_wrapped_value(self): + value = compiled.builtin_from_name(self._context.inference_state, 'slice') + slice_value, = value.execute_with_values() + return slice_value - @property - def obj(self): + def get_safe_value(self, default=sentinel): """ Imitate CompiledObject.obj behavior and return a ``builtin.slice()`` object. @@ -796,7 +795,7 @@ class Slice(object): if element is None: return None - result = self._python_context.infer_node(element) + result = self._context.infer_node(element) if len(result) != 1: # For simplicity, we want slices to be clear defined with just # one type. Otherwise we will return an empty slice object.