node_classes.py 163 KB

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