access.py 18 KB

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