]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/compiled/access.py
Archivo de configuraciĆ³n de la terminal
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / compiled / access.py
CommitLineData
53e6db90
DC
1import inspect
2import types
3import traceback
4import sys
5import operator as op
6from collections import namedtuple
7import warnings
8import re
9import builtins
10import typing
11from pathlib import Path
12from typing import Optional, Tuple
13
14from jedi.inference.compiled.getattr_static import getattr_static
15
16ALLOWED_GETITEM_TYPES = (str, list, tuple, bytes, bytearray, dict)
17
18MethodDescriptorType = type(str.replace)
19# These are not considered classes and access is granted even though they have
20# a __class__ attribute.
21NOT_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.
40MethodDescriptorType = type(str.replace)
41WrapperDescriptorType = type(set.__iter__)
42# `object.__subclasshook__` is an already executed descriptor.
43object_class_dict = type.__dict__["__dict__"].__get__(object) # type: ignore[index]
44ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
45
46_sentinel = object()
47
48# Maps Python syntax to the operator module.
49COMPARISON_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
66ALLOWED_DESCRIPTOR_ACCESS = (
67 types.FunctionType,
68 types.GetSetDescriptorType,
69 types.MemberDescriptorType,
70 MethodDescriptorType,
71 WrapperDescriptorType,
72 ClassMethodDescriptorType,
73 staticmethod,
74 classmethod,
75)
76
77
78def 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
98SignatureParam = namedtuple(
99 'SignatureParam',
100 'name has_default default default_string has_annotation annotation annotation_string kind_name'
101)
102
103
104def 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
113def create_access(inference_state, obj):
114 return inference_state.compiled_subprocess.get_or_create_access_handle(obj)
115
116
117def 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
145class AccessPath:
146 def __init__(self, accesses):
147 self.accesses = accesses
148
149
150def create_access_path(inference_state, obj) -> AccessPath:
151 access = create_access(inference_state, obj)
152 return AccessPath(access.get_access_path_tuples())
153
154
155def 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
167class 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
553def _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)