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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

694 statements  

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 itertools 

13import sys 

14import token 

15from collections.abc import Callable, Collection, Generator 

16from io import StringIO 

17from tokenize import TokenInfo, generate_tokens 

18from typing import TYPE_CHECKING, Final, TypeVar, cast, overload 

19 

20from astroid import nodes 

21from astroid._ast import ParserModule, get_parser_module, parse_function_type_comment 

22from astroid.const import PY312_PLUS, PY313_PLUS, Context 

23from astroid.nodes.utils import Position 

24from astroid.typing import InferenceResult 

25 

26if TYPE_CHECKING: 

27 from astroid.manager import AstroidManager 

28 

29 T_Doc = TypeVar( 

30 "T_Doc", 

31 ast.Module, 

32 ast.ClassDef, 

33 ast.FunctionDef | ast.AsyncFunctionDef, 

34 ) 

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

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

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

38 NodesWithDocsType = nodes.Module | nodes.ClassDef | nodes.FunctionDef 

39 

40 

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

42 "arguments": "Arguments", 

43 "comprehension": "Comprehension", 

44 "ListCompFor": "Comprehension", 

45 "GenExprFor": "Comprehension", 

46 "excepthandler": "ExceptHandler", 

47 "keyword": "Keyword", 

48 "match_case": "MatchCase", 

49} 

50 

51 

52# noinspection PyMethodMayBeStatic 

53class TreeRebuilder: 

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

55 

56 def __init__( 

57 self, 

58 manager: AstroidManager, 

59 parser_module: ParserModule | None = None, 

60 data: str | None = None, 

61 ) -> None: 

62 self._manager = manager 

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

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

65 self._import_from_nodes: list[tuple[nodes.ImportFrom, Collection[str]]] = [] 

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

67 self._visit_meths: dict[ 

68 type[ast.AST], Callable[[ast.AST, nodes.NodeNG], nodes.NodeNG] 

69 ] = {} 

70 

71 if parser_module is None: 

72 self._parser_module = get_parser_module() 

73 else: 

74 self._parser_module = parser_module 

75 

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

77 """Return the doc ast node.""" 

78 try: 

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

80 first_value = node.body[0].value 

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

82 first_value.value, str 

83 ): 

84 doc_ast_node = first_value 

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

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 visit_module( 

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

161 ) -> nodes.Module: 

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

163 

164 Note: Method not called by 'visit' 

165 """ 

166 node, doc_ast_node = self._get_doc(node) 

167 newnode = nodes.Module( 

168 name=modname, 

169 file=modpath, 

170 path=[modpath], 

171 package=package, 

172 ) 

173 newnode.postinit( 

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

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

176 ) 

177 return newnode 

178 

179 if TYPE_CHECKING: # noqa: C901 

180 

181 @overload 

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

183 

184 @overload 

185 def visit( 

186 self, node: ast.arguments, parent: nodes.NodeNG 

187 ) -> nodes.Arguments: ... 

188 

189 @overload 

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

191 

192 @overload 

193 def visit( 

194 self, node: ast.AsyncFunctionDef, parent: nodes.NodeNG 

195 ) -> nodes.AsyncFunctionDef: ... 

196 

197 @overload 

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

199 

200 @overload 

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

202 

203 @overload 

204 def visit( 

205 self, node: ast.AsyncWith, parent: nodes.NodeNG 

206 ) -> nodes.AsyncWith: ... 

207 

208 @overload 

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

210 

211 @overload 

212 def visit( 

213 self, node: ast.AnnAssign, parent: nodes.NodeNG 

214 ) -> nodes.AnnAssign: ... 

215 

216 @overload 

217 def visit( 

218 self, node: ast.AugAssign, parent: nodes.NodeNG 

219 ) -> nodes.AugAssign: ... 

220 

221 @overload 

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

223 

224 @overload 

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

226 

227 @overload 

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

229 

230 @overload 

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

232 

233 @overload 

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

235 

236 @overload 

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

238 

239 @overload 

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

241 

242 @overload 

243 def visit( 

244 self, node: ast.comprehension, parent: nodes.NodeNG 

245 ) -> nodes.Comprehension: ... 

246 

247 @overload 

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

249 

250 @overload 

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

252 

253 @overload 

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

255 

256 @overload 

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

258 

259 @overload 

260 def visit( 

261 self, node: ast.ExceptHandler, parent: nodes.NodeNG 

262 ) -> nodes.ExceptHandler: ... 

263 

264 @overload 

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

266 

267 @overload 

268 def visit( 

269 self, node: ast.ImportFrom, parent: nodes.NodeNG 

270 ) -> nodes.ImportFrom: ... 

271 

272 @overload 

273 def visit( 

274 self, node: ast.FunctionDef, parent: nodes.NodeNG 

275 ) -> nodes.FunctionDef: ... 

276 

277 @overload 

278 def visit( 

279 self, node: ast.GeneratorExp, parent: nodes.NodeNG 

280 ) -> nodes.GeneratorExp: ... 

281 

282 @overload 

283 def visit( 

284 self, node: ast.Attribute, parent: nodes.NodeNG 

285 ) -> nodes.Attribute: ... 

286 

287 @overload 

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

289 

290 @overload 

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

292 

293 @overload 

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

295 

296 @overload 

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

298 

299 @overload 

300 def visit( 

301 self, node: ast.JoinedStr, parent: nodes.NodeNG 

302 ) -> nodes.JoinedStr: ... 

303 

304 @overload 

305 def visit( 

306 self, node: ast.FormattedValue, parent: nodes.NodeNG 

307 ) -> nodes.FormattedValue: ... 

308 

309 @overload 

310 def visit( 

311 self, node: ast.NamedExpr, parent: nodes.NodeNG 

312 ) -> nodes.NamedExpr: ... 

313 

314 @overload 

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

316 

317 @overload 

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

319 

320 @overload 

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

322 

323 @overload 

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

325 

326 @overload 

327 def visit( 

328 self, node: ast.Name, parent: nodes.NodeNG 

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

330 

331 @overload 

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

333 

334 @overload 

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

336 

337 if sys.version_info >= (3, 12): 

338 

339 @overload 

340 def visit( 

341 self, node: ast.ParamSpec, parent: nodes.NodeNG 

342 ) -> nodes.ParamSpec: ... 

343 

344 @overload 

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

346 

347 @overload 

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

349 

350 @overload 

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

352 

353 @overload 

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

355 

356 @overload 

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

358 

359 @overload 

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

361 

362 @overload 

363 def visit( 

364 self, node: ast.Subscript, parent: nodes.NodeNG 

365 ) -> nodes.Subscript: ... 

366 

367 @overload 

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

369 

370 @overload 

371 def visit(self, node: ast.Try, parent: nodes.NodeNG) -> nodes.Try: ... 

372 

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

374 

375 @overload 

376 def visit( 

377 self, node: ast.TryStar, parent: nodes.NodeNG 

378 ) -> nodes.TryStar: ... 

379 

380 @overload 

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

382 

383 if sys.version_info >= (3, 12): 

384 

385 @overload 

386 def visit( 

387 self, node: ast.TypeAlias, parent: nodes.NodeNG 

388 ) -> nodes.TypeAlias: ... 

389 

390 @overload 

391 def visit( 

392 self, node: ast.TypeVar, parent: nodes.NodeNG 

393 ) -> nodes.TypeVar: ... 

394 

395 @overload 

396 def visit( 

397 self, node: ast.TypeVarTuple, parent: nodes.NodeNG 

398 ) -> nodes.TypeVarTuple: ... 

399 

400 @overload 

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

402 

403 @overload 

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

405 

406 @overload 

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

408 

409 @overload 

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

411 

412 @overload 

413 def visit( 

414 self, node: ast.YieldFrom, parent: nodes.NodeNG 

415 ) -> nodes.YieldFrom: ... 

416 

417 @overload 

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

419 

420 @overload 

421 def visit( 

422 self, node: ast.match_case, parent: nodes.NodeNG 

423 ) -> nodes.MatchCase: ... 

424 

425 @overload 

426 def visit( 

427 self, node: ast.MatchValue, parent: nodes.NodeNG 

428 ) -> nodes.MatchValue: ... 

429 

430 @overload 

431 def visit( 

432 self, node: ast.MatchSingleton, parent: nodes.NodeNG 

433 ) -> nodes.MatchSingleton: ... 

434 

435 @overload 

436 def visit( 

437 self, node: ast.MatchSequence, parent: nodes.NodeNG 

438 ) -> nodes.MatchSequence: ... 

439 

440 @overload 

441 def visit( 

442 self, node: ast.MatchMapping, parent: nodes.NodeNG 

443 ) -> nodes.MatchMapping: ... 

444 

445 @overload 

446 def visit( 

447 self, node: ast.MatchClass, parent: nodes.NodeNG 

448 ) -> nodes.MatchClass: ... 

449 

450 @overload 

451 def visit( 

452 self, node: ast.MatchStar, parent: nodes.NodeNG 

453 ) -> nodes.MatchStar: ... 

454 

455 @overload 

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

457 

458 @overload 

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

460 

461 @overload 

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

463 

464 if sys.version_info >= (3, 14): 

465 

466 @overload 

467 def visit( 

468 self, node: ast.TemplateStr, parent: nodes.NodeNG 

469 ) -> nodes.TemplateStr: ... 

470 

471 @overload 

472 def visit( 

473 self, node: ast.Interpolation, parent: nodes.NodeNG 

474 ) -> nodes.Interpolation: ... 

475 

476 @overload 

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

478 

479 @overload 

480 def visit(self, node: None, parent: nodes.NodeNG) -> None: ... 

481 

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

483 if node is None: 

484 return None 

485 cls = node.__class__ 

486 if cls in self._visit_meths: 

487 visit_method = self._visit_meths[cls] 

488 else: 

489 cls_name = cls.__name__ 

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

491 visit_method = getattr(self, visit_name) 

492 self._visit_meths[cls] = visit_method 

493 return visit_method(node, parent) 

494 

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

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

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

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

499 else: 

500 assert node.parent 

501 assert node.name 

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

503 

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

505 """Visit an arg node by returning a fresh AssignName instance.""" 

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

507 

508 def visit_arguments( 

509 self, node: ast.arguments, parent: nodes.NodeNG 

510 ) -> nodes.Arguments: 

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

512 vararg: str | None = None 

513 kwarg: str | None = None 

514 vararg_node = node.vararg 

515 kwarg_node = node.kwarg 

516 

517 newnode = nodes.Arguments( 

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

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

520 parent, 

521 ( 

522 nodes.AssignName( 

523 vararg_node.arg, 

524 vararg_node.lineno, 

525 vararg_node.col_offset, 

526 parent, 

527 end_lineno=vararg_node.end_lineno, 

528 end_col_offset=vararg_node.end_col_offset, 

529 ) 

530 if vararg_node 

531 else None 

532 ), 

533 ( 

534 nodes.AssignName( 

535 kwarg_node.arg, 

536 kwarg_node.lineno, 

537 kwarg_node.col_offset, 

538 parent, 

539 end_lineno=kwarg_node.end_lineno, 

540 end_col_offset=kwarg_node.end_col_offset, 

541 ) 

542 if kwarg_node 

543 else None 

544 ), 

545 ) 

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

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

548 varargannotation: nodes.NodeNG | None = None 

549 kwargannotation: nodes.NodeNG | None = None 

550 if node.vararg: 

551 vararg = node.vararg.arg 

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

553 if node.kwarg: 

554 kwarg = node.kwarg.arg 

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

556 

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

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

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

560 kwonlyargs_annotations = [ 

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

562 ] 

563 

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

565 posonlyargs_annotations = [ 

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

567 ] 

568 type_comment_args = [ 

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

570 ] 

571 type_comment_kwonlyargs = [ 

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

573 ] 

574 type_comment_posonlyargs = [ 

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

576 ] 

577 

578 newnode.postinit( 

579 args=args, 

580 defaults=defaults, 

581 kwonlyargs=kwonlyargs, 

582 posonlyargs=posonlyargs, 

583 kw_defaults=kw_defaults, 

584 annotations=annotations, 

585 kwonlyargs_annotations=kwonlyargs_annotations, 

586 posonlyargs_annotations=posonlyargs_annotations, 

587 varargannotation=varargannotation, 

588 kwargannotation=kwargannotation, 

589 type_comment_args=type_comment_args, 

590 type_comment_kwonlyargs=type_comment_kwonlyargs, 

591 type_comment_posonlyargs=type_comment_posonlyargs, 

592 ) 

593 if start_end_lineno_pairs := [ 

594 (arg.lineno, arg.end_lineno) 

595 for arg in itertools.chain( 

596 node.args, node.posonlyargs, node.kwonlyargs, [node.vararg, node.kwarg] 

597 ) 

598 if arg 

599 ]: 

600 newnode.lineno = min(startend[0] for startend in start_end_lineno_pairs) 

601 newnode.end_lineno = max(startend[1] for startend in start_end_lineno_pairs) 

602 

603 # save argument names in locals: 

604 assert newnode.parent 

605 if vararg: 

606 newnode.parent.set_local(vararg, newnode) 

607 if kwarg: 

608 newnode.parent.set_local(kwarg, newnode) 

609 return newnode 

610 

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

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

613 newnode = nodes.Assert( 

614 lineno=node.lineno, 

615 col_offset=node.col_offset, 

616 end_lineno=node.end_lineno, 

617 end_col_offset=node.end_col_offset, 

618 parent=parent, 

619 ) 

620 msg: nodes.NodeNG | None = None 

621 if node.msg: 

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

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

624 return newnode 

625 

626 def check_type_comment( 

627 self, 

628 node: ast.Assign | ast.arg | ast.For | ast.AsyncFor | ast.With | ast.AsyncWith, 

629 parent: ( 

630 nodes.Assign 

631 | nodes.Arguments 

632 | nodes.For 

633 | nodes.AsyncFor 

634 | nodes.With 

635 | nodes.AsyncWith 

636 ), 

637 ) -> nodes.NodeNG | None: 

638 if not node.type_comment: 

639 return None 

640 

641 try: 

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

643 except SyntaxError: 

644 # Invalid type comment, just skip it. 

645 return None 

646 

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

648 # without any nodes in the body. 

649 if not type_comment_ast.body: 

650 return None 

651 

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

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

654 return None 

655 

656 return type_object.value 

657 

658 def check_function_type_comment( 

659 self, node: ast.FunctionDef | ast.AsyncFunctionDef, parent: nodes.NodeNG 

660 ) -> tuple[nodes.NodeNG | None, list[nodes.NodeNG]] | None: 

661 if not node.type_comment: 

662 return None 

663 

664 try: 

665 type_comment_ast = parse_function_type_comment(node.type_comment) 

666 except SyntaxError: 

667 # Invalid type comment, just skip it. 

668 return None 

669 

670 if not type_comment_ast: 

671 return None 

672 

673 returns: nodes.NodeNG | None = None 

674 argtypes: list[nodes.NodeNG] = [ 

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

676 ] 

677 if type_comment_ast.returns: 

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

679 

680 return returns, argtypes 

681 

682 def visit_asyncfunctiondef( 

683 self, node: ast.AsyncFunctionDef, parent: nodes.NodeNG 

684 ) -> nodes.AsyncFunctionDef: 

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

686 

687 def visit_asyncfor( 

688 self, node: ast.AsyncFor, parent: nodes.NodeNG 

689 ) -> nodes.AsyncFor: 

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

691 

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

693 newnode = nodes.Await( 

694 lineno=node.lineno, 

695 col_offset=node.col_offset, 

696 end_lineno=node.end_lineno, 

697 end_col_offset=node.end_col_offset, 

698 parent=parent, 

699 ) 

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

701 return newnode 

702 

703 def visit_asyncwith( 

704 self, node: ast.AsyncWith, parent: nodes.NodeNG 

705 ) -> nodes.AsyncWith: 

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

707 

708 def visit_assign(self, node: ast.Assign, parent: nodes.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( 

726 self, node: ast.AnnAssign, parent: nodes.NodeNG 

727 ) -> nodes.AnnAssign: 

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

729 newnode = nodes.AnnAssign( 

730 lineno=node.lineno, 

731 col_offset=node.col_offset, 

732 end_lineno=node.end_lineno, 

733 end_col_offset=node.end_col_offset, 

734 parent=parent, 

735 ) 

736 newnode.postinit( 

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

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

739 simple=node.simple, 

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

741 ) 

742 return newnode 

743 

744 @overload 

745 def visit_assignname( 

746 self, node: ast.AST, parent: nodes.NodeNG, node_name: str 

747 ) -> nodes.AssignName: ... 

748 

749 @overload 

750 def visit_assignname( 

751 self, node: ast.AST, parent: nodes.NodeNG, node_name: None 

752 ) -> None: ... 

753 

754 def visit_assignname( 

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

756 ) -> nodes.AssignName | None: 

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

758 

759 Note: Method not called by 'visit' 

760 """ 

761 if node_name is None: 

762 return None 

763 newnode = nodes.AssignName( 

764 name=node_name, 

765 lineno=node.lineno, 

766 col_offset=node.col_offset, 

767 end_lineno=node.end_lineno, 

768 end_col_offset=node.end_col_offset, 

769 parent=parent, 

770 ) 

771 self._save_assignment(newnode) 

772 return newnode 

773 

774 def visit_augassign( 

775 self, node: ast.AugAssign, parent: nodes.NodeNG 

776 ) -> nodes.AugAssign: 

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

778 newnode = nodes.AugAssign( 

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

780 lineno=node.lineno, 

781 col_offset=node.col_offset, 

782 end_lineno=node.end_lineno, 

783 end_col_offset=node.end_col_offset, 

784 parent=parent, 

785 ) 

786 newnode.postinit( 

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

788 ) 

789 return newnode 

790 

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

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

793 newnode = nodes.BinOp( 

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

795 lineno=node.lineno, 

796 col_offset=node.col_offset, 

797 end_lineno=node.end_lineno, 

798 end_col_offset=node.end_col_offset, 

799 parent=parent, 

800 ) 

801 newnode.postinit( 

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

803 ) 

804 return newnode 

805 

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

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

808 newnode = nodes.BoolOp( 

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

810 lineno=node.lineno, 

811 col_offset=node.col_offset, 

812 end_lineno=node.end_lineno, 

813 end_col_offset=node.end_col_offset, 

814 parent=parent, 

815 ) 

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

817 return newnode 

818 

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

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

821 return nodes.Break( 

822 lineno=node.lineno, 

823 col_offset=node.col_offset, 

824 end_lineno=node.end_lineno, 

825 end_col_offset=node.end_col_offset, 

826 parent=parent, 

827 ) 

828 

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

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

831 newnode = nodes.Call( 

832 lineno=node.lineno, 

833 col_offset=node.col_offset, 

834 end_lineno=node.end_lineno, 

835 end_col_offset=node.end_col_offset, 

836 parent=parent, 

837 ) 

838 newnode.postinit( 

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

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

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

842 ) 

843 return newnode 

844 

845 def visit_classdef( 

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

847 ) -> nodes.ClassDef: 

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

849 node, doc_ast_node = self._get_doc(node) 

850 newnode = nodes.ClassDef( 

851 name=node.name, 

852 lineno=node.lineno, 

853 col_offset=node.col_offset, 

854 end_lineno=node.end_lineno, 

855 end_col_offset=node.end_col_offset, 

856 parent=parent, 

857 ) 

858 metaclass = None 

859 for keyword in node.keywords: 

860 if keyword.arg == "metaclass": 

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

862 break 

863 decorators = self.visit_decorators(node, newnode) 

864 newnode.postinit( 

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

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

867 decorators, 

868 newstyle, 

869 metaclass, 

870 [ 

871 self.visit(kwd, newnode) 

872 for kwd in node.keywords 

873 if kwd.arg != "metaclass" 

874 ], 

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

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

877 type_params=( 

878 [self.visit(param, newnode) for param in node.type_params] 

879 if PY312_PLUS 

880 else [] 

881 ), 

882 ) 

883 parent.set_local(newnode.name, newnode) 

884 return newnode 

885 

886 def visit_continue( 

887 self, node: ast.Continue, parent: nodes.NodeNG 

888 ) -> nodes.Continue: 

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

890 return nodes.Continue( 

891 lineno=node.lineno, 

892 col_offset=node.col_offset, 

893 end_lineno=node.end_lineno, 

894 end_col_offset=node.end_col_offset, 

895 parent=parent, 

896 ) 

897 

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

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

900 newnode = nodes.Compare( 

901 lineno=node.lineno, 

902 col_offset=node.col_offset, 

903 end_lineno=node.end_lineno, 

904 end_col_offset=node.end_col_offset, 

905 parent=parent, 

906 ) 

907 newnode.postinit( 

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

909 [ 

910 ( 

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

912 self.visit(expr, newnode), 

913 ) 

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

915 ], 

916 ) 

917 return newnode 

918 

919 def visit_comprehension( 

920 self, node: ast.comprehension, parent: nodes.NodeNG 

921 ) -> nodes.Comprehension: 

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

923 newnode = nodes.Comprehension( 

924 parent=parent, 

925 # Comprehension nodes don't have these attributes 

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

927 lineno=None, 

928 col_offset=None, 

929 end_lineno=None, 

930 end_col_offset=None, 

931 ) 

932 newnode.postinit( 

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

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

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

936 bool(node.is_async), 

937 ) 

938 return newnode 

939 

940 def visit_decorators( 

941 self, 

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

943 parent: nodes.NodeNG, 

944 ) -> nodes.Decorators | None: 

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

946 

947 Note: Method not called by 'visit' 

948 """ 

949 if not node.decorator_list: 

950 return None 

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

952 # parent is an astroid.nodes.FunctionDef node 

953 

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

955 lineno = node.decorator_list[0].lineno 

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

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

958 

959 newnode = nodes.Decorators( 

960 lineno=lineno, 

961 col_offset=node.col_offset, 

962 end_lineno=end_lineno, 

963 end_col_offset=end_col_offset, 

964 parent=parent, 

965 ) 

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

967 return newnode 

968 

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

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

971 newnode = nodes.Delete( 

972 lineno=node.lineno, 

973 col_offset=node.col_offset, 

974 end_lineno=node.end_lineno, 

975 end_col_offset=node.end_col_offset, 

976 parent=parent, 

977 ) 

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

979 return newnode 

980 

981 def _visit_dict_items( 

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

983 ) -> Generator[tuple[nodes.NodeNG, nodes.NodeNG]]: 

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

985 rebuilt_key: nodes.NodeNG 

986 rebuilt_value = self.visit(value, newnode) 

987 if not key: 

988 # Extended unpacking 

989 rebuilt_key = nodes.DictUnpack( 

990 lineno=rebuilt_value.lineno, 

991 col_offset=rebuilt_value.col_offset, 

992 end_lineno=rebuilt_value.end_lineno, 

993 end_col_offset=rebuilt_value.end_col_offset, 

994 parent=parent, 

995 ) 

996 else: 

997 rebuilt_key = self.visit(key, newnode) 

998 yield rebuilt_key, rebuilt_value 

999 

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

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

1002 newnode = nodes.Dict( 

1003 lineno=node.lineno, 

1004 col_offset=node.col_offset, 

1005 end_lineno=node.end_lineno, 

1006 end_col_offset=node.end_col_offset, 

1007 parent=parent, 

1008 ) 

1009 items: list[tuple[InferenceResult, InferenceResult]] = list( 

1010 self._visit_dict_items(node, parent, newnode) 

1011 ) 

1012 newnode.postinit(items) 

1013 return newnode 

1014 

1015 def visit_dictcomp( 

1016 self, node: ast.DictComp, parent: nodes.NodeNG 

1017 ) -> nodes.DictComp: 

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

1019 newnode = nodes.DictComp( 

1020 lineno=node.lineno, 

1021 col_offset=node.col_offset, 

1022 end_lineno=node.end_lineno, 

1023 end_col_offset=node.end_col_offset, 

1024 parent=parent, 

1025 ) 

1026 newnode.postinit( 

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

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

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

1030 ) 

1031 return newnode 

1032 

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

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

1035 newnode = nodes.Expr( 

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(self.visit(node.value, newnode)) 

1043 return newnode 

1044 

1045 def visit_excepthandler( 

1046 self, node: ast.ExceptHandler, parent: nodes.NodeNG 

1047 ) -> nodes.ExceptHandler: 

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

1049 newnode = nodes.ExceptHandler( 

1050 lineno=node.lineno, 

1051 col_offset=node.col_offset, 

1052 end_lineno=node.end_lineno, 

1053 end_col_offset=node.end_col_offset, 

1054 parent=parent, 

1055 ) 

1056 newnode.postinit( 

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

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

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

1060 ) 

1061 return newnode 

1062 

1063 @overload 

1064 def _visit_for( 

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

1066 ) -> nodes.For: ... 

1067 

1068 @overload 

1069 def _visit_for( 

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

1071 ) -> nodes.AsyncFor: ... 

1072 

1073 def _visit_for( 

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

1075 ) -> _ForT: 

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

1077 newnode = cls( 

1078 lineno=node.lineno, 

1079 col_offset=node.col_offset, 

1080 end_lineno=node.end_lineno, 

1081 end_col_offset=node.end_col_offset, 

1082 parent=parent, 

1083 ) 

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

1085 newnode.postinit( 

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

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

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

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

1090 type_annotation=type_annotation, 

1091 ) 

1092 return newnode 

1093 

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

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

1096 

1097 def visit_importfrom( 

1098 self, node: ast.ImportFrom, parent: nodes.NodeNG 

1099 ) -> nodes.ImportFrom: 

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

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

1102 newnode = nodes.ImportFrom( 

1103 fromname=node.module or "", 

1104 names=names, 

1105 level=node.level or None, 

1106 lineno=node.lineno, 

1107 col_offset=node.col_offset, 

1108 end_lineno=node.end_lineno, 

1109 end_col_offset=node.end_col_offset, 

1110 parent=parent, 

1111 ) 

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

1113 self._import_from_nodes.append( 

1114 (newnode, self._global_names[-1].keys() if self._global_names else ()) 

1115 ) 

1116 return newnode 

1117 

1118 @overload 

1119 def _visit_functiondef( 

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

1121 ) -> nodes.FunctionDef: ... 

1122 

1123 @overload 

1124 def _visit_functiondef( 

1125 self, 

1126 cls: type[nodes.AsyncFunctionDef], 

1127 node: ast.AsyncFunctionDef, 

1128 parent: nodes.NodeNG, 

1129 ) -> nodes.AsyncFunctionDef: ... 

1130 

1131 def _visit_functiondef( 

1132 self, 

1133 cls: type[_FunctionT], 

1134 node: ast.FunctionDef | ast.AsyncFunctionDef, 

1135 parent: nodes.NodeNG, 

1136 ) -> _FunctionT: 

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

1138 self._global_names.append({}) 

1139 node, doc_ast_node = self._get_doc(node) 

1140 

1141 lineno = node.lineno 

1142 if node.decorator_list: 

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

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

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

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

1147 # first decorator to maintain backward compatibility. 

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

1149 # the framework for *years*. 

1150 lineno = node.decorator_list[0].lineno 

1151 

1152 newnode = cls( 

1153 name=node.name, 

1154 lineno=lineno, 

1155 col_offset=node.col_offset, 

1156 end_lineno=node.end_lineno, 

1157 end_col_offset=node.end_col_offset, 

1158 parent=parent, 

1159 ) 

1160 decorators = self.visit_decorators(node, newnode) 

1161 returns: nodes.NodeNG | None 

1162 if node.returns: 

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

1164 else: 

1165 returns = None 

1166 

1167 type_comment_args = type_comment_returns = None 

1168 type_comment_annotation = self.check_function_type_comment(node, newnode) 

1169 if type_comment_annotation: 

1170 type_comment_returns, type_comment_args = type_comment_annotation 

1171 newnode.postinit( 

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

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

1174 decorators=decorators, 

1175 returns=returns, 

1176 type_comment_returns=type_comment_returns, 

1177 type_comment_args=type_comment_args, 

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

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

1180 type_params=( 

1181 [self.visit(param, newnode) for param in node.type_params] 

1182 if PY312_PLUS 

1183 else [] 

1184 ), 

1185 ) 

1186 self._global_names.pop() 

1187 parent.set_local(newnode.name, newnode) 

1188 return newnode 

1189 

1190 def visit_functiondef( 

1191 self, node: ast.FunctionDef, parent: nodes.NodeNG 

1192 ) -> nodes.FunctionDef: 

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

1194 

1195 def visit_generatorexp( 

1196 self, node: ast.GeneratorExp, parent: nodes.NodeNG 

1197 ) -> nodes.GeneratorExp: 

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

1199 newnode = nodes.GeneratorExp( 

1200 lineno=node.lineno, 

1201 col_offset=node.col_offset, 

1202 end_lineno=node.end_lineno, 

1203 end_col_offset=node.end_col_offset, 

1204 parent=parent, 

1205 ) 

1206 newnode.postinit( 

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

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

1209 ) 

1210 return newnode 

1211 

1212 def visit_attribute( 

1213 self, node: ast.Attribute, parent: nodes.NodeNG 

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

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

1216 context = self._get_context(node) 

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

1218 if context == Context.Del: 

1219 # FIXME : maybe we should reintroduce and visit_delattr ? 

1220 # for instance, deactivating assign_ctx 

1221 newnode = nodes.DelAttr( 

1222 attrname=node.attr, 

1223 lineno=node.lineno, 

1224 col_offset=node.col_offset, 

1225 end_lineno=node.end_lineno, 

1226 end_col_offset=node.end_col_offset, 

1227 parent=parent, 

1228 ) 

1229 elif context == Context.Store: 

1230 newnode = nodes.AssignAttr( 

1231 attrname=node.attr, 

1232 lineno=node.lineno, 

1233 col_offset=node.col_offset, 

1234 end_lineno=node.end_lineno, 

1235 end_col_offset=node.end_col_offset, 

1236 parent=parent, 

1237 ) 

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

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

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

1241 # doesn't support ParamSpec 

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

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

1244 else: 

1245 newnode = nodes.Attribute( 

1246 attrname=node.attr, 

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 newnode.postinit(self.visit(node.value, newnode)) 

1254 return newnode 

1255 

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

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

1258 newnode = nodes.Global( 

1259 names=node.names, 

1260 lineno=node.lineno, 

1261 col_offset=node.col_offset, 

1262 end_lineno=node.end_lineno, 

1263 end_col_offset=node.end_col_offset, 

1264 parent=parent, 

1265 ) 

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

1267 for name in node.names: 

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

1269 return newnode 

1270 

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

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

1273 newnode = nodes.If( 

1274 lineno=node.lineno, 

1275 col_offset=node.col_offset, 

1276 end_lineno=node.end_lineno, 

1277 end_col_offset=node.end_col_offset, 

1278 parent=parent, 

1279 ) 

1280 newnode.postinit( 

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

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

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

1284 ) 

1285 return newnode 

1286 

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

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

1289 newnode = nodes.IfExp( 

1290 lineno=node.lineno, 

1291 col_offset=node.col_offset, 

1292 end_lineno=node.end_lineno, 

1293 end_col_offset=node.end_col_offset, 

1294 parent=parent, 

1295 ) 

1296 newnode.postinit( 

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

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

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

1300 ) 

1301 return newnode 

1302 

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

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

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

1306 newnode = nodes.Import( 

1307 names=names, 

1308 lineno=node.lineno, 

1309 col_offset=node.col_offset, 

1310 end_lineno=node.end_lineno, 

1311 end_col_offset=node.end_col_offset, 

1312 parent=parent, 

1313 ) 

1314 # save import names in parent's locals: 

1315 for name, asname in newnode.names: 

1316 name = (asname or name).split(".")[0] 

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

1318 parent.root().set_local(name, newnode) 

1319 else: 

1320 parent.set_local(name, newnode) 

1321 return newnode 

1322 

1323 def visit_joinedstr( 

1324 self, node: ast.JoinedStr, parent: nodes.NodeNG 

1325 ) -> nodes.JoinedStr: 

1326 newnode = nodes.JoinedStr( 

1327 lineno=node.lineno, 

1328 col_offset=node.col_offset, 

1329 end_lineno=node.end_lineno, 

1330 end_col_offset=node.end_col_offset, 

1331 parent=parent, 

1332 ) 

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

1334 return newnode 

1335 

1336 def visit_formattedvalue( 

1337 self, node: ast.FormattedValue, parent: nodes.NodeNG 

1338 ) -> nodes.FormattedValue: 

1339 newnode = nodes.FormattedValue( 

1340 lineno=node.lineno, 

1341 col_offset=node.col_offset, 

1342 end_lineno=node.end_lineno, 

1343 end_col_offset=node.end_col_offset, 

1344 parent=parent, 

1345 ) 

1346 newnode.postinit( 

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

1348 conversion=node.conversion, 

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

1350 ) 

1351 return newnode 

1352 

1353 def visit_namedexpr( 

1354 self, node: ast.NamedExpr, parent: nodes.NodeNG 

1355 ) -> nodes.NamedExpr: 

1356 newnode = nodes.NamedExpr( 

1357 lineno=node.lineno, 

1358 col_offset=node.col_offset, 

1359 end_lineno=node.end_lineno, 

1360 end_col_offset=node.end_col_offset, 

1361 parent=parent, 

1362 ) 

1363 newnode.postinit( 

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

1365 ) 

1366 return newnode 

1367 

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

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

1370 newnode = nodes.Keyword( 

1371 arg=node.arg, 

1372 # position attributes added in 3.9 

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

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

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

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

1377 parent=parent, 

1378 ) 

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

1380 return newnode 

1381 

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

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

1384 newnode = nodes.Lambda( 

1385 lineno=node.lineno, 

1386 col_offset=node.col_offset, 

1387 end_lineno=node.end_lineno, 

1388 end_col_offset=node.end_col_offset, 

1389 parent=parent, 

1390 ) 

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

1392 return newnode 

1393 

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

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

1396 context = self._get_context(node) 

1397 newnode = nodes.List( 

1398 ctx=context, 

1399 lineno=node.lineno, 

1400 col_offset=node.col_offset, 

1401 end_lineno=node.end_lineno, 

1402 end_col_offset=node.end_col_offset, 

1403 parent=parent, 

1404 ) 

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

1406 return newnode 

1407 

1408 def visit_listcomp( 

1409 self, node: ast.ListComp, parent: nodes.NodeNG 

1410 ) -> nodes.ListComp: 

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

1412 newnode = nodes.ListComp( 

1413 lineno=node.lineno, 

1414 col_offset=node.col_offset, 

1415 end_lineno=node.end_lineno, 

1416 end_col_offset=node.end_col_offset, 

1417 parent=parent, 

1418 ) 

1419 newnode.postinit( 

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

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

1422 ) 

1423 return newnode 

1424 

1425 def visit_name( 

1426 self, node: ast.Name, parent: nodes.NodeNG 

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

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

1429 context = self._get_context(node) 

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

1431 if context == Context.Del: 

1432 newnode = nodes.DelName( 

1433 name=node.id, 

1434 lineno=node.lineno, 

1435 col_offset=node.col_offset, 

1436 end_lineno=node.end_lineno, 

1437 end_col_offset=node.end_col_offset, 

1438 parent=parent, 

1439 ) 

1440 elif context == Context.Store: 

1441 newnode = nodes.AssignName( 

1442 name=node.id, 

1443 lineno=node.lineno, 

1444 col_offset=node.col_offset, 

1445 end_lineno=node.end_lineno, 

1446 end_col_offset=node.end_col_offset, 

1447 parent=parent, 

1448 ) 

1449 else: 

1450 newnode = nodes.Name( 

1451 name=node.id, 

1452 lineno=node.lineno, 

1453 col_offset=node.col_offset, 

1454 end_lineno=node.end_lineno, 

1455 end_col_offset=node.end_col_offset, 

1456 parent=parent, 

1457 ) 

1458 # XXX REMOVE me : 

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

1460 newnode = cast((nodes.AssignName | nodes.DelName), newnode) 

1461 self._save_assignment(newnode) 

1462 return newnode 

1463 

1464 def visit_nonlocal( 

1465 self, node: ast.Nonlocal, parent: nodes.NodeNG 

1466 ) -> nodes.Nonlocal: 

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

1468 return nodes.Nonlocal( 

1469 names=node.names, 

1470 lineno=node.lineno, 

1471 col_offset=node.col_offset, 

1472 end_lineno=node.end_lineno, 

1473 end_col_offset=node.end_col_offset, 

1474 parent=parent, 

1475 ) 

1476 

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

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

1479 return nodes.Const( 

1480 value=node.value, 

1481 kind=node.kind, 

1482 lineno=node.lineno, 

1483 col_offset=node.col_offset, 

1484 end_lineno=node.end_lineno, 

1485 end_col_offset=node.end_col_offset, 

1486 parent=parent, 

1487 ) 

1488 

1489 def visit_paramspec( 

1490 self, node: ast.ParamSpec, parent: nodes.NodeNG 

1491 ) -> nodes.ParamSpec: 

1492 """Visit a ParamSpec node by returning a fresh instance of it.""" 

1493 newnode = nodes.ParamSpec( 

1494 lineno=node.lineno, 

1495 col_offset=node.col_offset, 

1496 end_lineno=node.end_lineno, 

1497 end_col_offset=node.end_col_offset, 

1498 parent=parent, 

1499 ) 

1500 # Add AssignName node for 'node.name' 

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

1502 newnode.postinit( 

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

1504 default_value=( 

1505 self.visit(node.default_value, newnode) if PY313_PLUS else None 

1506 ), 

1507 ) 

1508 return newnode 

1509 

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

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

1512 return nodes.Pass( 

1513 lineno=node.lineno, 

1514 col_offset=node.col_offset, 

1515 end_lineno=node.end_lineno, 

1516 end_col_offset=node.end_col_offset, 

1517 parent=parent, 

1518 ) 

1519 

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

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

1522 newnode = nodes.Raise( 

1523 lineno=node.lineno, 

1524 col_offset=node.col_offset, 

1525 end_lineno=node.end_lineno, 

1526 end_col_offset=node.end_col_offset, 

1527 parent=parent, 

1528 ) 

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

1530 newnode.postinit( 

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

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

1533 ) 

1534 return newnode 

1535 

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

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

1538 newnode = nodes.Return( 

1539 lineno=node.lineno, 

1540 col_offset=node.col_offset, 

1541 end_lineno=node.end_lineno, 

1542 end_col_offset=node.end_col_offset, 

1543 parent=parent, 

1544 ) 

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

1546 return newnode 

1547 

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

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

1550 newnode = nodes.Set( 

1551 lineno=node.lineno, 

1552 col_offset=node.col_offset, 

1553 end_lineno=node.end_lineno, 

1554 end_col_offset=node.end_col_offset, 

1555 parent=parent, 

1556 ) 

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

1558 return newnode 

1559 

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

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

1562 newnode = nodes.SetComp( 

1563 lineno=node.lineno, 

1564 col_offset=node.col_offset, 

1565 end_lineno=node.end_lineno, 

1566 end_col_offset=node.end_col_offset, 

1567 parent=parent, 

1568 ) 

1569 newnode.postinit( 

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

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

1572 ) 

1573 return newnode 

1574 

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

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

1577 newnode = nodes.Slice( 

1578 # position attributes added in 3.9 

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

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

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

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

1583 parent=parent, 

1584 ) 

1585 newnode.postinit( 

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

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

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

1589 ) 

1590 return newnode 

1591 

1592 def visit_subscript( 

1593 self, node: ast.Subscript, parent: nodes.NodeNG 

1594 ) -> nodes.Subscript: 

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

1596 context = self._get_context(node) 

1597 newnode = nodes.Subscript( 

1598 ctx=context, 

1599 lineno=node.lineno, 

1600 col_offset=node.col_offset, 

1601 end_lineno=node.end_lineno, 

1602 end_col_offset=node.end_col_offset, 

1603 parent=parent, 

1604 ) 

1605 newnode.postinit( 

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

1607 ) 

1608 return newnode 

1609 

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

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

1612 context = self._get_context(node) 

1613 newnode = nodes.Starred( 

1614 ctx=context, 

1615 lineno=node.lineno, 

1616 col_offset=node.col_offset, 

1617 end_lineno=node.end_lineno, 

1618 end_col_offset=node.end_col_offset, 

1619 parent=parent, 

1620 ) 

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

1622 return newnode 

1623 

1624 def visit_try(self, node: ast.Try, parent: nodes.NodeNG) -> nodes.Try: 

1625 """Visit a Try node by returning a fresh instance of it""" 

1626 newnode = nodes.Try( 

1627 lineno=node.lineno, 

1628 col_offset=node.col_offset, 

1629 end_lineno=node.end_lineno, 

1630 end_col_offset=node.end_col_offset, 

1631 parent=parent, 

1632 ) 

1633 newnode.postinit( 

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

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

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

1637 finalbody=[self.visit(child, newnode) for child in node.finalbody], 

1638 ) 

1639 return newnode 

1640 

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

1642 newnode = nodes.TryStar( 

1643 lineno=node.lineno, 

1644 col_offset=node.col_offset, 

1645 end_lineno=node.end_lineno, 

1646 end_col_offset=node.end_col_offset, 

1647 parent=parent, 

1648 ) 

1649 newnode.postinit( 

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

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

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

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

1654 ) 

1655 return newnode 

1656 

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

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

1659 context = self._get_context(node) 

1660 newnode = nodes.Tuple( 

1661 ctx=context, 

1662 lineno=node.lineno, 

1663 col_offset=node.col_offset, 

1664 end_lineno=node.end_lineno, 

1665 end_col_offset=node.end_col_offset, 

1666 parent=parent, 

1667 ) 

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

1669 return newnode 

1670 

1671 def visit_typealias( 

1672 self, node: ast.TypeAlias, parent: nodes.NodeNG 

1673 ) -> nodes.TypeAlias: 

1674 """Visit a TypeAlias node by returning a fresh instance of it.""" 

1675 newnode = nodes.TypeAlias( 

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( 

1683 name=self.visit(node.name, newnode), 

1684 type_params=[self.visit(p, newnode) for p in node.type_params], 

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

1686 ) 

1687 return newnode 

1688 

1689 def visit_typevar(self, node: ast.TypeVar, parent: nodes.NodeNG) -> nodes.TypeVar: 

1690 """Visit a TypeVar node by returning a fresh instance of it.""" 

1691 newnode = nodes.TypeVar( 

1692 lineno=node.lineno, 

1693 col_offset=node.col_offset, 

1694 end_lineno=node.end_lineno, 

1695 end_col_offset=node.end_col_offset, 

1696 parent=parent, 

1697 ) 

1698 # Add AssignName node for 'node.name' 

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

1700 newnode.postinit( 

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

1702 bound=self.visit(node.bound, newnode), 

1703 default_value=( 

1704 self.visit(node.default_value, newnode) if PY313_PLUS else None 

1705 ), 

1706 ) 

1707 return newnode 

1708 

1709 def visit_typevartuple( 

1710 self, node: ast.TypeVarTuple, parent: nodes.NodeNG 

1711 ) -> nodes.TypeVarTuple: 

1712 """Visit a TypeVarTuple node by returning a fresh instance of it.""" 

1713 newnode = nodes.TypeVarTuple( 

1714 lineno=node.lineno, 

1715 col_offset=node.col_offset, 

1716 end_lineno=node.end_lineno, 

1717 end_col_offset=node.end_col_offset, 

1718 parent=parent, 

1719 ) 

1720 # Add AssignName node for 'node.name' 

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

1722 newnode.postinit( 

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

1724 default_value=( 

1725 self.visit(node.default_value, newnode) if PY313_PLUS else None 

1726 ), 

1727 ) 

1728 return newnode 

1729 

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

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

1732 newnode = nodes.UnaryOp( 

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

1734 lineno=node.lineno, 

1735 col_offset=node.col_offset, 

1736 end_lineno=node.end_lineno, 

1737 end_col_offset=node.end_col_offset, 

1738 parent=parent, 

1739 ) 

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

1741 return newnode 

1742 

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

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

1745 newnode = nodes.While( 

1746 lineno=node.lineno, 

1747 col_offset=node.col_offset, 

1748 end_lineno=node.end_lineno, 

1749 end_col_offset=node.end_col_offset, 

1750 parent=parent, 

1751 ) 

1752 newnode.postinit( 

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

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

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

1756 ) 

1757 return newnode 

1758 

1759 @overload 

1760 def _visit_with( 

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

1762 ) -> nodes.With: ... 

1763 

1764 @overload 

1765 def _visit_with( 

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

1767 ) -> nodes.AsyncWith: ... 

1768 

1769 def _visit_with( 

1770 self, 

1771 cls: type[_WithT], 

1772 node: ast.With | ast.AsyncWith, 

1773 parent: nodes.NodeNG, 

1774 ) -> _WithT: 

1775 newnode = cls( 

1776 lineno=node.lineno, 

1777 col_offset=node.col_offset, 

1778 end_lineno=node.end_lineno, 

1779 end_col_offset=node.end_col_offset, 

1780 parent=parent, 

1781 ) 

1782 

1783 def visit_child( 

1784 child: ast.withitem, 

1785 ) -> tuple[nodes.NodeNG, nodes.NodeNG | None]: 

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

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

1788 return expr, var 

1789 

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

1791 newnode.postinit( 

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

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

1794 type_annotation=type_annotation, 

1795 ) 

1796 return newnode 

1797 

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

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

1800 

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

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

1803 newnode = nodes.Yield( 

1804 lineno=node.lineno, 

1805 col_offset=node.col_offset, 

1806 end_lineno=node.end_lineno, 

1807 end_col_offset=node.end_col_offset, 

1808 parent=parent, 

1809 ) 

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

1811 return newnode 

1812 

1813 def visit_yieldfrom( 

1814 self, node: ast.YieldFrom, parent: nodes.NodeNG 

1815 ) -> nodes.NodeNG: 

1816 newnode = nodes.YieldFrom( 

1817 lineno=node.lineno, 

1818 col_offset=node.col_offset, 

1819 end_lineno=node.end_lineno, 

1820 end_col_offset=node.end_col_offset, 

1821 parent=parent, 

1822 ) 

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

1824 return newnode 

1825 

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

1827 newnode = nodes.Match( 

1828 lineno=node.lineno, 

1829 col_offset=node.col_offset, 

1830 end_lineno=node.end_lineno, 

1831 end_col_offset=node.end_col_offset, 

1832 parent=parent, 

1833 ) 

1834 newnode.postinit( 

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

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

1837 ) 

1838 return newnode 

1839 

1840 def visit_matchcase( 

1841 self, node: ast.match_case, parent: nodes.NodeNG 

1842 ) -> nodes.MatchCase: 

1843 newnode = nodes.MatchCase(parent=parent) 

1844 newnode.postinit( 

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

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

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

1848 ) 

1849 return newnode 

1850 

1851 def visit_matchvalue( 

1852 self, node: ast.MatchValue, parent: nodes.NodeNG 

1853 ) -> nodes.MatchValue: 

1854 newnode = nodes.MatchValue( 

1855 lineno=node.lineno, 

1856 col_offset=node.col_offset, 

1857 end_lineno=node.end_lineno, 

1858 end_col_offset=node.end_col_offset, 

1859 parent=parent, 

1860 ) 

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

1862 return newnode 

1863 

1864 def visit_matchsingleton( 

1865 self, node: ast.MatchSingleton, parent: nodes.NodeNG 

1866 ) -> nodes.MatchSingleton: 

1867 return nodes.MatchSingleton( 

1868 value=node.value, 

1869 lineno=node.lineno, 

1870 col_offset=node.col_offset, 

1871 end_lineno=node.end_lineno, 

1872 end_col_offset=node.end_col_offset, 

1873 parent=parent, 

1874 ) 

1875 

1876 def visit_matchsequence( 

1877 self, node: ast.MatchSequence, parent: nodes.NodeNG 

1878 ) -> nodes.MatchSequence: 

1879 newnode = nodes.MatchSequence( 

1880 lineno=node.lineno, 

1881 col_offset=node.col_offset, 

1882 end_lineno=node.end_lineno, 

1883 end_col_offset=node.end_col_offset, 

1884 parent=parent, 

1885 ) 

1886 newnode.postinit( 

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

1888 ) 

1889 return newnode 

1890 

1891 def visit_matchmapping( 

1892 self, node: ast.MatchMapping, parent: nodes.NodeNG 

1893 ) -> nodes.MatchMapping: 

1894 newnode = nodes.MatchMapping( 

1895 lineno=node.lineno, 

1896 col_offset=node.col_offset, 

1897 end_lineno=node.end_lineno, 

1898 end_col_offset=node.end_col_offset, 

1899 parent=parent, 

1900 ) 

1901 # Add AssignName node for 'node.name' 

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

1903 newnode.postinit( 

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

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

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

1907 ) 

1908 return newnode 

1909 

1910 def visit_matchclass( 

1911 self, node: ast.MatchClass, parent: nodes.NodeNG 

1912 ) -> nodes.MatchClass: 

1913 newnode = nodes.MatchClass( 

1914 lineno=node.lineno, 

1915 col_offset=node.col_offset, 

1916 end_lineno=node.end_lineno, 

1917 end_col_offset=node.end_col_offset, 

1918 parent=parent, 

1919 ) 

1920 newnode.postinit( 

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

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

1923 kwd_attrs=node.kwd_attrs, 

1924 kwd_patterns=[ 

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

1926 ], 

1927 ) 

1928 return newnode 

1929 

1930 def visit_matchstar( 

1931 self, node: ast.MatchStar, parent: nodes.NodeNG 

1932 ) -> nodes.MatchStar: 

1933 newnode = nodes.MatchStar( 

1934 lineno=node.lineno, 

1935 col_offset=node.col_offset, 

1936 end_lineno=node.end_lineno, 

1937 end_col_offset=node.end_col_offset, 

1938 parent=parent, 

1939 ) 

1940 # Add AssignName node for 'node.name' 

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

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

1943 return newnode 

1944 

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

1946 newnode = nodes.MatchAs( 

1947 lineno=node.lineno, 

1948 col_offset=node.col_offset, 

1949 end_lineno=node.end_lineno, 

1950 end_col_offset=node.end_col_offset, 

1951 parent=parent, 

1952 ) 

1953 # Add AssignName node for 'node.name' 

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

1955 newnode.postinit( 

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

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

1958 ) 

1959 return newnode 

1960 

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

1962 newnode = nodes.MatchOr( 

1963 lineno=node.lineno, 

1964 col_offset=node.col_offset, 

1965 end_lineno=node.end_lineno, 

1966 end_col_offset=node.end_col_offset, 

1967 parent=parent, 

1968 ) 

1969 newnode.postinit( 

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

1971 ) 

1972 return newnode 

1973 

1974 if sys.version_info >= (3, 14): 

1975 

1976 def visit_templatestr( 

1977 self, node: ast.TemplateStr, parent: nodes.NodeNG 

1978 ) -> nodes.TemplateStr: 

1979 newnode = nodes.TemplateStr( 

1980 lineno=node.lineno, 

1981 col_offset=node.col_offset, 

1982 end_lineno=node.end_lineno, 

1983 end_col_offset=node.end_col_offset, 

1984 parent=parent, 

1985 ) 

1986 newnode.postinit( 

1987 values=[self.visit(value, newnode) for value in node.values] 

1988 ) 

1989 return newnode 

1990 

1991 def visit_interpolation( 

1992 self, node: ast.Interpolation, parent: nodes.NodeNG 

1993 ) -> nodes.Interpolation: 

1994 newnode = nodes.Interpolation( 

1995 lineno=node.lineno, 

1996 col_offset=node.col_offset, 

1997 end_lineno=node.end_lineno, 

1998 end_col_offset=node.end_col_offset, 

1999 parent=parent, 

2000 ) 

2001 newnode.postinit( 

2002 value=self.visit(node.value, parent), 

2003 str=node.str, 

2004 conversion=node.conversion, 

2005 format_spec=self.visit(node.format_spec, parent), 

2006 ) 

2007 return newnode