diff --git a/jedi/api/file_name.py b/jedi/api/file_name.py index 43164d36..3d2d8da3 100644 --- a/jedi/api/file_name.py +++ b/jedi/api/file_name.py @@ -77,15 +77,15 @@ def _get_string_additions(module_context, start_leaf): addition = start_leaf.get_previous_leaf() if addition != '+': return '' - value = module_context.create_context(start_leaf) - return _add_strings(value, reversed(list(iterate_nodes()))) + context = module_context.create_context(start_leaf) + return _add_strings(context, reversed(list(iterate_nodes()))) -def _add_strings(value, nodes, add_slash=False): +def _add_strings(context, nodes, add_slash=False): string = '' first = True for child_node in nodes: - values = value.infer_node(child_node) + values = context.infer_node(child_node) if len(values) != 1: return None c, = values @@ -111,8 +111,8 @@ def _add_os_path_join(module_context, start_leaf, bracket_start): if not nodes: return '' - value = module_context.create_context(nodes[0]) - return _add_strings(value, nodes, add_slash=True) or '' + context = module_context.create_context(nodes[0]) + return _add_strings(context, nodes, add_slash=True) or '' if start_leaf.type == 'error_leaf': # Unfinished string literal, like `join('` diff --git a/jedi/inference/__init__.py b/jedi/inference/__init__.py index 2e5aa9f1..a282a101 100644 --- a/jedi/inference/__init__.py +++ b/jedi/inference/__init__.py @@ -401,7 +401,7 @@ class InferenceState(object): if is_nested and not node_is_object: return func.get_function_execution() - return func + return func.as_context() elif scope_node.type == 'classdef': return ClassValue(self, parent_context, scope_node).as_context() elif scope_node.type in ('comp_for', 'sync_comp_for'): diff --git a/jedi/inference/compiled/mixed.py b/jedi/inference/compiled/mixed.py index e10a6c7c..447f735b 100644 --- a/jedi/inference/compiled/mixed.py +++ b/jedi/inference/compiled/mixed.py @@ -21,6 +21,7 @@ from jedi.inference.compiled.access import compiled_objects_cache, \ ALLOWED_GETITEM_TYPES, get_api_type from jedi.inference.compiled.value import create_cached_compiled_object from jedi.inference.gradual.conversion import to_stub +from jedi.inference.context import CompiledContext _sentinel = object() @@ -70,6 +71,9 @@ class MixedObject(ValueWrapper): return self.compiled_object.py__simple_getitem__(index) raise SimpleGetItemNotFound + def _as_context(self): + return MixedContext(self) + def __repr__(self): return '<%s: %s>' % ( type(self).__name__, @@ -77,6 +81,12 @@ class MixedObject(ValueWrapper): ) +class MixedContext(CompiledContext): + @property + def compiled_object(self): + return self._value.compiled_object + + class MixedName(compiled.CompiledName): """ The ``CompiledName._compiled_object`` is our MixedObject. @@ -102,7 +112,7 @@ class MixedName(compiled.CompiledName): else: parent_context = parent_value.as_context() - if parent_context is None or isinstance(parent_context, MixedObject): + if parent_context is None or isinstance(parent_context, MixedContext): return _create(self._inference_state, access, parent_context=parent_context) else: return ValueSet({ @@ -244,7 +254,8 @@ def _create(inference_state, access_handle, parent_context, *args): compiled_object = create_cached_compiled_object( inference_state, access_handle, - parent_context=parent_context and parent_context.compiled_object + parent_context=None if parent_context is None + else parent_context.compiled_object.as_context() # noqa ) # TODO accessing this is bad, but it probably doesn't matter that much, diff --git a/jedi/inference/compiled/value.py b/jedi/inference/compiled/value.py index f4cb51a5..b4eaf7bd 100644 --- a/jedi/inference/compiled/value.py +++ b/jedi/inference/compiled/value.py @@ -530,13 +530,18 @@ def _normalize_create_args(func): def create_from_access_path(inference_state, access_path): - parent_context = None + value = None for name, access in access_path.accesses: - parent_context = create_cached_compiled_object(inference_state, access, parent_context) - return parent_context + value = create_cached_compiled_object( + inference_state, + access, + parent_context=None if value is None else value.as_context() + ) + return value @_normalize_create_args @inference_state_function_cache() def create_cached_compiled_object(inference_state, access_handle, parent_context): + assert not isinstance(parent_context, CompiledObject) return CompiledObject(inference_state, access_handle, parent_context) diff --git a/jedi/inference/context.py b/jedi/inference/context.py index c1211785..64617aeb 100644 --- a/jedi/inference/context.py +++ b/jedi/inference/context.py @@ -185,3 +185,6 @@ class CompForContext(AbstractContext): class CompiledContext(AbstractContext): def get_filters(self, until_position=None, origin_scope=None): return self._value.get_filters() + + def get_value(self): + return self._value diff --git a/jedi/inference/gradual/typing.py b/jedi/inference/gradual/typing.py index 56bfe17a..af87202c 100644 --- a/jedi/inference/gradual/typing.py +++ b/jedi/inference/gradual/typing.py @@ -213,6 +213,10 @@ class _TypingClassMixin(ClassMixin): def get_metaclasses(self): return [] + @property + def name(self): + return ValueName(self, self._tree_name) + class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex): pass diff --git a/jedi/plugins/stdlib.py b/jedi/plugins/stdlib.py index 9ce30045..d39c1e38 100644 --- a/jedi/plugins/stdlib.py +++ b/jedi/plugins/stdlib.py @@ -476,7 +476,7 @@ def collections_namedtuple(obj, arguments, callback): file_io=None, string_names=None, code_lines=parso.split_lines(code, keepends=True), - ) + ).as_context() return ValueSet([ClassValue(inference_state, parent_context, generated_class)])