]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/base_value.py
Actualizado el Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / base_value.py
CommitLineData
53e6db90
DC
1"""
2Values are the "values" that Python would return. However Values are at the
3same time also the "values" that a user is currently sitting in.
4
5A ValueSet is typically used to specify the return of a function or any other
6static analysis operation. In jedi there are always multiple returns and not
7just one.
8"""
9from functools import reduce
10from operator import add
11from itertools import zip_longest
12
13from parso.python.tree import Name
14
15from jedi import debug
16from jedi.parser_utils import clean_scope_docstring
17from jedi.inference.helpers import SimpleGetItemNotFound
18from jedi.inference.utils import safe_property
19from jedi.inference.cache import inference_state_as_method_param_cache
20from jedi.cache import memoize_method
21
22sentinel = object()
23
24
25class HasNoContext(Exception):
26 pass
27
28
29class HelperValueMixin:
30 def get_root_context(self):
31 value = self
32 if value.parent_context is None:
33 return value.as_context()
34
35 while True:
36 if value.parent_context is None:
37 return value
38 value = value.parent_context
39
40 def execute(self, arguments):
41 return self.inference_state.execute(self, arguments=arguments)
42
43 def execute_with_values(self, *value_list):
44 from jedi.inference.arguments import ValuesArguments
45 arguments = ValuesArguments([ValueSet([value]) for value in value_list])
46 return self.inference_state.execute(self, arguments)
47
48 def execute_annotation(self):
49 return self.execute_with_values()
50
51 def gather_annotation_classes(self):
52 return ValueSet([self])
53
54 def merge_types_of_iterate(self, contextualized_node=None, is_async=False):
55 return ValueSet.from_sets(
56 lazy_value.infer()
57 for lazy_value in self.iterate(contextualized_node, is_async)
58 )
59
60 def _get_value_filters(self, name_or_str):
61 origin_scope = name_or_str if isinstance(name_or_str, Name) else None
62 yield from self.get_filters(origin_scope=origin_scope)
63 # This covers the case where a stub files are incomplete.
64 if self.is_stub():
65 from jedi.inference.gradual.conversion import convert_values
66 for c in convert_values(ValueSet({self})):
67 yield from c.get_filters()
68
69 def goto(self, name_or_str, name_context=None, analysis_errors=True):
70 from jedi.inference import finder
71 filters = self._get_value_filters(name_or_str)
72 names = finder.filter_name(filters, name_or_str)
73 debug.dbg('context.goto %s in (%s): %s', name_or_str, self, names)
74 return names
75
76 def py__getattribute__(self, name_or_str, name_context=None, position=None,
77 analysis_errors=True):
78 """
79 :param position: Position of the last statement -> tuple of line, column
80 """
81 if name_context is None:
82 name_context = self
83 names = self.goto(name_or_str, name_context, analysis_errors)
84 values = ValueSet.from_sets(name.infer() for name in names)
85 if not values:
86 n = name_or_str.value if isinstance(name_or_str, Name) else name_or_str
87 values = self.py__getattribute__alternatives(n)
88
89 if not names and not values and analysis_errors:
90 if isinstance(name_or_str, Name):
91 from jedi.inference import analysis
92 analysis.add_attribute_error(
93 name_context, self, name_or_str)
94 debug.dbg('context.names_to_types: %s -> %s', names, values)
95 return values
96
97 def py__await__(self):
98 await_value_set = self.py__getattribute__("__await__")
99 if not await_value_set:
100 debug.warning('Tried to run __await__ on value %s', self)
101 return await_value_set.execute_with_values()
102
103 def py__name__(self):
104 return self.name.string_name
105
106 def iterate(self, contextualized_node=None, is_async=False):
107 debug.dbg('iterate %s', self)
108 if is_async:
109 from jedi.inference.lazy_value import LazyKnownValues
110 # TODO if no __aiter__ values are there, error should be:
111 # TypeError: 'async for' requires an object with __aiter__ method, got int
112 return iter([
113 LazyKnownValues(
114 self.py__getattribute__('__aiter__').execute_with_values()
115 .py__getattribute__('__anext__').execute_with_values()
116 .py__getattribute__('__await__').execute_with_values()
117 .py__stop_iteration_returns()
118 ) # noqa: E124
119 ])
120 return self.py__iter__(contextualized_node)
121
122 def is_sub_class_of(self, class_value):
123 with debug.increase_indent_cm('subclass matching of %s <=> %s' % (self, class_value),
124 color='BLUE'):
125 for cls in self.py__mro__():
126 if cls.is_same_class(class_value):
127 debug.dbg('matched subclass True', color='BLUE')
128 return True
129 debug.dbg('matched subclass False', color='BLUE')
130 return False
131
132 def is_same_class(self, class2):
133 # Class matching should prefer comparisons that are not this function.
134 if type(class2).is_same_class != HelperValueMixin.is_same_class:
135 return class2.is_same_class(self)
136 return self == class2
137
138 @memoize_method
139 def as_context(self, *args, **kwargs):
140 return self._as_context(*args, **kwargs)
141
142
143class Value(HelperValueMixin):
144 """
145 To be implemented by subclasses.
146 """
147 tree_node = None
148 # Possible values: None, tuple, list, dict and set. Here to deal with these
149 # very important containers.
150 array_type = None
151 api_type = 'not_defined_please_report_bug'
152
153 def __init__(self, inference_state, parent_context=None):
154 self.inference_state = inference_state
155 self.parent_context = parent_context
156
157 def py__getitem__(self, index_value_set, contextualized_node):
158 from jedi.inference import analysis
159 # TODO this value is probably not right.
160 analysis.add(
161 contextualized_node.context,
162 'type-error-not-subscriptable',
163 contextualized_node.node,
164 message="TypeError: '%s' object is not subscriptable" % self
165 )
166 return NO_VALUES
167
168 def py__simple_getitem__(self, index):
169 raise SimpleGetItemNotFound
170
171 def py__iter__(self, contextualized_node=None):
172 if contextualized_node is not None:
173 from jedi.inference import analysis
174 analysis.add(
175 contextualized_node.context,
176 'type-error-not-iterable',
177 contextualized_node.node,
178 message="TypeError: '%s' object is not iterable" % self)
179 return iter([])
180
181 def py__next__(self, contextualized_node=None):
182 return self.py__iter__(contextualized_node)
183
184 def get_signatures(self):
185 return []
186
187 def is_class(self):
188 return False
189
190 def is_class_mixin(self):
191 return False
192
193 def is_instance(self):
194 return False
195
196 def is_function(self):
197 return False
198
199 def is_module(self):
200 return False
201
202 def is_namespace(self):
203 return False
204
205 def is_compiled(self):
206 return False
207
208 def is_bound_method(self):
209 return False
210
211 def is_builtins_module(self):
212 return False
213
214 def py__bool__(self):
215 """
216 Since Wrapper is a super class for classes, functions and modules,
217 the return value will always be true.
218 """
219 return True
220
221 def py__doc__(self):
222 try:
223 self.tree_node.get_doc_node
224 except AttributeError:
225 return ''
226 else:
227 return clean_scope_docstring(self.tree_node)
228
229 def get_safe_value(self, default=sentinel):
230 if default is sentinel:
231 raise ValueError("There exists no safe value for value %s" % self)
232 return default
233
234 def execute_operation(self, other, operator):
235 debug.warning("%s not possible between %s and %s", operator, self, other)
236 return NO_VALUES
237
238 def py__call__(self, arguments):
239 debug.warning("no execution possible %s", self)
240 return NO_VALUES
241
242 def py__stop_iteration_returns(self):
243 debug.warning("Not possible to return the stop iterations of %s", self)
244 return NO_VALUES
245
246 def py__getattribute__alternatives(self, name_or_str):
247 """
248 For now a way to add values in cases like __getattr__.
249 """
250 return NO_VALUES
251
252 def py__get__(self, instance, class_value):
253 debug.warning("No __get__ defined on %s", self)
254 return ValueSet([self])
255
256 def py__get__on_class(self, calling_instance, instance, class_value):
257 return NotImplemented
258
259 def get_qualified_names(self):
260 # Returns Optional[Tuple[str, ...]]
261 return None
262
263 def is_stub(self):
264 # The root value knows if it's a stub or not.
265 return self.parent_context.is_stub()
266
267 def _as_context(self):
268 raise HasNoContext
269
270 @property
271 def name(self):
272 raise NotImplementedError
273
274 def get_type_hint(self, add_class_info=True):
275 return None
276
277 def infer_type_vars(self, value_set):
278 """
279 When the current instance represents a type annotation, this method
280 tries to find information about undefined type vars and returns a dict
281 from type var name to value set.
282
283 This is for example important to understand what `iter([1])` returns.
284 According to typeshed, `iter` returns an `Iterator[_T]`:
285
286 def iter(iterable: Iterable[_T]) -> Iterator[_T]: ...
287
288 This functions would generate `int` for `_T` in this case, because it
289 unpacks the `Iterable`.
290
291 Parameters
292 ----------
293
294 `self`: represents the annotation of the current parameter to infer the
295 value for. In the above example, this would initially be the
296 `Iterable[_T]` of the `iterable` parameter and then, when recursing,
297 just the `_T` generic parameter.
298
299 `value_set`: represents the actual argument passed to the parameter
300 we're inferred for, or (for recursive calls) their types. In the
301 above example this would first be the representation of the list
302 `[1]` and then, when recursing, just of `1`.
303 """
304 return {}
305
306
307def iterate_values(values, contextualized_node=None, is_async=False):
308 """
309 Calls `iterate`, on all values but ignores the ordering and just returns
310 all values that the iterate functions yield.
311 """
312 return ValueSet.from_sets(
313 lazy_value.infer()
314 for lazy_value in values.iterate(contextualized_node, is_async=is_async)
315 )
316
317
318class _ValueWrapperBase(HelperValueMixin):
319 @safe_property
320 def name(self):
321 from jedi.inference.names import ValueName
322 wrapped_name = self._wrapped_value.name
323 if wrapped_name.tree_name is not None:
324 return ValueName(self, wrapped_name.tree_name)
325 else:
326 from jedi.inference.compiled import CompiledValueName
327 return CompiledValueName(self, wrapped_name.string_name)
328
329 @classmethod
330 @inference_state_as_method_param_cache()
331 def create_cached(cls, inference_state, *args, **kwargs):
332 return cls(*args, **kwargs)
333
334 def __getattr__(self, name):
335 assert name != '_wrapped_value', 'Problem with _get_wrapped_value'
336 return getattr(self._wrapped_value, name)
337
338
339class LazyValueWrapper(_ValueWrapperBase):
340 @safe_property
341 @memoize_method
342 def _wrapped_value(self):
343 with debug.increase_indent_cm('Resolve lazy value wrapper'):
344 return self._get_wrapped_value()
345
346 def __repr__(self):
347 return '<%s>' % (self.__class__.__name__)
348
349 def _get_wrapped_value(self):
350 raise NotImplementedError
351
352
353class ValueWrapper(_ValueWrapperBase):
354 def __init__(self, wrapped_value):
355 self._wrapped_value = wrapped_value
356
357 def __repr__(self):
358 return '%s(%s)' % (self.__class__.__name__, self._wrapped_value)
359
360
361class TreeValue(Value):
362 def __init__(self, inference_state, parent_context, tree_node):
363 super().__init__(inference_state, parent_context)
364 self.tree_node = tree_node
365
366 def __repr__(self):
367 return '<%s: %s>' % (self.__class__.__name__, self.tree_node)
368
369
370class ContextualizedNode:
371 def __init__(self, context, node):
372 self.context = context
373 self.node = node
374
375 def get_root_context(self):
376 return self.context.get_root_context()
377
378 def infer(self):
379 return self.context.infer_node(self.node)
380
381 def __repr__(self):
382 return '<%s: %s in %s>' % (self.__class__.__name__, self.node, self.context)
383
384
385def _getitem(value, index_values, contextualized_node):
386 # The actual getitem call.
387 result = NO_VALUES
388 unused_values = set()
389 for index_value in index_values:
390 index = index_value.get_safe_value(default=None)
391 if type(index) in (float, int, str, slice, bytes):
392 try:
393 result |= value.py__simple_getitem__(index)
394 continue
395 except SimpleGetItemNotFound:
396 pass
397
398 unused_values.add(index_value)
399
400 # The index was somehow not good enough or simply a wrong type.
401 # Therefore we now iterate through all the values and just take
402 # all results.
403 if unused_values or not index_values:
404 result |= value.py__getitem__(
405 ValueSet(unused_values),
406 contextualized_node
407 )
408 debug.dbg('py__getitem__ result: %s', result)
409 return result
410
411
412class ValueSet:
413 def __init__(self, iterable):
414 self._set = frozenset(iterable)
415 for value in iterable:
416 assert not isinstance(value, ValueSet)
417
418 @classmethod
419 def _from_frozen_set(cls, frozenset_):
420 self = cls.__new__(cls)
421 self._set = frozenset_
422 return self
423
424 @classmethod
425 def from_sets(cls, sets):
426 """
427 Used to work with an iterable of set.
428 """
429 aggregated = set()
430 for set_ in sets:
431 if isinstance(set_, ValueSet):
432 aggregated |= set_._set
433 else:
434 aggregated |= frozenset(set_)
435 return cls._from_frozen_set(frozenset(aggregated))
436
437 def __or__(self, other):
438 return self._from_frozen_set(self._set | other._set)
439
440 def __and__(self, other):
441 return self._from_frozen_set(self._set & other._set)
442
443 def __iter__(self):
444 return iter(self._set)
445
446 def __bool__(self):
447 return bool(self._set)
448
449 def __len__(self):
450 return len(self._set)
451
452 def __repr__(self):
453 return 'S{%s}' % (', '.join(str(s) for s in self._set))
454
455 def filter(self, filter_func):
456 return self.__class__(filter(filter_func, self._set))
457
458 def __getattr__(self, name):
459 def mapper(*args, **kwargs):
460 return self.from_sets(
461 getattr(value, name)(*args, **kwargs)
462 for value in self._set
463 )
464 return mapper
465
466 def __eq__(self, other):
467 return self._set == other._set
468
469 def __ne__(self, other):
470 return not self.__eq__(other)
471
472 def __hash__(self):
473 return hash(self._set)
474
475 def py__class__(self):
476 return ValueSet(c.py__class__() for c in self._set)
477
478 def iterate(self, contextualized_node=None, is_async=False):
479 from jedi.inference.lazy_value import get_merged_lazy_value
480 type_iters = [c.iterate(contextualized_node, is_async=is_async) for c in self._set]
481 for lazy_values in zip_longest(*type_iters):
482 yield get_merged_lazy_value(
483 [l for l in lazy_values if l is not None]
484 )
485
486 def execute(self, arguments):
487 return ValueSet.from_sets(c.inference_state.execute(c, arguments) for c in self._set)
488
489 def execute_with_values(self, *args, **kwargs):
490 return ValueSet.from_sets(c.execute_with_values(*args, **kwargs) for c in self._set)
491
492 def goto(self, *args, **kwargs):
493 return reduce(add, [c.goto(*args, **kwargs) for c in self._set], [])
494
495 def py__getattribute__(self, *args, **kwargs):
496 return ValueSet.from_sets(c.py__getattribute__(*args, **kwargs) for c in self._set)
497
498 def get_item(self, *args, **kwargs):
499 return ValueSet.from_sets(_getitem(c, *args, **kwargs) for c in self._set)
500
501 def try_merge(self, function_name):
502 value_set = self.__class__([])
503 for c in self._set:
504 try:
505 method = getattr(c, function_name)
506 except AttributeError:
507 pass
508 else:
509 value_set |= method()
510 return value_set
511
512 def gather_annotation_classes(self):
513 return ValueSet.from_sets([c.gather_annotation_classes() for c in self._set])
514
515 def get_signatures(self):
516 return [sig for c in self._set for sig in c.get_signatures()]
517
518 def get_type_hint(self, add_class_info=True):
519 t = [v.get_type_hint(add_class_info=add_class_info) for v in self._set]
520 type_hints = sorted(filter(None, t))
521 if len(type_hints) == 1:
522 return type_hints[0]
523
524 optional = 'None' in type_hints
525 if optional:
526 type_hints.remove('None')
527
528 if len(type_hints) == 0:
529 return None
530 elif len(type_hints) == 1:
531 s = type_hints[0]
532 else:
533 s = 'Union[%s]' % ', '.join(type_hints)
534 if optional:
535 s = 'Optional[%s]' % s
536 return s
537
538 def infer_type_vars(self, value_set):
539 # Circular
540 from jedi.inference.gradual.annotation import merge_type_var_dicts
541
542 type_var_dict = {}
543 for value in self._set:
544 merge_type_var_dicts(
545 type_var_dict,
546 value.infer_type_vars(value_set),
547 )
548 return type_var_dict
549
550
551NO_VALUES = ValueSet([])
552
553
554def iterator_to_value_set(func):
555 def wrapper(*args, **kwargs):
556 return ValueSet(func(*args, **kwargs))
557
558 return wrapper