]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/value/instance.py
Configuracion en desarrollo PC pega
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / value / instance.py
CommitLineData
53e6db90
DC
1from abc import abstractproperty
2
3from parso.tree import search_ancestor
4
5from jedi import debug
6from jedi import settings
7from jedi.inference import compiled
8from jedi.inference.compiled.value import CompiledValueFilter
9from jedi.inference.helpers import values_from_qualified_names, is_big_annoying_library
10from jedi.inference.filters import AbstractFilter, AnonymousFunctionExecutionFilter
11from jedi.inference.names import ValueName, TreeNameDefinition, ParamName, \
12 NameWrapper
13from jedi.inference.base_value import Value, NO_VALUES, ValueSet, \
14 iterator_to_value_set, ValueWrapper
15from jedi.inference.lazy_value import LazyKnownValue, LazyKnownValues
16from jedi.inference.cache import inference_state_method_cache
17from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper
18from jedi.inference.value.function import \
19 FunctionValue, FunctionMixin, OverloadedFunctionValue, \
20 BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass
21from jedi.inference.value.klass import ClassFilter
22from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance
23from jedi.parser_utils import function_is_staticmethod, function_is_classmethod
24
25
26class InstanceExecutedParamName(ParamName):
27 def __init__(self, instance, function_value, tree_name):
28 super().__init__(
29 function_value, tree_name, arguments=None)
30 self._instance = instance
31
32 def infer(self):
33 return ValueSet([self._instance])
34
35 def matches_signature(self):
36 return True
37
38
39class AnonymousMethodExecutionFilter(AnonymousFunctionExecutionFilter):
40 def __init__(self, instance, *args, **kwargs):
41 super().__init__(*args, **kwargs)
42 self._instance = instance
43
44 def _convert_param(self, param, name):
45 if param.position_index == 0:
46 if function_is_classmethod(self._function_value.tree_node):
47 return InstanceExecutedParamName(
48 self._instance.py__class__(),
49 self._function_value,
50 name
51 )
52 elif not function_is_staticmethod(self._function_value.tree_node):
53 return InstanceExecutedParamName(
54 self._instance,
55 self._function_value,
56 name
57 )
58 return super()._convert_param(param, name)
59
60
61class AnonymousMethodExecutionContext(BaseFunctionExecutionContext):
62 def __init__(self, instance, value):
63 super().__init__(value)
64 self.instance = instance
65
66 def get_filters(self, until_position=None, origin_scope=None):
67 yield AnonymousMethodExecutionFilter(
68 self.instance, self, self._value,
69 until_position=until_position,
70 origin_scope=origin_scope,
71 )
72
73 def get_param_names(self):
74 param_names = list(self._value.get_param_names())
75 # set the self name
76 param_names[0] = InstanceExecutedParamName(
77 self.instance,
78 self._value,
79 param_names[0].tree_name
80 )
81 return param_names
82
83
84class MethodExecutionContext(FunctionExecutionContext):
85 def __init__(self, instance, *args, **kwargs):
86 super().__init__(*args, **kwargs)
87 self.instance = instance
88
89
90class AbstractInstanceValue(Value):
91 api_type = 'instance'
92
93 def __init__(self, inference_state, parent_context, class_value):
94 super().__init__(inference_state, parent_context)
95 # Generated instances are classes that are just generated by self
96 # (No arguments) used.
97 self.class_value = class_value
98
99 def is_instance(self):
100 return True
101
102 def get_qualified_names(self):
103 return self.class_value.get_qualified_names()
104
105 def get_annotated_class_object(self):
106 return self.class_value # This is the default.
107
108 def py__class__(self):
109 return self.class_value
110
111 def py__bool__(self):
112 # Signalize that we don't know about the bool type.
113 return None
114
115 @abstractproperty
116 def name(self):
117 raise NotImplementedError
118
119 def get_signatures(self):
120 call_funcs = self.py__getattribute__('__call__').py__get__(self, self.class_value)
121 return [s.bind(self) for s in call_funcs.get_signatures()]
122
123 def get_function_slot_names(self, name):
124 # Python classes don't look at the dictionary of the instance when
125 # looking up `__call__`. This is something that has to do with Python's
126 # internal slot system (note: not __slots__, but C slots).
127 for filter in self.get_filters(include_self_names=False):
128 names = filter.get(name)
129 if names:
130 return names
131 return []
132
133 def execute_function_slots(self, names, *inferred_args):
134 return ValueSet.from_sets(
135 name.infer().execute_with_values(*inferred_args)
136 for name in names
137 )
138
139 def get_type_hint(self, add_class_info=True):
140 return self.py__name__()
141
142 def py__getitem__(self, index_value_set, contextualized_node):
143 names = self.get_function_slot_names('__getitem__')
144 if not names:
145 return super().py__getitem__(
146 index_value_set,
147 contextualized_node,
148 )
149
150 args = ValuesArguments([index_value_set])
151 return ValueSet.from_sets(name.infer().execute(args) for name in names)
152
153 def py__iter__(self, contextualized_node=None):
154 iter_slot_names = self.get_function_slot_names('__iter__')
155 if not iter_slot_names:
156 return super().py__iter__(contextualized_node)
157
158 def iterate():
159 for generator in self.execute_function_slots(iter_slot_names):
160 yield from generator.py__next__(contextualized_node)
161 return iterate()
162
163 def __repr__(self):
164 return "<%s of %s>" % (self.__class__.__name__, self.class_value)
165
166
167class CompiledInstance(AbstractInstanceValue):
168 # This is not really a compiled class, it's just an instance from a
169 # compiled class.
170 def __init__(self, inference_state, parent_context, class_value, arguments):
171 super().__init__(inference_state, parent_context, class_value)
172 self._arguments = arguments
173
174 def get_filters(self, origin_scope=None, include_self_names=True):
175 class_value = self.get_annotated_class_object()
176 class_filters = class_value.get_filters(
177 origin_scope=origin_scope,
178 is_instance=True,
179 )
180 for f in class_filters:
181 yield CompiledInstanceClassFilter(self, f)
182
183 @property
184 def name(self):
185 return compiled.CompiledValueName(self, self.class_value.name.string_name)
186
187 def is_stub(self):
188 return False
189
190
191class _BaseTreeInstance(AbstractInstanceValue):
192 @property
193 def array_type(self):
194 name = self.class_value.py__name__()
195 if name in ['list', 'set', 'dict'] \
196 and self.parent_context.get_root_context().is_builtins_module():
197 return name
198 return None
199
200 @property
201 def name(self):
202 return ValueName(self, self.class_value.name.tree_name)
203
204 def get_filters(self, origin_scope=None, include_self_names=True):
205 class_value = self.get_annotated_class_object()
206 if include_self_names:
207 for cls in class_value.py__mro__():
208 if not cls.is_compiled():
209 # In this case we're excluding compiled objects that are
210 # not fake objects. It doesn't make sense for normal
211 # compiled objects to search for self variables.
212 yield SelfAttributeFilter(self, class_value, cls.as_context(), origin_scope)
213
214 class_filters = class_value.get_filters(
215 origin_scope=origin_scope,
216 is_instance=True,
217 )
218 for f in class_filters:
219 if isinstance(f, ClassFilter):
220 yield InstanceClassFilter(self, f)
221 elif isinstance(f, CompiledValueFilter):
222 yield CompiledInstanceClassFilter(self, f)
223 else:
224 # Propably from the metaclass.
225 yield f
226
227 @inference_state_method_cache()
228 def create_instance_context(self, class_context, node):
229 new = node
230 while True:
231 func_node = new
232 new = search_ancestor(new, 'funcdef', 'classdef')
233 if class_context.tree_node is new:
234 func = FunctionValue.from_context(class_context, func_node)
235 bound_method = BoundMethod(self, class_context, func)
236 if func_node.name.value == '__init__':
237 context = bound_method.as_context(self._arguments)
238 else:
239 context = bound_method.as_context()
240 break
241 return context.create_context(node)
242
243 def py__getattribute__alternatives(self, string_name):
244 '''
245 Since nothing was inferred, now check the __getattr__ and
246 __getattribute__ methods. Stubs don't need to be checked, because
247 they don't contain any logic.
248 '''
249 if self.is_stub():
250 return NO_VALUES
251
252 name = compiled.create_simple_object(self.inference_state, string_name)
253
254 # This is a little bit special. `__getattribute__` is in Python
255 # executed before `__getattr__`. But: I know no use case, where
256 # this could be practical and where Jedi would return wrong types.
257 # If you ever find something, let me know!
258 # We are inversing this, because a hand-crafted `__getattribute__`
259 # could still call another hand-crafted `__getattr__`, but not the
260 # other way around.
261 if is_big_annoying_library(self.parent_context):
262 return NO_VALUES
263 names = (self.get_function_slot_names('__getattr__')
264 or self.get_function_slot_names('__getattribute__'))
265 return self.execute_function_slots(names, name)
266
267 def py__next__(self, contextualized_node=None):
268 name = u'__next__'
269 next_slot_names = self.get_function_slot_names(name)
270 if next_slot_names:
271 yield LazyKnownValues(
272 self.execute_function_slots(next_slot_names)
273 )
274 else:
275 debug.warning('Instance has no __next__ function in %s.', self)
276
277 def py__call__(self, arguments):
278 names = self.get_function_slot_names('__call__')
279 if not names:
280 # Means the Instance is not callable.
281 return super().py__call__(arguments)
282
283 return ValueSet.from_sets(name.infer().execute(arguments) for name in names)
284
285 def py__get__(self, instance, class_value):
286 """
287 obj may be None.
288 """
289 # Arguments in __get__ descriptors are obj, class.
290 # `method` is the new parent of the array, don't know if that's good.
291 for cls in self.class_value.py__mro__():
292 result = cls.py__get__on_class(self, instance, class_value)
293 if result is not NotImplemented:
294 return result
295
296 names = self.get_function_slot_names('__get__')
297 if names:
298 if instance is None:
299 instance = compiled.builtin_from_name(self.inference_state, 'None')
300 return self.execute_function_slots(names, instance, class_value)
301 else:
302 return ValueSet([self])
303
304
305class TreeInstance(_BaseTreeInstance):
306 def __init__(self, inference_state, parent_context, class_value, arguments):
307 # I don't think that dynamic append lookups should happen here. That
308 # sounds more like something that should go to py__iter__.
309 if class_value.py__name__() in ['list', 'set'] \
310 and parent_context.get_root_context().is_builtins_module():
311 # compare the module path with the builtin name.
312 if settings.dynamic_array_additions:
313 arguments = get_dynamic_array_instance(self, arguments)
314
315 super().__init__(inference_state, parent_context, class_value)
316 self._arguments = arguments
317 self.tree_node = class_value.tree_node
318
319 # This can recurse, if the initialization of the class includes a reference
320 # to itself.
321 @inference_state_method_cache(default=None)
322 def _get_annotated_class_object(self):
323 from jedi.inference.gradual.annotation import py__annotations__, \
324 infer_type_vars_for_execution
325
326 args = InstanceArguments(self, self._arguments)
327 for signature in self.class_value.py__getattribute__('__init__').get_signatures():
328 # Just take the first result, it should always be one, because we
329 # control the typeshed code.
330 funcdef = signature.value.tree_node
331 if funcdef is None or funcdef.type != 'funcdef' \
332 or not signature.matches_signature(args):
333 # First check if the signature even matches, if not we don't
334 # need to infer anything.
335 continue
336 bound_method = BoundMethod(self, self.class_value.as_context(), signature.value)
337 all_annotations = py__annotations__(funcdef)
338 type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations)
339 if type_var_dict:
340 defined, = self.class_value.define_generics(
341 infer_type_vars_for_execution(signature.value, args, all_annotations),
342 )
343 debug.dbg('Inferred instance value as %s', defined, color='BLUE')
344 return defined
345 return None
346
347 def get_annotated_class_object(self):
348 return self._get_annotated_class_object() or self.class_value
349
350 def get_key_values(self):
351 values = NO_VALUES
352 if self.array_type == 'dict':
353 for i, (key, instance) in enumerate(self._arguments.unpack()):
354 if key is None and i == 0:
355 values |= ValueSet.from_sets(
356 v.get_key_values()
357 for v in instance.infer()
358 if v.array_type == 'dict'
359 )
360 if key:
361 values |= ValueSet([compiled.create_simple_object(
362 self.inference_state,
363 key,
364 )])
365
366 return values
367
368 def py__simple_getitem__(self, index):
369 if self.array_type == 'dict':
370 # Logic for dict({'foo': bar}) and dict(foo=bar)
371 # reversed, because:
372 # >>> dict({'a': 1}, a=3)
373 # {'a': 3}
374 # TODO tuple initializations
375 # >>> dict([('a', 4)])
376 # {'a': 4}
377 for key, lazy_context in reversed(list(self._arguments.unpack())):
378 if key is None:
379 values = ValueSet.from_sets(
380 dct_value.py__simple_getitem__(index)
381 for dct_value in lazy_context.infer()
382 if dct_value.array_type == 'dict'
383 )
384 if values:
385 return values
386 else:
387 if key == index:
388 return lazy_context.infer()
389 return super().py__simple_getitem__(index)
390
391 def __repr__(self):
392 return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_value,
393 self._arguments)
394
395
396class AnonymousInstance(_BaseTreeInstance):
397 _arguments = None
398
399
400class CompiledInstanceName(NameWrapper):
401 @iterator_to_value_set
402 def infer(self):
403 for result_value in self._wrapped_name.infer():
404 if result_value.api_type == 'function':
405 yield CompiledBoundMethod(result_value)
406 else:
407 yield result_value
408
409
410class CompiledInstanceClassFilter(AbstractFilter):
411 def __init__(self, instance, f):
412 self._instance = instance
413 self._class_filter = f
414
415 def get(self, name):
416 return self._convert(self._class_filter.get(name))
417
418 def values(self):
419 return self._convert(self._class_filter.values())
420
421 def _convert(self, names):
422 return [CompiledInstanceName(n) for n in names]
423
424
425class BoundMethod(FunctionMixin, ValueWrapper):
426 def __init__(self, instance, class_context, function):
427 super().__init__(function)
428 self.instance = instance
429 self._class_context = class_context
430
431 def is_bound_method(self):
432 return True
433
434 @property
435 def name(self):
436 return FunctionNameInClass(
437 self._class_context,
438 super().name
439 )
440
441 def py__class__(self):
442 c, = values_from_qualified_names(self.inference_state, 'types', 'MethodType')
443 return c
444
445 def _get_arguments(self, arguments):
446 assert arguments is not None
447 return InstanceArguments(self.instance, arguments)
448
449 def _as_context(self, arguments=None):
450 if arguments is None:
451 return AnonymousMethodExecutionContext(self.instance, self)
452
453 arguments = self._get_arguments(arguments)
454 return MethodExecutionContext(self.instance, self, arguments)
455
456 def py__call__(self, arguments):
457 if isinstance(self._wrapped_value, OverloadedFunctionValue):
458 return self._wrapped_value.py__call__(self._get_arguments(arguments))
459
460 function_execution = self.as_context(arguments)
461 return function_execution.infer()
462
463 def get_signature_functions(self):
464 return [
465 BoundMethod(self.instance, self._class_context, f)
466 for f in self._wrapped_value.get_signature_functions()
467 ]
468
469 def get_signatures(self):
470 return [sig.bind(self) for sig in super().get_signatures()]
471
472 def __repr__(self):
473 return '<%s: %s>' % (self.__class__.__name__, self._wrapped_value)
474
475
476class CompiledBoundMethod(ValueWrapper):
477 def is_bound_method(self):
478 return True
479
480 def get_signatures(self):
481 return [sig.bind(self) for sig in self._wrapped_value.get_signatures()]
482
483
484class SelfName(TreeNameDefinition):
485 """
486 This name calculates the parent_context lazily.
487 """
488 def __init__(self, instance, class_context, tree_name):
489 self._instance = instance
490 self.class_context = class_context
491 self.tree_name = tree_name
492
493 @property
494 def parent_context(self):
495 return self._instance.create_instance_context(self.class_context, self.tree_name)
496
497 def get_defining_qualified_value(self):
498 return self._instance
499
500 def infer(self):
501 stmt = search_ancestor(self.tree_name, 'expr_stmt')
502 if stmt is not None:
503 if stmt.children[1].type == "annassign":
504 from jedi.inference.gradual.annotation import infer_annotation
505 values = infer_annotation(
506 self.parent_context, stmt.children[1].children[1]
507 ).execute_annotation()
508 if values:
509 return values
510 return super().infer()
511
512
513class LazyInstanceClassName(NameWrapper):
514 def __init__(self, instance, class_member_name):
515 super().__init__(class_member_name)
516 self._instance = instance
517
518 @iterator_to_value_set
519 def infer(self):
520 for result_value in self._wrapped_name.infer():
521 yield from result_value.py__get__(self._instance, self._instance.py__class__())
522
523 def get_signatures(self):
524 return self.infer().get_signatures()
525
526 def get_defining_qualified_value(self):
527 return self._instance
528
529
530class InstanceClassFilter(AbstractFilter):
531 """
532 This filter is special in that it uses the class filter and wraps the
533 resulting names in LazyInstanceClassName. The idea is that the class name
534 filtering can be very flexible and always be reflected in instances.
535 """
536 def __init__(self, instance, class_filter):
537 self._instance = instance
538 self._class_filter = class_filter
539
540 def get(self, name):
541 return self._convert(self._class_filter.get(name))
542
543 def values(self):
544 return self._convert(self._class_filter.values())
545
546 def _convert(self, names):
547 return [
548 LazyInstanceClassName(self._instance, n)
549 for n in names
550 ]
551
552 def __repr__(self):
553 return '<%s for %s>' % (self.__class__.__name__, self._class_filter)
554
555
556class SelfAttributeFilter(ClassFilter):
557 """
558 This class basically filters all the use cases where `self.*` was assigned.
559 """
560 def __init__(self, instance, instance_class, node_context, origin_scope):
561 super().__init__(
562 class_value=instance_class,
563 node_context=node_context,
564 origin_scope=origin_scope,
565 is_instance=True,
566 )
567 self._instance = instance
568
569 def _filter(self, names):
570 start, end = self._parser_scope.start_pos, self._parser_scope.end_pos
571 names = [n for n in names if start < n.start_pos < end]
572 return self._filter_self_names(names)
573
574 def _filter_self_names(self, names):
575 for name in names:
576 trailer = name.parent
577 if trailer.type == 'trailer' \
578 and len(trailer.parent.children) == 2 \
579 and trailer.children[0] == '.':
580 if name.is_definition() and self._access_possible(name):
581 # TODO filter non-self assignments instead of this bad
582 # filter.
583 if self._is_in_right_scope(trailer.parent.children[0], name):
584 yield name
585
586 def _is_in_right_scope(self, self_name, name):
587 self_context = self._node_context.create_context(self_name)
588 names = self_context.goto(self_name, position=self_name.start_pos)
589 return any(
590 n.api_type == 'param'
591 and n.tree_name.get_definition().position_index == 0
592 and n.parent_context.tree_node is self._parser_scope
593 for n in names
594 )
595
596 def _convert_names(self, names):
597 return [SelfName(self._instance, self._node_context, name) for name in names]
598
599 def _check_flows(self, names):
600 return names
601
602
603class InstanceArguments(TreeArgumentsWrapper):
604 def __init__(self, instance, arguments):
605 super().__init__(arguments)
606 self.instance = instance
607
608 def unpack(self, func=None):
609 yield None, LazyKnownValue(self.instance)
610 yield from self._wrapped_arguments.unpack(func)