Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/astroid/rebuilder.py: 46%

776 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:53 +0000

1# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 

2# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE 

3# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt 

4 

5"""This module contains utilities for rebuilding an _ast tree in 

6order to get a single Astroid representation. 

7""" 

8 

9from __future__ import annotations 

10 

11import ast 

12import sys 

13import token 

14from collections.abc import Callable, Generator 

15from io import StringIO 

16from tokenize import TokenInfo, generate_tokens 

17from typing import TYPE_CHECKING, Final, TypeVar, Union, cast, overload 

18 

19from astroid import nodes 

20from astroid._ast import ParserModule, get_parser_module, parse_function_type_comment 

21from astroid.const import IS_PYPY, PY38, PY39_PLUS, Context 

22from astroid.manager import AstroidManager 

23from astroid.nodes import NodeNG 

24from astroid.nodes.utils import Position 

25from astroid.typing import SuccessfulInferenceResult 

26 

27REDIRECT: Final[dict[str, str]] = { 

28 "arguments": "Arguments", 

29 "comprehension": "Comprehension", 

30 "ListCompFor": "Comprehension", 

31 "GenExprFor": "Comprehension", 

32 "excepthandler": "ExceptHandler", 

33 "keyword": "Keyword", 

34 "match_case": "MatchCase", 

35} 

36 

37 

38T_Doc = TypeVar( 

39 "T_Doc", 

40 "ast.Module", 

41 "ast.ClassDef", 

42 Union["ast.FunctionDef", "ast.AsyncFunctionDef"], 

43) 

44_FunctionT = TypeVar("_FunctionT", nodes.FunctionDef, nodes.AsyncFunctionDef) 

45_ForT = TypeVar("_ForT", nodes.For, nodes.AsyncFor) 

46_WithT = TypeVar("_WithT", nodes.With, nodes.AsyncWith) 

47NodesWithDocsType = Union[nodes.Module, nodes.ClassDef, nodes.FunctionDef] 

48 

49 

50# noinspection PyMethodMayBeStatic 

51class TreeRebuilder: 

52 """Rebuilds the _ast tree to become an Astroid tree.""" 

53 

54 def __init__( 

55 self, 

56 manager: AstroidManager, 

57 parser_module: ParserModule | None = None, 

58 data: str | None = None, 

59 ) -> None: 

60 self._manager = manager 

61 self._data = data.split("\n") if data else None 

62 self._global_names: list[dict[str, list[nodes.Global]]] = [] 

63 self._import_from_nodes: list[nodes.ImportFrom] = [] 

64 self._delayed_assattr: list[nodes.AssignAttr] = [] 

65 self._visit_meths: dict[type[ast.AST], Callable[[ast.AST, NodeNG], NodeNG]] = {} 

66 

67 if parser_module is None: 

68 self._parser_module = get_parser_module() 

69 else: 

70 self._parser_module = parser_module 

71 

72 def _get_doc(self, node: T_Doc) -> tuple[T_Doc, ast.Constant | ast.Str | None]: 

73 """Return the doc ast node.""" 

74 try: 

75 if node.body and isinstance(node.body[0], ast.Expr): 

76 first_value = node.body[0].value 

77 if isinstance(first_value, ast.Constant) and isinstance( 

78 first_value.value, str 

79 ): 

80 doc_ast_node = first_value 

81 node.body = node.body[1:] 

82 # The ast parser of python < 3.8 sets col_offset of multi-line strings to -1 

83 # as it is unable to determine the value correctly. We reset this to None. 

84 if doc_ast_node.col_offset == -1: 

85 doc_ast_node.col_offset = None 

86 return node, doc_ast_node 

87 except IndexError: 

88 pass # ast built from scratch 

89 return node, None 

90 

91 def _get_context( 

92 self, 

93 node: ( 

94 ast.Attribute 

95 | ast.List 

96 | ast.Name 

97 | ast.Subscript 

98 | ast.Starred 

99 | ast.Tuple 

100 ), 

101 ) -> Context: 

102 return self._parser_module.context_classes.get(type(node.ctx), Context.Load) 

103 

104 def _get_position_info( 

105 self, 

106 node: ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef, 

107 parent: nodes.ClassDef | nodes.FunctionDef | nodes.AsyncFunctionDef, 

108 ) -> Position | None: 

109 """Return position information for ClassDef and FunctionDef nodes. 

110 

111 In contrast to AST positions, these only include the actual keyword(s) 

112 and the class / function name. 

113 

114 >>> @decorator 

115 >>> async def some_func(var: int) -> None: 

116 >>> ^^^^^^^^^^^^^^^^^^^ 

117 """ 

118 if not self._data: 

119 return None 

120 end_lineno = node.end_lineno 

121 if node.body: 

122 end_lineno = node.body[0].lineno 

123 # pylint: disable-next=unsubscriptable-object 

124 data = "\n".join(self._data[node.lineno - 1 : end_lineno]) 

125 

126 start_token: TokenInfo | None = None 

127 keyword_tokens: tuple[int, ...] = (token.NAME,) 

128 if isinstance(parent, nodes.AsyncFunctionDef): 

129 search_token = "async" 

130 elif isinstance(parent, nodes.FunctionDef): 

131 search_token = "def" 

132 else: 

133 search_token = "class" 

134 

135 for t in generate_tokens(StringIO(data).readline): 

136 if ( 

137 start_token is not None 

138 and t.type == token.NAME 

139 and t.string == node.name 

140 ): 

141 break 

142 if t.type in keyword_tokens: 

143 if t.string == search_token: 

144 start_token = t 

145 continue 

146 if t.string in {"def"}: 

147 continue 

148 start_token = None 

149 else: 

150 return None 

151 

152 return Position( 

153 lineno=node.lineno + start_token.start[0] - 1, 

154 col_offset=start_token.start[1], 

155 end_lineno=node.lineno + t.end[0] - 1, 

156 end_col_offset=t.end[1], 

157 ) 

158 

159 def _reset_end_lineno(self, newnode: nodes.NodeNG) -> None: 

160 """Reset end_lineno and end_col_offset attributes for PyPy 3.8. 

161 

162 For some nodes, these are either set to -1 or only partially assigned. 

163 To keep consistency across astroid and pylint, reset all. 

164 

165 This has been fixed in PyPy 3.9. 

166 For reference, an (incomplete) list of nodes with issues: 

167 - ClassDef - For 

168 - FunctionDef - While 

169 - Call - If 

170 - Decorators - TryExcept 

171 - With - TryFinally 

172 - Assign 

173 """ 

174 newnode.end_lineno = None 

175 newnode.end_col_offset = None 

176 for child_node in newnode.get_children(): 

177 self._reset_end_lineno(child_node) 

178 

179 def visit_module( 

180 self, node: ast.Module, modname: str, modpath: str, package: bool 

181 ) -> nodes.Module: 

182 """Visit a Module node by returning a fresh instance of it. 

183 

184 Note: Method not called by 'visit' 

185 """ 

186 node, doc_ast_node = self._get_doc(node) 

187 newnode = nodes.Module( 

188 name=modname, 

189 file=modpath, 

190 path=[modpath], 

191 package=package, 

192 ) 

193 newnode.postinit( 

194 [self.visit(child, newnode) for child in node.body], 

195 doc_node=self.visit(doc_ast_node, newnode), 

196 ) 

197 if IS_PYPY and PY38: 

198 self._reset_end_lineno(newnode) 

199 return newnode 

200 

201 if TYPE_CHECKING: # noqa: C901 

202 

203 @overload 

204 def visit(self, node: ast.arg, parent: NodeNG) -> nodes.AssignName: 

205 ... 

206 

207 @overload 

208 def visit(self, node: ast.arguments, parent: NodeNG) -> nodes.Arguments: 

209 ... 

210 

211 @overload 

212 def visit(self, node: ast.Assert, parent: NodeNG) -> nodes.Assert: 

213 ... 

214 

215 @overload 

216 def visit( 

217 self, node: ast.AsyncFunctionDef, parent: NodeNG 

218 ) -> nodes.AsyncFunctionDef: 

219 ... 

220 

221 @overload 

222 def visit(self, node: ast.AsyncFor, parent: NodeNG) -> nodes.AsyncFor: 

223 ... 

224 

225 @overload 

226 def visit(self, node: ast.Await, parent: NodeNG) -> nodes.Await: 

227 ... 

228 

229 @overload 

230 def visit(self, node: ast.AsyncWith, parent: NodeNG) -> nodes.AsyncWith: 

231 ... 

232 

233 @overload 

234 def visit(self, node: ast.Assign, parent: NodeNG) -> nodes.Assign: 

235 ... 

236 

237 @overload 

238 def visit(self, node: ast.AnnAssign, parent: NodeNG) -> nodes.AnnAssign: 

239 ... 

240 

241 @overload 

242 def visit(self, node: ast.AugAssign, parent: NodeNG) -> nodes.AugAssign: 

243 ... 

244 

245 @overload 

246 def visit(self, node: ast.BinOp, parent: NodeNG) -> nodes.BinOp: 

247 ... 

248 

249 @overload 

250 def visit(self, node: ast.BoolOp, parent: NodeNG) -> nodes.BoolOp: 

251 ... 

252 

253 @overload 

254 def visit(self, node: ast.Break, parent: NodeNG) -> nodes.Break: 

255 ... 

256 

257 @overload 

258 def visit(self, node: ast.Call, parent: NodeNG) -> nodes.Call: 

259 ... 

260 

261 @overload 

262 def visit(self, node: ast.ClassDef, parent: NodeNG) -> nodes.ClassDef: 

263 ... 

264 

265 @overload 

266 def visit(self, node: ast.Continue, parent: NodeNG) -> nodes.Continue: 

267 ... 

268 

269 @overload 

270 def visit(self, node: ast.Compare, parent: NodeNG) -> nodes.Compare: 

271 ... 

272 

273 @overload 

274 def visit(self, node: ast.comprehension, parent: NodeNG) -> nodes.Comprehension: 

275 ... 

276 

277 @overload 

278 def visit(self, node: ast.Delete, parent: NodeNG) -> nodes.Delete: 

279 ... 

280 

281 @overload 

282 def visit(self, node: ast.Dict, parent: NodeNG) -> nodes.Dict: 

283 ... 

284 

285 @overload 

286 def visit(self, node: ast.DictComp, parent: NodeNG) -> nodes.DictComp: 

287 ... 

288 

289 @overload 

290 def visit(self, node: ast.Expr, parent: NodeNG) -> nodes.Expr: 

291 ... 

292 

293 @overload 

294 def visit(self, node: ast.ExceptHandler, parent: NodeNG) -> nodes.ExceptHandler: 

295 ... 

296 

297 @overload 

298 def visit(self, node: ast.For, parent: NodeNG) -> nodes.For: 

299 ... 

300 

301 @overload 

302 def visit(self, node: ast.ImportFrom, parent: NodeNG) -> nodes.ImportFrom: 

303 ... 

304 

305 @overload 

306 def visit(self, node: ast.FunctionDef, parent: NodeNG) -> nodes.FunctionDef: 

307 ... 

308 

309 @overload 

310 def visit(self, node: ast.GeneratorExp, parent: NodeNG) -> nodes.GeneratorExp: 

311 ... 

312 

313 @overload 

314 def visit(self, node: ast.Attribute, parent: NodeNG) -> nodes.Attribute: 

315 ... 

316 

317 @overload 

318 def visit(self, node: ast.Global, parent: NodeNG) -> nodes.Global: 

319 ... 

320 

321 @overload 

322 def visit(self, node: ast.If, parent: NodeNG) -> nodes.If: 

323 ... 

324 

325 @overload 

326 def visit(self, node: ast.IfExp, parent: NodeNG) -> nodes.IfExp: 

327 ... 

328 

329 @overload 

330 def visit(self, node: ast.Import, parent: NodeNG) -> nodes.Import: 

331 ... 

332 

333 @overload 

334 def visit(self, node: ast.JoinedStr, parent: NodeNG) -> nodes.JoinedStr: 

335 ... 

336 

337 @overload 

338 def visit( 

339 self, node: ast.FormattedValue, parent: NodeNG 

340 ) -> nodes.FormattedValue: 

341 ... 

342 

343 @overload 

344 def visit(self, node: ast.NamedExpr, parent: NodeNG) -> nodes.NamedExpr: 

345 ... 

346 

347 if sys.version_info < (3, 9): 

348 # Not used in Python 3.9+ 

349 @overload 

350 def visit(self, node: ast.ExtSlice, parent: nodes.Subscript) -> nodes.Tuple: 

351 ... 

352 

353 @overload 

354 def visit(self, node: ast.Index, parent: nodes.Subscript) -> NodeNG: 

355 ... 

356 

357 @overload 

358 def visit(self, node: ast.keyword, parent: NodeNG) -> nodes.Keyword: 

359 ... 

360 

361 @overload 

362 def visit(self, node: ast.Lambda, parent: NodeNG) -> nodes.Lambda: 

363 ... 

364 

365 @overload 

366 def visit(self, node: ast.List, parent: NodeNG) -> nodes.List: 

367 ... 

368 

369 @overload 

370 def visit(self, node: ast.ListComp, parent: NodeNG) -> nodes.ListComp: 

371 ... 

372 

373 @overload 

374 def visit( 

375 self, node: ast.Name, parent: NodeNG 

376 ) -> nodes.Name | nodes.Const | nodes.AssignName | nodes.DelName: 

377 ... 

378 

379 @overload 

380 def visit(self, node: ast.Nonlocal, parent: NodeNG) -> nodes.Nonlocal: 

381 ... 

382 

383 @overload 

384 def visit(self, node: ast.Constant, parent: NodeNG) -> nodes.Const: 

385 ... 

386 

387 @overload 

388 def visit(self, node: ast.Pass, parent: NodeNG) -> nodes.Pass: 

389 ... 

390 

391 @overload 

392 def visit(self, node: ast.Raise, parent: NodeNG) -> nodes.Raise: 

393 ... 

394 

395 @overload 

396 def visit(self, node: ast.Return, parent: NodeNG) -> nodes.Return: 

397 ... 

398 

399 @overload 

400 def visit(self, node: ast.Set, parent: NodeNG) -> nodes.Set: 

401 ... 

402 

403 @overload 

404 def visit(self, node: ast.SetComp, parent: NodeNG) -> nodes.SetComp: 

405 ... 

406 

407 @overload 

408 def visit(self, node: ast.Slice, parent: nodes.Subscript) -> nodes.Slice: 

409 ... 

410 

411 @overload 

412 def visit(self, node: ast.Subscript, parent: NodeNG) -> nodes.Subscript: 

413 ... 

414 

415 @overload 

416 def visit(self, node: ast.Starred, parent: NodeNG) -> nodes.Starred: 

417 ... 

418 

419 @overload 

420 def visit( 

421 self, node: ast.Try, parent: NodeNG 

422 ) -> nodes.TryExcept | nodes.TryFinally: 

423 ... 

424 

425 if sys.version_info >= (3, 11): 

426 

427 @overload 

428 def visit(self, node: ast.TryStar, parent: NodeNG) -> nodes.TryStar: 

429 ... 

430 

431 @overload 

432 def visit(self, node: ast.Tuple, parent: NodeNG) -> nodes.Tuple: 

433 ... 

434 

435 @overload 

436 def visit(self, node: ast.UnaryOp, parent: NodeNG) -> nodes.UnaryOp: 

437 ... 

438 

439 @overload 

440 def visit(self, node: ast.While, parent: NodeNG) -> nodes.While: 

441 ... 

442 

443 @overload 

444 def visit(self, node: ast.With, parent: NodeNG) -> nodes.With: 

445 ... 

446 

447 @overload 

448 def visit(self, node: ast.Yield, parent: NodeNG) -> nodes.Yield: 

449 ... 

450 

451 @overload 

452 def visit(self, node: ast.YieldFrom, parent: NodeNG) -> nodes.YieldFrom: 

453 ... 

454 

455 if sys.version_info >= (3, 10): 

456 

457 @overload 

458 def visit(self, node: ast.Match, parent: NodeNG) -> nodes.Match: 

459 ... 

460 

461 @overload 

462 def visit(self, node: ast.match_case, parent: NodeNG) -> nodes.MatchCase: 

463 ... 

464 

465 @overload 

466 def visit(self, node: ast.MatchValue, parent: NodeNG) -> nodes.MatchValue: 

467 ... 

468 

469 @overload 

470 def visit( 

471 self, node: ast.MatchSingleton, parent: NodeNG 

472 ) -> nodes.MatchSingleton: 

473 ... 

474 

475 @overload 

476 def visit( 

477 self, node: ast.MatchSequence, parent: NodeNG 

478 ) -> nodes.MatchSequence: 

479 ... 

480 

481 @overload 

482 def visit( 

483 self, node: ast.MatchMapping, parent: NodeNG 

484 ) -> nodes.MatchMapping: 

485 ... 

486 

487 @overload 

488 def visit(self, node: ast.MatchClass, parent: NodeNG) -> nodes.MatchClass: 

489 ... 

490 

491 @overload 

492 def visit(self, node: ast.MatchStar, parent: NodeNG) -> nodes.MatchStar: 

493 ... 

494 

495 @overload 

496 def visit(self, node: ast.MatchAs, parent: NodeNG) -> nodes.MatchAs: 

497 ... 

498 

499 @overload 

500 def visit(self, node: ast.MatchOr, parent: NodeNG) -> nodes.MatchOr: 

501 ... 

502 

503 @overload 

504 def visit(self, node: ast.pattern, parent: NodeNG) -> nodes.Pattern: 

505 ... 

506 

507 @overload 

508 def visit(self, node: ast.AST, parent: NodeNG) -> NodeNG: 

509 ... 

510 

511 @overload 

512 def visit(self, node: None, parent: NodeNG) -> None: 

513 ... 

514 

515 def visit(self, node: ast.AST | None, parent: NodeNG) -> NodeNG | None: 

516 if node is None: 

517 return None 

518 cls = node.__class__ 

519 if cls in self._visit_meths: 

520 visit_method = self._visit_meths[cls] 

521 else: 

522 cls_name = cls.__name__ 

523 visit_name = "visit_" + REDIRECT.get(cls_name, cls_name).lower() 

524 visit_method = getattr(self, visit_name) 

525 self._visit_meths[cls] = visit_method 

526 return visit_method(node, parent) 

527 

528 def _save_assignment(self, node: nodes.AssignName | nodes.DelName) -> None: 

529 """Save assignment situation since node.parent is not available yet.""" 

530 if self._global_names and node.name in self._global_names[-1]: 

531 node.root().set_local(node.name, node) 

532 else: 

533 assert node.parent 

534 assert node.name 

535 node.parent.set_local(node.name, node) 

536 

537 def visit_arg(self, node: ast.arg, parent: NodeNG) -> nodes.AssignName: 

538 """Visit an arg node by returning a fresh AssName instance.""" 

539 return self.visit_assignname(node, parent, node.arg) 

540 

541 def visit_arguments(self, node: ast.arguments, parent: NodeNG) -> nodes.Arguments: 

542 """Visit an Arguments node by returning a fresh instance of it.""" 

543 vararg: str | None = None 

544 kwarg: str | None = None 

545 newnode = nodes.Arguments( 

546 node.vararg.arg if node.vararg else None, 

547 node.kwarg.arg if node.kwarg else None, 

548 parent, 

549 ) 

550 args = [self.visit(child, newnode) for child in node.args] 

551 defaults = [self.visit(child, newnode) for child in node.defaults] 

552 varargannotation: NodeNG | None = None 

553 kwargannotation: NodeNG | None = None 

554 if node.vararg: 

555 vararg = node.vararg.arg 

556 varargannotation = self.visit(node.vararg.annotation, newnode) 

557 if node.kwarg: 

558 kwarg = node.kwarg.arg 

559 kwargannotation = self.visit(node.kwarg.annotation, newnode) 

560 

561 if PY38: 

562 # In Python 3.8 'end_lineno' and 'end_col_offset' 

563 # for 'kwonlyargs' don't include the annotation. 

564 for arg in node.kwonlyargs: 

565 if arg.annotation is not None: 

566 arg.end_lineno = arg.annotation.end_lineno 

567 arg.end_col_offset = arg.annotation.end_col_offset 

568 

569 kwonlyargs = [self.visit(child, newnode) for child in node.kwonlyargs] 

570 kw_defaults = [self.visit(child, newnode) for child in node.kw_defaults] 

571 annotations = [self.visit(arg.annotation, newnode) for arg in node.args] 

572 kwonlyargs_annotations = [ 

573 self.visit(arg.annotation, newnode) for arg in node.kwonlyargs 

574 ] 

575 

576 posonlyargs = [self.visit(child, newnode) for child in node.posonlyargs] 

577 posonlyargs_annotations = [ 

578 self.visit(arg.annotation, newnode) for arg in node.posonlyargs 

579 ] 

580 type_comment_args = [ 

581 self.check_type_comment(child, parent=newnode) for child in node.args 

582 ] 

583 type_comment_kwonlyargs = [ 

584 self.check_type_comment(child, parent=newnode) for child in node.kwonlyargs 

585 ] 

586 type_comment_posonlyargs = [ 

587 self.check_type_comment(child, parent=newnode) for child in node.posonlyargs 

588 ] 

589 

590 newnode.postinit( 

591 args=args, 

592 defaults=defaults, 

593 kwonlyargs=kwonlyargs, 

594 posonlyargs=posonlyargs, 

595 kw_defaults=kw_defaults, 

596 annotations=annotations, 

597 kwonlyargs_annotations=kwonlyargs_annotations, 

598 posonlyargs_annotations=posonlyargs_annotations, 

599 varargannotation=varargannotation, 

600 kwargannotation=kwargannotation, 

601 type_comment_args=type_comment_args, 

602 type_comment_kwonlyargs=type_comment_kwonlyargs, 

603 type_comment_posonlyargs=type_comment_posonlyargs, 

604 ) 

605 # save argument names in locals: 

606 assert newnode.parent 

607 if vararg: 

608 newnode.parent.set_local(vararg, newnode) 

609 if kwarg: 

610 newnode.parent.set_local(kwarg, newnode) 

611 return newnode 

612 

613 def visit_assert(self, node: ast.Assert, parent: NodeNG) -> nodes.Assert: 

614 """Visit a Assert node by returning a fresh instance of it.""" 

615 newnode = nodes.Assert( 

616 lineno=node.lineno, 

617 col_offset=node.col_offset, 

618 end_lineno=node.end_lineno, 

619 end_col_offset=node.end_col_offset, 

620 parent=parent, 

621 ) 

622 msg: NodeNG | None = None 

623 if node.msg: 

624 msg = self.visit(node.msg, newnode) 

625 newnode.postinit(self.visit(node.test, newnode), msg) 

626 return newnode 

627 

628 def check_type_comment( 

629 self, 

630 node: ( 

631 ast.Assign | ast.arg | ast.For | ast.AsyncFor | ast.With | ast.AsyncWith 

632 ), 

633 parent: ( 

634 nodes.Assign 

635 | nodes.Arguments 

636 | nodes.For 

637 | nodes.AsyncFor 

638 | nodes.With 

639 | nodes.AsyncWith 

640 ), 

641 ) -> NodeNG | None: 

642 if not node.type_comment: 

643 return None 

644 

645 try: 

646 type_comment_ast = self._parser_module.parse(node.type_comment) 

647 except SyntaxError: 

648 # Invalid type comment, just skip it. 

649 return None 

650 

651 # For '# type: # any comment' ast.parse returns a Module node, 

652 # without any nodes in the body. 

653 if not type_comment_ast.body: 

654 return None 

655 

656 type_object = self.visit(type_comment_ast.body[0], parent=parent) 

657 if not isinstance(type_object, nodes.Expr): 

658 return None 

659 

660 return type_object.value 

661 

662 def check_function_type_comment( 

663 self, node: ast.FunctionDef | ast.AsyncFunctionDef, parent: NodeNG 

664 ) -> tuple[NodeNG | None, list[NodeNG]] | None: 

665 if not node.type_comment: 

666 return None 

667 

668 try: 

669 type_comment_ast = parse_function_type_comment(node.type_comment) 

670 except SyntaxError: 

671 # Invalid type comment, just skip it. 

672 return None 

673 

674 if not type_comment_ast: 

675 return None 

676 

677 returns: NodeNG | None = None 

678 argtypes: list[NodeNG] = [ 

679 self.visit(elem, parent) for elem in (type_comment_ast.argtypes or []) 

680 ] 

681 if type_comment_ast.returns: 

682 returns = self.visit(type_comment_ast.returns, parent) 

683 

684 return returns, argtypes 

685 

686 def visit_asyncfunctiondef( 

687 self, node: ast.AsyncFunctionDef, parent: NodeNG 

688 ) -> nodes.AsyncFunctionDef: 

689 return self._visit_functiondef(nodes.AsyncFunctionDef, node, parent) 

690 

691 def visit_asyncfor(self, node: ast.AsyncFor, parent: NodeNG) -> nodes.AsyncFor: 

692 return self._visit_for(nodes.AsyncFor, node, parent) 

693 

694 def visit_await(self, node: ast.Await, parent: NodeNG) -> nodes.Await: 

695 newnode = nodes.Await( 

696 lineno=node.lineno, 

697 col_offset=node.col_offset, 

698 end_lineno=node.end_lineno, 

699 end_col_offset=node.end_col_offset, 

700 parent=parent, 

701 ) 

702 newnode.postinit(value=self.visit(node.value, newnode)) 

703 return newnode 

704 

705 def visit_asyncwith(self, node: ast.AsyncWith, parent: NodeNG) -> nodes.AsyncWith: 

706 return self._visit_with(nodes.AsyncWith, node, parent) 

707 

708 def visit_assign(self, node: ast.Assign, parent: NodeNG) -> nodes.Assign: 

709 """Visit a Assign node by returning a fresh instance of it.""" 

710 newnode = nodes.Assign( 

711 lineno=node.lineno, 

712 col_offset=node.col_offset, 

713 end_lineno=node.end_lineno, 

714 end_col_offset=node.end_col_offset, 

715 parent=parent, 

716 ) 

717 type_annotation = self.check_type_comment(node, parent=newnode) 

718 newnode.postinit( 

719 targets=[self.visit(child, newnode) for child in node.targets], 

720 value=self.visit(node.value, newnode), 

721 type_annotation=type_annotation, 

722 ) 

723 return newnode 

724 

725 def visit_annassign(self, node: ast.AnnAssign, parent: NodeNG) -> nodes.AnnAssign: 

726 """Visit an AnnAssign node by returning a fresh instance of it.""" 

727 newnode = nodes.AnnAssign( 

728 lineno=node.lineno, 

729 col_offset=node.col_offset, 

730 end_lineno=node.end_lineno, 

731 end_col_offset=node.end_col_offset, 

732 parent=parent, 

733 ) 

734 newnode.postinit( 

735 target=self.visit(node.target, newnode), 

736 annotation=self.visit(node.annotation, newnode), 

737 simple=node.simple, 

738 value=self.visit(node.value, newnode), 

739 ) 

740 return newnode 

741 

742 @overload 

743 def visit_assignname( 

744 self, node: ast.AST, parent: NodeNG, node_name: str 

745 ) -> nodes.AssignName: 

746 ... 

747 

748 @overload 

749 def visit_assignname(self, node: ast.AST, parent: NodeNG, node_name: None) -> None: 

750 ... 

751 

752 def visit_assignname( 

753 self, node: ast.AST, parent: NodeNG, node_name: str | None 

754 ) -> nodes.AssignName | None: 

755 """Visit a node and return a AssignName node. 

756 

757 Note: Method not called by 'visit' 

758 """ 

759 if node_name is None: 

760 return None 

761 newnode = nodes.AssignName( 

762 name=node_name, 

763 lineno=node.lineno, 

764 col_offset=node.col_offset, 

765 end_lineno=node.end_lineno, 

766 end_col_offset=node.end_col_offset, 

767 parent=parent, 

768 ) 

769 self._save_assignment(newnode) 

770 return newnode 

771 

772 def visit_augassign(self, node: ast.AugAssign, parent: NodeNG) -> nodes.AugAssign: 

773 """Visit a AugAssign node by returning a fresh instance of it.""" 

774 newnode = nodes.AugAssign( 

775 op=self._parser_module.bin_op_classes[type(node.op)] + "=", 

776 lineno=node.lineno, 

777 col_offset=node.col_offset, 

778 end_lineno=node.end_lineno, 

779 end_col_offset=node.end_col_offset, 

780 parent=parent, 

781 ) 

782 newnode.postinit( 

783 self.visit(node.target, newnode), self.visit(node.value, newnode) 

784 ) 

785 return newnode 

786 

787 def visit_binop(self, node: ast.BinOp, parent: NodeNG) -> nodes.BinOp: 

788 """Visit a BinOp node by returning a fresh instance of it.""" 

789 newnode = nodes.BinOp( 

790 op=self._parser_module.bin_op_classes[type(node.op)], 

791 lineno=node.lineno, 

792 col_offset=node.col_offset, 

793 end_lineno=node.end_lineno, 

794 end_col_offset=node.end_col_offset, 

795 parent=parent, 

796 ) 

797 newnode.postinit( 

798 self.visit(node.left, newnode), self.visit(node.right, newnode) 

799 ) 

800 return newnode 

801 

802 def visit_boolop(self, node: ast.BoolOp, parent: NodeNG) -> nodes.BoolOp: 

803 """Visit a BoolOp node by returning a fresh instance of it.""" 

804 newnode = nodes.BoolOp( 

805 op=self._parser_module.bool_op_classes[type(node.op)], 

806 lineno=node.lineno, 

807 col_offset=node.col_offset, 

808 end_lineno=node.end_lineno, 

809 end_col_offset=node.end_col_offset, 

810 parent=parent, 

811 ) 

812 newnode.postinit([self.visit(child, newnode) for child in node.values]) 

813 return newnode 

814 

815 def visit_break(self, node: ast.Break, parent: NodeNG) -> nodes.Break: 

816 """Visit a Break node by returning a fresh instance of it.""" 

817 return nodes.Break( 

818 lineno=node.lineno, 

819 col_offset=node.col_offset, 

820 end_lineno=node.end_lineno, 

821 end_col_offset=node.end_col_offset, 

822 parent=parent, 

823 ) 

824 

825 def visit_call(self, node: ast.Call, parent: NodeNG) -> nodes.Call: 

826 """Visit a CallFunc node by returning a fresh instance of it.""" 

827 newnode = nodes.Call( 

828 lineno=node.lineno, 

829 col_offset=node.col_offset, 

830 end_lineno=node.end_lineno, 

831 end_col_offset=node.end_col_offset, 

832 parent=parent, 

833 ) 

834 newnode.postinit( 

835 func=self.visit(node.func, newnode), 

836 args=[self.visit(child, newnode) for child in node.args], 

837 keywords=[self.visit(child, newnode) for child in node.keywords], 

838 ) 

839 return newnode 

840 

841 def visit_classdef( 

842 self, node: ast.ClassDef, parent: NodeNG, newstyle: bool = True 

843 ) -> nodes.ClassDef: 

844 """Visit a ClassDef node to become astroid.""" 

845 node, doc_ast_node = self._get_doc(node) 

846 newnode = nodes.ClassDef( 

847 name=node.name, 

848 lineno=node.lineno, 

849 col_offset=node.col_offset, 

850 end_lineno=node.end_lineno, 

851 end_col_offset=node.end_col_offset, 

852 parent=parent, 

853 ) 

854 metaclass = None 

855 for keyword in node.keywords: 

856 if keyword.arg == "metaclass": 

857 metaclass = self.visit(keyword, newnode).value 

858 break 

859 decorators = self.visit_decorators(node, newnode) 

860 newnode.postinit( 

861 [self.visit(child, newnode) for child in node.bases], 

862 [self.visit(child, newnode) for child in node.body], 

863 decorators, 

864 newstyle, 

865 metaclass, 

866 [ 

867 self.visit(kwd, newnode) 

868 for kwd in node.keywords 

869 if kwd.arg != "metaclass" 

870 ], 

871 position=self._get_position_info(node, newnode), 

872 doc_node=self.visit(doc_ast_node, newnode), 

873 ) 

874 return newnode 

875 

876 def visit_continue(self, node: ast.Continue, parent: NodeNG) -> nodes.Continue: 

877 """Visit a Continue node by returning a fresh instance of it.""" 

878 return nodes.Continue( 

879 lineno=node.lineno, 

880 col_offset=node.col_offset, 

881 end_lineno=node.end_lineno, 

882 end_col_offset=node.end_col_offset, 

883 parent=parent, 

884 ) 

885 

886 def visit_compare(self, node: ast.Compare, parent: NodeNG) -> nodes.Compare: 

887 """Visit a Compare node by returning a fresh instance of it.""" 

888 newnode = nodes.Compare( 

889 lineno=node.lineno, 

890 col_offset=node.col_offset, 

891 end_lineno=node.end_lineno, 

892 end_col_offset=node.end_col_offset, 

893 parent=parent, 

894 ) 

895 newnode.postinit( 

896 self.visit(node.left, newnode), 

897 [ 

898 ( 

899 self._parser_module.cmp_op_classes[op.__class__], 

900 self.visit(expr, newnode), 

901 ) 

902 for (op, expr) in zip(node.ops, node.comparators) 

903 ], 

904 ) 

905 return newnode 

906 

907 def visit_comprehension( 

908 self, node: ast.comprehension, parent: NodeNG 

909 ) -> nodes.Comprehension: 

910 """Visit a Comprehension node by returning a fresh instance of it.""" 

911 newnode = nodes.Comprehension( 

912 parent=parent, 

913 # Comprehension nodes don't have these attributes 

914 # see https://docs.python.org/3/library/ast.html#abstract-grammar 

915 lineno=None, 

916 col_offset=None, 

917 end_lineno=None, 

918 end_col_offset=None, 

919 ) 

920 newnode.postinit( 

921 self.visit(node.target, newnode), 

922 self.visit(node.iter, newnode), 

923 [self.visit(child, newnode) for child in node.ifs], 

924 bool(node.is_async), 

925 ) 

926 return newnode 

927 

928 def visit_decorators( 

929 self, 

930 node: ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef, 

931 parent: NodeNG, 

932 ) -> nodes.Decorators | None: 

933 """Visit a Decorators node by returning a fresh instance of it. 

934 

935 Note: Method not called by 'visit' 

936 """ 

937 if not node.decorator_list: 

938 return None 

939 # /!\ node is actually an _ast.FunctionDef node while 

940 # parent is an astroid.nodes.FunctionDef node 

941 

942 # Set the line number of the first decorator for Python 3.8+. 

943 lineno = node.decorator_list[0].lineno 

944 end_lineno = node.decorator_list[-1].end_lineno 

945 end_col_offset = node.decorator_list[-1].end_col_offset 

946 

947 newnode = nodes.Decorators( 

948 lineno=lineno, 

949 col_offset=node.col_offset, 

950 end_lineno=end_lineno, 

951 end_col_offset=end_col_offset, 

952 parent=parent, 

953 ) 

954 newnode.postinit([self.visit(child, newnode) for child in node.decorator_list]) 

955 return newnode 

956 

957 def visit_delete(self, node: ast.Delete, parent: NodeNG) -> nodes.Delete: 

958 """Visit a Delete node by returning a fresh instance of it.""" 

959 newnode = nodes.Delete( 

960 lineno=node.lineno, 

961 col_offset=node.col_offset, 

962 end_lineno=node.end_lineno, 

963 end_col_offset=node.end_col_offset, 

964 parent=parent, 

965 ) 

966 newnode.postinit([self.visit(child, newnode) for child in node.targets]) 

967 return newnode 

968 

969 def _visit_dict_items( 

970 self, node: ast.Dict, parent: NodeNG, newnode: nodes.Dict 

971 ) -> Generator[tuple[NodeNG, NodeNG], None, None]: 

972 for key, value in zip(node.keys, node.values): 

973 rebuilt_key: NodeNG 

974 rebuilt_value = self.visit(value, newnode) 

975 if not key: 

976 # Extended unpacking 

977 rebuilt_key = nodes.DictUnpack( 

978 lineno=rebuilt_value.lineno, 

979 col_offset=rebuilt_value.col_offset, 

980 end_lineno=rebuilt_value.end_lineno, 

981 end_col_offset=rebuilt_value.end_col_offset, 

982 parent=parent, 

983 ) 

984 else: 

985 rebuilt_key = self.visit(key, newnode) 

986 yield rebuilt_key, rebuilt_value 

987 

988 def visit_dict(self, node: ast.Dict, parent: NodeNG) -> nodes.Dict: 

989 """Visit a Dict node by returning a fresh instance of it.""" 

990 newnode = nodes.Dict( 

991 lineno=node.lineno, 

992 col_offset=node.col_offset, 

993 end_lineno=node.end_lineno, 

994 end_col_offset=node.end_col_offset, 

995 parent=parent, 

996 ) 

997 items: list[tuple[SuccessfulInferenceResult, SuccessfulInferenceResult]] = list( 

998 self._visit_dict_items(node, parent, newnode) 

999 ) 

1000 newnode.postinit(items) 

1001 return newnode 

1002 

1003 def visit_dictcomp(self, node: ast.DictComp, parent: NodeNG) -> nodes.DictComp: 

1004 """Visit a DictComp node by returning a fresh instance of it.""" 

1005 newnode = nodes.DictComp( 

1006 lineno=node.lineno, 

1007 col_offset=node.col_offset, 

1008 end_lineno=node.end_lineno, 

1009 end_col_offset=node.end_col_offset, 

1010 parent=parent, 

1011 ) 

1012 newnode.postinit( 

1013 self.visit(node.key, newnode), 

1014 self.visit(node.value, newnode), 

1015 [self.visit(child, newnode) for child in node.generators], 

1016 ) 

1017 return newnode 

1018 

1019 def visit_expr(self, node: ast.Expr, parent: NodeNG) -> nodes.Expr: 

1020 """Visit a Expr node by returning a fresh instance of it.""" 

1021 newnode = nodes.Expr( 

1022 lineno=node.lineno, 

1023 col_offset=node.col_offset, 

1024 end_lineno=node.end_lineno, 

1025 end_col_offset=node.end_col_offset, 

1026 parent=parent, 

1027 ) 

1028 newnode.postinit(self.visit(node.value, newnode)) 

1029 return newnode 

1030 

1031 def visit_excepthandler( 

1032 self, node: ast.ExceptHandler, parent: NodeNG 

1033 ) -> nodes.ExceptHandler: 

1034 """Visit an ExceptHandler node by returning a fresh instance of it.""" 

1035 newnode = nodes.ExceptHandler( 

1036 lineno=node.lineno, 

1037 col_offset=node.col_offset, 

1038 end_lineno=node.end_lineno, 

1039 end_col_offset=node.end_col_offset, 

1040 parent=parent, 

1041 ) 

1042 newnode.postinit( 

1043 self.visit(node.type, newnode), 

1044 self.visit_assignname(node, newnode, node.name), 

1045 [self.visit(child, newnode) for child in node.body], 

1046 ) 

1047 return newnode 

1048 

1049 @overload 

1050 def _visit_for( 

1051 self, cls: type[nodes.For], node: ast.For, parent: NodeNG 

1052 ) -> nodes.For: 

1053 ... 

1054 

1055 @overload 

1056 def _visit_for( 

1057 self, cls: type[nodes.AsyncFor], node: ast.AsyncFor, parent: NodeNG 

1058 ) -> nodes.AsyncFor: 

1059 ... 

1060 

1061 def _visit_for( 

1062 self, cls: type[_ForT], node: ast.For | ast.AsyncFor, parent: NodeNG 

1063 ) -> _ForT: 

1064 """Visit a For node by returning a fresh instance of it.""" 

1065 col_offset = node.col_offset 

1066 if IS_PYPY and not PY39_PLUS and isinstance(node, ast.AsyncFor) and self._data: 

1067 # pylint: disable-next=unsubscriptable-object 

1068 col_offset = self._data[node.lineno - 1].index("async") 

1069 

1070 newnode = cls( 

1071 lineno=node.lineno, 

1072 col_offset=col_offset, 

1073 end_lineno=node.end_lineno, 

1074 end_col_offset=node.end_col_offset, 

1075 parent=parent, 

1076 ) 

1077 type_annotation = self.check_type_comment(node, parent=newnode) 

1078 newnode.postinit( 

1079 target=self.visit(node.target, newnode), 

1080 iter=self.visit(node.iter, newnode), 

1081 body=[self.visit(child, newnode) for child in node.body], 

1082 orelse=[self.visit(child, newnode) for child in node.orelse], 

1083 type_annotation=type_annotation, 

1084 ) 

1085 return newnode 

1086 

1087 def visit_for(self, node: ast.For, parent: NodeNG) -> nodes.For: 

1088 return self._visit_for(nodes.For, node, parent) 

1089 

1090 def visit_importfrom( 

1091 self, node: ast.ImportFrom, parent: NodeNG 

1092 ) -> nodes.ImportFrom: 

1093 """Visit an ImportFrom node by returning a fresh instance of it.""" 

1094 names = [(alias.name, alias.asname) for alias in node.names] 

1095 newnode = nodes.ImportFrom( 

1096 fromname=node.module or "", 

1097 names=names, 

1098 level=node.level or None, 

1099 lineno=node.lineno, 

1100 col_offset=node.col_offset, 

1101 end_lineno=node.end_lineno, 

1102 end_col_offset=node.end_col_offset, 

1103 parent=parent, 

1104 ) 

1105 # store From names to add them to locals after building 

1106 self._import_from_nodes.append(newnode) 

1107 return newnode 

1108 

1109 @overload 

1110 def _visit_functiondef( 

1111 self, cls: type[nodes.FunctionDef], node: ast.FunctionDef, parent: NodeNG 

1112 ) -> nodes.FunctionDef: 

1113 ... 

1114 

1115 @overload 

1116 def _visit_functiondef( 

1117 self, 

1118 cls: type[nodes.AsyncFunctionDef], 

1119 node: ast.AsyncFunctionDef, 

1120 parent: NodeNG, 

1121 ) -> nodes.AsyncFunctionDef: 

1122 ... 

1123 

1124 def _visit_functiondef( 

1125 self, 

1126 cls: type[_FunctionT], 

1127 node: ast.FunctionDef | ast.AsyncFunctionDef, 

1128 parent: NodeNG, 

1129 ) -> _FunctionT: 

1130 """Visit an FunctionDef node to become astroid.""" 

1131 self._global_names.append({}) 

1132 node, doc_ast_node = self._get_doc(node) 

1133 

1134 lineno = node.lineno 

1135 if node.decorator_list: 

1136 # Python 3.8 sets the line number of a decorated function 

1137 # to be the actual line number of the function, but the 

1138 # previous versions expected the decorator's line number instead. 

1139 # We reset the function's line number to that of the 

1140 # first decorator to maintain backward compatibility. 

1141 # It's not ideal but this discrepancy was baked into 

1142 # the framework for *years*. 

1143 lineno = node.decorator_list[0].lineno 

1144 

1145 newnode = cls( 

1146 name=node.name, 

1147 lineno=lineno, 

1148 col_offset=node.col_offset, 

1149 end_lineno=node.end_lineno, 

1150 end_col_offset=node.end_col_offset, 

1151 parent=parent, 

1152 ) 

1153 decorators = self.visit_decorators(node, newnode) 

1154 returns: NodeNG | None 

1155 if node.returns: 

1156 returns = self.visit(node.returns, newnode) 

1157 else: 

1158 returns = None 

1159 

1160 type_comment_args = type_comment_returns = None 

1161 type_comment_annotation = self.check_function_type_comment(node, newnode) 

1162 if type_comment_annotation: 

1163 type_comment_returns, type_comment_args = type_comment_annotation 

1164 newnode.postinit( 

1165 args=self.visit(node.args, newnode), 

1166 body=[self.visit(child, newnode) for child in node.body], 

1167 decorators=decorators, 

1168 returns=returns, 

1169 type_comment_returns=type_comment_returns, 

1170 type_comment_args=type_comment_args, 

1171 position=self._get_position_info(node, newnode), 

1172 doc_node=self.visit(doc_ast_node, newnode), 

1173 ) 

1174 self._global_names.pop() 

1175 return newnode 

1176 

1177 def visit_functiondef( 

1178 self, node: ast.FunctionDef, parent: NodeNG 

1179 ) -> nodes.FunctionDef: 

1180 return self._visit_functiondef(nodes.FunctionDef, node, parent) 

1181 

1182 def visit_generatorexp( 

1183 self, node: ast.GeneratorExp, parent: NodeNG 

1184 ) -> nodes.GeneratorExp: 

1185 """Visit a GeneratorExp node by returning a fresh instance of it.""" 

1186 newnode = nodes.GeneratorExp( 

1187 lineno=node.lineno, 

1188 col_offset=node.col_offset, 

1189 end_lineno=node.end_lineno, 

1190 end_col_offset=node.end_col_offset, 

1191 parent=parent, 

1192 ) 

1193 newnode.postinit( 

1194 self.visit(node.elt, newnode), 

1195 [self.visit(child, newnode) for child in node.generators], 

1196 ) 

1197 return newnode 

1198 

1199 def visit_attribute( 

1200 self, node: ast.Attribute, parent: NodeNG 

1201 ) -> nodes.Attribute | nodes.AssignAttr | nodes.DelAttr: 

1202 """Visit an Attribute node by returning a fresh instance of it.""" 

1203 context = self._get_context(node) 

1204 newnode: nodes.Attribute | nodes.AssignAttr | nodes.DelAttr 

1205 if context == Context.Del: 

1206 # FIXME : maybe we should reintroduce and visit_delattr ? 

1207 # for instance, deactivating assign_ctx 

1208 newnode = nodes.DelAttr( 

1209 attrname=node.attr, 

1210 lineno=node.lineno, 

1211 col_offset=node.col_offset, 

1212 end_lineno=node.end_lineno, 

1213 end_col_offset=node.end_col_offset, 

1214 parent=parent, 

1215 ) 

1216 elif context == Context.Store: 

1217 newnode = nodes.AssignAttr( 

1218 attrname=node.attr, 

1219 lineno=node.lineno, 

1220 col_offset=node.col_offset, 

1221 end_lineno=node.end_lineno, 

1222 end_col_offset=node.end_col_offset, 

1223 parent=parent, 

1224 ) 

1225 # Prohibit a local save if we are in an ExceptHandler. 

1226 if not isinstance(parent, nodes.ExceptHandler): 

1227 # mypy doesn't recognize that newnode has to be AssignAttr because it 

1228 # doesn't support ParamSpec 

1229 # See https://github.com/python/mypy/issues/8645 

1230 self._delayed_assattr.append(newnode) # type: ignore[arg-type] 

1231 else: 

1232 newnode = nodes.Attribute( 

1233 attrname=node.attr, 

1234 lineno=node.lineno, 

1235 col_offset=node.col_offset, 

1236 end_lineno=node.end_lineno, 

1237 end_col_offset=node.end_col_offset, 

1238 parent=parent, 

1239 ) 

1240 newnode.postinit(self.visit(node.value, newnode)) 

1241 return newnode 

1242 

1243 def visit_global(self, node: ast.Global, parent: NodeNG) -> nodes.Global: 

1244 """Visit a Global node to become astroid.""" 

1245 newnode = nodes.Global( 

1246 names=node.names, 

1247 lineno=node.lineno, 

1248 col_offset=node.col_offset, 

1249 end_lineno=node.end_lineno, 

1250 end_col_offset=node.end_col_offset, 

1251 parent=parent, 

1252 ) 

1253 if self._global_names: # global at the module level, no effect 

1254 for name in node.names: 

1255 self._global_names[-1].setdefault(name, []).append(newnode) 

1256 return newnode 

1257 

1258 def visit_if(self, node: ast.If, parent: NodeNG) -> nodes.If: 

1259 """Visit an If node by returning a fresh instance of it.""" 

1260 newnode = nodes.If( 

1261 lineno=node.lineno, 

1262 col_offset=node.col_offset, 

1263 end_lineno=node.end_lineno, 

1264 end_col_offset=node.end_col_offset, 

1265 parent=parent, 

1266 ) 

1267 newnode.postinit( 

1268 self.visit(node.test, newnode), 

1269 [self.visit(child, newnode) for child in node.body], 

1270 [self.visit(child, newnode) for child in node.orelse], 

1271 ) 

1272 return newnode 

1273 

1274 def visit_ifexp(self, node: ast.IfExp, parent: NodeNG) -> nodes.IfExp: 

1275 """Visit a IfExp node by returning a fresh instance of it.""" 

1276 newnode = nodes.IfExp( 

1277 lineno=node.lineno, 

1278 col_offset=node.col_offset, 

1279 end_lineno=node.end_lineno, 

1280 end_col_offset=node.end_col_offset, 

1281 parent=parent, 

1282 ) 

1283 newnode.postinit( 

1284 self.visit(node.test, newnode), 

1285 self.visit(node.body, newnode), 

1286 self.visit(node.orelse, newnode), 

1287 ) 

1288 return newnode 

1289 

1290 def visit_import(self, node: ast.Import, parent: NodeNG) -> nodes.Import: 

1291 """Visit a Import node by returning a fresh instance of it.""" 

1292 names = [(alias.name, alias.asname) for alias in node.names] 

1293 newnode = nodes.Import( 

1294 names=names, 

1295 lineno=node.lineno, 

1296 col_offset=node.col_offset, 

1297 end_lineno=node.end_lineno, 

1298 end_col_offset=node.end_col_offset, 

1299 parent=parent, 

1300 ) 

1301 # save import names in parent's locals: 

1302 for name, asname in newnode.names: 

1303 name = asname or name 

1304 parent.set_local(name.split(".")[0], newnode) 

1305 return newnode 

1306 

1307 def visit_joinedstr(self, node: ast.JoinedStr, parent: NodeNG) -> nodes.JoinedStr: 

1308 newnode = nodes.JoinedStr( 

1309 lineno=node.lineno, 

1310 col_offset=node.col_offset, 

1311 end_lineno=node.end_lineno, 

1312 end_col_offset=node.end_col_offset, 

1313 parent=parent, 

1314 ) 

1315 newnode.postinit([self.visit(child, newnode) for child in node.values]) 

1316 return newnode 

1317 

1318 def visit_formattedvalue( 

1319 self, node: ast.FormattedValue, parent: NodeNG 

1320 ) -> nodes.FormattedValue: 

1321 newnode = nodes.FormattedValue( 

1322 lineno=node.lineno, 

1323 col_offset=node.col_offset, 

1324 end_lineno=node.end_lineno, 

1325 end_col_offset=node.end_col_offset, 

1326 parent=parent, 

1327 ) 

1328 newnode.postinit( 

1329 value=self.visit(node.value, newnode), 

1330 conversion=node.conversion, 

1331 format_spec=self.visit(node.format_spec, newnode), 

1332 ) 

1333 return newnode 

1334 

1335 def visit_namedexpr(self, node: ast.NamedExpr, parent: NodeNG) -> nodes.NamedExpr: 

1336 newnode = nodes.NamedExpr( 

1337 lineno=node.lineno, 

1338 col_offset=node.col_offset, 

1339 end_lineno=node.end_lineno, 

1340 end_col_offset=node.end_col_offset, 

1341 parent=parent, 

1342 ) 

1343 newnode.postinit( 

1344 self.visit(node.target, newnode), self.visit(node.value, newnode) 

1345 ) 

1346 return newnode 

1347 

1348 if sys.version_info < (3, 9): 

1349 # Not used in Python 3.9+. 

1350 def visit_extslice( 

1351 self, node: ast.ExtSlice, parent: nodes.Subscript 

1352 ) -> nodes.Tuple: 

1353 """Visit an ExtSlice node by returning a fresh instance of Tuple.""" 

1354 # ExtSlice doesn't have lineno or col_offset information 

1355 newnode = nodes.Tuple(ctx=Context.Load, parent=parent) 

1356 newnode.postinit([self.visit(dim, newnode) for dim in node.dims]) 

1357 return newnode 

1358 

1359 def visit_index(self, node: ast.Index, parent: nodes.Subscript) -> NodeNG: 

1360 """Visit a Index node by returning a fresh instance of NodeNG.""" 

1361 return self.visit(node.value, parent) 

1362 

1363 def visit_keyword(self, node: ast.keyword, parent: NodeNG) -> nodes.Keyword: 

1364 """Visit a Keyword node by returning a fresh instance of it.""" 

1365 newnode = nodes.Keyword( 

1366 arg=node.arg, 

1367 # position attributes added in 3.9 

1368 lineno=getattr(node, "lineno", None), 

1369 col_offset=getattr(node, "col_offset", None), 

1370 end_lineno=getattr(node, "end_lineno", None), 

1371 end_col_offset=getattr(node, "end_col_offset", None), 

1372 parent=parent, 

1373 ) 

1374 newnode.postinit(self.visit(node.value, newnode)) 

1375 return newnode 

1376 

1377 def visit_lambda(self, node: ast.Lambda, parent: NodeNG) -> nodes.Lambda: 

1378 """Visit a Lambda node by returning a fresh instance of it.""" 

1379 newnode = nodes.Lambda( 

1380 lineno=node.lineno, 

1381 col_offset=node.col_offset, 

1382 end_lineno=node.end_lineno, 

1383 end_col_offset=node.end_col_offset, 

1384 parent=parent, 

1385 ) 

1386 newnode.postinit(self.visit(node.args, newnode), self.visit(node.body, newnode)) 

1387 return newnode 

1388 

1389 def visit_list(self, node: ast.List, parent: NodeNG) -> nodes.List: 

1390 """Visit a List node by returning a fresh instance of it.""" 

1391 context = self._get_context(node) 

1392 newnode = nodes.List( 

1393 ctx=context, 

1394 lineno=node.lineno, 

1395 col_offset=node.col_offset, 

1396 end_lineno=node.end_lineno, 

1397 end_col_offset=node.end_col_offset, 

1398 parent=parent, 

1399 ) 

1400 newnode.postinit([self.visit(child, newnode) for child in node.elts]) 

1401 return newnode 

1402 

1403 def visit_listcomp(self, node: ast.ListComp, parent: NodeNG) -> nodes.ListComp: 

1404 """Visit a ListComp node by returning a fresh instance of it.""" 

1405 newnode = nodes.ListComp( 

1406 lineno=node.lineno, 

1407 col_offset=node.col_offset, 

1408 end_lineno=node.end_lineno, 

1409 end_col_offset=node.end_col_offset, 

1410 parent=parent, 

1411 ) 

1412 newnode.postinit( 

1413 self.visit(node.elt, newnode), 

1414 [self.visit(child, newnode) for child in node.generators], 

1415 ) 

1416 return newnode 

1417 

1418 def visit_name( 

1419 self, node: ast.Name, parent: NodeNG 

1420 ) -> nodes.Name | nodes.AssignName | nodes.DelName: 

1421 """Visit a Name node by returning a fresh instance of it.""" 

1422 context = self._get_context(node) 

1423 newnode: nodes.Name | nodes.AssignName | nodes.DelName 

1424 if context == Context.Del: 

1425 newnode = nodes.DelName( 

1426 name=node.id, 

1427 lineno=node.lineno, 

1428 col_offset=node.col_offset, 

1429 end_lineno=node.end_lineno, 

1430 end_col_offset=node.end_col_offset, 

1431 parent=parent, 

1432 ) 

1433 elif context == Context.Store: 

1434 newnode = nodes.AssignName( 

1435 name=node.id, 

1436 lineno=node.lineno, 

1437 col_offset=node.col_offset, 

1438 end_lineno=node.end_lineno, 

1439 end_col_offset=node.end_col_offset, 

1440 parent=parent, 

1441 ) 

1442 else: 

1443 newnode = nodes.Name( 

1444 name=node.id, 

1445 lineno=node.lineno, 

1446 col_offset=node.col_offset, 

1447 end_lineno=node.end_lineno, 

1448 end_col_offset=node.end_col_offset, 

1449 parent=parent, 

1450 ) 

1451 # XXX REMOVE me : 

1452 if context in (Context.Del, Context.Store): # 'Aug' ?? 

1453 newnode = cast(Union[nodes.AssignName, nodes.DelName], newnode) 

1454 self._save_assignment(newnode) 

1455 return newnode 

1456 

1457 def visit_nonlocal(self, node: ast.Nonlocal, parent: NodeNG) -> nodes.Nonlocal: 

1458 """Visit a Nonlocal node and return a new instance of it.""" 

1459 return nodes.Nonlocal( 

1460 names=node.names, 

1461 lineno=node.lineno, 

1462 col_offset=node.col_offset, 

1463 end_lineno=node.end_lineno, 

1464 end_col_offset=node.end_col_offset, 

1465 parent=parent, 

1466 ) 

1467 

1468 def visit_constant(self, node: ast.Constant, parent: NodeNG) -> nodes.Const: 

1469 """Visit a Constant node by returning a fresh instance of Const.""" 

1470 return nodes.Const( 

1471 value=node.value, 

1472 kind=node.kind, 

1473 lineno=node.lineno, 

1474 col_offset=node.col_offset, 

1475 end_lineno=node.end_lineno, 

1476 end_col_offset=node.end_col_offset, 

1477 parent=parent, 

1478 ) 

1479 

1480 def visit_pass(self, node: ast.Pass, parent: NodeNG) -> nodes.Pass: 

1481 """Visit a Pass node by returning a fresh instance of it.""" 

1482 return nodes.Pass( 

1483 lineno=node.lineno, 

1484 col_offset=node.col_offset, 

1485 end_lineno=node.end_lineno, 

1486 end_col_offset=node.end_col_offset, 

1487 parent=parent, 

1488 ) 

1489 

1490 def visit_raise(self, node: ast.Raise, parent: NodeNG) -> nodes.Raise: 

1491 """Visit a Raise node by returning a fresh instance of it.""" 

1492 newnode = nodes.Raise( 

1493 lineno=node.lineno, 

1494 col_offset=node.col_offset, 

1495 end_lineno=node.end_lineno, 

1496 end_col_offset=node.end_col_offset, 

1497 parent=parent, 

1498 ) 

1499 # no traceback; anyway it is not used in Pylint 

1500 newnode.postinit( 

1501 exc=self.visit(node.exc, newnode), 

1502 cause=self.visit(node.cause, newnode), 

1503 ) 

1504 return newnode 

1505 

1506 def visit_return(self, node: ast.Return, parent: NodeNG) -> nodes.Return: 

1507 """Visit a Return node by returning a fresh instance of it.""" 

1508 newnode = nodes.Return( 

1509 lineno=node.lineno, 

1510 col_offset=node.col_offset, 

1511 end_lineno=node.end_lineno, 

1512 end_col_offset=node.end_col_offset, 

1513 parent=parent, 

1514 ) 

1515 newnode.postinit(self.visit(node.value, newnode)) 

1516 return newnode 

1517 

1518 def visit_set(self, node: ast.Set, parent: NodeNG) -> nodes.Set: 

1519 """Visit a Set node by returning a fresh instance of it.""" 

1520 newnode = nodes.Set( 

1521 lineno=node.lineno, 

1522 col_offset=node.col_offset, 

1523 end_lineno=node.end_lineno, 

1524 end_col_offset=node.end_col_offset, 

1525 parent=parent, 

1526 ) 

1527 newnode.postinit([self.visit(child, newnode) for child in node.elts]) 

1528 return newnode 

1529 

1530 def visit_setcomp(self, node: ast.SetComp, parent: NodeNG) -> nodes.SetComp: 

1531 """Visit a SetComp node by returning a fresh instance of it.""" 

1532 newnode = nodes.SetComp( 

1533 lineno=node.lineno, 

1534 col_offset=node.col_offset, 

1535 end_lineno=node.end_lineno, 

1536 end_col_offset=node.end_col_offset, 

1537 parent=parent, 

1538 ) 

1539 newnode.postinit( 

1540 self.visit(node.elt, newnode), 

1541 [self.visit(child, newnode) for child in node.generators], 

1542 ) 

1543 return newnode 

1544 

1545 def visit_slice(self, node: ast.Slice, parent: nodes.Subscript) -> nodes.Slice: 

1546 """Visit a Slice node by returning a fresh instance of it.""" 

1547 newnode = nodes.Slice( 

1548 # position attributes added in 3.9 

1549 lineno=getattr(node, "lineno", None), 

1550 col_offset=getattr(node, "col_offset", None), 

1551 end_lineno=getattr(node, "end_lineno", None), 

1552 end_col_offset=getattr(node, "end_col_offset", None), 

1553 parent=parent, 

1554 ) 

1555 newnode.postinit( 

1556 lower=self.visit(node.lower, newnode), 

1557 upper=self.visit(node.upper, newnode), 

1558 step=self.visit(node.step, newnode), 

1559 ) 

1560 return newnode 

1561 

1562 def visit_subscript(self, node: ast.Subscript, parent: NodeNG) -> nodes.Subscript: 

1563 """Visit a Subscript node by returning a fresh instance of it.""" 

1564 context = self._get_context(node) 

1565 newnode = nodes.Subscript( 

1566 ctx=context, 

1567 lineno=node.lineno, 

1568 col_offset=node.col_offset, 

1569 end_lineno=node.end_lineno, 

1570 end_col_offset=node.end_col_offset, 

1571 parent=parent, 

1572 ) 

1573 newnode.postinit( 

1574 self.visit(node.value, newnode), self.visit(node.slice, newnode) 

1575 ) 

1576 return newnode 

1577 

1578 def visit_starred(self, node: ast.Starred, parent: NodeNG) -> nodes.Starred: 

1579 """Visit a Starred node and return a new instance of it.""" 

1580 context = self._get_context(node) 

1581 newnode = nodes.Starred( 

1582 ctx=context, 

1583 lineno=node.lineno, 

1584 col_offset=node.col_offset, 

1585 end_lineno=node.end_lineno, 

1586 end_col_offset=node.end_col_offset, 

1587 parent=parent, 

1588 ) 

1589 newnode.postinit(self.visit(node.value, newnode)) 

1590 return newnode 

1591 

1592 def visit_tryexcept(self, node: ast.Try, parent: NodeNG) -> nodes.TryExcept: 

1593 """Visit a TryExcept node by returning a fresh instance of it.""" 

1594 # TryExcept excludes the 'finally' but that will be included in the 

1595 # end_lineno from 'node'. Therefore, we check all non 'finally' 

1596 # children to find the correct end_lineno and column. 

1597 end_lineno = node.end_lineno 

1598 end_col_offset = node.end_col_offset 

1599 all_children: list[ast.AST] = [*node.body, *node.handlers, *node.orelse] 

1600 for child in reversed(all_children): 

1601 end_lineno = child.end_lineno 

1602 end_col_offset = child.end_col_offset 

1603 break 

1604 newnode = nodes.TryExcept( 

1605 lineno=node.lineno, 

1606 col_offset=node.col_offset, 

1607 end_lineno=end_lineno, 

1608 end_col_offset=end_col_offset, 

1609 parent=parent, 

1610 ) 

1611 newnode.postinit( 

1612 [self.visit(child, newnode) for child in node.body], 

1613 [self.visit(child, newnode) for child in node.handlers], 

1614 [self.visit(child, newnode) for child in node.orelse], 

1615 ) 

1616 return newnode 

1617 

1618 def visit_try( 

1619 self, node: ast.Try, parent: NodeNG 

1620 ) -> nodes.TryExcept | nodes.TryFinally | None: 

1621 # python 3.3 introduce a new Try node replacing 

1622 # TryFinally/TryExcept nodes 

1623 if node.finalbody: 

1624 newnode = nodes.TryFinally( 

1625 lineno=node.lineno, 

1626 col_offset=node.col_offset, 

1627 end_lineno=node.end_lineno, 

1628 end_col_offset=node.end_col_offset, 

1629 parent=parent, 

1630 ) 

1631 body: list[NodeNG | nodes.TryExcept] 

1632 if node.handlers: 

1633 body = [self.visit_tryexcept(node, newnode)] 

1634 else: 

1635 body = [self.visit(child, newnode) for child in node.body] 

1636 newnode.postinit(body, [self.visit(n, newnode) for n in node.finalbody]) 

1637 return newnode 

1638 if node.handlers: 

1639 return self.visit_tryexcept(node, parent) 

1640 return None 

1641 

1642 def visit_trystar(self, node: ast.TryStar, parent: NodeNG) -> nodes.TryStar: 

1643 newnode = nodes.TryStar( 

1644 lineno=node.lineno, 

1645 col_offset=node.col_offset, 

1646 end_lineno=node.end_lineno, 

1647 end_col_offset=node.end_col_offset, 

1648 parent=parent, 

1649 ) 

1650 newnode.postinit( 

1651 body=[self.visit(n, newnode) for n in node.body], 

1652 handlers=[self.visit(n, newnode) for n in node.handlers], 

1653 orelse=[self.visit(n, newnode) for n in node.orelse], 

1654 finalbody=[self.visit(n, newnode) for n in node.finalbody], 

1655 ) 

1656 return newnode 

1657 

1658 def visit_tuple(self, node: ast.Tuple, parent: NodeNG) -> nodes.Tuple: 

1659 """Visit a Tuple node by returning a fresh instance of it.""" 

1660 context = self._get_context(node) 

1661 newnode = nodes.Tuple( 

1662 ctx=context, 

1663 lineno=node.lineno, 

1664 col_offset=node.col_offset, 

1665 end_lineno=node.end_lineno, 

1666 end_col_offset=node.end_col_offset, 

1667 parent=parent, 

1668 ) 

1669 newnode.postinit([self.visit(child, newnode) for child in node.elts]) 

1670 return newnode 

1671 

1672 def visit_unaryop(self, node: ast.UnaryOp, parent: NodeNG) -> nodes.UnaryOp: 

1673 """Visit a UnaryOp node by returning a fresh instance of it.""" 

1674 newnode = nodes.UnaryOp( 

1675 op=self._parser_module.unary_op_classes[node.op.__class__], 

1676 lineno=node.lineno, 

1677 col_offset=node.col_offset, 

1678 end_lineno=node.end_lineno, 

1679 end_col_offset=node.end_col_offset, 

1680 parent=parent, 

1681 ) 

1682 newnode.postinit(self.visit(node.operand, newnode)) 

1683 return newnode 

1684 

1685 def visit_while(self, node: ast.While, parent: NodeNG) -> nodes.While: 

1686 """Visit a While node by returning a fresh instance of it.""" 

1687 newnode = nodes.While( 

1688 lineno=node.lineno, 

1689 col_offset=node.col_offset, 

1690 end_lineno=node.end_lineno, 

1691 end_col_offset=node.end_col_offset, 

1692 parent=parent, 

1693 ) 

1694 newnode.postinit( 

1695 self.visit(node.test, newnode), 

1696 [self.visit(child, newnode) for child in node.body], 

1697 [self.visit(child, newnode) for child in node.orelse], 

1698 ) 

1699 return newnode 

1700 

1701 @overload 

1702 def _visit_with( 

1703 self, cls: type[nodes.With], node: ast.With, parent: NodeNG 

1704 ) -> nodes.With: 

1705 ... 

1706 

1707 @overload 

1708 def _visit_with( 

1709 self, cls: type[nodes.AsyncWith], node: ast.AsyncWith, parent: NodeNG 

1710 ) -> nodes.AsyncWith: 

1711 ... 

1712 

1713 def _visit_with( 

1714 self, 

1715 cls: type[_WithT], 

1716 node: ast.With | ast.AsyncWith, 

1717 parent: NodeNG, 

1718 ) -> _WithT: 

1719 col_offset = node.col_offset 

1720 if IS_PYPY and not PY39_PLUS and isinstance(node, ast.AsyncWith) and self._data: 

1721 # pylint: disable-next=unsubscriptable-object 

1722 col_offset = self._data[node.lineno - 1].index("async") 

1723 

1724 newnode = cls( 

1725 lineno=node.lineno, 

1726 col_offset=col_offset, 

1727 end_lineno=node.end_lineno, 

1728 end_col_offset=node.end_col_offset, 

1729 parent=parent, 

1730 ) 

1731 

1732 def visit_child(child: ast.withitem) -> tuple[NodeNG, NodeNG | None]: 

1733 expr = self.visit(child.context_expr, newnode) 

1734 var = self.visit(child.optional_vars, newnode) 

1735 return expr, var 

1736 

1737 type_annotation = self.check_type_comment(node, parent=newnode) 

1738 newnode.postinit( 

1739 items=[visit_child(child) for child in node.items], 

1740 body=[self.visit(child, newnode) for child in node.body], 

1741 type_annotation=type_annotation, 

1742 ) 

1743 return newnode 

1744 

1745 def visit_with(self, node: ast.With, parent: NodeNG) -> NodeNG: 

1746 return self._visit_with(nodes.With, node, parent) 

1747 

1748 def visit_yield(self, node: ast.Yield, parent: NodeNG) -> NodeNG: 

1749 """Visit a Yield node by returning a fresh instance of it.""" 

1750 newnode = nodes.Yield( 

1751 lineno=node.lineno, 

1752 col_offset=node.col_offset, 

1753 end_lineno=node.end_lineno, 

1754 end_col_offset=node.end_col_offset, 

1755 parent=parent, 

1756 ) 

1757 newnode.postinit(self.visit(node.value, newnode)) 

1758 return newnode 

1759 

1760 def visit_yieldfrom(self, node: ast.YieldFrom, parent: NodeNG) -> NodeNG: 

1761 newnode = nodes.YieldFrom( 

1762 lineno=node.lineno, 

1763 col_offset=node.col_offset, 

1764 end_lineno=node.end_lineno, 

1765 end_col_offset=node.end_col_offset, 

1766 parent=parent, 

1767 ) 

1768 newnode.postinit(self.visit(node.value, newnode)) 

1769 return newnode 

1770 

1771 if sys.version_info >= (3, 10): 

1772 

1773 def visit_match(self, node: ast.Match, parent: NodeNG) -> nodes.Match: 

1774 newnode = nodes.Match( 

1775 lineno=node.lineno, 

1776 col_offset=node.col_offset, 

1777 end_lineno=node.end_lineno, 

1778 end_col_offset=node.end_col_offset, 

1779 parent=parent, 

1780 ) 

1781 newnode.postinit( 

1782 subject=self.visit(node.subject, newnode), 

1783 cases=[self.visit(case, newnode) for case in node.cases], 

1784 ) 

1785 return newnode 

1786 

1787 def visit_matchcase( 

1788 self, node: ast.match_case, parent: NodeNG 

1789 ) -> nodes.MatchCase: 

1790 newnode = nodes.MatchCase(parent=parent) 

1791 newnode.postinit( 

1792 pattern=self.visit(node.pattern, newnode), 

1793 guard=self.visit(node.guard, newnode), 

1794 body=[self.visit(child, newnode) for child in node.body], 

1795 ) 

1796 return newnode 

1797 

1798 def visit_matchvalue( 

1799 self, node: ast.MatchValue, parent: NodeNG 

1800 ) -> nodes.MatchValue: 

1801 newnode = nodes.MatchValue( 

1802 lineno=node.lineno, 

1803 col_offset=node.col_offset, 

1804 end_lineno=node.end_lineno, 

1805 end_col_offset=node.end_col_offset, 

1806 parent=parent, 

1807 ) 

1808 newnode.postinit(value=self.visit(node.value, newnode)) 

1809 return newnode 

1810 

1811 def visit_matchsingleton( 

1812 self, node: ast.MatchSingleton, parent: NodeNG 

1813 ) -> nodes.MatchSingleton: 

1814 return nodes.MatchSingleton( 

1815 value=node.value, 

1816 lineno=node.lineno, 

1817 col_offset=node.col_offset, 

1818 end_lineno=node.end_lineno, 

1819 end_col_offset=node.end_col_offset, 

1820 parent=parent, 

1821 ) 

1822 

1823 def visit_matchsequence( 

1824 self, node: ast.MatchSequence, parent: NodeNG 

1825 ) -> nodes.MatchSequence: 

1826 newnode = nodes.MatchSequence( 

1827 lineno=node.lineno, 

1828 col_offset=node.col_offset, 

1829 end_lineno=node.end_lineno, 

1830 end_col_offset=node.end_col_offset, 

1831 parent=parent, 

1832 ) 

1833 newnode.postinit( 

1834 patterns=[self.visit(pattern, newnode) for pattern in node.patterns] 

1835 ) 

1836 return newnode 

1837 

1838 def visit_matchmapping( 

1839 self, node: ast.MatchMapping, parent: NodeNG 

1840 ) -> nodes.MatchMapping: 

1841 newnode = nodes.MatchMapping( 

1842 lineno=node.lineno, 

1843 col_offset=node.col_offset, 

1844 end_lineno=node.end_lineno, 

1845 end_col_offset=node.end_col_offset, 

1846 parent=parent, 

1847 ) 

1848 # Add AssignName node for 'node.name' 

1849 # https://bugs.python.org/issue43994 

1850 newnode.postinit( 

1851 keys=[self.visit(child, newnode) for child in node.keys], 

1852 patterns=[self.visit(pattern, newnode) for pattern in node.patterns], 

1853 rest=self.visit_assignname(node, newnode, node.rest), 

1854 ) 

1855 return newnode 

1856 

1857 def visit_matchclass( 

1858 self, node: ast.MatchClass, parent: NodeNG 

1859 ) -> nodes.MatchClass: 

1860 newnode = nodes.MatchClass( 

1861 lineno=node.lineno, 

1862 col_offset=node.col_offset, 

1863 end_lineno=node.end_lineno, 

1864 end_col_offset=node.end_col_offset, 

1865 parent=parent, 

1866 ) 

1867 newnode.postinit( 

1868 cls=self.visit(node.cls, newnode), 

1869 patterns=[self.visit(pattern, newnode) for pattern in node.patterns], 

1870 kwd_attrs=node.kwd_attrs, 

1871 kwd_patterns=[ 

1872 self.visit(pattern, newnode) for pattern in node.kwd_patterns 

1873 ], 

1874 ) 

1875 return newnode 

1876 

1877 def visit_matchstar( 

1878 self, node: ast.MatchStar, parent: NodeNG 

1879 ) -> nodes.MatchStar: 

1880 newnode = nodes.MatchStar( 

1881 lineno=node.lineno, 

1882 col_offset=node.col_offset, 

1883 end_lineno=node.end_lineno, 

1884 end_col_offset=node.end_col_offset, 

1885 parent=parent, 

1886 ) 

1887 # Add AssignName node for 'node.name' 

1888 # https://bugs.python.org/issue43994 

1889 newnode.postinit(name=self.visit_assignname(node, newnode, node.name)) 

1890 return newnode 

1891 

1892 def visit_matchas(self, node: ast.MatchAs, parent: NodeNG) -> nodes.MatchAs: 

1893 newnode = nodes.MatchAs( 

1894 lineno=node.lineno, 

1895 col_offset=node.col_offset, 

1896 end_lineno=node.end_lineno, 

1897 end_col_offset=node.end_col_offset, 

1898 parent=parent, 

1899 ) 

1900 # Add AssignName node for 'node.name' 

1901 # https://bugs.python.org/issue43994 

1902 newnode.postinit( 

1903 pattern=self.visit(node.pattern, newnode), 

1904 name=self.visit_assignname(node, newnode, node.name), 

1905 ) 

1906 return newnode 

1907 

1908 def visit_matchor(self, node: ast.MatchOr, parent: NodeNG) -> nodes.MatchOr: 

1909 newnode = nodes.MatchOr( 

1910 lineno=node.lineno, 

1911 col_offset=node.col_offset, 

1912 end_lineno=node.end_lineno, 

1913 end_col_offset=node.end_col_offset, 

1914 parent=parent, 

1915 ) 

1916 newnode.postinit( 

1917 patterns=[self.visit(pattern, newnode) for pattern in node.patterns] 

1918 ) 

1919 return newnode