node_classes.py 169 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643
  1. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  2. # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  3. # Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
  4. """Module for some node classes. More nodes in scoped_nodes.py"""
  5. from __future__ import annotations
  6. import abc
  7. import itertools
  8. import sys
  9. import typing
  10. import warnings
  11. from collections.abc import Generator, Iterable, Mapping
  12. from functools import lru_cache
  13. from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union
  14. from astroid import decorators, util
  15. from astroid.bases import Instance, _infer_stmts
  16. from astroid.const import _EMPTY_OBJECT_MARKER, Context
  17. from astroid.context import InferenceContext
  18. from astroid.exceptions import (
  19. AstroidIndexError,
  20. AstroidTypeError,
  21. AstroidValueError,
  22. InferenceError,
  23. NoDefault,
  24. ParentMissingError,
  25. )
  26. from astroid.manager import AstroidManager
  27. from astroid.nodes import _base_nodes
  28. from astroid.nodes.const import OP_PRECEDENCE
  29. from astroid.nodes.node_ng import NodeNG
  30. from astroid.typing import (
  31. ConstFactoryResult,
  32. InferBinaryOp,
  33. InferenceErrorInfo,
  34. InferenceResult,
  35. SuccessfulInferenceResult,
  36. )
  37. if sys.version_info >= (3, 8):
  38. from typing import Literal
  39. else:
  40. from typing_extensions import Literal
  41. if TYPE_CHECKING:
  42. from astroid import nodes
  43. from astroid.nodes import LocalsDictNodeNG
  44. if sys.version_info >= (3, 8):
  45. from functools import cached_property
  46. else:
  47. from astroid.decorators import cachedproperty as cached_property
  48. def _is_const(value) -> bool:
  49. return isinstance(value, tuple(CONST_CLS))
  50. _NodesT = TypeVar("_NodesT", bound=NodeNG)
  51. _BadOpMessageT = TypeVar("_BadOpMessageT", bound=util.BadOperationMessage)
  52. AssignedStmtsPossibleNode = Union["List", "Tuple", "AssignName", "AssignAttr", None]
  53. AssignedStmtsCall = Callable[
  54. [
  55. _NodesT,
  56. AssignedStmtsPossibleNode,
  57. Optional[InferenceContext],
  58. Optional[typing.List[int]],
  59. ],
  60. Any,
  61. ]
  62. InferBinaryOperation = Callable[
  63. [_NodesT, Optional[InferenceContext]],
  64. typing.Generator[Union[InferenceResult, _BadOpMessageT], None, None],
  65. ]
  66. InferLHS = Callable[
  67. [_NodesT, Optional[InferenceContext]],
  68. typing.Generator[InferenceResult, None, Optional[InferenceErrorInfo]],
  69. ]
  70. InferUnaryOp = Callable[[_NodesT, str], ConstFactoryResult]
  71. @decorators.raise_if_nothing_inferred
  72. def unpack_infer(stmt, context: InferenceContext | None = None):
  73. """recursively generate nodes inferred by the given statement.
  74. If the inferred value is a list or a tuple, recurse on the elements
  75. """
  76. if isinstance(stmt, (List, Tuple)):
  77. for elt in stmt.elts:
  78. if elt is util.Uninferable:
  79. yield elt
  80. continue
  81. yield from unpack_infer(elt, context)
  82. return {"node": stmt, "context": context}
  83. # if inferred is a final node, return it and stop
  84. inferred = next(stmt.infer(context), util.Uninferable)
  85. if inferred is stmt:
  86. yield inferred
  87. return {"node": stmt, "context": context}
  88. # else, infer recursively, except Uninferable object that should be returned as is
  89. for inferred in stmt.infer(context):
  90. if isinstance(inferred, util.UninferableBase):
  91. yield inferred
  92. else:
  93. yield from unpack_infer(inferred, context)
  94. return {"node": stmt, "context": context}
  95. def are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:
  96. """return true if the two given statements are mutually exclusive
  97. `exceptions` may be a list of exception names. If specified, discard If
  98. branches and check one of the statement is in an exception handler catching
  99. one of the given exceptions.
  100. algorithm :
  101. 1) index stmt1's parents
  102. 2) climb among stmt2's parents until we find a common parent
  103. 3) if the common parent is a If or TryExcept statement, look if nodes are
  104. in exclusive branches
  105. """
  106. # index stmt1's parents
  107. stmt1_parents = {}
  108. children = {}
  109. previous = stmt1
  110. for node in stmt1.node_ancestors():
  111. stmt1_parents[node] = 1
  112. children[node] = previous
  113. previous = node
  114. # climb among stmt2's parents until we find a common parent
  115. previous = stmt2
  116. for node in stmt2.node_ancestors():
  117. if node in stmt1_parents:
  118. # if the common parent is a If or TryExcept statement, look if
  119. # nodes are in exclusive branches
  120. if isinstance(node, If) and exceptions is None:
  121. c2attr, c2node = node.locate_child(previous)
  122. c1attr, c1node = node.locate_child(children[node])
  123. if "test" in (c1attr, c2attr):
  124. # If any node is `If.test`, then it must be inclusive with
  125. # the other node (`If.body` and `If.orelse`)
  126. return False
  127. if c1attr != c2attr:
  128. # different `If` branches (`If.body` and `If.orelse`)
  129. return True
  130. elif isinstance(node, TryExcept):
  131. c2attr, c2node = node.locate_child(previous)
  132. c1attr, c1node = node.locate_child(children[node])
  133. if c1node is not c2node:
  134. first_in_body_caught_by_handlers = (
  135. c2attr == "handlers"
  136. and c1attr == "body"
  137. and previous.catch(exceptions)
  138. )
  139. second_in_body_caught_by_handlers = (
  140. c2attr == "body"
  141. and c1attr == "handlers"
  142. and children[node].catch(exceptions)
  143. )
  144. first_in_else_other_in_handlers = (
  145. c2attr == "handlers" and c1attr == "orelse"
  146. )
  147. second_in_else_other_in_handlers = (
  148. c2attr == "orelse" and c1attr == "handlers"
  149. )
  150. if any(
  151. (
  152. first_in_body_caught_by_handlers,
  153. second_in_body_caught_by_handlers,
  154. first_in_else_other_in_handlers,
  155. second_in_else_other_in_handlers,
  156. )
  157. ):
  158. return True
  159. elif c2attr == "handlers" and c1attr == "handlers":
  160. return previous is not children[node]
  161. return False
  162. previous = node
  163. return False
  164. # getitem() helpers.
  165. _SLICE_SENTINEL = object()
  166. def _slice_value(index, context: InferenceContext | None = None):
  167. """Get the value of the given slice index."""
  168. if isinstance(index, Const):
  169. if isinstance(index.value, (int, type(None))):
  170. return index.value
  171. elif index is None:
  172. return None
  173. else:
  174. # Try to infer what the index actually is.
  175. # Since we can't return all the possible values,
  176. # we'll stop at the first possible value.
  177. try:
  178. inferred = next(index.infer(context=context))
  179. except (InferenceError, StopIteration):
  180. pass
  181. else:
  182. if isinstance(inferred, Const):
  183. if isinstance(inferred.value, (int, type(None))):
  184. return inferred.value
  185. # Use a sentinel, because None can be a valid
  186. # value that this function can return,
  187. # as it is the case for unspecified bounds.
  188. return _SLICE_SENTINEL
  189. def _infer_slice(node, context: InferenceContext | None = None):
  190. lower = _slice_value(node.lower, context)
  191. upper = _slice_value(node.upper, context)
  192. step = _slice_value(node.step, context)
  193. if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):
  194. return slice(lower, upper, step)
  195. raise AstroidTypeError(
  196. message="Could not infer slice used in subscript",
  197. node=node,
  198. index=node.parent,
  199. context=context,
  200. )
  201. def _container_getitem(instance, elts, index, context: InferenceContext | None = None):
  202. """Get a slice or an item, using the given *index*, for the given sequence."""
  203. try:
  204. if isinstance(index, Slice):
  205. index_slice = _infer_slice(index, context=context)
  206. new_cls = instance.__class__()
  207. new_cls.elts = elts[index_slice]
  208. new_cls.parent = instance.parent
  209. return new_cls
  210. if isinstance(index, Const):
  211. return elts[index.value]
  212. except ValueError as exc:
  213. raise AstroidValueError(
  214. message="Slice {index!r} cannot index container",
  215. node=instance,
  216. index=index,
  217. context=context,
  218. ) from exc
  219. except IndexError as exc:
  220. raise AstroidIndexError(
  221. message="Index {index!s} out of range",
  222. node=instance,
  223. index=index,
  224. context=context,
  225. ) from exc
  226. except TypeError as exc:
  227. raise AstroidTypeError(
  228. message="Type error {error!r}", node=instance, index=index, context=context
  229. ) from exc
  230. raise AstroidTypeError(f"Could not use {index} as subscript index")
  231. class BaseContainer(_base_nodes.ParentAssignNode, Instance, metaclass=abc.ABCMeta):
  232. """Base class for Set, FrozenSet, Tuple and List."""
  233. _astroid_fields = ("elts",)
  234. def __init__(
  235. self,
  236. lineno: int | None = None,
  237. col_offset: int | None = None,
  238. parent: NodeNG | None = None,
  239. *,
  240. end_lineno: int | None = None,
  241. end_col_offset: int | None = None,
  242. ) -> None:
  243. """
  244. :param lineno: The line that this node appears on in the source code.
  245. :param col_offset: The column that this node appears on in the
  246. source code.
  247. :param parent: The parent node in the syntax tree.
  248. :param end_lineno: The last line this node appears on in the source code.
  249. :param end_col_offset: The end column this node appears on in the
  250. source code. Note: This is after the last symbol.
  251. """
  252. self.elts: list[NodeNG] = []
  253. """The elements in the node."""
  254. super().__init__(
  255. lineno=lineno,
  256. col_offset=col_offset,
  257. end_lineno=end_lineno,
  258. end_col_offset=end_col_offset,
  259. parent=parent,
  260. )
  261. def postinit(self, elts: list[NodeNG]) -> None:
  262. """Do some setup after initialisation.
  263. :param elts: The list of elements the that node contains.
  264. """
  265. self.elts = elts
  266. @classmethod
  267. def from_elements(cls, elts=None):
  268. """Create a node of this type from the given list of elements.
  269. :param elts: The list of elements that the node should contain.
  270. :type elts: list(NodeNG)
  271. :returns: A new node containing the given elements.
  272. :rtype: NodeNG
  273. """
  274. node = cls()
  275. if elts is None:
  276. node.elts = []
  277. else:
  278. node.elts = [const_factory(e) if _is_const(e) else e for e in elts]
  279. return node
  280. def itered(self):
  281. """An iterator over the elements this node contains.
  282. :returns: The contents of this node.
  283. :rtype: iterable(NodeNG)
  284. """
  285. return self.elts
  286. def bool_value(self, context: InferenceContext | None = None) -> bool:
  287. """Determine the boolean value of this node.
  288. :returns: The boolean value of this node.
  289. """
  290. return bool(self.elts)
  291. @abc.abstractmethod
  292. def pytype(self) -> str:
  293. """Get the name of the type that this node represents.
  294. :returns: The name of the type.
  295. """
  296. def get_children(self):
  297. yield from self.elts
  298. # TODO: Move into _base_nodes. Blocked by import of _infer_stmts from bases.
  299. class LookupMixIn(NodeNG):
  300. """Mixin to look up a name in the right scope."""
  301. @lru_cache() # noqa
  302. def lookup(self, name: str) -> tuple[LocalsDictNodeNG, list[NodeNG]]:
  303. """Lookup where the given variable is assigned.
  304. The lookup starts from self's scope. If self is not a frame itself
  305. and the name is found in the inner frame locals, statements will be
  306. filtered to remove ignorable statements according to self's location.
  307. :param name: The name of the variable to find assignments for.
  308. :returns: The scope node and the list of assignments associated to the
  309. given name according to the scope where it has been found (locals,
  310. globals or builtin).
  311. """
  312. return self.scope().scope_lookup(self, name)
  313. def ilookup(self, name):
  314. """Lookup the inferred values of the given variable.
  315. :param name: The variable name to find values for.
  316. :type name: str
  317. :returns: The inferred values of the statements returned from
  318. :meth:`lookup`.
  319. :rtype: iterable
  320. """
  321. frame, stmts = self.lookup(name)
  322. context = InferenceContext()
  323. return _infer_stmts(stmts, context, frame)
  324. # Name classes
  325. class AssignName(_base_nodes.NoChildrenNode, LookupMixIn, _base_nodes.ParentAssignNode):
  326. """Variation of :class:`ast.Assign` representing assignment to a name.
  327. An :class:`AssignName` is the name of something that is assigned to.
  328. This includes variables defined in a function signature or in a loop.
  329. >>> import astroid
  330. >>> node = astroid.extract_node('variable = range(10)')
  331. >>> node
  332. <Assign l.1 at 0x7effe1db8550>
  333. >>> list(node.get_children())
  334. [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]
  335. >>> list(node.get_children())[0].as_string()
  336. 'variable'
  337. """
  338. _other_fields = ("name",)
  339. infer_lhs: ClassVar[InferLHS[AssignName]]
  340. @decorators.deprecate_default_argument_values(name="str")
  341. def __init__(
  342. self,
  343. name: str | None = None,
  344. lineno: int | None = None,
  345. col_offset: int | None = None,
  346. parent: NodeNG | None = None,
  347. *,
  348. end_lineno: int | None = None,
  349. end_col_offset: int | None = None,
  350. ) -> None:
  351. """
  352. :param name: The name that is assigned to.
  353. :param lineno: The line that this node appears on in the source code.
  354. :param col_offset: The column that this node appears on in the
  355. source code.
  356. :param parent: The parent node in the syntax tree.
  357. :param end_lineno: The last line this node appears on in the source code.
  358. :param end_col_offset: The end column this node appears on in the
  359. source code. Note: This is after the last symbol.
  360. """
  361. self.name: str | None = name
  362. """The name that is assigned to."""
  363. super().__init__(
  364. lineno=lineno,
  365. col_offset=col_offset,
  366. end_lineno=end_lineno,
  367. end_col_offset=end_col_offset,
  368. parent=parent,
  369. )
  370. assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]
  371. """Returns the assigned statement (non inferred) according to the assignment type.
  372. See astroid/protocols.py for actual implementation.
  373. """
  374. class DelName(_base_nodes.NoChildrenNode, LookupMixIn, _base_nodes.ParentAssignNode):
  375. """Variation of :class:`ast.Delete` representing deletion of a name.
  376. A :class:`DelName` is the name of something that is deleted.
  377. >>> import astroid
  378. >>> node = astroid.extract_node("del variable #@")
  379. >>> list(node.get_children())
  380. [<DelName.variable l.1 at 0x7effe1da4d30>]
  381. >>> list(node.get_children())[0].as_string()
  382. 'variable'
  383. """
  384. _other_fields = ("name",)
  385. @decorators.deprecate_default_argument_values(name="str")
  386. def __init__(
  387. self,
  388. name: str | None = None,
  389. lineno: int | None = None,
  390. col_offset: int | None = None,
  391. parent: NodeNG | None = None,
  392. *,
  393. end_lineno: int | None = None,
  394. end_col_offset: int | None = None,
  395. ) -> None:
  396. """
  397. :param name: The name that is being deleted.
  398. :param lineno: The line that this node appears on in the source code.
  399. :param col_offset: The column that this node appears on in the
  400. source code.
  401. :param parent: The parent node in the syntax tree.
  402. :param end_lineno: The last line this node appears on in the source code.
  403. :param end_col_offset: The end column this node appears on in the
  404. source code. Note: This is after the last symbol.
  405. """
  406. self.name: str | None = name
  407. """The name that is being deleted."""
  408. super().__init__(
  409. lineno=lineno,
  410. col_offset=col_offset,
  411. end_lineno=end_lineno,
  412. end_col_offset=end_col_offset,
  413. parent=parent,
  414. )
  415. class Name(_base_nodes.NoChildrenNode, LookupMixIn):
  416. """Class representing an :class:`ast.Name` node.
  417. A :class:`Name` node is something that is named, but not covered by
  418. :class:`AssignName` or :class:`DelName`.
  419. >>> import astroid
  420. >>> node = astroid.extract_node('range(10)')
  421. >>> node
  422. <Call l.1 at 0x7effe1db8710>
  423. >>> list(node.get_children())
  424. [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]
  425. >>> list(node.get_children())[0].as_string()
  426. 'range'
  427. """
  428. _other_fields = ("name",)
  429. @decorators.deprecate_default_argument_values(name="str")
  430. def __init__(
  431. self,
  432. name: str | None = None,
  433. lineno: int | None = None,
  434. col_offset: int | None = None,
  435. parent: NodeNG | None = None,
  436. *,
  437. end_lineno: int | None = None,
  438. end_col_offset: int | None = None,
  439. ) -> None:
  440. """
  441. :param name: The name that this node refers to.
  442. :param lineno: The line that this node appears on in the source code.
  443. :param col_offset: The column that this node appears on in the
  444. source code.
  445. :param parent: The parent node in the syntax tree.
  446. :param end_lineno: The last line this node appears on in the source code.
  447. :param end_col_offset: The end column this node appears on in the
  448. source code. Note: This is after the last symbol.
  449. """
  450. self.name: str | None = name
  451. """The name that this node refers to."""
  452. super().__init__(
  453. lineno=lineno,
  454. col_offset=col_offset,
  455. end_lineno=end_lineno,
  456. end_col_offset=end_col_offset,
  457. parent=parent,
  458. )
  459. def _get_name_nodes(self):
  460. yield self
  461. for child_node in self.get_children():
  462. yield from child_node._get_name_nodes()
  463. class Arguments(_base_nodes.AssignTypeNode):
  464. """Class representing an :class:`ast.arguments` node.
  465. An :class:`Arguments` node represents that arguments in a
  466. function definition.
  467. >>> import astroid
  468. >>> node = astroid.extract_node('def foo(bar): pass')
  469. >>> node
  470. <FunctionDef.foo l.1 at 0x7effe1db8198>
  471. >>> node.args
  472. <Arguments l.1 at 0x7effe1db82e8>
  473. """
  474. # Python 3.4+ uses a different approach regarding annotations,
  475. # each argument is a new class, _ast.arg, which exposes an
  476. # 'annotation' attribute. In astroid though, arguments are exposed
  477. # as is in the Arguments node and the only way to expose annotations
  478. # is by using something similar with Python 3.3:
  479. # - we expose 'varargannotation' and 'kwargannotation' of annotations
  480. # of varargs and kwargs.
  481. # - we expose 'annotation', a list with annotations for
  482. # for each normal argument. If an argument doesn't have an
  483. # annotation, its value will be None.
  484. _astroid_fields = (
  485. "args",
  486. "defaults",
  487. "kwonlyargs",
  488. "posonlyargs",
  489. "posonlyargs_annotations",
  490. "kw_defaults",
  491. "annotations",
  492. "varargannotation",
  493. "kwargannotation",
  494. "kwonlyargs_annotations",
  495. "type_comment_args",
  496. "type_comment_kwonlyargs",
  497. "type_comment_posonlyargs",
  498. )
  499. _other_fields = ("vararg", "kwarg")
  500. lineno: None
  501. col_offset: None
  502. end_lineno: None
  503. end_col_offset: None
  504. def __init__(
  505. self,
  506. vararg: str | None = None,
  507. kwarg: str | None = None,
  508. parent: NodeNG | None = None,
  509. ) -> None:
  510. """
  511. :param vararg: The name of the variable length arguments.
  512. :param kwarg: The name of the variable length keyword arguments.
  513. :param parent: The parent node in the syntax tree.
  514. """
  515. super().__init__(parent=parent)
  516. self.vararg: str | None = vararg # can be None
  517. """The name of the variable length arguments."""
  518. self.kwarg: str | None = kwarg # can be None
  519. """The name of the variable length keyword arguments."""
  520. self.args: list[AssignName] | None
  521. """The names of the required arguments.
  522. Can be None if the associated function does not have a retrievable
  523. signature and the arguments are therefore unknown.
  524. This can happen with (builtin) functions implemented in C that have
  525. incomplete signature information.
  526. """
  527. # TODO: Check if other attributes should also be None when
  528. # .args is None.
  529. self.defaults: list[NodeNG] | None
  530. """The default values for arguments that can be passed positionally."""
  531. self.kwonlyargs: list[AssignName]
  532. """The keyword arguments that cannot be passed positionally."""
  533. self.posonlyargs: list[AssignName] = []
  534. """The arguments that can only be passed positionally."""
  535. self.kw_defaults: list[NodeNG | None] | None
  536. """
  537. The default values for keyword arguments that cannot be passed positionally.
  538. See .args for why this can be None.
  539. """
  540. self.annotations: list[NodeNG | None]
  541. """The type annotations of arguments that can be passed positionally."""
  542. self.posonlyargs_annotations: list[NodeNG | None] = []
  543. """The type annotations of arguments that can only be passed positionally."""
  544. self.kwonlyargs_annotations: list[NodeNG | None] = []
  545. """The type annotations of arguments that cannot be passed positionally."""
  546. self.type_comment_args: list[NodeNG | None] = []
  547. """The type annotation, passed by a type comment, of each argument.
  548. If an argument does not have a type comment,
  549. the value for that argument will be None.
  550. """
  551. self.type_comment_kwonlyargs: list[NodeNG | None] = []
  552. """The type annotation, passed by a type comment, of each keyword only argument.
  553. If an argument does not have a type comment,
  554. the value for that argument will be None.
  555. """
  556. self.type_comment_posonlyargs: list[NodeNG | None] = []
  557. """The type annotation, passed by a type comment, of each positional argument.
  558. If an argument does not have a type comment,
  559. the value for that argument will be None.
  560. """
  561. self.varargannotation: NodeNG | None = None # can be None
  562. """The type annotation for the variable length arguments."""
  563. self.kwargannotation: NodeNG | None = None # can be None
  564. """The type annotation for the variable length keyword arguments."""
  565. # pylint: disable=too-many-arguments
  566. def postinit(
  567. self,
  568. args: list[AssignName] | None,
  569. defaults: list[NodeNG] | None,
  570. kwonlyargs: list[AssignName],
  571. kw_defaults: list[NodeNG | None] | None,
  572. annotations: list[NodeNG | None],
  573. posonlyargs: list[AssignName] | None = None,
  574. kwonlyargs_annotations: list[NodeNG | None] | None = None,
  575. posonlyargs_annotations: list[NodeNG | None] | None = None,
  576. varargannotation: NodeNG | None = None,
  577. kwargannotation: NodeNG | None = None,
  578. type_comment_args: list[NodeNG | None] | None = None,
  579. type_comment_kwonlyargs: list[NodeNG | None] | None = None,
  580. type_comment_posonlyargs: list[NodeNG | None] | None = None,
  581. ) -> None:
  582. """Do some setup after initialisation.
  583. :param args: The names of the required arguments.
  584. :param defaults: The default values for arguments that can be passed
  585. positionally.
  586. :param kwonlyargs: The keyword arguments that cannot be passed
  587. positionally.
  588. :param posonlyargs: The arguments that can only be passed
  589. positionally.
  590. :param kw_defaults: The default values for keyword arguments that
  591. cannot be passed positionally.
  592. :param annotations: The type annotations of arguments that can be
  593. passed positionally.
  594. :param kwonlyargs_annotations: The type annotations of arguments that
  595. cannot be passed positionally. This should always be passed in
  596. Python 3.
  597. :param posonlyargs_annotations: The type annotations of arguments that
  598. can only be passed positionally. This should always be passed in
  599. Python 3.
  600. :param varargannotation: The type annotation for the variable length
  601. arguments.
  602. :param kwargannotation: The type annotation for the variable length
  603. keyword arguments.
  604. :param type_comment_args: The type annotation,
  605. passed by a type comment, of each argument.
  606. :param type_comment_args: The type annotation,
  607. passed by a type comment, of each keyword only argument.
  608. :param type_comment_args: The type annotation,
  609. passed by a type comment, of each positional argument.
  610. """
  611. self.args = args
  612. self.defaults = defaults
  613. self.kwonlyargs = kwonlyargs
  614. if posonlyargs is not None:
  615. self.posonlyargs = posonlyargs
  616. self.kw_defaults = kw_defaults
  617. self.annotations = annotations
  618. if kwonlyargs_annotations is not None:
  619. self.kwonlyargs_annotations = kwonlyargs_annotations
  620. if posonlyargs_annotations is not None:
  621. self.posonlyargs_annotations = posonlyargs_annotations
  622. self.varargannotation = varargannotation
  623. self.kwargannotation = kwargannotation
  624. if type_comment_args is not None:
  625. self.type_comment_args = type_comment_args
  626. if type_comment_kwonlyargs is not None:
  627. self.type_comment_kwonlyargs = type_comment_kwonlyargs
  628. if type_comment_posonlyargs is not None:
  629. self.type_comment_posonlyargs = type_comment_posonlyargs
  630. assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]
  631. """Returns the assigned statement (non inferred) according to the assignment type.
  632. See astroid/protocols.py for actual implementation.
  633. """
  634. def _infer_name(self, frame, name):
  635. if self.parent is frame:
  636. return name
  637. return None
  638. @cached_property
  639. def fromlineno(self):
  640. """The first line that this node appears on in the source code.
  641. :type: int or None
  642. """
  643. lineno = super().fromlineno
  644. return max(lineno, self.parent.fromlineno or 0)
  645. @cached_property
  646. def arguments(self):
  647. """Get all the arguments for this node, including positional only and positional and keyword"""
  648. return list(itertools.chain((self.posonlyargs or ()), self.args or ()))
  649. def format_args(self, *, skippable_names: set[str] | None = None) -> str:
  650. """Get the arguments formatted as string.
  651. :returns: The formatted arguments.
  652. :rtype: str
  653. """
  654. result = []
  655. positional_only_defaults = []
  656. positional_or_keyword_defaults = self.defaults
  657. if self.defaults:
  658. args = self.args or []
  659. positional_or_keyword_defaults = self.defaults[-len(args) :]
  660. positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]
  661. if self.posonlyargs:
  662. result.append(
  663. _format_args(
  664. self.posonlyargs,
  665. positional_only_defaults,
  666. self.posonlyargs_annotations,
  667. skippable_names=skippable_names,
  668. )
  669. )
  670. result.append("/")
  671. if self.args:
  672. result.append(
  673. _format_args(
  674. self.args,
  675. positional_or_keyword_defaults,
  676. getattr(self, "annotations", None),
  677. skippable_names=skippable_names,
  678. )
  679. )
  680. if self.vararg:
  681. result.append(f"*{self.vararg}")
  682. if self.kwonlyargs:
  683. if not self.vararg:
  684. result.append("*")
  685. result.append(
  686. _format_args(
  687. self.kwonlyargs,
  688. self.kw_defaults,
  689. self.kwonlyargs_annotations,
  690. skippable_names=skippable_names,
  691. )
  692. )
  693. if self.kwarg:
  694. result.append(f"**{self.kwarg}")
  695. return ", ".join(result)
  696. def _get_arguments_data(
  697. self,
  698. ) -> tuple[
  699. dict[str, tuple[str | None, str | None]],
  700. dict[str, tuple[str | None, str | None]],
  701. ]:
  702. """Get the arguments as dictionary with information about typing and defaults.
  703. The return tuple contains a dictionary for positional and keyword arguments with their typing
  704. and their default value, if any.
  705. The method follows a similar order as format_args but instead of formatting into a string it
  706. returns the data that is used to do so.
  707. """
  708. pos_only: dict[str, tuple[str | None, str | None]] = {}
  709. kw_only: dict[str, tuple[str | None, str | None]] = {}
  710. # Setup and match defaults with arguments
  711. positional_only_defaults = []
  712. positional_or_keyword_defaults = self.defaults
  713. if self.defaults:
  714. args = self.args or []
  715. positional_or_keyword_defaults = self.defaults[-len(args) :]
  716. positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]
  717. for index, posonly in enumerate(self.posonlyargs):
  718. annotation, default = self.posonlyargs_annotations[index], None
  719. if annotation is not None:
  720. annotation = annotation.as_string()
  721. if positional_only_defaults:
  722. default = positional_only_defaults[index].as_string()
  723. pos_only[posonly.name] = (annotation, default)
  724. for index, arg in enumerate(self.args):
  725. annotation, default = self.annotations[index], None
  726. if annotation is not None:
  727. annotation = annotation.as_string()
  728. if positional_or_keyword_defaults:
  729. defaults_offset = len(self.args) - len(positional_or_keyword_defaults)
  730. default_index = index - defaults_offset
  731. if (
  732. default_index > -1
  733. and positional_or_keyword_defaults[default_index] is not None
  734. ):
  735. default = positional_or_keyword_defaults[default_index].as_string()
  736. pos_only[arg.name] = (annotation, default)
  737. if self.vararg:
  738. annotation = self.varargannotation
  739. if annotation is not None:
  740. annotation = annotation.as_string()
  741. pos_only[self.vararg] = (annotation, None)
  742. for index, kwarg in enumerate(self.kwonlyargs):
  743. annotation = self.kwonlyargs_annotations[index]
  744. if annotation is not None:
  745. annotation = annotation.as_string()
  746. default = self.kw_defaults[index]
  747. if default is not None:
  748. default = default.as_string()
  749. kw_only[kwarg.name] = (annotation, default)
  750. if self.kwarg:
  751. annotation = self.kwargannotation
  752. if annotation is not None:
  753. annotation = annotation.as_string()
  754. kw_only[self.kwarg] = (annotation, None)
  755. return pos_only, kw_only
  756. def default_value(self, argname):
  757. """Get the default value for an argument.
  758. :param argname: The name of the argument to get the default value for.
  759. :type argname: str
  760. :raises NoDefault: If there is no default value defined for the
  761. given argument.
  762. """
  763. args = self.arguments
  764. index = _find_arg(argname, args)[0]
  765. if index is not None:
  766. idx = index - (len(args) - len(self.defaults))
  767. if idx >= 0:
  768. return self.defaults[idx]
  769. index = _find_arg(argname, self.kwonlyargs)[0]
  770. if index is not None and self.kw_defaults[index] is not None:
  771. return self.kw_defaults[index]
  772. raise NoDefault(func=self.parent, name=argname)
  773. def is_argument(self, name) -> bool:
  774. """Check if the given name is defined in the arguments.
  775. :param name: The name to check for.
  776. :type name: str
  777. :returns: Whether the given name is defined in the arguments,
  778. """
  779. if name == self.vararg:
  780. return True
  781. if name == self.kwarg:
  782. return True
  783. return (
  784. self.find_argname(name, rec=True)[1] is not None
  785. or self.kwonlyargs
  786. and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None
  787. )
  788. def find_argname(self, argname, rec=False):
  789. """Get the index and :class:`AssignName` node for given name.
  790. :param argname: The name of the argument to search for.
  791. :type argname: str
  792. :param rec: Whether or not to include arguments in unpacked tuples
  793. in the search.
  794. :type rec: bool
  795. :returns: The index and node for the argument.
  796. :rtype: tuple(str or None, AssignName or None)
  797. """
  798. if self.arguments:
  799. return _find_arg(argname, self.arguments, rec)
  800. return None, None
  801. def get_children(self):
  802. yield from self.posonlyargs or ()
  803. for elt in self.posonlyargs_annotations:
  804. if elt is not None:
  805. yield elt
  806. yield from self.args or ()
  807. if self.defaults is not None:
  808. yield from self.defaults
  809. yield from self.kwonlyargs
  810. for elt in self.kw_defaults or ():
  811. if elt is not None:
  812. yield elt
  813. for elt in self.annotations:
  814. if elt is not None:
  815. yield elt
  816. if self.varargannotation is not None:
  817. yield self.varargannotation
  818. if self.kwargannotation is not None:
  819. yield self.kwargannotation
  820. for elt in self.kwonlyargs_annotations:
  821. if elt is not None:
  822. yield elt
  823. def _find_arg(argname, args, rec=False):
  824. for i, arg in enumerate(args):
  825. if isinstance(arg, Tuple):
  826. if rec:
  827. found = _find_arg(argname, arg.elts)
  828. if found[0] is not None:
  829. return found
  830. elif arg.name == argname:
  831. return i, arg
  832. return None, None
  833. def _format_args(
  834. args, defaults=None, annotations=None, skippable_names: set[str] | None = None
  835. ) -> str:
  836. if skippable_names is None:
  837. skippable_names = set()
  838. values = []
  839. if args is None:
  840. return ""
  841. if annotations is None:
  842. annotations = []
  843. if defaults is not None:
  844. default_offset = len(args) - len(defaults)
  845. packed = itertools.zip_longest(args, annotations)
  846. for i, (arg, annotation) in enumerate(packed):
  847. if arg.name in skippable_names:
  848. continue
  849. if isinstance(arg, Tuple):
  850. values.append(f"({_format_args(arg.elts)})")
  851. else:
  852. argname = arg.name
  853. default_sep = "="
  854. if annotation is not None:
  855. argname += ": " + annotation.as_string()
  856. default_sep = " = "
  857. values.append(argname)
  858. if defaults is not None and i >= default_offset:
  859. if defaults[i - default_offset] is not None:
  860. values[-1] += default_sep + defaults[i - default_offset].as_string()
  861. return ", ".join(values)
  862. class AssignAttr(_base_nodes.ParentAssignNode):
  863. """Variation of :class:`ast.Assign` representing assignment to an attribute.
  864. >>> import astroid
  865. >>> node = astroid.extract_node('self.attribute = range(10)')
  866. >>> node
  867. <Assign l.1 at 0x7effe1d521d0>
  868. >>> list(node.get_children())
  869. [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]
  870. >>> list(node.get_children())[0].as_string()
  871. 'self.attribute'
  872. """
  873. _astroid_fields = ("expr",)
  874. _other_fields = ("attrname",)
  875. infer_lhs: ClassVar[InferLHS[AssignAttr]]
  876. @decorators.deprecate_default_argument_values(attrname="str")
  877. def __init__(
  878. self,
  879. attrname: str | None = None,
  880. lineno: int | None = None,
  881. col_offset: int | None = None,
  882. parent: NodeNG | None = None,
  883. *,
  884. end_lineno: int | None = None,
  885. end_col_offset: int | None = None,
  886. ) -> None:
  887. """
  888. :param attrname: The name of the attribute being assigned to.
  889. :param lineno: The line that this node appears on in the source code.
  890. :param col_offset: The column that this node appears on in the
  891. source code.
  892. :param parent: The parent node in the syntax tree.
  893. :param end_lineno: The last line this node appears on in the source code.
  894. :param end_col_offset: The end column this node appears on in the
  895. source code. Note: This is after the last symbol.
  896. """
  897. self.expr: NodeNG | None = None
  898. """What has the attribute that is being assigned to."""
  899. self.attrname: str | None = attrname
  900. """The name of the attribute being assigned to."""
  901. super().__init__(
  902. lineno=lineno,
  903. col_offset=col_offset,
  904. end_lineno=end_lineno,
  905. end_col_offset=end_col_offset,
  906. parent=parent,
  907. )
  908. def postinit(self, expr: NodeNG | None = None) -> None:
  909. """Do some setup after initialisation.
  910. :param expr: What has the attribute that is being assigned to.
  911. """
  912. self.expr = expr
  913. assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]
  914. """Returns the assigned statement (non inferred) according to the assignment type.
  915. See astroid/protocols.py for actual implementation.
  916. """
  917. def get_children(self):
  918. yield self.expr
  919. class Assert(_base_nodes.Statement):
  920. """Class representing an :class:`ast.Assert` node.
  921. An :class:`Assert` node represents an assert statement.
  922. >>> import astroid
  923. >>> node = astroid.extract_node('assert len(things) == 10, "Not enough things"')
  924. >>> node
  925. <Assert l.1 at 0x7effe1d527b8>
  926. """
  927. _astroid_fields = ("test", "fail")
  928. def __init__(
  929. self,
  930. lineno: int | None = None,
  931. col_offset: int | None = None,
  932. parent: NodeNG | None = None,
  933. *,
  934. end_lineno: int | None = None,
  935. end_col_offset: int | None = None,
  936. ) -> None:
  937. """
  938. :param lineno: The line that this node appears on in the source code.
  939. :param col_offset: The column that this node appears on in the
  940. source code.
  941. :param parent: The parent node in the syntax tree.
  942. :param end_lineno: The last line this node appears on in the source code.
  943. :param end_col_offset: The end column this node appears on in the
  944. source code. Note: This is after the last symbol.
  945. """
  946. self.test: NodeNG | None = None
  947. """The test that passes or fails the assertion."""
  948. self.fail: NodeNG | None = None # can be None
  949. """The message shown when the assertion fails."""
  950. super().__init__(
  951. lineno=lineno,
  952. col_offset=col_offset,
  953. end_lineno=end_lineno,
  954. end_col_offset=end_col_offset,
  955. parent=parent,
  956. )
  957. def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:
  958. """Do some setup after initialisation.
  959. :param test: The test that passes or fails the assertion.
  960. :param fail: The message shown when the assertion fails.
  961. """
  962. self.fail = fail
  963. self.test = test
  964. def get_children(self):
  965. yield self.test
  966. if self.fail is not None:
  967. yield self.fail
  968. class Assign(_base_nodes.AssignTypeNode, _base_nodes.Statement):
  969. """Class representing an :class:`ast.Assign` node.
  970. An :class:`Assign` is a statement where something is explicitly
  971. asssigned to.
  972. >>> import astroid
  973. >>> node = astroid.extract_node('variable = range(10)')
  974. >>> node
  975. <Assign l.1 at 0x7effe1db8550>
  976. """
  977. _astroid_fields = ("targets", "value")
  978. _other_other_fields = ("type_annotation",)
  979. def __init__(
  980. self,
  981. lineno: int | None = None,
  982. col_offset: int | None = None,
  983. parent: NodeNG | None = None,
  984. *,
  985. end_lineno: int | None = None,
  986. end_col_offset: int | None = None,
  987. ) -> None:
  988. """
  989. :param lineno: The line that this node appears on in the source code.
  990. :param col_offset: The column that this node appears on in the
  991. source code.
  992. :param parent: The parent node in the syntax tree.
  993. :param end_lineno: The last line this node appears on in the source code.
  994. :param end_col_offset: The end column this node appears on in the
  995. source code. Note: This is after the last symbol.
  996. """
  997. self.targets: list[NodeNG] = []
  998. """What is being assigned to."""
  999. self.value: NodeNG | None = None
  1000. """The value being assigned to the variables."""
  1001. self.type_annotation: NodeNG | None = None # can be None
  1002. """If present, this will contain the type annotation passed by a type comment"""
  1003. super().__init__(
  1004. lineno=lineno,
  1005. col_offset=col_offset,
  1006. end_lineno=end_lineno,
  1007. end_col_offset=end_col_offset,
  1008. parent=parent,
  1009. )
  1010. def postinit(
  1011. self,
  1012. targets: list[NodeNG] | None = None,
  1013. value: NodeNG | None = None,
  1014. type_annotation: NodeNG | None = None,
  1015. ) -> None:
  1016. """Do some setup after initialisation.
  1017. :param targets: What is being assigned to.
  1018. :param value: The value being assigned to the variables.
  1019. :param type_annotation:
  1020. """
  1021. if targets is not None:
  1022. self.targets = targets
  1023. self.value = value
  1024. self.type_annotation = type_annotation
  1025. assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]
  1026. """Returns the assigned statement (non inferred) according to the assignment type.
  1027. See astroid/protocols.py for actual implementation.
  1028. """
  1029. def get_children(self):
  1030. yield from self.targets
  1031. yield self.value
  1032. @decorators.cached
  1033. def _get_assign_nodes(self):
  1034. return [self] + list(self.value._get_assign_nodes())
  1035. def _get_yield_nodes_skip_lambdas(self):
  1036. yield from self.value._get_yield_nodes_skip_lambdas()
  1037. class AnnAssign(_base_nodes.AssignTypeNode, _base_nodes.Statement):
  1038. """Class representing an :class:`ast.AnnAssign` node.
  1039. An :class:`AnnAssign` is an assignment with a type annotation.
  1040. >>> import astroid
  1041. >>> node = astroid.extract_node('variable: List[int] = range(10)')
  1042. >>> node
  1043. <AnnAssign l.1 at 0x7effe1d4c630>
  1044. """
  1045. _astroid_fields = ("target", "annotation", "value")
  1046. _other_fields = ("simple",)
  1047. def __init__(
  1048. self,
  1049. lineno: int | None = None,
  1050. col_offset: int | None = None,
  1051. parent: NodeNG | None = None,
  1052. *,
  1053. end_lineno: int | None = None,
  1054. end_col_offset: int | None = None,
  1055. ) -> None:
  1056. """
  1057. :param lineno: The line that this node appears on in the source code.
  1058. :param col_offset: The column that this node appears on in the
  1059. source code.
  1060. :param parent: The parent node in the syntax tree.
  1061. :param end_lineno: The last line this node appears on in the source code.
  1062. :param end_col_offset: The end column this node appears on in the
  1063. source code. Note: This is after the last symbol.
  1064. """
  1065. self.target: NodeNG | None = None
  1066. """What is being assigned to."""
  1067. self.annotation: NodeNG | None = None
  1068. """The type annotation of what is being assigned to."""
  1069. self.value: NodeNG | None = None # can be None
  1070. """The value being assigned to the variables."""
  1071. self.simple: int | None = None
  1072. """Whether :attr:`target` is a pure name or a complex statement."""
  1073. super().__init__(
  1074. lineno=lineno,
  1075. col_offset=col_offset,
  1076. end_lineno=end_lineno,
  1077. end_col_offset=end_col_offset,
  1078. parent=parent,
  1079. )
  1080. def postinit(
  1081. self,
  1082. target: NodeNG,
  1083. annotation: NodeNG,
  1084. simple: int,
  1085. value: NodeNG | None = None,
  1086. ) -> None:
  1087. """Do some setup after initialisation.
  1088. :param target: What is being assigned to.
  1089. :param annotation: The type annotation of what is being assigned to.
  1090. :param simple: Whether :attr:`target` is a pure name
  1091. or a complex statement.
  1092. :param value: The value being assigned to the variables.
  1093. """
  1094. self.target = target
  1095. self.annotation = annotation
  1096. self.value = value
  1097. self.simple = simple
  1098. assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]
  1099. """Returns the assigned statement (non inferred) according to the assignment type.
  1100. See astroid/protocols.py for actual implementation.
  1101. """
  1102. def get_children(self):
  1103. yield self.target
  1104. yield self.annotation
  1105. if self.value is not None:
  1106. yield self.value
  1107. class AugAssign(_base_nodes.AssignTypeNode, _base_nodes.Statement):
  1108. """Class representing an :class:`ast.AugAssign` node.
  1109. An :class:`AugAssign` is an assignment paired with an operator.
  1110. >>> import astroid
  1111. >>> node = astroid.extract_node('variable += 1')
  1112. >>> node
  1113. <AugAssign l.1 at 0x7effe1db4d68>
  1114. """
  1115. _astroid_fields = ("target", "value")
  1116. _other_fields = ("op",)
  1117. @decorators.deprecate_default_argument_values(op="str")
  1118. def __init__(
  1119. self,
  1120. op: str | None = None,
  1121. lineno: int | None = None,
  1122. col_offset: int | None = None,
  1123. parent: NodeNG | None = None,
  1124. *,
  1125. end_lineno: int | None = None,
  1126. end_col_offset: int | None = None,
  1127. ) -> None:
  1128. """
  1129. :param op: The operator that is being combined with the assignment.
  1130. This includes the equals sign.
  1131. :param lineno: The line that this node appears on in the source code.
  1132. :param col_offset: The column that this node appears on in the
  1133. source code.
  1134. :param parent: The parent node in the syntax tree.
  1135. :param end_lineno: The last line this node appears on in the source code.
  1136. :param end_col_offset: The end column this node appears on in the
  1137. source code. Note: This is after the last symbol.
  1138. """
  1139. self.target: NodeNG | None = None
  1140. """What is being assigned to."""
  1141. self.op: str | None = op
  1142. """The operator that is being combined with the assignment.
  1143. This includes the equals sign.
  1144. """
  1145. self.value: NodeNG | None = None
  1146. """The value being assigned to the variable."""
  1147. super().__init__(
  1148. lineno=lineno,
  1149. col_offset=col_offset,
  1150. end_lineno=end_lineno,
  1151. end_col_offset=end_col_offset,
  1152. parent=parent,
  1153. )
  1154. def postinit(
  1155. self, target: NodeNG | None = None, value: NodeNG | None = None
  1156. ) -> None:
  1157. """Do some setup after initialisation.
  1158. :param target: What is being assigned to.
  1159. :param value: The value being assigned to the variable.
  1160. """
  1161. self.target = target
  1162. self.value = value
  1163. assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]
  1164. """Returns the assigned statement (non inferred) according to the assignment type.
  1165. See astroid/protocols.py for actual implementation.
  1166. """
  1167. # This is set by inference.py
  1168. _infer_augassign: ClassVar[
  1169. InferBinaryOperation[AugAssign, util.BadBinaryOperationMessage]
  1170. ]
  1171. def type_errors(self, context: InferenceContext | None = None):
  1172. """Get a list of type errors which can occur during inference.
  1173. Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,
  1174. which holds the original exception.
  1175. :returns: The list of possible type errors.
  1176. :rtype: list(BadBinaryOperationMessage)
  1177. """
  1178. try:
  1179. results = self._infer_augassign(context=context)
  1180. return [
  1181. result
  1182. for result in results
  1183. if isinstance(result, util.BadBinaryOperationMessage)
  1184. ]
  1185. except InferenceError:
  1186. return []
  1187. def get_children(self):
  1188. yield self.target
  1189. yield self.value
  1190. def _get_yield_nodes_skip_lambdas(self):
  1191. """An AugAssign node can contain a Yield node in the value"""
  1192. yield from self.value._get_yield_nodes_skip_lambdas()
  1193. yield from super()._get_yield_nodes_skip_lambdas()
  1194. class BinOp(NodeNG):
  1195. """Class representing an :class:`ast.BinOp` node.
  1196. A :class:`BinOp` node is an application of a binary operator.
  1197. >>> import astroid
  1198. >>> node = astroid.extract_node('a + b')
  1199. >>> node
  1200. <BinOp l.1 at 0x7f23b2e8cfd0>
  1201. """
  1202. _astroid_fields = ("left", "right")
  1203. _other_fields = ("op",)
  1204. @decorators.deprecate_default_argument_values(op="str")
  1205. def __init__(
  1206. self,
  1207. op: str | None = None,
  1208. lineno: int | None = None,
  1209. col_offset: int | None = None,
  1210. parent: NodeNG | None = None,
  1211. *,
  1212. end_lineno: int | None = None,
  1213. end_col_offset: int | None = None,
  1214. ) -> None:
  1215. """
  1216. :param op: The operator.
  1217. :param lineno: The line that this node appears on in the source code.
  1218. :param col_offset: The column that this node appears on in the
  1219. source code.
  1220. :param parent: The parent node in the syntax tree.
  1221. :param end_lineno: The last line this node appears on in the source code.
  1222. :param end_col_offset: The end column this node appears on in the
  1223. source code. Note: This is after the last symbol.
  1224. """
  1225. self.left: NodeNG | None = None
  1226. """What is being applied to the operator on the left side."""
  1227. self.op: str | None = op
  1228. """The operator."""
  1229. self.right: NodeNG | None = None
  1230. """What is being applied to the operator on the right side."""
  1231. super().__init__(
  1232. lineno=lineno,
  1233. col_offset=col_offset,
  1234. end_lineno=end_lineno,
  1235. end_col_offset=end_col_offset,
  1236. parent=parent,
  1237. )
  1238. def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:
  1239. """Do some setup after initialisation.
  1240. :param left: What is being applied to the operator on the left side.
  1241. :param right: What is being applied to the operator on the right side.
  1242. """
  1243. self.left = left
  1244. self.right = right
  1245. # This is set by inference.py
  1246. _infer_binop: ClassVar[InferBinaryOperation[BinOp, util.BadBinaryOperationMessage]]
  1247. def type_errors(self, context: InferenceContext | None = None):
  1248. """Get a list of type errors which can occur during inference.
  1249. Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
  1250. which holds the original exception.
  1251. :returns: The list of possible type errors.
  1252. :rtype: list(BadBinaryOperationMessage)
  1253. """
  1254. try:
  1255. results = self._infer_binop(context=context)
  1256. return [
  1257. result
  1258. for result in results
  1259. if isinstance(result, util.BadBinaryOperationMessage)
  1260. ]
  1261. except InferenceError:
  1262. return []
  1263. def get_children(self):
  1264. yield self.left
  1265. yield self.right
  1266. def op_precedence(self):
  1267. return OP_PRECEDENCE[self.op]
  1268. def op_left_associative(self) -> bool:
  1269. # 2**3**4 == 2**(3**4)
  1270. return self.op != "**"
  1271. class BoolOp(NodeNG):
  1272. """Class representing an :class:`ast.BoolOp` node.
  1273. A :class:`BoolOp` is an application of a boolean operator.
  1274. >>> import astroid
  1275. >>> node = astroid.extract_node('a and b')
  1276. >>> node
  1277. <BinOp l.1 at 0x7f23b2e71c50>
  1278. """
  1279. _astroid_fields = ("values",)
  1280. _other_fields = ("op",)
  1281. @decorators.deprecate_default_argument_values(op="str")
  1282. def __init__(
  1283. self,
  1284. op: str | None = None,
  1285. lineno: int | None = None,
  1286. col_offset: int | None = None,
  1287. parent: NodeNG | None = None,
  1288. *,
  1289. end_lineno: int | None = None,
  1290. end_col_offset: int | None = None,
  1291. ) -> None:
  1292. """
  1293. :param op: The operator.
  1294. :param lineno: The line that this node appears on in the source code.
  1295. :param col_offset: The column that this node appears on in the
  1296. source code.
  1297. :param parent: The parent node in the syntax tree.
  1298. :param end_lineno: The last line this node appears on in the source code.
  1299. :param end_col_offset: The end column this node appears on in the
  1300. source code. Note: This is after the last symbol.
  1301. """
  1302. self.op: str | None = op
  1303. """The operator."""
  1304. self.values: list[NodeNG] = []
  1305. """The values being applied to the operator."""
  1306. super().__init__(
  1307. lineno=lineno,
  1308. col_offset=col_offset,
  1309. end_lineno=end_lineno,
  1310. end_col_offset=end_col_offset,
  1311. parent=parent,
  1312. )
  1313. def postinit(self, values: list[NodeNG] | None = None) -> None:
  1314. """Do some setup after initialisation.
  1315. :param values: The values being applied to the operator.
  1316. """
  1317. if values is not None:
  1318. self.values = values
  1319. def get_children(self):
  1320. yield from self.values
  1321. def op_precedence(self):
  1322. return OP_PRECEDENCE[self.op]
  1323. class Break(_base_nodes.NoChildrenNode, _base_nodes.Statement):
  1324. """Class representing an :class:`ast.Break` node.
  1325. >>> import astroid
  1326. >>> node = astroid.extract_node('break')
  1327. >>> node
  1328. <Break l.1 at 0x7f23b2e9e5c0>
  1329. """
  1330. class Call(NodeNG):
  1331. """Class representing an :class:`ast.Call` node.
  1332. A :class:`Call` node is a call to a function, method, etc.
  1333. >>> import astroid
  1334. >>> node = astroid.extract_node('function()')
  1335. >>> node
  1336. <Call l.1 at 0x7f23b2e71eb8>
  1337. """
  1338. _astroid_fields = ("func", "args", "keywords")
  1339. def __init__(
  1340. self,
  1341. lineno: int | None = None,
  1342. col_offset: int | None = None,
  1343. parent: NodeNG | None = None,
  1344. *,
  1345. end_lineno: int | None = None,
  1346. end_col_offset: int | None = None,
  1347. ) -> None:
  1348. """
  1349. :param lineno: The line that this node appears on in the source code.
  1350. :param col_offset: The column that this node appears on in the
  1351. source code.
  1352. :param parent: The parent node in the syntax tree.
  1353. :param end_lineno: The last line this node appears on in the source code.
  1354. :param end_col_offset: The end column this node appears on in the
  1355. source code. Note: This is after the last symbol.
  1356. """
  1357. self.func: NodeNG | None = None
  1358. """What is being called."""
  1359. self.args: list[NodeNG] = []
  1360. """The positional arguments being given to the call."""
  1361. self.keywords: list[Keyword] = []
  1362. """The keyword arguments being given to the call."""
  1363. super().__init__(
  1364. lineno=lineno,
  1365. col_offset=col_offset,
  1366. end_lineno=end_lineno,
  1367. end_col_offset=end_col_offset,
  1368. parent=parent,
  1369. )
  1370. def postinit(
  1371. self,
  1372. func: NodeNG | None = None,
  1373. args: list[NodeNG] | None = None,
  1374. keywords: list[Keyword] | None = None,
  1375. ) -> None:
  1376. """Do some setup after initialisation.
  1377. :param func: What is being called.
  1378. :param args: The positional arguments being given to the call.
  1379. :param keywords: The keyword arguments being given to the call.
  1380. """
  1381. self.func = func
  1382. if args is not None:
  1383. self.args = args
  1384. if keywords is not None:
  1385. self.keywords = keywords
  1386. @property
  1387. def starargs(self) -> list[Starred]:
  1388. """The positional arguments that unpack something."""
  1389. return [arg for arg in self.args if isinstance(arg, Starred)]
  1390. @property
  1391. def kwargs(self) -> list[Keyword]:
  1392. """The keyword arguments that unpack something."""
  1393. return [keyword for keyword in self.keywords if keyword.arg is None]
  1394. def get_children(self):
  1395. yield self.func
  1396. yield from self.args
  1397. yield from self.keywords
  1398. class Compare(NodeNG):
  1399. """Class representing an :class:`ast.Compare` node.
  1400. A :class:`Compare` node indicates a comparison.
  1401. >>> import astroid
  1402. >>> node = astroid.extract_node('a <= b <= c')
  1403. >>> node
  1404. <Compare l.1 at 0x7f23b2e9e6d8>
  1405. >>> node.ops
  1406. [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]
  1407. """
  1408. _astroid_fields = ("left", "ops")
  1409. def __init__(
  1410. self,
  1411. lineno: int | None = None,
  1412. col_offset: int | None = None,
  1413. parent: NodeNG | None = None,
  1414. *,
  1415. end_lineno: int | None = None,
  1416. end_col_offset: int | None = None,
  1417. ) -> None:
  1418. """
  1419. :param lineno: The line that this node appears on in the source code.
  1420. :param col_offset: The column that this node appears on in the
  1421. source code.
  1422. :param parent: The parent node in the syntax tree.
  1423. :param end_lineno: The last line this node appears on in the source code.
  1424. :param end_col_offset: The end column this node appears on in the
  1425. source code. Note: This is after the last symbol.
  1426. """
  1427. self.left: NodeNG | None = None
  1428. """The value at the left being applied to a comparison operator."""
  1429. self.ops: list[tuple[str, NodeNG]] = []
  1430. """The remainder of the operators and their relevant right hand value."""
  1431. super().__init__(
  1432. lineno=lineno,
  1433. col_offset=col_offset,
  1434. end_lineno=end_lineno,
  1435. end_col_offset=end_col_offset,
  1436. parent=parent,
  1437. )
  1438. def postinit(
  1439. self,
  1440. left: NodeNG | None = None,
  1441. ops: list[tuple[str, NodeNG]] | None = None,
  1442. ) -> None:
  1443. """Do some setup after initialisation.
  1444. :param left: The value at the left being applied to a comparison
  1445. operator.
  1446. :param ops: The remainder of the operators
  1447. and their relevant right hand value.
  1448. """
  1449. self.left = left
  1450. if ops is not None:
  1451. self.ops = ops
  1452. def get_children(self):
  1453. """Get the child nodes below this node.
  1454. Overridden to handle the tuple fields and skip returning the operator
  1455. strings.
  1456. :returns: The children.
  1457. :rtype: iterable(NodeNG)
  1458. """
  1459. yield self.left
  1460. for _, comparator in self.ops:
  1461. yield comparator # we don't want the 'op'
  1462. def last_child(self):
  1463. """An optimized version of list(get_children())[-1]
  1464. :returns: The last child.
  1465. :rtype: NodeNG
  1466. """
  1467. # XXX maybe if self.ops:
  1468. return self.ops[-1][1]
  1469. # return self.left
  1470. class Comprehension(NodeNG):
  1471. """Class representing an :class:`ast.comprehension` node.
  1472. A :class:`Comprehension` indicates the loop inside any type of
  1473. comprehension including generator expressions.
  1474. >>> import astroid
  1475. >>> node = astroid.extract_node('[x for x in some_values]')
  1476. >>> list(node.get_children())
  1477. [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]
  1478. >>> list(node.get_children())[1].as_string()
  1479. 'for x in some_values'
  1480. """
  1481. _astroid_fields = ("target", "iter", "ifs")
  1482. _other_fields = ("is_async",)
  1483. optional_assign = True
  1484. """Whether this node optionally assigns a variable."""
  1485. lineno: None
  1486. col_offset: None
  1487. end_lineno: None
  1488. end_col_offset: None
  1489. def __init__(self, parent: NodeNG | None = None) -> None:
  1490. """
  1491. :param parent: The parent node in the syntax tree.
  1492. """
  1493. self.target: NodeNG | None = None
  1494. """What is assigned to by the comprehension."""
  1495. self.iter: NodeNG | None = None
  1496. """What is iterated over by the comprehension."""
  1497. self.ifs: list[NodeNG] = []
  1498. """The contents of any if statements that filter the comprehension."""
  1499. self.is_async: bool | None = None
  1500. """Whether this is an asynchronous comprehension or not."""
  1501. super().__init__(parent=parent)
  1502. # pylint: disable=redefined-builtin; same name as builtin ast module.
  1503. def postinit(
  1504. self,
  1505. target: NodeNG | None = None,
  1506. iter: NodeNG | None = None,
  1507. ifs: list[NodeNG] | None = None,
  1508. is_async: bool | None = None,
  1509. ) -> None:
  1510. """Do some setup after initialisation.
  1511. :param target: What is assigned to by the comprehension.
  1512. :param iter: What is iterated over by the comprehension.
  1513. :param ifs: The contents of any if statements that filter
  1514. the comprehension.
  1515. :param is_async: Whether this is an asynchronous comprehension or not.
  1516. """
  1517. self.target = target
  1518. self.iter = iter
  1519. if ifs is not None:
  1520. self.ifs = ifs
  1521. self.is_async = is_async
  1522. assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]
  1523. """Returns the assigned statement (non inferred) according to the assignment type.
  1524. See astroid/protocols.py for actual implementation.
  1525. """
  1526. def assign_type(self):
  1527. """The type of assignment that this node performs.
  1528. :returns: The assignment type.
  1529. :rtype: NodeNG
  1530. """
  1531. return self
  1532. def _get_filtered_stmts(
  1533. self, lookup_node, node, stmts, mystmt: _base_nodes.Statement | None
  1534. ):
  1535. """method used in filter_stmts"""
  1536. if self is mystmt:
  1537. if isinstance(lookup_node, (Const, Name)):
  1538. return [lookup_node], True
  1539. elif self.statement(future=True) is mystmt:
  1540. # original node's statement is the assignment, only keeps
  1541. # current node (gen exp, list comp)
  1542. return [node], True
  1543. return stmts, False
  1544. def get_children(self):
  1545. yield self.target
  1546. yield self.iter
  1547. yield from self.ifs
  1548. class Const(_base_nodes.NoChildrenNode, Instance):
  1549. """Class representing any constant including num, str, bool, None, bytes.
  1550. >>> import astroid
  1551. >>> node = astroid.extract_node('(5, "This is a string.", True, None, b"bytes")')
  1552. >>> node
  1553. <Tuple.tuple l.1 at 0x7f23b2e358d0>
  1554. >>> list(node.get_children())
  1555. [<Const.int l.1 at 0x7f23b2e35940>,
  1556. <Const.str l.1 at 0x7f23b2e35978>,
  1557. <Const.bool l.1 at 0x7f23b2e359b0>,
  1558. <Const.NoneType l.1 at 0x7f23b2e359e8>,
  1559. <Const.bytes l.1 at 0x7f23b2e35a20>]
  1560. """
  1561. _other_fields = ("value", "kind")
  1562. def __init__(
  1563. self,
  1564. value: Any,
  1565. lineno: int | None = None,
  1566. col_offset: int | None = None,
  1567. parent: NodeNG | None = None,
  1568. kind: str | None = None,
  1569. *,
  1570. end_lineno: int | None = None,
  1571. end_col_offset: int | None = None,
  1572. ) -> None:
  1573. """
  1574. :param value: The value that the constant represents.
  1575. :param lineno: The line that this node appears on in the source code.
  1576. :param col_offset: The column that this node appears on in the
  1577. source code.
  1578. :param parent: The parent node in the syntax tree.
  1579. :param kind: The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.
  1580. :param end_lineno: The last line this node appears on in the source code.
  1581. :param end_col_offset: The end column this node appears on in the
  1582. source code. Note: This is after the last symbol.
  1583. """
  1584. self.value: Any = value
  1585. """The value that the constant represents."""
  1586. self.kind: str | None = kind # can be None
  1587. """"The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only."""
  1588. super().__init__(
  1589. lineno=lineno,
  1590. col_offset=col_offset,
  1591. end_lineno=end_lineno,
  1592. end_col_offset=end_col_offset,
  1593. parent=parent,
  1594. )
  1595. Instance.__init__(self, None)
  1596. infer_unary_op: ClassVar[InferUnaryOp[Const]]
  1597. infer_binary_op: ClassVar[InferBinaryOp[Const]]
  1598. def __getattr__(self, name):
  1599. # This is needed because of Proxy's __getattr__ method.
  1600. # Calling object.__new__ on this class without calling
  1601. # __init__ would result in an infinite loop otherwise
  1602. # since __getattr__ is called when an attribute doesn't
  1603. # exist and self._proxied indirectly calls self.value
  1604. # and Proxy __getattr__ calls self.value
  1605. if name == "value":
  1606. raise AttributeError
  1607. return super().__getattr__(name)
  1608. def getitem(self, index, context: InferenceContext | None = None):
  1609. """Get an item from this node if subscriptable.
  1610. :param index: The node to use as a subscript index.
  1611. :type index: Const or Slice
  1612. :raises AstroidTypeError: When the given index cannot be used as a
  1613. subscript index, or if this node is not subscriptable.
  1614. """
  1615. if isinstance(index, Const):
  1616. index_value = index.value
  1617. elif isinstance(index, Slice):
  1618. index_value = _infer_slice(index, context=context)
  1619. else:
  1620. raise AstroidTypeError(
  1621. f"Could not use type {type(index)} as subscript index"
  1622. )
  1623. try:
  1624. if isinstance(self.value, (str, bytes)):
  1625. return Const(self.value[index_value])
  1626. except ValueError as exc:
  1627. raise AstroidValueError(
  1628. f"Could not index {self.value!r} with {index_value!r}"
  1629. ) from exc
  1630. except IndexError as exc:
  1631. raise AstroidIndexError(
  1632. message="Index {index!r} out of range",
  1633. node=self,
  1634. index=index,
  1635. context=context,
  1636. ) from exc
  1637. except TypeError as exc:
  1638. raise AstroidTypeError(
  1639. message="Type error {error!r}", node=self, index=index, context=context
  1640. ) from exc
  1641. raise AstroidTypeError(f"{self!r} (value={self.value})")
  1642. def has_dynamic_getattr(self) -> bool:
  1643. """Check if the node has a custom __getattr__ or __getattribute__.
  1644. :returns: Whether the class has a custom __getattr__ or __getattribute__.
  1645. For a :class:`Const` this is always ``False``.
  1646. """
  1647. return False
  1648. def itered(self):
  1649. """An iterator over the elements this node contains.
  1650. :returns: The contents of this node.
  1651. :rtype: iterable(Const)
  1652. :raises TypeError: If this node does not represent something that is iterable.
  1653. """
  1654. if isinstance(self.value, str):
  1655. return [const_factory(elem) for elem in self.value]
  1656. raise TypeError(f"Cannot iterate over type {type(self.value)!r}")
  1657. def pytype(self) -> str:
  1658. """Get the name of the type that this node represents.
  1659. :returns: The name of the type.
  1660. """
  1661. return self._proxied.qname()
  1662. def bool_value(self, context: InferenceContext | None = None):
  1663. """Determine the boolean value of this node.
  1664. :returns: The boolean value of this node.
  1665. :rtype: bool
  1666. """
  1667. return bool(self.value)
  1668. class Continue(_base_nodes.NoChildrenNode, _base_nodes.Statement):
  1669. """Class representing an :class:`ast.Continue` node.
  1670. >>> import astroid
  1671. >>> node = astroid.extract_node('continue')
  1672. >>> node
  1673. <Continue l.1 at 0x7f23b2e35588>
  1674. """
  1675. class Decorators(NodeNG):
  1676. """A node representing a list of decorators.
  1677. A :class:`Decorators` is the decorators that are applied to
  1678. a method or function.
  1679. >>> import astroid
  1680. >>> node = astroid.extract_node('''
  1681. @property
  1682. def my_property(self):
  1683. return 3
  1684. ''')
  1685. >>> node
  1686. <FunctionDef.my_property l.2 at 0x7f23b2e35d30>
  1687. >>> list(node.get_children())[0]
  1688. <Decorators l.1 at 0x7f23b2e35d68>
  1689. """
  1690. _astroid_fields = ("nodes",)
  1691. def __init__(
  1692. self,
  1693. lineno: int | None = None,
  1694. col_offset: int | None = None,
  1695. parent: NodeNG | None = None,
  1696. *,
  1697. end_lineno: int | None = None,
  1698. end_col_offset: int | None = None,
  1699. ) -> None:
  1700. """
  1701. :param lineno: The line that this node appears on in the source code.
  1702. :param col_offset: The column that this node appears on in the
  1703. source code.
  1704. :param parent: The parent node in the syntax tree.
  1705. :param end_lineno: The last line this node appears on in the source code.
  1706. :param end_col_offset: The end column this node appears on in the
  1707. source code. Note: This is after the last symbol.
  1708. """
  1709. self.nodes: list[NodeNG]
  1710. """The decorators that this node contains.
  1711. :type: list(Name or Call) or None
  1712. """
  1713. super().__init__(
  1714. lineno=lineno,
  1715. col_offset=col_offset,
  1716. end_lineno=end_lineno,
  1717. end_col_offset=end_col_offset,
  1718. parent=parent,
  1719. )
  1720. def postinit(self, nodes: list[NodeNG]) -> None:
  1721. """Do some setup after initialisation.
  1722. :param nodes: The decorators that this node contains.
  1723. :type nodes: list(Name or Call)
  1724. """
  1725. self.nodes = nodes
  1726. def scope(self) -> LocalsDictNodeNG:
  1727. """The first parent node defining a new scope.
  1728. These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  1729. :returns: The first parent scope node.
  1730. """
  1731. # skip the function node to go directly to the upper level scope
  1732. if not self.parent:
  1733. raise ParentMissingError(target=self)
  1734. if not self.parent.parent:
  1735. raise ParentMissingError(target=self.parent)
  1736. return self.parent.parent.scope()
  1737. def get_children(self):
  1738. yield from self.nodes
  1739. class DelAttr(_base_nodes.ParentAssignNode):
  1740. """Variation of :class:`ast.Delete` representing deletion of an attribute.
  1741. >>> import astroid
  1742. >>> node = astroid.extract_node('del self.attr')
  1743. >>> node
  1744. <Delete l.1 at 0x7f23b2e35f60>
  1745. >>> list(node.get_children())[0]
  1746. <DelAttr.attr l.1 at 0x7f23b2e411d0>
  1747. """
  1748. _astroid_fields = ("expr",)
  1749. _other_fields = ("attrname",)
  1750. @decorators.deprecate_default_argument_values(attrname="str")
  1751. def __init__(
  1752. self,
  1753. attrname: str | None = None,
  1754. lineno: int | None = None,
  1755. col_offset: int | None = None,
  1756. parent: NodeNG | None = None,
  1757. *,
  1758. end_lineno: int | None = None,
  1759. end_col_offset: int | None = None,
  1760. ) -> None:
  1761. """
  1762. :param attrname: The name of the attribute that is being deleted.
  1763. :param lineno: The line that this node appears on in the source code.
  1764. :param col_offset: The column that this node appears on in the
  1765. source code.
  1766. :param parent: The parent node in the syntax tree.
  1767. :param end_lineno: The last line this node appears on in the source code.
  1768. :param end_col_offset: The end column this node appears on in the
  1769. source code. Note: This is after the last symbol.
  1770. """
  1771. self.expr: NodeNG | None = None
  1772. """The name that this node represents.
  1773. :type: Name or None
  1774. """
  1775. self.attrname: str | None = attrname
  1776. """The name of the attribute that is being deleted."""
  1777. super().__init__(
  1778. lineno=lineno,
  1779. col_offset=col_offset,
  1780. end_lineno=end_lineno,
  1781. end_col_offset=end_col_offset,
  1782. parent=parent,
  1783. )
  1784. def postinit(self, expr: NodeNG | None = None) -> None:
  1785. """Do some setup after initialisation.
  1786. :param expr: The name that this node represents.
  1787. :type expr: Name or None
  1788. """
  1789. self.expr = expr
  1790. def get_children(self):
  1791. yield self.expr
  1792. class Delete(_base_nodes.AssignTypeNode, _base_nodes.Statement):
  1793. """Class representing an :class:`ast.Delete` node.
  1794. A :class:`Delete` is a ``del`` statement this is deleting something.
  1795. >>> import astroid
  1796. >>> node = astroid.extract_node('del self.attr')
  1797. >>> node
  1798. <Delete l.1 at 0x7f23b2e35f60>
  1799. """
  1800. _astroid_fields = ("targets",)
  1801. def __init__(
  1802. self,
  1803. lineno: int | None = None,
  1804. col_offset: int | None = None,
  1805. parent: NodeNG | None = None,
  1806. *,
  1807. end_lineno: int | None = None,
  1808. end_col_offset: int | None = None,
  1809. ) -> None:
  1810. """
  1811. :param lineno: The line that this node appears on in the source code.
  1812. :param col_offset: The column that this node appears on in the
  1813. source code.
  1814. :param parent: The parent node in the syntax tree.
  1815. :param end_lineno: The last line this node appears on in the source code.
  1816. :param end_col_offset: The end column this node appears on in the
  1817. source code. Note: This is after the last symbol.
  1818. """
  1819. self.targets: list[NodeNG] = []
  1820. """What is being deleted."""
  1821. super().__init__(
  1822. lineno=lineno,
  1823. col_offset=col_offset,
  1824. end_lineno=end_lineno,
  1825. end_col_offset=end_col_offset,
  1826. parent=parent,
  1827. )
  1828. def postinit(self, targets: list[NodeNG] | None = None) -> None:
  1829. """Do some setup after initialisation.
  1830. :param targets: What is being deleted.
  1831. """
  1832. if targets is not None:
  1833. self.targets = targets
  1834. def get_children(self):
  1835. yield from self.targets
  1836. class Dict(NodeNG, Instance):
  1837. """Class representing an :class:`ast.Dict` node.
  1838. A :class:`Dict` is a dictionary that is created with ``{}`` syntax.
  1839. >>> import astroid
  1840. >>> node = astroid.extract_node('{1: "1"}')
  1841. >>> node
  1842. <Dict.dict l.1 at 0x7f23b2e35cc0>
  1843. """
  1844. _astroid_fields = ("items",)
  1845. def __init__(
  1846. self,
  1847. lineno: int | None = None,
  1848. col_offset: int | None = None,
  1849. parent: NodeNG | None = None,
  1850. *,
  1851. end_lineno: int | None = None,
  1852. end_col_offset: int | None = None,
  1853. ) -> None:
  1854. """
  1855. :param lineno: The line that this node appears on in the source code.
  1856. :param col_offset: The column that this node appears on in the
  1857. source code.
  1858. :param parent: The parent node in the syntax tree.
  1859. :param end_lineno: The last line this node appears on in the source code.
  1860. :param end_col_offset: The end column this node appears on in the
  1861. source code. Note: This is after the last symbol.
  1862. """
  1863. self.items: list[
  1864. tuple[SuccessfulInferenceResult, SuccessfulInferenceResult]
  1865. ] = []
  1866. """The key-value pairs contained in the dictionary."""
  1867. super().__init__(
  1868. lineno=lineno,
  1869. col_offset=col_offset,
  1870. end_lineno=end_lineno,
  1871. end_col_offset=end_col_offset,
  1872. parent=parent,
  1873. )
  1874. def postinit(
  1875. self, items: list[tuple[SuccessfulInferenceResult, SuccessfulInferenceResult]]
  1876. ) -> None:
  1877. """Do some setup after initialisation.
  1878. :param items: The key-value pairs contained in the dictionary.
  1879. """
  1880. self.items = items
  1881. infer_unary_op: ClassVar[InferUnaryOp[Dict]]
  1882. @classmethod
  1883. def from_elements(cls, items=None):
  1884. """Create a :class:`Dict` of constants from a live dictionary.
  1885. :param items: The items to store in the node.
  1886. :type items: dict
  1887. :returns: The created dictionary node.
  1888. :rtype: Dict
  1889. """
  1890. node = cls()
  1891. if items is None:
  1892. node.items = []
  1893. else:
  1894. node.items = [
  1895. (const_factory(k), const_factory(v) if _is_const(v) else v)
  1896. for k, v in items.items()
  1897. # The keys need to be constants
  1898. if _is_const(k)
  1899. ]
  1900. return node
  1901. def pytype(self) -> Literal["builtins.dict"]:
  1902. """Get the name of the type that this node represents.
  1903. :returns: The name of the type.
  1904. """
  1905. return "builtins.dict"
  1906. def get_children(self):
  1907. """Get the key and value nodes below this node.
  1908. Children are returned in the order that they are defined in the source
  1909. code, key first then the value.
  1910. :returns: The children.
  1911. :rtype: iterable(NodeNG)
  1912. """
  1913. for key, value in self.items:
  1914. yield key
  1915. yield value
  1916. def last_child(self):
  1917. """An optimized version of list(get_children())[-1]
  1918. :returns: The last child, or None if no children exist.
  1919. :rtype: NodeNG or None
  1920. """
  1921. if self.items:
  1922. return self.items[-1][1]
  1923. return None
  1924. def itered(self):
  1925. """An iterator over the keys this node contains.
  1926. :returns: The keys of this node.
  1927. :rtype: iterable(NodeNG)
  1928. """
  1929. return [key for (key, _) in self.items]
  1930. def getitem(
  1931. self, index: Const | Slice, context: InferenceContext | None = None
  1932. ) -> NodeNG:
  1933. """Get an item from this node.
  1934. :param index: The node to use as a subscript index.
  1935. :raises AstroidTypeError: When the given index cannot be used as a
  1936. subscript index, or if this node is not subscriptable.
  1937. :raises AstroidIndexError: If the given index does not exist in the
  1938. dictionary.
  1939. """
  1940. # pylint: disable-next=import-outside-toplevel; circular import
  1941. from astroid.helpers import safe_infer
  1942. for key, value in self.items:
  1943. # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.
  1944. if isinstance(key, DictUnpack):
  1945. inferred_value = safe_infer(value, context)
  1946. if not isinstance(inferred_value, Dict):
  1947. continue
  1948. try:
  1949. return inferred_value.getitem(index, context)
  1950. except (AstroidTypeError, AstroidIndexError):
  1951. continue
  1952. for inferredkey in key.infer(context):
  1953. if isinstance(inferredkey, util.UninferableBase):
  1954. continue
  1955. if isinstance(inferredkey, Const) and isinstance(index, Const):
  1956. if inferredkey.value == index.value:
  1957. return value
  1958. raise AstroidIndexError(index)
  1959. def bool_value(self, context: InferenceContext | None = None):
  1960. """Determine the boolean value of this node.
  1961. :returns: The boolean value of this node.
  1962. :rtype: bool
  1963. """
  1964. return bool(self.items)
  1965. class Expr(_base_nodes.Statement):
  1966. """Class representing an :class:`ast.Expr` node.
  1967. An :class:`Expr` is any expression that does not have its value used or
  1968. stored.
  1969. >>> import astroid
  1970. >>> node = astroid.extract_node('method()')
  1971. >>> node
  1972. <Call l.1 at 0x7f23b2e352b0>
  1973. >>> node.parent
  1974. <Expr l.1 at 0x7f23b2e35278>
  1975. """
  1976. _astroid_fields = ("value",)
  1977. def __init__(
  1978. self,
  1979. lineno: int | None = None,
  1980. col_offset: int | None = None,
  1981. parent: NodeNG | None = None,
  1982. *,
  1983. end_lineno: int | None = None,
  1984. end_col_offset: int | None = None,
  1985. ) -> None:
  1986. """
  1987. :param lineno: The line that this node appears on in the source code.
  1988. :param col_offset: The column that this node appears on in the
  1989. source code.
  1990. :param parent: The parent node in the syntax tree.
  1991. :param end_lineno: The last line this node appears on in the source code.
  1992. :param end_col_offset: The end column this node appears on in the
  1993. source code. Note: This is after the last symbol.
  1994. """
  1995. self.value: NodeNG | None = None
  1996. """What the expression does."""
  1997. super().__init__(
  1998. lineno=lineno,
  1999. col_offset=col_offset,
  2000. end_lineno=end_lineno,
  2001. end_col_offset=end_col_offset,
  2002. parent=parent,
  2003. )
  2004. def postinit(self, value: NodeNG | None = None) -> None:
  2005. """Do some setup after initialisation.
  2006. :param value: What the expression does.
  2007. """
  2008. self.value = value
  2009. def get_children(self):
  2010. yield self.value
  2011. def _get_yield_nodes_skip_lambdas(self):
  2012. if not self.value.is_lambda:
  2013. yield from self.value._get_yield_nodes_skip_lambdas()
  2014. class Ellipsis(_base_nodes.NoChildrenNode): # pylint: disable=redefined-builtin
  2015. """Class representing an :class:`ast.Ellipsis` node.
  2016. An :class:`Ellipsis` is the ``...`` syntax.
  2017. Deprecated since v2.6.0 - Use :class:`Const` instead.
  2018. Will be removed with the release v2.7.0
  2019. """
  2020. class EmptyNode(_base_nodes.NoChildrenNode):
  2021. """Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`."""
  2022. object = None
  2023. def has_underlying_object(self) -> bool:
  2024. return self.object is not None and self.object is not _EMPTY_OBJECT_MARKER
  2025. class ExceptHandler(
  2026. _base_nodes.MultiLineBlockNode, _base_nodes.AssignTypeNode, _base_nodes.Statement
  2027. ):
  2028. """Class representing an :class:`ast.ExceptHandler`. node.
  2029. An :class:`ExceptHandler` is an ``except`` block on a try-except.
  2030. >>> import astroid
  2031. >>> node = astroid.extract_node('''
  2032. try:
  2033. do_something()
  2034. except Exception as error:
  2035. print("Error!")
  2036. ''')
  2037. >>> node
  2038. <TryExcept l.2 at 0x7f23b2e9d908>
  2039. >>> node.handlers
  2040. [<ExceptHandler l.4 at 0x7f23b2e9e860>]
  2041. """
  2042. _astroid_fields = ("type", "name", "body")
  2043. _multi_line_block_fields = ("body",)
  2044. def __init__(
  2045. self,
  2046. lineno: int | None = None,
  2047. col_offset: int | None = None,
  2048. parent: NodeNG | None = None,
  2049. *,
  2050. end_lineno: int | None = None,
  2051. end_col_offset: int | None = None,
  2052. ) -> None:
  2053. """
  2054. :param lineno: The line that this node appears on in the source code.
  2055. :param col_offset: The column that this node appears on in the
  2056. source code.
  2057. :param parent: The parent node in the syntax tree.
  2058. :param end_lineno: The last line this node appears on in the source code.
  2059. :param end_col_offset: The end column this node appears on in the
  2060. source code. Note: This is after the last symbol.
  2061. """
  2062. self.type: NodeNG | None = None # can be None
  2063. """The types that the block handles.
  2064. :type: Tuple or NodeNG or None
  2065. """
  2066. self.name: AssignName | None = None # can be None
  2067. """The name that the caught exception is assigned to."""
  2068. self.body: list[NodeNG] = []
  2069. """The contents of the block."""
  2070. super().__init__(
  2071. lineno=lineno,
  2072. col_offset=col_offset,
  2073. end_lineno=end_lineno,
  2074. end_col_offset=end_col_offset,
  2075. parent=parent,
  2076. )
  2077. assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]
  2078. """Returns the assigned statement (non inferred) according to the assignment type.
  2079. See astroid/protocols.py for actual implementation.
  2080. """
  2081. def get_children(self):
  2082. if self.type is not None:
  2083. yield self.type
  2084. if self.name is not None:
  2085. yield self.name
  2086. yield from self.body
  2087. # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
  2088. def postinit(
  2089. self,
  2090. type: NodeNG | None = None,
  2091. name: AssignName | None = None,
  2092. body: list[NodeNG] | None = None,
  2093. ) -> None:
  2094. """Do some setup after initialisation.
  2095. :param type: The types that the block handles.
  2096. :type type: Tuple or NodeNG or None
  2097. :param name: The name that the caught exception is assigned to.
  2098. :param body:The contents of the block.
  2099. """
  2100. self.type = type
  2101. self.name = name
  2102. if body is not None:
  2103. self.body = body
  2104. @cached_property
  2105. def blockstart_tolineno(self):
  2106. """The line on which the beginning of this block ends.
  2107. :type: int
  2108. """
  2109. if self.name:
  2110. return self.name.tolineno
  2111. if self.type:
  2112. return self.type.tolineno
  2113. return self.lineno
  2114. def catch(self, exceptions: list[str] | None) -> bool:
  2115. """Check if this node handles any of the given
  2116. :param exceptions: The names of the exceptions to check for.
  2117. """
  2118. if self.type is None or exceptions is None:
  2119. return True
  2120. return any(node.name in exceptions for node in self.type._get_name_nodes())
  2121. class ExtSlice(NodeNG):
  2122. """Class representing an :class:`ast.ExtSlice` node.
  2123. An :class:`ExtSlice` is a complex slice expression.
  2124. Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
  2125. Will be removed with the release of v2.7.0
  2126. """
  2127. class For(
  2128. _base_nodes.MultiLineWithElseBlockNode,
  2129. _base_nodes.AssignTypeNode,
  2130. _base_nodes.Statement,
  2131. ):
  2132. """Class representing an :class:`ast.For` node.
  2133. >>> import astroid
  2134. >>> node = astroid.extract_node('for thing in things: print(thing)')
  2135. >>> node
  2136. <For l.1 at 0x7f23b2e8cf28>
  2137. """
  2138. _astroid_fields = ("target", "iter", "body", "orelse")
  2139. _other_other_fields = ("type_annotation",)
  2140. _multi_line_block_fields = ("body", "orelse")
  2141. optional_assign = True
  2142. """Whether this node optionally assigns a variable.
  2143. This is always ``True`` for :class:`For` nodes.
  2144. """
  2145. def __init__(
  2146. self,
  2147. lineno: int | None = None,
  2148. col_offset: int | None = None,
  2149. parent: NodeNG | None = None,
  2150. *,
  2151. end_lineno: int | None = None,
  2152. end_col_offset: int | None = None,
  2153. ) -> None:
  2154. """
  2155. :param lineno: The line that this node appears on in the source code.
  2156. :param col_offset: The column that this node appears on in the
  2157. source code.
  2158. :param parent: The parent node in the syntax tree.
  2159. :param end_lineno: The last line this node appears on in the source code.
  2160. :param end_col_offset: The end column this node appears on in the
  2161. source code. Note: This is after the last symbol.
  2162. """
  2163. self.target: NodeNG | None = None
  2164. """What the loop assigns to."""
  2165. self.iter: NodeNG | None = None
  2166. """What the loop iterates over."""
  2167. self.body: list[NodeNG] = []
  2168. """The contents of the body of the loop."""
  2169. self.orelse: list[NodeNG] = []
  2170. """The contents of the ``else`` block of the loop."""
  2171. self.type_annotation: NodeNG | None = None # can be None
  2172. """If present, this will contain the type annotation passed by a type comment"""
  2173. super().__init__(
  2174. lineno=lineno,
  2175. col_offset=col_offset,
  2176. end_lineno=end_lineno,
  2177. end_col_offset=end_col_offset,
  2178. parent=parent,
  2179. )
  2180. # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
  2181. def postinit(
  2182. self,
  2183. target: NodeNG | None = None,
  2184. iter: NodeNG | None = None,
  2185. body: list[NodeNG] | None = None,
  2186. orelse: list[NodeNG] | None = None,
  2187. type_annotation: NodeNG | None = None,
  2188. ) -> None:
  2189. """Do some setup after initialisation.
  2190. :param target: What the loop assigns to.
  2191. :param iter: What the loop iterates over.
  2192. :param body: The contents of the body of the loop.
  2193. :param orelse: The contents of the ``else`` block of the loop.
  2194. """
  2195. self.target = target
  2196. self.iter = iter
  2197. if body is not None:
  2198. self.body = body
  2199. if orelse is not None:
  2200. self.orelse = orelse
  2201. self.type_annotation = type_annotation
  2202. assigned_stmts: ClassVar[AssignedStmtsCall[For]]
  2203. """Returns the assigned statement (non inferred) according to the assignment type.
  2204. See astroid/protocols.py for actual implementation.
  2205. """
  2206. @cached_property
  2207. def blockstart_tolineno(self):
  2208. """The line on which the beginning of this block ends.
  2209. :type: int
  2210. """
  2211. return self.iter.tolineno
  2212. def get_children(self):
  2213. yield self.target
  2214. yield self.iter
  2215. yield from self.body
  2216. yield from self.orelse
  2217. class AsyncFor(For):
  2218. """Class representing an :class:`ast.AsyncFor` node.
  2219. An :class:`AsyncFor` is an asynchronous :class:`For` built with
  2220. the ``async`` keyword.
  2221. >>> import astroid
  2222. >>> node = astroid.extract_node('''
  2223. async def func(things):
  2224. async for thing in things:
  2225. print(thing)
  2226. ''')
  2227. >>> node
  2228. <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>
  2229. >>> node.body[0]
  2230. <AsyncFor l.3 at 0x7f23b2e417b8>
  2231. """
  2232. class Await(NodeNG):
  2233. """Class representing an :class:`ast.Await` node.
  2234. An :class:`Await` is the ``await`` keyword.
  2235. >>> import astroid
  2236. >>> node = astroid.extract_node('''
  2237. async def func(things):
  2238. await other_func()
  2239. ''')
  2240. >>> node
  2241. <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>
  2242. >>> node.body[0]
  2243. <Expr l.3 at 0x7f23b2e419e8>
  2244. >>> list(node.body[0].get_children())[0]
  2245. <Await l.3 at 0x7f23b2e41a20>
  2246. """
  2247. _astroid_fields = ("value",)
  2248. def __init__(
  2249. self,
  2250. lineno: int | None = None,
  2251. col_offset: int | None = None,
  2252. parent: NodeNG | None = None,
  2253. *,
  2254. end_lineno: int | None = None,
  2255. end_col_offset: int | None = None,
  2256. ) -> None:
  2257. """
  2258. :param lineno: The line that this node appears on in the source code.
  2259. :param col_offset: The column that this node appears on in the
  2260. source code.
  2261. :param parent: The parent node in the syntax tree.
  2262. :param end_lineno: The last line this node appears on in the source code.
  2263. :param end_col_offset: The end column this node appears on in the
  2264. source code. Note: This is after the last symbol.
  2265. """
  2266. self.value: NodeNG | None = None
  2267. """What to wait for."""
  2268. super().__init__(
  2269. lineno=lineno,
  2270. col_offset=col_offset,
  2271. end_lineno=end_lineno,
  2272. end_col_offset=end_col_offset,
  2273. parent=parent,
  2274. )
  2275. def postinit(self, value: NodeNG | None = None) -> None:
  2276. """Do some setup after initialisation.
  2277. :param value: What to wait for.
  2278. """
  2279. self.value = value
  2280. def get_children(self):
  2281. yield self.value
  2282. class ImportFrom(_base_nodes.ImportNode):
  2283. """Class representing an :class:`ast.ImportFrom` node.
  2284. >>> import astroid
  2285. >>> node = astroid.extract_node('from my_package import my_module')
  2286. >>> node
  2287. <ImportFrom l.1 at 0x7f23b2e415c0>
  2288. """
  2289. _other_fields = ("modname", "names", "level")
  2290. def __init__(
  2291. self,
  2292. fromname: str | None,
  2293. names: list[tuple[str, str | None]],
  2294. level: int | None = 0,
  2295. lineno: int | None = None,
  2296. col_offset: int | None = None,
  2297. parent: NodeNG | None = None,
  2298. *,
  2299. end_lineno: int | None = None,
  2300. end_col_offset: int | None = None,
  2301. ) -> None:
  2302. """
  2303. :param fromname: The module that is being imported from.
  2304. :param names: What is being imported from the module.
  2305. :param level: The level of relative import.
  2306. :param lineno: The line that this node appears on in the source code.
  2307. :param col_offset: The column that this node appears on in the
  2308. source code.
  2309. :param parent: The parent node in the syntax tree.
  2310. :param end_lineno: The last line this node appears on in the source code.
  2311. :param end_col_offset: The end column this node appears on in the
  2312. source code. Note: This is after the last symbol.
  2313. """
  2314. self.modname: str | None = fromname # can be None
  2315. """The module that is being imported from.
  2316. This is ``None`` for relative imports.
  2317. """
  2318. self.names: list[tuple[str, str | None]] = names
  2319. """What is being imported from the module.
  2320. Each entry is a :class:`tuple` of the name being imported,
  2321. and the alias that the name is assigned to (if any).
  2322. """
  2323. # TODO When is 'level' None?
  2324. self.level: int | None = level # can be None
  2325. """The level of relative import.
  2326. Essentially this is the number of dots in the import.
  2327. This is always 0 for absolute imports.
  2328. """
  2329. super().__init__(
  2330. lineno=lineno,
  2331. col_offset=col_offset,
  2332. end_lineno=end_lineno,
  2333. end_col_offset=end_col_offset,
  2334. parent=parent,
  2335. )
  2336. class Attribute(NodeNG):
  2337. """Class representing an :class:`ast.Attribute` node."""
  2338. _astroid_fields = ("expr",)
  2339. _other_fields = ("attrname",)
  2340. @decorators.deprecate_default_argument_values(attrname="str")
  2341. def __init__(
  2342. self,
  2343. attrname: str | None = None,
  2344. lineno: int | None = None,
  2345. col_offset: int | None = None,
  2346. parent: NodeNG | None = None,
  2347. *,
  2348. end_lineno: int | None = None,
  2349. end_col_offset: int | None = None,
  2350. ) -> None:
  2351. """
  2352. :param attrname: The name of the attribute.
  2353. :param lineno: The line that this node appears on in the source code.
  2354. :param col_offset: The column that this node appears on in the
  2355. source code.
  2356. :param parent: The parent node in the syntax tree.
  2357. :param end_lineno: The last line this node appears on in the source code.
  2358. :param end_col_offset: The end column this node appears on in the
  2359. source code. Note: This is after the last symbol.
  2360. """
  2361. self.expr: NodeNG | None = None
  2362. """The name that this node represents.
  2363. :type: Name or None
  2364. """
  2365. self.attrname: str | None = attrname
  2366. """The name of the attribute."""
  2367. super().__init__(
  2368. lineno=lineno,
  2369. col_offset=col_offset,
  2370. end_lineno=end_lineno,
  2371. end_col_offset=end_col_offset,
  2372. parent=parent,
  2373. )
  2374. def postinit(self, expr: NodeNG | None = None) -> None:
  2375. """Do some setup after initialisation.
  2376. :param expr: The name that this node represents.
  2377. :type expr: Name or None
  2378. """
  2379. self.expr = expr
  2380. def get_children(self):
  2381. yield self.expr
  2382. class Global(_base_nodes.NoChildrenNode, _base_nodes.Statement):
  2383. """Class representing an :class:`ast.Global` node.
  2384. >>> import astroid
  2385. >>> node = astroid.extract_node('global a_global')
  2386. >>> node
  2387. <Global l.1 at 0x7f23b2e9de10>
  2388. """
  2389. _other_fields = ("names",)
  2390. def __init__(
  2391. self,
  2392. names: list[str],
  2393. lineno: int | None = None,
  2394. col_offset: int | None = None,
  2395. parent: NodeNG | None = None,
  2396. *,
  2397. end_lineno: int | None = None,
  2398. end_col_offset: int | None = None,
  2399. ) -> None:
  2400. """
  2401. :param names: The names being declared as global.
  2402. :param lineno: The line that this node appears on in the source code.
  2403. :param col_offset: The column that this node appears on in the
  2404. source code.
  2405. :param parent: The parent node in the syntax tree.
  2406. :param end_lineno: The last line this node appears on in the source code.
  2407. :param end_col_offset: The end column this node appears on in the
  2408. source code. Note: This is after the last symbol.
  2409. """
  2410. self.names: list[str] = names
  2411. """The names being declared as global."""
  2412. super().__init__(
  2413. lineno=lineno,
  2414. col_offset=col_offset,
  2415. end_lineno=end_lineno,
  2416. end_col_offset=end_col_offset,
  2417. parent=parent,
  2418. )
  2419. def _infer_name(self, frame, name):
  2420. return name
  2421. class If(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
  2422. """Class representing an :class:`ast.If` node.
  2423. >>> import astroid
  2424. >>> node = astroid.extract_node('if condition: print(True)')
  2425. >>> node
  2426. <If l.1 at 0x7f23b2e9dd30>
  2427. """
  2428. _astroid_fields = ("test", "body", "orelse")
  2429. _multi_line_block_fields = ("body", "orelse")
  2430. def __init__(
  2431. self,
  2432. lineno: int | None = None,
  2433. col_offset: int | None = None,
  2434. parent: NodeNG | None = None,
  2435. *,
  2436. end_lineno: int | None = None,
  2437. end_col_offset: int | None = None,
  2438. ) -> None:
  2439. """
  2440. :param lineno: The line that this node appears on in the source code.
  2441. :param col_offset: The column that this node appears on in the
  2442. source code.
  2443. :param parent: The parent node in the syntax tree.
  2444. :param end_lineno: The last line this node appears on in the source code.
  2445. :param end_col_offset: The end column this node appears on in the
  2446. source code. Note: This is after the last symbol.
  2447. """
  2448. self.test: NodeNG | None = None
  2449. """The condition that the statement tests."""
  2450. self.body: list[NodeNG] = []
  2451. """The contents of the block."""
  2452. self.orelse: list[NodeNG] = []
  2453. """The contents of the ``else`` block."""
  2454. self.is_orelse: bool = False
  2455. """Whether the if-statement is the orelse-block of another if statement."""
  2456. super().__init__(
  2457. lineno=lineno,
  2458. col_offset=col_offset,
  2459. end_lineno=end_lineno,
  2460. end_col_offset=end_col_offset,
  2461. parent=parent,
  2462. )
  2463. def postinit(
  2464. self,
  2465. test: NodeNG | None = None,
  2466. body: list[NodeNG] | None = None,
  2467. orelse: list[NodeNG] | None = None,
  2468. ) -> None:
  2469. """Do some setup after initialisation.
  2470. :param test: The condition that the statement tests.
  2471. :param body: The contents of the block.
  2472. :param orelse: The contents of the ``else`` block.
  2473. """
  2474. self.test = test
  2475. if body is not None:
  2476. self.body = body
  2477. if orelse is not None:
  2478. self.orelse = orelse
  2479. if isinstance(self.parent, If) and self in self.parent.orelse:
  2480. self.is_orelse = True
  2481. @cached_property
  2482. def blockstart_tolineno(self):
  2483. """The line on which the beginning of this block ends.
  2484. :type: int
  2485. """
  2486. return self.test.tolineno
  2487. def block_range(self, lineno):
  2488. """Get a range from the given line number to where this node ends.
  2489. :param lineno: The line number to start the range at.
  2490. :type lineno: int
  2491. :returns: The range of line numbers that this node belongs to,
  2492. starting at the given line number.
  2493. :rtype: tuple(int, int)
  2494. """
  2495. if lineno == self.body[0].fromlineno:
  2496. return lineno, lineno
  2497. if lineno <= self.body[-1].tolineno:
  2498. return lineno, self.body[-1].tolineno
  2499. return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)
  2500. def get_children(self):
  2501. yield self.test
  2502. yield from self.body
  2503. yield from self.orelse
  2504. def has_elif_block(self):
  2505. return len(self.orelse) == 1 and isinstance(self.orelse[0], If)
  2506. def _get_yield_nodes_skip_lambdas(self):
  2507. """An If node can contain a Yield node in the test"""
  2508. yield from self.test._get_yield_nodes_skip_lambdas()
  2509. yield from super()._get_yield_nodes_skip_lambdas()
  2510. def is_sys_guard(self) -> bool:
  2511. """Return True if IF stmt is a sys.version_info guard.
  2512. >>> import astroid
  2513. >>> node = astroid.extract_node('''
  2514. import sys
  2515. if sys.version_info > (3, 8):
  2516. from typing import Literal
  2517. else:
  2518. from typing_extensions import Literal
  2519. ''')
  2520. >>> node.is_sys_guard()
  2521. True
  2522. """
  2523. warnings.warn(
  2524. "The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 "
  2525. "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
  2526. "starting with pylint 2.12",
  2527. DeprecationWarning,
  2528. stacklevel=2,
  2529. )
  2530. if isinstance(self.test, Compare):
  2531. value = self.test.left
  2532. if isinstance(value, Subscript):
  2533. value = value.value
  2534. if isinstance(value, Attribute) and value.as_string() == "sys.version_info":
  2535. return True
  2536. return False
  2537. def is_typing_guard(self) -> bool:
  2538. """Return True if IF stmt is a typing guard.
  2539. >>> import astroid
  2540. >>> node = astroid.extract_node('''
  2541. from typing import TYPE_CHECKING
  2542. if TYPE_CHECKING:
  2543. from xyz import a
  2544. ''')
  2545. >>> node.is_typing_guard()
  2546. True
  2547. """
  2548. warnings.warn(
  2549. "The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 "
  2550. "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
  2551. "starting with pylint 2.12",
  2552. DeprecationWarning,
  2553. stacklevel=2,
  2554. )
  2555. return isinstance(
  2556. self.test, (Name, Attribute)
  2557. ) and self.test.as_string().endswith("TYPE_CHECKING")
  2558. class IfExp(NodeNG):
  2559. """Class representing an :class:`ast.IfExp` node.
  2560. >>> import astroid
  2561. >>> node = astroid.extract_node('value if condition else other')
  2562. >>> node
  2563. <IfExp l.1 at 0x7f23b2e9dbe0>
  2564. """
  2565. _astroid_fields = ("test", "body", "orelse")
  2566. def __init__(
  2567. self,
  2568. lineno: int | None = None,
  2569. col_offset: int | None = None,
  2570. parent: NodeNG | None = None,
  2571. *,
  2572. end_lineno: int | None = None,
  2573. end_col_offset: int | None = None,
  2574. ) -> None:
  2575. """
  2576. :param lineno: The line that this node appears on in the source code.
  2577. :param col_offset: The column that this node appears on in the
  2578. source code.
  2579. :param parent: The parent node in the syntax tree.
  2580. :param end_lineno: The last line this node appears on in the source code.
  2581. :param end_col_offset: The end column this node appears on in the
  2582. source code. Note: This is after the last symbol.
  2583. """
  2584. self.test: NodeNG | None = None
  2585. """The condition that the statement tests."""
  2586. self.body: NodeNG | None = None
  2587. """The contents of the block."""
  2588. self.orelse: NodeNG | None = None
  2589. """The contents of the ``else`` block."""
  2590. super().__init__(
  2591. lineno=lineno,
  2592. col_offset=col_offset,
  2593. end_lineno=end_lineno,
  2594. end_col_offset=end_col_offset,
  2595. parent=parent,
  2596. )
  2597. def postinit(
  2598. self,
  2599. test: NodeNG | None = None,
  2600. body: NodeNG | None = None,
  2601. orelse: NodeNG | None = None,
  2602. ) -> None:
  2603. """Do some setup after initialisation.
  2604. :param test: The condition that the statement tests.
  2605. :param body: The contents of the block.
  2606. :param orelse: The contents of the ``else`` block.
  2607. """
  2608. self.test = test
  2609. self.body = body
  2610. self.orelse = orelse
  2611. def get_children(self):
  2612. yield self.test
  2613. yield self.body
  2614. yield self.orelse
  2615. def op_left_associative(self) -> Literal[False]:
  2616. # `1 if True else 2 if False else 3` is parsed as
  2617. # `1 if True else (2 if False else 3)`
  2618. return False
  2619. class Import(_base_nodes.ImportNode):
  2620. """Class representing an :class:`ast.Import` node.
  2621. >>> import astroid
  2622. >>> node = astroid.extract_node('import astroid')
  2623. >>> node
  2624. <Import l.1 at 0x7f23b2e4e5c0>
  2625. """
  2626. _other_fields = ("names",)
  2627. @decorators.deprecate_default_argument_values(names="list[tuple[str, str | None]]")
  2628. def __init__(
  2629. self,
  2630. names: list[tuple[str, str | None]] | None = None,
  2631. lineno: int | None = None,
  2632. col_offset: int | None = None,
  2633. parent: NodeNG | None = None,
  2634. *,
  2635. end_lineno: int | None = None,
  2636. end_col_offset: int | None = None,
  2637. ) -> None:
  2638. """
  2639. :param names: The names being imported.
  2640. :param lineno: The line that this node appears on in the source code.
  2641. :param col_offset: The column that this node appears on in the
  2642. source code.
  2643. :param parent: The parent node in the syntax tree.
  2644. :param end_lineno: The last line this node appears on in the source code.
  2645. :param end_col_offset: The end column this node appears on in the
  2646. source code. Note: This is after the last symbol.
  2647. """
  2648. self.names: list[tuple[str, str | None]] = names or []
  2649. """The names being imported.
  2650. Each entry is a :class:`tuple` of the name being imported,
  2651. and the alias that the name is assigned to (if any).
  2652. """
  2653. super().__init__(
  2654. lineno=lineno,
  2655. col_offset=col_offset,
  2656. end_lineno=end_lineno,
  2657. end_col_offset=end_col_offset,
  2658. parent=parent,
  2659. )
  2660. class Index(NodeNG):
  2661. """Class representing an :class:`ast.Index` node.
  2662. An :class:`Index` is a simple subscript.
  2663. Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
  2664. Will be removed with the release of v2.7.0
  2665. """
  2666. class Keyword(NodeNG):
  2667. """Class representing an :class:`ast.keyword` node.
  2668. >>> import astroid
  2669. >>> node = astroid.extract_node('function(a_kwarg=True)')
  2670. >>> node
  2671. <Call l.1 at 0x7f23b2e9e320>
  2672. >>> node.keywords
  2673. [<Keyword l.1 at 0x7f23b2e9e9b0>]
  2674. """
  2675. _astroid_fields = ("value",)
  2676. _other_fields = ("arg",)
  2677. def __init__(
  2678. self,
  2679. arg: str | None = None,
  2680. lineno: int | None = None,
  2681. col_offset: int | None = None,
  2682. parent: NodeNG | None = None,
  2683. *,
  2684. end_lineno: int | None = None,
  2685. end_col_offset: int | None = None,
  2686. ) -> None:
  2687. """
  2688. :param arg: The argument being assigned to.
  2689. :param lineno: The line that this node appears on in the source code.
  2690. :param col_offset: The column that this node appears on in the
  2691. source code.
  2692. :param parent: The parent node in the syntax tree.
  2693. :param end_lineno: The last line this node appears on in the source code.
  2694. :param end_col_offset: The end column this node appears on in the
  2695. source code. Note: This is after the last symbol.
  2696. """
  2697. self.arg: str | None = arg # can be None
  2698. """The argument being assigned to."""
  2699. self.value: NodeNG | None = None
  2700. """The value being assigned to the keyword argument."""
  2701. super().__init__(
  2702. lineno=lineno,
  2703. col_offset=col_offset,
  2704. end_lineno=end_lineno,
  2705. end_col_offset=end_col_offset,
  2706. parent=parent,
  2707. )
  2708. def postinit(self, value: NodeNG | None = None) -> None:
  2709. """Do some setup after initialisation.
  2710. :param value: The value being assigned to the keyword argument.
  2711. """
  2712. self.value = value
  2713. def get_children(self):
  2714. yield self.value
  2715. class List(BaseContainer):
  2716. """Class representing an :class:`ast.List` node.
  2717. >>> import astroid
  2718. >>> node = astroid.extract_node('[1, 2, 3]')
  2719. >>> node
  2720. <List.list l.1 at 0x7f23b2e9e128>
  2721. """
  2722. _other_fields = ("ctx",)
  2723. def __init__(
  2724. self,
  2725. ctx: Context | None = None,
  2726. lineno: int | None = None,
  2727. col_offset: int | None = None,
  2728. parent: NodeNG | None = None,
  2729. *,
  2730. end_lineno: int | None = None,
  2731. end_col_offset: int | None = None,
  2732. ) -> None:
  2733. """
  2734. :param ctx: Whether the list is assigned to or loaded from.
  2735. :param lineno: The line that this node appears on in the source code.
  2736. :param col_offset: The column that this node appears on in the
  2737. source code.
  2738. :param parent: The parent node in the syntax tree.
  2739. :param end_lineno: The last line this node appears on in the source code.
  2740. :param end_col_offset: The end column this node appears on in the
  2741. source code. Note: This is after the last symbol.
  2742. """
  2743. self.ctx: Context | None = ctx
  2744. """Whether the list is assigned to or loaded from."""
  2745. super().__init__(
  2746. lineno=lineno,
  2747. col_offset=col_offset,
  2748. end_lineno=end_lineno,
  2749. end_col_offset=end_col_offset,
  2750. parent=parent,
  2751. )
  2752. assigned_stmts: ClassVar[AssignedStmtsCall[List]]
  2753. """Returns the assigned statement (non inferred) according to the assignment type.
  2754. See astroid/protocols.py for actual implementation.
  2755. """
  2756. infer_unary_op: ClassVar[InferUnaryOp[List]]
  2757. infer_binary_op: ClassVar[InferBinaryOp[List]]
  2758. def pytype(self) -> Literal["builtins.list"]:
  2759. """Get the name of the type that this node represents.
  2760. :returns: The name of the type.
  2761. """
  2762. return "builtins.list"
  2763. def getitem(self, index, context: InferenceContext | None = None):
  2764. """Get an item from this node.
  2765. :param index: The node to use as a subscript index.
  2766. :type index: Const or Slice
  2767. """
  2768. return _container_getitem(self, self.elts, index, context=context)
  2769. class Nonlocal(_base_nodes.NoChildrenNode, _base_nodes.Statement):
  2770. """Class representing an :class:`ast.Nonlocal` node.
  2771. >>> import astroid
  2772. >>> node = astroid.extract_node('''
  2773. def function():
  2774. nonlocal var
  2775. ''')
  2776. >>> node
  2777. <FunctionDef.function l.2 at 0x7f23b2e9e208>
  2778. >>> node.body[0]
  2779. <Nonlocal l.3 at 0x7f23b2e9e908>
  2780. """
  2781. _other_fields = ("names",)
  2782. def __init__(
  2783. self,
  2784. names: list[str],
  2785. lineno: int | None = None,
  2786. col_offset: int | None = None,
  2787. parent: NodeNG | None = None,
  2788. *,
  2789. end_lineno: int | None = None,
  2790. end_col_offset: int | None = None,
  2791. ) -> None:
  2792. """
  2793. :param names: The names being declared as not local.
  2794. :param lineno: The line that this node appears on in the source code.
  2795. :param col_offset: The column that this node appears on in the
  2796. source code.
  2797. :param parent: The parent node in the syntax tree.
  2798. :param end_lineno: The last line this node appears on in the source code.
  2799. :param end_col_offset: The end column this node appears on in the
  2800. source code. Note: This is after the last symbol.
  2801. """
  2802. self.names: list[str] = names
  2803. """The names being declared as not local."""
  2804. super().__init__(
  2805. lineno=lineno,
  2806. col_offset=col_offset,
  2807. end_lineno=end_lineno,
  2808. end_col_offset=end_col_offset,
  2809. parent=parent,
  2810. )
  2811. def _infer_name(self, frame, name):
  2812. return name
  2813. class Pass(_base_nodes.NoChildrenNode, _base_nodes.Statement):
  2814. """Class representing an :class:`ast.Pass` node.
  2815. >>> import astroid
  2816. >>> node = astroid.extract_node('pass')
  2817. >>> node
  2818. <Pass l.1 at 0x7f23b2e9e748>
  2819. """
  2820. class Raise(_base_nodes.Statement):
  2821. """Class representing an :class:`ast.Raise` node.
  2822. >>> import astroid
  2823. >>> node = astroid.extract_node('raise RuntimeError("Something bad happened!")')
  2824. >>> node
  2825. <Raise l.1 at 0x7f23b2e9e828>
  2826. """
  2827. _astroid_fields = ("exc", "cause")
  2828. def __init__(
  2829. self,
  2830. lineno: int | None = None,
  2831. col_offset: int | None = None,
  2832. parent: NodeNG | None = None,
  2833. *,
  2834. end_lineno: int | None = None,
  2835. end_col_offset: int | None = None,
  2836. ) -> None:
  2837. """
  2838. :param lineno: The line that this node appears on in the source code.
  2839. :param col_offset: The column that this node appears on in the
  2840. source code.
  2841. :param parent: The parent node in the syntax tree.
  2842. :param end_lineno: The last line this node appears on in the source code.
  2843. :param end_col_offset: The end column this node appears on in the
  2844. source code. Note: This is after the last symbol.
  2845. """
  2846. self.exc: NodeNG | None = None # can be None
  2847. """What is being raised."""
  2848. self.cause: NodeNG | None = None # can be None
  2849. """The exception being used to raise this one."""
  2850. super().__init__(
  2851. lineno=lineno,
  2852. col_offset=col_offset,
  2853. end_lineno=end_lineno,
  2854. end_col_offset=end_col_offset,
  2855. parent=parent,
  2856. )
  2857. def postinit(
  2858. self,
  2859. exc: NodeNG | None = None,
  2860. cause: NodeNG | None = None,
  2861. ) -> None:
  2862. """Do some setup after initialisation.
  2863. :param exc: What is being raised.
  2864. :param cause: The exception being used to raise this one.
  2865. """
  2866. self.exc = exc
  2867. self.cause = cause
  2868. def raises_not_implemented(self) -> bool:
  2869. """Check if this node raises a :class:`NotImplementedError`.
  2870. :returns: Whether this node raises a :class:`NotImplementedError`.
  2871. """
  2872. if not self.exc:
  2873. return False
  2874. return any(
  2875. name.name == "NotImplementedError" for name in self.exc._get_name_nodes()
  2876. )
  2877. def get_children(self):
  2878. if self.exc is not None:
  2879. yield self.exc
  2880. if self.cause is not None:
  2881. yield self.cause
  2882. class Return(_base_nodes.Statement):
  2883. """Class representing an :class:`ast.Return` node.
  2884. >>> import astroid
  2885. >>> node = astroid.extract_node('return True')
  2886. >>> node
  2887. <Return l.1 at 0x7f23b8211908>
  2888. """
  2889. _astroid_fields = ("value",)
  2890. def __init__(
  2891. self,
  2892. lineno: int | None = None,
  2893. col_offset: int | None = None,
  2894. parent: NodeNG | None = None,
  2895. *,
  2896. end_lineno: int | None = None,
  2897. end_col_offset: int | None = None,
  2898. ) -> None:
  2899. """
  2900. :param lineno: The line that this node appears on in the source code.
  2901. :param col_offset: The column that this node appears on in the
  2902. source code.
  2903. :param parent: The parent node in the syntax tree.
  2904. :param end_lineno: The last line this node appears on in the source code.
  2905. :param end_col_offset: The end column this node appears on in the
  2906. source code. Note: This is after the last symbol.
  2907. """
  2908. self.value: NodeNG | None = None # can be None
  2909. """The value being returned."""
  2910. super().__init__(
  2911. lineno=lineno,
  2912. col_offset=col_offset,
  2913. end_lineno=end_lineno,
  2914. end_col_offset=end_col_offset,
  2915. parent=parent,
  2916. )
  2917. def postinit(self, value: NodeNG | None = None) -> None:
  2918. """Do some setup after initialisation.
  2919. :param value: The value being returned.
  2920. """
  2921. self.value = value
  2922. def get_children(self):
  2923. if self.value is not None:
  2924. yield self.value
  2925. def is_tuple_return(self):
  2926. return isinstance(self.value, Tuple)
  2927. def _get_return_nodes_skip_functions(self):
  2928. yield self
  2929. class Set(BaseContainer):
  2930. """Class representing an :class:`ast.Set` node.
  2931. >>> import astroid
  2932. >>> node = astroid.extract_node('{1, 2, 3}')
  2933. >>> node
  2934. <Set.set l.1 at 0x7f23b2e71d68>
  2935. """
  2936. infer_unary_op: ClassVar[InferUnaryOp[Set]]
  2937. def pytype(self) -> Literal["builtins.set"]:
  2938. """Get the name of the type that this node represents.
  2939. :returns: The name of the type.
  2940. """
  2941. return "builtins.set"
  2942. class Slice(NodeNG):
  2943. """Class representing an :class:`ast.Slice` node.
  2944. >>> import astroid
  2945. >>> node = astroid.extract_node('things[1:3]')
  2946. >>> node
  2947. <Subscript l.1 at 0x7f23b2e71f60>
  2948. >>> node.slice
  2949. <Slice l.1 at 0x7f23b2e71e80>
  2950. """
  2951. _astroid_fields = ("lower", "upper", "step")
  2952. def __init__(
  2953. self,
  2954. lineno: int | None = None,
  2955. col_offset: int | None = None,
  2956. parent: NodeNG | None = None,
  2957. *,
  2958. end_lineno: int | None = None,
  2959. end_col_offset: int | None = None,
  2960. ) -> None:
  2961. """
  2962. :param lineno: The line that this node appears on in the source code.
  2963. :param col_offset: The column that this node appears on in the
  2964. source code.
  2965. :param parent: The parent node in the syntax tree.
  2966. :param end_lineno: The last line this node appears on in the source code.
  2967. :param end_col_offset: The end column this node appears on in the
  2968. source code. Note: This is after the last symbol.
  2969. """
  2970. self.lower: NodeNG | None = None # can be None
  2971. """The lower index in the slice."""
  2972. self.upper: NodeNG | None = None # can be None
  2973. """The upper index in the slice."""
  2974. self.step: NodeNG | None = None # can be None
  2975. """The step to take between indexes."""
  2976. super().__init__(
  2977. lineno=lineno,
  2978. col_offset=col_offset,
  2979. end_lineno=end_lineno,
  2980. end_col_offset=end_col_offset,
  2981. parent=parent,
  2982. )
  2983. def postinit(
  2984. self,
  2985. lower: NodeNG | None = None,
  2986. upper: NodeNG | None = None,
  2987. step: NodeNG | None = None,
  2988. ) -> None:
  2989. """Do some setup after initialisation.
  2990. :param lower: The lower index in the slice.
  2991. :param upper: The upper index in the slice.
  2992. :param step: The step to take between index.
  2993. """
  2994. self.lower = lower
  2995. self.upper = upper
  2996. self.step = step
  2997. def _wrap_attribute(self, attr):
  2998. """Wrap the empty attributes of the Slice in a Const node."""
  2999. if not attr:
  3000. const = const_factory(attr)
  3001. const.parent = self
  3002. return const
  3003. return attr
  3004. @cached_property
  3005. def _proxied(self) -> nodes.ClassDef:
  3006. builtins = AstroidManager().builtins_module
  3007. return builtins.getattr("slice")[0]
  3008. def pytype(self) -> Literal["builtins.slice"]:
  3009. """Get the name of the type that this node represents.
  3010. :returns: The name of the type.
  3011. """
  3012. return "builtins.slice"
  3013. def igetattr(self, attrname, context: InferenceContext | None = None):
  3014. """Infer the possible values of the given attribute on the slice.
  3015. :param attrname: The name of the attribute to infer.
  3016. :type attrname: str
  3017. :returns: The inferred possible values.
  3018. :rtype: iterable(NodeNG)
  3019. """
  3020. if attrname == "start":
  3021. yield self._wrap_attribute(self.lower)
  3022. elif attrname == "stop":
  3023. yield self._wrap_attribute(self.upper)
  3024. elif attrname == "step":
  3025. yield self._wrap_attribute(self.step)
  3026. else:
  3027. yield from self.getattr(attrname, context=context)
  3028. def getattr(self, attrname, context: InferenceContext | None = None):
  3029. return self._proxied.getattr(attrname, context)
  3030. def get_children(self):
  3031. if self.lower is not None:
  3032. yield self.lower
  3033. if self.upper is not None:
  3034. yield self.upper
  3035. if self.step is not None:
  3036. yield self.step
  3037. class Starred(_base_nodes.ParentAssignNode):
  3038. """Class representing an :class:`ast.Starred` node.
  3039. >>> import astroid
  3040. >>> node = astroid.extract_node('*args')
  3041. >>> node
  3042. <Starred l.1 at 0x7f23b2e41978>
  3043. """
  3044. _astroid_fields = ("value",)
  3045. _other_fields = ("ctx",)
  3046. def __init__(
  3047. self,
  3048. ctx: Context | None = None,
  3049. lineno: int | None = None,
  3050. col_offset: int | None = None,
  3051. parent: NodeNG | None = None,
  3052. *,
  3053. end_lineno: int | None = None,
  3054. end_col_offset: int | None = None,
  3055. ) -> None:
  3056. """
  3057. :param ctx: Whether the list is assigned to or loaded from.
  3058. :param lineno: The line that this node appears on in the source code.
  3059. :param col_offset: The column that this node appears on in the
  3060. source code.
  3061. :param parent: The parent node in the syntax tree.
  3062. :param end_lineno: The last line this node appears on in the source code.
  3063. :param end_col_offset: The end column this node appears on in the
  3064. source code. Note: This is after the last symbol.
  3065. """
  3066. self.value: NodeNG | None = None
  3067. """What is being unpacked."""
  3068. self.ctx: Context | None = ctx
  3069. """Whether the starred item is assigned to or loaded from."""
  3070. super().__init__(
  3071. lineno=lineno,
  3072. col_offset=col_offset,
  3073. end_lineno=end_lineno,
  3074. end_col_offset=end_col_offset,
  3075. parent=parent,
  3076. )
  3077. def postinit(self, value: NodeNG | None = None) -> None:
  3078. """Do some setup after initialisation.
  3079. :param value: What is being unpacked.
  3080. """
  3081. self.value = value
  3082. assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]
  3083. """Returns the assigned statement (non inferred) according to the assignment type.
  3084. See astroid/protocols.py for actual implementation.
  3085. """
  3086. def get_children(self):
  3087. yield self.value
  3088. class Subscript(NodeNG):
  3089. """Class representing an :class:`ast.Subscript` node.
  3090. >>> import astroid
  3091. >>> node = astroid.extract_node('things[1:3]')
  3092. >>> node
  3093. <Subscript l.1 at 0x7f23b2e71f60>
  3094. """
  3095. _astroid_fields = ("value", "slice")
  3096. _other_fields = ("ctx",)
  3097. infer_lhs: ClassVar[InferLHS[Subscript]]
  3098. def __init__(
  3099. self,
  3100. ctx: Context | None = None,
  3101. lineno: int | None = None,
  3102. col_offset: int | None = None,
  3103. parent: NodeNG | None = None,
  3104. *,
  3105. end_lineno: int | None = None,
  3106. end_col_offset: int | None = None,
  3107. ) -> None:
  3108. """
  3109. :param ctx: Whether the subscripted item is assigned to or loaded from.
  3110. :param lineno: The line that this node appears on in the source code.
  3111. :param col_offset: The column that this node appears on in the
  3112. source code.
  3113. :param parent: The parent node in the syntax tree.
  3114. :param end_lineno: The last line this node appears on in the source code.
  3115. :param end_col_offset: The end column this node appears on in the
  3116. source code. Note: This is after the last symbol.
  3117. """
  3118. self.value: NodeNG | None = None
  3119. """What is being indexed."""
  3120. self.slice: NodeNG | None = None
  3121. """The slice being used to lookup."""
  3122. self.ctx: Context | None = ctx
  3123. """Whether the subscripted item is assigned to or loaded from."""
  3124. super().__init__(
  3125. lineno=lineno,
  3126. col_offset=col_offset,
  3127. end_lineno=end_lineno,
  3128. end_col_offset=end_col_offset,
  3129. parent=parent,
  3130. )
  3131. # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
  3132. def postinit(
  3133. self, value: NodeNG | None = None, slice: NodeNG | None = None
  3134. ) -> None:
  3135. """Do some setup after initialisation.
  3136. :param value: What is being indexed.
  3137. :param slice: The slice being used to lookup.
  3138. """
  3139. self.value = value
  3140. self.slice = slice
  3141. def get_children(self):
  3142. yield self.value
  3143. yield self.slice
  3144. class TryExcept(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
  3145. """Class representing an :class:`ast.TryExcept` node.
  3146. >>> import astroid
  3147. >>> node = astroid.extract_node('''
  3148. try:
  3149. do_something()
  3150. except Exception as error:
  3151. print("Error!")
  3152. ''')
  3153. >>> node
  3154. <TryExcept l.2 at 0x7f23b2e9d908>
  3155. """
  3156. _astroid_fields = ("body", "handlers", "orelse")
  3157. _multi_line_block_fields = ("body", "handlers", "orelse")
  3158. def __init__(
  3159. self,
  3160. lineno: int | None = None,
  3161. col_offset: int | None = None,
  3162. parent: NodeNG | None = None,
  3163. *,
  3164. end_lineno: int | None = None,
  3165. end_col_offset: int | None = None,
  3166. ) -> None:
  3167. """
  3168. :param lineno: The line that this node appears on in the source code.
  3169. :param col_offset: The column that this node appears on in the
  3170. source code.
  3171. :param parent: The parent node in the syntax tree.
  3172. :param end_lineno: The last line this node appears on in the source code.
  3173. :param end_col_offset: The end column this node appears on in the
  3174. source code. Note: This is after the last symbol.
  3175. """
  3176. self.body: list[NodeNG] = []
  3177. """The contents of the block to catch exceptions from."""
  3178. self.handlers: list[ExceptHandler] = []
  3179. """The exception handlers."""
  3180. self.orelse: list[NodeNG] = []
  3181. """The contents of the ``else`` block."""
  3182. super().__init__(
  3183. lineno=lineno,
  3184. col_offset=col_offset,
  3185. end_lineno=end_lineno,
  3186. end_col_offset=end_col_offset,
  3187. parent=parent,
  3188. )
  3189. def postinit(
  3190. self,
  3191. body: list[NodeNG] | None = None,
  3192. handlers: list[ExceptHandler] | None = None,
  3193. orelse: list[NodeNG] | None = None,
  3194. ) -> None:
  3195. """Do some setup after initialisation.
  3196. :param body: The contents of the block to catch exceptions from.
  3197. :param handlers: The exception handlers.
  3198. :param orelse: The contents of the ``else`` block.
  3199. """
  3200. if body is not None:
  3201. self.body = body
  3202. if handlers is not None:
  3203. self.handlers = handlers
  3204. if orelse is not None:
  3205. self.orelse = orelse
  3206. def _infer_name(self, frame, name):
  3207. return name
  3208. def block_range(self, lineno):
  3209. """Get a range from the given line number to where this node ends.
  3210. :param lineno: The line number to start the range at.
  3211. :type lineno: int
  3212. :returns: The range of line numbers that this node belongs to,
  3213. starting at the given line number.
  3214. :rtype: tuple(int, int)
  3215. """
  3216. last = None
  3217. for exhandler in self.handlers:
  3218. if exhandler.type and lineno == exhandler.type.fromlineno:
  3219. return lineno, lineno
  3220. if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
  3221. return lineno, exhandler.body[-1].tolineno
  3222. if last is None:
  3223. last = exhandler.body[0].fromlineno - 1
  3224. return self._elsed_block_range(lineno, self.orelse, last)
  3225. def get_children(self):
  3226. yield from self.body
  3227. yield from self.handlers or ()
  3228. yield from self.orelse or ()
  3229. class TryFinally(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
  3230. """Class representing an :class:`ast.TryFinally` node.
  3231. >>> import astroid
  3232. >>> node = astroid.extract_node('''
  3233. try:
  3234. do_something()
  3235. except Exception as error:
  3236. print("Error!")
  3237. finally:
  3238. print("Cleanup!")
  3239. ''')
  3240. >>> node
  3241. <TryFinally l.2 at 0x7f23b2e41d68>
  3242. """
  3243. _astroid_fields = ("body", "finalbody")
  3244. _multi_line_block_fields = ("body", "finalbody")
  3245. def __init__(
  3246. self,
  3247. lineno: int | None = None,
  3248. col_offset: int | None = None,
  3249. parent: NodeNG | None = None,
  3250. *,
  3251. end_lineno: int | None = None,
  3252. end_col_offset: int | None = None,
  3253. ) -> None:
  3254. """
  3255. :param lineno: The line that this node appears on in the source code.
  3256. :param col_offset: The column that this node appears on in the
  3257. source code.
  3258. :param parent: The parent node in the syntax tree.
  3259. :param end_lineno: The last line this node appears on in the source code.
  3260. :param end_col_offset: The end column this node appears on in the
  3261. source code. Note: This is after the last symbol.
  3262. """
  3263. self.body: list[NodeNG | TryExcept] = []
  3264. """The try-except that the finally is attached to."""
  3265. self.finalbody: list[NodeNG] = []
  3266. """The contents of the ``finally`` block."""
  3267. super().__init__(
  3268. lineno=lineno,
  3269. col_offset=col_offset,
  3270. end_lineno=end_lineno,
  3271. end_col_offset=end_col_offset,
  3272. parent=parent,
  3273. )
  3274. def postinit(
  3275. self,
  3276. body: list[NodeNG | TryExcept] | None = None,
  3277. finalbody: list[NodeNG] | None = None,
  3278. ) -> None:
  3279. """Do some setup after initialisation.
  3280. :param body: The try-except that the finally is attached to.
  3281. :param finalbody: The contents of the ``finally`` block.
  3282. """
  3283. if body is not None:
  3284. self.body = body
  3285. if finalbody is not None:
  3286. self.finalbody = finalbody
  3287. def block_range(self, lineno):
  3288. """Get a range from the given line number to where this node ends.
  3289. :param lineno: The line number to start the range at.
  3290. :type lineno: int
  3291. :returns: The range of line numbers that this node belongs to,
  3292. starting at the given line number.
  3293. :rtype: tuple(int, int)
  3294. """
  3295. child = self.body[0]
  3296. # py2.5 try: except: finally:
  3297. if (
  3298. isinstance(child, TryExcept)
  3299. and child.fromlineno == self.fromlineno
  3300. and child.tolineno >= lineno > self.fromlineno
  3301. ):
  3302. return child.block_range(lineno)
  3303. return self._elsed_block_range(lineno, self.finalbody)
  3304. def get_children(self):
  3305. yield from self.body
  3306. yield from self.finalbody
  3307. class TryStar(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
  3308. """Class representing an :class:`ast.TryStar` node."""
  3309. _astroid_fields = ("body", "handlers", "orelse", "finalbody")
  3310. _multi_line_block_fields = ("body", "handlers", "orelse", "finalbody")
  3311. def __init__(
  3312. self,
  3313. *,
  3314. lineno: int | None = None,
  3315. col_offset: int | None = None,
  3316. end_lineno: int | None = None,
  3317. end_col_offset: int | None = None,
  3318. parent: NodeNG | None = None,
  3319. ) -> None:
  3320. """
  3321. :param lineno: The line that this node appears on in the source code.
  3322. :param col_offset: The column that this node appears on in the
  3323. source code.
  3324. :param parent: The parent node in the syntax tree.
  3325. :param end_lineno: The last line this node appears on in the source code.
  3326. :param end_col_offset: The end column this node appears on in the
  3327. source code. Note: This is after the last symbol.
  3328. """
  3329. self.body: list[NodeNG] = []
  3330. """The contents of the block to catch exceptions from."""
  3331. self.handlers: list[ExceptHandler] = []
  3332. """The exception handlers."""
  3333. self.orelse: list[NodeNG] = []
  3334. """The contents of the ``else`` block."""
  3335. self.finalbody: list[NodeNG] = []
  3336. """The contents of the ``finally`` block."""
  3337. super().__init__(
  3338. lineno=lineno,
  3339. col_offset=col_offset,
  3340. end_lineno=end_lineno,
  3341. end_col_offset=end_col_offset,
  3342. parent=parent,
  3343. )
  3344. def postinit(
  3345. self,
  3346. *,
  3347. body: list[NodeNG] | None = None,
  3348. handlers: list[ExceptHandler] | None = None,
  3349. orelse: list[NodeNG] | None = None,
  3350. finalbody: list[NodeNG] | None = None,
  3351. ) -> None:
  3352. """Do some setup after initialisation.
  3353. :param body: The contents of the block to catch exceptions from.
  3354. :param handlers: The exception handlers.
  3355. :param orelse: The contents of the ``else`` block.
  3356. :param finalbody: The contents of the ``finally`` block.
  3357. """
  3358. if body:
  3359. self.body = body
  3360. if handlers:
  3361. self.handlers = handlers
  3362. if orelse:
  3363. self.orelse = orelse
  3364. if finalbody:
  3365. self.finalbody = finalbody
  3366. def _infer_name(self, frame, name):
  3367. return name
  3368. def block_range(self, lineno: int) -> tuple[int, int]:
  3369. """Get a range from a given line number to where this node ends."""
  3370. if lineno == self.fromlineno:
  3371. return lineno, lineno
  3372. if self.body and self.body[0].fromlineno <= lineno <= self.body[-1].tolineno:
  3373. # Inside try body - return from lineno till end of try body
  3374. return lineno, self.body[-1].tolineno
  3375. for exhandler in self.handlers:
  3376. if exhandler.type and lineno == exhandler.type.fromlineno:
  3377. return lineno, lineno
  3378. if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
  3379. return lineno, exhandler.body[-1].tolineno
  3380. if self.orelse:
  3381. if self.orelse[0].fromlineno - 1 == lineno:
  3382. return lineno, lineno
  3383. if self.orelse[0].fromlineno <= lineno <= self.orelse[-1].tolineno:
  3384. return lineno, self.orelse[-1].tolineno
  3385. if self.finalbody:
  3386. if self.finalbody[0].fromlineno - 1 == lineno:
  3387. return lineno, lineno
  3388. if self.finalbody[0].fromlineno <= lineno <= self.finalbody[-1].tolineno:
  3389. return lineno, self.finalbody[-1].tolineno
  3390. return lineno, self.tolineno
  3391. def get_children(self):
  3392. yield from self.body
  3393. yield from self.handlers
  3394. yield from self.orelse
  3395. yield from self.finalbody
  3396. class Tuple(BaseContainer):
  3397. """Class representing an :class:`ast.Tuple` node.
  3398. >>> import astroid
  3399. >>> node = astroid.extract_node('(1, 2, 3)')
  3400. >>> node
  3401. <Tuple.tuple l.1 at 0x7f23b2e41780>
  3402. """
  3403. _other_fields = ("ctx",)
  3404. def __init__(
  3405. self,
  3406. ctx: Context | None = None,
  3407. lineno: int | None = None,
  3408. col_offset: int | None = None,
  3409. parent: NodeNG | None = None,
  3410. *,
  3411. end_lineno: int | None = None,
  3412. end_col_offset: int | None = None,
  3413. ) -> None:
  3414. """
  3415. :param ctx: Whether the tuple is assigned to or loaded from.
  3416. :param lineno: The line that this node appears on in the source code.
  3417. :param col_offset: The column that this node appears on in the
  3418. source code.
  3419. :param parent: The parent node in the syntax tree.
  3420. :param end_lineno: The last line this node appears on in the source code.
  3421. :param end_col_offset: The end column this node appears on in the
  3422. source code. Note: This is after the last symbol.
  3423. """
  3424. self.ctx: Context | None = ctx
  3425. """Whether the tuple is assigned to or loaded from."""
  3426. super().__init__(
  3427. lineno=lineno,
  3428. col_offset=col_offset,
  3429. end_lineno=end_lineno,
  3430. end_col_offset=end_col_offset,
  3431. parent=parent,
  3432. )
  3433. assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]
  3434. """Returns the assigned statement (non inferred) according to the assignment type.
  3435. See astroid/protocols.py for actual implementation.
  3436. """
  3437. infer_unary_op: ClassVar[InferUnaryOp[Tuple]]
  3438. infer_binary_op: ClassVar[InferBinaryOp[Tuple]]
  3439. def pytype(self) -> Literal["builtins.tuple"]:
  3440. """Get the name of the type that this node represents.
  3441. :returns: The name of the type.
  3442. """
  3443. return "builtins.tuple"
  3444. def getitem(self, index, context: InferenceContext | None = None):
  3445. """Get an item from this node.
  3446. :param index: The node to use as a subscript index.
  3447. :type index: Const or Slice
  3448. """
  3449. return _container_getitem(self, self.elts, index, context=context)
  3450. class UnaryOp(NodeNG):
  3451. """Class representing an :class:`ast.UnaryOp` node.
  3452. >>> import astroid
  3453. >>> node = astroid.extract_node('-5')
  3454. >>> node
  3455. <UnaryOp l.1 at 0x7f23b2e4e198>
  3456. """
  3457. _astroid_fields = ("operand",)
  3458. _other_fields = ("op",)
  3459. @decorators.deprecate_default_argument_values(op="str")
  3460. def __init__(
  3461. self,
  3462. op: str | None = None,
  3463. lineno: int | None = None,
  3464. col_offset: int | None = None,
  3465. parent: NodeNG | None = None,
  3466. *,
  3467. end_lineno: int | None = None,
  3468. end_col_offset: int | None = None,
  3469. ) -> None:
  3470. """
  3471. :param op: The operator.
  3472. :param lineno: The line that this node appears on in the source code.
  3473. :param col_offset: The column that this node appears on in the
  3474. source code.
  3475. :param parent: The parent node in the syntax tree.
  3476. :param end_lineno: The last line this node appears on in the source code.
  3477. :param end_col_offset: The end column this node appears on in the
  3478. source code. Note: This is after the last symbol.
  3479. """
  3480. self.op: str | None = op
  3481. """The operator."""
  3482. self.operand: NodeNG | None = None
  3483. """What the unary operator is applied to."""
  3484. super().__init__(
  3485. lineno=lineno,
  3486. col_offset=col_offset,
  3487. end_lineno=end_lineno,
  3488. end_col_offset=end_col_offset,
  3489. parent=parent,
  3490. )
  3491. def postinit(self, operand: NodeNG | None = None) -> None:
  3492. """Do some setup after initialisation.
  3493. :param operand: What the unary operator is applied to.
  3494. """
  3495. self.operand = operand
  3496. # This is set by inference.py
  3497. _infer_unaryop: ClassVar[
  3498. InferBinaryOperation[UnaryOp, util.BadUnaryOperationMessage]
  3499. ]
  3500. def type_errors(self, context: InferenceContext | None = None):
  3501. """Get a list of type errors which can occur during inference.
  3502. Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
  3503. which holds the original exception.
  3504. :returns: The list of possible type errors.
  3505. :rtype: list(BadBinaryOperationMessage)
  3506. """
  3507. try:
  3508. results = self._infer_unaryop(context=context)
  3509. return [
  3510. result
  3511. for result in results
  3512. if isinstance(result, util.BadUnaryOperationMessage)
  3513. ]
  3514. except InferenceError:
  3515. return []
  3516. def get_children(self):
  3517. yield self.operand
  3518. def op_precedence(self):
  3519. if self.op == "not":
  3520. return OP_PRECEDENCE[self.op]
  3521. return super().op_precedence()
  3522. class While(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
  3523. """Class representing an :class:`ast.While` node.
  3524. >>> import astroid
  3525. >>> node = astroid.extract_node('''
  3526. while condition():
  3527. print("True")
  3528. ''')
  3529. >>> node
  3530. <While l.2 at 0x7f23b2e4e390>
  3531. """
  3532. _astroid_fields = ("test", "body", "orelse")
  3533. _multi_line_block_fields = ("body", "orelse")
  3534. def __init__(
  3535. self,
  3536. lineno: int | None = None,
  3537. col_offset: int | None = None,
  3538. parent: NodeNG | None = None,
  3539. *,
  3540. end_lineno: int | None = None,
  3541. end_col_offset: int | None = None,
  3542. ) -> None:
  3543. """
  3544. :param lineno: The line that this node appears on in the source code.
  3545. :param col_offset: The column that this node appears on in the
  3546. source code.
  3547. :param parent: The parent node in the syntax tree.
  3548. :param end_lineno: The last line this node appears on in the source code.
  3549. :param end_col_offset: The end column this node appears on in the
  3550. source code. Note: This is after the last symbol.
  3551. """
  3552. self.test: NodeNG | None = None
  3553. """The condition that the loop tests."""
  3554. self.body: list[NodeNG] = []
  3555. """The contents of the loop."""
  3556. self.orelse: list[NodeNG] = []
  3557. """The contents of the ``else`` block."""
  3558. super().__init__(
  3559. lineno=lineno,
  3560. col_offset=col_offset,
  3561. end_lineno=end_lineno,
  3562. end_col_offset=end_col_offset,
  3563. parent=parent,
  3564. )
  3565. def postinit(
  3566. self,
  3567. test: NodeNG | None = None,
  3568. body: list[NodeNG] | None = None,
  3569. orelse: list[NodeNG] | None = None,
  3570. ) -> None:
  3571. """Do some setup after initialisation.
  3572. :param test: The condition that the loop tests.
  3573. :param body: The contents of the loop.
  3574. :param orelse: The contents of the ``else`` block.
  3575. """
  3576. self.test = test
  3577. if body is not None:
  3578. self.body = body
  3579. if orelse is not None:
  3580. self.orelse = orelse
  3581. @cached_property
  3582. def blockstart_tolineno(self):
  3583. """The line on which the beginning of this block ends.
  3584. :type: int
  3585. """
  3586. return self.test.tolineno
  3587. def block_range(self, lineno):
  3588. """Get a range from the given line number to where this node ends.
  3589. :param lineno: The line number to start the range at.
  3590. :type lineno: int
  3591. :returns: The range of line numbers that this node belongs to,
  3592. starting at the given line number.
  3593. :rtype: tuple(int, int)
  3594. """
  3595. return self._elsed_block_range(lineno, self.orelse)
  3596. def get_children(self):
  3597. yield self.test
  3598. yield from self.body
  3599. yield from self.orelse
  3600. def _get_yield_nodes_skip_lambdas(self):
  3601. """A While node can contain a Yield node in the test"""
  3602. yield from self.test._get_yield_nodes_skip_lambdas()
  3603. yield from super()._get_yield_nodes_skip_lambdas()
  3604. class With(
  3605. _base_nodes.MultiLineWithElseBlockNode,
  3606. _base_nodes.AssignTypeNode,
  3607. _base_nodes.Statement,
  3608. ):
  3609. """Class representing an :class:`ast.With` node.
  3610. >>> import astroid
  3611. >>> node = astroid.extract_node('''
  3612. with open(file_path) as file_:
  3613. print(file_.read())
  3614. ''')
  3615. >>> node
  3616. <With l.2 at 0x7f23b2e4e710>
  3617. """
  3618. _astroid_fields = ("items", "body")
  3619. _other_other_fields = ("type_annotation",)
  3620. _multi_line_block_fields = ("body",)
  3621. def __init__(
  3622. self,
  3623. lineno: int | None = None,
  3624. col_offset: int | None = None,
  3625. parent: NodeNG | None = None,
  3626. *,
  3627. end_lineno: int | None = None,
  3628. end_col_offset: int | None = None,
  3629. ) -> None:
  3630. """
  3631. :param lineno: The line that this node appears on in the source code.
  3632. :param col_offset: The column that this node appears on in the
  3633. source code.
  3634. :param parent: The parent node in the syntax tree.
  3635. :param end_lineno: The last line this node appears on in the source code.
  3636. :param end_col_offset: The end column this node appears on in the
  3637. source code. Note: This is after the last symbol.
  3638. """
  3639. self.items: list[tuple[NodeNG, NodeNG | None]] = []
  3640. """The pairs of context managers and the names they are assigned to."""
  3641. self.body: list[NodeNG] = []
  3642. """The contents of the ``with`` block."""
  3643. self.type_annotation: NodeNG | None = None # can be None
  3644. """If present, this will contain the type annotation passed by a type comment"""
  3645. super().__init__(
  3646. lineno=lineno,
  3647. col_offset=col_offset,
  3648. end_lineno=end_lineno,
  3649. end_col_offset=end_col_offset,
  3650. parent=parent,
  3651. )
  3652. def postinit(
  3653. self,
  3654. items: list[tuple[NodeNG, NodeNG | None]] | None = None,
  3655. body: list[NodeNG] | None = None,
  3656. type_annotation: NodeNG | None = None,
  3657. ) -> None:
  3658. """Do some setup after initialisation.
  3659. :param items: The pairs of context managers and the names
  3660. they are assigned to.
  3661. :param body: The contents of the ``with`` block.
  3662. """
  3663. if items is not None:
  3664. self.items = items
  3665. if body is not None:
  3666. self.body = body
  3667. self.type_annotation = type_annotation
  3668. assigned_stmts: ClassVar[AssignedStmtsCall[With]]
  3669. """Returns the assigned statement (non inferred) according to the assignment type.
  3670. See astroid/protocols.py for actual implementation.
  3671. """
  3672. @cached_property
  3673. def blockstart_tolineno(self):
  3674. """The line on which the beginning of this block ends.
  3675. :type: int
  3676. """
  3677. return self.items[-1][0].tolineno
  3678. def get_children(self):
  3679. """Get the child nodes below this node.
  3680. :returns: The children.
  3681. :rtype: iterable(NodeNG)
  3682. """
  3683. for expr, var in self.items:
  3684. yield expr
  3685. if var:
  3686. yield var
  3687. yield from self.body
  3688. class AsyncWith(With):
  3689. """Asynchronous ``with`` built with the ``async`` keyword."""
  3690. class Yield(NodeNG):
  3691. """Class representing an :class:`ast.Yield` node.
  3692. >>> import astroid
  3693. >>> node = astroid.extract_node('yield True')
  3694. >>> node
  3695. <Yield l.1 at 0x7f23b2e4e5f8>
  3696. """
  3697. _astroid_fields = ("value",)
  3698. def __init__(
  3699. self,
  3700. lineno: int | None = None,
  3701. col_offset: int | None = None,
  3702. parent: NodeNG | None = None,
  3703. *,
  3704. end_lineno: int | None = None,
  3705. end_col_offset: int | None = None,
  3706. ) -> None:
  3707. """
  3708. :param lineno: The line that this node appears on in the source code.
  3709. :param col_offset: The column that this node appears on in the
  3710. source code.
  3711. :param parent: The parent node in the syntax tree.
  3712. :param end_lineno: The last line this node appears on in the source code.
  3713. :param end_col_offset: The end column this node appears on in the
  3714. source code. Note: This is after the last symbol.
  3715. """
  3716. self.value: NodeNG | None = None # can be None
  3717. """The value to yield."""
  3718. super().__init__(
  3719. lineno=lineno,
  3720. col_offset=col_offset,
  3721. end_lineno=end_lineno,
  3722. end_col_offset=end_col_offset,
  3723. parent=parent,
  3724. )
  3725. def postinit(self, value: NodeNG | None = None) -> None:
  3726. """Do some setup after initialisation.
  3727. :param value: The value to yield.
  3728. """
  3729. self.value = value
  3730. def get_children(self):
  3731. if self.value is not None:
  3732. yield self.value
  3733. def _get_yield_nodes_skip_lambdas(self):
  3734. yield self
  3735. class YieldFrom(Yield): # TODO value is required, not optional
  3736. """Class representing an :class:`ast.YieldFrom` node."""
  3737. class DictUnpack(_base_nodes.NoChildrenNode):
  3738. """Represents the unpacking of dicts into dicts using :pep:`448`."""
  3739. class FormattedValue(NodeNG):
  3740. """Class representing an :class:`ast.FormattedValue` node.
  3741. Represents a :pep:`498` format string.
  3742. >>> import astroid
  3743. >>> node = astroid.extract_node('f"Format {type_}"')
  3744. >>> node
  3745. <JoinedStr l.1 at 0x7f23b2e4ed30>
  3746. >>> node.values
  3747. [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]
  3748. """
  3749. _astroid_fields = ("value", "format_spec")
  3750. _other_fields = ("conversion",)
  3751. def __init__(
  3752. self,
  3753. lineno: int | None = None,
  3754. col_offset: int | None = None,
  3755. parent: NodeNG | None = None,
  3756. *,
  3757. end_lineno: int | None = None,
  3758. end_col_offset: int | None = None,
  3759. ) -> None:
  3760. """
  3761. :param lineno: The line that this node appears on in the source code.
  3762. :param col_offset: The column that this node appears on in the
  3763. source code.
  3764. :param parent: The parent node in the syntax tree.
  3765. :param end_lineno: The last line this node appears on in the source code.
  3766. :param end_col_offset: The end column this node appears on in the
  3767. source code. Note: This is after the last symbol.
  3768. """
  3769. self.value: NodeNG
  3770. """The value to be formatted into the string."""
  3771. self.conversion: int
  3772. """The type of formatting to be applied to the value.
  3773. .. seealso::
  3774. :class:`ast.FormattedValue`
  3775. """
  3776. self.format_spec: JoinedStr | None = None
  3777. """The formatting to be applied to the value.
  3778. .. seealso::
  3779. :class:`ast.FormattedValue`
  3780. """
  3781. super().__init__(
  3782. lineno=lineno,
  3783. col_offset=col_offset,
  3784. end_lineno=end_lineno,
  3785. end_col_offset=end_col_offset,
  3786. parent=parent,
  3787. )
  3788. def postinit(
  3789. self,
  3790. *,
  3791. value: NodeNG,
  3792. conversion: int,
  3793. format_spec: JoinedStr | None = None,
  3794. ) -> None:
  3795. """Do some setup after initialisation.
  3796. :param value: The value to be formatted into the string.
  3797. :param conversion: The type of formatting to be applied to the value.
  3798. :param format_spec: The formatting to be applied to the value.
  3799. :type format_spec: JoinedStr or None
  3800. """
  3801. self.value = value
  3802. self.conversion = conversion
  3803. self.format_spec = format_spec
  3804. def get_children(self):
  3805. yield self.value
  3806. if self.format_spec is not None:
  3807. yield self.format_spec
  3808. class JoinedStr(NodeNG):
  3809. """Represents a list of string expressions to be joined.
  3810. >>> import astroid
  3811. >>> node = astroid.extract_node('f"Format {type_}"')
  3812. >>> node
  3813. <JoinedStr l.1 at 0x7f23b2e4ed30>
  3814. """
  3815. _astroid_fields = ("values",)
  3816. def __init__(
  3817. self,
  3818. lineno: int | None = None,
  3819. col_offset: int | None = None,
  3820. parent: NodeNG | None = None,
  3821. *,
  3822. end_lineno: int | None = None,
  3823. end_col_offset: int | None = None,
  3824. ) -> None:
  3825. """
  3826. :param lineno: The line that this node appears on in the source code.
  3827. :param col_offset: The column that this node appears on in the
  3828. source code.
  3829. :param parent: The parent node in the syntax tree.
  3830. :param end_lineno: The last line this node appears on in the source code.
  3831. :param end_col_offset: The end column this node appears on in the
  3832. source code. Note: This is after the last symbol.
  3833. """
  3834. self.values: list[NodeNG] = []
  3835. """The string expressions to be joined.
  3836. :type: list(FormattedValue or Const)
  3837. """
  3838. super().__init__(
  3839. lineno=lineno,
  3840. col_offset=col_offset,
  3841. end_lineno=end_lineno,
  3842. end_col_offset=end_col_offset,
  3843. parent=parent,
  3844. )
  3845. def postinit(self, values: list[NodeNG] | None = None) -> None:
  3846. """Do some setup after initialisation.
  3847. :param value: The string expressions to be joined.
  3848. :type: list(FormattedValue or Const)
  3849. """
  3850. if values is not None:
  3851. self.values = values
  3852. def get_children(self):
  3853. yield from self.values
  3854. class NamedExpr(_base_nodes.AssignTypeNode):
  3855. """Represents the assignment from the assignment expression
  3856. >>> import astroid
  3857. >>> module = astroid.parse('if a := 1: pass')
  3858. >>> module.body[0].test
  3859. <NamedExpr l.1 at 0x7f23b2e4ed30>
  3860. """
  3861. _astroid_fields = ("target", "value")
  3862. optional_assign = True
  3863. """Whether this node optionally assigns a variable.
  3864. Since NamedExpr are not always called they do not always assign."""
  3865. def __init__(
  3866. self,
  3867. lineno: int | None = None,
  3868. col_offset: int | None = None,
  3869. parent: NodeNG | None = None,
  3870. *,
  3871. end_lineno: int | None = None,
  3872. end_col_offset: int | None = None,
  3873. ) -> None:
  3874. """
  3875. :param lineno: The line that this node appears on in the source code.
  3876. :param col_offset: The column that this node appears on in the
  3877. source code.
  3878. :param parent: The parent node in the syntax tree.
  3879. :param end_lineno: The last line this node appears on in the source code.
  3880. :param end_col_offset: The end column this node appears on in the
  3881. source code. Note: This is after the last symbol.
  3882. """
  3883. self.target: NodeNG
  3884. """The assignment target
  3885. :type: Name
  3886. """
  3887. self.value: NodeNG
  3888. """The value that gets assigned in the expression"""
  3889. super().__init__(
  3890. lineno=lineno,
  3891. col_offset=col_offset,
  3892. end_lineno=end_lineno,
  3893. end_col_offset=end_col_offset,
  3894. parent=parent,
  3895. )
  3896. def postinit(self, target: NodeNG, value: NodeNG) -> None:
  3897. self.target = target
  3898. self.value = value
  3899. assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]
  3900. """Returns the assigned statement (non inferred) according to the assignment type.
  3901. See astroid/protocols.py for actual implementation.
  3902. """
  3903. def frame(
  3904. self, *, future: Literal[None, True] = None
  3905. ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:
  3906. """The first parent frame node.
  3907. A frame node is a :class:`Module`, :class:`FunctionDef`,
  3908. or :class:`ClassDef`.
  3909. :returns: The first parent frame node.
  3910. """
  3911. if not self.parent:
  3912. raise ParentMissingError(target=self)
  3913. # For certain parents NamedExpr evaluate to the scope of the parent
  3914. if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
  3915. if not self.parent.parent:
  3916. raise ParentMissingError(target=self.parent)
  3917. if not self.parent.parent.parent:
  3918. raise ParentMissingError(target=self.parent.parent)
  3919. return self.parent.parent.parent.frame(future=True)
  3920. return self.parent.frame(future=True)
  3921. def scope(self) -> LocalsDictNodeNG:
  3922. """The first parent node defining a new scope.
  3923. These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  3924. :returns: The first parent scope node.
  3925. """
  3926. if not self.parent:
  3927. raise ParentMissingError(target=self)
  3928. # For certain parents NamedExpr evaluate to the scope of the parent
  3929. if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
  3930. if not self.parent.parent:
  3931. raise ParentMissingError(target=self.parent)
  3932. if not self.parent.parent.parent:
  3933. raise ParentMissingError(target=self.parent.parent)
  3934. return self.parent.parent.parent.scope()
  3935. return self.parent.scope()
  3936. def set_local(self, name: str, stmt: NodeNG) -> None:
  3937. """Define that the given name is declared in the given statement node.
  3938. NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their
  3939. parent's parent scope. So we add to their frame's locals.
  3940. .. seealso:: :meth:`scope`
  3941. :param name: The name that is being defined.
  3942. :param stmt: The statement that defines the given name.
  3943. """
  3944. self.frame(future=True).set_local(name, stmt)
  3945. class Unknown(_base_nodes.AssignTypeNode):
  3946. """This node represents a node in a constructed AST where
  3947. introspection is not possible. At the moment, it's only used in
  3948. the args attribute of FunctionDef nodes where function signature
  3949. introspection failed.
  3950. """
  3951. name = "Unknown"
  3952. def qname(self) -> Literal["Unknown"]:
  3953. return "Unknown"
  3954. def _infer(self, context: InferenceContext | None = None, **kwargs):
  3955. """Inference on an Unknown node immediately terminates."""
  3956. yield util.Uninferable
  3957. class EvaluatedObject(NodeNG):
  3958. """Contains an object that has already been inferred
  3959. This class is useful to pre-evaluate a particular node,
  3960. with the resulting class acting as the non-evaluated node.
  3961. """
  3962. name = "EvaluatedObject"
  3963. _astroid_fields = ("original",)
  3964. _other_fields = ("value",)
  3965. def __init__(self, original: NodeNG, value: NodeNG | util.UninferableBase) -> None:
  3966. self.original: NodeNG = original
  3967. """The original node that has already been evaluated"""
  3968. self.value: NodeNG | util.UninferableBase = value
  3969. """The inferred value"""
  3970. super().__init__(
  3971. lineno=self.original.lineno,
  3972. col_offset=self.original.col_offset,
  3973. parent=self.original.parent,
  3974. )
  3975. def _infer(
  3976. self, context: InferenceContext | None = None, **kwargs: Any
  3977. ) -> Generator[NodeNG | util.UninferableBase, None, None]:
  3978. yield self.value
  3979. # Pattern matching #######################################################
  3980. class Match(_base_nodes.Statement, _base_nodes.MultiLineBlockNode):
  3981. """Class representing a :class:`ast.Match` node.
  3982. >>> import astroid
  3983. >>> node = astroid.extract_node('''
  3984. match x:
  3985. case 200:
  3986. ...
  3987. case _:
  3988. ...
  3989. ''')
  3990. >>> node
  3991. <Match l.2 at 0x10c24e170>
  3992. """
  3993. _astroid_fields = ("subject", "cases")
  3994. _multi_line_block_fields = ("cases",)
  3995. def __init__(
  3996. self,
  3997. lineno: int | None = None,
  3998. col_offset: int | None = None,
  3999. parent: NodeNG | None = None,
  4000. *,
  4001. end_lineno: int | None = None,
  4002. end_col_offset: int | None = None,
  4003. ) -> None:
  4004. self.subject: NodeNG
  4005. self.cases: list[MatchCase]
  4006. super().__init__(
  4007. lineno=lineno,
  4008. col_offset=col_offset,
  4009. end_lineno=end_lineno,
  4010. end_col_offset=end_col_offset,
  4011. parent=parent,
  4012. )
  4013. def postinit(
  4014. self,
  4015. *,
  4016. subject: NodeNG,
  4017. cases: list[MatchCase],
  4018. ) -> None:
  4019. self.subject = subject
  4020. self.cases = cases
  4021. class Pattern(NodeNG):
  4022. """Base class for all Pattern nodes."""
  4023. class MatchCase(_base_nodes.MultiLineBlockNode):
  4024. """Class representing a :class:`ast.match_case` node.
  4025. >>> import astroid
  4026. >>> node = astroid.extract_node('''
  4027. match x:
  4028. case 200:
  4029. ...
  4030. ''')
  4031. >>> node.cases[0]
  4032. <MatchCase l.3 at 0x10c24e590>
  4033. """
  4034. _astroid_fields = ("pattern", "guard", "body")
  4035. _multi_line_block_fields = ("body",)
  4036. lineno: None
  4037. col_offset: None
  4038. end_lineno: None
  4039. end_col_offset: None
  4040. def __init__(self, *, parent: NodeNG | None = None) -> None:
  4041. self.pattern: Pattern
  4042. self.guard: NodeNG | None
  4043. self.body: list[NodeNG]
  4044. super().__init__(parent=parent)
  4045. def postinit(
  4046. self,
  4047. *,
  4048. pattern: Pattern,
  4049. guard: NodeNG | None,
  4050. body: list[NodeNG],
  4051. ) -> None:
  4052. self.pattern = pattern
  4053. self.guard = guard
  4054. self.body = body
  4055. class MatchValue(Pattern):
  4056. """Class representing a :class:`ast.MatchValue` node.
  4057. >>> import astroid
  4058. >>> node = astroid.extract_node('''
  4059. match x:
  4060. case 200:
  4061. ...
  4062. ''')
  4063. >>> node.cases[0].pattern
  4064. <MatchValue l.3 at 0x10c24e200>
  4065. """
  4066. _astroid_fields = ("value",)
  4067. def __init__(
  4068. self,
  4069. lineno: int | None = None,
  4070. col_offset: int | None = None,
  4071. parent: NodeNG | None = None,
  4072. *,
  4073. end_lineno: int | None = None,
  4074. end_col_offset: int | None = None,
  4075. ) -> None:
  4076. self.value: NodeNG
  4077. super().__init__(
  4078. lineno=lineno,
  4079. col_offset=col_offset,
  4080. end_lineno=end_lineno,
  4081. end_col_offset=end_col_offset,
  4082. parent=parent,
  4083. )
  4084. def postinit(self, *, value: NodeNG) -> None:
  4085. self.value = value
  4086. class MatchSingleton(Pattern):
  4087. """Class representing a :class:`ast.MatchSingleton` node.
  4088. >>> import astroid
  4089. >>> node = astroid.extract_node('''
  4090. match x:
  4091. case True:
  4092. ...
  4093. case False:
  4094. ...
  4095. case None:
  4096. ...
  4097. ''')
  4098. >>> node.cases[0].pattern
  4099. <MatchSingleton l.3 at 0x10c2282e0>
  4100. >>> node.cases[1].pattern
  4101. <MatchSingleton l.5 at 0x10c228af0>
  4102. >>> node.cases[2].pattern
  4103. <MatchSingleton l.7 at 0x10c229f90>
  4104. """
  4105. _other_fields = ("value",)
  4106. def __init__(
  4107. self,
  4108. *,
  4109. value: Literal[True, False, None],
  4110. lineno: int | None = None,
  4111. col_offset: int | None = None,
  4112. end_lineno: int | None = None,
  4113. end_col_offset: int | None = None,
  4114. parent: NodeNG | None = None,
  4115. ) -> None:
  4116. self.value = value
  4117. super().__init__(
  4118. lineno=lineno,
  4119. col_offset=col_offset,
  4120. end_lineno=end_lineno,
  4121. end_col_offset=end_col_offset,
  4122. parent=parent,
  4123. )
  4124. class MatchSequence(Pattern):
  4125. """Class representing a :class:`ast.MatchSequence` node.
  4126. >>> import astroid
  4127. >>> node = astroid.extract_node('''
  4128. match x:
  4129. case [1, 2]:
  4130. ...
  4131. case (1, 2, *_):
  4132. ...
  4133. ''')
  4134. >>> node.cases[0].pattern
  4135. <MatchSequence l.3 at 0x10ca80d00>
  4136. >>> node.cases[1].pattern
  4137. <MatchSequence l.5 at 0x10ca80b20>
  4138. """
  4139. _astroid_fields = ("patterns",)
  4140. def __init__(
  4141. self,
  4142. lineno: int | None = None,
  4143. col_offset: int | None = None,
  4144. parent: NodeNG | None = None,
  4145. *,
  4146. end_lineno: int | None = None,
  4147. end_col_offset: int | None = None,
  4148. ) -> None:
  4149. self.patterns: list[Pattern]
  4150. super().__init__(
  4151. lineno=lineno,
  4152. col_offset=col_offset,
  4153. end_lineno=end_lineno,
  4154. end_col_offset=end_col_offset,
  4155. parent=parent,
  4156. )
  4157. def postinit(self, *, patterns: list[Pattern]) -> None:
  4158. self.patterns = patterns
  4159. class MatchMapping(_base_nodes.AssignTypeNode, Pattern):
  4160. """Class representing a :class:`ast.MatchMapping` node.
  4161. >>> import astroid
  4162. >>> node = astroid.extract_node('''
  4163. match x:
  4164. case {1: "Hello", 2: "World", 3: _, **rest}:
  4165. ...
  4166. ''')
  4167. >>> node.cases[0].pattern
  4168. <MatchMapping l.3 at 0x10c8a8850>
  4169. """
  4170. _astroid_fields = ("keys", "patterns", "rest")
  4171. def __init__(
  4172. self,
  4173. lineno: int | None = None,
  4174. col_offset: int | None = None,
  4175. parent: NodeNG | None = None,
  4176. *,
  4177. end_lineno: int | None = None,
  4178. end_col_offset: int | None = None,
  4179. ) -> None:
  4180. self.keys: list[NodeNG]
  4181. self.patterns: list[Pattern]
  4182. self.rest: AssignName | None
  4183. super().__init__(
  4184. lineno=lineno,
  4185. col_offset=col_offset,
  4186. end_lineno=end_lineno,
  4187. end_col_offset=end_col_offset,
  4188. parent=parent,
  4189. )
  4190. def postinit(
  4191. self,
  4192. *,
  4193. keys: list[NodeNG],
  4194. patterns: list[Pattern],
  4195. rest: AssignName | None,
  4196. ) -> None:
  4197. self.keys = keys
  4198. self.patterns = patterns
  4199. self.rest = rest
  4200. assigned_stmts: ClassVar[
  4201. Callable[
  4202. [
  4203. MatchMapping,
  4204. AssignName,
  4205. InferenceContext | None,
  4206. None,
  4207. ],
  4208. Generator[NodeNG, None, None],
  4209. ]
  4210. ]
  4211. """Returns the assigned statement (non inferred) according to the assignment type.
  4212. See astroid/protocols.py for actual implementation.
  4213. """
  4214. class MatchClass(Pattern):
  4215. """Class representing a :class:`ast.MatchClass` node.
  4216. >>> import astroid
  4217. >>> node = astroid.extract_node('''
  4218. match x:
  4219. case Point2D(0, 0):
  4220. ...
  4221. case Point3D(x=0, y=0, z=0):
  4222. ...
  4223. ''')
  4224. >>> node.cases[0].pattern
  4225. <MatchClass l.3 at 0x10ca83940>
  4226. >>> node.cases[1].pattern
  4227. <MatchClass l.5 at 0x10ca80880>
  4228. """
  4229. _astroid_fields = ("cls", "patterns", "kwd_patterns")
  4230. _other_fields = ("kwd_attrs",)
  4231. def __init__(
  4232. self,
  4233. lineno: int | None = None,
  4234. col_offset: int | None = None,
  4235. parent: NodeNG | None = None,
  4236. *,
  4237. end_lineno: int | None = None,
  4238. end_col_offset: int | None = None,
  4239. ) -> None:
  4240. self.cls: NodeNG
  4241. self.patterns: list[Pattern]
  4242. self.kwd_attrs: list[str]
  4243. self.kwd_patterns: list[Pattern]
  4244. super().__init__(
  4245. lineno=lineno,
  4246. col_offset=col_offset,
  4247. end_lineno=end_lineno,
  4248. end_col_offset=end_col_offset,
  4249. parent=parent,
  4250. )
  4251. def postinit(
  4252. self,
  4253. *,
  4254. cls: NodeNG,
  4255. patterns: list[Pattern],
  4256. kwd_attrs: list[str],
  4257. kwd_patterns: list[Pattern],
  4258. ) -> None:
  4259. self.cls = cls
  4260. self.patterns = patterns
  4261. self.kwd_attrs = kwd_attrs
  4262. self.kwd_patterns = kwd_patterns
  4263. class MatchStar(_base_nodes.AssignTypeNode, Pattern):
  4264. """Class representing a :class:`ast.MatchStar` node.
  4265. >>> import astroid
  4266. >>> node = astroid.extract_node('''
  4267. match x:
  4268. case [1, *_]:
  4269. ...
  4270. ''')
  4271. >>> node.cases[0].pattern.patterns[1]
  4272. <MatchStar l.3 at 0x10ca809a0>
  4273. """
  4274. _astroid_fields = ("name",)
  4275. def __init__(
  4276. self,
  4277. lineno: int | None = None,
  4278. col_offset: int | None = None,
  4279. parent: NodeNG | None = None,
  4280. *,
  4281. end_lineno: int | None = None,
  4282. end_col_offset: int | None = None,
  4283. ) -> None:
  4284. self.name: AssignName | None
  4285. super().__init__(
  4286. lineno=lineno,
  4287. col_offset=col_offset,
  4288. end_lineno=end_lineno,
  4289. end_col_offset=end_col_offset,
  4290. parent=parent,
  4291. )
  4292. def postinit(self, *, name: AssignName | None) -> None:
  4293. self.name = name
  4294. assigned_stmts: ClassVar[
  4295. Callable[
  4296. [
  4297. MatchStar,
  4298. AssignName,
  4299. InferenceContext | None,
  4300. None,
  4301. ],
  4302. Generator[NodeNG, None, None],
  4303. ]
  4304. ]
  4305. """Returns the assigned statement (non inferred) according to the assignment type.
  4306. See astroid/protocols.py for actual implementation.
  4307. """
  4308. class MatchAs(_base_nodes.AssignTypeNode, Pattern):
  4309. """Class representing a :class:`ast.MatchAs` node.
  4310. >>> import astroid
  4311. >>> node = astroid.extract_node('''
  4312. match x:
  4313. case [1, a]:
  4314. ...
  4315. case {'key': b}:
  4316. ...
  4317. case Point2D(0, 0) as c:
  4318. ...
  4319. case d:
  4320. ...
  4321. ''')
  4322. >>> node.cases[0].pattern.patterns[1]
  4323. <MatchAs l.3 at 0x10d0b2da0>
  4324. >>> node.cases[1].pattern.patterns[0]
  4325. <MatchAs l.5 at 0x10d0b2920>
  4326. >>> node.cases[2].pattern
  4327. <MatchAs l.7 at 0x10d0b06a0>
  4328. >>> node.cases[3].pattern
  4329. <MatchAs l.9 at 0x10d09b880>
  4330. """
  4331. _astroid_fields = ("pattern", "name")
  4332. def __init__(
  4333. self,
  4334. lineno: int | None = None,
  4335. col_offset: int | None = None,
  4336. parent: NodeNG | None = None,
  4337. *,
  4338. end_lineno: int | None = None,
  4339. end_col_offset: int | None = None,
  4340. ) -> None:
  4341. self.pattern: Pattern | None
  4342. self.name: AssignName | None
  4343. super().__init__(
  4344. lineno=lineno,
  4345. col_offset=col_offset,
  4346. end_lineno=end_lineno,
  4347. end_col_offset=end_col_offset,
  4348. parent=parent,
  4349. )
  4350. def postinit(
  4351. self,
  4352. *,
  4353. pattern: Pattern | None,
  4354. name: AssignName | None,
  4355. ) -> None:
  4356. self.pattern = pattern
  4357. self.name = name
  4358. assigned_stmts: ClassVar[
  4359. Callable[
  4360. [
  4361. MatchAs,
  4362. AssignName,
  4363. InferenceContext | None,
  4364. None,
  4365. ],
  4366. Generator[NodeNG, None, None],
  4367. ]
  4368. ]
  4369. """Returns the assigned statement (non inferred) according to the assignment type.
  4370. See astroid/protocols.py for actual implementation.
  4371. """
  4372. class MatchOr(Pattern):
  4373. """Class representing a :class:`ast.MatchOr` node.
  4374. >>> import astroid
  4375. >>> node = astroid.extract_node('''
  4376. match x:
  4377. case 400 | 401 | 402:
  4378. ...
  4379. ''')
  4380. >>> node.cases[0].pattern
  4381. <MatchOr l.3 at 0x10d0b0b50>
  4382. """
  4383. _astroid_fields = ("patterns",)
  4384. def __init__(
  4385. self,
  4386. lineno: int | None = None,
  4387. col_offset: int | None = None,
  4388. parent: NodeNG | None = None,
  4389. *,
  4390. end_lineno: int | None = None,
  4391. end_col_offset: int | None = None,
  4392. ) -> None:
  4393. self.patterns: list[Pattern]
  4394. super().__init__(
  4395. lineno=lineno,
  4396. col_offset=col_offset,
  4397. end_lineno=end_lineno,
  4398. end_col_offset=end_col_offset,
  4399. parent=parent,
  4400. )
  4401. def postinit(self, *, patterns: list[Pattern]) -> None:
  4402. self.patterns = patterns
  4403. # constants ##############################################################
  4404. # The _proxied attribute of all container types (List, Tuple, etc.)
  4405. # are set during bootstrapping by _astroid_bootstrapping().
  4406. CONST_CLS: dict[type, type[NodeNG]] = {
  4407. list: List,
  4408. tuple: Tuple,
  4409. dict: Dict,
  4410. set: Set,
  4411. type(None): Const,
  4412. type(NotImplemented): Const,
  4413. type(...): Const,
  4414. bool: Const,
  4415. int: Const,
  4416. float: Const,
  4417. complex: Const,
  4418. str: Const,
  4419. bytes: Const,
  4420. }
  4421. def _create_basic_elements(
  4422. value: Iterable[Any], node: List | Set | Tuple
  4423. ) -> list[NodeNG]:
  4424. """Create a list of nodes to function as the elements of a new node."""
  4425. elements: list[NodeNG] = []
  4426. for element in value:
  4427. element_node = const_factory(element)
  4428. element_node.parent = node
  4429. elements.append(element_node)
  4430. return elements
  4431. def _create_dict_items(
  4432. values: Mapping[Any, Any], node: Dict
  4433. ) -> list[tuple[SuccessfulInferenceResult, SuccessfulInferenceResult]]:
  4434. """Create a list of node pairs to function as the items of a new dict node."""
  4435. elements: list[tuple[SuccessfulInferenceResult, SuccessfulInferenceResult]] = []
  4436. for key, value in values.items():
  4437. key_node = const_factory(key)
  4438. key_node.parent = node
  4439. value_node = const_factory(value)
  4440. value_node.parent = node
  4441. elements.append((key_node, value_node))
  4442. return elements
  4443. def const_factory(value: Any) -> ConstFactoryResult:
  4444. """Return an astroid node for a python value."""
  4445. assert not isinstance(value, NodeNG)
  4446. # This only handles instances of the CONST types. Any
  4447. # subclasses get inferred as EmptyNode.
  4448. # TODO: See if we should revisit these with the normal builder.
  4449. if value.__class__ not in CONST_CLS:
  4450. node = EmptyNode()
  4451. node.object = value
  4452. return node
  4453. instance: List | Set | Tuple | Dict
  4454. initializer_cls = CONST_CLS[value.__class__]
  4455. if issubclass(initializer_cls, (List, Set, Tuple)):
  4456. instance = initializer_cls()
  4457. instance.postinit(_create_basic_elements(value, instance))
  4458. return instance
  4459. if issubclass(initializer_cls, Dict):
  4460. instance = initializer_cls()
  4461. instance.postinit(_create_dict_items(value, instance))
  4462. return instance
  4463. return Const(value)