1 """ 2 Values are the "values" that Python would return. However Values are at the 3 same time also the "values" that a user is currently sitting in. 4 5 A ValueSet is typically used to specify the return of a function or any other 6 static analysis operation. In jedi there are always multiple returns and not 7 just one. 8 """ 9 from functools import reduce 10 from operator import add 11 from itertools import zip_longest 12 13 from parso.python.tree import Name 14 15 from jedi import debug 16 from jedi.parser_utils import clean_scope_docstring 17 from jedi.inference.helpers import SimpleGetItemNotFound 18 from jedi.inference.utils import safe_property 19 from jedi.inference.cache import inference_state_as_method_param_cache 20 from jedi.cache import memoize_method 21 22 sentinel = object() 23 24 25 class HasNoContext(Exception): 26 pass 27 28 29 class HelperValueMixin: 30 def get_root_context(self): 31 value = self 32 if value.parent_context is None: 33 return value.as_context() 34 35 while True: 36 if value.parent_context is None: 37 return value 38 value = value.parent_context 39 40 def execute(self, arguments): 41 return self.inference_state.execute(self, arguments=arguments) 42 43 def execute_with_values(self, *value_list): 44 from jedi.inference.arguments import ValuesArguments 45 arguments = ValuesArguments([ValueSet([value]) for value in value_list]) 46 return self.inference_state.execute(self, arguments) 47 48 def execute_annotation(self): 49 return self.execute_with_values() 50 51 def gather_annotation_classes(self): 52 return ValueSet([self]) 53 54 def merge_types_of_iterate(self, contextualized_node=None, is_async=False): 55 return ValueSet.from_sets( 56 lazy_value.infer() 57 for lazy_value in self.iterate(contextualized_node, is_async) 58 ) 59 60 def _get_value_filters(self, name_or_str): 61 origin_scope = name_or_str if isinstance(name_or_str, Name) else None 62 yield from self.get_filters(origin_scope=origin_scope) 63 # This covers the case where a stub files are incomplete. 64 if self.is_stub(): 65 from jedi.inference.gradual.conversion import convert_values 66 for c in convert_values(ValueSet({self})): 67 yield from c.get_filters() 68 69 def goto(self, name_or_str, name_context=None, analysis_errors=True): 70 from jedi.inference import finder 71 filters = self._get_value_filters(name_or_str) 72 names = finder.filter_name(filters, name_or_str) 73 debug.dbg('context.goto %s in (%s): %s', name_or_str, self, names) 74 return names 75 76 def py__getattribute__(self, name_or_str, name_context=None, position=None, 77 analysis_errors=True): 78 """ 79 :param position: Position of the last statement -> tuple of line, column 80 """ 81 if name_context is None: 82 name_context = self 83 names = self.goto(name_or_str, name_context, analysis_errors) 84 values = ValueSet.from_sets(name.infer() for name in names) 85 if not values: 86 n = name_or_str.value if isinstance(name_or_str, Name) else name_or_str 87 values = self.py__getattribute__alternatives(n) 88 89 if not names and not values and analysis_errors: 90 if isinstance(name_or_str, Name): 91 from jedi.inference import analysis 92 analysis.add_attribute_error( 93 name_context, self, name_or_str) 94 debug.dbg('context.names_to_types: %s -> %s', names, values) 95 return values 96 97 def py__await__(self): 98 await_value_set = self.py__getattribute__("__await__") 99 if not await_value_set: 100 debug.warning('Tried to run __await__ on value %s', self) 101 return await_value_set.execute_with_values() 102 103 def py__name__(self): 104 return self.name.string_name 105 106 def iterate(self, contextualized_node=None, is_async=False): 107 debug.dbg('iterate %s', self) 108 if is_async: 109 from jedi.inference.lazy_value import LazyKnownValues 110 # TODO if no __aiter__ values are there, error should be: 111 # TypeError: 'async for' requires an object with __aiter__ method, got int 112 return iter([ 113 LazyKnownValues( 114 self.py__getattribute__('__aiter__').execute_with_values() 115 .py__getattribute__('__anext__').execute_with_values() 116 .py__getattribute__('__await__').execute_with_values() 117 .py__stop_iteration_returns() 118 ) # noqa: E124 119 ]) 120 return self.py__iter__(contextualized_node) 121 122 def is_sub_class_of(self, class_value): 123 with debug.increase_indent_cm('subclass matching of %s <=> %s' % (self, class_value), 124 color='BLUE'): 125 for cls in self.py__mro__(): 126 if cls.is_same_class(class_value): 127 debug.dbg('matched subclass True', color='BLUE') 128 return True 129 debug.dbg('matched subclass False', color='BLUE') 130 return False 131 132 def is_same_class(self, class2): 133 # Class matching should prefer comparisons that are not this function. 134 if type(class2).is_same_class != HelperValueMixin.is_same_class: 135 return class2.is_same_class(self) 136 return self == class2 137 138 @memoize_method 139 def as_context(self, *args, **kwargs): 140 return self._as_context(*args, **kwargs) 141 142 143 class Value(HelperValueMixin): 144 """ 145 To be implemented by subclasses. 146 """ 147 tree_node = None 148 # Possible values: None, tuple, list, dict and set. Here to deal with these 149 # very important containers. 150 array_type = None 151 api_type = 'not_defined_please_report_bug' 152 153 def __init__(self, inference_state, parent_context=None): 154 self.inference_state = inference_state 155 self.parent_context = parent_context 156 157 def py__getitem__(self, index_value_set, contextualized_node): 158 from jedi.inference import analysis 159 # TODO this value is probably not right. 160 analysis.add( 161 contextualized_node.context, 162 'type-error-not-subscriptable', 163 contextualized_node.node, 164 message="TypeError: '%s' object is not subscriptable" % self 165 ) 166 return NO_VALUES 167 168 def py__simple_getitem__(self, index): 169 raise SimpleGetItemNotFound 170 171 def py__iter__(self, contextualized_node=None): 172 if contextualized_node is not None: 173 from jedi.inference import analysis 174 analysis.add( 175 contextualized_node.context, 176 'type-error-not-iterable', 177 contextualized_node.node, 178 message="TypeError: '%s' object is not iterable" % self) 179 return iter([]) 180 181 def py__next__(self, contextualized_node=None): 182 return self.py__iter__(contextualized_node) 183 184 def get_signatures(self): 185 return [] 186 187 def is_class(self): 188 return False 189 190 def is_class_mixin(self): 191 return False 192 193 def is_instance(self): 194 return False 195 196 def is_function(self): 197 return False 198 199 def is_module(self): 200 return False 201 202 def is_namespace(self): 203 return False 204 205 def is_compiled(self): 206 return False 207 208 def is_bound_method(self): 209 return False 210 211 def is_builtins_module(self): 212 return False 213 214 def py__bool__(self): 215 """ 216 Since Wrapper is a super class for classes, functions and modules, 217 the return value will always be true. 218 """ 219 return True 220 221 def py__doc__(self): 222 try: 223 self.tree_node.get_doc_node 224 except AttributeError: 225 return '' 226 else: 227 return clean_scope_docstring(self.tree_node) 228 229 def get_safe_value(self, default=sentinel): 230 if default is sentinel: 231 raise ValueError("There exists no safe value for value %s" % self) 232 return default 233 234 def execute_operation(self, other, operator): 235 debug.warning("%s not possible between %s and %s", operator, self, other) 236 return NO_VALUES 237 238 def py__call__(self, arguments): 239 debug.warning("no execution possible %s", self) 240 return NO_VALUES 241 242 def py__stop_iteration_returns(self): 243 debug.warning("Not possible to return the stop iterations of %s", self) 244 return NO_VALUES 245 246 def py__getattribute__alternatives(self, name_or_str): 247 """ 248 For now a way to add values in cases like __getattr__. 249 """ 250 return NO_VALUES 251 252 def py__get__(self, instance, class_value): 253 debug.warning("No __get__ defined on %s", self) 254 return ValueSet([self]) 255 256 def py__get__on_class(self, calling_instance, instance, class_value): 257 return NotImplemented 258 259 def get_qualified_names(self): 260 # Returns Optional[Tuple[str, ...]] 261 return None 262 263 def is_stub(self): 264 # The root value knows if it's a stub or not. 265 return self.parent_context.is_stub() 266 267 def _as_context(self): 268 raise HasNoContext 269 270 @property 271 def name(self): 272 raise NotImplementedError 273 274 def get_type_hint(self, add_class_info=True): 275 return None 276 277 def infer_type_vars(self, value_set): 278 """ 279 When the current instance represents a type annotation, this method 280 tries to find information about undefined type vars and returns a dict 281 from type var name to value set. 282 283 This is for example important to understand what `iter([1])` returns. 284 According to typeshed, `iter` returns an `Iterator[_T]`: 285 286 def iter(iterable: Iterable[_T]) -> Iterator[_T]: ... 287 288 This functions would generate `int` for `_T` in this case, because it 289 unpacks the `Iterable`. 290 291 Parameters 292 ---------- 293 294 `self`: represents the annotation of the current parameter to infer the 295 value for. In the above example, this would initially be the 296 `Iterable[_T]` of the `iterable` parameter and then, when recursing, 297 just the `_T` generic parameter. 298 299 `value_set`: represents the actual argument passed to the parameter 300 we're inferred for, or (for recursive calls) their types. In the 301 above example this would first be the representation of the list 302 `[1]` and then, when recursing, just of `1`. 303 """ 304 return {} 305 306 307 def iterate_values(values, contextualized_node=None, is_async=False): 308 """ 309 Calls `iterate`, on all values but ignores the ordering and just returns 310 all values that the iterate functions yield. 311 """ 312 return ValueSet.from_sets( 313 lazy_value.infer() 314 for lazy_value in values.iterate(contextualized_node, is_async=is_async) 315 ) 316 317 318 class _ValueWrapperBase(HelperValueMixin): 319 @safe_property 320 def name(self): 321 from jedi.inference.names import ValueName 322 wrapped_name = self._wrapped_value.name 323 if wrapped_name.tree_name is not None: 324 return ValueName(self, wrapped_name.tree_name) 325 else: 326 from jedi.inference.compiled import CompiledValueName 327 return CompiledValueName(self, wrapped_name.string_name) 328 329 @classmethod 330 @inference_state_as_method_param_cache() 331 def create_cached(cls, inference_state, *args, **kwargs): 332 return cls(*args, **kwargs) 333 334 def __getattr__(self, name): 335 assert name != '_wrapped_value', 'Problem with _get_wrapped_value' 336 return getattr(self._wrapped_value, name) 337 338 339 class LazyValueWrapper(_ValueWrapperBase): 340 @safe_property 341 @memoize_method 342 def _wrapped_value(self): 343 with debug.increase_indent_cm('Resolve lazy value wrapper'): 344 return self._get_wrapped_value() 345 346 def __repr__(self): 347 return '<%s>' % (self.__class__.__name__) 348 349 def _get_wrapped_value(self): 350 raise NotImplementedError 351 352 353 class ValueWrapper(_ValueWrapperBase): 354 def __init__(self, wrapped_value): 355 self._wrapped_value = wrapped_value 356 357 def __repr__(self): 358 return '%s(%s)' % (self.__class__.__name__, self._wrapped_value) 359 360 361 class TreeValue(Value): 362 def __init__(self, inference_state, parent_context, tree_node): 363 super().__init__(inference_state, parent_context) 364 self.tree_node = tree_node 365 366 def __repr__(self): 367 return '<%s: %s>' % (self.__class__.__name__, self.tree_node) 368 369 370 class ContextualizedNode: 371 def __init__(self, context, node): 372 self.context = context 373 self.node = node 374 375 def get_root_context(self): 376 return self.context.get_root_context() 377 378 def infer(self): 379 return self.context.infer_node(self.node) 380 381 def __repr__(self): 382 return '<%s: %s in %s>' % (self.__class__.__name__, self.node, self.context) 383 384 385 def _getitem(value, index_values, contextualized_node): 386 # The actual getitem call. 387 result = NO_VALUES 388 unused_values = set() 389 for index_value in index_values: 390 index = index_value.get_safe_value(default=None) 391 if type(index) in (float, int, str, slice, bytes): 392 try: 393 result |= value.py__simple_getitem__(index) 394 continue 395 except SimpleGetItemNotFound: 396 pass 397 398 unused_values.add(index_value) 399 400 # The index was somehow not good enough or simply a wrong type. 401 # Therefore we now iterate through all the values and just take 402 # all results. 403 if unused_values or not index_values: 404 result |= value.py__getitem__( 405 ValueSet(unused_values), 406 contextualized_node 407 ) 408 debug.dbg('py__getitem__ result: %s', result) 409 return result 410 411 412 class ValueSet: 413 def __init__(self, iterable): 414 self._set = frozenset(iterable) 415 for value in iterable: 416 assert not isinstance(value, ValueSet) 417 418 @classmethod 419 def _from_frozen_set(cls, frozenset_): 420 self = cls.__new__(cls) 421 self._set = frozenset_ 422 return self 423 424 @classmethod 425 def from_sets(cls, sets): 426 """ 427 Used to work with an iterable of set. 428 """ 429 aggregated = set() 430 for set_ in sets: 431 if isinstance(set_, ValueSet): 432 aggregated |= set_._set 433 else: 434 aggregated |= frozenset(set_) 435 return cls._from_frozen_set(frozenset(aggregated)) 436 437 def __or__(self, other): 438 return self._from_frozen_set(self._set | other._set) 439 440 def __and__(self, other): 441 return self._from_frozen_set(self._set & other._set) 442 443 def __iter__(self): 444 return iter(self._set) 445 446 def __bool__(self): 447 return bool(self._set) 448 449 def __len__(self): 450 return len(self._set) 451 452 def __repr__(self): 453 return 'S{%s}' % (', '.join(str(s) for s in self._set)) 454 455 def filter(self, filter_func): 456 return self.__class__(filter(filter_func, self._set)) 457 458 def __getattr__(self, name): 459 def mapper(*args, **kwargs): 460 return self.from_sets( 461 getattr(value, name)(*args, **kwargs) 462 for value in self._set 463 ) 464 return mapper 465 466 def __eq__(self, other): 467 return self._set == other._set 468 469 def __ne__(self, other): 470 return not self.__eq__(other) 471 472 def __hash__(self): 473 return hash(self._set) 474 475 def py__class__(self): 476 return ValueSet(c.py__class__() for c in self._set) 477 478 def iterate(self, contextualized_node=None, is_async=False): 479 from jedi.inference.lazy_value import get_merged_lazy_value 480 type_iters = [c.iterate(contextualized_node, is_async=is_async) for c in self._set] 481 for lazy_values in zip_longest(*type_iters): 482 yield get_merged_lazy_value( 483 [l for l in lazy_values if l is not None] 484 ) 485 486 def execute(self, arguments): 487 return ValueSet.from_sets(c.inference_state.execute(c, arguments) for c in self._set) 488 489 def execute_with_values(self, *args, **kwargs): 490 return ValueSet.from_sets(c.execute_with_values(*args, **kwargs) for c in self._set) 491 492 def goto(self, *args, **kwargs): 493 return reduce(add, [c.goto(*args, **kwargs) for c in self._set], []) 494 495 def py__getattribute__(self, *args, **kwargs): 496 return ValueSet.from_sets(c.py__getattribute__(*args, **kwargs) for c in self._set) 497 498 def get_item(self, *args, **kwargs): 499 return ValueSet.from_sets(_getitem(c, *args, **kwargs) for c in self._set) 500 501 def try_merge(self, function_name): 502 value_set = self.__class__([]) 503 for c in self._set: 504 try: 505 method = getattr(c, function_name) 506 except AttributeError: 507 pass 508 else: 509 value_set |= method() 510 return value_set 511 512 def gather_annotation_classes(self): 513 return ValueSet.from_sets([c.gather_annotation_classes() for c in self._set]) 514 515 def get_signatures(self): 516 return [sig for c in self._set for sig in c.get_signatures()] 517 518 def get_type_hint(self, add_class_info=True): 519 t = [v.get_type_hint(add_class_info=add_class_info) for v in self._set] 520 type_hints = sorted(filter(None, t)) 521 if len(type_hints) == 1: 522 return type_hints[0] 523 524 optional = 'None' in type_hints 525 if optional: 526 type_hints.remove('None') 527 528 if len(type_hints) == 0: 529 return None 530 elif len(type_hints) == 1: 531 s = type_hints[0] 532 else: 533 s = 'Union[%s]' % ', '.join(type_hints) 534 if optional: 535 s = 'Optional[%s]' % s 536 return s 537 538 def infer_type_vars(self, value_set): 539 # Circular 540 from jedi.inference.gradual.annotation import merge_type_var_dicts 541 542 type_var_dict = {} 543 for value in self._set: 544 merge_type_var_dicts( 545 type_var_dict, 546 value.infer_type_vars(value_set), 547 ) 548 return type_var_dict 549 550 551 NO_VALUES = ValueSet([]) 552 553 554 def iterator_to_value_set(func): 555 def wrapper(*args, **kwargs): 556 return ValueSet(func(*args, **kwargs)) 557 558 return wrapper 559