Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jedi-0.20.0-py3.11.egg/jedi/inference/syntax_tree.py: 11%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

589 statements  

1""" 

2Functions inferring the syntax tree. 

3""" 

4import copy 

5import itertools 

6 

7from parso.python import tree 

8 

9from jedi import debug 

10from jedi import parser_utils 

11from jedi.inference.base_value import ValueSet, NO_VALUES, ContextualizedNode, \ 

12 iterator_to_value_set, iterate_values 

13from jedi.inference.lazy_value import LazyTreeValue 

14from jedi.inference import compiled 

15from jedi.inference import recursion 

16from jedi.inference import analysis 

17from jedi.inference import imports 

18from jedi.inference import arguments 

19from jedi.inference.value import ClassValue, FunctionValue 

20from jedi.inference.value import iterable 

21from jedi.inference.value.dynamic_arrays import ListModification, DictModification 

22from jedi.inference.value import TreeInstance 

23from jedi.inference.helpers import is_string, is_literal, is_number, \ 

24 get_names_of_node, is_big_annoying_library 

25from jedi.inference.compiled.access import COMPARISON_OPERATORS 

26from jedi.inference.cache import inference_state_method_cache 

27from jedi.inference.gradual.stub_value import VersionInfo 

28from jedi.inference.gradual import annotation 

29from jedi.inference.names import TreeNameDefinition 

30from jedi.inference.context import CompForContext 

31from jedi.inference.value.decorator import Decoratee 

32from jedi.plugins import plugin_manager 

33from jedi.inference.gradual.typing import ProxyTypingValue, IGNORE_ANNOTATION_PARTS 

34from jedi.inference.gradual.type_var import TypeVar 

35 

36operator_to_magic_method = { 

37 '+': '__add__', 

38 '-': '__sub__', 

39 '*': '__mul__', 

40 '@': '__matmul__', 

41 '/': '__truediv__', 

42 '//': '__floordiv__', 

43 '%': '__mod__', 

44 '**': '__pow__', 

45 '<<': '__lshift__', 

46 '>>': '__rshift__', 

47 '&': '__and__', 

48 '|': '__or__', 

49 '^': '__xor__', 

50} 

51 

52reverse_operator_to_magic_method = { 

53 k: '__r' + v[2:] for k, v in operator_to_magic_method.items() 

54} 

55 

56 

57def _limit_value_infers(func): 

58 """ 

59 This is for now the way how we limit type inference going wild. There are 

60 other ways to ensure recursion limits as well. This is mostly necessary 

61 because of instance (self) access that can be quite tricky to limit. 

62 

63 I'm still not sure this is the way to go, but it looks okay for now and we 

64 can still go anther way in the future. Tests are there. ~ dave 

65 """ 

66 def wrapper(context, *args, **kwargs): 

67 n = context.tree_node 

68 inference_state = context.inference_state 

69 try: 

70 inference_state.inferred_element_counts[n] += 1 

71 maximum = 300 

72 if context.parent_context is None \ 

73 and context.get_value() is inference_state.builtins_module: 

74 # Builtins should have a more generous inference limit. 

75 # It is important that builtins can be executed, otherwise some 

76 # functions that depend on certain builtins features would be 

77 # broken, see e.g. GH #1432 

78 maximum *= 100 

79 

80 if inference_state.inferred_element_counts[n] > maximum: 

81 debug.warning('In value %s there were too many inferences.', n) 

82 return NO_VALUES 

83 except KeyError: 

84 inference_state.inferred_element_counts[n] = 1 

85 return func(context, *args, **kwargs) 

86 

87 return wrapper 

88 

89 

90def infer_node(context, element): 

91 if isinstance(context, CompForContext): 

92 return _infer_node(context, element) 

93 

94 name_dicts = [{}] 

95 if_stmt = element 

96 while if_stmt is not None: 

97 if_stmt = if_stmt.parent 

98 if if_stmt.type in ('if_stmt', 'for_stmt'): 

99 break 

100 if parser_utils.is_scope(if_stmt): 

101 if_stmt = None 

102 break 

103 predefined_if_name_dict = context.predefined_names.get(if_stmt) 

104 # TODO there's a lot of issues with this one. We actually should do 

105 # this in a different way. Caching should only be active in certain 

106 # cases and this all sucks. 

107 if predefined_if_name_dict is None and if_stmt \ 

108 and if_stmt.type == 'if_stmt' and context.inference_state.is_analysis: 

109 if_stmt_test = if_stmt.children[1] 

110 # If we already did a check, we don't want to do it again -> If 

111 # value.predefined_names is filled, we stop. 

112 # We don't want to check the if stmt itself, it's just about 

113 # the content. 

114 if element.start_pos > if_stmt_test.end_pos: 

115 # Now we need to check if the names in the if_stmt match the 

116 # names in the suite. 

117 if_names = get_names_of_node(if_stmt_test) 

118 element_names = get_names_of_node(element) 

119 str_element_names = [e.value for e in element_names] 

120 if any(i.value in str_element_names for i in if_names): 

121 for if_name in if_names: 

122 definitions = context.inference_state.infer(context, if_name) 

123 # Every name that has multiple different definitions 

124 # causes the complexity to rise. The complexity should 

125 # never fall below 1. 

126 if len(definitions) > 1: 

127 if len(name_dicts) * len(definitions) > 16: 

128 debug.dbg('Too many options for if branch inference %s.', if_stmt) 

129 # There's only a certain amount of branches 

130 # Jedi can infer, otherwise it will take to 

131 # long. 

132 name_dicts = [{}] 

133 break 

134 

135 original_name_dicts = list(name_dicts) 

136 name_dicts = [] 

137 for definition in definitions: 

138 new_name_dicts = list(original_name_dicts) 

139 for i, name_dict in enumerate(new_name_dicts): 

140 new_name_dicts[i] = name_dict.copy() 

141 new_name_dicts[i][if_name.value] = ValueSet([definition]) 

142 

143 name_dicts += new_name_dicts 

144 else: 

145 for name_dict in name_dicts: 

146 name_dict[if_name.value] = definitions 

147 if len(name_dicts) > 1: 

148 result = NO_VALUES 

149 for name_dict in name_dicts: 

150 with context.predefine_names(if_stmt, name_dict): 

151 result |= _infer_node(context, element) 

152 return result 

153 else: 

154 return _infer_node_if_inferred(context, element) 

155 else: 

156 if predefined_if_name_dict: 

157 return _infer_node(context, element) 

158 else: 

159 return _infer_node_if_inferred(context, element) 

160 

161 

162def _infer_node_if_inferred(context, element): 

163 """ 

164 TODO This function is temporary: Merge with infer_node. 

165 """ 

166 parent = element 

167 while parent is not None: 

168 parent = parent.parent 

169 predefined_if_name_dict = context.predefined_names.get(parent) 

170 if predefined_if_name_dict is not None: 

171 return _infer_node(context, element) 

172 return _infer_node_cached(context, element) 

173 

174 

175@inference_state_method_cache(default=NO_VALUES) 

176def _infer_node_cached(context, element): 

177 return _infer_node(context, element) 

178 

179 

180@debug.increase_indent 

181@_limit_value_infers 

182def _infer_node(context, element): 

183 debug.dbg('infer_node %s@%s in %s', element, element.start_pos, context) 

184 inference_state = context.inference_state 

185 typ = element.type 

186 if typ in ('name', 'number', 'string', 'atom', 'strings', 'keyword', 'fstring'): 

187 return infer_atom(context, element) 

188 elif typ == 'lambdef': 

189 return ValueSet([FunctionValue.from_context(context, element)]) 

190 elif typ == 'expr_stmt': 

191 return infer_expr_stmt(context, element) 

192 elif typ in ('power', 'atom_expr'): 

193 first_child = element.children[0] 

194 children = element.children[1:] 

195 had_await = False 

196 if first_child.type == 'keyword' and first_child.value == 'await': 

197 had_await = True 

198 first_child = children.pop(0) 

199 

200 value_set = context.infer_node(first_child) 

201 for (i, trailer) in enumerate(children): 

202 if trailer == '**': # has a power operation. 

203 right = context.infer_node(children[i + 1]) 

204 value_set = _infer_comparison( 

205 context, 

206 value_set, 

207 trailer, 

208 right 

209 ) 

210 break 

211 value_set = infer_trailer(context, value_set, trailer) 

212 

213 if had_await: 

214 return value_set.py__await__().py__stop_iteration_returns() 

215 return value_set 

216 elif typ in ('testlist_star_expr', 'testlist',): 

217 # The implicit tuple in statements. 

218 return ValueSet([iterable.SequenceLiteralValue(inference_state, context, element)]) 

219 elif typ in ('not_test', 'factor'): 

220 value_set = context.infer_node(element.children[-1]) 

221 for operator in element.children[:-1]: 

222 value_set = infer_factor(value_set, operator) 

223 return value_set 

224 elif typ == 'test': 

225 # `x if foo else y` case. 

226 return (context.infer_node(element.children[0]) 

227 | context.infer_node(element.children[-1])) 

228 elif typ == 'operator': 

229 # Must be an ellipsis, other operators are not inferred. 

230 if element.value != '...': 

231 origin = element.parent 

232 raise AssertionError("unhandled operator %s in %s " % (repr(element.value), origin)) 

233 return ValueSet([compiled.builtin_from_name(inference_state, 'Ellipsis')]) 

234 elif typ == 'dotted_name': 

235 value_set = infer_atom(context, element.children[0]) 

236 for next_name in element.children[2::2]: 

237 value_set = value_set.py__getattribute__(next_name, name_context=context) 

238 return value_set 

239 elif typ == 'eval_input': 

240 return context.infer_node(element.children[0]) 

241 elif typ == 'annassign': 

242 return annotation.infer_annotation(context, element.children[1]) \ 

243 .execute_annotation(context) 

244 elif typ == 'yield_expr': 

245 if len(element.children) and element.children[1].type == 'yield_arg': 

246 # Implies that it's a yield from. 

247 element = element.children[1].children[1] 

248 generators = context.infer_node(element) \ 

249 .py__getattribute__('__iter__').execute_with_values() 

250 return generators.py__stop_iteration_returns() 

251 

252 # Generator.send() is not implemented. 

253 return NO_VALUES 

254 elif typ == 'namedexpr_test': 

255 return context.infer_node(element.children[2]) 

256 elif typ == 'star_expr': 

257 return NO_VALUES 

258 else: 

259 return infer_or_test(context, element) 

260 

261 

262def infer_trailer(context, atom_values, trailer): 

263 trailer_op, node = trailer.children[:2] 

264 if node == ')': # `arglist` is optional. 

265 node = None 

266 

267 if trailer_op == '[': 

268 trailer_op, node, _ = trailer.children 

269 return atom_values.get_item( 

270 _infer_subscript_list(context, node), 

271 ContextualizedNode(context, trailer) 

272 ) 

273 else: 

274 debug.dbg('infer_trailer: %s in %s', trailer, atom_values) 

275 if trailer_op == '.': 

276 return atom_values.py__getattribute__( 

277 name_context=context, 

278 name_or_str=node 

279 ) 

280 else: 

281 assert trailer_op == '(', 'trailer_op is actually %s' % trailer_op 

282 args = arguments.TreeArguments(context.inference_state, context, node, trailer) 

283 return atom_values.execute(args) 

284 

285 

286def infer_atom(context, atom): 

287 """ 

288 Basically to process ``atom`` nodes. The parser sometimes doesn't 

289 generate the node (because it has just one child). In that case an atom 

290 might be a name or a literal as well. 

291 """ 

292 state = context.inference_state 

293 if atom.type == 'name': 

294 # This is the first global lookup. 

295 stmt = atom.search_ancestor('expr_stmt', 'lambdef', 'if_stmt') or atom 

296 if stmt.type == 'if_stmt': 

297 if not any(n.start_pos <= atom.start_pos < n.end_pos for n in stmt.get_test_nodes()): 

298 stmt = atom 

299 elif stmt.type == 'lambdef': 

300 stmt = atom 

301 position = stmt.start_pos 

302 if _is_annotation_name(atom): 

303 # Since Python 3.7 (with from __future__ import annotations), 

304 # annotations are essentially strings and can reference objects 

305 # that are defined further down in code. Therefore just set the 

306 # position to None, so the finder will not try to stop at a certain 

307 # position in the module. 

308 position = None 

309 return context.py__getattribute__(atom, position=position) 

310 elif atom.type == 'keyword': 

311 # For False/True/None 

312 if atom.value in ('False', 'True', 'None'): 

313 return ValueSet([compiled.builtin_from_name(state, atom.value)]) 

314 elif atom.value == 'yield': 

315 # Contrary to yield from, yield can just appear alone to return a 

316 # value when used with `.send()`. 

317 return NO_VALUES 

318 assert False, 'Cannot infer the keyword %s' % atom 

319 

320 elif isinstance(atom, tree.Literal): 

321 string = state.compiled_subprocess.safe_literal_eval(atom.value) 

322 return ValueSet([compiled.create_simple_object(state, string)]) 

323 elif atom.type == 'strings': 

324 # Will be multiple string. 

325 value_set = infer_atom(context, atom.children[0]) 

326 for string in atom.children[1:]: 

327 right = infer_atom(context, string) 

328 value_set = _infer_comparison(context, value_set, '+', right) 

329 return value_set 

330 elif atom.type == 'fstring': 

331 return compiled.get_string_value_set(state) 

332 else: 

333 c = atom.children 

334 # Parentheses without commas are not tuples. 

335 if c[0] == '(' and not len(c) == 2 \ 

336 and not (c[1].type == 'testlist_comp' 

337 and len(c[1].children) > 1): 

338 return context.infer_node(c[1]) 

339 

340 try: 

341 comp_for = c[1].children[1] 

342 except (IndexError, AttributeError): 

343 pass 

344 else: 

345 if comp_for == ':': 

346 # Dict comprehensions have a colon at the 3rd index. 

347 try: 

348 comp_for = c[1].children[3] 

349 except IndexError: 

350 pass 

351 

352 if comp_for.type in ('comp_for', 'sync_comp_for'): 

353 return ValueSet([iterable.comprehension_from_atom( 

354 state, context, atom 

355 )]) 

356 

357 # It's a dict/list/tuple literal. 

358 array_node = c[1] 

359 try: 

360 array_node_c = array_node.children 

361 except AttributeError: 

362 array_node_c = [] 

363 if c[0] == '{' and (array_node == '}' or ':' in array_node_c 

364 or '**' in array_node_c): 

365 new_value = iterable.DictLiteralValue(state, context, atom) 

366 else: 

367 new_value = iterable.SequenceLiteralValue(state, context, atom) 

368 return ValueSet([new_value]) 

369 

370 

371@_limit_value_infers 

372def infer_expr_stmt(context, stmt, seek_name=None): 

373 with recursion.execution_allowed(context.inference_state, stmt) as allowed: 

374 if allowed: 

375 if seek_name is not None: 

376 pep0484_values = \ 

377 annotation.find_type_from_comment_hint_assign(context, stmt, seek_name) 

378 if pep0484_values: 

379 return pep0484_values 

380 

381 return _infer_expr_stmt(context, stmt, seek_name) 

382 return NO_VALUES 

383 

384 

385@debug.increase_indent 

386def _infer_expr_stmt(context, stmt, seek_name=None): 

387 """ 

388 The starting point of the completion. A statement always owns a call 

389 list, which are the calls, that a statement does. In case multiple 

390 names are defined in the statement, `seek_name` returns the result for 

391 this name. 

392 

393 expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | 

394 ('=' (yield_expr|testlist_star_expr))*) 

395 annassign: ':' test ['=' test] 

396 augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | 

397 '<<=' | '>>=' | '**=' | '//=') 

398 

399 :param stmt: A `tree.ExprStmt`. 

400 """ 

401 def check_setitem(stmt): 

402 atom_expr = stmt.children[0] 

403 if atom_expr.type not in ('atom_expr', 'power'): 

404 return False, None 

405 name = atom_expr.children[0] 

406 if name.type != 'name' or len(atom_expr.children) != 2: 

407 return False, None 

408 trailer = atom_expr.children[-1] 

409 return trailer.children[0] == '[', trailer.children[1] 

410 

411 debug.dbg('infer_expr_stmt %s (%s)', stmt, seek_name) 

412 rhs = stmt.get_rhs() 

413 

414 value_set = context.infer_node(rhs) 

415 

416 if seek_name: 

417 n = TreeNameDefinition(context, seek_name) 

418 value_set = check_tuple_assignments(n, value_set) 

419 

420 first_operator = next(stmt.yield_operators(), None) 

421 is_setitem, subscriptlist = check_setitem(stmt) 

422 is_annassign = first_operator not in ('=', None) and first_operator.type == 'operator' 

423 if is_annassign or is_setitem: 

424 # `=` is always the last character in aug assignments -> -1 

425 name = stmt.get_defined_names(include_setitem=True)[0].value 

426 left_values = context.py__getattribute__(name, position=stmt.start_pos) 

427 

428 if is_setitem: 

429 def to_mod(v): 

430 c = ContextualizedSubscriptListNode(context, subscriptlist) 

431 if v.array_type == 'dict': 

432 return DictModification(v, value_set, c) 

433 elif v.array_type == 'list': 

434 return ListModification(v, value_set, c) 

435 return v 

436 

437 value_set = ValueSet(to_mod(v) for v in left_values) 

438 else: 

439 operator = copy.copy(first_operator) 

440 operator.value = operator.value[:-1] 

441 for_stmt = stmt.search_ancestor('for_stmt') 

442 if for_stmt is not None and for_stmt.type == 'for_stmt' and value_set \ 

443 and parser_utils.for_stmt_defines_one_name(for_stmt): 

444 # Iterate through result and add the values, that's possible 

445 # only in for loops without clutter, because they are 

446 # predictable. Also only do it, if the variable is not a tuple. 

447 node = for_stmt.get_testlist() 

448 cn = ContextualizedNode(context, node) 

449 ordered = list(cn.infer().iterate(cn)) 

450 

451 for lazy_value in ordered: 

452 dct = {for_stmt.children[1].value: lazy_value.infer()} 

453 with context.predefine_names(for_stmt, dct): 

454 t = context.infer_node(rhs) 

455 left_values = _infer_comparison(context, left_values, operator, t) 

456 value_set = left_values 

457 else: 

458 value_set = _infer_comparison(context, left_values, operator, value_set) 

459 debug.dbg('infer_expr_stmt result %s', value_set) 

460 return value_set 

461 

462 

463def infer_or_test(context, or_test): 

464 iterator = iter(or_test.children) 

465 types = context.infer_node(next(iterator)) 

466 for operator in iterator: 

467 right = next(iterator) 

468 if operator.type == 'comp_op': # not in / is not 

469 operator = ' '.join(c.value for c in operator.children) 

470 

471 # handle type inference of and/or here. 

472 if operator in ('and', 'or'): 

473 left_bools = set(left.py__bool__() for left in types) 

474 if left_bools == {True}: 

475 if operator == 'and': 

476 types = context.infer_node(right) 

477 elif left_bools == {False}: 

478 if operator != 'and': 

479 types = context.infer_node(right) 

480 # Otherwise continue, because of uncertainty. 

481 else: 

482 types = _infer_comparison(context, types, operator, 

483 context.infer_node(right)) 

484 debug.dbg('infer_or_test types %s', types) 

485 return types 

486 

487 

488@iterator_to_value_set 

489def infer_factor(value_set, operator): 

490 """ 

491 Calculates `+`, `-`, `~` and `not` prefixes. 

492 """ 

493 for value in value_set: 

494 if operator == '-': 

495 if is_number(value): 

496 yield value.negate() 

497 elif operator == 'not': 

498 b = value.py__bool__() 

499 if b is None: # Uncertainty. 

500 yield list(value.inference_state.builtins_module.py__getattribute__('bool') 

501 .execute_annotation(None)).pop() 

502 else: 

503 yield compiled.create_simple_object(value.inference_state, not b) 

504 else: 

505 yield value 

506 

507 

508def _literals_to_types(inference_state, result): 

509 # Changes literals ('a', 1, 1.0, etc) to its type instances (str(), 

510 # int(), float(), etc). 

511 new_result = NO_VALUES 

512 for typ in result: 

513 if is_literal(typ): 

514 # Literals are only valid as long as the operations are 

515 # correct. Otherwise add a value-free instance. 

516 cls = compiled.builtin_from_name(inference_state, typ.name.string_name) 

517 new_result |= cls.execute_with_values() 

518 else: 

519 new_result |= ValueSet([typ]) 

520 return new_result 

521 

522 

523def _infer_comparison(context, left_values, operator, right_values): 

524 state = context.inference_state 

525 if isinstance(operator, str): 

526 operator_str = operator 

527 else: 

528 operator_str = str(operator.value) 

529 if not left_values or not right_values: 

530 # illegal slices e.g. cause left/right_result to be None 

531 result = (left_values or NO_VALUES) | (right_values or NO_VALUES) 

532 return _literals_to_types(state, result) 

533 elif operator_str == "|" and all( 

534 value.is_class() or value.is_compiled() or isinstance(value, TypeVar) 

535 for value in itertools.chain(left_values, right_values) 

536 ): 

537 # ^^^ A naive hack for PEP 604 

538 return ValueSet.from_sets((left_values, right_values)) 

539 else: 

540 # I don't think there's a reasonable chance that a string 

541 # operation is still correct, once we pass something like six 

542 # objects. 

543 if len(left_values) * len(right_values) > 6: 

544 return _literals_to_types(state, left_values | right_values) 

545 else: 

546 return ValueSet.from_sets( 

547 _infer_comparison_part(state, context, left, operator, right) 

548 for left in left_values 

549 for right in right_values 

550 ) 

551 

552 

553def _is_annotation_name(name): 

554 ancestor = name.search_ancestor('param', 'funcdef', 'expr_stmt') 

555 if ancestor is None: 

556 return False 

557 

558 if ancestor.type in ('param', 'funcdef'): 

559 ann = ancestor.annotation 

560 if ann is not None: 

561 return ann.start_pos <= name.start_pos < ann.end_pos 

562 elif ancestor.type == 'expr_stmt': 

563 c = ancestor.children 

564 if len(c) > 1 and c[1].type == 'annassign': 

565 return c[1].start_pos <= name.start_pos < c[1].end_pos 

566 return False 

567 

568 

569def _is_list(value): 

570 return value.array_type == 'list' 

571 

572 

573def _is_tuple(value): 

574 return value.array_type == 'tuple' 

575 

576 

577def _bool_to_value(inference_state, bool_): 

578 return compiled.builtin_from_name(inference_state, str(bool_)) 

579 

580 

581def _get_tuple_ints(value): 

582 if not isinstance(value, iterable.SequenceLiteralValue): 

583 return None 

584 numbers = [] 

585 for lazy_value in value.py__iter__(): 

586 if not isinstance(lazy_value, LazyTreeValue): 

587 return None 

588 node = lazy_value.data 

589 if node.type != 'number': 

590 return None 

591 try: 

592 numbers.append(int(node.value)) 

593 except ValueError: 

594 return None 

595 return numbers 

596 

597 

598def _infer_comparison_part(inference_state, context, left, operator, right): 

599 l_is_num = is_number(left) 

600 r_is_num = is_number(right) 

601 if isinstance(operator, str): 

602 str_operator = operator 

603 else: 

604 str_operator = str(operator.value) 

605 

606 if str_operator == '*': 

607 # for iterables, ignore * operations 

608 if isinstance(left, iterable.Sequence) or is_string(left): 

609 return ValueSet([left]) 

610 elif isinstance(right, iterable.Sequence) or is_string(right): 

611 return ValueSet([right]) 

612 elif str_operator == '+': 

613 if l_is_num and r_is_num or is_string(left) and is_string(right): 

614 return left.execute_operation(right, str_operator) 

615 elif _is_list(left) and _is_list(right) or _is_tuple(left) and _is_tuple(right): 

616 return ValueSet([iterable.MergedArray(inference_state, (left, right))]) 

617 elif str_operator == '-': 

618 if l_is_num and r_is_num: 

619 return left.execute_operation(right, str_operator) 

620 elif str_operator == '%': 

621 # With strings and numbers the left type typically remains. Except for 

622 # `int() % float()`. 

623 return ValueSet([left]) 

624 elif str_operator in COMPARISON_OPERATORS: 

625 if left.is_compiled() and right.is_compiled(): 

626 # Possible, because the return is not an option. Just compare. 

627 result = left.execute_operation(right, str_operator) 

628 if result: 

629 return result 

630 else: 

631 if str_operator in ('is', '!=', '==', 'is not'): 

632 operation = COMPARISON_OPERATORS[str_operator] 

633 bool_ = operation(left, right) 

634 # Only if == returns True or != returns False, we can continue. 

635 # There's no guarantee that they are not equal. This can help 

636 # in some cases, but does not cover everything. 

637 if (str_operator in ('is', '==')) == bool_: 

638 return ValueSet([_bool_to_value(inference_state, bool_)]) 

639 

640 if isinstance(left, VersionInfo): 

641 version_info = _get_tuple_ints(right) 

642 if version_info is not None: 

643 bool_result = compiled.access.COMPARISON_OPERATORS[operator]( 

644 inference_state.environment.version_info, 

645 tuple(version_info) 

646 ) 

647 return ValueSet([_bool_to_value(inference_state, bool_result)]) 

648 

649 return ValueSet([ 

650 _bool_to_value(inference_state, True), 

651 _bool_to_value(inference_state, False) 

652 ]) 

653 elif str_operator in ('in', 'not in'): 

654 return inference_state.builtins_module.py__getattribute__('bool').execute_annotation( 

655 context 

656 ) 

657 

658 def check(obj): 

659 """Checks if a Jedi object is either a float or an int.""" 

660 return isinstance(obj, TreeInstance) and \ 

661 obj.name.string_name in ('int', 'float') 

662 

663 # Static analysis, one is a number, the other one is not. 

664 if str_operator in ('+', '-') and l_is_num != r_is_num \ 

665 and not (check(left) or check(right)): 

666 message = "TypeError: unsupported operand type(s) for +: %s and %s" 

667 analysis.add(context, 'type-error-operation', operator, 

668 message % (left, right)) 

669 

670 if left.is_class() or right.is_class(): 

671 return NO_VALUES 

672 

673 method_name = operator_to_magic_method[str_operator] 

674 magic_methods = left.py__getattribute__(method_name) 

675 if magic_methods: 

676 result = magic_methods.execute_with_values(right) 

677 if result: 

678 return result 

679 

680 if not magic_methods: 

681 reverse_method_name = reverse_operator_to_magic_method[str_operator] 

682 magic_methods = right.py__getattribute__(reverse_method_name) 

683 

684 result = magic_methods.execute_with_values(left) 

685 if result: 

686 return result 

687 

688 result = ValueSet([left, right]) 

689 debug.dbg('Used operator %s resulting in %s', operator, result) 

690 return result 

691 

692 

693@plugin_manager.decorate() 

694def tree_name_to_values(inference_state, context, tree_name): 

695 value_set = NO_VALUES 

696 module_node = context.get_root_context().tree_node 

697 # First check for annotations, like: `foo: int = 3` 

698 if module_node is not None: 

699 names = module_node.get_used_names().get(tree_name.value, []) 

700 found_annotation = False 

701 for name in names: 

702 expr_stmt = name.parent 

703 

704 if expr_stmt.type == "expr_stmt" and expr_stmt.children[1].type == "annassign": 

705 correct_scope = parser_utils.get_parent_scope(name) == context.tree_node 

706 ann_assign = expr_stmt.children[1] 

707 first = ann_assign.children[1] 

708 code = first.get_code() 

709 if correct_scope and not (code.endswith(".TypeAlias") 

710 or code.strip() == "TypeAlias"): 

711 if ( 

712 (first.type == 'name') 

713 and (ann_assign.children[1].value == tree_name.value) 

714 and context.parent_context 

715 ): 

716 context = context.parent_context 

717 found = annotation.infer_annotation( 

718 context, expr_stmt.children[1].children[1] 

719 ) 

720 set_found_annotation = True 

721 if len(found) == 1: 

722 first = next(iter(found)) 

723 set_found_annotation = not ( 

724 isinstance(first, ProxyTypingValue) 

725 and first.name.string_name in IGNORE_ANNOTATION_PARTS 

726 ) 

727 found_annotation = set_found_annotation 

728 value_set |= found.execute_annotation(context) 

729 if found_annotation: 

730 return value_set 

731 

732 types = [] 

733 node = tree_name.get_definition(import_name_always=True, include_setitem=True) 

734 if node is None: 

735 node = tree_name.parent 

736 if node.type == 'global_stmt': 

737 c = context.create_context(tree_name) 

738 if c.is_module(): 

739 # In case we are already part of the module, there is no point 

740 # in looking up the global statement anymore, because it's not 

741 # valid at that point anyway. 

742 return NO_VALUES 

743 # For global_stmt lookups, we only need the first possible scope, 

744 # which means the function itself. 

745 filter = next(c.get_filters()) 

746 names = filter.get(tree_name.value) 

747 return ValueSet.from_sets(name.infer() for name in names) 

748 elif node.type not in ('import_from', 'import_name'): 

749 c = context.create_context(tree_name) 

750 return infer_atom(c, tree_name) 

751 

752 typ = node.type 

753 if typ == 'for_stmt': 

754 types = annotation.find_type_from_comment_hint_for(context, node, tree_name) 

755 if types: 

756 return types 

757 if typ == 'with_stmt': 

758 types = annotation.find_type_from_comment_hint_with(context, node, tree_name) 

759 if types: 

760 return types 

761 

762 if typ in ('for_stmt', 'comp_for', 'sync_comp_for'): 

763 try: 

764 types = context.predefined_names[node][tree_name.value] 

765 except KeyError: 

766 cn = ContextualizedNode(context, node.children[3]) 

767 for_types = iterate_values( 

768 cn.infer(), 

769 contextualized_node=cn, 

770 is_async=node.parent.type == 'async_stmt', 

771 ) 

772 n = TreeNameDefinition(context, tree_name) 

773 types = check_tuple_assignments(n, for_types) 

774 elif typ == 'expr_stmt': 

775 types = infer_expr_stmt(context, node, tree_name) 

776 elif typ == 'with_stmt': 

777 value_managers = context.infer_node(node.get_test_node_from_name(tree_name)) 

778 if node.parent.type == 'async_stmt': 

779 # In the case of `async with` statements, we need to 

780 # first get the coroutine from the `__aenter__` method, 

781 # then "unwrap" via the `__await__` method 

782 enter_methods = value_managers.py__getattribute__('__aenter__') 

783 coro = enter_methods.execute_with_values() 

784 return coro.py__await__().py__stop_iteration_returns() 

785 enter_methods = value_managers.py__getattribute__('__enter__') 

786 return enter_methods.execute_annotation(context) 

787 elif typ in ('import_from', 'import_name'): 

788 types = imports.infer_import(context, tree_name) 

789 elif typ in ('funcdef', 'classdef'): 

790 types = _apply_decorators(context, node) 

791 elif typ == 'try_stmt': 

792 # TODO an exception can also be a tuple. Check for those. 

793 # TODO check for types that are not classes and add it to 

794 # the static analysis report. 

795 exceptions = context.infer_node(tree_name.get_previous_sibling().get_previous_sibling()) 

796 types = exceptions.execute_with_values() 

797 elif typ == 'param': 

798 types = NO_VALUES 

799 elif typ == 'del_stmt': 

800 types = NO_VALUES 

801 elif typ == 'namedexpr_test': 

802 types = infer_node(context, node) 

803 else: 

804 raise ValueError("Should not happen. type: %s" % typ) 

805 return types 

806 

807 

808# We don't want to have functions/classes that are created by the same 

809# tree_node. 

810@inference_state_method_cache() 

811def _apply_decorators(context, node): 

812 """ 

813 Returns the function, that should to be executed in the end. 

814 This is also the places where the decorators are processed. 

815 """ 

816 if node.type == 'classdef': 

817 decoratee_value = ClassValue( 

818 context.inference_state, 

819 parent_context=context, 

820 tree_node=node 

821 ) 

822 else: 

823 decoratee_value = FunctionValue.from_context(context, node) 

824 initial = values = ValueSet([decoratee_value]) 

825 

826 if is_big_annoying_library(context): 

827 return values 

828 

829 for dec in reversed(node.get_decorators()): 

830 debug.dbg('decorator: %s %s', dec, values, color="MAGENTA") 

831 with debug.increase_indent_cm(): 

832 dec_values = context.infer_node(dec.children[1]) 

833 trailer_nodes = dec.children[2:-1] 

834 if trailer_nodes: 

835 # Create a trailer and infer it. 

836 trailer = tree.PythonNode('trailer', trailer_nodes) 

837 trailer.parent = dec 

838 dec_values = infer_trailer(context, dec_values, trailer) 

839 

840 if not len(dec_values): 

841 code = dec.get_code(include_prefix=False) 

842 # For the short future, we don't want to hear about the runtime 

843 # decorator in typing that was intentionally omitted. This is not 

844 # "correct", but helps with debugging. 

845 if code != '@runtime\n': 

846 debug.warning('decorator not found: %s on %s', dec, node) 

847 return initial 

848 

849 values = dec_values.execute(arguments.ValuesArguments([values])) 

850 if not len(values): 

851 debug.warning('not possible to resolve wrappers found %s', node) 

852 return initial 

853 

854 debug.dbg('decorator end %s', values, color="MAGENTA") 

855 if values != initial: 

856 return ValueSet([Decoratee(c, decoratee_value) for c in values]) 

857 return values 

858 

859 

860def check_tuple_assignments(name, value_set): 

861 """ 

862 Checks if tuples are assigned. 

863 """ 

864 lazy_value = None 

865 for index, node in name.assignment_indexes(): 

866 cn = ContextualizedNode(name.parent_context, node) 

867 iterated = value_set.iterate(cn) 

868 if isinstance(index, slice): 

869 # For no star unpacking is not possible. 

870 return NO_VALUES 

871 i = 0 

872 lazy_value = None 

873 while i <= index: 

874 try: 

875 lazy_value = next(iterated) 

876 except StopIteration: 

877 # A desperate attempt to fix inference for tuples from an 

878 # iterator. 

879 if lazy_value is not None: 

880 return lazy_value.infer() 

881 

882 # We could do this with the default param in next. But this 

883 # would allow this loop to run for a very long time if the 

884 # index number is high. Therefore break if the loop is 

885 # finished. 

886 return NO_VALUES 

887 else: 

888 i += lazy_value.max 

889 value_set = lazy_value.infer() 

890 return value_set 

891 

892 

893class ContextualizedSubscriptListNode(ContextualizedNode): 

894 def infer(self): 

895 return _infer_subscript_list(self.context, self.node) 

896 

897 

898def _infer_subscript_list(context, index): 

899 """ 

900 Handles slices in subscript nodes. 

901 """ 

902 if index == ':': 

903 # Like array[:] 

904 return ValueSet([iterable.Slice(context, None, None, None)]) 

905 

906 elif index.type == 'subscript' and not index.children[0] == '.': 

907 # subscript basically implies a slice operation 

908 # e.g. array[:3] 

909 result = [] 

910 for el in index.children: 

911 if el == ':': 

912 if not result: 

913 result.append(None) 

914 elif el.type == 'sliceop': 

915 if len(el.children) == 2: 

916 result.append(el.children[1]) 

917 else: 

918 result.append(el) 

919 result += [None] * (3 - len(result)) 

920 

921 return ValueSet([iterable.Slice(context, *result)]) 

922 elif index.type == 'subscriptlist': 

923 return ValueSet([iterable.SequenceLiteralValue(context.inference_state, context, index)]) 

924 

925 # No slices 

926 return context.infer_node(index)