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

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

676 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 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 PY312_PLUS, Context 

22from astroid.manager import AstroidManager 

23from astroid.nodes import NodeNG 

24from astroid.nodes.node_classes import AssignName 

25from astroid.nodes.utils import Position 

26from astroid.typing import InferenceResult 

27 

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

29 "arguments": "Arguments", 

30 "comprehension": "Comprehension", 

31 "ListCompFor": "Comprehension", 

32 "GenExprFor": "Comprehension", 

33 "excepthandler": "ExceptHandler", 

34 "keyword": "Keyword", 

35 "match_case": "MatchCase", 

36} 

37 

38 

39T_Doc = TypeVar( 

40 "T_Doc", 

41 "ast.Module", 

42 "ast.ClassDef", 

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

44) 

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

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

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

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

49 

50 

51# noinspection PyMethodMayBeStatic 

52class TreeRebuilder: 

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

54 

55 def __init__( 

56 self, 

57 manager: AstroidManager, 

58 parser_module: ParserModule | None = None, 

59 data: str | None = None, 

60 ) -> None: 

61 self._manager = manager 

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

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

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

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

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

67 

68 if parser_module is None: 

69 self._parser_module = get_parser_module() 

70 else: 

71 self._parser_module = parser_module 

72 

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

74 """Return the doc ast node.""" 

75 try: 

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

77 first_value = node.body[0].value 

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

79 first_value.value, str 

80 ): 

81 doc_ast_node = first_value 

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

83 return node, doc_ast_node 

84 except IndexError: 

85 pass # ast built from scratch 

86 return node, None 

87 

88 def _get_context( 

89 self, 

90 node: ( 

91 ast.Attribute 

92 | ast.List 

93 | ast.Name 

94 | ast.Subscript 

95 | ast.Starred 

96 | ast.Tuple 

97 ), 

98 ) -> Context: 

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

100 

101 def _get_position_info( 

102 self, 

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

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

105 ) -> Position | None: 

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

107 

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

109 and the class / function name. 

110 

111 >>> @decorator 

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

113 >>> ^^^^^^^^^^^^^^^^^^^ 

114 """ 

115 if not self._data: 

116 return None 

117 end_lineno = node.end_lineno 

118 if node.body: 

119 end_lineno = node.body[0].lineno 

120 # pylint: disable-next=unsubscriptable-object 

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

122 

123 start_token: TokenInfo | None = None 

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

125 if isinstance(parent, nodes.AsyncFunctionDef): 

126 search_token = "async" 

127 elif isinstance(parent, nodes.FunctionDef): 

128 search_token = "def" 

129 else: 

130 search_token = "class" 

131 

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

133 if ( 

134 start_token is not None 

135 and t.type == token.NAME 

136 and t.string == node.name 

137 ): 

138 break 

139 if t.type in keyword_tokens: 

140 if t.string == search_token: 

141 start_token = t 

142 continue 

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

144 continue 

145 start_token = None 

146 else: 

147 return None 

148 

149 return Position( 

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

151 col_offset=start_token.start[1], 

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

153 end_col_offset=t.end[1], 

154 ) 

155 

156 def visit_module( 

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

158 ) -> nodes.Module: 

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

160 

161 Note: Method not called by 'visit' 

162 """ 

163 node, doc_ast_node = self._get_doc(node) 

164 newnode = nodes.Module( 

165 name=modname, 

166 file=modpath, 

167 path=[modpath], 

168 package=package, 

169 ) 

170 newnode.postinit( 

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

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

173 ) 

174 return newnode 

175 

176 if TYPE_CHECKING: # noqa: C901 

177 

178 @overload 

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

180 

181 @overload 

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

183 

184 @overload 

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

186 

187 @overload 

188 def visit( 

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

190 ) -> nodes.AsyncFunctionDef: ... 

191 

192 @overload 

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

194 

195 @overload 

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

197 

198 @overload 

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

200 

201 @overload 

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

203 

204 @overload 

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

206 

207 @overload 

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

209 

210 @overload 

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

212 

213 @overload 

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

215 

216 @overload 

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

218 

219 @overload 

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

221 

222 @overload 

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

224 

225 @overload 

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

227 

228 @overload 

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

230 

231 @overload 

232 def visit( 

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

234 ) -> nodes.Comprehension: ... 

235 

236 @overload 

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

238 

239 @overload 

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

241 

242 @overload 

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

244 

245 @overload 

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

247 

248 @overload 

249 def visit( 

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

251 ) -> nodes.ExceptHandler: ... 

252 

253 @overload 

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

255 

256 @overload 

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

258 

259 @overload 

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

261 

262 @overload 

263 def visit( 

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

265 ) -> nodes.GeneratorExp: ... 

266 

267 @overload 

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

269 

270 @overload 

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

272 

273 @overload 

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

275 

276 @overload 

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

278 

279 @overload 

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

281 

282 @overload 

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

284 

285 @overload 

286 def visit( 

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

288 ) -> nodes.FormattedValue: ... 

289 

290 @overload 

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

292 

293 @overload 

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

295 

296 @overload 

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

298 

299 @overload 

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

301 

302 @overload 

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

304 

305 @overload 

306 def visit( 

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

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

309 

310 @overload 

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

312 

313 @overload 

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

315 

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

317 

318 @overload 

319 def visit(self, node: ast.ParamSpec, parent: NodeNG) -> nodes.ParamSpec: ... 

320 

321 @overload 

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

323 

324 @overload 

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

326 

327 @overload 

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

329 

330 @overload 

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

332 

333 @overload 

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

335 

336 @overload 

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

338 

339 @overload 

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

341 

342 @overload 

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

344 

345 @overload 

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

347 

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

349 

350 @overload 

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

352 

353 @overload 

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

355 

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

357 

358 @overload 

359 def visit(self, node: ast.TypeAlias, parent: NodeNG) -> nodes.TypeAlias: ... 

360 

361 @overload 

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

363 

364 @overload 

365 def visit( 

366 self, node: ast.TypeVarTuple, parent: NodeNG 

367 ) -> nodes.TypeVarTuple: ... 

368 

369 @overload 

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

371 

372 @overload 

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

374 

375 @overload 

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

377 

378 @overload 

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

380 

381 @overload 

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

383 

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

385 

386 @overload 

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

388 

389 @overload 

390 def visit( 

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

392 ) -> nodes.MatchCase: ... 

393 

394 @overload 

395 def visit( 

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

397 ) -> nodes.MatchValue: ... 

398 

399 @overload 

400 def visit( 

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

402 ) -> nodes.MatchSingleton: ... 

403 

404 @overload 

405 def visit( 

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

407 ) -> nodes.MatchSequence: ... 

408 

409 @overload 

410 def visit( 

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

412 ) -> nodes.MatchMapping: ... 

413 

414 @overload 

415 def visit( 

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

417 ) -> nodes.MatchClass: ... 

418 

419 @overload 

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

421 

422 @overload 

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

424 

425 @overload 

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

427 

428 @overload 

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

430 

431 @overload 

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

433 

434 @overload 

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

436 

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

438 if node is None: 

439 return None 

440 cls = node.__class__ 

441 if cls in self._visit_meths: 

442 visit_method = self._visit_meths[cls] 

443 else: 

444 cls_name = cls.__name__ 

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

446 visit_method = getattr(self, visit_name) 

447 self._visit_meths[cls] = visit_method 

448 return visit_method(node, parent) 

449 

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

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

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

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

454 else: 

455 assert node.parent 

456 assert node.name 

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

458 

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

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

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

462 

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

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

465 vararg: str | None = None 

466 kwarg: str | None = None 

467 vararg_node = node.vararg 

468 kwarg_node = node.kwarg 

469 

470 newnode = nodes.Arguments( 

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

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

473 parent, 

474 ( 

475 AssignName( 

476 vararg_node.arg, 

477 vararg_node.lineno, 

478 vararg_node.col_offset, 

479 parent, 

480 end_lineno=vararg_node.end_lineno, 

481 end_col_offset=vararg_node.end_col_offset, 

482 ) 

483 if vararg_node 

484 else None 

485 ), 

486 ( 

487 AssignName( 

488 kwarg_node.arg, 

489 kwarg_node.lineno, 

490 kwarg_node.col_offset, 

491 parent, 

492 end_lineno=kwarg_node.end_lineno, 

493 end_col_offset=kwarg_node.end_col_offset, 

494 ) 

495 if kwarg_node 

496 else None 

497 ), 

498 ) 

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

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

501 varargannotation: NodeNG | None = None 

502 kwargannotation: NodeNG | None = None 

503 if node.vararg: 

504 vararg = node.vararg.arg 

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

506 if node.kwarg: 

507 kwarg = node.kwarg.arg 

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

509 

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

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

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

513 kwonlyargs_annotations = [ 

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

515 ] 

516 

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

518 posonlyargs_annotations = [ 

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

520 ] 

521 type_comment_args = [ 

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

523 ] 

524 type_comment_kwonlyargs = [ 

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

526 ] 

527 type_comment_posonlyargs = [ 

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

529 ] 

530 

531 newnode.postinit( 

532 args=args, 

533 defaults=defaults, 

534 kwonlyargs=kwonlyargs, 

535 posonlyargs=posonlyargs, 

536 kw_defaults=kw_defaults, 

537 annotations=annotations, 

538 kwonlyargs_annotations=kwonlyargs_annotations, 

539 posonlyargs_annotations=posonlyargs_annotations, 

540 varargannotation=varargannotation, 

541 kwargannotation=kwargannotation, 

542 type_comment_args=type_comment_args, 

543 type_comment_kwonlyargs=type_comment_kwonlyargs, 

544 type_comment_posonlyargs=type_comment_posonlyargs, 

545 ) 

546 # save argument names in locals: 

547 assert newnode.parent 

548 if vararg: 

549 newnode.parent.set_local(vararg, newnode) 

550 if kwarg: 

551 newnode.parent.set_local(kwarg, newnode) 

552 return newnode 

553 

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

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

556 newnode = nodes.Assert( 

557 lineno=node.lineno, 

558 col_offset=node.col_offset, 

559 end_lineno=node.end_lineno, 

560 end_col_offset=node.end_col_offset, 

561 parent=parent, 

562 ) 

563 msg: NodeNG | None = None 

564 if node.msg: 

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

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

567 return newnode 

568 

569 def check_type_comment( 

570 self, 

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

572 parent: ( 

573 nodes.Assign 

574 | nodes.Arguments 

575 | nodes.For 

576 | nodes.AsyncFor 

577 | nodes.With 

578 | nodes.AsyncWith 

579 ), 

580 ) -> NodeNG | None: 

581 if not node.type_comment: 

582 return None 

583 

584 try: 

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

586 except SyntaxError: 

587 # Invalid type comment, just skip it. 

588 return None 

589 

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

591 # without any nodes in the body. 

592 if not type_comment_ast.body: 

593 return None 

594 

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

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

597 return None 

598 

599 return type_object.value 

600 

601 def check_function_type_comment( 

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

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

604 if not node.type_comment: 

605 return None 

606 

607 try: 

608 type_comment_ast = parse_function_type_comment(node.type_comment) 

609 except SyntaxError: 

610 # Invalid type comment, just skip it. 

611 return None 

612 

613 if not type_comment_ast: 

614 return None 

615 

616 returns: NodeNG | None = None 

617 argtypes: list[NodeNG] = [ 

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

619 ] 

620 if type_comment_ast.returns: 

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

622 

623 return returns, argtypes 

624 

625 def visit_asyncfunctiondef( 

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

627 ) -> nodes.AsyncFunctionDef: 

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

629 

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

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

632 

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

634 newnode = nodes.Await( 

635 lineno=node.lineno, 

636 col_offset=node.col_offset, 

637 end_lineno=node.end_lineno, 

638 end_col_offset=node.end_col_offset, 

639 parent=parent, 

640 ) 

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

642 return newnode 

643 

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

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

646 

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

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

649 newnode = nodes.Assign( 

650 lineno=node.lineno, 

651 col_offset=node.col_offset, 

652 end_lineno=node.end_lineno, 

653 end_col_offset=node.end_col_offset, 

654 parent=parent, 

655 ) 

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

657 newnode.postinit( 

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

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

660 type_annotation=type_annotation, 

661 ) 

662 return newnode 

663 

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

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

666 newnode = nodes.AnnAssign( 

667 lineno=node.lineno, 

668 col_offset=node.col_offset, 

669 end_lineno=node.end_lineno, 

670 end_col_offset=node.end_col_offset, 

671 parent=parent, 

672 ) 

673 newnode.postinit( 

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

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

676 simple=node.simple, 

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

678 ) 

679 return newnode 

680 

681 @overload 

682 def visit_assignname( 

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

684 ) -> nodes.AssignName: ... 

685 

686 @overload 

687 def visit_assignname( 

688 self, node: ast.AST, parent: NodeNG, node_name: None 

689 ) -> None: ... 

690 

691 def visit_assignname( 

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

693 ) -> nodes.AssignName | None: 

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

695 

696 Note: Method not called by 'visit' 

697 """ 

698 if node_name is None: 

699 return None 

700 newnode = nodes.AssignName( 

701 name=node_name, 

702 lineno=node.lineno, 

703 col_offset=node.col_offset, 

704 end_lineno=node.end_lineno, 

705 end_col_offset=node.end_col_offset, 

706 parent=parent, 

707 ) 

708 self._save_assignment(newnode) 

709 return newnode 

710 

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

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

713 newnode = nodes.AugAssign( 

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

715 lineno=node.lineno, 

716 col_offset=node.col_offset, 

717 end_lineno=node.end_lineno, 

718 end_col_offset=node.end_col_offset, 

719 parent=parent, 

720 ) 

721 newnode.postinit( 

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

723 ) 

724 return newnode 

725 

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

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

728 newnode = nodes.BinOp( 

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

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

738 ) 

739 return newnode 

740 

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

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

743 newnode = nodes.BoolOp( 

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

745 lineno=node.lineno, 

746 col_offset=node.col_offset, 

747 end_lineno=node.end_lineno, 

748 end_col_offset=node.end_col_offset, 

749 parent=parent, 

750 ) 

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

752 return newnode 

753 

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

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

756 return nodes.Break( 

757 lineno=node.lineno, 

758 col_offset=node.col_offset, 

759 end_lineno=node.end_lineno, 

760 end_col_offset=node.end_col_offset, 

761 parent=parent, 

762 ) 

763 

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

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

766 newnode = nodes.Call( 

767 lineno=node.lineno, 

768 col_offset=node.col_offset, 

769 end_lineno=node.end_lineno, 

770 end_col_offset=node.end_col_offset, 

771 parent=parent, 

772 ) 

773 newnode.postinit( 

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

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

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

777 ) 

778 return newnode 

779 

780 def visit_classdef( 

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

782 ) -> nodes.ClassDef: 

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

784 node, doc_ast_node = self._get_doc(node) 

785 newnode = nodes.ClassDef( 

786 name=node.name, 

787 lineno=node.lineno, 

788 col_offset=node.col_offset, 

789 end_lineno=node.end_lineno, 

790 end_col_offset=node.end_col_offset, 

791 parent=parent, 

792 ) 

793 metaclass = None 

794 for keyword in node.keywords: 

795 if keyword.arg == "metaclass": 

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

797 break 

798 decorators = self.visit_decorators(node, newnode) 

799 newnode.postinit( 

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

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

802 decorators, 

803 newstyle, 

804 metaclass, 

805 [ 

806 self.visit(kwd, newnode) 

807 for kwd in node.keywords 

808 if kwd.arg != "metaclass" 

809 ], 

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

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

812 type_params=( 

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

814 if PY312_PLUS 

815 else [] 

816 ), 

817 ) 

818 parent.set_local(newnode.name, newnode) 

819 return newnode 

820 

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

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

823 return nodes.Continue( 

824 lineno=node.lineno, 

825 col_offset=node.col_offset, 

826 end_lineno=node.end_lineno, 

827 end_col_offset=node.end_col_offset, 

828 parent=parent, 

829 ) 

830 

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

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

833 newnode = nodes.Compare( 

834 lineno=node.lineno, 

835 col_offset=node.col_offset, 

836 end_lineno=node.end_lineno, 

837 end_col_offset=node.end_col_offset, 

838 parent=parent, 

839 ) 

840 newnode.postinit( 

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

842 [ 

843 ( 

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

845 self.visit(expr, newnode), 

846 ) 

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

848 ], 

849 ) 

850 return newnode 

851 

852 def visit_comprehension( 

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

854 ) -> nodes.Comprehension: 

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

856 newnode = nodes.Comprehension( 

857 parent=parent, 

858 # Comprehension nodes don't have these attributes 

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

860 lineno=None, 

861 col_offset=None, 

862 end_lineno=None, 

863 end_col_offset=None, 

864 ) 

865 newnode.postinit( 

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

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

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

869 bool(node.is_async), 

870 ) 

871 return newnode 

872 

873 def visit_decorators( 

874 self, 

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

876 parent: NodeNG, 

877 ) -> nodes.Decorators | None: 

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

879 

880 Note: Method not called by 'visit' 

881 """ 

882 if not node.decorator_list: 

883 return None 

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

885 # parent is an astroid.nodes.FunctionDef node 

886 

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

888 lineno = node.decorator_list[0].lineno 

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

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

891 

892 newnode = nodes.Decorators( 

893 lineno=lineno, 

894 col_offset=node.col_offset, 

895 end_lineno=end_lineno, 

896 end_col_offset=end_col_offset, 

897 parent=parent, 

898 ) 

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

900 return newnode 

901 

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

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

904 newnode = nodes.Delete( 

905 lineno=node.lineno, 

906 col_offset=node.col_offset, 

907 end_lineno=node.end_lineno, 

908 end_col_offset=node.end_col_offset, 

909 parent=parent, 

910 ) 

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

912 return newnode 

913 

914 def _visit_dict_items( 

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

916 ) -> Generator[tuple[NodeNG, NodeNG]]: 

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

918 rebuilt_key: NodeNG 

919 rebuilt_value = self.visit(value, newnode) 

920 if not key: 

921 # Extended unpacking 

922 rebuilt_key = nodes.DictUnpack( 

923 lineno=rebuilt_value.lineno, 

924 col_offset=rebuilt_value.col_offset, 

925 end_lineno=rebuilt_value.end_lineno, 

926 end_col_offset=rebuilt_value.end_col_offset, 

927 parent=parent, 

928 ) 

929 else: 

930 rebuilt_key = self.visit(key, newnode) 

931 yield rebuilt_key, rebuilt_value 

932 

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

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

935 newnode = nodes.Dict( 

936 lineno=node.lineno, 

937 col_offset=node.col_offset, 

938 end_lineno=node.end_lineno, 

939 end_col_offset=node.end_col_offset, 

940 parent=parent, 

941 ) 

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

943 self._visit_dict_items(node, parent, newnode) 

944 ) 

945 newnode.postinit(items) 

946 return newnode 

947 

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

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

950 newnode = nodes.DictComp( 

951 lineno=node.lineno, 

952 col_offset=node.col_offset, 

953 end_lineno=node.end_lineno, 

954 end_col_offset=node.end_col_offset, 

955 parent=parent, 

956 ) 

957 newnode.postinit( 

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

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

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

961 ) 

962 return newnode 

963 

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

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

966 newnode = nodes.Expr( 

967 lineno=node.lineno, 

968 col_offset=node.col_offset, 

969 end_lineno=node.end_lineno, 

970 end_col_offset=node.end_col_offset, 

971 parent=parent, 

972 ) 

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

974 return newnode 

975 

976 def visit_excepthandler( 

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

978 ) -> nodes.ExceptHandler: 

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

980 newnode = nodes.ExceptHandler( 

981 lineno=node.lineno, 

982 col_offset=node.col_offset, 

983 end_lineno=node.end_lineno, 

984 end_col_offset=node.end_col_offset, 

985 parent=parent, 

986 ) 

987 newnode.postinit( 

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

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

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

991 ) 

992 return newnode 

993 

994 @overload 

995 def _visit_for( 

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

997 ) -> nodes.For: ... 

998 

999 @overload 

1000 def _visit_for( 

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

1002 ) -> nodes.AsyncFor: ... 

1003 

1004 def _visit_for( 

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

1006 ) -> _ForT: 

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

1008 newnode = cls( 

1009 lineno=node.lineno, 

1010 col_offset=node.col_offset, 

1011 end_lineno=node.end_lineno, 

1012 end_col_offset=node.end_col_offset, 

1013 parent=parent, 

1014 ) 

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

1016 newnode.postinit( 

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

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

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

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

1021 type_annotation=type_annotation, 

1022 ) 

1023 return newnode 

1024 

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

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

1027 

1028 def visit_importfrom( 

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

1030 ) -> nodes.ImportFrom: 

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

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

1033 newnode = nodes.ImportFrom( 

1034 fromname=node.module or "", 

1035 names=names, 

1036 level=node.level or None, 

1037 lineno=node.lineno, 

1038 col_offset=node.col_offset, 

1039 end_lineno=node.end_lineno, 

1040 end_col_offset=node.end_col_offset, 

1041 parent=parent, 

1042 ) 

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

1044 self._import_from_nodes.append(newnode) 

1045 return newnode 

1046 

1047 @overload 

1048 def _visit_functiondef( 

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

1050 ) -> nodes.FunctionDef: ... 

1051 

1052 @overload 

1053 def _visit_functiondef( 

1054 self, 

1055 cls: type[nodes.AsyncFunctionDef], 

1056 node: ast.AsyncFunctionDef, 

1057 parent: NodeNG, 

1058 ) -> nodes.AsyncFunctionDef: ... 

1059 

1060 def _visit_functiondef( 

1061 self, 

1062 cls: type[_FunctionT], 

1063 node: ast.FunctionDef | ast.AsyncFunctionDef, 

1064 parent: NodeNG, 

1065 ) -> _FunctionT: 

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

1067 self._global_names.append({}) 

1068 node, doc_ast_node = self._get_doc(node) 

1069 

1070 lineno = node.lineno 

1071 if node.decorator_list: 

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

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

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

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

1076 # first decorator to maintain backward compatibility. 

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

1078 # the framework for *years*. 

1079 lineno = node.decorator_list[0].lineno 

1080 

1081 newnode = cls( 

1082 name=node.name, 

1083 lineno=lineno, 

1084 col_offset=node.col_offset, 

1085 end_lineno=node.end_lineno, 

1086 end_col_offset=node.end_col_offset, 

1087 parent=parent, 

1088 ) 

1089 decorators = self.visit_decorators(node, newnode) 

1090 returns: NodeNG | None 

1091 if node.returns: 

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

1093 else: 

1094 returns = None 

1095 

1096 type_comment_args = type_comment_returns = None 

1097 type_comment_annotation = self.check_function_type_comment(node, newnode) 

1098 if type_comment_annotation: 

1099 type_comment_returns, type_comment_args = type_comment_annotation 

1100 newnode.postinit( 

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

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

1103 decorators=decorators, 

1104 returns=returns, 

1105 type_comment_returns=type_comment_returns, 

1106 type_comment_args=type_comment_args, 

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

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

1109 type_params=( 

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

1111 if PY312_PLUS 

1112 else [] 

1113 ), 

1114 ) 

1115 self._global_names.pop() 

1116 parent.set_local(newnode.name, newnode) 

1117 return newnode 

1118 

1119 def visit_functiondef( 

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

1121 ) -> nodes.FunctionDef: 

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

1123 

1124 def visit_generatorexp( 

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

1126 ) -> nodes.GeneratorExp: 

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

1128 newnode = nodes.GeneratorExp( 

1129 lineno=node.lineno, 

1130 col_offset=node.col_offset, 

1131 end_lineno=node.end_lineno, 

1132 end_col_offset=node.end_col_offset, 

1133 parent=parent, 

1134 ) 

1135 newnode.postinit( 

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

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

1138 ) 

1139 return newnode 

1140 

1141 def visit_attribute( 

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

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

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

1145 context = self._get_context(node) 

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

1147 if context == Context.Del: 

1148 # FIXME : maybe we should reintroduce and visit_delattr ? 

1149 # for instance, deactivating assign_ctx 

1150 newnode = nodes.DelAttr( 

1151 attrname=node.attr, 

1152 lineno=node.lineno, 

1153 col_offset=node.col_offset, 

1154 end_lineno=node.end_lineno, 

1155 end_col_offset=node.end_col_offset, 

1156 parent=parent, 

1157 ) 

1158 elif context == Context.Store: 

1159 newnode = nodes.AssignAttr( 

1160 attrname=node.attr, 

1161 lineno=node.lineno, 

1162 col_offset=node.col_offset, 

1163 end_lineno=node.end_lineno, 

1164 end_col_offset=node.end_col_offset, 

1165 parent=parent, 

1166 ) 

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

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

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

1170 # doesn't support ParamSpec 

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

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

1173 else: 

1174 newnode = nodes.Attribute( 

1175 attrname=node.attr, 

1176 lineno=node.lineno, 

1177 col_offset=node.col_offset, 

1178 end_lineno=node.end_lineno, 

1179 end_col_offset=node.end_col_offset, 

1180 parent=parent, 

1181 ) 

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

1183 return newnode 

1184 

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

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

1187 newnode = nodes.Global( 

1188 names=node.names, 

1189 lineno=node.lineno, 

1190 col_offset=node.col_offset, 

1191 end_lineno=node.end_lineno, 

1192 end_col_offset=node.end_col_offset, 

1193 parent=parent, 

1194 ) 

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

1196 for name in node.names: 

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

1198 return newnode 

1199 

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

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

1202 newnode = nodes.If( 

1203 lineno=node.lineno, 

1204 col_offset=node.col_offset, 

1205 end_lineno=node.end_lineno, 

1206 end_col_offset=node.end_col_offset, 

1207 parent=parent, 

1208 ) 

1209 newnode.postinit( 

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

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

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

1213 ) 

1214 return newnode 

1215 

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

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

1218 newnode = nodes.IfExp( 

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 newnode.postinit( 

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

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

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

1229 ) 

1230 return newnode 

1231 

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

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

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

1235 newnode = nodes.Import( 

1236 names=names, 

1237 lineno=node.lineno, 

1238 col_offset=node.col_offset, 

1239 end_lineno=node.end_lineno, 

1240 end_col_offset=node.end_col_offset, 

1241 parent=parent, 

1242 ) 

1243 # save import names in parent's locals: 

1244 for name, asname in newnode.names: 

1245 name = asname or name 

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

1247 return newnode 

1248 

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

1250 newnode = nodes.JoinedStr( 

1251 lineno=node.lineno, 

1252 col_offset=node.col_offset, 

1253 end_lineno=node.end_lineno, 

1254 end_col_offset=node.end_col_offset, 

1255 parent=parent, 

1256 ) 

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

1258 return newnode 

1259 

1260 def visit_formattedvalue( 

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

1262 ) -> nodes.FormattedValue: 

1263 newnode = nodes.FormattedValue( 

1264 lineno=node.lineno, 

1265 col_offset=node.col_offset, 

1266 end_lineno=node.end_lineno, 

1267 end_col_offset=node.end_col_offset, 

1268 parent=parent, 

1269 ) 

1270 newnode.postinit( 

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

1272 conversion=node.conversion, 

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

1274 ) 

1275 return newnode 

1276 

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

1278 newnode = nodes.NamedExpr( 

1279 lineno=node.lineno, 

1280 col_offset=node.col_offset, 

1281 end_lineno=node.end_lineno, 

1282 end_col_offset=node.end_col_offset, 

1283 parent=parent, 

1284 ) 

1285 newnode.postinit( 

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

1287 ) 

1288 return newnode 

1289 

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

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

1292 newnode = nodes.Keyword( 

1293 arg=node.arg, 

1294 # position attributes added in 3.9 

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

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

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

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

1299 parent=parent, 

1300 ) 

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

1302 return newnode 

1303 

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

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

1306 newnode = nodes.Lambda( 

1307 lineno=node.lineno, 

1308 col_offset=node.col_offset, 

1309 end_lineno=node.end_lineno, 

1310 end_col_offset=node.end_col_offset, 

1311 parent=parent, 

1312 ) 

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

1314 return newnode 

1315 

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

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

1318 context = self._get_context(node) 

1319 newnode = nodes.List( 

1320 ctx=context, 

1321 lineno=node.lineno, 

1322 col_offset=node.col_offset, 

1323 end_lineno=node.end_lineno, 

1324 end_col_offset=node.end_col_offset, 

1325 parent=parent, 

1326 ) 

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

1328 return newnode 

1329 

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

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

1332 newnode = nodes.ListComp( 

1333 lineno=node.lineno, 

1334 col_offset=node.col_offset, 

1335 end_lineno=node.end_lineno, 

1336 end_col_offset=node.end_col_offset, 

1337 parent=parent, 

1338 ) 

1339 newnode.postinit( 

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

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

1342 ) 

1343 return newnode 

1344 

1345 def visit_name( 

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

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

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

1349 context = self._get_context(node) 

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

1351 if context == Context.Del: 

1352 newnode = nodes.DelName( 

1353 name=node.id, 

1354 lineno=node.lineno, 

1355 col_offset=node.col_offset, 

1356 end_lineno=node.end_lineno, 

1357 end_col_offset=node.end_col_offset, 

1358 parent=parent, 

1359 ) 

1360 elif context == Context.Store: 

1361 newnode = nodes.AssignName( 

1362 name=node.id, 

1363 lineno=node.lineno, 

1364 col_offset=node.col_offset, 

1365 end_lineno=node.end_lineno, 

1366 end_col_offset=node.end_col_offset, 

1367 parent=parent, 

1368 ) 

1369 else: 

1370 newnode = nodes.Name( 

1371 name=node.id, 

1372 lineno=node.lineno, 

1373 col_offset=node.col_offset, 

1374 end_lineno=node.end_lineno, 

1375 end_col_offset=node.end_col_offset, 

1376 parent=parent, 

1377 ) 

1378 # XXX REMOVE me : 

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

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

1381 self._save_assignment(newnode) 

1382 return newnode 

1383 

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

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

1386 return nodes.Nonlocal( 

1387 names=node.names, 

1388 lineno=node.lineno, 

1389 col_offset=node.col_offset, 

1390 end_lineno=node.end_lineno, 

1391 end_col_offset=node.end_col_offset, 

1392 parent=parent, 

1393 ) 

1394 

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

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

1397 return nodes.Const( 

1398 value=node.value, 

1399 kind=node.kind, 

1400 lineno=node.lineno, 

1401 col_offset=node.col_offset, 

1402 end_lineno=node.end_lineno, 

1403 end_col_offset=node.end_col_offset, 

1404 parent=parent, 

1405 ) 

1406 

1407 def visit_paramspec(self, node: ast.ParamSpec, parent: NodeNG) -> nodes.ParamSpec: 

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

1409 newnode = nodes.ParamSpec( 

1410 lineno=node.lineno, 

1411 col_offset=node.col_offset, 

1412 end_lineno=node.end_lineno, 

1413 end_col_offset=node.end_col_offset, 

1414 parent=parent, 

1415 ) 

1416 # Add AssignName node for 'node.name' 

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

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

1419 return newnode 

1420 

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

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

1423 return nodes.Pass( 

1424 lineno=node.lineno, 

1425 col_offset=node.col_offset, 

1426 end_lineno=node.end_lineno, 

1427 end_col_offset=node.end_col_offset, 

1428 parent=parent, 

1429 ) 

1430 

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

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

1433 newnode = nodes.Raise( 

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 # no traceback; anyway it is not used in Pylint 

1441 newnode.postinit( 

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

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

1444 ) 

1445 return newnode 

1446 

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

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

1449 newnode = nodes.Return( 

1450 lineno=node.lineno, 

1451 col_offset=node.col_offset, 

1452 end_lineno=node.end_lineno, 

1453 end_col_offset=node.end_col_offset, 

1454 parent=parent, 

1455 ) 

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

1457 return newnode 

1458 

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

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

1461 newnode = nodes.Set( 

1462 lineno=node.lineno, 

1463 col_offset=node.col_offset, 

1464 end_lineno=node.end_lineno, 

1465 end_col_offset=node.end_col_offset, 

1466 parent=parent, 

1467 ) 

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

1469 return newnode 

1470 

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

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

1473 newnode = nodes.SetComp( 

1474 lineno=node.lineno, 

1475 col_offset=node.col_offset, 

1476 end_lineno=node.end_lineno, 

1477 end_col_offset=node.end_col_offset, 

1478 parent=parent, 

1479 ) 

1480 newnode.postinit( 

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

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

1483 ) 

1484 return newnode 

1485 

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

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

1488 newnode = nodes.Slice( 

1489 # position attributes added in 3.9 

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

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

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

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

1494 parent=parent, 

1495 ) 

1496 newnode.postinit( 

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

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

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

1500 ) 

1501 return newnode 

1502 

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

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

1505 context = self._get_context(node) 

1506 newnode = nodes.Subscript( 

1507 ctx=context, 

1508 lineno=node.lineno, 

1509 col_offset=node.col_offset, 

1510 end_lineno=node.end_lineno, 

1511 end_col_offset=node.end_col_offset, 

1512 parent=parent, 

1513 ) 

1514 newnode.postinit( 

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

1516 ) 

1517 return newnode 

1518 

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

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

1521 context = self._get_context(node) 

1522 newnode = nodes.Starred( 

1523 ctx=context, 

1524 lineno=node.lineno, 

1525 col_offset=node.col_offset, 

1526 end_lineno=node.end_lineno, 

1527 end_col_offset=node.end_col_offset, 

1528 parent=parent, 

1529 ) 

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

1531 return newnode 

1532 

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

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

1535 newnode = nodes.Try( 

1536 lineno=node.lineno, 

1537 col_offset=node.col_offset, 

1538 end_lineno=node.end_lineno, 

1539 end_col_offset=node.end_col_offset, 

1540 parent=parent, 

1541 ) 

1542 newnode.postinit( 

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

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

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

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

1547 ) 

1548 return newnode 

1549 

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

1551 newnode = nodes.TryStar( 

1552 lineno=node.lineno, 

1553 col_offset=node.col_offset, 

1554 end_lineno=node.end_lineno, 

1555 end_col_offset=node.end_col_offset, 

1556 parent=parent, 

1557 ) 

1558 newnode.postinit( 

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

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

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

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

1563 ) 

1564 return newnode 

1565 

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

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

1568 context = self._get_context(node) 

1569 newnode = nodes.Tuple( 

1570 ctx=context, 

1571 lineno=node.lineno, 

1572 col_offset=node.col_offset, 

1573 end_lineno=node.end_lineno, 

1574 end_col_offset=node.end_col_offset, 

1575 parent=parent, 

1576 ) 

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

1578 return newnode 

1579 

1580 def visit_typealias(self, node: ast.TypeAlias, parent: NodeNG) -> nodes.TypeAlias: 

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

1582 newnode = nodes.TypeAlias( 

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( 

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

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

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

1593 ) 

1594 return newnode 

1595 

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

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

1598 newnode = nodes.TypeVar( 

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 # Add AssignName node for 'node.name' 

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

1607 newnode.postinit( 

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

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

1610 ) 

1611 return newnode 

1612 

1613 def visit_typevartuple( 

1614 self, node: ast.TypeVarTuple, parent: NodeNG 

1615 ) -> nodes.TypeVarTuple: 

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

1617 newnode = nodes.TypeVarTuple( 

1618 lineno=node.lineno, 

1619 col_offset=node.col_offset, 

1620 end_lineno=node.end_lineno, 

1621 end_col_offset=node.end_col_offset, 

1622 parent=parent, 

1623 ) 

1624 # Add AssignName node for 'node.name' 

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

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

1627 return newnode 

1628 

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

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

1631 newnode = nodes.UnaryOp( 

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

1633 lineno=node.lineno, 

1634 col_offset=node.col_offset, 

1635 end_lineno=node.end_lineno, 

1636 end_col_offset=node.end_col_offset, 

1637 parent=parent, 

1638 ) 

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

1640 return newnode 

1641 

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

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

1644 newnode = nodes.While( 

1645 lineno=node.lineno, 

1646 col_offset=node.col_offset, 

1647 end_lineno=node.end_lineno, 

1648 end_col_offset=node.end_col_offset, 

1649 parent=parent, 

1650 ) 

1651 newnode.postinit( 

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

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

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

1655 ) 

1656 return newnode 

1657 

1658 @overload 

1659 def _visit_with( 

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

1661 ) -> nodes.With: ... 

1662 

1663 @overload 

1664 def _visit_with( 

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

1666 ) -> nodes.AsyncWith: ... 

1667 

1668 def _visit_with( 

1669 self, 

1670 cls: type[_WithT], 

1671 node: ast.With | ast.AsyncWith, 

1672 parent: NodeNG, 

1673 ) -> _WithT: 

1674 newnode = cls( 

1675 lineno=node.lineno, 

1676 col_offset=node.col_offset, 

1677 end_lineno=node.end_lineno, 

1678 end_col_offset=node.end_col_offset, 

1679 parent=parent, 

1680 ) 

1681 

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

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

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

1685 return expr, var 

1686 

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

1688 newnode.postinit( 

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

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

1691 type_annotation=type_annotation, 

1692 ) 

1693 return newnode 

1694 

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

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

1697 

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

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

1700 newnode = nodes.Yield( 

1701 lineno=node.lineno, 

1702 col_offset=node.col_offset, 

1703 end_lineno=node.end_lineno, 

1704 end_col_offset=node.end_col_offset, 

1705 parent=parent, 

1706 ) 

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

1708 return newnode 

1709 

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

1711 newnode = nodes.YieldFrom( 

1712 lineno=node.lineno, 

1713 col_offset=node.col_offset, 

1714 end_lineno=node.end_lineno, 

1715 end_col_offset=node.end_col_offset, 

1716 parent=parent, 

1717 ) 

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

1719 return newnode 

1720 

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

1722 

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

1724 newnode = nodes.Match( 

1725 lineno=node.lineno, 

1726 col_offset=node.col_offset, 

1727 end_lineno=node.end_lineno, 

1728 end_col_offset=node.end_col_offset, 

1729 parent=parent, 

1730 ) 

1731 newnode.postinit( 

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

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

1734 ) 

1735 return newnode 

1736 

1737 def visit_matchcase( 

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

1739 ) -> nodes.MatchCase: 

1740 newnode = nodes.MatchCase(parent=parent) 

1741 newnode.postinit( 

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

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

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

1745 ) 

1746 return newnode 

1747 

1748 def visit_matchvalue( 

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

1750 ) -> nodes.MatchValue: 

1751 newnode = nodes.MatchValue( 

1752 lineno=node.lineno, 

1753 col_offset=node.col_offset, 

1754 end_lineno=node.end_lineno, 

1755 end_col_offset=node.end_col_offset, 

1756 parent=parent, 

1757 ) 

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

1759 return newnode 

1760 

1761 def visit_matchsingleton( 

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

1763 ) -> nodes.MatchSingleton: 

1764 return nodes.MatchSingleton( 

1765 value=node.value, 

1766 lineno=node.lineno, 

1767 col_offset=node.col_offset, 

1768 end_lineno=node.end_lineno, 

1769 end_col_offset=node.end_col_offset, 

1770 parent=parent, 

1771 ) 

1772 

1773 def visit_matchsequence( 

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

1775 ) -> nodes.MatchSequence: 

1776 newnode = nodes.MatchSequence( 

1777 lineno=node.lineno, 

1778 col_offset=node.col_offset, 

1779 end_lineno=node.end_lineno, 

1780 end_col_offset=node.end_col_offset, 

1781 parent=parent, 

1782 ) 

1783 newnode.postinit( 

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

1785 ) 

1786 return newnode 

1787 

1788 def visit_matchmapping( 

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

1790 ) -> nodes.MatchMapping: 

1791 newnode = nodes.MatchMapping( 

1792 lineno=node.lineno, 

1793 col_offset=node.col_offset, 

1794 end_lineno=node.end_lineno, 

1795 end_col_offset=node.end_col_offset, 

1796 parent=parent, 

1797 ) 

1798 # Add AssignName node for 'node.name' 

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

1800 newnode.postinit( 

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

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

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

1804 ) 

1805 return newnode 

1806 

1807 def visit_matchclass( 

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

1809 ) -> nodes.MatchClass: 

1810 newnode = nodes.MatchClass( 

1811 lineno=node.lineno, 

1812 col_offset=node.col_offset, 

1813 end_lineno=node.end_lineno, 

1814 end_col_offset=node.end_col_offset, 

1815 parent=parent, 

1816 ) 

1817 newnode.postinit( 

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

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

1820 kwd_attrs=node.kwd_attrs, 

1821 kwd_patterns=[ 

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

1823 ], 

1824 ) 

1825 return newnode 

1826 

1827 def visit_matchstar( 

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

1829 ) -> nodes.MatchStar: 

1830 newnode = nodes.MatchStar( 

1831 lineno=node.lineno, 

1832 col_offset=node.col_offset, 

1833 end_lineno=node.end_lineno, 

1834 end_col_offset=node.end_col_offset, 

1835 parent=parent, 

1836 ) 

1837 # Add AssignName node for 'node.name' 

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

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

1840 return newnode 

1841 

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

1843 newnode = nodes.MatchAs( 

1844 lineno=node.lineno, 

1845 col_offset=node.col_offset, 

1846 end_lineno=node.end_lineno, 

1847 end_col_offset=node.end_col_offset, 

1848 parent=parent, 

1849 ) 

1850 # Add AssignName node for 'node.name' 

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

1852 newnode.postinit( 

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

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

1855 ) 

1856 return newnode 

1857 

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

1859 newnode = nodes.MatchOr( 

1860 lineno=node.lineno, 

1861 col_offset=node.col_offset, 

1862 end_lineno=node.end_lineno, 

1863 end_col_offset=node.end_col_offset, 

1864 parent=parent, 

1865 ) 

1866 newnode.postinit( 

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

1868 ) 

1869 return newnode