| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996 |
- # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
- # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
- # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
- """This module contains utilities for rebuilding an _ast tree in
- order to get a single Astroid representation.
- """
- from __future__ import annotations
- import ast
- import sys
- import token
- from collections.abc import Callable, Collection, Generator
- from io import StringIO
- from tokenize import TokenInfo, generate_tokens
- from typing import TYPE_CHECKING, Final, TypeVar, cast, overload
- from astroid import nodes
- from astroid._ast import ParserModule, get_parser_module, parse_function_type_comment
- from astroid.const import PY312_PLUS, PY313_PLUS, Context
- from astroid.nodes.utils import Position
- from astroid.typing import InferenceResult
- if TYPE_CHECKING:
- from astroid.manager import AstroidManager
- T_Doc = TypeVar(
- "T_Doc",
- ast.Module,
- ast.ClassDef,
- ast.FunctionDef | ast.AsyncFunctionDef,
- )
- _FunctionT = TypeVar("_FunctionT", nodes.FunctionDef, nodes.AsyncFunctionDef)
- _ForT = TypeVar("_ForT", nodes.For, nodes.AsyncFor)
- _WithT = TypeVar("_WithT", nodes.With, nodes.AsyncWith)
- NodesWithDocsType = nodes.Module | nodes.ClassDef | nodes.FunctionDef
- REDIRECT: Final[dict[str, str]] = {
- "arguments": "Arguments",
- "comprehension": "Comprehension",
- "ListCompFor": "Comprehension",
- "GenExprFor": "Comprehension",
- "excepthandler": "ExceptHandler",
- "keyword": "Keyword",
- "match_case": "MatchCase",
- }
- # noinspection PyMethodMayBeStatic
- class TreeRebuilder:
- """Rebuilds the _ast tree to become an Astroid tree."""
- def __init__(
- self,
- manager: AstroidManager,
- parser_module: ParserModule | None = None,
- data: str | None = None,
- ) -> None:
- self._manager = manager
- self._data = data.split("\n") if data else None
- self._global_names: list[dict[str, list[nodes.Global]]] = []
- self._import_from_nodes: list[tuple[nodes.ImportFrom, Collection[str]]] = []
- self._delayed_assattr: list[nodes.AssignAttr] = []
- self._visit_meths: dict[
- type[ast.AST], Callable[[ast.AST, nodes.NodeNG], nodes.NodeNG]
- ] = {}
- if parser_module is None:
- self._parser_module = get_parser_module()
- else:
- self._parser_module = parser_module
- def _get_doc(self, node: T_Doc) -> tuple[T_Doc, ast.Constant | None]:
- """Return the doc ast node."""
- try:
- if node.body and isinstance(node.body[0], ast.Expr):
- first_value = node.body[0].value
- if isinstance(first_value, ast.Constant) and isinstance(
- first_value.value, str
- ):
- doc_ast_node = first_value
- node.body = node.body[1:]
- return node, doc_ast_node
- except IndexError:
- pass # ast built from scratch
- return node, None
- def _get_context(
- self,
- node: (
- ast.Attribute
- | ast.List
- | ast.Name
- | ast.Subscript
- | ast.Starred
- | ast.Tuple
- ),
- ) -> Context:
- return self._parser_module.context_classes.get(type(node.ctx), Context.Load)
- def _get_position_info(
- self,
- node: ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef,
- parent: nodes.ClassDef | nodes.FunctionDef | nodes.AsyncFunctionDef,
- ) -> Position | None:
- """Return position information for ClassDef and FunctionDef nodes.
- In contrast to AST positions, these only include the actual keyword(s)
- and the class / function name.
- >>> @decorator
- >>> async def some_func(var: int) -> None:
- >>> ^^^^^^^^^^^^^^^^^^^
- """
- if not self._data:
- return None
- end_lineno = node.end_lineno
- if node.body:
- end_lineno = node.body[0].lineno
- # pylint: disable-next=unsubscriptable-object
- data = "\n".join(self._data[node.lineno - 1 : end_lineno])
- start_token: TokenInfo | None = None
- keyword_tokens: tuple[int, ...] = (token.NAME,)
- if isinstance(parent, nodes.AsyncFunctionDef):
- search_token = "async"
- elif isinstance(parent, nodes.FunctionDef):
- search_token = "def"
- else:
- search_token = "class"
- for t in generate_tokens(StringIO(data).readline):
- if (
- start_token is not None
- and t.type == token.NAME
- and t.string == node.name
- ):
- break
- if t.type in keyword_tokens:
- if t.string == search_token:
- start_token = t
- continue
- if t.string in {"def"}:
- continue
- start_token = None
- else:
- return None
- return Position(
- lineno=node.lineno + start_token.start[0] - 1,
- col_offset=start_token.start[1],
- end_lineno=node.lineno + t.end[0] - 1,
- end_col_offset=t.end[1],
- )
- def visit_module(
- self, node: ast.Module, modname: str, modpath: str, package: bool
- ) -> nodes.Module:
- """Visit a Module node by returning a fresh instance of it.
- Note: Method not called by 'visit'
- """
- node, doc_ast_node = self._get_doc(node)
- newnode = nodes.Module(
- name=modname,
- file=modpath,
- path=[modpath],
- package=package,
- )
- newnode.postinit(
- [self.visit(child, newnode) for child in node.body],
- doc_node=self.visit(doc_ast_node, newnode),
- )
- return newnode
- if TYPE_CHECKING: # noqa: C901
- @overload
- def visit(self, node: ast.arg, parent: nodes.NodeNG) -> nodes.AssignName: ...
- @overload
- def visit(
- self, node: ast.arguments, parent: nodes.NodeNG
- ) -> nodes.Arguments: ...
- @overload
- def visit(self, node: ast.Assert, parent: nodes.NodeNG) -> nodes.Assert: ...
- @overload
- def visit(
- self, node: ast.AsyncFunctionDef, parent: nodes.NodeNG
- ) -> nodes.AsyncFunctionDef: ...
- @overload
- def visit(self, node: ast.AsyncFor, parent: nodes.NodeNG) -> nodes.AsyncFor: ...
- @overload
- def visit(self, node: ast.Await, parent: nodes.NodeNG) -> nodes.Await: ...
- @overload
- def visit(
- self, node: ast.AsyncWith, parent: nodes.NodeNG
- ) -> nodes.AsyncWith: ...
- @overload
- def visit(self, node: ast.Assign, parent: nodes.NodeNG) -> nodes.Assign: ...
- @overload
- def visit(
- self, node: ast.AnnAssign, parent: nodes.NodeNG
- ) -> nodes.AnnAssign: ...
- @overload
- def visit(
- self, node: ast.AugAssign, parent: nodes.NodeNG
- ) -> nodes.AugAssign: ...
- @overload
- def visit(self, node: ast.BinOp, parent: nodes.NodeNG) -> nodes.BinOp: ...
- @overload
- def visit(self, node: ast.BoolOp, parent: nodes.NodeNG) -> nodes.BoolOp: ...
- @overload
- def visit(self, node: ast.Break, parent: nodes.NodeNG) -> nodes.Break: ...
- @overload
- def visit(self, node: ast.Call, parent: nodes.NodeNG) -> nodes.Call: ...
- @overload
- def visit(self, node: ast.ClassDef, parent: nodes.NodeNG) -> nodes.ClassDef: ...
- @overload
- def visit(self, node: ast.Continue, parent: nodes.NodeNG) -> nodes.Continue: ...
- @overload
- def visit(self, node: ast.Compare, parent: nodes.NodeNG) -> nodes.Compare: ...
- @overload
- def visit(
- self, node: ast.comprehension, parent: nodes.NodeNG
- ) -> nodes.Comprehension: ...
- @overload
- def visit(self, node: ast.Delete, parent: nodes.NodeNG) -> nodes.Delete: ...
- @overload
- def visit(self, node: ast.Dict, parent: nodes.NodeNG) -> nodes.Dict: ...
- @overload
- def visit(self, node: ast.DictComp, parent: nodes.NodeNG) -> nodes.DictComp: ...
- @overload
- def visit(self, node: ast.Expr, parent: nodes.NodeNG) -> nodes.Expr: ...
- @overload
- def visit(
- self, node: ast.ExceptHandler, parent: nodes.NodeNG
- ) -> nodes.ExceptHandler: ...
- @overload
- def visit(self, node: ast.For, parent: nodes.NodeNG) -> nodes.For: ...
- @overload
- def visit(
- self, node: ast.ImportFrom, parent: nodes.NodeNG
- ) -> nodes.ImportFrom: ...
- @overload
- def visit(
- self, node: ast.FunctionDef, parent: nodes.NodeNG
- ) -> nodes.FunctionDef: ...
- @overload
- def visit(
- self, node: ast.GeneratorExp, parent: nodes.NodeNG
- ) -> nodes.GeneratorExp: ...
- @overload
- def visit(
- self, node: ast.Attribute, parent: nodes.NodeNG
- ) -> nodes.Attribute: ...
- @overload
- def visit(self, node: ast.Global, parent: nodes.NodeNG) -> nodes.Global: ...
- @overload
- def visit(self, node: ast.If, parent: nodes.NodeNG) -> nodes.If: ...
- @overload
- def visit(self, node: ast.IfExp, parent: nodes.NodeNG) -> nodes.IfExp: ...
- @overload
- def visit(self, node: ast.Import, parent: nodes.NodeNG) -> nodes.Import: ...
- @overload
- def visit(
- self, node: ast.JoinedStr, parent: nodes.NodeNG
- ) -> nodes.JoinedStr: ...
- @overload
- def visit(
- self, node: ast.FormattedValue, parent: nodes.NodeNG
- ) -> nodes.FormattedValue: ...
- @overload
- def visit(
- self, node: ast.NamedExpr, parent: nodes.NodeNG
- ) -> nodes.NamedExpr: ...
- @overload
- def visit(self, node: ast.keyword, parent: nodes.NodeNG) -> nodes.Keyword: ...
- @overload
- def visit(self, node: ast.Lambda, parent: nodes.NodeNG) -> nodes.Lambda: ...
- @overload
- def visit(self, node: ast.List, parent: nodes.NodeNG) -> nodes.List: ...
- @overload
- def visit(self, node: ast.ListComp, parent: nodes.NodeNG) -> nodes.ListComp: ...
- @overload
- def visit(
- self, node: ast.Name, parent: nodes.NodeNG
- ) -> nodes.Name | nodes.Const | nodes.AssignName | nodes.DelName: ...
- @overload
- def visit(self, node: ast.Nonlocal, parent: nodes.NodeNG) -> nodes.Nonlocal: ...
- @overload
- def visit(self, node: ast.Constant, parent: nodes.NodeNG) -> nodes.Const: ...
- if sys.version_info >= (3, 12):
- @overload
- def visit(
- self, node: ast.ParamSpec, parent: nodes.NodeNG
- ) -> nodes.ParamSpec: ...
- @overload
- def visit(self, node: ast.Pass, parent: nodes.NodeNG) -> nodes.Pass: ...
- @overload
- def visit(self, node: ast.Raise, parent: nodes.NodeNG) -> nodes.Raise: ...
- @overload
- def visit(self, node: ast.Return, parent: nodes.NodeNG) -> nodes.Return: ...
- @overload
- def visit(self, node: ast.Set, parent: nodes.NodeNG) -> nodes.Set: ...
- @overload
- def visit(self, node: ast.SetComp, parent: nodes.NodeNG) -> nodes.SetComp: ...
- @overload
- def visit(self, node: ast.Slice, parent: nodes.Subscript) -> nodes.Slice: ...
- @overload
- def visit(
- self, node: ast.Subscript, parent: nodes.NodeNG
- ) -> nodes.Subscript: ...
- @overload
- def visit(self, node: ast.Starred, parent: nodes.NodeNG) -> nodes.Starred: ...
- @overload
- def visit(self, node: ast.Try, parent: nodes.NodeNG) -> nodes.Try: ...
- if sys.version_info >= (3, 11):
- @overload
- def visit(
- self, node: ast.TryStar, parent: nodes.NodeNG
- ) -> nodes.TryStar: ...
- @overload
- def visit(self, node: ast.Tuple, parent: nodes.NodeNG) -> nodes.Tuple: ...
- if sys.version_info >= (3, 12):
- @overload
- def visit(
- self, node: ast.TypeAlias, parent: nodes.NodeNG
- ) -> nodes.TypeAlias: ...
- @overload
- def visit(
- self, node: ast.TypeVar, parent: nodes.NodeNG
- ) -> nodes.TypeVar: ...
- @overload
- def visit(
- self, node: ast.TypeVarTuple, parent: nodes.NodeNG
- ) -> nodes.TypeVarTuple: ...
- @overload
- def visit(self, node: ast.UnaryOp, parent: nodes.NodeNG) -> nodes.UnaryOp: ...
- @overload
- def visit(self, node: ast.While, parent: nodes.NodeNG) -> nodes.While: ...
- @overload
- def visit(self, node: ast.With, parent: nodes.NodeNG) -> nodes.With: ...
- @overload
- def visit(self, node: ast.Yield, parent: nodes.NodeNG) -> nodes.Yield: ...
- @overload
- def visit(
- self, node: ast.YieldFrom, parent: nodes.NodeNG
- ) -> nodes.YieldFrom: ...
- @overload
- def visit(self, node: ast.Match, parent: nodes.NodeNG) -> nodes.Match: ...
- @overload
- def visit(
- self, node: ast.match_case, parent: nodes.NodeNG
- ) -> nodes.MatchCase: ...
- @overload
- def visit(
- self, node: ast.MatchValue, parent: nodes.NodeNG
- ) -> nodes.MatchValue: ...
- @overload
- def visit(
- self, node: ast.MatchSingleton, parent: nodes.NodeNG
- ) -> nodes.MatchSingleton: ...
- @overload
- def visit(
- self, node: ast.MatchSequence, parent: nodes.NodeNG
- ) -> nodes.MatchSequence: ...
- @overload
- def visit(
- self, node: ast.MatchMapping, parent: nodes.NodeNG
- ) -> nodes.MatchMapping: ...
- @overload
- def visit(
- self, node: ast.MatchClass, parent: nodes.NodeNG
- ) -> nodes.MatchClass: ...
- @overload
- def visit(
- self, node: ast.MatchStar, parent: nodes.NodeNG
- ) -> nodes.MatchStar: ...
- @overload
- def visit(self, node: ast.MatchAs, parent: nodes.NodeNG) -> nodes.MatchAs: ...
- @overload
- def visit(self, node: ast.MatchOr, parent: nodes.NodeNG) -> nodes.MatchOr: ...
- @overload
- def visit(self, node: ast.pattern, parent: nodes.NodeNG) -> nodes.Pattern: ...
- if sys.version_info >= (3, 14):
- @overload
- def visit(
- self, node: ast.TemplateStr, parent: nodes.NodeNG
- ) -> nodes.TemplateStr: ...
- @overload
- def visit(
- self, node: ast.Interpolation, parent: nodes.NodeNG
- ) -> nodes.Interpolation: ...
- @overload
- def visit(self, node: ast.AST, parent: nodes.NodeNG) -> nodes.NodeNG: ...
- @overload
- def visit(self, node: None, parent: nodes.NodeNG) -> None: ...
- def visit(self, node: ast.AST | None, parent: nodes.NodeNG) -> nodes.NodeNG | None:
- if node is None:
- return None
- cls = node.__class__
- if cls in self._visit_meths:
- visit_method = self._visit_meths[cls]
- else:
- cls_name = cls.__name__
- visit_name = "visit_" + REDIRECT.get(cls_name, cls_name).lower()
- visit_method = getattr(self, visit_name)
- self._visit_meths[cls] = visit_method
- return visit_method(node, parent)
- def _save_assignment(self, node: nodes.AssignName | nodes.DelName) -> None:
- """Save assignment situation since node.parent is not available yet."""
- if self._global_names and node.name in self._global_names[-1]:
- node.root().set_local(node.name, node)
- else:
- assert node.parent
- assert node.name
- node.parent.set_local(node.name, node)
- def visit_arg(self, node: ast.arg, parent: nodes.NodeNG) -> nodes.AssignName:
- """Visit an arg node by returning a fresh AssignName instance."""
- return self.visit_assignname(node, parent, node.arg)
- def visit_arguments(
- self, node: ast.arguments, parent: nodes.NodeNG
- ) -> nodes.Arguments:
- """Visit an Arguments node by returning a fresh instance of it."""
- vararg: str | None = None
- kwarg: str | None = None
- vararg_node = node.vararg
- kwarg_node = node.kwarg
- newnode = nodes.Arguments(
- node.vararg.arg if node.vararg else None,
- node.kwarg.arg if node.kwarg else None,
- parent,
- (
- nodes.AssignName(
- vararg_node.arg,
- vararg_node.lineno,
- vararg_node.col_offset,
- parent,
- end_lineno=vararg_node.end_lineno,
- end_col_offset=vararg_node.end_col_offset,
- )
- if vararg_node
- else None
- ),
- (
- nodes.AssignName(
- kwarg_node.arg,
- kwarg_node.lineno,
- kwarg_node.col_offset,
- parent,
- end_lineno=kwarg_node.end_lineno,
- end_col_offset=kwarg_node.end_col_offset,
- )
- if kwarg_node
- else None
- ),
- )
- args = [self.visit(child, newnode) for child in node.args]
- defaults = [self.visit(child, newnode) for child in node.defaults]
- varargannotation: nodes.NodeNG | None = None
- kwargannotation: nodes.NodeNG | None = None
- if node.vararg:
- vararg = node.vararg.arg
- varargannotation = self.visit(node.vararg.annotation, newnode)
- if node.kwarg:
- kwarg = node.kwarg.arg
- kwargannotation = self.visit(node.kwarg.annotation, newnode)
- kwonlyargs = [self.visit(child, newnode) for child in node.kwonlyargs]
- kw_defaults = [self.visit(child, newnode) for child in node.kw_defaults]
- annotations = [self.visit(arg.annotation, newnode) for arg in node.args]
- kwonlyargs_annotations = [
- self.visit(arg.annotation, newnode) for arg in node.kwonlyargs
- ]
- posonlyargs = [self.visit(child, newnode) for child in node.posonlyargs]
- posonlyargs_annotations = [
- self.visit(arg.annotation, newnode) for arg in node.posonlyargs
- ]
- type_comment_args = [
- self.check_type_comment(child, parent=newnode) for child in node.args
- ]
- type_comment_kwonlyargs = [
- self.check_type_comment(child, parent=newnode) for child in node.kwonlyargs
- ]
- type_comment_posonlyargs = [
- self.check_type_comment(child, parent=newnode) for child in node.posonlyargs
- ]
- newnode.postinit(
- args=args,
- defaults=defaults,
- kwonlyargs=kwonlyargs,
- posonlyargs=posonlyargs,
- kw_defaults=kw_defaults,
- annotations=annotations,
- kwonlyargs_annotations=kwonlyargs_annotations,
- posonlyargs_annotations=posonlyargs_annotations,
- varargannotation=varargannotation,
- kwargannotation=kwargannotation,
- type_comment_args=type_comment_args,
- type_comment_kwonlyargs=type_comment_kwonlyargs,
- type_comment_posonlyargs=type_comment_posonlyargs,
- )
- # save argument names in locals:
- assert newnode.parent
- if vararg:
- newnode.parent.set_local(vararg, newnode)
- if kwarg:
- newnode.parent.set_local(kwarg, newnode)
- return newnode
- def visit_assert(self, node: ast.Assert, parent: nodes.NodeNG) -> nodes.Assert:
- """Visit a Assert node by returning a fresh instance of it."""
- newnode = nodes.Assert(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- msg: nodes.NodeNG | None = None
- if node.msg:
- msg = self.visit(node.msg, newnode)
- newnode.postinit(self.visit(node.test, newnode), msg)
- return newnode
- def check_type_comment(
- self,
- node: ast.Assign | ast.arg | ast.For | ast.AsyncFor | ast.With | ast.AsyncWith,
- parent: (
- nodes.Assign
- | nodes.Arguments
- | nodes.For
- | nodes.AsyncFor
- | nodes.With
- | nodes.AsyncWith
- ),
- ) -> nodes.NodeNG | None:
- if not node.type_comment:
- return None
- try:
- type_comment_ast = self._parser_module.parse(node.type_comment)
- except SyntaxError:
- # Invalid type comment, just skip it.
- return None
- # For '# type: # any comment' ast.parse returns a Module node,
- # without any nodes in the body.
- if not type_comment_ast.body:
- return None
- type_object = self.visit(type_comment_ast.body[0], parent=parent)
- if not isinstance(type_object, nodes.Expr):
- return None
- return type_object.value
- def check_function_type_comment(
- self, node: ast.FunctionDef | ast.AsyncFunctionDef, parent: nodes.NodeNG
- ) -> tuple[nodes.NodeNG | None, list[nodes.NodeNG]] | None:
- if not node.type_comment:
- return None
- try:
- type_comment_ast = parse_function_type_comment(node.type_comment)
- except SyntaxError:
- # Invalid type comment, just skip it.
- return None
- if not type_comment_ast:
- return None
- returns: nodes.NodeNG | None = None
- argtypes: list[nodes.NodeNG] = [
- self.visit(elem, parent) for elem in (type_comment_ast.argtypes or [])
- ]
- if type_comment_ast.returns:
- returns = self.visit(type_comment_ast.returns, parent)
- return returns, argtypes
- def visit_asyncfunctiondef(
- self, node: ast.AsyncFunctionDef, parent: nodes.NodeNG
- ) -> nodes.AsyncFunctionDef:
- return self._visit_functiondef(nodes.AsyncFunctionDef, node, parent)
- def visit_asyncfor(
- self, node: ast.AsyncFor, parent: nodes.NodeNG
- ) -> nodes.AsyncFor:
- return self._visit_for(nodes.AsyncFor, node, parent)
- def visit_await(self, node: ast.Await, parent: nodes.NodeNG) -> nodes.Await:
- newnode = nodes.Await(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(value=self.visit(node.value, newnode))
- return newnode
- def visit_asyncwith(
- self, node: ast.AsyncWith, parent: nodes.NodeNG
- ) -> nodes.AsyncWith:
- return self._visit_with(nodes.AsyncWith, node, parent)
- def visit_assign(self, node: ast.Assign, parent: nodes.NodeNG) -> nodes.Assign:
- """Visit a Assign node by returning a fresh instance of it."""
- newnode = nodes.Assign(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- type_annotation = self.check_type_comment(node, parent=newnode)
- newnode.postinit(
- targets=[self.visit(child, newnode) for child in node.targets],
- value=self.visit(node.value, newnode),
- type_annotation=type_annotation,
- )
- return newnode
- def visit_annassign(
- self, node: ast.AnnAssign, parent: nodes.NodeNG
- ) -> nodes.AnnAssign:
- """Visit an AnnAssign node by returning a fresh instance of it."""
- newnode = nodes.AnnAssign(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- target=self.visit(node.target, newnode),
- annotation=self.visit(node.annotation, newnode),
- simple=node.simple,
- value=self.visit(node.value, newnode),
- )
- return newnode
- @overload
- def visit_assignname(
- self, node: ast.AST, parent: nodes.NodeNG, node_name: str
- ) -> nodes.AssignName: ...
- @overload
- def visit_assignname(
- self, node: ast.AST, parent: nodes.NodeNG, node_name: None
- ) -> None: ...
- def visit_assignname(
- self, node: ast.AST, parent: nodes.NodeNG, node_name: str | None
- ) -> nodes.AssignName | None:
- """Visit a node and return a AssignName node.
- Note: Method not called by 'visit'
- """
- if node_name is None:
- return None
- newnode = nodes.AssignName(
- name=node_name,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- self._save_assignment(newnode)
- return newnode
- def visit_augassign(
- self, node: ast.AugAssign, parent: nodes.NodeNG
- ) -> nodes.AugAssign:
- """Visit a AugAssign node by returning a fresh instance of it."""
- newnode = nodes.AugAssign(
- op=self._parser_module.bin_op_classes[type(node.op)] + "=",
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.target, newnode), self.visit(node.value, newnode)
- )
- return newnode
- def visit_binop(self, node: ast.BinOp, parent: nodes.NodeNG) -> nodes.BinOp:
- """Visit a BinOp node by returning a fresh instance of it."""
- newnode = nodes.BinOp(
- op=self._parser_module.bin_op_classes[type(node.op)],
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.left, newnode), self.visit(node.right, newnode)
- )
- return newnode
- def visit_boolop(self, node: ast.BoolOp, parent: nodes.NodeNG) -> nodes.BoolOp:
- """Visit a BoolOp node by returning a fresh instance of it."""
- newnode = nodes.BoolOp(
- op=self._parser_module.bool_op_classes[type(node.op)],
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.values])
- return newnode
- def visit_break(self, node: ast.Break, parent: nodes.NodeNG) -> nodes.Break:
- """Visit a Break node by returning a fresh instance of it."""
- return nodes.Break(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_call(self, node: ast.Call, parent: nodes.NodeNG) -> nodes.Call:
- """Visit a CallFunc node by returning a fresh instance of it."""
- newnode = nodes.Call(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- func=self.visit(node.func, newnode),
- args=[self.visit(child, newnode) for child in node.args],
- keywords=[self.visit(child, newnode) for child in node.keywords],
- )
- return newnode
- def visit_classdef(
- self, node: ast.ClassDef, parent: nodes.NodeNG, newstyle: bool = True
- ) -> nodes.ClassDef:
- """Visit a ClassDef node to become astroid."""
- node, doc_ast_node = self._get_doc(node)
- newnode = nodes.ClassDef(
- name=node.name,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- metaclass = None
- for keyword in node.keywords:
- if keyword.arg == "metaclass":
- metaclass = self.visit(keyword, newnode).value
- break
- decorators = self.visit_decorators(node, newnode)
- newnode.postinit(
- [self.visit(child, newnode) for child in node.bases],
- [self.visit(child, newnode) for child in node.body],
- decorators,
- newstyle,
- metaclass,
- [
- self.visit(kwd, newnode)
- for kwd in node.keywords
- if kwd.arg != "metaclass"
- ],
- position=self._get_position_info(node, newnode),
- doc_node=self.visit(doc_ast_node, newnode),
- type_params=(
- [self.visit(param, newnode) for param in node.type_params]
- if PY312_PLUS
- else []
- ),
- )
- parent.set_local(newnode.name, newnode)
- return newnode
- def visit_continue(
- self, node: ast.Continue, parent: nodes.NodeNG
- ) -> nodes.Continue:
- """Visit a Continue node by returning a fresh instance of it."""
- return nodes.Continue(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_compare(self, node: ast.Compare, parent: nodes.NodeNG) -> nodes.Compare:
- """Visit a Compare node by returning a fresh instance of it."""
- newnode = nodes.Compare(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.left, newnode),
- [
- (
- self._parser_module.cmp_op_classes[op.__class__],
- self.visit(expr, newnode),
- )
- for (op, expr) in zip(node.ops, node.comparators)
- ],
- )
- return newnode
- def visit_comprehension(
- self, node: ast.comprehension, parent: nodes.NodeNG
- ) -> nodes.Comprehension:
- """Visit a Comprehension node by returning a fresh instance of it."""
- newnode = nodes.Comprehension(
- parent=parent,
- # Comprehension nodes don't have these attributes
- # see https://docs.python.org/3/library/ast.html#abstract-grammar
- lineno=None,
- col_offset=None,
- end_lineno=None,
- end_col_offset=None,
- )
- newnode.postinit(
- self.visit(node.target, newnode),
- self.visit(node.iter, newnode),
- [self.visit(child, newnode) for child in node.ifs],
- bool(node.is_async),
- )
- return newnode
- def visit_decorators(
- self,
- node: ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef,
- parent: nodes.NodeNG,
- ) -> nodes.Decorators | None:
- """Visit a Decorators node by returning a fresh instance of it.
- Note: Method not called by 'visit'
- """
- if not node.decorator_list:
- return None
- # /!\ node is actually an _ast.FunctionDef node while
- # parent is an astroid.nodes.FunctionDef node
- # Set the line number of the first decorator for Python 3.8+.
- lineno = node.decorator_list[0].lineno
- end_lineno = node.decorator_list[-1].end_lineno
- end_col_offset = node.decorator_list[-1].end_col_offset
- newnode = nodes.Decorators(
- lineno=lineno,
- col_offset=node.col_offset,
- end_lineno=end_lineno,
- end_col_offset=end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.decorator_list])
- return newnode
- def visit_delete(self, node: ast.Delete, parent: nodes.NodeNG) -> nodes.Delete:
- """Visit a Delete node by returning a fresh instance of it."""
- newnode = nodes.Delete(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.targets])
- return newnode
- def _visit_dict_items(
- self, node: ast.Dict, parent: nodes.NodeNG, newnode: nodes.Dict
- ) -> Generator[tuple[nodes.NodeNG, nodes.NodeNG]]:
- for key, value in zip(node.keys, node.values):
- rebuilt_key: nodes.NodeNG
- rebuilt_value = self.visit(value, newnode)
- if not key:
- # Extended unpacking
- rebuilt_key = nodes.DictUnpack(
- lineno=rebuilt_value.lineno,
- col_offset=rebuilt_value.col_offset,
- end_lineno=rebuilt_value.end_lineno,
- end_col_offset=rebuilt_value.end_col_offset,
- parent=parent,
- )
- else:
- rebuilt_key = self.visit(key, newnode)
- yield rebuilt_key, rebuilt_value
- def visit_dict(self, node: ast.Dict, parent: nodes.NodeNG) -> nodes.Dict:
- """Visit a Dict node by returning a fresh instance of it."""
- newnode = nodes.Dict(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- items: list[tuple[InferenceResult, InferenceResult]] = list(
- self._visit_dict_items(node, parent, newnode)
- )
- newnode.postinit(items)
- return newnode
- def visit_dictcomp(
- self, node: ast.DictComp, parent: nodes.NodeNG
- ) -> nodes.DictComp:
- """Visit a DictComp node by returning a fresh instance of it."""
- newnode = nodes.DictComp(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.key, newnode),
- self.visit(node.value, newnode),
- [self.visit(child, newnode) for child in node.generators],
- )
- return newnode
- def visit_expr(self, node: ast.Expr, parent: nodes.NodeNG) -> nodes.Expr:
- """Visit a Expr node by returning a fresh instance of it."""
- newnode = nodes.Expr(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_excepthandler(
- self, node: ast.ExceptHandler, parent: nodes.NodeNG
- ) -> nodes.ExceptHandler:
- """Visit an ExceptHandler node by returning a fresh instance of it."""
- newnode = nodes.ExceptHandler(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.type, newnode),
- self.visit_assignname(node, newnode, node.name),
- [self.visit(child, newnode) for child in node.body],
- )
- return newnode
- @overload
- def _visit_for(
- self, cls: type[nodes.For], node: ast.For, parent: nodes.NodeNG
- ) -> nodes.For: ...
- @overload
- def _visit_for(
- self, cls: type[nodes.AsyncFor], node: ast.AsyncFor, parent: nodes.NodeNG
- ) -> nodes.AsyncFor: ...
- def _visit_for(
- self, cls: type[_ForT], node: ast.For | ast.AsyncFor, parent: nodes.NodeNG
- ) -> _ForT:
- """Visit a For node by returning a fresh instance of it."""
- newnode = cls(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- type_annotation = self.check_type_comment(node, parent=newnode)
- newnode.postinit(
- target=self.visit(node.target, newnode),
- iter=self.visit(node.iter, newnode),
- body=[self.visit(child, newnode) for child in node.body],
- orelse=[self.visit(child, newnode) for child in node.orelse],
- type_annotation=type_annotation,
- )
- return newnode
- def visit_for(self, node: ast.For, parent: nodes.NodeNG) -> nodes.For:
- return self._visit_for(nodes.For, node, parent)
- def visit_importfrom(
- self, node: ast.ImportFrom, parent: nodes.NodeNG
- ) -> nodes.ImportFrom:
- """Visit an ImportFrom node by returning a fresh instance of it."""
- names = [(alias.name, alias.asname) for alias in node.names]
- newnode = nodes.ImportFrom(
- fromname=node.module or "",
- names=names,
- level=node.level or None,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # store From names to add them to locals after building
- self._import_from_nodes.append(
- (newnode, self._global_names[-1].keys() if self._global_names else ())
- )
- return newnode
- @overload
- def _visit_functiondef(
- self, cls: type[nodes.FunctionDef], node: ast.FunctionDef, parent: nodes.NodeNG
- ) -> nodes.FunctionDef: ...
- @overload
- def _visit_functiondef(
- self,
- cls: type[nodes.AsyncFunctionDef],
- node: ast.AsyncFunctionDef,
- parent: nodes.NodeNG,
- ) -> nodes.AsyncFunctionDef: ...
- def _visit_functiondef(
- self,
- cls: type[_FunctionT],
- node: ast.FunctionDef | ast.AsyncFunctionDef,
- parent: nodes.NodeNG,
- ) -> _FunctionT:
- """Visit an FunctionDef node to become astroid."""
- self._global_names.append({})
- node, doc_ast_node = self._get_doc(node)
- lineno = node.lineno
- if node.decorator_list:
- # Python 3.8 sets the line number of a decorated function
- # to be the actual line number of the function, but the
- # previous versions expected the decorator's line number instead.
- # We reset the function's line number to that of the
- # first decorator to maintain backward compatibility.
- # It's not ideal but this discrepancy was baked into
- # the framework for *years*.
- lineno = node.decorator_list[0].lineno
- newnode = cls(
- name=node.name,
- lineno=lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- decorators = self.visit_decorators(node, newnode)
- returns: nodes.NodeNG | None
- if node.returns:
- returns = self.visit(node.returns, newnode)
- else:
- returns = None
- type_comment_args = type_comment_returns = None
- type_comment_annotation = self.check_function_type_comment(node, newnode)
- if type_comment_annotation:
- type_comment_returns, type_comment_args = type_comment_annotation
- newnode.postinit(
- args=self.visit(node.args, newnode),
- body=[self.visit(child, newnode) for child in node.body],
- decorators=decorators,
- returns=returns,
- type_comment_returns=type_comment_returns,
- type_comment_args=type_comment_args,
- position=self._get_position_info(node, newnode),
- doc_node=self.visit(doc_ast_node, newnode),
- type_params=(
- [self.visit(param, newnode) for param in node.type_params]
- if PY312_PLUS
- else []
- ),
- )
- self._global_names.pop()
- parent.set_local(newnode.name, newnode)
- return newnode
- def visit_functiondef(
- self, node: ast.FunctionDef, parent: nodes.NodeNG
- ) -> nodes.FunctionDef:
- return self._visit_functiondef(nodes.FunctionDef, node, parent)
- def visit_generatorexp(
- self, node: ast.GeneratorExp, parent: nodes.NodeNG
- ) -> nodes.GeneratorExp:
- """Visit a GeneratorExp node by returning a fresh instance of it."""
- newnode = nodes.GeneratorExp(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.elt, newnode),
- [self.visit(child, newnode) for child in node.generators],
- )
- return newnode
- def visit_attribute(
- self, node: ast.Attribute, parent: nodes.NodeNG
- ) -> nodes.Attribute | nodes.AssignAttr | nodes.DelAttr:
- """Visit an Attribute node by returning a fresh instance of it."""
- context = self._get_context(node)
- newnode: nodes.Attribute | nodes.AssignAttr | nodes.DelAttr
- if context == Context.Del:
- # FIXME : maybe we should reintroduce and visit_delattr ?
- # for instance, deactivating assign_ctx
- newnode = nodes.DelAttr(
- attrname=node.attr,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- elif context == Context.Store:
- newnode = nodes.AssignAttr(
- attrname=node.attr,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Prohibit a local save if we are in an ExceptHandler.
- if not isinstance(parent, nodes.ExceptHandler):
- # mypy doesn't recognize that newnode has to be AssignAttr because it
- # doesn't support ParamSpec
- # See https://github.com/python/mypy/issues/8645
- self._delayed_assattr.append(newnode) # type: ignore[arg-type]
- else:
- newnode = nodes.Attribute(
- attrname=node.attr,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_global(self, node: ast.Global, parent: nodes.NodeNG) -> nodes.Global:
- """Visit a Global node to become astroid."""
- newnode = nodes.Global(
- names=node.names,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- if self._global_names: # global at the module level, no effect
- for name in node.names:
- self._global_names[-1].setdefault(name, []).append(newnode)
- return newnode
- def visit_if(self, node: ast.If, parent: nodes.NodeNG) -> nodes.If:
- """Visit an If node by returning a fresh instance of it."""
- newnode = nodes.If(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.test, newnode),
- [self.visit(child, newnode) for child in node.body],
- [self.visit(child, newnode) for child in node.orelse],
- )
- return newnode
- def visit_ifexp(self, node: ast.IfExp, parent: nodes.NodeNG) -> nodes.IfExp:
- """Visit a IfExp node by returning a fresh instance of it."""
- newnode = nodes.IfExp(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.test, newnode),
- self.visit(node.body, newnode),
- self.visit(node.orelse, newnode),
- )
- return newnode
- def visit_import(self, node: ast.Import, parent: nodes.NodeNG) -> nodes.Import:
- """Visit a Import node by returning a fresh instance of it."""
- names = [(alias.name, alias.asname) for alias in node.names]
- newnode = nodes.Import(
- names=names,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # save import names in parent's locals:
- for name, asname in newnode.names:
- name = (asname or name).split(".")[0]
- if self._global_names and name in self._global_names[-1]:
- parent.root().set_local(name, newnode)
- else:
- parent.set_local(name, newnode)
- return newnode
- def visit_joinedstr(
- self, node: ast.JoinedStr, parent: nodes.NodeNG
- ) -> nodes.JoinedStr:
- newnode = nodes.JoinedStr(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.values])
- return newnode
- def visit_formattedvalue(
- self, node: ast.FormattedValue, parent: nodes.NodeNG
- ) -> nodes.FormattedValue:
- newnode = nodes.FormattedValue(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- value=self.visit(node.value, newnode),
- conversion=node.conversion,
- format_spec=self.visit(node.format_spec, newnode),
- )
- return newnode
- def visit_namedexpr(
- self, node: ast.NamedExpr, parent: nodes.NodeNG
- ) -> nodes.NamedExpr:
- newnode = nodes.NamedExpr(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.target, newnode), self.visit(node.value, newnode)
- )
- return newnode
- def visit_keyword(self, node: ast.keyword, parent: nodes.NodeNG) -> nodes.Keyword:
- """Visit a Keyword node by returning a fresh instance of it."""
- newnode = nodes.Keyword(
- arg=node.arg,
- # position attributes added in 3.9
- lineno=getattr(node, "lineno", None),
- col_offset=getattr(node, "col_offset", None),
- end_lineno=getattr(node, "end_lineno", None),
- end_col_offset=getattr(node, "end_col_offset", None),
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_lambda(self, node: ast.Lambda, parent: nodes.NodeNG) -> nodes.Lambda:
- """Visit a Lambda node by returning a fresh instance of it."""
- newnode = nodes.Lambda(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.args, newnode), self.visit(node.body, newnode))
- return newnode
- def visit_list(self, node: ast.List, parent: nodes.NodeNG) -> nodes.List:
- """Visit a List node by returning a fresh instance of it."""
- context = self._get_context(node)
- newnode = nodes.List(
- ctx=context,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.elts])
- return newnode
- def visit_listcomp(
- self, node: ast.ListComp, parent: nodes.NodeNG
- ) -> nodes.ListComp:
- """Visit a ListComp node by returning a fresh instance of it."""
- newnode = nodes.ListComp(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.elt, newnode),
- [self.visit(child, newnode) for child in node.generators],
- )
- return newnode
- def visit_name(
- self, node: ast.Name, parent: nodes.NodeNG
- ) -> nodes.Name | nodes.AssignName | nodes.DelName:
- """Visit a Name node by returning a fresh instance of it."""
- context = self._get_context(node)
- newnode: nodes.Name | nodes.AssignName | nodes.DelName
- if context == Context.Del:
- newnode = nodes.DelName(
- name=node.id,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- elif context == Context.Store:
- newnode = nodes.AssignName(
- name=node.id,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- else:
- newnode = nodes.Name(
- name=node.id,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # XXX REMOVE me :
- if context in (Context.Del, Context.Store): # 'Aug' ??
- newnode = cast((nodes.AssignName | nodes.DelName), newnode)
- self._save_assignment(newnode)
- return newnode
- def visit_nonlocal(
- self, node: ast.Nonlocal, parent: nodes.NodeNG
- ) -> nodes.Nonlocal:
- """Visit a Nonlocal node and return a new instance of it."""
- return nodes.Nonlocal(
- names=node.names,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_constant(self, node: ast.Constant, parent: nodes.NodeNG) -> nodes.Const:
- """Visit a Constant node by returning a fresh instance of Const."""
- return nodes.Const(
- value=node.value,
- kind=node.kind,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_paramspec(
- self, node: ast.ParamSpec, parent: nodes.NodeNG
- ) -> nodes.ParamSpec:
- """Visit a ParamSpec node by returning a fresh instance of it."""
- newnode = nodes.ParamSpec(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Add AssignName node for 'node.name'
- # https://bugs.python.org/issue43994
- newnode.postinit(
- name=self.visit_assignname(node, newnode, node.name),
- default_value=(
- self.visit(node.default_value, newnode) if PY313_PLUS else None
- ),
- )
- return newnode
- def visit_pass(self, node: ast.Pass, parent: nodes.NodeNG) -> nodes.Pass:
- """Visit a Pass node by returning a fresh instance of it."""
- return nodes.Pass(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_raise(self, node: ast.Raise, parent: nodes.NodeNG) -> nodes.Raise:
- """Visit a Raise node by returning a fresh instance of it."""
- newnode = nodes.Raise(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # no traceback; anyway it is not used in Pylint
- newnode.postinit(
- exc=self.visit(node.exc, newnode),
- cause=self.visit(node.cause, newnode),
- )
- return newnode
- def visit_return(self, node: ast.Return, parent: nodes.NodeNG) -> nodes.Return:
- """Visit a Return node by returning a fresh instance of it."""
- newnode = nodes.Return(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_set(self, node: ast.Set, parent: nodes.NodeNG) -> nodes.Set:
- """Visit a Set node by returning a fresh instance of it."""
- newnode = nodes.Set(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.elts])
- return newnode
- def visit_setcomp(self, node: ast.SetComp, parent: nodes.NodeNG) -> nodes.SetComp:
- """Visit a SetComp node by returning a fresh instance of it."""
- newnode = nodes.SetComp(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.elt, newnode),
- [self.visit(child, newnode) for child in node.generators],
- )
- return newnode
- def visit_slice(self, node: ast.Slice, parent: nodes.Subscript) -> nodes.Slice:
- """Visit a Slice node by returning a fresh instance of it."""
- newnode = nodes.Slice(
- # position attributes added in 3.9
- lineno=getattr(node, "lineno", None),
- col_offset=getattr(node, "col_offset", None),
- end_lineno=getattr(node, "end_lineno", None),
- end_col_offset=getattr(node, "end_col_offset", None),
- parent=parent,
- )
- newnode.postinit(
- lower=self.visit(node.lower, newnode),
- upper=self.visit(node.upper, newnode),
- step=self.visit(node.step, newnode),
- )
- return newnode
- def visit_subscript(
- self, node: ast.Subscript, parent: nodes.NodeNG
- ) -> nodes.Subscript:
- """Visit a Subscript node by returning a fresh instance of it."""
- context = self._get_context(node)
- newnode = nodes.Subscript(
- ctx=context,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.value, newnode), self.visit(node.slice, newnode)
- )
- return newnode
- def visit_starred(self, node: ast.Starred, parent: nodes.NodeNG) -> nodes.Starred:
- """Visit a Starred node and return a new instance of it."""
- context = self._get_context(node)
- newnode = nodes.Starred(
- ctx=context,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_try(self, node: ast.Try, parent: nodes.NodeNG) -> nodes.Try:
- """Visit a Try node by returning a fresh instance of it"""
- newnode = nodes.Try(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- body=[self.visit(child, newnode) for child in node.body],
- handlers=[self.visit(child, newnode) for child in node.handlers],
- orelse=[self.visit(child, newnode) for child in node.orelse],
- finalbody=[self.visit(child, newnode) for child in node.finalbody],
- )
- return newnode
- def visit_trystar(self, node: ast.TryStar, parent: nodes.NodeNG) -> nodes.TryStar:
- newnode = nodes.TryStar(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- body=[self.visit(n, newnode) for n in node.body],
- handlers=[self.visit(n, newnode) for n in node.handlers],
- orelse=[self.visit(n, newnode) for n in node.orelse],
- finalbody=[self.visit(n, newnode) for n in node.finalbody],
- )
- return newnode
- def visit_tuple(self, node: ast.Tuple, parent: nodes.NodeNG) -> nodes.Tuple:
- """Visit a Tuple node by returning a fresh instance of it."""
- context = self._get_context(node)
- newnode = nodes.Tuple(
- ctx=context,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit([self.visit(child, newnode) for child in node.elts])
- return newnode
- def visit_typealias(
- self, node: ast.TypeAlias, parent: nodes.NodeNG
- ) -> nodes.TypeAlias:
- """Visit a TypeAlias node by returning a fresh instance of it."""
- newnode = nodes.TypeAlias(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- name=self.visit(node.name, newnode),
- type_params=[self.visit(p, newnode) for p in node.type_params],
- value=self.visit(node.value, newnode),
- )
- return newnode
- def visit_typevar(self, node: ast.TypeVar, parent: nodes.NodeNG) -> nodes.TypeVar:
- """Visit a TypeVar node by returning a fresh instance of it."""
- newnode = nodes.TypeVar(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Add AssignName node for 'node.name'
- # https://bugs.python.org/issue43994
- newnode.postinit(
- name=self.visit_assignname(node, newnode, node.name),
- bound=self.visit(node.bound, newnode),
- default_value=(
- self.visit(node.default_value, newnode) if PY313_PLUS else None
- ),
- )
- return newnode
- def visit_typevartuple(
- self, node: ast.TypeVarTuple, parent: nodes.NodeNG
- ) -> nodes.TypeVarTuple:
- """Visit a TypeVarTuple node by returning a fresh instance of it."""
- newnode = nodes.TypeVarTuple(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Add AssignName node for 'node.name'
- # https://bugs.python.org/issue43994
- newnode.postinit(
- name=self.visit_assignname(node, newnode, node.name),
- default_value=(
- self.visit(node.default_value, newnode) if PY313_PLUS else None
- ),
- )
- return newnode
- def visit_unaryop(self, node: ast.UnaryOp, parent: nodes.NodeNG) -> nodes.UnaryOp:
- """Visit a UnaryOp node by returning a fresh instance of it."""
- newnode = nodes.UnaryOp(
- op=self._parser_module.unary_op_classes[node.op.__class__],
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.operand, newnode))
- return newnode
- def visit_while(self, node: ast.While, parent: nodes.NodeNG) -> nodes.While:
- """Visit a While node by returning a fresh instance of it."""
- newnode = nodes.While(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- self.visit(node.test, newnode),
- [self.visit(child, newnode) for child in node.body],
- [self.visit(child, newnode) for child in node.orelse],
- )
- return newnode
- @overload
- def _visit_with(
- self, cls: type[nodes.With], node: ast.With, parent: nodes.NodeNG
- ) -> nodes.With: ...
- @overload
- def _visit_with(
- self, cls: type[nodes.AsyncWith], node: ast.AsyncWith, parent: nodes.NodeNG
- ) -> nodes.AsyncWith: ...
- def _visit_with(
- self,
- cls: type[_WithT],
- node: ast.With | ast.AsyncWith,
- parent: nodes.NodeNG,
- ) -> _WithT:
- newnode = cls(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_child(
- child: ast.withitem,
- ) -> tuple[nodes.NodeNG, nodes.NodeNG | None]:
- expr = self.visit(child.context_expr, newnode)
- var = self.visit(child.optional_vars, newnode)
- return expr, var
- type_annotation = self.check_type_comment(node, parent=newnode)
- newnode.postinit(
- items=[visit_child(child) for child in node.items],
- body=[self.visit(child, newnode) for child in node.body],
- type_annotation=type_annotation,
- )
- return newnode
- def visit_with(self, node: ast.With, parent: nodes.NodeNG) -> nodes.NodeNG:
- return self._visit_with(nodes.With, node, parent)
- def visit_yield(self, node: ast.Yield, parent: nodes.NodeNG) -> nodes.NodeNG:
- """Visit a Yield node by returning a fresh instance of it."""
- newnode = nodes.Yield(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_yieldfrom(
- self, node: ast.YieldFrom, parent: nodes.NodeNG
- ) -> nodes.NodeNG:
- newnode = nodes.YieldFrom(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(self.visit(node.value, newnode))
- return newnode
- def visit_match(self, node: ast.Match, parent: nodes.NodeNG) -> nodes.Match:
- newnode = nodes.Match(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- subject=self.visit(node.subject, newnode),
- cases=[self.visit(case, newnode) for case in node.cases],
- )
- return newnode
- def visit_matchcase(
- self, node: ast.match_case, parent: nodes.NodeNG
- ) -> nodes.MatchCase:
- newnode = nodes.MatchCase(parent=parent)
- newnode.postinit(
- pattern=self.visit(node.pattern, newnode),
- guard=self.visit(node.guard, newnode),
- body=[self.visit(child, newnode) for child in node.body],
- )
- return newnode
- def visit_matchvalue(
- self, node: ast.MatchValue, parent: nodes.NodeNG
- ) -> nodes.MatchValue:
- newnode = nodes.MatchValue(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(value=self.visit(node.value, newnode))
- return newnode
- def visit_matchsingleton(
- self, node: ast.MatchSingleton, parent: nodes.NodeNG
- ) -> nodes.MatchSingleton:
- return nodes.MatchSingleton(
- value=node.value,
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- def visit_matchsequence(
- self, node: ast.MatchSequence, parent: nodes.NodeNG
- ) -> nodes.MatchSequence:
- newnode = nodes.MatchSequence(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- patterns=[self.visit(pattern, newnode) for pattern in node.patterns]
- )
- return newnode
- def visit_matchmapping(
- self, node: ast.MatchMapping, parent: nodes.NodeNG
- ) -> nodes.MatchMapping:
- newnode = nodes.MatchMapping(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Add AssignName node for 'node.name'
- # https://bugs.python.org/issue43994
- newnode.postinit(
- keys=[self.visit(child, newnode) for child in node.keys],
- patterns=[self.visit(pattern, newnode) for pattern in node.patterns],
- rest=self.visit_assignname(node, newnode, node.rest),
- )
- return newnode
- def visit_matchclass(
- self, node: ast.MatchClass, parent: nodes.NodeNG
- ) -> nodes.MatchClass:
- newnode = nodes.MatchClass(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- cls=self.visit(node.cls, newnode),
- patterns=[self.visit(pattern, newnode) for pattern in node.patterns],
- kwd_attrs=node.kwd_attrs,
- kwd_patterns=[
- self.visit(pattern, newnode) for pattern in node.kwd_patterns
- ],
- )
- return newnode
- def visit_matchstar(
- self, node: ast.MatchStar, parent: nodes.NodeNG
- ) -> nodes.MatchStar:
- newnode = nodes.MatchStar(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Add AssignName node for 'node.name'
- # https://bugs.python.org/issue43994
- newnode.postinit(name=self.visit_assignname(node, newnode, node.name))
- return newnode
- def visit_matchas(self, node: ast.MatchAs, parent: nodes.NodeNG) -> nodes.MatchAs:
- newnode = nodes.MatchAs(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- # Add AssignName node for 'node.name'
- # https://bugs.python.org/issue43994
- newnode.postinit(
- pattern=self.visit(node.pattern, newnode),
- name=self.visit_assignname(node, newnode, node.name),
- )
- return newnode
- def visit_matchor(self, node: ast.MatchOr, parent: nodes.NodeNG) -> nodes.MatchOr:
- newnode = nodes.MatchOr(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- patterns=[self.visit(pattern, newnode) for pattern in node.patterns]
- )
- return newnode
- if sys.version_info >= (3, 14):
- def visit_templatestr(
- self, node: ast.TemplateStr, parent: nodes.NodeNG
- ) -> nodes.TemplateStr:
- newnode = nodes.TemplateStr(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- values=[self.visit(value, newnode) for value in node.values]
- )
- return newnode
- def visit_interpolation(
- self, node: ast.Interpolation, parent: nodes.NodeNG
- ) -> nodes.Interpolation:
- newnode = nodes.Interpolation(
- lineno=node.lineno,
- col_offset=node.col_offset,
- end_lineno=node.end_lineno,
- end_col_offset=node.end_col_offset,
- parent=parent,
- )
- newnode.postinit(
- value=self.visit(node.value, parent),
- str=node.str,
- conversion=node.conversion,
- format_spec=self.visit(node.format_spec, parent),
- )
- return newnode
|