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

630 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

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 

46try: 

47 from collections.abc import Mapping 

48except ImportError: 

49 from collections import Mapping 

50from typing import Tuple 

51 

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

53from parso.python.prefix import split_prefix 

54from parso.utils import split_lines 

55 

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

57 'with_stmt', 'async_stmt', 'suite']) 

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

59 

60_FUNC_CONTAINERS = set( 

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

62) | _FLOW_CONTAINERS 

63 

64_GET_DEFINITION_TYPES = set([ 

65 'expr_stmt', 'sync_comp_for', 'with_stmt', 'for_stmt', 'import_name', 

66 'import_from', 'param', 'del_stmt', 'namedexpr_test', 

67]) 

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

69 

70 

71class DocstringMixin: 

72 __slots__ = () 

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 

105 def get_name_of_position(self, position): 

106 """ 

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

108 there is no name at that position. 

109 """ 

110 for c in self.children: 

111 if isinstance(c, Leaf): 

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

113 return c 

114 else: 

115 result = c.get_name_of_position(position) 

116 if result is not None: 

117 return result 

118 return None 

119 

120 

121class PythonLeaf(PythonMixin, Leaf): 

122 __slots__ = () 

123 

124 def _split_prefix(self): 

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

126 

127 def get_start_pos_of_prefix(self): 

128 """ 

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

130 """ 

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

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

133 previous_leaf = self.get_previous_leaf() 

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

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

136 previous_leaf = previous_leaf.get_previous_leaf() 

137 

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

139 lines = split_lines(self.prefix) 

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

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

142 return previous_leaf.end_pos 

143 

144 

145class _LeafWithoutNewlines(PythonLeaf): 

146 """ 

147 Simply here to optimize performance. 

148 """ 

149 __slots__ = () 

150 

151 @property 

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

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

154 

155 

156# Python base classes 

157class PythonBaseNode(PythonMixin, BaseNode): 

158 __slots__ = () 

159 

160 

161class PythonNode(PythonMixin, Node): 

162 __slots__ = () 

163 

164 

165class PythonErrorNode(PythonMixin, ErrorNode): 

166 __slots__ = () 

167 

168 

169class PythonErrorLeaf(ErrorLeaf, PythonLeaf): 

170 __slots__ = () 

171 

172 

173class EndMarker(_LeafWithoutNewlines): 

174 __slots__ = () 

175 type = 'endmarker' 

176 

177 def __repr__(self): 

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

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

180 ) 

181 

182 

183class Newline(PythonLeaf): 

184 """Contains NEWLINE and ENDMARKER tokens.""" 

185 __slots__ = () 

186 type = 'newline' 

187 

188 def __repr__(self): 

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

190 

191 

192class Name(_LeafWithoutNewlines): 

193 """ 

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

195 or not. 

196 """ 

197 type = 'name' 

198 __slots__ = () 

199 

200 def __repr__(self): 

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

202 self.line, self.column) 

203 

204 def is_definition(self, include_setitem=False): 

205 """ 

206 Returns True if the name is being defined. 

207 """ 

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

209 

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

211 """ 

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

213 

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

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

216 definition. 

217 """ 

218 node = self.parent 

219 type_ = node.type 

220 

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

222 if self == node.name: 

223 return node 

224 return None 

225 

226 if type_ == 'except_clause': 

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

228 return node.parent # The try_stmt. 

229 return None 

230 

231 while node is not None: 

232 if node.type == 'suite': 

233 return None 

234 if node.type in _GET_DEFINITION_TYPES: 

235 if self in node.get_defined_names(include_setitem): 

236 return node 

237 if import_name_always and node.type in _IMPORTS: 

238 return node 

239 return None 

240 node = node.parent 

241 return None 

242 

243 

244class Literal(PythonLeaf): 

245 __slots__ = () 

246 

247 

248class Number(Literal): 

249 type = 'number' 

250 __slots__ = () 

251 

252 

253class String(Literal): 

254 type = 'string' 

255 __slots__ = () 

256 

257 @property 

258 def string_prefix(self): 

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

260 

261 def _get_payload(self): 

262 match = re.search( 

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

264 self.value, 

265 flags=re.DOTALL 

266 ) 

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

268 

269 

270class FStringString(PythonLeaf): 

271 """ 

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

273 the string parts of f-strings. 

274 """ 

275 type = 'fstring_string' 

276 __slots__ = () 

277 

278 

279class FStringStart(PythonLeaf): 

280 """ 

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

282 the string parts of f-strings. 

283 """ 

284 type = 'fstring_start' 

285 __slots__ = () 

286 

287 

288class FStringEnd(PythonLeaf): 

289 """ 

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

291 the string parts of f-strings. 

292 """ 

293 type = 'fstring_end' 

294 __slots__ = () 

295 

296 

297class _StringComparisonMixin: 

298 __slots__ = () 

299 

300 def __eq__(self, other): 

301 """ 

302 Make comparisons with strings easy. 

303 Improves the readability of the parser. 

304 """ 

305 if isinstance(other, str): 

306 return self.value == other 

307 

308 return self is other 

309 

310 def __hash__(self): 

311 return hash(self.value) 

312 

313 

314class Operator(_LeafWithoutNewlines, _StringComparisonMixin): 

315 type = 'operator' 

316 __slots__ = () 

317 

318 

319class Keyword(_LeafWithoutNewlines, _StringComparisonMixin): 

320 type = 'keyword' 

321 __slots__ = () 

322 

323 

324class Scope(PythonBaseNode, DocstringMixin): 

325 """ 

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

327 text file. 

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

329 """ 

330 __slots__ = () 

331 

332 def __init__(self, children): 

333 super().__init__(children) 

334 

335 def iter_funcdefs(self): 

336 """ 

337 Returns a generator of `funcdef` nodes. 

338 """ 

339 return self._search_in_scope('funcdef') 

340 

341 def iter_classdefs(self): 

342 """ 

343 Returns a generator of `classdef` nodes. 

344 """ 

345 return self._search_in_scope('classdef') 

346 

347 def iter_imports(self): 

348 """ 

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

350 """ 

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

352 

353 def _search_in_scope(self, *names): 

354 def scan(children): 

355 for element in children: 

356 if element.type in names: 

357 yield element 

358 if element.type in _FUNC_CONTAINERS: 

359 yield from scan(element.children) 

360 

361 return scan(self.children) 

362 

363 def get_suite(self): 

364 """ 

365 Returns the part that is executed by the function. 

366 """ 

367 return self.children[-1] 

368 

369 def __repr__(self): 

370 try: 

371 name = self.name.value 

372 except AttributeError: 

373 name = '' 

374 

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

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

377 

378 

379class Module(Scope): 

380 """ 

381 The top scope, which is always a module. 

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

383 of a module. 

384 """ 

385 __slots__ = ('_used_names',) 

386 type = 'file_input' 

387 

388 def __init__(self, children): 

389 super().__init__(children) 

390 self._used_names = None 

391 

392 def _iter_future_import_names(self): 

393 """ 

394 :return: A list of future import names. 

395 :rtype: list of str 

396 """ 

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

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

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

400 # they should use the API. 

401 for imp in self.iter_imports(): 

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

403 for path in imp.get_paths(): 

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

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

406 yield names[1] 

407 

408 def get_used_names(self): 

409 """ 

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

411 includes both definitions and references of names. 

412 """ 

413 if self._used_names is None: 

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

415 dct = {} 

416 

417 def recurse(node): 

418 try: 

419 children = node.children 

420 except AttributeError: 

421 if node.type == 'name': 

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

423 arr.append(node) 

424 else: 

425 for child in children: 

426 recurse(child) 

427 

428 recurse(self) 

429 self._used_names = UsedNamesMapping(dct) 

430 return self._used_names 

431 

432 

433class Decorator(PythonBaseNode): 

434 type = 'decorator' 

435 __slots__ = () 

436 

437 

438class ClassOrFunc(Scope): 

439 __slots__ = () 

440 

441 @property 

442 def name(self): 

443 """ 

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

445 """ 

446 return self.children[1] 

447 

448 def get_decorators(self): 

449 """ 

450 :rtype: list of :class:`Decorator` 

451 """ 

452 decorated = self.parent 

453 if decorated.type == 'async_funcdef': 

454 decorated = decorated.parent 

455 

456 if decorated.type == 'decorated': 

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

458 return decorated.children[0].children 

459 else: 

460 return decorated.children[:1] 

461 else: 

462 return [] 

463 

464 

465class Class(ClassOrFunc): 

466 """ 

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

468 """ 

469 type = 'classdef' 

470 __slots__ = () 

471 

472 def __init__(self, children): 

473 super().__init__(children) 

474 

475 def get_super_arglist(self): 

476 """ 

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

478 None if there are no arguments. 

479 """ 

480 if self.children[2] != '(': # Has no parentheses 

481 return None 

482 else: 

483 if self.children[3] == ')': # Empty parentheses 

484 return None 

485 else: 

486 return self.children[3] 

487 

488 

489def _create_params(parent, argslist_list): 

490 """ 

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

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

493 at most one item). 

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

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

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

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

498 list of Param objects. 

499 """ 

500 try: 

501 first = argslist_list[0] 

502 except IndexError: 

503 return [] 

504 

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

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

507 elif first == '*': 

508 return [first] 

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

510 if first.type == 'tfpdef': 

511 children = [first] 

512 else: 

513 children = first.children 

514 new_children = [] 

515 start = 0 

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

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

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

519 param_children = children[start:end] 

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

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

522 and (len(param_children) == 1 

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

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

525 for p in param_children: 

526 p.parent = parent 

527 new_children += param_children 

528 else: 

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

530 start = end 

531 return new_children 

532 

533 

534class Function(ClassOrFunc): 

535 """ 

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

537 

538 Children:: 

539 

540 0. <Keyword: def> 

541 1. <Name> 

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

543 3. or 5. <Operator: :> 

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

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

546 4. annotation (if present) 

547 """ 

548 type = 'funcdef' 

549 __slots__ = () 

550 

551 def __init__(self, children): 

552 super().__init__(children) 

553 parameters = self.children[2] # After `def foo` 

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

555 # If input parameters list already has Param objects, keep it as is; 

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

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

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

559 

560 def _get_param_nodes(self): 

561 return self.children[2].children 

562 

563 def get_params(self): 

564 """ 

565 Returns a list of `Param()`. 

566 """ 

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

568 

569 @property 

570 def name(self): 

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

572 

573 def iter_yield_exprs(self): 

574 """ 

575 Returns a generator of `yield_expr`. 

576 """ 

577 def scan(children): 

578 for element in children: 

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

580 continue 

581 

582 try: 

583 nested_children = element.children 

584 except AttributeError: 

585 if element.value == 'yield': 

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

587 yield element.parent 

588 else: 

589 yield element 

590 else: 

591 yield from scan(nested_children) 

592 

593 return scan(self.children) 

594 

595 def iter_return_stmts(self): 

596 """ 

597 Returns a generator of `return_stmt`. 

598 """ 

599 def scan(children): 

600 for element in children: 

601 if element.type == 'return_stmt' \ 

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

603 yield element 

604 if element.type in _RETURN_STMT_CONTAINERS: 

605 yield from scan(element.children) 

606 

607 return scan(self.children) 

608 

609 def iter_raise_stmts(self): 

610 """ 

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

612 """ 

613 def scan(children): 

614 for element in children: 

615 if element.type == 'raise_stmt' \ 

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

617 yield element 

618 if element.type in _RETURN_STMT_CONTAINERS: 

619 yield from scan(element.children) 

620 

621 return scan(self.children) 

622 

623 def is_generator(self): 

624 """ 

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

626 """ 

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

628 

629 @property 

630 def annotation(self): 

631 """ 

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

633 """ 

634 try: 

635 if self.children[3] == "->": 

636 return self.children[4] 

637 assert self.children[3] == ":" 

638 return None 

639 except IndexError: 

640 return None 

641 

642 

643class Lambda(Function): 

644 """ 

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

646 

647 Children:: 

648 

649 0. <Keyword: lambda> 

650 *. <Param x> for each argument x 

651 -2. <Operator: :> 

652 -1. Node() representing body 

653 """ 

654 type = 'lambdef' 

655 __slots__ = () 

656 

657 def __init__(self, children): 

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

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

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

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

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

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

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

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

666 

667 @property 

668 def name(self): 

669 """ 

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

671 """ 

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

673 

674 def _get_param_nodes(self): 

675 return self.children[1:-2] 

676 

677 @property 

678 def annotation(self): 

679 """ 

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

681 """ 

682 return None 

683 

684 def __repr__(self): 

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

686 

687 

688class Flow(PythonBaseNode): 

689 __slots__ = () 

690 

691 

692class IfStmt(Flow): 

693 type = 'if_stmt' 

694 __slots__ = () 

695 

696 def get_test_nodes(self): 

697 """ 

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

699 

700 if x: 

701 pass 

702 elif x: 

703 pass 

704 """ 

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

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

707 yield self.children[i + 1] 

708 

709 def get_corresponding_test_node(self, node): 

710 """ 

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

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

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

714 """ 

715 start_pos = node.start_pos 

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

717 if check_node.start_pos < start_pos: 

718 if start_pos < check_node.end_pos: 

719 return None 

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

721 # not in the suite 

722 else: 

723 return check_node 

724 

725 def is_node_after_else(self, node): 

726 """ 

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

728 """ 

729 for c in self.children: 

730 if c == 'else': 

731 if node.start_pos > c.start_pos: 

732 return True 

733 else: 

734 return False 

735 

736 

737class WhileStmt(Flow): 

738 type = 'while_stmt' 

739 __slots__ = () 

740 

741 

742class ForStmt(Flow): 

743 type = 'for_stmt' 

744 __slots__ = () 

745 

746 def get_testlist(self): 

747 """ 

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

749 """ 

750 return self.children[3] 

751 

752 def get_defined_names(self, include_setitem=False): 

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

754 

755 

756class TryStmt(Flow): 

757 type = 'try_stmt' 

758 __slots__ = () 

759 

760 def get_except_clause_tests(self): 

761 """ 

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

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

764 """ 

765 for node in self.children: 

766 if node.type == 'except_clause': 

767 yield node.children[1] 

768 elif node == 'except': 

769 yield None 

770 

771 

772class WithStmt(Flow): 

773 type = 'with_stmt' 

774 __slots__ = () 

775 

776 def get_defined_names(self, include_setitem=False): 

777 """ 

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

779 defined names are set after `as`. 

780 """ 

781 names = [] 

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

783 # Check with items for 'as' names. 

784 if with_item.type == 'with_item': 

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

786 return names 

787 

788 def get_test_node_from_name(self, name): 

789 node = name.search_ancestor("with_item") 

790 if node is None: 

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

792 return node.children[0] 

793 

794 

795class Import(PythonBaseNode): 

796 __slots__ = () 

797 

798 def get_path_for_name(self, name): 

799 """ 

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

801 

802 :return list of Name: 

803 """ 

804 try: 

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

806 name = self._aliases()[name] 

807 except KeyError: 

808 pass 

809 

810 for path in self.get_paths(): 

811 if name in path: 

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

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

814 

815 def is_nested(self): 

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

817 

818 def is_star_import(self): 

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

820 

821 

822class ImportFrom(Import): 

823 type = 'import_from' 

824 __slots__ = () 

825 

826 def get_defined_names(self, include_setitem=False): 

827 """ 

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

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

830 present that name is returned. 

831 """ 

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

833 

834 def _aliases(self): 

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

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

837 if alias is not None) 

838 

839 def get_from_names(self): 

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

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

842 break 

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

844 return n.children[::2] 

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

846 return [] 

847 else: # from x import 

848 return [n] 

849 

850 @property 

851 def level(self): 

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

853 level = 0 

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

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

856 level += len(n.value) 

857 else: 

858 break 

859 return level 

860 

861 def _as_name_tuples(self): 

862 last = self.children[-1] 

863 if last == ')': 

864 last = self.children[-2] 

865 elif last == '*': 

866 return # No names defined directly. 

867 

868 if last.type == 'import_as_names': 

869 as_names = last.children[::2] 

870 else: 

871 as_names = [last] 

872 for as_name in as_names: 

873 if as_name.type == 'name': 

874 yield as_name, None 

875 else: 

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

877 

878 def get_paths(self): 

879 """ 

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

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

882 

883 :return list of list of Name: 

884 """ 

885 dotted = self.get_from_names() 

886 

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

888 return [dotted] 

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

890 

891 

892class ImportName(Import): 

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

894 type = 'import_name' 

895 __slots__ = () 

896 

897 def get_defined_names(self, include_setitem=False): 

898 """ 

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

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

901 present that name is returned. 

902 """ 

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

904 

905 @property 

906 def level(self): 

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

908 return 0 # Obviously 0 for imports without from. 

909 

910 def get_paths(self): 

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

912 

913 def _dotted_as_names(self): 

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

915 dotted_as_names = self.children[1] 

916 if dotted_as_names.type == 'dotted_as_names': 

917 as_names = dotted_as_names.children[::2] 

918 else: 

919 as_names = [dotted_as_names] 

920 

921 for as_name in as_names: 

922 if as_name.type == 'dotted_as_name': 

923 alias = as_name.children[2] 

924 as_name = as_name.children[0] 

925 else: 

926 alias = None 

927 if as_name.type == 'name': 

928 yield [as_name], alias 

929 else: 

930 # dotted_names 

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

932 

933 def is_nested(self): 

934 """ 

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

936 from statement:: 

937 

938 import foo.bar 

939 """ 

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

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

942 

943 def _aliases(self): 

944 """ 

945 :return list of Name: Returns all the alias 

946 """ 

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

948 if alias is not None) 

949 

950 

951class KeywordStatement(PythonBaseNode): 

952 """ 

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

954 `raise`, `return`, `yield`. 

955 

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

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

958 """ 

959 __slots__ = () 

960 

961 @property 

962 def type(self): 

963 """ 

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

965 crosscheck this with the Python grammar. 

966 """ 

967 return '%s_stmt' % self.keyword 

968 

969 @property 

970 def keyword(self): 

971 return self.children[0].value 

972 

973 def get_defined_names(self, include_setitem=False): 

974 keyword = self.keyword 

975 if keyword == 'del': 

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

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

978 return self.children[1::2] 

979 return [] 

980 

981 

982class AssertStmt(KeywordStatement): 

983 __slots__ = () 

984 

985 @property 

986 def assertion(self): 

987 return self.children[1] 

988 

989 

990class GlobalStmt(KeywordStatement): 

991 __slots__ = () 

992 

993 def get_global_names(self): 

994 return self.children[1::2] 

995 

996 

997class ReturnStmt(KeywordStatement): 

998 __slots__ = () 

999 

1000 

1001class YieldExpr(PythonBaseNode): 

1002 type = 'yield_expr' 

1003 __slots__ = () 

1004 

1005 

1006def _defined_names(current, include_setitem): 

1007 """ 

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

1009 list comprehensions. 

1010 """ 

1011 names = [] 

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

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

1014 names += _defined_names(child, include_setitem) 

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

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

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

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

1019 trailer = current.children[-1] 

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

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

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

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

1024 if node.type == 'trailer': 

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

1026 break 

1027 if node.type == 'name': 

1028 names.append(node) 

1029 break 

1030 else: 

1031 names.append(current) 

1032 return names 

1033 

1034 

1035class ExprStmt(PythonBaseNode, DocstringMixin): 

1036 type = 'expr_stmt' 

1037 __slots__ = () 

1038 

1039 def get_defined_names(self, include_setitem=False): 

1040 """ 

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

1042 """ 

1043 names = [] 

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

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

1046 return [ 

1047 name 

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

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

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

1051 ] + names 

1052 

1053 def get_rhs(self): 

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

1055 node = self.children[-1] 

1056 if node.type == 'annassign': 

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

1058 node = node.children[3] 

1059 else: 

1060 node = node.children[1] 

1061 return node 

1062 

1063 def yield_operators(self): 

1064 """ 

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

1066 """ 

1067 first = self.children[1] 

1068 if first.type == 'annassign': 

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

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

1071 

1072 first = first.children[2] 

1073 yield first 

1074 

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

1076 

1077 

1078class NamedExpr(PythonBaseNode): 

1079 type = 'namedexpr_test' 

1080 

1081 def get_defined_names(self, include_setitem=False): 

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

1083 

1084 

1085class Param(PythonBaseNode): 

1086 """ 

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

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

1089 that is not really suited to working with parameters. 

1090 """ 

1091 type = 'param' 

1092 

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

1094 super().__init__(children) 

1095 self.parent = parent 

1096 

1097 @property 

1098 def star_count(self): 

1099 """ 

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

1101 `**foo`. 

1102 """ 

1103 first = self.children[0] 

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

1105 return len(first.value) 

1106 return 0 

1107 

1108 @property 

1109 def default(self): 

1110 """ 

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

1112 case no default is present. 

1113 """ 

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

1115 try: 

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

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

1118 except IndexError: 

1119 return None 

1120 

1121 @property 

1122 def annotation(self): 

1123 """ 

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

1125 no annotation is present. 

1126 """ 

1127 tfpdef = self._tfpdef() 

1128 if tfpdef.type == 'tfpdef': 

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

1130 assert len(tfpdef.children) == 3 

1131 annotation = tfpdef.children[2] 

1132 return annotation 

1133 else: 

1134 return None 

1135 

1136 def _tfpdef(self): 

1137 """ 

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

1139 """ 

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

1141 return self.children[offset] 

1142 

1143 @property 

1144 def name(self): 

1145 """ 

1146 The `Name` leaf of the param. 

1147 """ 

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

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

1150 else: 

1151 return self._tfpdef() 

1152 

1153 def get_defined_names(self, include_setitem=False): 

1154 return [self.name] 

1155 

1156 @property 

1157 def position_index(self): 

1158 """ 

1159 Property for the positional index of a paramter. 

1160 """ 

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

1162 try: 

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

1164 if index > keyword_only_index: 

1165 # Skip the ` *, ` 

1166 index -= 2 

1167 except ValueError: 

1168 pass 

1169 try: 

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

1171 if index > keyword_only_index: 

1172 # Skip the ` /, ` 

1173 index -= 2 

1174 except ValueError: 

1175 pass 

1176 return index - 1 

1177 

1178 def get_parent_function(self): 

1179 """ 

1180 Returns the function/lambda of a parameter. 

1181 """ 

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

1183 

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

1185 """ 

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

1187 `include_comma`. 

1188 

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

1190 """ 

1191 if include_comma: 

1192 return super().get_code(include_prefix) 

1193 

1194 children = self.children 

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

1196 children = children[:-1] 

1197 return self._get_code_for_children( 

1198 children, 

1199 include_prefix=include_prefix 

1200 ) 

1201 

1202 def __repr__(self): 

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

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

1205 

1206 

1207class SyncCompFor(PythonBaseNode): 

1208 type = 'sync_comp_for' 

1209 __slots__ = () 

1210 

1211 def get_defined_names(self, include_setitem=False): 

1212 """ 

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

1214 """ 

1215 # allow async for 

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

1217 

1218 

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

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

1221CompFor = SyncCompFor 

1222 

1223 

1224class UsedNamesMapping(Mapping): 

1225 """ 

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

1227 """ 

1228 def __init__(self, dct): 

1229 self._dict = dct 

1230 

1231 def __getitem__(self, key): 

1232 return self._dict[key] 

1233 

1234 def __len__(self): 

1235 return len(self._dict) 

1236 

1237 def __iter__(self): 

1238 return iter(self._dict) 

1239 

1240 def __hash__(self): 

1241 return id(self) 

1242 

1243 def __eq__(self, other): 

1244 # Comparing these dicts does not make sense. 

1245 return self is other