2 Used only for REPL Completion.
6 from pathlib
import Path
8 from jedi
.parser_utils
import get_cached_code_lines
10 from jedi
import settings
11 from jedi
.cache
import memoize_method
12 from jedi
.inference
import compiled
13 from jedi
.file_io
import FileIO
14 from jedi
.inference
.names
import NameWrapper
15 from jedi
.inference
.base_value
import ValueSet
, ValueWrapper
, NO_VALUES
16 from jedi
.inference
.value
import ModuleValue
17 from jedi
.inference
.cache
import inference_state_function_cache
, \
18 inference_state_method_cache
19 from jedi
.inference
.compiled
.access
import ALLOWED_GETITEM_TYPES
, get_api_type
20 from jedi
.inference
.gradual
.conversion
import to_stub
21 from jedi
.inference
.context
import CompiledContext
, CompiledModuleContext
, \
27 class MixedObject(ValueWrapper
):
29 A ``MixedObject`` is used in two ways:
31 1. It uses the default logic of ``parser.python.tree`` objects,
32 2. except for getattr calls and signatures. The names dicts are generated
33 in a fashion like ``CompiledValue``.
35 This combined logic makes it possible to provide more powerful REPL
36 completion. It allows side effects that are not noticable with the default
37 parser structure to still be completable.
39 The biggest difference from CompiledValue to MixedObject is that we are
40 generally dealing with Python code and not with C code. This will generate
41 fewer special cases, because we in Python you don't have the same freedoms
42 to modify the runtime.
44 def __init__(self
, compiled_value
, tree_value
):
45 super().__init
__(tree_value
)
46 self
.compiled_value
= compiled_value
47 self
.access_handle
= compiled_value
.access_handle
49 def get_filters(self
, *args
, **kwargs
):
50 yield MixedObjectFilter(
51 self
.inference_state
, self
.compiled_value
, self
._wrapped
_value
)
53 def get_signatures(self
):
54 # Prefer `inspect.signature` over somehow analyzing Python code. It
55 # should be very precise, especially for stuff like `partial`.
56 return self
.compiled_value
.get_signatures()
58 @inference_state_method_cache(default
=NO_VALUES
)
59 def py__call__(self
, arguments
):
60 # Fallback to the wrapped value if to stub returns no values.
61 values
= to_stub(self
._wrapped
_value
)
63 values
= self
._wrapped
_value
64 return values
.py__call__(arguments
)
66 def get_safe_value(self
, default
=_sentinel
):
67 if default
is _sentinel
:
68 return self
.compiled_value
.get_safe_value()
70 return self
.compiled_value
.get_safe_value(default
)
74 return self
.compiled_value
.array_type
76 def get_key_values(self
):
77 return self
.compiled_value
.get_key_values()
79 def py__simple_getitem__(self
, index
):
80 python_object
= self
.compiled_value
.access_handle
.access
._obj
81 if type(python_object
) in ALLOWED_GETITEM_TYPES
:
82 return self
.compiled_value
.py__simple_getitem__(index
)
83 return self
._wrapped
_value
.py__simple_getitem__(index
)
86 return self
.compiled_value
.negate()
88 def _as_context(self
):
89 if self
.parent_context
is None:
90 return MixedModuleContext(self
)
91 return MixedContext(self
)
94 return '<%s: %s; %s>' % (
96 self
.access_handle
.get_repr(),
101 class MixedContext(CompiledContext
, TreeContextMixin
):
103 def compiled_value(self
):
104 return self
._value
.compiled_value
107 class MixedModuleContext(CompiledModuleContext
, MixedContext
):
111 class MixedName(NameWrapper
):
113 The ``CompiledName._compiled_value`` is our MixedObject.
115 def __init__(self
, wrapped_name
, parent_tree_value
):
116 super().__init
__(wrapped_name
)
117 self
._parent
_tree
_value
= parent_tree_value
121 values
= list(self
.infer())
123 # This means a start_pos that doesn't exist (compiled objects).
125 return values
[0].name
.start_pos
129 compiled_value
= self
._wrapped
_name
.infer_compiled_value()
130 tree_value
= self
._parent
_tree
_value
131 if tree_value
.is_instance() or tree_value
.is_class():
132 tree_values
= tree_value
.py__getattribute__(self
.string_name
)
133 if compiled_value
.is_function():
134 return ValueSet({MixedObject(compiled_value
, v
) for v
in tree_values
})
136 module_context
= tree_value
.get_root_context()
137 return _create(self
._inference
_state
, compiled_value
, module_context
)
140 class MixedObjectFilter(compiled
.CompiledValueFilter
):
141 def __init__(self
, inference_state
, compiled_value
, tree_value
):
142 super().__init
__(inference_state
, compiled_value
)
143 self
._tree
_value
= tree_value
145 def _create_name(self
, *args
, **kwargs
):
147 super()._create
_name
(*args
, **kwargs
),
152 @inference_state_function_cache()
153 def _load_module(inference_state
, path
):
154 return inference_state
.parse(
157 diff_cache
=settings
.fast_parser
,
158 cache_path
=settings
.cache_directory
162 def _get_object_to_check(python_object
):
163 """Check if inspect.getfile has a chance to find the source."""
165 python_object
= inspect
.unwrap(python_object
)
167 # Can return a ValueError when it wraps around
170 if (inspect
.ismodule(python_object
)
171 or inspect
.isclass(python_object
)
172 or inspect
.ismethod(python_object
)
173 or inspect
.isfunction(python_object
)
174 or inspect
.istraceback(python_object
)
175 or inspect
.isframe(python_object
)
176 or inspect
.iscode(python_object
)):
180 return python_object
.__class
__
181 except AttributeError:
182 raise TypeError # Prevents computation of `repr` within inspect.
185 def _find_syntax_node_name(inference_state
, python_object
):
186 original_object
= python_object
188 python_object
= _get_object_to_check(python_object
)
189 path
= inspect
.getsourcefile(python_object
)
190 except (OSError, TypeError):
191 # The type might not be known (e.g. class_with_dict.__weakref__)
193 path
= None if path
is None else Path(path
)
195 if path
is None or not path
.exists():
196 # The path might not exist or be e.g. <stdin>.
199 # Might raise an OSError on Windows:
201 # [WinError 123] The filename, directory name, or volume label
202 # syntax is incorrect: '<string>'
205 file_io
= FileIO(path
)
206 module_node
= _load_module(inference_state
, path
)
208 if inspect
.ismodule(python_object
):
209 # We don't need to check names for modules, because there's not really
210 # a way to write a module in a module in Python (and also __name__ can
211 # be something like ``email.utils``).
212 code_lines
= get_cached_code_lines(inference_state
.grammar
, path
)
213 return module_node
, module_node
, file_io
, code_lines
216 name_str
= python_object
.__name
__
217 except AttributeError:
218 # Stuff like python_function.__code__.
221 if name_str
== '<lambda>':
222 return None # It's too hard to find lambdas.
224 # Doesn't always work (e.g. os.stat_result)
225 names
= module_node
.get_used_names().get(name_str
, [])
226 # Only functions and classes are relevant. If a name e.g. points to an
227 # import, it's probably a builtin (like collections.deque) and needs to be
231 if n
.parent
.type in ('funcdef', 'classdef') and n
.parent
.name
== n
237 code
= python_object
.__code
__
238 # By using the line number of a code object we make the lookup in a
239 # file pretty easy. There's still a possibility of people defining
240 # stuff like ``a = 3; foo(a); a = 4`` on the same line, but if people
241 # do so we just don't care.
242 line_nr
= code
.co_firstlineno
243 except AttributeError:
246 line_names
= [name
for name
in names
if name
.start_pos
[0] == line_nr
]
247 # There's a chance that the object is not available anymore, because
248 # the code has changed in the background.
252 code_lines
= get_cached_code_lines(inference_state
.grammar
, path
)
253 # It's really hard to actually get the right definition, here as a last
254 # resort we just return the last one. This chance might lead to odd
255 # completions at some points but will lead to mostly correct type
256 # inference, because people tend to define a public name in a module only
258 tree_node
= names
[-1].parent
259 if tree_node
.type == 'funcdef' and get_api_type(original_object
) == 'instance':
260 # If an instance is given and we're landing on a function (e.g.
261 # partial in 3.5), something is completely wrong and we should not
264 return module_node
, tree_node
, file_io
, code_lines
267 @inference_state_function_cache()
268 def _create(inference_state
, compiled_value
, module_context
):
269 # TODO accessing this is bad, but it probably doesn't matter that much,
270 # because we're working with interpreters only here.
271 python_object
= compiled_value
.access_handle
.access
._obj
272 result
= _find_syntax_node_name(inference_state
, python_object
)
274 # TODO Care about generics from stuff like `[1]` and don't return like this.
275 if type(python_object
) in (dict, list, tuple):
276 return ValueSet({compiled_value}
)
278 tree_values
= to_stub(compiled_value
)
280 return ValueSet({compiled_value}
)
282 module_node
, tree_node
, file_io
, code_lines
= result
284 if module_context
is None or module_context
.tree_node
!= module_node
:
285 root_compiled_value
= compiled_value
.get_root_context().get_value()
286 # TODO this __name__ might be wrong.
287 name
= root_compiled_value
.py__name__()
288 string_names
= tuple(name
.split('.'))
289 module_value
= ModuleValue(
290 inference_state
, module_node
,
292 string_names
=string_names
,
293 code_lines
=code_lines
,
294 is_package
=root_compiled_value
.is_package(),
297 inference_state
.module_cache
.add(string_names
, ValueSet([module_value
]))
298 module_context
= module_value
.as_context()
300 tree_values
= ValueSet({module_context
.create_value(tree_node
)})
301 if tree_node
.type == 'classdef':
302 if not compiled_value
.is_class():
303 # Is an instance, not a class.
304 tree_values
= tree_values
.execute_with_values()
307 MixedObject(compiled_value
, tree_value
=tree_value
)
308 for tree_value
in tree_values