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