]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/compiled/value.py
Archivo de configuraciĆ³n de la terminal
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / compiled / value.py
CommitLineData
53e6db90
DC
1"""
2Imitate the parser representation.
3"""
4import re
5from functools import partial
6from inspect import Parameter
7from pathlib import Path
8from typing import Optional
9
10from jedi import debug
11from jedi.inference.utils import to_list
12from jedi.cache import memoize_method
13from jedi.inference.filters import AbstractFilter
14from jedi.inference.names import AbstractNameDefinition, ValueNameMixin, \
15 ParamNameInterface
16from jedi.inference.base_value import Value, ValueSet, NO_VALUES
17from jedi.inference.lazy_value import LazyKnownValue
18from jedi.inference.compiled.access import _sentinel
19from jedi.inference.cache import inference_state_function_cache
20from jedi.inference.helpers import reraise_getitem_errors
21from jedi.inference.signature import BuiltinSignature
22from jedi.inference.context import CompiledContext, CompiledModuleContext
23
24
25class CheckAttribute:
26 """Raises :exc:`AttributeError` if the attribute X is not available."""
27 def __init__(self, check_name=None):
28 # Remove the py in front of e.g. py__call__.
29 self.check_name = check_name
30
31 def __call__(self, func):
32 self.func = func
33 if self.check_name is None:
34 self.check_name = func.__name__[2:]
35 return self
36
37 def __get__(self, instance, owner):
38 if instance is None:
39 return self
40
41 # This might raise an AttributeError. That's wanted.
42 instance.access_handle.getattr_paths(self.check_name)
43 return partial(self.func, instance)
44
45
46class CompiledValue(Value):
47 def __init__(self, inference_state, access_handle, parent_context=None):
48 super().__init__(inference_state, parent_context)
49 self.access_handle = access_handle
50
51 def py__call__(self, arguments):
52 return_annotation = self.access_handle.get_return_annotation()
53 if return_annotation is not None:
54 return create_from_access_path(
55 self.inference_state,
56 return_annotation
57 ).execute_annotation()
58
59 try:
60 self.access_handle.getattr_paths('__call__')
61 except AttributeError:
62 return super().py__call__(arguments)
63 else:
64 if self.access_handle.is_class():
65 from jedi.inference.value import CompiledInstance
66 return ValueSet([
67 CompiledInstance(self.inference_state, self.parent_context, self, arguments)
68 ])
69 else:
70 return ValueSet(self._execute_function(arguments))
71
72 @CheckAttribute()
73 def py__class__(self):
74 return create_from_access_path(self.inference_state, self.access_handle.py__class__())
75
76 @CheckAttribute()
77 def py__mro__(self):
78 return (self,) + tuple(
79 create_from_access_path(self.inference_state, access)
80 for access in self.access_handle.py__mro__accesses()
81 )
82
83 @CheckAttribute()
84 def py__bases__(self):
85 return tuple(
86 create_from_access_path(self.inference_state, access)
87 for access in self.access_handle.py__bases__()
88 )
89
90 def get_qualified_names(self):
91 return self.access_handle.get_qualified_names()
92
93 def py__bool__(self):
94 return self.access_handle.py__bool__()
95
96 def is_class(self):
97 return self.access_handle.is_class()
98
99 def is_function(self):
100 return self.access_handle.is_function()
101
102 def is_module(self):
103 return self.access_handle.is_module()
104
105 def is_compiled(self):
106 return True
107
108 def is_stub(self):
109 return False
110
111 def is_instance(self):
112 return self.access_handle.is_instance()
113
114 def py__doc__(self):
115 return self.access_handle.py__doc__()
116
117 @to_list
118 def get_param_names(self):
119 try:
120 signature_params = self.access_handle.get_signature_params()
121 except ValueError: # Has no signature
122 params_str, ret = self._parse_function_doc()
123 if not params_str:
124 tokens = []
125 else:
126 tokens = params_str.split(',')
127 if self.access_handle.ismethoddescriptor():
128 tokens.insert(0, 'self')
129 for p in tokens:
130 name, _, default = p.strip().partition('=')
131 yield UnresolvableParamName(self, name, default)
132 else:
133 for signature_param in signature_params:
134 yield SignatureParamName(self, signature_param)
135
136 def get_signatures(self):
137 _, return_string = self._parse_function_doc()
138 return [BuiltinSignature(self, return_string)]
139
140 def __repr__(self):
141 return '<%s: %s>' % (self.__class__.__name__, self.access_handle.get_repr())
142
143 @memoize_method
144 def _parse_function_doc(self):
145 doc = self.py__doc__()
146 if doc is None:
147 return '', ''
148
149 return _parse_function_doc(doc)
150
151 @property
152 def api_type(self):
153 return self.access_handle.get_api_type()
154
155 def get_filters(self, is_instance=False, origin_scope=None):
156 yield self._ensure_one_filter(is_instance)
157
158 @memoize_method
159 def _ensure_one_filter(self, is_instance):
160 return CompiledValueFilter(self.inference_state, self, is_instance)
161
162 def py__simple_getitem__(self, index):
163 with reraise_getitem_errors(IndexError, KeyError, TypeError):
164 try:
165 access = self.access_handle.py__simple_getitem__(
166 index,
167 safe=not self.inference_state.allow_unsafe_executions
168 )
169 except AttributeError:
170 return super().py__simple_getitem__(index)
171 if access is None:
172 return super().py__simple_getitem__(index)
173
174 return ValueSet([create_from_access_path(self.inference_state, access)])
175
176 def py__getitem__(self, index_value_set, contextualized_node):
177 all_access_paths = self.access_handle.py__getitem__all_values()
178 if all_access_paths is None:
179 # This means basically that no __getitem__ has been defined on this
180 # object.
181 return super().py__getitem__(index_value_set, contextualized_node)
182 return ValueSet(
183 create_from_access_path(self.inference_state, access)
184 for access in all_access_paths
185 )
186
187 def py__iter__(self, contextualized_node=None):
188 if not self.access_handle.has_iter():
189 yield from super().py__iter__(contextualized_node)
190
191 access_path_list = self.access_handle.py__iter__list()
192 if access_path_list is None:
193 # There is no __iter__ method on this object.
194 return
195
196 for access in access_path_list:
197 yield LazyKnownValue(create_from_access_path(self.inference_state, access))
198
199 def py__name__(self):
200 return self.access_handle.py__name__()
201
202 @property
203 def name(self):
204 name = self.py__name__()
205 if name is None:
206 name = self.access_handle.get_repr()
207 return CompiledValueName(self, name)
208
209 def _execute_function(self, params):
210 from jedi.inference import docstrings
211 from jedi.inference.compiled import builtin_from_name
212 if self.api_type != 'function':
213 return
214
215 for name in self._parse_function_doc()[1].split():
216 try:
217 # TODO wtf is this? this is exactly the same as the thing
218 # below. It uses getattr as well.
219 self.inference_state.builtins_module.access_handle.getattr_paths(name)
220 except AttributeError:
221 continue
222 else:
223 bltn_obj = builtin_from_name(self.inference_state, name)
224 yield from self.inference_state.execute(bltn_obj, params)
225 yield from docstrings.infer_return_types(self)
226
227 def get_safe_value(self, default=_sentinel):
228 try:
229 return self.access_handle.get_safe_value()
230 except ValueError:
231 if default == _sentinel:
232 raise
233 return default
234
235 def execute_operation(self, other, operator):
236 try:
237 return ValueSet([create_from_access_path(
238 self.inference_state,
239 self.access_handle.execute_operation(other.access_handle, operator)
240 )])
241 except TypeError:
242 return NO_VALUES
243
244 def execute_annotation(self):
245 if self.access_handle.get_repr() == 'None':
246 # None as an annotation doesn't need to be executed.
247 return ValueSet([self])
248
249 name, args = self.access_handle.get_annotation_name_and_args()
250 arguments = [
251 ValueSet([create_from_access_path(self.inference_state, path)])
252 for path in args
253 ]
254 if name == 'Union':
255 return ValueSet.from_sets(arg.execute_annotation() for arg in arguments)
256 elif name:
257 # While with_generics only exists on very specific objects, we
258 # should probably be fine, because we control all the typing
259 # objects.
260 return ValueSet([
261 v.with_generics(arguments)
262 for v in self.inference_state.typing_module.py__getattribute__(name)
263 ]).execute_annotation()
264 return super().execute_annotation()
265
266 def negate(self):
267 return create_from_access_path(self.inference_state, self.access_handle.negate())
268
269 def get_metaclasses(self):
270 return NO_VALUES
271
272 def _as_context(self):
273 return CompiledContext(self)
274
275 @property
276 def array_type(self):
277 return self.access_handle.get_array_type()
278
279 def get_key_values(self):
280 return [
281 create_from_access_path(self.inference_state, k)
282 for k in self.access_handle.get_key_paths()
283 ]
284
285 def get_type_hint(self, add_class_info=True):
286 if self.access_handle.get_repr() in ('None', "<class 'NoneType'>"):
287 return 'None'
288 return None
289
290
291class CompiledModule(CompiledValue):
292 file_io = None # For modules
293
294 def _as_context(self):
295 return CompiledModuleContext(self)
296
297 def py__path__(self):
298 return self.access_handle.py__path__()
299
300 def is_package(self):
301 return self.py__path__() is not None
302
303 @property
304 def string_names(self):
305 # For modules
306 name = self.py__name__()
307 if name is None:
308 return ()
309 return tuple(name.split('.'))
310
311 def py__file__(self) -> Optional[Path]:
312 return self.access_handle.py__file__() # type: ignore[no-any-return]
313
314
315class CompiledName(AbstractNameDefinition):
316 def __init__(self, inference_state, parent_value, name, is_descriptor):
317 self._inference_state = inference_state
318 self.parent_context = parent_value.as_context()
319 self._parent_value = parent_value
320 self.string_name = name
321 self.is_descriptor = is_descriptor
322
323 def py__doc__(self):
324 return self.infer_compiled_value().py__doc__()
325
326 def _get_qualified_names(self):
327 parent_qualified_names = self.parent_context.get_qualified_names()
328 if parent_qualified_names is None:
329 return None
330 return parent_qualified_names + (self.string_name,)
331
332 def get_defining_qualified_value(self):
333 context = self.parent_context
334 if context.is_module() or context.is_class():
335 return self.parent_context.get_value() # Might be None
336
337 return None
338
339 def __repr__(self):
340 try:
341 name = self.parent_context.name # __name__ is not defined all the time
342 except AttributeError:
343 name = None
344 return '<%s: (%s).%s>' % (self.__class__.__name__, name, self.string_name)
345
346 @property
347 def api_type(self):
348 if self.is_descriptor:
349 # In case of properties we want to avoid executions as much as
350 # possible. Since the api_type can be wrong for other reasons
351 # anyway, we just return instance here.
352 return "instance"
353 return self.infer_compiled_value().api_type
354
355 def infer(self):
356 return ValueSet([self.infer_compiled_value()])
357
358 @memoize_method
359 def infer_compiled_value(self):
360 return create_from_name(self._inference_state, self._parent_value, self.string_name)
361
362
363class SignatureParamName(ParamNameInterface, AbstractNameDefinition):
364 def __init__(self, compiled_value, signature_param):
365 self.parent_context = compiled_value.parent_context
366 self._signature_param = signature_param
367
368 @property
369 def string_name(self):
370 return self._signature_param.name
371
372 def to_string(self):
373 s = self._kind_string() + self.string_name
374 if self._signature_param.has_annotation:
375 s += ': ' + self._signature_param.annotation_string
376 if self._signature_param.has_default:
377 s += '=' + self._signature_param.default_string
378 return s
379
380 def get_kind(self):
381 return getattr(Parameter, self._signature_param.kind_name)
382
383 def infer(self):
384 p = self._signature_param
385 inference_state = self.parent_context.inference_state
386 values = NO_VALUES
387 if p.has_default:
388 values = ValueSet([create_from_access_path(inference_state, p.default)])
389 if p.has_annotation:
390 annotation = create_from_access_path(inference_state, p.annotation)
391 values |= annotation.execute_with_values()
392 return values
393
394
395class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition):
396 def __init__(self, compiled_value, name, default):
397 self.parent_context = compiled_value.parent_context
398 self.string_name = name
399 self._default = default
400
401 def get_kind(self):
402 return Parameter.POSITIONAL_ONLY
403
404 def to_string(self):
405 string = self.string_name
406 if self._default:
407 string += '=' + self._default
408 return string
409
410 def infer(self):
411 return NO_VALUES
412
413
414class CompiledValueName(ValueNameMixin, AbstractNameDefinition):
415 def __init__(self, value, name):
416 self.string_name = name
417 self._value = value
418 self.parent_context = value.parent_context
419
420
421class EmptyCompiledName(AbstractNameDefinition):
422 """
423 Accessing some names will raise an exception. To avoid not having any
424 completions, just give Jedi the option to return this object. It infers to
425 nothing.
426 """
427 def __init__(self, inference_state, name):
428 self.parent_context = inference_state.builtins_module
429 self.string_name = name
430
431 def infer(self):
432 return NO_VALUES
433
434
435class CompiledValueFilter(AbstractFilter):
436 def __init__(self, inference_state, compiled_value, is_instance=False):
437 self._inference_state = inference_state
438 self.compiled_value = compiled_value
439 self.is_instance = is_instance
440
441 def get(self, name):
442 access_handle = self.compiled_value.access_handle
443 safe = not self._inference_state.allow_unsafe_executions
444 return self._get(
445 name,
446 lambda name: access_handle.is_allowed_getattr(name, safe=safe),
447 lambda name: name in access_handle.dir(),
448 check_has_attribute=True
449 )
450
451 def _get(self, name, allowed_getattr_callback, in_dir_callback, check_has_attribute=False):
452 """
453 To remove quite a few access calls we introduced the callback here.
454 """
455 has_attribute, is_descriptor, property_return_annotation = allowed_getattr_callback(
456 name,
457 )
458 if property_return_annotation is not None:
459 values = create_from_access_path(
460 self._inference_state,
461 property_return_annotation
462 ).execute_annotation()
463 if values:
464 return [CompiledValueName(v, name) for v in values]
465
466 if check_has_attribute and not has_attribute:
467 return []
468
469 if (is_descriptor or not has_attribute) \
470 and not self._inference_state.allow_unsafe_executions:
471 return [self._get_cached_name(name, is_empty=True)]
472
473 if self.is_instance and not in_dir_callback(name):
474 return []
475 return [self._get_cached_name(name, is_descriptor=is_descriptor)]
476
477 @memoize_method
478 def _get_cached_name(self, name, is_empty=False, *, is_descriptor=False):
479 if is_empty:
480 return EmptyCompiledName(self._inference_state, name)
481 else:
482 return self._create_name(name, is_descriptor=is_descriptor)
483
484 def values(self):
485 from jedi.inference.compiled import builtin_from_name
486 names = []
487 needs_type_completions, dir_infos = self.compiled_value.access_handle.get_dir_infos()
488 # We could use `safe=False` here as well, especially as a parameter to
489 # get_dir_infos. But this would lead to a lot of property executions
490 # that are probably not wanted. The drawback for this is that we
491 # have a different name for `get` and `values`. For `get` we always
492 # execute.
493 for name in dir_infos:
494 names += self._get(
495 name,
496 lambda name: dir_infos[name],
497 lambda name: name in dir_infos,
498 )
499
500 # ``dir`` doesn't include the type names.
501 if not self.is_instance and needs_type_completions:
502 for filter in builtin_from_name(self._inference_state, 'type').get_filters():
503 names += filter.values()
504 return names
505
506 def _create_name(self, name, is_descriptor):
507 return CompiledName(
508 self._inference_state,
509 self.compiled_value,
510 name,
511 is_descriptor,
512 )
513
514 def __repr__(self):
515 return "<%s: %s>" % (self.__class__.__name__, self.compiled_value)
516
517
518docstr_defaults = {
519 'floating point number': 'float',
520 'character': 'str',
521 'integer': 'int',
522 'dictionary': 'dict',
523 'string': 'str',
524}
525
526
527def _parse_function_doc(doc):
528 """
529 Takes a function and returns the params and return value as a tuple.
530 This is nothing more than a docstring parser.
531
532 TODO docstrings like utime(path, (atime, mtime)) and a(b [, b]) -> None
533 TODO docstrings like 'tuple of integers'
534 """
535 # parse round parentheses: def func(a, (b,c))
536 try:
537 count = 0
538 start = doc.index('(')
539 for i, s in enumerate(doc[start:]):
540 if s == '(':
541 count += 1
542 elif s == ')':
543 count -= 1
544 if count == 0:
545 end = start + i
546 break
547 param_str = doc[start + 1:end]
548 except (ValueError, UnboundLocalError):
549 # ValueError for doc.index
550 # UnboundLocalError for undefined end in last line
551 debug.dbg('no brackets found - no param')
552 end = 0
553 param_str = ''
554 else:
555 # remove square brackets, that show an optional param ( = None)
556 def change_options(m):
557 args = m.group(1).split(',')
558 for i, a in enumerate(args):
559 if a and '=' not in a:
560 args[i] += '=None'
561 return ','.join(args)
562
563 while True:
564 param_str, changes = re.subn(r' ?\[([^\[\]]+)\]',
565 change_options, param_str)
566 if changes == 0:
567 break
568 param_str = param_str.replace('-', '_') # see: isinstance.__doc__
569
570 # parse return value
571 r = re.search('-[>-]* ', doc[end:end + 7])
572 if r is None:
573 ret = ''
574 else:
575 index = end + r.end()
576 # get result type, which can contain newlines
577 pattern = re.compile(r'(,\n|[^\n-])+')
578 ret_str = pattern.match(doc, index).group(0).strip()
579 # New object -> object()
580 ret_str = re.sub(r'[nN]ew (.*)', r'\1()', ret_str)
581
582 ret = docstr_defaults.get(ret_str, ret_str)
583
584 return param_str, ret
585
586
587def create_from_name(inference_state, compiled_value, name):
588 access_paths = compiled_value.access_handle.getattr_paths(name, default=None)
589
590 value = None
591 for access_path in access_paths:
592 value = create_cached_compiled_value(
593 inference_state,
594 access_path,
595 parent_context=None if value is None else value.as_context(),
596 )
597 return value
598
599
600def _normalize_create_args(func):
601 """The cache doesn't care about keyword vs. normal args."""
602 def wrapper(inference_state, obj, parent_context=None):
603 return func(inference_state, obj, parent_context)
604 return wrapper
605
606
607def create_from_access_path(inference_state, access_path):
608 value = None
609 for name, access in access_path.accesses:
610 value = create_cached_compiled_value(
611 inference_state,
612 access,
613 parent_context=None if value is None else value.as_context()
614 )
615 return value
616
617
618@_normalize_create_args
619@inference_state_function_cache()
620def create_cached_compiled_value(inference_state, access_handle, parent_context):
621 assert not isinstance(parent_context, CompiledValue)
622 if parent_context is None:
623 cls = CompiledModule
624 else:
625 cls = CompiledValue
626 return cls(inference_state, access_handle, parent_context)