Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/parso/python/tree.py: 68%

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

641 statements  

1""" 

2This is the syntax tree for Python 3 syntaxes. The classes represent 

3syntax elements like functions and imports. 

4 

5All of the nodes can be traced back to the `Python grammar file 

6<https://docs.python.org/3/reference/grammar.html>`_. If you want to know how 

7a tree is structured, just analyse that file (for each Python version it's a 

8bit different). 

9 

10There's a lot of logic here that makes it easier for Jedi (and other libraries) 

11to deal with a Python syntax tree. 

12 

13By using :py:meth:`parso.tree.NodeOrLeaf.get_code` on a module, you can get 

14back the 1-to-1 representation of the input given to the parser. This is 

15important if you want to refactor a parser tree. 

16 

17>>> from parso import parse 

18>>> parser = parse('import os') 

19>>> module = parser.get_root_node() 

20>>> module 

21<Module: @1-1> 

22 

23Any subclasses of :class:`Scope`, including :class:`Module` has an attribute 

24:attr:`iter_imports <Scope.iter_imports>`: 

25 

26>>> list(module.iter_imports()) 

27[<ImportName: import os@1,0>] 

28 

29Changes to the Python Grammar 

30----------------------------- 

31 

32A few things have changed when looking at Python grammar files: 

33 

34- :class:`Param` does not exist in Python grammar files. It is essentially a 

35 part of a ``parameters`` node. |parso| splits it up to make it easier to 

36 analyse parameters. However this just makes it easier to deal with the syntax 

37 tree, it doesn't actually change the valid syntax. 

38- A few nodes like `lambdef` and `lambdef_nocond` have been merged in the 

39 syntax tree to make it easier to do deal with them. 

40 

41Parser Tree Classes 

42------------------- 

43""" 

44 

45import re 

46from collections.abc import Mapping 

47from typing import Tuple, Any 

48 

49from parso.tree import Node, BaseNode, Leaf, ErrorNode, ErrorLeaf, search_ancestor # noqa 

50from parso.python.prefix import split_prefix 

51from parso.utils import split_lines 

52 

53_FLOW_CONTAINERS = set(['if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 

54 'with_stmt', 'async_stmt', 'suite']) 

55_RETURN_STMT_CONTAINERS = set(['suite', 'simple_stmt']) | _FLOW_CONTAINERS 

56 

57_FUNC_CONTAINERS = set( 

58 ['suite', 'simple_stmt', 'decorated', 'async_funcdef'] 

59) | _FLOW_CONTAINERS 

60 

61_GET_DEFINITION_TYPES = set([ 

62 'expr_stmt', 'sync_comp_for', 'with_stmt', 'for_stmt', 'import_name', 

63 'import_from', 'param', 'del_stmt', 'namedexpr_test', 

64]) 

65_IMPORTS = set(['import_name', 'import_from']) 

66 

67 

68class DocstringMixin: 

69 __slots__ = () 

70 type: str 

71 children: "list[Any]" 

72 parent: Any 

73 

74 def get_doc_node(self): 

75 """ 

76 Returns the string leaf of a docstring. e.g. ``r'''foo'''``. 

77 """ 

78 if self.type == 'file_input': 

79 node = self.children[0] 

80 elif self.type in ('funcdef', 'classdef'): 

81 node = self.children[self.children.index(':') + 1] 

82 if node.type == 'suite': # Normally a suite 

83 node = node.children[1] # -> NEWLINE stmt 

84 else: # ExprStmt 

85 simple_stmt = self.parent 

86 c = simple_stmt.parent.children 

87 index = c.index(simple_stmt) 

88 if not index: 

89 return None 

90 node = c[index - 1] 

91 

92 if node.type == 'simple_stmt': 

93 node = node.children[0] 

94 if node.type == 'string': 

95 return node 

96 return None 

97 

98 

99class PythonMixin: 

100 """ 

101 Some Python specific utilities. 

102 """ 

103 __slots__ = () 

104 children: "list[Any]" 

105 

106 def get_name_of_position(self, position): 

107 """ 

108 Given a (line, column) tuple, returns a :py:class:`Name` or ``None`` if 

109 there is no name at that position. 

110 """ 

111 for c in self.children: 

112 if isinstance(c, Leaf): 

113 if c.type == 'name' and c.start_pos <= position <= c.end_pos: 

114 return c 

115 else: 

116 result = c.get_name_of_position(position) 

117 if result is not None: 

118 return result 

119 return None 

120 

121 

122class PythonLeaf(PythonMixin, Leaf): 

123 __slots__ = () 

124 

125 def _split_prefix(self): 

126 return split_prefix(self, self.get_start_pos_of_prefix()) 

127 

128 def get_start_pos_of_prefix(self): 

129 """ 

130 Basically calls :py:meth:`parso.tree.NodeOrLeaf.get_start_pos_of_prefix`. 

131 """ 

132 # TODO it is really ugly that we have to override it. Maybe change 

133 # indent error leafs somehow? No idea how, though. 

134 previous_leaf = self.get_previous_leaf() 

135 if previous_leaf is not None and previous_leaf.type == 'error_leaf' \ 

136 and previous_leaf.token_type in ('INDENT', 'DEDENT', 'ERROR_DEDENT'): 

137 previous_leaf = previous_leaf.get_previous_leaf() 

138 

139 if previous_leaf is None: # It's the first leaf. 

140 lines = split_lines(self.prefix) 

141 # + 1 is needed because split_lines always returns at least ['']. 

142 return self.line - len(lines) + 1, 0 # It's the first leaf. 

143 return previous_leaf.end_pos 

144 

145 

146class _LeafWithoutNewlines(PythonLeaf): 

147 """ 

148 Simply here to optimize performance. 

149 """ 

150 __slots__ = () 

151 

152 @property 

153 def end_pos(self) -> Tuple[int, int]: 

154 return self.line, self.column + len(self.value) 

155 

156 

157# Python base classes 

158class PythonBaseNode(PythonMixin, BaseNode): 

159 __slots__ = () 

160 

161 

162class PythonNode(PythonMixin, Node): 

163 __slots__ = () 

164 

165 

166class PythonErrorNode(PythonMixin, ErrorNode): 

167 __slots__ = () 

168 

169 

170class PythonErrorLeaf(ErrorLeaf, PythonLeaf): 

171 __slots__ = () 

172 

173 

174class EndMarker(_LeafWithoutNewlines): 

175 __slots__ = () 

176 type = 'endmarker' 

177 

178 def __repr__(self): 

179 return "<%s: prefix=%s end_pos=%s>" % ( 

180 type(self).__name__, repr(self.prefix), self.end_pos 

181 ) 

182 

183 

184class Newline(PythonLeaf): 

185 """Contains NEWLINE and ENDMARKER tokens.""" 

186 __slots__ = () 

187 type = 'newline' 

188 

189 def __repr__(self): 

190 return "<%s: %s>" % (type(self).__name__, repr(self.value)) 

191 

192 

193class Name(_LeafWithoutNewlines): 

194 """ 

195 A string. Sometimes it is important to know if the string belongs to a name 

196 or not. 

197 """ 

198 type = 'name' 

199 __slots__ = () 

200 

201 def __repr__(self): 

202 return "<%s: %s@%s,%s>" % (type(self).__name__, self.value, 

203 self.line, self.column) 

204 

205 def is_definition(self, include_setitem=False): 

206 """ 

207 Returns True if the name is being defined. 

208 """ 

209 return self.get_definition(include_setitem=include_setitem) is not None 

210 

211 def get_definition(self, import_name_always=False, include_setitem=False): 

212 """ 

213 Returns None if there's no definition for a name. 

214 

215 :param import_name_always: Specifies if an import name is always a 

216 definition. Normally foo in `from foo import bar` is not a 

217 definition. 

218 """ 

219 node = self.parent 

220 type_ = node.type 

221 

222 if type_ in ('funcdef', 'classdef'): 

223 if self == node.name: # type: ignore[union-attr] 

224 return node 

225 return None 

226 

227 if type_ == 'except_clause': 

228 if self.get_previous_sibling() == 'as': 

229 return node.parent # The try_stmt. 

230 return None 

231 

232 while node is not None: 

233 if node.type == 'suite': 

234 return None 

235 if node.type in _GET_DEFINITION_TYPES: 

236 if self in node.get_defined_names(include_setitem): # type: ignore[attr-defined] 

237 return node 

238 if import_name_always and node.type in _IMPORTS: 

239 return node 

240 return None 

241 node = node.parent 

242 return None 

243 

244 

245class Literal(PythonLeaf): 

246 __slots__ = () 

247 

248 

249class Number(Literal): 

250 type = 'number' 

251 __slots__ = () 

252 

253 

254class String(Literal): 

255 type = 'string' 

256 __slots__ = () 

257 

258 @property 

259 def string_prefix(self): 

260 return re.match(r'\w*(?=[\'"])', self.value).group(0) 

261 

262 def _get_payload(self): 

263 match = re.search( 

264 r'''('{3}|"{3}|'|")(.*)$''', 

265 self.value, 

266 flags=re.DOTALL 

267 ) 

268 return match.group(2)[:-len(match.group(1))] 

269 

270 

271class FStringString(PythonLeaf): 

272 """ 

273 f-strings contain f-string expressions and normal python strings. These are 

274 the string parts of f-strings. 

275 """ 

276 type = 'fstring_string' 

277 __slots__ = () 

278 

279 

280class FStringStart(PythonLeaf): 

281 """ 

282 f-strings contain f-string expressions and normal python strings. These are 

283 the string parts of f-strings. 

284 """ 

285 type = 'fstring_start' 

286 __slots__ = () 

287 

288 

289class FStringEnd(PythonLeaf): 

290 """ 

291 f-strings contain f-string expressions and normal python strings. These are 

292 the string parts of f-strings. 

293 """ 

294 type = 'fstring_end' 

295 __slots__ = () 

296 

297 

298class _StringComparisonMixin: 

299 __slots__ = () 

300 value: Any 

301 

302 def __eq__(self, other): 

303 """ 

304 Make comparisons with strings easy. 

305 Improves the readability of the parser. 

306 """ 

307 if isinstance(other, str): 

308 return self.value == other 

309 

310 return self is other 

311 

312 def __hash__(self): 

313 return hash(self.value) 

314 

315 

316class Operator(_LeafWithoutNewlines, _StringComparisonMixin): 

317 type = 'operator' 

318 __slots__ = () 

319 

320 

321class Keyword(_LeafWithoutNewlines, _StringComparisonMixin): 

322 type = 'keyword' 

323 __slots__ = () 

324 

325 

326class Scope(PythonBaseNode, DocstringMixin): 

327 """ 

328 Super class for the parser tree, which represents the state of a python 

329 text file. 

330 A Scope is either a function, class or lambda. 

331 """ 

332 __slots__ = () 

333 

334 def __init__(self, children): 

335 super().__init__(children) 

336 

337 def iter_funcdefs(self): 

338 """ 

339 Returns a generator of `funcdef` nodes. 

340 """ 

341 return self._search_in_scope('funcdef') 

342 

343 def iter_classdefs(self): 

344 """ 

345 Returns a generator of `classdef` nodes. 

346 """ 

347 return self._search_in_scope('classdef') 

348 

349 def iter_imports(self): 

350 """ 

351 Returns a generator of `import_name` and `import_from` nodes. 

352 """ 

353 return self._search_in_scope('import_name', 'import_from') 

354 

355 def _search_in_scope(self, *names): 

356 def scan(children): 

357 for element in children: 

358 if element.type in names: 

359 yield element 

360 if element.type in _FUNC_CONTAINERS: 

361 yield from scan(element.children) 

362 

363 return scan(self.children) 

364 

365 def get_suite(self): 

366 """ 

367 Returns the part that is executed by the function. 

368 """ 

369 return self.children[-1] 

370 

371 def __repr__(self): 

372 try: 

373 name = self.name.value # type: ignore[attr-defined] 

374 except AttributeError: 

375 name = '' 

376 

377 return "<%s: %s@%s-%s>" % (type(self).__name__, name, 

378 self.start_pos[0], self.end_pos[0]) 

379 

380 

381class Module(Scope): 

382 """ 

383 The top scope, which is always a module. 

384 Depending on the underlying parser this may be a full module or just a part 

385 of a module. 

386 """ 

387 __slots__ = ('_used_names',) 

388 type = 'file_input' 

389 

390 def __init__(self, children): 

391 super().__init__(children) 

392 self._used_names = None 

393 

394 def _iter_future_import_names(self): 

395 """ 

396 :return: A list of future import names. 

397 :rtype: list of str 

398 """ 

399 # In Python it's not allowed to use future imports after the first 

400 # actual (non-future) statement. However this is not a linter here, 

401 # just return all future imports. If people want to scan for issues 

402 # they should use the API. 

403 for imp in self.iter_imports(): 

404 if imp.type == 'import_from' and imp.level == 0: 

405 for path in imp.get_paths(): 

406 names = [name.value for name in path] 

407 if len(names) == 2 and names[0] == '__future__': 

408 yield names[1] 

409 

410 def get_used_names(self): 

411 """ 

412 Returns all the :class:`Name` leafs that exist in this module. This 

413 includes both definitions and references of names. 

414 """ 

415 if self._used_names is None: 

416 # Don't directly use self._used_names to eliminate a lookup. 

417 dct = {} 

418 

419 def recurse(node): 

420 try: 

421 children = node.children 

422 except AttributeError: 

423 if node.type == 'name': 

424 arr = dct.setdefault(node.value, []) 

425 arr.append(node) 

426 else: 

427 for child in children: 

428 recurse(child) 

429 

430 recurse(self) 

431 self._used_names = UsedNamesMapping(dct) 

432 return self._used_names 

433 

434 

435class Decorator(PythonBaseNode): 

436 type = 'decorator' 

437 __slots__ = () 

438 

439 

440class ClassOrFunc(Scope): 

441 __slots__ = () 

442 

443 @property 

444 def name(self): 

445 """ 

446 Returns the `Name` leaf that defines the function or class name. 

447 """ 

448 return self.children[1] 

449 

450 def get_decorators(self): 

451 """ 

452 :rtype: list of :class:`Decorator` 

453 """ 

454 decorated = self.parent 

455 if decorated.type == 'async_funcdef': 

456 decorated = decorated.parent 

457 

458 if decorated.type == 'decorated': 

459 if decorated.children[0].type == 'decorators': 

460 return decorated.children[0].children 

461 else: 

462 return decorated.children[:1] 

463 else: 

464 return [] 

465 

466 

467class Class(ClassOrFunc): 

468 """ 

469 Used to store the parsed contents of a python class. 

470 """ 

471 type = 'classdef' 

472 __slots__ = () 

473 

474 def __init__(self, children): 

475 super().__init__(children) 

476 

477 def get_super_arglist(self): 

478 """ 

479 Returns the `arglist` node that defines the super classes. It returns 

480 None if there are no arguments. 

481 """ 

482 for i, child in enumerate(self.children): 

483 if child == '(': 

484 next_child = self.children[i + 1] 

485 if next_child == ')': 

486 return None 

487 return next_child 

488 return None 

489 

490 

491def _create_params(parent, argslist_list): 

492 """ 

493 `argslist_list` is a list that can contain an argslist as a first item, but 

494 most not. It's basically the items between the parameter brackets (which is 

495 at most one item). 

496 This function modifies the parser structure. It generates `Param` objects 

497 from the normal ast. Those param objects do not exist in a normal ast, but 

498 make the evaluation of the ast tree so much easier. 

499 You could also say that this function replaces the argslist node with a 

500 list of Param objects. 

501 """ 

502 try: 

503 first = argslist_list[0] 

504 except IndexError: 

505 return [] 

506 

507 if first.type in ('name', 'fpdef'): 

508 return [Param([first], parent)] 

509 elif first == '*': 

510 return [first] 

511 else: # argslist is a `typedargslist` or a `varargslist`. 

512 if first.type == 'tfpdef': 

513 children = [first] 

514 else: 

515 children = first.children 

516 new_children = [] 

517 start = 0 

518 # Start with offset 1, because the end is higher. 

519 for end, child in enumerate(children + [None], 1): 

520 if child is None or child == ',': 

521 param_children = children[start:end] 

522 if param_children: # Could as well be comma and then end. 

523 if param_children[0] == '*' \ 

524 and (len(param_children) == 1 

525 or param_children[1] == ',') \ 

526 or param_children[0] == '/': 

527 for p in param_children: 

528 p.parent = parent 

529 new_children += param_children 

530 else: 

531 new_children.append(Param(param_children, parent)) 

532 start = end 

533 return new_children 

534 

535 

536class Function(ClassOrFunc): 

537 """ 

538 Used to store the parsed contents of a python function. 

539 

540 Children:: 

541 

542 0. <Keyword: def> 

543 1. <Name> 

544 2. parameter list (including open-paren and close-paren <Operator>s) 

545 3. or 5. <Operator: :> 

546 4. or 6. Node() representing function body 

547 3. -> (if annotation is also present) 

548 4. annotation (if present) 

549 """ 

550 type = 'funcdef' 

551 __slots__ = () 

552 

553 def __init__(self, children): 

554 super().__init__(children) 

555 parameters = self._find_parameters() 

556 parameters_children = parameters.children[1:-1] 

557 if not any(isinstance(child, Param) for child in parameters_children): 

558 parameters.children[1:-1] = _create_params( 

559 parameters, parameters_children 

560 ) 

561 

562 def _find_parameters(self): 

563 for child in self.children: 

564 if child.type == 'parameters': 

565 return child 

566 raise Exception("A function should always have parameters") 

567 

568 def _get_param_nodes(self): 

569 return self._find_parameters().children 

570 

571 def get_params(self): 

572 """ 

573 Returns a list of `Param()`. 

574 """ 

575 return [p for p in self._get_param_nodes() if p.type == 'param'] 

576 

577 @property 

578 def name(self): 

579 return self.children[1] # First token after `def` 

580 

581 def iter_yield_exprs(self): 

582 """ 

583 Returns a generator of `yield_expr`. 

584 """ 

585 def scan(children): 

586 for element in children: 

587 if element.type in ('classdef', 'funcdef', 'lambdef'): 

588 continue 

589 

590 try: 

591 nested_children = element.children 

592 except AttributeError: 

593 if element.value == 'yield': 

594 if element.parent.type == 'yield_expr': 

595 yield element.parent 

596 else: 

597 yield element 

598 else: 

599 yield from scan(nested_children) 

600 

601 return scan(self.children) 

602 

603 def iter_return_stmts(self): 

604 """ 

605 Returns a generator of `return_stmt`. 

606 """ 

607 def scan(children): 

608 for element in children: 

609 if element.type == 'return_stmt' \ 

610 or element.type == 'keyword' and element.value == 'return': 

611 yield element 

612 if element.type in _RETURN_STMT_CONTAINERS: 

613 yield from scan(element.children) 

614 

615 return scan(self.children) 

616 

617 def iter_raise_stmts(self): 

618 """ 

619 Returns a generator of `raise_stmt`. Includes raise statements inside try-except blocks 

620 """ 

621 def scan(children): 

622 for element in children: 

623 if element.type == 'raise_stmt' \ 

624 or element.type == 'keyword' and element.value == 'raise': 

625 yield element 

626 if element.type in _RETURN_STMT_CONTAINERS: 

627 yield from scan(element.children) 

628 

629 return scan(self.children) 

630 

631 def is_generator(self): 

632 """ 

633 :return bool: Checks if a function is a generator or not. 

634 """ 

635 return next(self.iter_yield_exprs(), None) is not None 

636 

637 @property 

638 def annotation(self): 

639 """ 

640 Returns the test node after `->` or `None` if there is no annotation. 

641 """ 

642 for i, child in enumerate(self.children): 

643 if child == '->': 

644 return self.children[i + 1] 

645 return None 

646 

647 

648class Lambda(Function): 

649 """ 

650 Lambdas are basically trimmed functions, so give it the same interface. 

651 

652 Children:: 

653 

654 0. <Keyword: lambda> 

655 *. <Param x> for each argument x 

656 -2. <Operator: :> 

657 -1. Node() representing body 

658 """ 

659 type = 'lambdef' 

660 __slots__ = () 

661 

662 def __init__(self, children): 

663 # We don't want to call the Function constructor, call its parent. 

664 super(Function, self).__init__(children) 

665 # Everything between `lambda` and the `:` operator is a parameter. 

666 parameters_children = self.children[1:-2] 

667 # If input children list already has Param objects, keep it as is; 

668 # otherwise, convert it to a list of Param objects. 

669 if not any(isinstance(child, Param) for child in parameters_children): 

670 self.children[1:-2] = _create_params(self, parameters_children) 

671 

672 @property 

673 def name(self): 

674 """ 

675 Raises an AttributeError. Lambdas don't have a defined name. 

676 """ 

677 raise AttributeError("lambda is not named.") 

678 

679 def _get_param_nodes(self): 

680 return self.children[1:-2] 

681 

682 @property 

683 def annotation(self): 

684 """ 

685 Returns `None`, lambdas don't have annotations. 

686 """ 

687 return None 

688 

689 def __repr__(self): 

690 return "<%s@%s>" % (self.__class__.__name__, self.start_pos) 

691 

692 

693class Flow(PythonBaseNode): 

694 __slots__ = () 

695 

696 

697class IfStmt(Flow): 

698 type = 'if_stmt' 

699 __slots__ = () 

700 

701 def get_test_nodes(self): 

702 """ 

703 E.g. returns all the `test` nodes that are named as x, below: 

704 

705 if x: 

706 pass 

707 elif x: 

708 pass 

709 """ 

710 for i, c in enumerate(self.children): 

711 if c in ('elif', 'if'): 

712 yield self.children[i + 1] 

713 

714 def get_corresponding_test_node(self, node): 

715 """ 

716 Searches for the branch in which the node is and returns the 

717 corresponding test node (see function above). However if the node is in 

718 the test node itself and not in the suite return None. 

719 """ 

720 start_pos = node.start_pos 

721 for check_node in reversed(list(self.get_test_nodes())): 

722 if check_node.start_pos < start_pos: 

723 if start_pos < check_node.end_pos: 

724 return None 

725 # In this case the node is within the check_node itself, 

726 # not in the suite 

727 else: 

728 return check_node 

729 

730 def is_node_after_else(self, node): 

731 """ 

732 Checks if a node is defined after `else`. 

733 """ 

734 for c in self.children: 

735 if c == 'else': 

736 if node.start_pos > c.start_pos: 

737 return True 

738 else: 

739 return False 

740 

741 

742class WhileStmt(Flow): 

743 type = 'while_stmt' 

744 __slots__ = () 

745 

746 

747class ForStmt(Flow): 

748 type = 'for_stmt' 

749 __slots__ = () 

750 

751 def get_testlist(self): 

752 """ 

753 Returns the input node ``y`` from: ``for x in y:``. 

754 """ 

755 return self.children[3] 

756 

757 def get_defined_names(self, include_setitem=False): 

758 return _defined_names(self.children[1], include_setitem) 

759 

760 

761class TryStmt(Flow): 

762 type = 'try_stmt' 

763 __slots__ = () 

764 

765 def get_except_clause_tests(self): 

766 """ 

767 Returns the ``test`` nodes found in ``except_clause`` nodes. 

768 Returns ``[None]`` for except clauses without an exception given. 

769 """ 

770 for node in self.children: 

771 if node.type == 'except_clause': 

772 yield node.children[1] 

773 elif node == 'except': 

774 yield None 

775 

776 

777class WithStmt(Flow): 

778 type = 'with_stmt' 

779 __slots__ = () 

780 

781 def get_defined_names(self, include_setitem=False): 

782 """ 

783 Returns the a list of `Name` that the with statement defines. The 

784 defined names are set after `as`. 

785 """ 

786 names = [] 

787 for with_item in self.children[1:-2:2]: 

788 # Check with items for 'as' names. 

789 if with_item.type == 'with_item': 

790 names += _defined_names(with_item.children[2], include_setitem) 

791 return names 

792 

793 def get_test_node_from_name(self, name): 

794 node = name.search_ancestor("with_item") 

795 if node is None: 

796 raise ValueError('The name is not actually part of a with statement.') 

797 return node.children[0] 

798 

799 

800class Import(PythonBaseNode): 

801 __slots__ = () 

802 get_paths: Any 

803 _aliases: Any 

804 

805 def get_path_for_name(self, name): 

806 """ 

807 The path is the list of names that leads to the searched name. 

808 

809 :return list of Name: 

810 """ 

811 try: 

812 # The name may be an alias. If it is, just map it back to the name. 

813 name = self._aliases()[name] 

814 except KeyError: 

815 pass 

816 

817 for path in self.get_paths(): 

818 if name in path: 

819 return path[:path.index(name) + 1] 

820 raise ValueError('Name should be defined in the import itself') 

821 

822 def is_nested(self): 

823 return False # By default, sub classes may overwrite this behavior 

824 

825 def is_star_import(self): 

826 return self.children[-1] == '*' 

827 

828 def get_defined_names(self): 

829 raise NotImplementedError("Use ImportFrom or ImportName") 

830 

831 

832class ImportFrom(Import): 

833 type = 'import_from' 

834 __slots__ = () 

835 

836 def get_defined_names(self, include_setitem=False): 

837 """ 

838 Returns the a list of `Name` that the import defines. The 

839 defined names are set after `import` or in case an alias - `as` - is 

840 present that name is returned. 

841 """ 

842 return [alias or name for name, alias in self._as_name_tuples()] 

843 

844 def _aliases(self): 

845 """Mapping from alias to its corresponding name.""" 

846 return dict((alias, name) for name, alias in self._as_name_tuples() 

847 if alias is not None) 

848 

849 def get_from_names(self): 

850 for n in self.children[1:]: 

851 if n not in ('.', '...'): 

852 break 

853 if n.type == 'dotted_name': # from x.y import 

854 return n.children[::2] 

855 elif n == 'import': # from . import 

856 return [] 

857 else: # from x import 

858 return [n] 

859 

860 @property 

861 def level(self): 

862 """The level parameter of ``__import__``.""" 

863 level = 0 

864 for n in self.children[1:]: 

865 if n in ('.', '...'): 

866 level += len(n.value) 

867 else: 

868 break 

869 return level 

870 

871 def _as_name_tuples(self): 

872 last = self.children[-1] 

873 if last == ')': 

874 last = self.children[-2] 

875 elif last == '*': 

876 return # No names defined directly. 

877 

878 if last.type == 'import_as_names': 

879 as_names = last.children[::2] 

880 else: 

881 as_names = [last] 

882 for as_name in as_names: 

883 if as_name.type == 'name': 

884 yield as_name, None 

885 else: 

886 yield as_name.children[::2] # yields x, y -> ``x as y`` 

887 

888 def get_paths(self): 

889 """ 

890 The import paths defined in an import statement. Typically an array 

891 like this: ``[<Name: datetime>, <Name: date>]``. 

892 

893 :return list of list of Name: 

894 """ 

895 dotted = self.get_from_names() 

896 

897 if self.children[-1] == '*': 

898 return [dotted] 

899 return [dotted + [name] for name, alias in self._as_name_tuples()] 

900 

901 

902class ImportName(Import): 

903 """For ``import_name`` nodes. Covers normal imports without ``from``.""" 

904 type = 'import_name' 

905 __slots__ = () 

906 

907 def get_defined_names(self, include_setitem=False): 

908 """ 

909 Returns the a list of `Name` that the import defines. The defined names 

910 is always the first name after `import` or in case an alias - `as` - is 

911 present that name is returned. 

912 """ 

913 return [alias or path[0] for path, alias in self._dotted_as_names()] 

914 

915 @property 

916 def level(self): 

917 """The level parameter of ``__import__``.""" 

918 return 0 # Obviously 0 for imports without from. 

919 

920 def get_paths(self): 

921 return [path for path, alias in self._dotted_as_names()] 

922 

923 def _dotted_as_names(self): 

924 """Generator of (list(path), alias) where alias may be None.""" 

925 dotted_as_names = self.children[1] 

926 if dotted_as_names.type == 'dotted_as_names': 

927 as_names = dotted_as_names.children[::2] 

928 else: 

929 as_names = [dotted_as_names] 

930 

931 for as_name in as_names: 

932 if as_name.type == 'dotted_as_name': 

933 alias = as_name.children[2] 

934 as_name = as_name.children[0] 

935 else: 

936 alias = None 

937 if as_name.type == 'name': 

938 yield [as_name], alias 

939 else: 

940 # dotted_names 

941 yield as_name.children[::2], alias 

942 

943 def is_nested(self): 

944 """ 

945 This checks for the special case of nested imports, without aliases and 

946 from statement:: 

947 

948 import foo.bar 

949 """ 

950 return bool([1 for path, alias in self._dotted_as_names() 

951 if alias is None and len(path) > 1]) 

952 

953 def _aliases(self): 

954 """ 

955 :return list of Name: Returns all the alias 

956 """ 

957 return dict((alias, path[-1]) for path, alias in self._dotted_as_names() 

958 if alias is not None) 

959 

960 

961class KeywordStatement(PythonBaseNode): 

962 """ 

963 For the following statements: `assert`, `del`, `global`, `nonlocal`, 

964 `raise`, `return`, `yield`. 

965 

966 `pass`, `continue` and `break` are not in there, because they are just 

967 simple keywords and the parser reduces it to a keyword. 

968 """ 

969 __slots__ = () 

970 

971 @property 

972 def type(self): 

973 """ 

974 Keyword statements start with the keyword and end with `_stmt`. You can 

975 crosscheck this with the Python grammar. 

976 """ 

977 return '%s_stmt' % self.keyword 

978 

979 @property 

980 def keyword(self): 

981 return self.children[0].value 

982 

983 def get_defined_names(self, include_setitem=False): 

984 keyword = self.keyword 

985 if keyword == 'del': 

986 return _defined_names(self.children[1], include_setitem) 

987 if keyword in ('global', 'nonlocal'): 

988 return self.children[1::2] 

989 return [] 

990 

991 

992class AssertStmt(KeywordStatement): 

993 __slots__ = () 

994 

995 @property 

996 def assertion(self): 

997 return self.children[1] 

998 

999 

1000class GlobalStmt(KeywordStatement): 

1001 __slots__ = () 

1002 

1003 def get_global_names(self): 

1004 return self.children[1::2] 

1005 

1006 

1007class ReturnStmt(KeywordStatement): 

1008 __slots__ = () 

1009 

1010 

1011class YieldExpr(PythonBaseNode): 

1012 type = 'yield_expr' 

1013 __slots__ = () 

1014 

1015 

1016def _defined_names(current, include_setitem): 

1017 """ 

1018 A helper function to find the defined names in statements, for loops and 

1019 list comprehensions. 

1020 """ 

1021 names = [] 

1022 if current.type in ('testlist_star_expr', 'testlist_comp', 'exprlist', 'testlist'): 

1023 for child in current.children[::2]: 

1024 names += _defined_names(child, include_setitem) 

1025 elif current.type in ('atom', 'star_expr'): 

1026 names += _defined_names(current.children[1], include_setitem) 

1027 elif current.type in ('power', 'atom_expr'): 

1028 if current.children[-2] != '**': # Just if there's no operation 

1029 trailer = current.children[-1] 

1030 if trailer.children[0] == '.': 

1031 names.append(trailer.children[1]) 

1032 elif trailer.children[0] == '[' and include_setitem: 

1033 for node in current.children[-2::-1]: 

1034 if node.type == 'trailer': 

1035 names.append(node.children[1]) 

1036 break 

1037 if node.type == 'name': 

1038 names.append(node) 

1039 break 

1040 else: 

1041 names.append(current) 

1042 return names 

1043 

1044 

1045class ExprStmt(PythonBaseNode, DocstringMixin): 

1046 type = 'expr_stmt' 

1047 __slots__ = () 

1048 

1049 def get_defined_names(self, include_setitem=False): 

1050 """ 

1051 Returns a list of `Name` defined before the `=` sign. 

1052 """ 

1053 names = [] 

1054 if self.children[1].type == 'annassign': 

1055 names = _defined_names(self.children[0], include_setitem) 

1056 return [ 

1057 name 

1058 for i in range(0, len(self.children) - 2, 2) 

1059 if '=' in self.children[i + 1].value 

1060 for name in _defined_names(self.children[i], include_setitem) 

1061 ] + names 

1062 

1063 def get_rhs(self): 

1064 """Returns the right-hand-side of the equals.""" 

1065 node = self.children[-1] 

1066 if node.type == 'annassign': 

1067 if len(node.children) == 4: 

1068 node = node.children[3] 

1069 else: 

1070 node = node.children[1] 

1071 return node 

1072 

1073 def yield_operators(self): 

1074 """ 

1075 Returns a generator of `+=`, `=`, etc. or None if there is no operation. 

1076 """ 

1077 first = self.children[1] 

1078 if first.type == 'annassign': 

1079 if len(first.children) <= 2: 

1080 return # No operator is available, it's just PEP 484. 

1081 

1082 first = first.children[2] 

1083 yield first 

1084 

1085 yield from self.children[3::2] 

1086 

1087 

1088class NamedExpr(PythonBaseNode): 

1089 type = 'namedexpr_test' 

1090 

1091 def get_defined_names(self, include_setitem=False): 

1092 return _defined_names(self.children[0], include_setitem) 

1093 

1094 

1095class Param(PythonBaseNode): 

1096 """ 

1097 It's a helper class that makes business logic with params much easier. The 

1098 Python grammar defines no ``param`` node. It defines it in a different way 

1099 that is not really suited to working with parameters. 

1100 """ 

1101 type = 'param' 

1102 

1103 def __init__(self, children, parent=None): 

1104 super().__init__(children) 

1105 self.parent = parent 

1106 

1107 @property 

1108 def star_count(self): 

1109 """ 

1110 Is `0` in case of `foo`, `1` in case of `*foo` or `2` in case of 

1111 `**foo`. 

1112 """ 

1113 first = self.children[0] 

1114 if first in ('*', '**'): 

1115 return len(first.value) 

1116 return 0 

1117 

1118 @property 

1119 def default(self): 

1120 """ 

1121 The default is the test node that appears after the `=`. Is `None` in 

1122 case no default is present. 

1123 """ 

1124 has_comma = self.children[-1] == ',' 

1125 try: 

1126 if self.children[-2 - int(has_comma)] == '=': 

1127 return self.children[-1 - int(has_comma)] 

1128 except IndexError: 

1129 return None 

1130 

1131 @property 

1132 def annotation(self): 

1133 """ 

1134 The default is the test node that appears after `:`. Is `None` in case 

1135 no annotation is present. 

1136 """ 

1137 tfpdef = self._tfpdef() 

1138 if tfpdef.type == 'tfpdef': 

1139 assert tfpdef.children[1] == ":" 

1140 assert len(tfpdef.children) == 3 

1141 annotation = tfpdef.children[2] 

1142 return annotation 

1143 else: 

1144 return None 

1145 

1146 def _tfpdef(self): 

1147 """ 

1148 tfpdef: see e.g. grammar36.txt. 

1149 """ 

1150 offset = int(self.children[0] in ('*', '**')) 

1151 return self.children[offset] 

1152 

1153 @property 

1154 def name(self): 

1155 """ 

1156 The `Name` leaf of the param. 

1157 """ 

1158 if self._tfpdef().type == 'tfpdef': 

1159 return self._tfpdef().children[0] 

1160 else: 

1161 return self._tfpdef() 

1162 

1163 def get_defined_names(self, include_setitem=False): 

1164 return [self.name] 

1165 

1166 @property 

1167 def position_index(self): 

1168 """ 

1169 Property for the positional index of a paramter. 

1170 """ 

1171 index = self.parent.children.index(self) 

1172 try: 

1173 keyword_only_index = self.parent.children.index('*') 

1174 if index > keyword_only_index: 

1175 # Skip the ` *, ` 

1176 index -= 2 

1177 except ValueError: 

1178 pass 

1179 try: 

1180 keyword_only_index = self.parent.children.index('/') 

1181 if index > keyword_only_index: 

1182 # Skip the ` /, ` 

1183 index -= 2 

1184 except ValueError: 

1185 pass 

1186 return index - 1 

1187 

1188 def get_parent_function(self): 

1189 """ 

1190 Returns the function/lambda of a parameter. 

1191 """ 

1192 return self.search_ancestor('funcdef', 'lambdef') 

1193 

1194 def get_code(self, include_prefix=True, include_comma=True): 

1195 """ 

1196 Like all the other get_code functions, but includes the param 

1197 `include_comma`. 

1198 

1199 :param include_comma bool: If enabled includes the comma in the string output. 

1200 """ 

1201 if include_comma: 

1202 return super().get_code(include_prefix) 

1203 

1204 children = self.children 

1205 if children[-1] == ',': 

1206 children = children[:-1] 

1207 return self._get_code_for_children( 

1208 children, 

1209 include_prefix=include_prefix 

1210 ) 

1211 

1212 def __repr__(self): 

1213 default = '' if self.default is None else '=%s' % self.default.get_code() 

1214 return '<%s: %s>' % (type(self).__name__, str(self._tfpdef()) + default) 

1215 

1216 

1217class SyncCompFor(PythonBaseNode): 

1218 type = 'sync_comp_for' 

1219 __slots__ = () 

1220 

1221 def get_defined_names(self, include_setitem=False): 

1222 """ 

1223 Returns the a list of `Name` that the comprehension defines. 

1224 """ 

1225 # allow async for 

1226 return _defined_names(self.children[1], include_setitem) 

1227 

1228 

1229# This is simply here so an older Jedi version can work with this new parso 

1230# version. Can be deleted in the next release. 

1231CompFor = SyncCompFor 

1232 

1233 

1234class UsedNamesMapping(Mapping): 

1235 """ 

1236 This class exists for the sole purpose of creating an immutable dict. 

1237 """ 

1238 def __init__(self, dct): 

1239 self._dict = dct 

1240 

1241 def __getitem__(self, key): 

1242 return self._dict[key] 

1243 

1244 def __len__(self): 

1245 return len(self._dict) 

1246 

1247 def __iter__(self): 

1248 return iter(self._dict) 

1249 

1250 def __hash__(self): 

1251 return id(self) 

1252 

1253 def __eq__(self, other): 

1254 # Comparing these dicts does not make sense. 

1255 return self is other