value.py 21 KB

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