]> crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/compiled/access.py
ActualizaciĆ³n de Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / compiled / access.py
1 import inspect
2 import types
3 import traceback
4 import sys
5 import operator as op
6 from collections import namedtuple
7 import warnings
8 import re
9 import builtins
10 import typing
11 from pathlib import Path
12 from typing import Optional, Tuple
13
14 from jedi.inference.compiled.getattr_static import getattr_static
15
16 ALLOWED_GETITEM_TYPES = (str, list, tuple, bytes, bytearray, dict)
17
18 MethodDescriptorType = type(str.replace)
19 # These are not considered classes and access is granted even though they have
20 # a __class__ attribute.
21 NOT_CLASS_TYPES = (
22 types.BuiltinFunctionType,
23 types.CodeType,
24 types.FrameType,
25 types.FunctionType,
26 types.GeneratorType,
27 types.GetSetDescriptorType,
28 types.LambdaType,
29 types.MemberDescriptorType,
30 types.MethodType,
31 types.ModuleType,
32 types.TracebackType,
33 MethodDescriptorType,
34 types.MappingProxyType,
35 types.SimpleNamespace,
36 types.DynamicClassAttribute,
37 )
38
39 # Those types don't exist in typing.
40 MethodDescriptorType = type(str.replace)
41 WrapperDescriptorType = type(set.__iter__)
42 # `object.__subclasshook__` is an already executed descriptor.
43 object_class_dict = type.__dict__["__dict__"].__get__(object) # type: ignore[index]
44 ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
45
46 _sentinel = object()
47
48 # Maps Python syntax to the operator module.
49 COMPARISON_OPERATORS = {
50 '==': op.eq,
51 '!=': op.ne,
52 'is': op.is_,
53 'is not': op.is_not,
54 '<': op.lt,
55 '<=': op.le,
56 '>': op.gt,
57 '>=': op.ge,
58 }
59
60 _OPERATORS = {
61 '+': op.add,
62 '-': op.sub,
63 }
64 _OPERATORS.update(COMPARISON_OPERATORS)
65
66 ALLOWED_DESCRIPTOR_ACCESS = (
67 types.FunctionType,
68 types.GetSetDescriptorType,
69 types.MemberDescriptorType,
70 MethodDescriptorType,
71 WrapperDescriptorType,
72 ClassMethodDescriptorType,
73 staticmethod,
74 classmethod,
75 )
76
77
78 def safe_getattr(obj, name, default=_sentinel):
79 try:
80 attr, is_get_descriptor = getattr_static(obj, name)
81 except AttributeError:
82 if default is _sentinel:
83 raise
84 return default
85 else:
86 if isinstance(attr, ALLOWED_DESCRIPTOR_ACCESS):
87 # In case of descriptors that have get methods we cannot return
88 # it's value, because that would mean code execution.
89 # Since it's an isinstance call, code execution is still possible,
90 # but this is not really a security feature, but much more of a
91 # safety feature. Code execution is basically always possible when
92 # a module is imported. This is here so people don't shoot
93 # themselves in the foot.
94 return getattr(obj, name)
95 return attr
96
97
98 SignatureParam = namedtuple(
99 'SignatureParam',
100 'name has_default default default_string has_annotation annotation annotation_string kind_name'
101 )
102
103
104 def shorten_repr(func):
105 def wrapper(self):
106 r = func(self)
107 if len(r) > 50:
108 r = r[:50] + '..'
109 return r
110 return wrapper
111
112
113 def create_access(inference_state, obj):
114 return inference_state.compiled_subprocess.get_or_create_access_handle(obj)
115
116
117 def load_module(inference_state, dotted_name, sys_path):
118 temp, sys.path = sys.path, sys_path
119 try:
120 __import__(dotted_name)
121 except ImportError:
122 # If a module is "corrupt" or not really a Python module or whatever.
123 warnings.warn(
124 "Module %s not importable in path %s." % (dotted_name, sys_path),
125 UserWarning,
126 stacklevel=2,
127 )
128 return None
129 except Exception:
130 # Since __import__ pretty much makes code execution possible, just
131 # catch any error here and print it.
132 warnings.warn(
133 "Cannot import:\n%s" % traceback.format_exc(), UserWarning, stacklevel=2
134 )
135 return None
136 finally:
137 sys.path = temp
138
139 # Just access the cache after import, because of #59 as well as the very
140 # complicated import structure of Python.
141 module = sys.modules[dotted_name]
142 return create_access_path(inference_state, module)
143
144
145 class AccessPath:
146 def __init__(self, accesses):
147 self.accesses = accesses
148
149
150 def create_access_path(inference_state, obj) -> AccessPath:
151 access = create_access(inference_state, obj)
152 return AccessPath(access.get_access_path_tuples())
153
154
155 def get_api_type(obj):
156 if inspect.isclass(obj):
157 return 'class'
158 elif inspect.ismodule(obj):
159 return 'module'
160 elif inspect.isbuiltin(obj) or inspect.ismethod(obj) \
161 or inspect.ismethoddescriptor(obj) or inspect.isfunction(obj):
162 return 'function'
163 # Everything else...
164 return 'instance'
165
166
167 class DirectObjectAccess:
168 def __init__(self, inference_state, obj):
169 self._inference_state = inference_state
170 self._obj = obj
171
172 def __repr__(self):
173 return '%s(%s)' % (self.__class__.__name__, self.get_repr())
174
175 def _create_access(self, obj):
176 return create_access(self._inference_state, obj)
177
178 def _create_access_path(self, obj) -> AccessPath:
179 return create_access_path(self._inference_state, obj)
180
181 def py__bool__(self):
182 return bool(self._obj)
183
184 def py__file__(self) -> Optional[Path]:
185 try:
186 return Path(self._obj.__file__)
187 except AttributeError:
188 return None
189
190 def py__doc__(self):
191 return inspect.getdoc(self._obj) or ''
192
193 def py__name__(self):
194 if not _is_class_instance(self._obj) or \
195 inspect.ismethoddescriptor(self._obj): # slots
196 cls = self._obj
197 else:
198 try:
199 cls = self._obj.__class__
200 except AttributeError:
201 # happens with numpy.core.umath._UFUNC_API (you get it
202 # automatically by doing `import numpy`.
203 return None
204
205 try:
206 return cls.__name__
207 except AttributeError:
208 return None
209
210 def py__mro__accesses(self):
211 return tuple(self._create_access_path(cls) for cls in self._obj.__mro__[1:])
212
213 def py__getitem__all_values(self):
214 if isinstance(self._obj, dict):
215 return [self._create_access_path(v) for v in self._obj.values()]
216 if isinstance(self._obj, (list, tuple)):
217 return [self._create_access_path(v) for v in self._obj]
218
219 if self.is_instance():
220 cls = DirectObjectAccess(self._inference_state, self._obj.__class__)
221 return cls.py__getitem__all_values()
222
223 try:
224 getitem = self._obj.__getitem__
225 except AttributeError:
226 pass
227 else:
228 annotation = DirectObjectAccess(self._inference_state, getitem).get_return_annotation()
229 if annotation is not None:
230 return [annotation]
231 return None
232
233 def py__simple_getitem__(self, index, *, safe=True):
234 if safe and type(self._obj) not in ALLOWED_GETITEM_TYPES:
235 # Get rid of side effects, we won't call custom `__getitem__`s.
236 return None
237
238 return self._create_access_path(self._obj[index])
239
240 def py__iter__list(self):
241 try:
242 iter_method = self._obj.__iter__
243 except AttributeError:
244 return None
245 else:
246 p = DirectObjectAccess(self._inference_state, iter_method).get_return_annotation()
247 if p is not None:
248 return [p]
249
250 if type(self._obj) not in ALLOWED_GETITEM_TYPES:
251 # Get rid of side effects, we won't call custom `__getitem__`s.
252 return []
253
254 lst = []
255 for i, part in enumerate(self._obj):
256 if i > 20:
257 # Should not go crazy with large iterators
258 break
259 lst.append(self._create_access_path(part))
260 return lst
261
262 def py__class__(self):
263 return self._create_access_path(self._obj.__class__)
264
265 def py__bases__(self):
266 return [self._create_access_path(base) for base in self._obj.__bases__]
267
268 def py__path__(self):
269 paths = getattr(self._obj, '__path__', None)
270 # Avoid some weird hacks that would just fail, because they cannot be
271 # used by pickle.
272 if not isinstance(paths, list) \
273 or not all(isinstance(p, str) for p in paths):
274 return None
275 return paths
276
277 @shorten_repr
278 def get_repr(self):
279 if inspect.ismodule(self._obj):
280 return repr(self._obj)
281 # Try to avoid execution of the property.
282 if safe_getattr(self._obj, '__module__', default='') == 'builtins':
283 return repr(self._obj)
284
285 type_ = type(self._obj)
286 if type_ == type:
287 return type.__repr__(self._obj)
288
289 if safe_getattr(type_, '__module__', default='') == 'builtins':
290 # Allow direct execution of repr for builtins.
291 return repr(self._obj)
292 return object.__repr__(self._obj)
293
294 def is_class(self):
295 return inspect.isclass(self._obj)
296
297 def is_function(self):
298 return inspect.isfunction(self._obj) or inspect.ismethod(self._obj)
299
300 def is_module(self):
301 return inspect.ismodule(self._obj)
302
303 def is_instance(self):
304 return _is_class_instance(self._obj)
305
306 def ismethoddescriptor(self):
307 return inspect.ismethoddescriptor(self._obj)
308
309 def get_qualified_names(self):
310 def try_to_get_name(obj):
311 return getattr(obj, '__qualname__', getattr(obj, '__name__', None))
312
313 if self.is_module():
314 return ()
315 name = try_to_get_name(self._obj)
316 if name is None:
317 name = try_to_get_name(type(self._obj))
318 if name is None:
319 return ()
320 return tuple(name.split('.'))
321
322 def dir(self):
323 return dir(self._obj)
324
325 def has_iter(self):
326 try:
327 iter(self._obj)
328 return True
329 except TypeError:
330 return False
331
332 def is_allowed_getattr(self, name, safe=True) -> Tuple[bool, bool, Optional[AccessPath]]:
333 # TODO this API is ugly.
334 try:
335 attr, is_get_descriptor = getattr_static(self._obj, name)
336 except AttributeError:
337 if not safe:
338 # Unsafe is mostly used to check for __getattr__/__getattribute__.
339 # getattr_static works for properties, but the underscore methods
340 # are just ignored (because it's safer and avoids more code
341 # execution). See also GH #1378.
342
343 # Avoid warnings, see comment in the next function.
344 with warnings.catch_warnings(record=True):
345 warnings.simplefilter("always")
346 try:
347 return hasattr(self._obj, name), False, None
348 except Exception:
349 # Obviously has an attribute (probably a property) that
350 # gets executed, so just avoid all exceptions here.
351 pass
352 return False, False, None
353 else:
354 if is_get_descriptor and type(attr) not in ALLOWED_DESCRIPTOR_ACCESS:
355 if isinstance(attr, property):
356 if hasattr(attr.fget, '__annotations__'):
357 a = DirectObjectAccess(self._inference_state, attr.fget)
358 return True, True, a.get_return_annotation()
359 # In case of descriptors that have get methods we cannot return
360 # it's value, because that would mean code execution.
361 return True, True, None
362 return True, False, None
363
364 def getattr_paths(self, name, default=_sentinel):
365 try:
366 # Make sure no warnings are printed here, this is autocompletion,
367 # warnings should not be shown. See also GH #1383.
368 with warnings.catch_warnings(record=True):
369 warnings.simplefilter("always")
370 return_obj = getattr(self._obj, name)
371 except Exception as e:
372 if default is _sentinel:
373 if isinstance(e, AttributeError):
374 # Happens e.g. in properties of
375 # PyQt4.QtGui.QStyleOptionComboBox.currentText
376 # -> just set it to None
377 raise
378 # Just in case anything happens, return an AttributeError. It
379 # should not crash.
380 raise AttributeError
381 return_obj = default
382 access = self._create_access(return_obj)
383 if inspect.ismodule(return_obj):
384 return [access]
385
386 try:
387 module = return_obj.__module__
388 except AttributeError:
389 pass
390 else:
391 if module is not None and isinstance(module, str):
392 try:
393 __import__(module)
394 # For some modules like _sqlite3, the __module__ for classes is
395 # different, in this case it's sqlite3. So we have to try to
396 # load that "original" module, because it's not loaded yet. If
397 # we don't do that, we don't really have a "parent" module and
398 # we would fall back to builtins.
399 except ImportError:
400 pass
401
402 module = inspect.getmodule(return_obj)
403 if module is None:
404 module = inspect.getmodule(type(return_obj))
405 if module is None:
406 module = builtins
407 return [self._create_access(module), access]
408
409 def get_safe_value(self):
410 if type(self._obj) in (bool, bytes, float, int, str, slice) or self._obj is None:
411 return self._obj
412 raise ValueError("Object is type %s and not simple" % type(self._obj))
413
414 def get_api_type(self):
415 return get_api_type(self._obj)
416
417 def get_array_type(self):
418 if isinstance(self._obj, dict):
419 return 'dict'
420 return None
421
422 def get_key_paths(self):
423 def iter_partial_keys():
424 # We could use list(keys()), but that might take a lot more memory.
425 for (i, k) in enumerate(self._obj.keys()):
426 # Limit key listing at some point. This is artificial, but this
427 # way we don't get stalled because of slow completions
428 if i > 50:
429 break
430 yield k
431
432 return [self._create_access_path(k) for k in iter_partial_keys()]
433
434 def get_access_path_tuples(self):
435 accesses = [create_access(self._inference_state, o) for o in self._get_objects_path()]
436 return [(access.py__name__(), access) for access in accesses]
437
438 def _get_objects_path(self):
439 def get():
440 obj = self._obj
441 yield obj
442 try:
443 obj = obj.__objclass__
444 except AttributeError:
445 pass
446 else:
447 yield obj
448
449 try:
450 # Returns a dotted string path.
451 imp_plz = obj.__module__
452 except AttributeError:
453 # Unfortunately in some cases like `int` there's no __module__
454 if not inspect.ismodule(obj):
455 yield builtins
456 else:
457 if imp_plz is None:
458 # Happens for example in `(_ for _ in []).send.__module__`.
459 yield builtins
460 else:
461 try:
462 yield sys.modules[imp_plz]
463 except KeyError:
464 # __module__ can be something arbitrary that doesn't exist.
465 yield builtins
466
467 return list(reversed(list(get())))
468
469 def execute_operation(self, other_access_handle, operator):
470 other_access = other_access_handle.access
471 op = _OPERATORS[operator]
472 return self._create_access_path(op(self._obj, other_access._obj))
473
474 def get_annotation_name_and_args(self):
475 """
476 Returns Tuple[Optional[str], Tuple[AccessPath, ...]]
477 """
478 name = None
479 args = ()
480 if safe_getattr(self._obj, '__module__', default='') == 'typing':
481 m = re.match(r'typing.(\w+)\[', repr(self._obj))
482 if m is not None:
483 name = m.group(1)
484
485 import typing
486 if sys.version_info >= (3, 8):
487 args = typing.get_args(self._obj)
488 else:
489 args = safe_getattr(self._obj, '__args__', default=None)
490 return name, tuple(self._create_access_path(arg) for arg in args)
491
492 def needs_type_completions(self):
493 return inspect.isclass(self._obj) and self._obj != type
494
495 def _annotation_to_str(self, annotation):
496 return inspect.formatannotation(annotation)
497
498 def get_signature_params(self):
499 return [
500 SignatureParam(
501 name=p.name,
502 has_default=p.default is not p.empty,
503 default=self._create_access_path(p.default),
504 default_string=repr(p.default),
505 has_annotation=p.annotation is not p.empty,
506 annotation=self._create_access_path(p.annotation),
507 annotation_string=self._annotation_to_str(p.annotation),
508 kind_name=str(p.kind)
509 ) for p in self._get_signature().parameters.values()
510 ]
511
512 def _get_signature(self):
513 obj = self._obj
514 try:
515 return inspect.signature(obj)
516 except (RuntimeError, TypeError):
517 # Reading the code of the function in Python 3.6 implies there are
518 # at least these errors that might occur if something is wrong with
519 # the signature. In that case we just want a simple escape for now.
520 raise ValueError
521
522 def get_return_annotation(self) -> Optional[AccessPath]:
523 try:
524 o = self._obj.__annotations__.get('return')
525 except AttributeError:
526 return None
527
528 if o is None:
529 return None
530
531 try:
532 o = typing.get_type_hints(self._obj).get('return')
533 except Exception:
534 pass
535
536 return self._create_access_path(o)
537
538 def negate(self):
539 return self._create_access_path(-self._obj)
540
541 def get_dir_infos(self):
542 """
543 Used to return a couple of infos that are needed when accessing the sub
544 objects of an objects
545 """
546 tuples = dict(
547 (name, self.is_allowed_getattr(name))
548 for name in self.dir()
549 )
550 return self.needs_type_completions(), tuples
551
552
553 def _is_class_instance(obj):
554 """Like inspect.* methods."""
555 try:
556 cls = obj.__class__
557 except AttributeError:
558 return False
559 else:
560 # The isinstance check for cls is just there so issubclass doesn't
561 # raise an exception.
562 return cls != type and isinstance(cls, type) and not issubclass(cls, NOT_CLASS_TYPES)