6 from collections
import namedtuple
11 from pathlib
import Path
12 from typing
import Optional
, Tuple
14 from jedi
.inference
.compiled
.getattr_static
import getattr_static
16 ALLOWED_GETITEM_TYPES
= (str, list, tuple, bytes
, bytearray
, dict)
18 MethodDescriptorType
= type(str.replace
)
19 # These are not considered classes and access is granted even though they have
20 # a __class__ attribute.
22 types
.BuiltinFunctionType
,
27 types
.GetSetDescriptorType
,
29 types
.MemberDescriptorType
,
34 types
.MappingProxyType
,
35 types
.SimpleNamespace
,
36 types
.DynamicClassAttribute
,
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__'])
48 # Maps Python syntax to the operator module.
49 COMPARISON_OPERATORS
= {
64 _OPERATORS
.update(COMPARISON_OPERATORS
)
66 ALLOWED_DESCRIPTOR_ACCESS
= (
68 types
.GetSetDescriptorType
,
69 types
.MemberDescriptorType
,
71 WrapperDescriptorType
,
72 ClassMethodDescriptorType
,
78 def safe_getattr(obj
, name
, default
=_sentinel
):
80 attr
, is_get_descriptor
= getattr_static(obj
, name
)
81 except AttributeError:
82 if default
is _sentinel
:
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
)
98 SignatureParam
= namedtuple(
100 'name has_default default default_string has_annotation annotation annotation_string kind_name'
104 def shorten_repr(func
):
113 def create_access(inference_state
, obj
):
114 return inference_state
.compiled_subprocess
.get_or_create_access_handle(obj
)
117 def load_module(inference_state
, dotted_name
, sys_path
):
118 temp
, sys
.path
= sys
.path
, sys_path
120 __import__(dotted_name
)
122 # If a module is "corrupt" or not really a Python module or whatever.
124 "Module %s not importable in path %s." % (dotted_name
, sys_path
),
130 # Since __import__ pretty much makes code execution possible, just
131 # catch any error here and print it.
133 "Cannot import:\n%s" % traceback
.format_exc(), UserWarning, stacklevel
=2
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
)
146 def __init__(self
, accesses
):
147 self
.accesses
= accesses
150 def create_access_path(inference_state
, obj
) -> AccessPath
:
151 access
= create_access(inference_state
, obj
)
152 return AccessPath(access
.get_access_path_tuples())
155 def get_api_type(obj
):
156 if inspect
.isclass(obj
):
158 elif inspect
.ismodule(obj
):
160 elif inspect
.isbuiltin(obj
) or inspect
.ismethod(obj
) \
161 or inspect
.ismethoddescriptor(obj
) or inspect
.isfunction(obj
):
167 class DirectObjectAccess
:
168 def __init__(self
, inference_state
, obj
):
169 self
._inference
_state
= inference_state
173 return '%s(%s)' % (self
.__class
__.__name
__, self
.get_repr())
175 def _create_access(self
, obj
):
176 return create_access(self
._inference
_state
, obj
)
178 def _create_access_path(self
, obj
) -> AccessPath
:
179 return create_access_path(self
._inference
_state
, obj
)
181 def py__bool__(self
):
182 return bool(self
._obj
)
184 def py__file__(self
) -> Optional
[Path
]:
186 return Path(self
._obj
.__file
__)
187 except AttributeError:
191 return inspect
.getdoc(self
._obj
) or ''
193 def py__name__(self
):
194 if not _is_class_instance(self
._obj
) or \
195 inspect
.ismethoddescriptor(self
._obj
): # slots
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`.
207 except AttributeError:
210 def py__mro__accesses(self
):
211 return tuple(self
._create
_access
_path
(cls
) for cls
in self
._obj
.__mro
__[1:])
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
]
219 if self
.is_instance():
220 cls
= DirectObjectAccess(self
._inference
_state
, self
._obj
.__class
__)
221 return cls
.py__getitem__all_values()
224 getitem
= self
._obj
.__getitem
__
225 except AttributeError:
228 annotation
= DirectObjectAccess(self
._inference
_state
, getitem
).get_return_annotation()
229 if annotation
is not None:
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.
238 return self
._create
_access
_path
(self
._obj
[index
])
240 def py__iter__list(self
):
242 iter_method
= self
._obj
.__iter
__
243 except AttributeError:
246 p
= DirectObjectAccess(self
._inference
_state
, iter_method
).get_return_annotation()
250 if type(self
._obj
) not in ALLOWED_GETITEM_TYPES
:
251 # Get rid of side effects, we won't call custom `__getitem__`s.
255 for i
, part
in enumerate(self
._obj
):
257 # Should not go crazy with large iterators
259 lst
.append(self
._create
_access
_path
(part
))
262 def py__class__(self
):
263 return self
._create
_access
_path
(self
._obj
.__class
__)
265 def py__bases__(self
):
266 return [self
._create
_access
_path
(base
) for base
in self
._obj
.__bases
__]
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
272 if not isinstance(paths
, list) \
273 or not all(isinstance(p
, str) for p
in paths
):
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
)
285 type_
= type(self
._obj
)
287 return type.__repr
__(self
._obj
)
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
)
295 return inspect
.isclass(self
._obj
)
297 def is_function(self
):
298 return inspect
.isfunction(self
._obj
) or inspect
.ismethod(self
._obj
)
301 return inspect
.ismodule(self
._obj
)
303 def is_instance(self
):
304 return _is_class_instance(self
._obj
)
306 def ismethoddescriptor(self
):
307 return inspect
.ismethoddescriptor(self
._obj
)
309 def get_qualified_names(self
):
310 def try_to_get_name(obj
):
311 return getattr(obj
, '__qualname__', getattr(obj
, '__name__', None))
315 name
= try_to_get_name(self
._obj
)
317 name
= try_to_get_name(type(self
._obj
))
320 return tuple(name
.split('.'))
323 return dir(self
._obj
)
332 def is_allowed_getattr(self
, name
, safe
=True) -> Tuple
[bool, bool, Optional
[AccessPath
]]:
333 # TODO this API is ugly.
335 attr
, is_get_descriptor
= getattr_static(self
._obj
, name
)
336 except AttributeError:
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.
343 # Avoid warnings, see comment in the next function.
344 with warnings
.catch_warnings(record
=True):
345 warnings
.simplefilter("always")
347 return hasattr(self
._obj
, name
), False, None
349 # Obviously has an attribute (probably a property) that
350 # gets executed, so just avoid all exceptions here.
352 return False, False, None
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
364 def getattr_paths(self
, name
, default
=_sentinel
):
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
378 # Just in case anything happens, return an AttributeError. It
382 access
= self
._create
_access
(return_obj
)
383 if inspect
.ismodule(return_obj
):
387 module
= return_obj
.__module
__
388 except AttributeError:
391 if module
is not None and isinstance(module
, str):
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.
402 module
= inspect
.getmodule(return_obj
)
404 module
= inspect
.getmodule(type(return_obj
))
407 return [self
._create
_access
(module
), access
]
409 def get_safe_value(self
):
410 if type(self
._obj
) in (bool, bytes
, float, int, str, slice) or self
._obj
is None:
412 raise ValueError("Object is type %s and not simple" % type(self
._obj
))
414 def get_api_type(self
):
415 return get_api_type(self
._obj
)
417 def get_array_type(self
):
418 if isinstance(self
._obj
, dict):
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
432 return [self
._create
_access
_path
(k
) for k
in iter_partial_keys()]
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
]
438 def _get_objects_path(self
):
443 obj
= obj
.__objclass
__
444 except AttributeError:
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
):
458 # Happens for example in `(_ for _ in []).send.__module__`.
462 yield sys
.modules
[imp_plz
]
464 # __module__ can be something arbitrary that doesn't exist.
467 return list(reversed(list(get())))
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
))
474 def get_annotation_name_and_args(self
):
476 Returns Tuple[Optional[str], Tuple[AccessPath, ...]]
480 if safe_getattr(self
._obj
, '__module__', default
='') == 'typing':
481 m
= re
.match(r
'typing.(\w+)\[', repr(self
._obj
))
486 if sys
.version_info
>= (3, 8):
487 args
= typing
.get_args(self
._obj
)
489 args
= safe_getattr(self
._obj
, '__args__', default
=None)
490 return name
, tuple(self
._create
_access
_path
(arg
) for arg
in args
)
492 def needs_type_completions(self
):
493 return inspect
.isclass(self
._obj
) and self
._obj
!= type
495 def _annotation_to_str(self
, annotation
):
496 return inspect
.formatannotation(annotation
)
498 def get_signature_params(self
):
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()
512 def _get_signature(self
):
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.
522 def get_return_annotation(self
) -> Optional
[AccessPath
]:
524 o
= self
._obj
.__annotations
__.get('return')
525 except AttributeError:
532 o
= typing
.get_type_hints(self
._obj
).get('return')
536 return self
._create
_access
_path
(o
)
539 return self
._create
_access
_path
(-self
._obj
)
541 def get_dir_infos(self
):
543 Used to return a couple of infos that are needed when accessing the sub
544 objects of an objects
547 (name
, self
.is_allowed_getattr(name
))
548 for name
in self
.dir()
550 return self
.needs_type_completions(), tuples
553 def _is_class_instance(obj
):
554 """Like inspect.* methods."""
557 except AttributeError:
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
)