12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337 |
- # Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
- # Copyright (c) 2013-2014 Google, Inc.
- # Copyright (c) 2014-2016 Claudiu Popa <pcmanticore@gmail.com>
- # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
- # Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru>
- # Copyright (c) 2015 Rene Zhang <rz99@cornell.edu>
-
- # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
- # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
-
- """tests for the astroid inference capabilities
- """
- # pylint: disable=too-many-lines
- import os
- import sys
- from functools import partial
- import unittest
- import warnings
-
- import six
-
- from astroid import InferenceError, builder, nodes
- from astroid.builder import parse, extract_node
- from astroid.inference import infer_end as inference_infer_end
- from astroid.bases import Instance, BoundMethod, UnboundMethod,\
- BUILTINS
- from astroid import arguments
- from astroid import decorators as decoratorsmod
- from astroid import exceptions
- from astroid import helpers
- from astroid import objects
- from astroid import test_utils
- from astroid import util
- from astroid.tests import resources
-
-
- def get_node_of_class(start_from, klass):
- return next(start_from.nodes_of_class(klass))
-
- builder = builder.AstroidBuilder()
-
- if sys.version_info < (3, 0):
- EXC_MODULE = 'exceptions'
- BOOL_SPECIAL_METHOD = '__nonzero__'
- else:
- EXC_MODULE = BUILTINS
- BOOL_SPECIAL_METHOD = '__bool__'
-
-
- class InferenceUtilsTest(unittest.TestCase):
-
- def test_path_wrapper(self):
- def infer_default(self, *args):
- raise InferenceError
- infer_default = decoratorsmod.path_wrapper(infer_default)
- infer_end = decoratorsmod.path_wrapper(inference_infer_end)
- with self.assertRaises(InferenceError):
- next(infer_default(1))
- self.assertEqual(next(infer_end(1)), 1)
-
-
- def _assertInferElts(node_type, self, node, elts):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, node_type)
- self.assertEqual(sorted(elt.value for elt in inferred.elts),
- elts)
-
- def partialmethod(func, arg):
- """similar to functools.partial but return a lambda instead of a class so returned value may be
- turned into a method.
- """
- return lambda *args, **kwargs: func(arg, *args, **kwargs)
-
- class InferenceTest(resources.SysPathSetup, unittest.TestCase):
-
- # additional assertInfer* method for builtin types
-
- def assertInferConst(self, node, expected):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, expected)
-
- def assertInferDict(self, node, expected):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Dict)
-
- elts = set([(key.value, value.value)
- for (key, value) in inferred.items])
- self.assertEqual(sorted(elts), sorted(expected.items()))
-
- assertInferTuple = partialmethod(_assertInferElts, nodes.Tuple)
- assertInferList = partialmethod(_assertInferElts, nodes.List)
- assertInferSet = partialmethod(_assertInferElts, nodes.Set)
- assertInferFrozenSet = partialmethod(_assertInferElts, objects.FrozenSet)
-
- CODE = '''
- class C(object):
- "new style"
- attr = 4
-
- def meth1(self, arg1, optarg=0):
- var = object()
- print ("yo", arg1, optarg)
- self.iattr = "hop"
- return var
-
- def meth2(self):
- self.meth1(*self.meth3)
-
- def meth3(self, d=attr):
- b = self.attr
- c = self.iattr
- return b, c
-
- ex = Exception("msg")
- v = C().meth1(1)
- m_unbound = C.meth1
- m_bound = C().meth1
- a, b, c = ex, 1, "bonjour"
- [d, e, f] = [ex, 1.0, ("bonjour", v)]
- g, h = f
- i, (j, k) = "glup", f
-
- a, b= b, a # Gasp !
- '''
-
- ast = parse(CODE, __name__)
-
- def test_infer_abstract_property_return_values(self):
- module = parse('''
- import abc
-
- class A(object):
- @abc.abstractproperty
- def test(self):
- return 42
-
- a = A()
- x = a.test
- ''')
- inferred = next(module['x'].infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def test_module_inference(self):
- inferred = self.ast.infer()
- obj = next(inferred)
- self.assertEqual(obj.name, __name__)
- self.assertEqual(obj.root().name, __name__)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_class_inference(self):
- inferred = self.ast['C'].infer()
- obj = next(inferred)
- self.assertEqual(obj.name, 'C')
- self.assertEqual(obj.root().name, __name__)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_function_inference(self):
- inferred = self.ast['C']['meth1'].infer()
- obj = next(inferred)
- self.assertEqual(obj.name, 'meth1')
- self.assertEqual(obj.root().name, __name__)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_builtin_name_inference(self):
- inferred = self.ast['C']['meth1']['var'].infer()
- var = next(inferred)
- self.assertEqual(var.name, 'object')
- self.assertEqual(var.root().name, BUILTINS)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_tupleassign_name_inference(self):
- inferred = self.ast['a'].infer()
- exc = next(inferred)
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['b'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 1)
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['c'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "bonjour")
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_listassign_name_inference(self):
- inferred = self.ast['d'].infer()
- exc = next(inferred)
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['e'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 1.0)
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['f'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Tuple)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_advanced_tupleassign_name_inference1(self):
- inferred = self.ast['g'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "bonjour")
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['h'].infer()
- var = next(inferred)
- self.assertEqual(var.name, 'object')
- self.assertEqual(var.root().name, BUILTINS)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_advanced_tupleassign_name_inference2(self):
- inferred = self.ast['i'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, u"glup")
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['j'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "bonjour")
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast['k'].infer()
- var = next(inferred)
- self.assertEqual(var.name, 'object')
- self.assertEqual(var.root().name, BUILTINS)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_swap_assign_inference(self):
- inferred = self.ast.locals['a'][1].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 1)
- self.assertRaises(StopIteration, partial(next, inferred))
- inferred = self.ast.locals['b'][1].infer()
- exc = next(inferred)
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_getattr_inference1(self):
- inferred = self.ast['ex'].infer()
- exc = next(inferred)
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_getattr_inference2(self):
- inferred = get_node_of_class(self.ast['C']['meth2'], nodes.Attribute).infer()
- meth1 = next(inferred)
- self.assertEqual(meth1.name, 'meth1')
- self.assertEqual(meth1.root().name, __name__)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_getattr_inference3(self):
- inferred = self.ast['C']['meth3']['b'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 4)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_getattr_inference4(self):
- inferred = self.ast['C']['meth3']['c'].infer()
- const = next(inferred)
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "hop")
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_callfunc_inference(self):
- inferred = self.ast['v'].infer()
- meth1 = next(inferred)
- self.assertIsInstance(meth1, Instance)
- self.assertEqual(meth1.name, 'object')
- self.assertEqual(meth1.root().name, BUILTINS)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_unbound_method_inference(self):
- inferred = self.ast['m_unbound'].infer()
- meth1 = next(inferred)
- self.assertIsInstance(meth1, UnboundMethod)
- self.assertEqual(meth1.name, 'meth1')
- self.assertEqual(meth1.parent.frame().name, 'C')
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_bound_method_inference(self):
- inferred = self.ast['m_bound'].infer()
- meth1 = next(inferred)
- self.assertIsInstance(meth1, BoundMethod)
- self.assertEqual(meth1.name, 'meth1')
- self.assertEqual(meth1.parent.frame().name, 'C')
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_args_default_inference1(self):
- optarg = test_utils.get_name_node(self.ast['C']['meth1'], 'optarg')
- inferred = optarg.infer()
- obj1 = next(inferred)
- self.assertIsInstance(obj1, nodes.Const)
- self.assertEqual(obj1.value, 0)
- obj1 = next(inferred)
- self.assertIs(obj1, util.Uninferable, obj1)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_args_default_inference2(self):
- inferred = self.ast['C']['meth3'].ilookup('d')
- obj1 = next(inferred)
- self.assertIsInstance(obj1, nodes.Const)
- self.assertEqual(obj1.value, 4)
- obj1 = next(inferred)
- self.assertIs(obj1, util.Uninferable, obj1)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_inference_restrictions(self):
- inferred = test_utils.get_name_node(self.ast['C']['meth1'], 'arg1').infer()
- obj1 = next(inferred)
- self.assertIs(obj1, util.Uninferable, obj1)
- self.assertRaises(StopIteration, partial(next, inferred))
-
- def test_ancestors_inference(self):
- code = '''
- class A(object): #@
- pass
-
- class A(A): #@
- pass
- '''
- a1, a2 = extract_node(code, __name__)
- a2_ancestors = list(a2.ancestors())
- self.assertEqual(len(a2_ancestors), 2)
- self.assertIs(a2_ancestors[0], a1)
-
- def test_ancestors_inference2(self):
- code = '''
- class A(object): #@
- pass
-
- class B(A): #@
- pass
-
- class A(B): #@
- pass
- '''
- a1, b, a2 = extract_node(code, __name__)
- a2_ancestors = list(a2.ancestors())
- self.assertEqual(len(a2_ancestors), 3)
- self.assertIs(a2_ancestors[0], b)
- self.assertIs(a2_ancestors[1], a1)
-
- def test_f_arg_f(self):
- code = '''
- def f(f=1):
- return f
-
- a = f()
- '''
- ast = parse(code, __name__)
- a = ast['a']
- a_inferred = a.inferred()
- self.assertEqual(a_inferred[0].value, 1)
- self.assertEqual(len(a_inferred), 1)
-
- def test_infered_warning(self):
- code = '''
- def f(f=1):
- return f
-
- a = f()
- '''
- ast = parse(code, __name__)
- a = ast['a']
-
- with warnings.catch_warnings(record=True) as w:
- with test_utils.enable_warning(PendingDeprecationWarning):
- a.infered()
- self.assertIsInstance(w[0].message, PendingDeprecationWarning)
-
- def test_exc_ancestors(self):
- code = '''
- def f():
- raise __(NotImplementedError)
- '''
- error = extract_node(code, __name__)
- nie = error.inferred()[0]
- self.assertIsInstance(nie, nodes.ClassDef)
- nie_ancestors = [c.name for c in nie.ancestors()]
- if sys.version_info < (3, 0):
- expected = ['RuntimeError', 'StandardError',
- 'Exception', 'BaseException', 'object']
- self.assertEqual(nie_ancestors, expected)
- else:
- expected = ['RuntimeError', 'Exception', 'BaseException', 'object']
- self.assertEqual(nie_ancestors, expected)
-
- def test_except_inference(self):
- code = '''
- try:
- print (hop)
- except NameError as ex:
- ex1 = ex
- except Exception as ex:
- ex2 = ex
- raise
- '''
- ast = parse(code, __name__)
- ex1 = ast['ex1']
- ex1_infer = ex1.infer()
- ex1 = next(ex1_infer)
- self.assertIsInstance(ex1, Instance)
- self.assertEqual(ex1.name, 'NameError')
- self.assertRaises(StopIteration, partial(next, ex1_infer))
- ex2 = ast['ex2']
- ex2_infer = ex2.infer()
- ex2 = next(ex2_infer)
- self.assertIsInstance(ex2, Instance)
- self.assertEqual(ex2.name, 'Exception')
- self.assertRaises(StopIteration, partial(next, ex2_infer))
-
- def test_del1(self):
- code = '''
- del undefined_attr
- '''
- delete = extract_node(code, __name__)
- self.assertRaises(InferenceError, delete.infer)
-
- def test_del2(self):
- code = '''
- a = 1
- b = a
- del a
- c = a
- a = 2
- d = a
- '''
- ast = parse(code, __name__)
- n = ast['b']
- n_infer = n.infer()
- inferred = next(n_infer)
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 1)
- self.assertRaises(StopIteration, partial(next, n_infer))
- n = ast['c']
- n_infer = n.infer()
- self.assertRaises(InferenceError, partial(next, n_infer))
- n = ast['d']
- n_infer = n.infer()
- inferred = next(n_infer)
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 2)
- self.assertRaises(StopIteration, partial(next, n_infer))
-
- def test_builtin_types(self):
- code = '''
- l = [1]
- t = (2,)
- d = {}
- s = ''
- s2 = '_'
- '''
- ast = parse(code, __name__)
- n = ast['l']
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.List)
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.getitem(nodes.Const(0)).value, 1)
- self.assertIsInstance(inferred._proxied, nodes.ClassDef)
- self.assertEqual(inferred._proxied.name, 'list')
- self.assertIn('append', inferred._proxied.locals)
- n = ast['t']
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.Tuple)
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.getitem(nodes.Const(0)).value, 2)
- self.assertIsInstance(inferred._proxied, nodes.ClassDef)
- self.assertEqual(inferred._proxied.name, 'tuple')
- n = ast['d']
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.Dict)
- self.assertIsInstance(inferred, Instance)
- self.assertIsInstance(inferred._proxied, nodes.ClassDef)
- self.assertEqual(inferred._proxied.name, 'dict')
- self.assertIn('get', inferred._proxied.locals)
- n = ast['s']
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'str')
- self.assertIn('lower', inferred._proxied.locals)
- n = ast['s2']
- inferred = next(n.infer())
- self.assertEqual(inferred.getitem(nodes.Const(0)).value, '_')
-
- code = 's = {1}'
- ast = parse(code, __name__)
- n = ast['s']
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.Set)
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'set')
- self.assertIn('remove', inferred._proxied.locals)
-
- @test_utils.require_version(maxver='3.0')
- def test_unicode_type(self):
- code = '''u = u""'''
- ast = parse(code, __name__)
- n = ast['u']
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'unicode')
- self.assertIn('lower', inferred._proxied.locals)
-
- @unittest.expectedFailure
- def test_descriptor_are_callable(self):
- code = '''
- class A:
- statm = staticmethod(open)
- clsm = classmethod('whatever')
- '''
- ast = parse(code, __name__)
- statm = next(ast['A'].igetattr('statm'))
- self.assertTrue(statm.callable())
- clsm = next(ast['A'].igetattr('clsm'))
- self.assertFalse(clsm.callable())
-
- def test_bt_ancestor_crash(self):
- code = '''
- class Warning(Warning):
- pass
- '''
- ast = parse(code, __name__)
- w = ast['Warning']
- ancestors = w.ancestors()
- ancestor = next(ancestors)
- self.assertEqual(ancestor.name, 'Warning')
- self.assertEqual(ancestor.root().name, EXC_MODULE)
- ancestor = next(ancestors)
- self.assertEqual(ancestor.name, 'Exception')
- self.assertEqual(ancestor.root().name, EXC_MODULE)
- ancestor = next(ancestors)
- self.assertEqual(ancestor.name, 'BaseException')
- self.assertEqual(ancestor.root().name, EXC_MODULE)
- ancestor = next(ancestors)
- self.assertEqual(ancestor.name, 'object')
- self.assertEqual(ancestor.root().name, BUILTINS)
- self.assertRaises(StopIteration, partial(next, ancestors))
-
- def test_qqch(self):
- code = '''
- from astroid.modutils import load_module_from_name
- xxx = load_module_from_name('__pkginfo__')
- '''
- ast = parse(code, __name__)
- xxx = ast['xxx']
- self.assertSetEqual({n.__class__ for n in xxx.inferred()},
- {nodes.Const, util.Uninferable.__class__})
-
- def test_method_argument(self):
- code = '''
- class ErudiEntitySchema:
- """a entity has a type, a set of subject and or object relations"""
- def __init__(self, e_type, **kwargs):
- kwargs['e_type'] = e_type.capitalize().encode()
-
- def meth(self, e_type, *args, **kwargs):
- kwargs['e_type'] = e_type.capitalize().encode()
- print(args)
- '''
- ast = parse(code, __name__)
- arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'e_type')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [util.Uninferable.__class__])
- arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'kwargs')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [nodes.Dict])
- arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'e_type')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [util.Uninferable.__class__])
- arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'args')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [nodes.Tuple])
- arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'kwargs')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [nodes.Dict])
-
- def test_tuple_then_list(self):
- code = '''
- def test_view(rql, vid, tags=()):
- tags = list(tags)
- __(tags).append(vid)
- '''
- name = extract_node(code, __name__)
- it = name.infer()
- tags = next(it)
- self.assertIsInstance(tags, nodes.List)
- self.assertEqual(tags.elts, [])
- with self.assertRaises(StopIteration):
- next(it)
-
- def test_mulassign_inference(self):
- code = '''
- def first_word(line):
- """Return the first word of a line"""
-
- return line.split()[0]
-
- def last_word(line):
- """Return last word of a line"""
-
- return line.split()[-1]
-
- def process_line(word_pos):
- """Silly function: returns (ok, callable) based on argument.
-
- For test purpose only.
- """
-
- if word_pos > 0:
- return (True, first_word)
- elif word_pos < 0:
- return (True, last_word)
- else:
- return (False, None)
-
- if __name__ == '__main__':
-
- line_number = 0
- for a_line in file('test_callable.py'):
- tupletest = process_line(line_number)
- (ok, fct) = process_line(line_number)
- if ok:
- fct(a_line)
- '''
- ast = parse(code, __name__)
- self.assertEqual(len(list(ast['process_line'].infer_call_result(None))), 3)
- self.assertEqual(len(list(ast['tupletest'].infer())), 3)
- values = ['<FunctionDef.first_word', '<FunctionDef.last_word',
- '<Const.NoneType']
- self.assertTrue(all(repr(inferred).startswith(value) for inferred, value
- in zip(ast['fct'].infer(), values)))
-
- def test_float_complex_ambiguity(self):
- code = '''
- def no_conjugate_member(magic_flag): #@
- """should not raise E1101 on something.conjugate"""
- if magic_flag:
- something = 1.0
- else:
- something = 1.0j
- if isinstance(something, float):
- return something
- return __(something).conjugate()
- '''
- func, retval = extract_node(code, __name__)
- self.assertEqual(
- [i.value for i in func.ilookup('something')],
- [1.0, 1.0j])
- self.assertEqual(
- [i.value for i in retval.infer()],
- [1.0, 1.0j])
-
- def test_lookup_cond_branches(self):
- code = '''
- def no_conjugate_member(magic_flag):
- """should not raise E1101 on something.conjugate"""
- something = 1.0
- if magic_flag:
- something = 1.0j
- return something.conjugate()
- '''
- ast = parse(code, __name__)
- values = [i.value for i in test_utils.get_name_node(ast, 'something', -1).infer()]
- self.assertEqual(values, [1.0, 1.0j])
-
-
- def test_simple_subscript(self):
- code = '''
- class A(object):
- def __getitem__(self, index):
- return index + 42
- [1, 2, 3][0] #@
- (1, 2, 3)[1] #@
- (1, 2, 3)[-1] #@
- [1, 2, 3][0] + (2, )[0] + (3, )[-1] #@
- e = {'key': 'value'}
- e['key'] #@
- "first"[0] #@
- list([1, 2, 3])[-1] #@
- tuple((4, 5, 6))[2] #@
- A()[0] #@
- A()[-1] #@
- '''
- ast_nodes = extract_node(code, __name__)
- expected = [1, 2, 3, 6, 'value', 'f', 3, 6, 42, 41]
- for node, expected_value in zip(ast_nodes, expected):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, expected_value)
-
- def test_invalid_subscripts(self):
- ast_nodes = extract_node('''
- class NoGetitem(object):
- pass
- class InvalidGetitem(object):
- def __getitem__(self): pass
- class InvalidGetitem2(object):
- __getitem__ = 42
- NoGetitem()[4] #@
- InvalidGetitem()[5] #@
- InvalidGetitem2()[10] #@
- ''')
- for node in ast_nodes[:3]:
- self.assertRaises(InferenceError, next, node.infer())
- for node in ast_nodes[3:]:
- self.assertEqual(next(node.infer()), util.Uninferable)
- ast_nodes = extract_node('''
- [1, 2, 3][None] #@
- 'lala'['bala'] #@
- ''')
- for node in ast_nodes:
- self.assertRaises(InferenceError, next, node.infer())
-
- def test_bytes_subscript(self):
- node = extract_node('''b'a'[0]''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- if six.PY2:
- self.assertEqual(inferred.value, 'a')
- else:
- self.assertEqual(inferred.value, 97)
-
- def test_simple_tuple(self):
- module = parse("""
- a = (1,)
- b = (22,)
- some = a + b #@
- """)
- ast = next(module['some'].infer())
- self.assertIsInstance(ast, nodes.Tuple)
- self.assertEqual(len(ast.elts), 2)
- self.assertEqual(ast.elts[0].value, 1)
- self.assertEqual(ast.elts[1].value, 22)
-
- def test_simple_for(self):
- code = '''
- for a in [1, 2, 3]:
- print (a)
- for b,c in [(1,2), (3,4)]:
- print (b)
- print (c)
-
- print ([(d,e) for e,d in ([1,2], [3,4])])
- '''
- ast = parse(code, __name__)
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'a', -1).infer()], [1, 2, 3])
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'b', -1).infer()], [1, 3])
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'c', -1).infer()], [2, 4])
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4])
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3])
-
- def test_simple_for_genexpr(self):
- code = '''
- print ((d,e) for e,d in ([1,2], [3,4]))
- '''
- ast = parse(code, __name__)
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4])
- self.assertEqual([i.value for i in
- test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3])
-
-
- def test_builtin_help(self):
- code = '''
- help()
- '''
- # XXX failing since __builtin__.help assignment has
- # been moved into a function...
- node = extract_node(code, __name__)
- inferred = list(node.func.infer())
- self.assertEqual(len(inferred), 1, inferred)
- self.assertIsInstance(inferred[0], Instance)
- self.assertEqual(inferred[0].name, "_Helper")
-
- def test_builtin_open(self):
- code = '''
- open("toto.txt")
- '''
- node = extract_node(code, __name__).func
- inferred = list(node.infer())
- self.assertEqual(len(inferred), 1)
- if hasattr(sys, 'pypy_version_info'):
- self.assertIsInstance(inferred[0], nodes.ClassDef)
- self.assertEqual(inferred[0].name, 'file')
- else:
- self.assertIsInstance(inferred[0], nodes.FunctionDef)
- self.assertEqual(inferred[0].name, 'open')
-
- if os.name == 'java':
- test_builtin_open = unittest.expectedFailure(test_builtin_open)
-
- def test_callfunc_context_func(self):
- code = '''
- def mirror(arg=None):
- return arg
-
- un = mirror(1)
- '''
- ast = parse(code, __name__)
- inferred = list(ast.igetattr('un'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Const)
- self.assertEqual(inferred[0].value, 1)
-
- def test_callfunc_context_lambda(self):
- code = '''
- mirror = lambda x=None: x
-
- un = mirror(1)
- '''
- ast = parse(code, __name__)
- inferred = list(ast.igetattr('mirror'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Lambda)
- inferred = list(ast.igetattr('un'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Const)
- self.assertEqual(inferred[0].value, 1)
-
- def test_factory_method(self):
- code = '''
- class Super(object):
- @classmethod
- def instance(cls):
- return cls()
-
- class Sub(Super):
- def method(self):
- print ('method called')
-
- sub = Sub.instance()
- '''
- ast = parse(code, __name__)
- inferred = list(ast.igetattr('sub'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], Instance)
- self.assertEqual(inferred[0]._proxied.name, 'Sub')
-
-
- def test_import_as(self):
- code = '''
- import os.path as osp
- print (osp.dirname(__file__))
-
- from os.path import exists as e
- assert e(__file__)
- '''
- ast = parse(code, __name__)
- inferred = list(ast.igetattr('osp'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Module)
- self.assertEqual(inferred[0].name, 'os.path')
- inferred = list(ast.igetattr('e'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.FunctionDef)
- self.assertEqual(inferred[0].name, 'exists')
-
- def _test_const_inferred(self, node, value):
- inferred = list(node.infer())
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Const)
- self.assertEqual(inferred[0].value, value)
-
- def test_unary_not(self):
- for code in ('a = not (1,); b = not ()',
- 'a = not {1:2}; b = not {}',
- 'a = not [1, 2]; b = not []',
- 'a = not {1, 2}; b = not set()',
- 'a = not 1; b = not 0',
- 'a = not "a"; b = not ""',
- 'a = not b"a"; b = not b""'):
- ast = builder.string_build(code, __name__, __file__)
- self._test_const_inferred(ast['a'], False)
- self._test_const_inferred(ast['b'], True)
-
- def test_unary_op_numbers(self):
- ast_nodes = extract_node('''
- +1 #@
- -1 #@
- ~1 #@
- +2.0 #@
- -2.0 #@
- ''')
- expected = [1, -1, -2, 2.0, -2.0]
- for node, expected_value in zip(ast_nodes, expected):
- inferred = next(node.infer())
- self.assertEqual(inferred.value, expected_value)
-
- @test_utils.require_version(minver='3.5')
- def test_matmul(self):
- node = extract_node('''
- class Array:
- def __matmul__(self, other):
- return 42
- Array() @ Array() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def test_binary_op_int_add(self):
- ast = builder.string_build('a = 1 + 2', __name__, __file__)
- self._test_const_inferred(ast['a'], 3)
-
- def test_binary_op_int_sub(self):
- ast = builder.string_build('a = 1 - 2', __name__, __file__)
- self._test_const_inferred(ast['a'], -1)
-
- def test_binary_op_float_div(self):
- ast = builder.string_build('a = 1 / 2.', __name__, __file__)
- self._test_const_inferred(ast['a'], 1 / 2.)
-
- def test_binary_op_str_mul(self):
- ast = builder.string_build('a = "*" * 40', __name__, __file__)
- self._test_const_inferred(ast['a'], "*" * 40)
-
- def test_binary_op_int_bitand(self):
- ast = builder.string_build('a = 23&20', __name__, __file__)
- self._test_const_inferred(ast['a'], 23&20)
-
- def test_binary_op_int_bitor(self):
- ast = builder.string_build('a = 23|8', __name__, __file__)
- self._test_const_inferred(ast['a'], 23|8)
-
- def test_binary_op_int_bitxor(self):
- ast = builder.string_build('a = 23^9', __name__, __file__)
- self._test_const_inferred(ast['a'], 23^9)
-
- def test_binary_op_int_shiftright(self):
- ast = builder.string_build('a = 23 >>1', __name__, __file__)
- self._test_const_inferred(ast['a'], 23>>1)
-
- def test_binary_op_int_shiftleft(self):
- ast = builder.string_build('a = 23 <<1', __name__, __file__)
- self._test_const_inferred(ast['a'], 23<<1)
-
- def test_binary_op_other_type(self):
- ast_nodes = extract_node('''
- class A:
- def __add__(self, other):
- return other + 42
- A() + 1 #@
- 1 + A() #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertIsInstance(first, nodes.Const)
- self.assertEqual(first.value, 43)
-
- second = next(ast_nodes[1].infer())
- self.assertEqual(second, util.Uninferable)
-
- def test_binary_op_other_type_using_reflected_operands(self):
- ast_nodes = extract_node('''
- class A(object):
- def __radd__(self, other):
- return other + 42
- A() + 1 #@
- 1 + A() #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertEqual(first, util.Uninferable)
-
- second = next(ast_nodes[1].infer())
- self.assertIsInstance(second, nodes.Const)
- self.assertEqual(second.value, 43)
-
- def test_binary_op_reflected_and_not_implemented_is_type_error(self):
- ast_node = extract_node('''
- class A(object):
- def __radd__(self, other): return NotImplemented
-
- 1 + A() #@
- ''')
- first = next(ast_node.infer())
- self.assertEqual(first, util.Uninferable)
-
- def test_binary_op_list_mul(self):
- for code in ('a = [[]] * 2', 'a = 2 * [[]]'):
- ast = builder.string_build(code, __name__, __file__)
- inferred = list(ast['a'].infer())
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.List)
- self.assertEqual(len(inferred[0].elts), 2)
- self.assertIsInstance(inferred[0].elts[0], nodes.List)
- self.assertIsInstance(inferred[0].elts[1], nodes.List)
-
- def test_binary_op_list_mul_none(self):
- 'test correct handling on list multiplied by None'
- ast = builder.string_build('a = [1] * None\nb = [1] * "r"')
- inferred = ast['a'].inferred()
- self.assertEqual(len(inferred), 1)
- self.assertEqual(inferred[0], util.Uninferable)
- inferred = ast['b'].inferred()
- self.assertEqual(len(inferred), 1)
- self.assertEqual(inferred[0], util.Uninferable)
-
- def test_binary_op_list_mul_int(self):
- 'test correct handling on list multiplied by int when there are more than one'
- code = '''
- from ctypes import c_int
- seq = [c_int()] * 4
- '''
- ast = parse(code, __name__)
- inferred = ast['seq'].inferred()
- self.assertEqual(len(inferred), 1)
- listval = inferred[0]
- self.assertIsInstance(listval, nodes.List)
- self.assertEqual(len(listval.itered()), 4)
-
- def test_binary_op_on_self(self):
- 'test correct handling of applying binary operator to self'
- code = '''
- import sys
- sys.path = ['foo'] + sys.path
- sys.path.insert(0, 'bar')
- path = sys.path
- '''
- ast = parse(code, __name__)
- inferred = ast['path'].inferred()
- self.assertIsInstance(inferred[0], nodes.List)
-
- def test_binary_op_tuple_add(self):
- ast = builder.string_build('a = (1,) + (2,)', __name__, __file__)
- inferred = list(ast['a'].infer())
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Tuple)
- self.assertEqual(len(inferred[0].elts), 2)
- self.assertEqual(inferred[0].elts[0].value, 1)
- self.assertEqual(inferred[0].elts[1].value, 2)
-
- def test_binary_op_custom_class(self):
- code = '''
- class myarray:
- def __init__(self, array):
- self.array = array
- def __mul__(self, x):
- return myarray([2,4,6])
- def astype(self):
- return "ASTYPE"
-
- def randint(maximum):
- if maximum is not None:
- return myarray([1,2,3]) * 2
- else:
- return int(5)
-
- x = randint(1)
- '''
- ast = parse(code, __name__)
- inferred = list(ast.igetattr('x'))
- self.assertEqual(len(inferred), 2)
- value = [str(v) for v in inferred]
- # The __name__ trick here makes it work when invoked directly
- # (__name__ == '__main__') and through pytest (__name__ ==
- # 'unittest_inference')
- self.assertEqual(value, ['Instance of %s.myarray' % __name__,
- 'Instance of %s.int' % BUILTINS])
-
- def test_nonregr_lambda_arg(self):
- code = '''
- def f(g = lambda: None):
- __(g()).x
- '''
- callfuncnode = extract_node(code)
- inferred = list(callfuncnode.infer())
- self.assertEqual(len(inferred), 2, inferred)
- inferred.remove(util.Uninferable)
- self.assertIsInstance(inferred[0], nodes.Const)
- self.assertIsNone(inferred[0].value)
-
- def test_nonregr_getitem_empty_tuple(self):
- code = '''
- def f(x):
- a = ()[x]
- '''
- ast = parse(code, __name__)
- inferred = list(ast['f'].ilookup('a'))
- self.assertEqual(len(inferred), 1)
- self.assertEqual(inferred[0], util.Uninferable)
-
- def test_nonregr_instance_attrs(self):
- """non regression for instance_attrs infinite loop : pylint / #4"""
-
- code = """
- class Foo(object):
-
- def set_42(self):
- self.attr = 42
-
- class Bar(Foo):
-
- def __init__(self):
- self.attr = 41
- """
- ast = parse(code, __name__)
- foo_class = ast['Foo']
- bar_class = ast['Bar']
- bar_self = ast['Bar']['__init__']['self']
- assattr = bar_class.instance_attrs['attr'][0]
- self.assertEqual(len(foo_class.instance_attrs['attr']), 1)
- self.assertEqual(len(bar_class.instance_attrs['attr']), 1)
- self.assertEqual(bar_class.instance_attrs, {'attr': [assattr]})
- # call 'instance_attr' via 'Instance.getattr' to trigger the bug:
- instance = bar_self.inferred()[0]
- instance.getattr('attr')
- self.assertEqual(len(bar_class.instance_attrs['attr']), 1)
- self.assertEqual(len(foo_class.instance_attrs['attr']), 1)
- self.assertEqual(bar_class.instance_attrs, {'attr': [assattr]})
-
- def test_python25_no_relative_import(self):
- ast = resources.build_file('data/package/absimport.py')
- self.assertTrue(ast.absolute_import_activated(), True)
- inferred = next(test_utils.get_name_node(ast, 'import_package_subpackage_module').infer())
- # failed to import since absolute_import is activated
- self.assertIs(inferred, util.Uninferable)
-
- def test_nonregr_absolute_import(self):
- ast = resources.build_file('data/absimp/string.py', 'data.absimp.string')
- self.assertTrue(ast.absolute_import_activated(), True)
- inferred = next(test_utils.get_name_node(ast, 'string').infer())
- self.assertIsInstance(inferred, nodes.Module)
- self.assertEqual(inferred.name, 'string')
- self.assertIn('ascii_letters', inferred.locals)
-
- def test_mechanize_open(self):
- try:
- import mechanize # pylint: disable=unused-variable
- except ImportError:
- self.skipTest('require mechanize installed')
- data = '''
- from mechanize import Browser
- print(Browser)
- b = Browser()
- '''
- ast = parse(data, __name__)
- browser = next(test_utils.get_name_node(ast, 'Browser').infer())
- self.assertIsInstance(browser, nodes.ClassDef)
- bopen = list(browser.igetattr('open'))
- self.skipTest('the commit said: "huum, see that later"')
- self.assertEqual(len(bopen), 1)
- self.assertIsInstance(bopen[0], nodes.FunctionDef)
- self.assertTrue(bopen[0].callable())
- b = next(test_utils.get_name_node(ast, 'b').infer())
- self.assertIsInstance(b, Instance)
- bopen = list(b.igetattr('open'))
- self.assertEqual(len(bopen), 1)
- self.assertIsInstance(bopen[0], BoundMethod)
- self.assertTrue(bopen[0].callable())
-
- def test_property(self):
- code = '''
- from smtplib import SMTP
- class SendMailController(object):
-
- @property
- def smtp(self):
- return SMTP(mailhost, port)
-
- @property
- def me(self):
- return self
-
- my_smtp = SendMailController().smtp
- my_me = SendMailController().me
- '''
- decorators = set(['%s.property' % BUILTINS])
- ast = parse(code, __name__)
- self.assertEqual(ast['SendMailController']['smtp'].decoratornames(),
- decorators)
- propinferred = list(ast.body[2].value.infer())
- self.assertEqual(len(propinferred), 1)
- propinferred = propinferred[0]
- self.assertIsInstance(propinferred, Instance)
- self.assertEqual(propinferred.name, 'SMTP')
- self.assertEqual(propinferred.root().name, 'smtplib')
- self.assertEqual(ast['SendMailController']['me'].decoratornames(),
- decorators)
- propinferred = list(ast.body[3].value.infer())
- self.assertEqual(len(propinferred), 1)
- propinferred = propinferred[0]
- self.assertIsInstance(propinferred, Instance)
- self.assertEqual(propinferred.name, 'SendMailController')
- self.assertEqual(propinferred.root().name, __name__)
-
- def test_im_func_unwrap(self):
- code = '''
- class EnvBasedTC:
- def pactions(self):
- pass
- pactions = EnvBasedTC.pactions.im_func
- print (pactions)
-
- class EnvBasedTC2:
- pactions = EnvBasedTC.pactions.im_func
- print (pactions)
- '''
- ast = parse(code, __name__)
- pactions = test_utils.get_name_node(ast, 'pactions')
- inferred = list(pactions.infer())
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.FunctionDef)
- pactions = test_utils.get_name_node(ast['EnvBasedTC2'], 'pactions')
- inferred = list(pactions.infer())
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.FunctionDef)
-
- def test_augassign(self):
- code = '''
- a = 1
- a += 2
- print (a)
- '''
- ast = parse(code, __name__)
- inferred = list(test_utils.get_name_node(ast, 'a').infer())
-
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Const)
- self.assertEqual(inferred[0].value, 3)
-
- def test_nonregr_func_arg(self):
- code = '''
- def foo(self, bar):
- def baz():
- pass
- def qux():
- return baz
- spam = bar(None, qux)
- print (spam)
- '''
- ast = parse(code, __name__)
- inferred = list(test_utils.get_name_node(ast['foo'], 'spam').infer())
- self.assertEqual(len(inferred), 1)
- self.assertIs(inferred[0], util.Uninferable)
-
- def test_nonregr_func_global(self):
- code = '''
- active_application = None
-
- def get_active_application():
- global active_application
- return active_application
-
- class Application(object):
- def __init__(self):
- global active_application
- active_application = self
-
- class DataManager(object):
- def __init__(self, app=None):
- self.app = get_active_application()
- def test(self):
- p = self.app
- print (p)
- '''
- ast = parse(code, __name__)
- inferred = list(Instance(ast['DataManager']).igetattr('app'))
- self.assertEqual(len(inferred), 2, inferred) # None / Instance(Application)
- inferred = list(test_utils.get_name_node(ast['DataManager']['test'], 'p').infer())
- self.assertEqual(len(inferred), 2, inferred)
- for node in inferred:
- if isinstance(node, Instance) and node.name == 'Application':
- break
- else:
- self.fail('expected to find an instance of Application in %s' % inferred)
-
- def test_list_inference(self):
- """#20464"""
- code = '''
- from unknown import Unknown
- A = []
- B = []
-
- def test():
- xyz = [
- Unknown
- ] + A + B
- return xyz
-
- Z = test()
- '''
- ast = parse(code, __name__)
- inferred = next(ast['Z'].infer())
- self.assertIsInstance(inferred, nodes.List)
- self.assertEqual(len(inferred.elts), 1)
- self.assertIsInstance(inferred.elts[0], nodes.Unknown)
-
- def test__new__(self):
- code = '''
- class NewTest(object):
- "doc"
- def __new__(cls, arg):
- self = object.__new__(cls)
- self.arg = arg
- return self
-
- n = NewTest()
- '''
- ast = parse(code, __name__)
- self.assertRaises(InferenceError, list, ast['NewTest'].igetattr('arg'))
- n = next(ast['n'].infer())
- inferred = list(n.igetattr('arg'))
- self.assertEqual(len(inferred), 1, inferred)
-
- def test__new__bound_methods(self):
- node = extract_node('''
- class cls(object): pass
- cls().__new__(cls) #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred._proxied, node.root()['cls'])
-
- def test_two_parents_from_same_module(self):
- code = '''
- from data import nonregr
- class Xxx(nonregr.Aaa, nonregr.Ccc):
- "doc"
- '''
- ast = parse(code, __name__)
- parents = list(ast['Xxx'].ancestors())
- self.assertEqual(len(parents), 3, parents) # Aaa, Ccc, object
-
- def test_pluggable_inference(self):
- code = '''
- from collections import namedtuple
- A = namedtuple('A', ['a', 'b'])
- B = namedtuple('B', 'a b')
- '''
- ast = parse(code, __name__)
- aclass = ast['A'].inferred()[0]
- self.assertIsInstance(aclass, nodes.ClassDef)
- self.assertIn('a', aclass.instance_attrs)
- self.assertIn('b', aclass.instance_attrs)
- bclass = ast['B'].inferred()[0]
- self.assertIsInstance(bclass, nodes.ClassDef)
- self.assertIn('a', bclass.instance_attrs)
- self.assertIn('b', bclass.instance_attrs)
-
- def test_infer_arguments(self):
- code = '''
- class A(object):
- def first(self, arg1, arg2):
- return arg1
- @classmethod
- def method(cls, arg1, arg2):
- return arg2
- @classmethod
- def empty(cls):
- return 2
- @staticmethod
- def static(arg1, arg2):
- return arg1
- def empty_method(self):
- return []
- x = A().first(1, [])
- y = A.method(1, [])
- z = A.static(1, [])
- empty = A.empty()
- empty_list = A().empty_method()
- '''
- ast = parse(code, __name__)
- int_node = ast['x'].inferred()[0]
- self.assertIsInstance(int_node, nodes.Const)
- self.assertEqual(int_node.value, 1)
- list_node = ast['y'].inferred()[0]
- self.assertIsInstance(list_node, nodes.List)
- int_node = ast['z'].inferred()[0]
- self.assertIsInstance(int_node, nodes.Const)
- self.assertEqual(int_node.value, 1)
- empty = ast['empty'].inferred()[0]
- self.assertIsInstance(empty, nodes.Const)
- self.assertEqual(empty.value, 2)
- empty_list = ast['empty_list'].inferred()[0]
- self.assertIsInstance(empty_list, nodes.List)
-
- def test_infer_variable_arguments(self):
- code = '''
- def test(*args, **kwargs):
- vararg = args
- kwarg = kwargs
- '''
- ast = parse(code, __name__)
- func = ast['test']
- vararg = func.body[0].value
- kwarg = func.body[1].value
-
- kwarg_inferred = kwarg.inferred()[0]
- self.assertIsInstance(kwarg_inferred, nodes.Dict)
- self.assertIs(kwarg_inferred.parent, func.args)
-
- vararg_inferred = vararg.inferred()[0]
- self.assertIsInstance(vararg_inferred, nodes.Tuple)
- self.assertIs(vararg_inferred.parent, func.args)
-
- def test_infer_nested(self):
- code = """
- def nested():
- from threading import Thread
-
- class NestedThread(Thread):
- def __init__(self):
- Thread.__init__(self)
- """
- # Test that inferring Thread.__init__ looks up in
- # the nested scope.
- ast = parse(code, __name__)
- callfunc = next(ast.nodes_of_class(nodes.Call))
- func = callfunc.func
- inferred = func.inferred()[0]
- self.assertIsInstance(inferred, UnboundMethod)
-
- def test_instance_binary_operations(self):
- code = """
- class A(object):
- def __mul__(self, other):
- return 42
- a = A()
- b = A()
- sub = a - b
- mul = a * b
- """
- ast = parse(code, __name__)
- sub = ast['sub'].inferred()[0]
- mul = ast['mul'].inferred()[0]
- self.assertIs(sub, util.Uninferable)
- self.assertIsInstance(mul, nodes.Const)
- self.assertEqual(mul.value, 42)
-
- def test_instance_binary_operations_parent(self):
- code = """
- class A(object):
- def __mul__(self, other):
- return 42
- class B(A):
- pass
- a = B()
- b = B()
- sub = a - b
- mul = a * b
- """
- ast = parse(code, __name__)
- sub = ast['sub'].inferred()[0]
- mul = ast['mul'].inferred()[0]
- self.assertIs(sub, util. Uninferable)
- self.assertIsInstance(mul, nodes.Const)
- self.assertEqual(mul.value, 42)
-
- def test_instance_binary_operations_multiple_methods(self):
- code = """
- class A(object):
- def __mul__(self, other):
- return 42
- class B(A):
- def __mul__(self, other):
- return [42]
- a = B()
- b = B()
- sub = a - b
- mul = a * b
- """
- ast = parse(code, __name__)
- sub = ast['sub'].inferred()[0]
- mul = ast['mul'].inferred()[0]
- self.assertIs(sub, util.Uninferable)
- self.assertIsInstance(mul, nodes.List)
- self.assertIsInstance(mul.elts[0], nodes.Const)
- self.assertEqual(mul.elts[0].value, 42)
-
- def test_infer_call_result_crash(self):
- code = """
- class A(object):
- def __mul__(self, other):
- return type.__new__()
-
- a = A()
- b = A()
- c = a * b
- """
- ast = parse(code, __name__)
- node = ast['c']
- self.assertEqual(node.inferred(), [util.Uninferable])
-
- def test_infer_empty_nodes(self):
- # Should not crash when trying to infer EmptyNodes.
- node = nodes.EmptyNode()
- self.assertEqual(node.inferred(), [util.Uninferable])
-
- def test_infinite_loop_for_decorators(self):
- # Issue https://bitbucket.org/logilab/astroid/issue/50
- # A decorator that returns itself leads to an infinite loop.
- code = """
- def decorator():
- def wrapper():
- return decorator()
- return wrapper
-
- @decorator()
- def do_a_thing():
- pass
- """
- ast = parse(code, __name__)
- node = ast['do_a_thing']
- self.assertEqual(node.type, 'function')
-
- def test_no_infinite_ancestor_loop(self):
- klass = extract_node("""
- import datetime
-
- def method(self):
- datetime.datetime = something()
-
- class something(datetime.datetime): #@
- pass
- """)
- self.assertIn(
- 'object',
- [base.name for base in klass.ancestors()])
-
- def test_stop_iteration_leak(self):
- code = """
- class Test:
- def __init__(self):
- self.config = {0: self.config[0]}
- self.config[0].test() #@
- """
- ast = extract_node(code, __name__)
- expr = ast.func.expr
- self.assertRaises(InferenceError, next, expr.infer())
-
- def test_tuple_builtin_inference(self):
- code = """
- var = (1, 2)
- tuple() #@
- tuple([1]) #@
- tuple({2}) #@
- tuple("abc") #@
- tuple({1: 2}) #@
- tuple(var) #@
- tuple(tuple([1])) #@
- tuple(frozenset((1, 2))) #@
-
- tuple(None) #@
- tuple(1) #@
- tuple(1, 2) #@
- """
- ast = extract_node(code, __name__)
-
- self.assertInferTuple(ast[0], [])
- self.assertInferTuple(ast[1], [1])
- self.assertInferTuple(ast[2], [2])
- self.assertInferTuple(ast[3], ["a", "b", "c"])
- self.assertInferTuple(ast[4], [1])
- self.assertInferTuple(ast[5], [1, 2])
- self.assertInferTuple(ast[6], [1])
- self.assertInferTuple(ast[7], [1, 2])
-
- for node in ast[8:]:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.qname(), "{}.tuple".format(BUILTINS))
-
- @test_utils.require_version('3.5')
- def test_starred_in_tuple_literal(self):
- code = """
- var = (1, 2, 3)
- bar = (5, 6, 7)
- foo = [999, 1000, 1001]
- (0, *var) #@
- (0, *var, 4) #@
- (0, *var, 4, *bar) #@
- (0, *var, 4, *(*bar, 8)) #@
- (0, *var, 4, *(*bar, *foo)) #@
- """
- ast = extract_node(code, __name__)
- self.assertInferTuple(ast[0], [0, 1, 2, 3])
- self.assertInferTuple(ast[1], [0, 1, 2, 3, 4])
- self.assertInferTuple(ast[2], [0, 1, 2, 3, 4, 5, 6, 7])
- self.assertInferTuple(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8])
- self.assertInferTuple(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001])
-
- @test_utils.require_version('3.5')
- def test_starred_in_list_literal(self):
- code = """
- var = (1, 2, 3)
- bar = (5, 6, 7)
- foo = [999, 1000, 1001]
- [0, *var] #@
- [0, *var, 4] #@
- [0, *var, 4, *bar] #@
- [0, *var, 4, *[*bar, 8]] #@
- [0, *var, 4, *[*bar, *foo]] #@
- """
- ast = extract_node(code, __name__)
- self.assertInferList(ast[0], [0, 1, 2, 3])
- self.assertInferList(ast[1], [0, 1, 2, 3, 4])
- self.assertInferList(ast[2], [0, 1, 2, 3, 4, 5, 6, 7])
- self.assertInferList(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8])
- self.assertInferList(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001])
-
- @test_utils.require_version('3.5')
- def test_starred_in_set_literal(self):
- code = """
- var = (1, 2, 3)
- bar = (5, 6, 7)
- foo = [999, 1000, 1001]
- {0, *var} #@
- {0, *var, 4} #@
- {0, *var, 4, *bar} #@
- {0, *var, 4, *{*bar, 8}} #@
- {0, *var, 4, *{*bar, *foo}} #@
- """
- ast = extract_node(code, __name__)
- self.assertInferSet(ast[0], [0, 1, 2, 3])
- self.assertInferSet(ast[1], [0, 1, 2, 3, 4])
- self.assertInferSet(ast[2], [0, 1, 2, 3, 4, 5, 6, 7])
- self.assertInferSet(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8])
- self.assertInferSet(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001])
-
- @test_utils.require_version('3.5')
- def test_starred_in_literals_inference_issues(self):
- code = """
- {0, *var} #@
- {0, *var, 4} #@
- {0, *var, 4, *bar} #@
- {0, *var, 4, *{*bar, 8}} #@
- {0, *var, 4, *{*bar, *foo}} #@
- """
- ast = extract_node(code, __name__)
- for node in ast:
- with self.assertRaises(InferenceError):
- next(node.infer())
-
- @test_utils.require_version('3.5')
- def test_starred_in_mapping_literal(self):
- code = """
- var = {1: 'b', 2: 'c'}
- bar = {4: 'e', 5: 'f'}
- {0: 'a', **var} #@
- {0: 'a', **var, 3: 'd'} #@
- {0: 'a', **var, 3: 'd', **{**bar, 6: 'g'}} #@
- """
- ast = extract_node(code, __name__)
- self.assertInferDict(ast[0], {0: 'a', 1: 'b', 2: 'c'})
- self.assertInferDict(ast[1], {0: 'a', 1: 'b', 2: 'c', 3: 'd'})
- self.assertInferDict(ast[2], {0: 'a', 1: 'b', 2: 'c', 3: 'd',
- 4: 'e', 5: 'f', 6: 'g'})
-
- @test_utils.require_version('3.5')
- def test_starred_in_mapping_literal_no_inference_possible(self):
- node = extract_node('''
- from unknown import unknown
-
- def test(a):
- return a + 1
-
- def func():
- a = {unknown: 'a'}
- return {0: 1, **a}
-
- test(**func())
- ''')
- self.assertEqual(next(node.infer()), util.Uninferable)
-
- @test_utils.require_version('3.5')
- def test_starred_in_mapping_inference_issues(self):
- code = """
- {0: 'a', **var} #@
- {0: 'a', **var, 3: 'd'} #@
- {0: 'a', **var, 3: 'd', **{**bar, 6: 'g'}} #@
- """
- ast = extract_node(code, __name__)
- for node in ast:
- with self.assertRaises(InferenceError):
- next(node.infer())
-
- @test_utils.require_version('3.5')
- def test_starred_in_mapping_literal_non_const_keys_values(self):
- code = """
- a, b, c, d, e, f, g, h, i, j = "ABCDEFGHIJ"
- var = {c: d, e: f}
- bar = {i: j}
- {a: b, **var} #@
- {a: b, **var, **{g: h, **bar}} #@
- """
- ast = extract_node(code, __name__)
- self.assertInferDict(ast[0], {"A": "B", "C": "D", "E": "F"})
- self.assertInferDict(ast[1], {"A": "B", "C": "D", "E": "F", "G": "H", "I": "J"})
-
- def test_frozenset_builtin_inference(self):
- code = """
- var = (1, 2)
- frozenset() #@
- frozenset([1, 2, 1]) #@
- frozenset({2, 3, 1}) #@
- frozenset("abcab") #@
- frozenset({1: 2}) #@
- frozenset(var) #@
- frozenset(tuple([1])) #@
-
- frozenset(set(tuple([4, 5, set([2])]))) #@
- frozenset(None) #@
- frozenset(1) #@
- frozenset(1, 2) #@
- """
- ast = extract_node(code, __name__)
-
- self.assertInferFrozenSet(ast[0], [])
- self.assertInferFrozenSet(ast[1], [1, 2])
- self.assertInferFrozenSet(ast[2], [1, 2, 3])
- self.assertInferFrozenSet(ast[3], ["a", "b", "c"])
- self.assertInferFrozenSet(ast[4], [1])
- self.assertInferFrozenSet(ast[5], [1, 2])
- self.assertInferFrozenSet(ast[6], [1])
-
- for node in ast[7:]:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.qname(), "{}.frozenset".format(BUILTINS))
-
- def test_set_builtin_inference(self):
- code = """
- var = (1, 2)
- set() #@
- set([1, 2, 1]) #@
- set({2, 3, 1}) #@
- set("abcab") #@
- set({1: 2}) #@
- set(var) #@
- set(tuple([1])) #@
-
- set(set(tuple([4, 5, set([2])]))) #@
- set(None) #@
- set(1) #@
- set(1, 2) #@
- """
- ast = extract_node(code, __name__)
-
- self.assertInferSet(ast[0], [])
- self.assertInferSet(ast[1], [1, 2])
- self.assertInferSet(ast[2], [1, 2, 3])
- self.assertInferSet(ast[3], ["a", "b", "c"])
- self.assertInferSet(ast[4], [1])
- self.assertInferSet(ast[5], [1, 2])
- self.assertInferSet(ast[6], [1])
-
- for node in ast[7:]:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.qname(), "{}.set".format(BUILTINS))
-
- def test_list_builtin_inference(self):
- code = """
- var = (1, 2)
- list() #@
- list([1, 2, 1]) #@
- list({2, 3, 1}) #@
- list("abcab") #@
- list({1: 2}) #@
- list(var) #@
- list(tuple([1])) #@
-
- list(list(tuple([4, 5, list([2])]))) #@
- list(None) #@
- list(1) #@
- list(1, 2) #@
- """
- ast = extract_node(code, __name__)
- self.assertInferList(ast[0], [])
- self.assertInferList(ast[1], [1, 1, 2])
- self.assertInferList(ast[2], [1, 2, 3])
- self.assertInferList(ast[3], ["a", "a", "b", "b", "c"])
- self.assertInferList(ast[4], [1])
- self.assertInferList(ast[5], [1, 2])
- self.assertInferList(ast[6], [1])
-
- for node in ast[7:]:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.qname(), "{}.list".format(BUILTINS))
-
- def test_conversion_of_dict_methods(self):
- ast_nodes = extract_node('''
- list({1:2, 2:3}.values()) #@
- list({1:2, 2:3}.keys()) #@
- tuple({1:2, 2:3}.values()) #@
- tuple({1:2, 3:4}.keys()) #@
- set({1:2, 2:4}.keys()) #@
- ''')
- self.assertInferList(ast_nodes[0], [2, 3])
- self.assertInferList(ast_nodes[1], [1, 2])
- self.assertInferTuple(ast_nodes[2], [2, 3])
- self.assertInferTuple(ast_nodes[3], [1, 3])
- self.assertInferSet(ast_nodes[4], [1, 2])
-
- @test_utils.require_version('3.0')
- def test_builtin_inference_py3k(self):
- code = """
- list(b"abc") #@
- tuple(b"abc") #@
- set(b"abc") #@
- """
- ast = extract_node(code, __name__)
- self.assertInferList(ast[0], [97, 98, 99])
- self.assertInferTuple(ast[1], [97, 98, 99])
- self.assertInferSet(ast[2], [97, 98, 99])
-
- def test_dict_inference(self):
- code = """
- dict() #@
- dict(a=1, b=2, c=3) #@
- dict([(1, 2), (2, 3)]) #@
- dict([[1, 2], [2, 3]]) #@
- dict([(1, 2), [2, 3]]) #@
- dict([('a', 2)], b=2, c=3) #@
- dict({1: 2}) #@
- dict({'c': 2}, a=4, b=5) #@
- def func():
- return dict(a=1, b=2)
- func() #@
- var = {'x': 2, 'y': 3}
- dict(var, a=1, b=2) #@
-
- dict([1, 2, 3]) #@
- dict([(1, 2), (1, 2, 3)]) #@
- dict({1: 2}, {1: 2}) #@
- dict({1: 2}, (1, 2)) #@
- dict({1: 2}, (1, 2), a=4) #@
- dict([(1, 2), ([4, 5], 2)]) #@
- dict([None, None]) #@
-
- def using_unknown_kwargs(**kwargs):
- return dict(**kwargs)
- using_unknown_kwargs(a=1, b=2) #@
- """
- ast = extract_node(code, __name__)
- self.assertInferDict(ast[0], {})
- self.assertInferDict(ast[1], {'a': 1, 'b': 2, 'c': 3})
- for i in range(2, 5):
- self.assertInferDict(ast[i], {1: 2, 2: 3})
- self.assertInferDict(ast[5], {'a': 2, 'b': 2, 'c': 3})
- self.assertInferDict(ast[6], {1: 2})
- self.assertInferDict(ast[7], {'c': 2, 'a': 4, 'b': 5})
- self.assertInferDict(ast[8], {'a': 1, 'b': 2})
- self.assertInferDict(ast[9], {'x': 2, 'y': 3, 'a': 1, 'b': 2})
-
- for node in ast[10:]:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS))
-
- def test_dict_inference_kwargs(self):
- ast_node = extract_node('''dict(a=1, b=2, **{'c': 3})''')
- self.assertInferDict(ast_node, {'a': 1, 'b': 2, 'c': 3})
-
- @test_utils.require_version('3.5')
- def test_dict_inference_for_multiple_starred(self):
- pairs = [
- ('dict(a=1, **{"b": 2}, **{"c":3})', {'a':1, 'b':2, 'c':3}),
- ('dict(a=1, **{"b": 2}, d=4, **{"c":3})', {'a':1, 'b':2, 'c':3, 'd':4}),
- ('dict({"a":1}, b=2, **{"c":3})', {'a':1, 'b':2, 'c':3}),
- ]
- for code, expected_value in pairs:
- node = extract_node(code)
- self.assertInferDict(node, expected_value)
-
- def test_dict_invalid_args(self):
- invalid_values = [
- 'dict(*1)',
- 'dict(**lala)',
- 'dict(**[])',
- ]
- for invalid in invalid_values:
- ast_node = extract_node(invalid)
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS))
-
- def test_str_methods(self):
- code = """
- ' '.decode() #@
-
- ' '.encode() #@
- ' '.join('abcd') #@
- ' '.replace('a', 'b') #@
- ' '.format('a') #@
- ' '.capitalize() #@
- ' '.title() #@
- ' '.lower() #@
- ' '.upper() #@
- ' '.swapcase() #@
- ' '.strip() #@
- ' '.rstrip() #@
- ' '.lstrip() #@
- ' '.rjust() #@
- ' '.ljust() #@
- ' '.center() #@
-
- ' '.index() #@
- ' '.find() #@
- ' '.count() #@
- """
- ast = extract_node(code, __name__)
- self.assertInferConst(ast[0], u'')
- for i in range(1, 16):
- self.assertInferConst(ast[i], '')
- for i in range(16, 19):
- self.assertInferConst(ast[i], 0)
-
- def test_unicode_methods(self):
- code = """
- u' '.encode() #@
-
- u' '.decode() #@
- u' '.join('abcd') #@
- u' '.replace('a', 'b') #@
- u' '.format('a') #@
- u' '.capitalize() #@
- u' '.title() #@
- u' '.lower() #@
- u' '.upper() #@
- u' '.swapcase() #@
- u' '.strip() #@
- u' '.rstrip() #@
- u' '.lstrip() #@
- u' '.rjust() #@
- u' '.ljust() #@
- u' '.center() #@
-
- u' '.index() #@
- u' '.find() #@
- u' '.count() #@
- """
- ast = extract_node(code, __name__)
- self.assertInferConst(ast[0], '')
- for i in range(1, 16):
- self.assertInferConst(ast[i], u'')
- for i in range(16, 19):
- self.assertInferConst(ast[i], 0)
-
- def test_scope_lookup_same_attributes(self):
- code = '''
- import collections
- class Second(collections.Counter):
- def collections(self):
- return "second"
-
- '''
- ast = parse(code, __name__)
- bases = ast['Second'].bases[0]
- inferred = next(bases.infer())
- self.assertTrue(inferred)
- self.assertIsInstance(inferred, nodes.ClassDef)
- self.assertEqual(inferred.qname(), 'collections.Counter')
-
- def test_inferring_with_statement_failures(self):
- module = parse('''
- class NoEnter(object):
- pass
- class NoMethod(object):
- __enter__ = None
- class NoElts(object):
- def __enter__(self):
- return 42
-
- with NoEnter() as no_enter:
- pass
- with NoMethod() as no_method:
- pass
- with NoElts() as (no_elts, no_elts1):
- pass
- ''')
- self.assertRaises(InferenceError, next, module['no_enter'].infer())
- self.assertRaises(InferenceError, next, module['no_method'].infer())
- self.assertRaises(InferenceError, next, module['no_elts'].infer())
-
- def test_inferring_with_statement(self):
- module = parse('''
- class SelfContext(object):
- def __enter__(self):
- return self
-
- class OtherContext(object):
- def __enter__(self):
- return SelfContext()
-
- class MultipleReturns(object):
- def __enter__(self):
- return SelfContext(), OtherContext()
-
- class MultipleReturns2(object):
- def __enter__(self):
- return [1, [2, 3]]
-
- with SelfContext() as self_context:
- pass
- with OtherContext() as other_context:
- pass
- with MultipleReturns(), OtherContext() as multiple_with:
- pass
- with MultipleReturns2() as (stdout, (stderr, stdin)):
- pass
- ''')
- self_context = module['self_context']
- inferred = next(self_context.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'SelfContext')
-
- other_context = module['other_context']
- inferred = next(other_context.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'SelfContext')
-
- multiple_with = module['multiple_with']
- inferred = next(multiple_with.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'SelfContext')
-
- stdout = module['stdout']
- inferred = next(stdout.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 1)
- stderr = module['stderr']
- inferred = next(stderr.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 2)
-
- def test_inferring_with_contextlib_contextmanager(self):
- module = parse('''
- import contextlib
- from contextlib import contextmanager
-
- @contextlib.contextmanager
- def manager_none():
- try:
- yield
- finally:
- pass
-
- @contextlib.contextmanager
- def manager_something():
- try:
- yield 42
- yield 24 # This should be ignored.
- finally:
- pass
-
- @contextmanager
- def manager_multiple():
- with manager_none() as foo:
- with manager_something() as bar:
- yield foo, bar
-
- with manager_none() as none:
- pass
- with manager_something() as something:
- pass
- with manager_multiple() as (first, second):
- pass
- ''')
- none = module['none']
- inferred = next(none.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertIsNone(inferred.value)
-
- something = module['something']
- inferred = something.inferred()
- self.assertEqual(len(inferred), 1)
- inferred = inferred[0]
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- first, second = module['first'], module['second']
- first = next(first.infer())
- second = next(second.infer())
- self.assertIsInstance(first, nodes.Const)
- self.assertIsNone(first.value)
- self.assertIsInstance(second, nodes.Const)
- self.assertEqual(second.value, 42)
-
- def test_inferring_context_manager_skip_index_error(self):
- # Raise an InferenceError when having multiple 'as' bindings
- # from a context manager, but its result doesn't have those
- # indices. This is the case of contextlib.nested, where the
- # result is a list, which is mutated later on, so it's
- # undetected by astroid.
- module = parse('''
- class Manager(object):
- def __enter__(self):
- return []
- with Manager() as (a, b, c):
- pass
- ''')
- self.assertRaises(InferenceError, next, module['a'].infer())
-
- def test_inferring_context_manager_unpacking_inference_error(self):
- # https://github.com/PyCQA/pylint/issues/1463
- module = parse('''
- import contextlib
-
- @contextlib.contextmanager
- def _select_source(a=None):
- with _select_source() as result:
- yield result
-
- result = _select_source()
- with result as (a, b, c):
- pass
- ''')
- self.assertRaises(InferenceError, next, module['a'].infer())
-
- def test_inferring_with_contextlib_contextmanager_failures(self):
- module = parse('''
- from contextlib import contextmanager
-
- def no_decorators_mgr():
- yield
- @no_decorators_mgr
- def other_decorators_mgr():
- yield
- @contextmanager
- def no_yield_mgr():
- pass
-
- with no_decorators_mgr() as no_decorators:
- pass
- with other_decorators_mgr() as other_decorators:
- pass
- with no_yield_mgr() as no_yield:
- pass
- ''')
- self.assertRaises(InferenceError, next, module['no_decorators'].infer())
- self.assertRaises(InferenceError, next, module['other_decorators'].infer())
- self.assertRaises(InferenceError, next, module['no_yield'].infer())
-
- def test_nested_contextmanager(self):
- """Make sure contextmanager works with nested functions
-
- Previously contextmanager would retrieve
- the first yield instead of the yield in the
- proper scope
-
- Fixes https://github.com/PyCQA/pylint/issues/1746
- """
- code = """
- from contextlib import contextmanager
-
- @contextmanager
- def outer():
- @contextmanager
- def inner():
- yield 2
- yield inner
-
- with outer() as ctx:
- ctx #@
- with ctx() as val:
- val #@
- """
- context_node, value_node = extract_node(code)
- value = next(value_node.infer())
- context = next(context_node.infer())
- assert isinstance(context, nodes.FunctionDef)
- assert isinstance(value, nodes.Const)
-
- def test_unary_op_leaks_stop_iteration(self):
- node = extract_node('+[] #@')
- self.assertEqual(util.Uninferable, next(node.infer()))
-
- def test_unary_operands(self):
- ast_nodes = extract_node('''
- import os
- def func(): pass
- from missing import missing
- class GoodInstance(object):
- def __pos__(self):
- return 42
- def __neg__(self):
- return +self - 41
- def __invert__(self):
- return 42
- class BadInstance(object):
- def __pos__(self):
- return lala
- def __neg__(self):
- return missing
- class LambdaInstance(object):
- __pos__ = lambda self: self.lala
- __neg__ = lambda self: self.lala + 1
- @property
- def lala(self): return 24
- instance = GoodInstance()
- lambda_instance = LambdaInstance()
- +instance #@
- -instance #@
- ~instance #@
- --instance #@
- +lambda_instance #@
- -lambda_instance #@
-
- bad_instance = BadInstance()
- +bad_instance #@
- -bad_instance #@
- ~bad_instance #@
-
- # These should be TypeErrors.
- ~BadInstance #@
- ~os #@
- -func #@
- +BadInstance #@
- ''')
- expected = [42, 1, 42, -1, 24, 25]
- for node, value in zip(ast_nodes[:6], expected):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, value)
-
- for bad_node in ast_nodes[6:]:
- inferred = next(bad_node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_unary_op_instance_method_not_callable(self):
- ast_node = extract_node('''
- class A:
- __pos__ = (i for i in range(10))
- +A() #@
- ''')
- self.assertRaises(InferenceError, next, ast_node.infer())
-
- def test_binary_op_type_errors(self):
- ast_nodes = extract_node('''
- import collections
- 1 + "a" #@
- 1 - [] #@
- 1 * {} #@
- 1 / collections #@
- 1 ** (lambda x: x) #@
- {} * {} #@
- {} - {} #@
- {} | {} #@
- {} >> {} #@
- [] + () #@
- () + [] #@
- [] * 2.0 #@
- () * 2.0 #@
- 2.0 >> 2.0 #@
- class A(object): pass
- class B(object): pass
- A() + B() #@
- class A1(object):
- def __add__(self, other): return NotImplemented
- A1() + A1() #@
- class A(object):
- def __add__(self, other): return NotImplemented
- class B(object):
- def __radd__(self, other): return NotImplemented
- A() + B() #@
- class Parent(object):
- pass
- class Child(Parent):
- def __add__(self, other): return NotImplemented
- Child() + Parent() #@
- class A(object):
- def __add__(self, other): return NotImplemented
- class B(A):
- def __radd__(self, other):
- return NotImplemented
- A() + B() #@
- # Augmented
- f = 1
- f+=A() #@
- x = 1
- x+=[] #@
- ''')
- msg = "unsupported operand type(s) for {op}: {lhs!r} and {rhs!r}"
- expected = [
- msg.format(op="+", lhs="int", rhs="str"),
- msg.format(op="-", lhs="int", rhs="list"),
- msg.format(op="*", lhs="int", rhs="dict"),
- msg.format(op="/", lhs="int", rhs="module"),
- msg.format(op="**", lhs="int", rhs="function"),
- msg.format(op="*", lhs="dict", rhs="dict"),
- msg.format(op="-", lhs="dict", rhs="dict"),
- msg.format(op="|", lhs="dict", rhs="dict"),
- msg.format(op=">>", lhs="dict", rhs="dict"),
- msg.format(op="+", lhs="list", rhs="tuple"),
- msg.format(op="+", lhs="tuple", rhs="list"),
- msg.format(op="*", lhs="list", rhs="float"),
- msg.format(op="*", lhs="tuple", rhs="float"),
- msg.format(op=">>", lhs="float", rhs="float"),
- msg.format(op="+", lhs="A", rhs="B"),
- msg.format(op="+", lhs="A1", rhs="A1"),
- msg.format(op="+", lhs="A", rhs="B"),
- msg.format(op="+", lhs="Child", rhs="Parent"),
- msg.format(op="+", lhs="A", rhs="B"),
- msg.format(op="+=", lhs="int", rhs="A"),
- msg.format(op="+=", lhs="int", rhs="list"),
- ]
- for node, expected_value in zip(ast_nodes, expected):
- errors = node.type_errors()
- self.assertEqual(len(errors), 1)
- error = errors[0]
- self.assertEqual(str(error), expected_value)
-
- def test_unary_type_errors(self):
- ast_nodes = extract_node('''
- import collections
- ~[] #@
- ~() #@
- ~dict() #@
- ~{} #@
- ~set() #@
- -set() #@
- -"" #@
- ~"" #@
- +"" #@
- class A(object): pass
- ~(lambda: None) #@
- ~A #@
- ~A() #@
- ~collections #@
- ~2.0 #@
- ''')
- msg = "bad operand type for unary {op}: {type}"
- expected = [
- msg.format(op="~", type='list'),
- msg.format(op="~", type='tuple'),
- msg.format(op="~", type='dict'),
- msg.format(op="~", type='dict'),
- msg.format(op="~", type='set'),
- msg.format(op="-", type='set'),
- msg.format(op="-", type='str'),
- msg.format(op="~", type='str'),
- msg.format(op="+", type='str'),
- msg.format(op="~", type='<lambda>'),
- msg.format(op="~", type='A'),
- msg.format(op="~", type='A'),
- msg.format(op="~", type='collections'),
- msg.format(op="~", type='float'),
- ]
- for node, expected_value in zip(ast_nodes, expected):
- errors = node.type_errors()
- self.assertEqual(len(errors), 1)
- error = errors[0]
- self.assertEqual(str(error), expected_value)
-
- def test_unary_empty_type_errors(self):
- # These aren't supported right now
- ast_nodes = extract_node('''
- ~(2 and []) #@
- -(0 or {}) #@
- ''')
- expected = [
- "bad operand type for unary ~: list",
- "bad operand type for unary -: dict",
- ]
- for node, expected_value in zip(ast_nodes, expected):
- errors = node.type_errors()
- self.assertEqual(len(errors), 1, (expected, node))
- self.assertEqual(str(errors[0]), expected_value)
-
- def test_unary_type_errors_for_non_instance_objects(self):
- node = extract_node('~slice(1, 2, 3)')
- errors = node.type_errors()
- self.assertEqual(len(errors), 1)
- self.assertEqual(
- str(errors[0]),
- 'bad operand type for unary ~: slice'
- )
-
- def test_bool_value_recursive(self):
- pairs = [
- ('{}', False),
- ('{1:2}', True),
- ('()', False),
- ('(1, 2)', True),
- ('[]', False),
- ('[1,2]', True),
- ('frozenset()', False),
- ('frozenset((1, 2))', True),
- ]
- for code, expected in pairs:
- node = extract_node(code)
- inferred = next(node.infer())
- self.assertEqual(inferred.bool_value(), expected)
-
- def test_genexpr_bool_value(self):
- node = extract_node('''(x for x in range(10))''')
- self.assertTrue(node.bool_value())
-
- def test_name_bool_value(self):
- node = extract_node('''
- x = 42
- y = x
- y
- ''')
- self.assertIs(node.bool_value(), util.Uninferable)
-
- def test_bool_value(self):
- # Verify the truth value of nodes.
- module = parse('''
- import collections
- collections_module = collections
- def function(): pass
- class Class(object):
- def method(self): pass
- dict_comp = {x:y for (x, y) in ((1, 2), (2, 3))}
- set_comp = {x for x in range(10)}
- list_comp = [x for x in range(10)]
- lambda_func = lambda: None
- unbound_method = Class.method
- instance = Class()
- bound_method = instance.method
- def generator_func():
- yield
- def true_value():
- return True
- generator = generator_func()
- bin_op = 1 + 2
- bool_op = x and y
- callfunc = test()
- good_callfunc = true_value()
- compare = 2 < 3
- const_str_true = 'testconst'
- const_str_false = ''
- ''')
- collections_module = next(module['collections_module'].infer())
- self.assertTrue(collections_module.bool_value())
- function = module['function']
- self.assertTrue(function.bool_value())
- klass = module['Class']
- self.assertTrue(klass.bool_value())
- dict_comp = next(module['dict_comp'].infer())
- self.assertEqual(dict_comp, util.Uninferable)
- set_comp = next(module['set_comp'].infer())
- self.assertEqual(set_comp, util.Uninferable)
- list_comp = next(module['list_comp'].infer())
- self.assertEqual(list_comp, util.Uninferable)
- lambda_func = next(module['lambda_func'].infer())
- self.assertTrue(lambda_func)
- unbound_method = next(module['unbound_method'].infer())
- self.assertTrue(unbound_method)
- bound_method = next(module['bound_method'].infer())
- self.assertTrue(bound_method)
- generator = next(module['generator'].infer())
- self.assertTrue(generator)
- bin_op = module['bin_op'].parent.value
- self.assertIs(bin_op.bool_value(), util.Uninferable)
- bool_op = module['bool_op'].parent.value
- self.assertEqual(bool_op.bool_value(), util.Uninferable)
- callfunc = module['callfunc'].parent.value
- self.assertEqual(callfunc.bool_value(), util.Uninferable)
- good_callfunc = next(module['good_callfunc'].infer())
- self.assertTrue(good_callfunc.bool_value())
- compare = module['compare'].parent.value
- self.assertEqual(compare.bool_value(), util.Uninferable)
-
- def test_bool_value_instances(self):
- instances = extract_node('''
- class FalseBoolInstance(object):
- def {bool}(self):
- return False
- class TrueBoolInstance(object):
- def {bool}(self):
- return True
- class FalseLenInstance(object):
- def __len__(self):
- return 0
- class TrueLenInstance(object):
- def __len__(self):
- return 14
- class AlwaysTrueInstance(object):
- pass
- class ErrorInstance(object):
- def __bool__(self):
- return lala
- def __len__(self):
- return lala
- class NonMethods(object):
- __bool__ = 1
- __len__ = 2
- FalseBoolInstance() #@
- TrueBoolInstance() #@
- FalseLenInstance() #@
- TrueLenInstance() #@
- AlwaysTrueInstance() #@
- ErrorInstance() #@
- '''.format(bool=BOOL_SPECIAL_METHOD))
- expected = (False, True, False, True, True, util.Uninferable, util.Uninferable)
- for node, expected_value in zip(instances, expected):
- inferred = next(node.infer())
- self.assertEqual(inferred.bool_value(), expected_value)
-
- def test_bool_value_variable(self):
- instance = extract_node('''
- class VariableBoolInstance(object):
- def __init__(self, value):
- self.value = value
- def {bool}(self):
- return self.value
-
- not VariableBoolInstance(True)
- '''.format(bool=BOOL_SPECIAL_METHOD))
- inferred = next(instance.infer())
- self.assertIs(inferred.bool_value(), util.Uninferable)
-
- def test_infer_coercion_rules_for_floats_complex(self):
- ast_nodes = extract_node('''
- 1 + 1.0 #@
- 1 * 1.0 #@
- 2 - 1.0 #@
- 2 / 2.0 #@
- 1 + 1j #@
- 2 * 1j #@
- 2 - 1j #@
- 3 / 1j #@
- ''')
- expected_values = [2.0, 1.0, 1.0, 1.0, 1 + 1j, 2j, 2 - 1j, -3j]
- for node, expected in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertEqual(inferred.value, expected)
-
- def test_binop_list_with_elts(self):
- ast_node = extract_node('''
- x = [A] * 1
- [1] + x
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.List)
- self.assertEqual(len(inferred.elts), 2)
- self.assertIsInstance(inferred.elts[0], nodes.Const)
- self.assertIsInstance(inferred.elts[1], nodes.Unknown)
-
- def test_binop_same_types(self):
- ast_nodes = extract_node('''
- class A(object):
- def __add__(self, other):
- return 42
- 1 + 1 #@
- 1 - 1 #@
- "a" + "b" #@
- A() + A() #@
- ''')
- expected_values = [2, 0, "ab", 42]
- for node, expected in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, expected)
-
- def test_binop_different_types_reflected_only(self):
- node = extract_node('''
- class A(object):
- pass
- class B(object):
- def __radd__(self, other):
- return other
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_binop_different_types_unknown_bases(self):
- node = extract_node('''
- from foo import bar
-
- class A(bar):
- pass
- class B(object):
- def __radd__(self, other):
- return other
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertIs(inferred, util.Uninferable)
-
- def test_binop_different_types_normal_not_implemented_and_reflected(self):
- node = extract_node('''
- class A(object):
- def __add__(self, other):
- return NotImplemented
- class B(object):
- def __radd__(self, other):
- return other
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_binop_different_types_no_method_implemented(self):
- node = extract_node('''
- class A(object):
- pass
- class B(object): pass
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_binop_different_types_reflected_and_normal_not_implemented(self):
- node = extract_node('''
- class A(object):
- def __add__(self, other): return NotImplemented
- class B(object):
- def __radd__(self, other): return NotImplemented
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_binop_subtype(self):
- node = extract_node('''
- class A(object): pass
- class B(A):
- def __add__(self, other): return other
- B() + A() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_binop_subtype_implemented_in_parent(self):
- node = extract_node('''
- class A(object):
- def __add__(self, other): return other
- class B(A): pass
- B() + A() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_binop_subtype_not_implemented(self):
- node = extract_node('''
- class A(object):
- pass
- class B(A):
- def __add__(self, other): return NotImplemented
- B() + A() #@
- ''')
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_binop_supertype(self):
- node = extract_node('''
- class A(object):
- pass
- class B(A):
- def __radd__(self, other):
- return other
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_binop_supertype_rop_not_implemented(self):
- node = extract_node('''
- class A(object):
- def __add__(self, other):
- return other
- class B(A):
- def __radd__(self, other):
- return NotImplemented
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'B')
-
- def test_binop_supertype_both_not_implemented(self):
- node = extract_node('''
- class A(object):
- def __add__(self): return NotImplemented
- class B(A):
- def __radd__(self, other):
- return NotImplemented
- A() + B() #@
- ''')
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_binop_inferrence_errors(self):
- ast_nodes = extract_node('''
- from unknown import Unknown
- class A(object):
- def __add__(self, other): return NotImplemented
- class B(object):
- def __add__(self, other): return Unknown
- A() + Unknown #@
- Unknown + A() #@
- B() + A() #@
- A() + B() #@
- ''')
- for node in ast_nodes:
- self.assertEqual(next(node.infer()), util.Uninferable)
-
- def test_binop_ambiguity(self):
- ast_nodes = extract_node('''
- class A(object):
- def __add__(self, other):
- if isinstance(other, B):
- return NotImplemented
- if type(other) is type(self):
- return 42
- return NotImplemented
- class B(A): pass
- class C(object):
- def __radd__(self, other):
- if isinstance(other, B):
- return 42
- return NotImplemented
- A() + B() #@
- B() + A() #@
- A() + C() #@
- C() + A() #@
- ''')
- for node in ast_nodes:
- self.assertEqual(next(node.infer()), util.Uninferable)
-
- def test_metaclass__getitem__(self):
- ast_node = extract_node('''
- class Meta(type):
- def __getitem__(cls, arg):
- return 24
- import six
- @six.add_metaclass(Meta)
- class A(object):
- pass
-
- A['Awesome'] #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 24)
-
- def test_bin_op_classes(self):
- ast_node = extract_node('''
- class Meta(type):
- def __or__(self, other):
- return 24
- import six
- @six.add_metaclass(Meta)
- class A(object):
- pass
-
- A | A
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 24)
-
- def test_bin_op_supertype_more_complicated_example(self):
- ast_node = extract_node('''
- class A(object):
- def __init__(self):
- self.foo = 42
- def __add__(self, other):
- return other.bar + self.foo / 2
-
- class B(A):
- def __init__(self):
- self.bar = 24
- def __radd__(self, other):
- return NotImplemented
-
- A() + B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(int(inferred.value), 45)
-
- def test_aug_op_same_type_not_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return NotImplemented
- A() + A() #@
- ''')
- self.assertEqual(next(ast_node.infer()), util.Uninferable)
-
- def test_aug_op_same_type_aug_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return other
- f = A()
- f += A() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_aug_op_same_type_aug_not_implemented_normal_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return 42
- f = A()
- f += A() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def test_aug_op_subtype_both_not_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return NotImplemented
- class B(A):
- pass
- b = B()
- b+=A() #@
- ''')
- self.assertEqual(next(ast_node.infer()), util.Uninferable)
-
- def test_aug_op_subtype_aug_op_is_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return 42
- class B(A):
- pass
- b = B()
- b+=A() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def test_aug_op_subtype_normal_op_is_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __add__(self, other): return 42
- class B(A):
- pass
- b = B()
- b+=A() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def test_aug_different_types_no_method_implemented(self):
- ast_node = extract_node('''
- class A(object): pass
- class B(object): pass
- f = A()
- f += B() #@
- ''')
- self.assertEqual(next(ast_node.infer()), util.Uninferable)
-
- def test_aug_different_types_augop_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return other
- class B(object): pass
- f = A()
- f += B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'B')
-
- def test_aug_different_types_aug_not_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return other
- class B(object): pass
- f = A()
- f += B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'B')
-
- def test_aug_different_types_aug_not_implemented_rop_fallback(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return NotImplemented
- class B(object):
- def __radd__(self, other): return other
- f = A()
- f += B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_augop_supertypes_none_implemented(self):
- ast_node = extract_node('''
- class A(object): pass
- class B(object): pass
- a = A()
- a += B() #@
- ''')
- self.assertEqual(next(ast_node.infer()), util.Uninferable)
-
- def test_augop_supertypes_not_implemented_returned_for_all(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return NotImplemented
- class B(object):
- def __add__(self, other): return NotImplemented
- a = A()
- a += B() #@
- ''')
- self.assertEqual(next(ast_node.infer()), util.Uninferable)
-
- def test_augop_supertypes_augop_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return other
- class B(A): pass
- a = A()
- a += B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'B')
-
- def test_augop_supertypes_reflected_binop_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- class B(A):
- def __radd__(self, other): return other
- a = A()
- a += B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'A')
-
- def test_augop_supertypes_normal_binop_implemented(self):
- ast_node = extract_node('''
- class A(object):
- def __iadd__(self, other): return NotImplemented
- def __add__(self, other): return other
- class B(A):
- def __radd__(self, other): return NotImplemented
-
- a = A()
- a += B() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'B')
-
- @unittest.expectedFailure
- def test_string_interpolation(self):
- ast_nodes = extract_node('''
- "a%d%d" % (1, 2) #@
- "a%(x)s" % {"x": 42} #@
- ''')
- expected = ["a12", "a42"]
- for node, expected_value in zip(ast_nodes, expected):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, expected_value)
-
- def test_mul_list_supports__index__(self):
- ast_nodes = extract_node('''
- class Index(object):
- def __index__(self): return 2
- class NotIndex(object): pass
- class NotIndex2(object):
- def __index__(self): return None
- a = [1, 2]
- a * Index() #@
- a * NotIndex() #@
- a * NotIndex2() #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertIsInstance(first, nodes.List)
- self.assertEqual([node.value for node in first.itered()],
- [1, 2, 1, 2])
- for rest in ast_nodes[1:]:
- inferred = next(rest.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_subscript_supports__index__(self):
- ast_nodes = extract_node('''
- class Index(object):
- def __index__(self): return 2
- class LambdaIndex(object):
- __index__ = lambda self: self.foo
- @property
- def foo(self): return 1
- class NonIndex(object):
- __index__ = lambda self: None
- a = [1, 2, 3, 4]
- a[Index()] #@
- a[LambdaIndex()] #@
- a[NonIndex()] #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertIsInstance(first, nodes.Const)
- self.assertEqual(first.value, 3)
- second = next(ast_nodes[1].infer())
- self.assertIsInstance(second, nodes.Const)
- self.assertEqual(second.value, 2)
- self.assertRaises(InferenceError, next, ast_nodes[2].infer())
-
- def test_special_method_masquerading_as_another(self):
- ast_node = extract_node('''
- class Info(object):
- def __add__(self, other):
- return "lala"
- __or__ = __add__
-
- f = Info()
- f | Info() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, "lala")
-
- def test_unary_op_assignment(self):
- ast_node = extract_node('''
- class A(object): pass
- def pos(self):
- return 42
- A.__pos__ = pos
- f = A()
- +f #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def test_unary_op_classes(self):
- ast_node = extract_node('''
- import six
- class Meta(type):
- def __invert__(self):
- return 42
- @six.add_metaclass(Meta)
- class A(object):
- pass
- ~A
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 42)
-
- def _slicing_test_helper(self, pairs, cls, get_elts):
- for code, expected in pairs:
- ast_node = extract_node(code)
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, cls)
- self.assertEqual(get_elts(inferred), expected,
- ast_node.as_string())
-
- def test_slicing_list(self):
- pairs = (
- ("[1, 2, 3][:] #@", [1, 2, 3]),
- ("[1, 2, 3][0:] #@", [1, 2, 3]),
- ("[1, 2, 3][None:] #@", [1, 2, 3]),
- ("[1, 2, 3][None:None] #@", [1, 2, 3]),
- ("[1, 2, 3][0:-1] #@", [1, 2]),
- ("[1, 2, 3][0:2] #@", [1, 2]),
- ("[1, 2, 3][0:2:None] #@", [1, 2]),
- ("[1, 2, 3][::] #@", [1, 2, 3]),
- ("[1, 2, 3][::2] #@", [1, 3]),
- ("[1, 2, 3][::-1] #@", [3, 2, 1]),
- ("[1, 2, 3][0:2:2] #@", [1]),
- ("[1, 2, 3, 4, 5, 6][0:4-1:2+0] #@", [1, 3]),
- )
- self._slicing_test_helper(
- pairs, nodes.List,
- lambda inferred: [elt.value for elt in inferred.elts])
-
- def test_slicing_tuple(self):
- pairs = (
- ("(1, 2, 3)[:] #@", [1, 2, 3]),
- ("(1, 2, 3)[0:] #@", [1, 2, 3]),
- ("(1, 2, 3)[None:] #@", [1, 2, 3]),
- ("(1, 2, 3)[None:None] #@", [1, 2, 3]),
- ("(1, 2, 3)[0:-1] #@", [1, 2]),
- ("(1, 2, 3)[0:2] #@", [1, 2]),
- ("(1, 2, 3)[0:2:None] #@", [1, 2]),
- ("(1, 2, 3)[::] #@", [1, 2, 3]),
- ("(1, 2, 3)[::2] #@", [1, 3]),
- ("(1, 2, 3)[::-1] #@", [3, 2, 1]),
- ("(1, 2, 3)[0:2:2] #@", [1]),
- ("(1, 2, 3, 4, 5, 6)[0:4-1:2+0] #@", [1, 3]),
- )
- self._slicing_test_helper(
- pairs, nodes.Tuple,
- lambda inferred: [elt.value for elt in inferred.elts])
-
- def test_slicing_str(self):
- pairs = (
- ("'123'[:] #@", "123"),
- ("'123'[0:] #@", "123"),
- ("'123'[None:] #@", "123"),
- ("'123'[None:None] #@", "123"),
- ("'123'[0:-1] #@", "12"),
- ("'123'[0:2] #@", "12"),
- ("'123'[0:2:None] #@", "12"),
- ("'123'[::] #@", "123"),
- ("'123'[::2] #@", "13"),
- ("'123'[::-1] #@", "321"),
- ("'123'[0:2:2] #@", "1"),
- ("'123456'[0:4-1:2+0] #@", "13"),
- )
- self._slicing_test_helper(
- pairs, nodes.Const, lambda inferred: inferred.value)
-
- def test_invalid_slicing_primaries(self):
- examples = [
- "(lambda x: x)[1:2]",
- "1[2]",
- "(1, 2, 3)[a:]",
- "(1, 2, 3)[object:object]",
- "(1, 2, 3)[1:object]",
- 'enumerate[2]'
- ]
- for code in examples:
- node = extract_node(code)
- self.assertRaises(InferenceError, next, node.infer())
-
- def test_instance_slicing(self):
- ast_nodes = extract_node('''
- class A(object):
- def __getitem__(self, index):
- return [1, 2, 3, 4, 5][index]
- A()[1:] #@
- A()[:2] #@
- A()[1:4] #@
- ''')
- expected_values = [
- [2, 3, 4, 5],
- [1, 2],
- [2, 3, 4],
- ]
- for expected, node in zip(expected_values, ast_nodes):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.List)
- self.assertEqual([elt.value for elt in inferred.elts], expected)
-
- def test_instance_slicing_slices(self):
- ast_node = extract_node('''
- class A(object):
- def __getitem__(self, index):
- return index
- A()[1:] #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Slice)
- self.assertEqual(inferred.lower.value, 1)
- self.assertIsNone(inferred.upper)
-
- def test_instance_slicing_fails(self):
- ast_nodes = extract_node('''
- class A(object):
- def __getitem__(self, index):
- return 1[index]
- A()[4:5] #@
- A()[2:] #@
- ''')
- for node in ast_nodes:
- self.assertEqual(next(node.infer()), util.Uninferable)
-
- def test_type__new__with_metaclass(self):
- ast_node = extract_node('''
- class Metaclass(type):
- pass
- class Entity(object):
- pass
- type.__new__(Metaclass, 'NewClass', (Entity,), {'a': 1}) #@
- ''')
- inferred = next(ast_node.infer())
-
- self.assertIsInstance(inferred, nodes.ClassDef)
- self.assertEqual(inferred.name, 'NewClass')
- metaclass = inferred.metaclass()
- self.assertEqual(metaclass, inferred.root()['Metaclass'])
- ancestors = list(inferred.ancestors())
- self.assertEqual(len(ancestors), 2)
- self.assertEqual(ancestors[0], inferred.root()['Entity'])
- attributes = inferred.getattr('a')
- self.assertEqual(len(attributes), 1)
- self.assertIsInstance(attributes[0], nodes.Const)
- self.assertEqual(attributes[0].value, 1)
-
- def test_type__new__not_enough_arguments(self):
- ast_nodes = extract_node('''
- type.__new__(1) #@
- type.__new__(1, 2) #@
- type.__new__(1, 2, 3) #@
- type.__new__(1, 2, 3, 4, 5) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
-
- def test_type__new__invalid_mcs_argument(self):
- ast_nodes = extract_node('''
- class Class(object): pass
- type.__new__(1, 2, 3, 4) #@
- type.__new__(Class, 2, 3, 4) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
-
- def test_type__new__invalid_name(self):
- ast_nodes = extract_node('''
- class Class(type): pass
- type.__new__(Class, object, 1, 2) #@
- type.__new__(Class, 1, 1, 2) #@
- type.__new__(Class, [], 1, 2) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
-
- def test_type__new__invalid_bases(self):
- ast_nodes = extract_node('''
- type.__new__(type, 'a', 1, 2) #@
- type.__new__(type, 'a', [], 2) #@
- type.__new__(type, 'a', {}, 2) #@
- type.__new__(type, 'a', (1, ), 2) #@
- type.__new__(type, 'a', (object, 1), 2) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
-
- def test_type__new__invalid_attrs(self):
- ast_nodes = extract_node('''
- type.__new__(type, 'a', (), ()) #@
- type.__new__(type, 'a', (), object) #@
- type.__new__(type, 'a', (), 1) #@
- type.__new__(type, 'a', (), {object: 1}) #@
- type.__new__(type, 'a', (), {1:2, "a":5}) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
-
- def test_type__new__metaclass_lookup(self):
- ast_node = extract_node('''
- class Metaclass(type):
- def test(cls): pass
- @classmethod
- def test1(cls): pass
- attr = 42
- type.__new__(Metaclass, 'A', (), {}) #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
- test = inferred.getattr('test')
- self.assertEqual(len(test), 1)
- self.assertIsInstance(test[0], BoundMethod)
- self.assertIsInstance(test[0].bound, nodes.ClassDef)
- self.assertEqual(test[0].bound, inferred)
- test1 = inferred.getattr('test1')
- self.assertEqual(len(test1), 1)
- self.assertIsInstance(test1[0], BoundMethod)
- self.assertIsInstance(test1[0].bound, nodes.ClassDef)
- self.assertEqual(test1[0].bound, inferred.metaclass())
- attr = inferred.getattr('attr')
- self.assertEqual(len(attr), 1)
- self.assertIsInstance(attr[0], nodes.Const)
- self.assertEqual(attr[0].value, 42)
-
- def test_type__new__metaclass_and_ancestors_lookup(self):
- ast_node = extract_node('''
- class Book(object):
- title = 'Ubik'
- class MetaBook(type):
- title = 'Grimus'
- type.__new__(MetaBook, 'book', (Book, ), {'title':'Catch 22'}) #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
- titles = [title.value for title in inferred.igetattr('title')]
- self.assertEqual(titles, ['Catch 22', 'Ubik', 'Grimus'])
-
- @unittest.expectedFailure
- def test_function_metaclasses(self):
- # These are not supported right now, although
- # they will be in the future.
- ast_node = extract_node('''
- import six
-
- class BookMeta(type):
- author = 'Rushdie'
-
- def metaclass_function(*args):
- return BookMeta
-
- @six.add_metaclass(metaclass_function)
- class Book(object):
- pass
- Book #@
- ''')
- inferred = next(ast_node.infer())
- metaclass = inferred.metaclass()
- self.assertIsInstance(metaclass, nodes.ClassDef)
- self.assertEqual(metaclass.name, 'BookMeta')
- author = next(inferred.igetattr('author'))
- self.assertIsInstance(author, nodes.Const)
- self.assertEqual(author.value, 'Rushdie')
-
- def test_subscript_inference_error(self):
- # Used to raise StopIteration
- ast_node = extract_node('''
- class AttributeDict(dict):
- def __getitem__(self, name):
- return self
- flow = AttributeDict()
- flow['app'] = AttributeDict()
- flow['app']['config'] = AttributeDict()
- flow['app']['config']['doffing'] = AttributeDict() #@
- ''')
- self.assertIsNone(helpers.safe_infer(ast_node.targets[0]))
-
- def test_classmethod_inferred_by_context(self):
- ast_node = extract_node('''
- class Super(object):
- def instance(cls):
- return cls()
- instance = classmethod(instance)
-
- class Sub(Super):
- def method(self):
- return self
-
- # should see the Sub.instance() is returning a Sub
- # instance, not a Super instance
- Sub.instance().method() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, 'Sub')
-
- def test_infer_call_result_invalid_dunder_call_on_instance(self):
- ast_nodes = extract_node('''
- class A:
- __call__ = 42
- class B:
- __call__ = A()
- class C:
- __call = None
- A() #@
- B() #@
- C() #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertRaises(InferenceError, next, inferred.infer_call_result(node))
-
- def test_context_call_for_context_managers(self):
- ast_nodes = extract_node('''
- class A:
- def __enter__(self):
- return self
- class B:
- __enter__ = lambda self: self
- class C:
- @property
- def a(self): return A()
- def __enter__(self):
- return self.a
- with A() as a:
- a #@
- with B() as b:
- b #@
- with C() as c:
- c #@
- ''')
- first_a = next(ast_nodes[0].infer())
- self.assertIsInstance(first_a, Instance)
- self.assertEqual(first_a.name, 'A')
- second_b = next(ast_nodes[1].infer())
- self.assertIsInstance(second_b, Instance)
- self.assertEqual(second_b.name, 'B')
- third_c = next(ast_nodes[2].infer())
- self.assertIsInstance(third_c, Instance)
- self.assertEqual(third_c.name, 'A')
-
- def test_metaclass_subclasses_arguments_are_classes_not_instances(self):
- ast_node = extract_node('''
- class A(type):
- def test(cls):
- return cls
- import six
- @six.add_metaclass(A)
- class B(object):
- pass
-
- B.test() #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
- self.assertEqual(inferred.name, 'B')
-
- def test_infer_cls_in_class_methods(self):
- ast_nodes = extract_node('''
- class A(type):
- def __call__(cls):
- cls #@
- class B(object):
- def __call__(cls):
- cls #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertIsInstance(first, nodes.ClassDef)
- second = next(ast_nodes[1].infer())
- self.assertIsInstance(second, Instance)
-
- @unittest.expectedFailure
- def test_metaclass_arguments_are_classes_not_instances(self):
- ast_node = extract_node('''
- class A(type):
- def test(cls): return cls
- A.test() #@
- ''')
- # This is not supported yet
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
- self.assertEqual(inferred.name, 'A')
-
- @test_utils.require_version(minver='3.0')
- def test_metaclass_with_keyword_args(self):
- ast_node = extract_node('''
- class TestMetaKlass(type):
- def __new__(mcs, name, bases, ns, kwo_arg):
- return super().__new__(mcs, name, bases, ns)
-
- class TestKlass(metaclass=TestMetaKlass, kwo_arg=42): #@
- pass
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
-
- def test_delayed_attributes_without_slots(self):
- ast_node = extract_node('''
- class A(object):
- __slots__ = ('a', )
- a = A()
- a.teta = 24
- a.a = 24
- a #@
- ''')
- inferred = next(ast_node.infer())
- with self.assertRaises(exceptions.NotFoundError):
- inferred.getattr('teta')
- inferred.getattr('a')
-
- @test_utils.require_version(maxver='3.0')
- def test_delayed_attributes_with_old_style_classes(self):
- ast_node = extract_node('''
- class A:
- __slots__ = ('a', )
- a = A()
- a.teta = 42
- a #@
- ''')
- next(ast_node.infer()).getattr('teta')
-
- def test_lambda_as_methods(self):
- ast_node = extract_node('''
- class X:
- m = lambda self, arg: self.z + arg
- z = 24
-
- X().m(4) #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 28)
-
- def test_inner_value_redefined_by_subclass(self):
- ast_node = extract_node('''
- class X(object):
- M = lambda self, arg: "a"
- x = 24
- def __init__(self):
- x = 24
- self.m = self.M(x)
-
- class Y(X):
- M = lambda self, arg: arg + 1
- def blurb(self):
- self.m #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 25)
-
- @unittest.expectedFailure
- def test_inner_value_redefined_by_subclass_with_mro(self):
- # This might work, but it currently doesn't due to not being able
- # to reuse inference contexts.
- ast_node = extract_node('''
- class X(object):
- M = lambda self, arg: arg + 1
- x = 24
- def __init__(self):
- y = self
- self.m = y.M(1) + y.z
-
- class C(object):
- z = 24
-
- class Y(X, C):
- M = lambda self, arg: arg + 1
- def blurb(self):
- self.m #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, 25)
-
- def test_getitem_of_class_raised_type_error(self):
- # Test that we wrap an AttributeInferenceError
- # and reraise it as a TypeError in Class.getitem
- node = extract_node('''
- def test():
- yield
- test()
- ''')
- inferred = next(node.infer())
- with self.assertRaises(exceptions.AstroidTypeError):
- inferred.getitem(nodes.Const('4'))
-
-
- class GetattrTest(unittest.TestCase):
-
- def test_yes_when_unknown(self):
- ast_nodes = extract_node('''
- from missing import Missing
- getattr(1, Unknown) #@
- getattr(Unknown, 'a') #@
- getattr(Unknown, Unknown) #@
- getattr(Unknown, Unknown, Unknown) #@
-
- getattr(Missing, 'a') #@
- getattr(Missing, Missing) #@
- getattr('a', Missing) #@
- getattr('a', Missing, Missing) #@
- ''')
- for node in ast_nodes[:4]:
- self.assertRaises(InferenceError, next, node.infer())
-
- for node in ast_nodes[4:]:
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable, node)
-
- def test_attrname_not_string(self):
- ast_nodes = extract_node('''
- getattr(1, 1) #@
- c = int
- getattr(1, c) #@
- ''')
- for node in ast_nodes:
- self.assertRaises(InferenceError, next, node.infer())
-
- def test_attribute_missing(self):
- ast_nodes = extract_node('''
- getattr(1, 'ala') #@
- getattr(int, 'ala') #@
- getattr(float, 'bala') #@
- getattr({}, 'portocala') #@
- ''')
- for node in ast_nodes:
- self.assertRaises(InferenceError, next, node.infer())
-
- def test_default(self):
- ast_nodes = extract_node('''
- getattr(1, 'ala', None) #@
- getattr(int, 'bala', int) #@
- getattr(int, 'bala', getattr(int, 'portocala', None)) #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertIsInstance(first, nodes.Const)
- self.assertIsNone(first.value)
-
- second = next(ast_nodes[1].infer())
- self.assertIsInstance(second, nodes.ClassDef)
- self.assertEqual(second.qname(), "%s.int" % BUILTINS)
-
- third = next(ast_nodes[2].infer())
- self.assertIsInstance(third, nodes.Const)
- self.assertIsNone(third.value)
-
- def test_lookup(self):
- ast_nodes = extract_node('''
- class A(object):
- def test(self): pass
- class B(A):
- def test_b(self): pass
- class C(A): pass
- class E(C, B):
- def test_e(self): pass
-
- getattr(A(), 'test') #@
- getattr(A, 'test') #@
- getattr(E(), 'test_b') #@
- getattr(E(), 'test') #@
-
- class X(object):
- def test(self):
- getattr(self, 'test') #@
- ''')
-
- first = next(ast_nodes[0].infer())
- self.assertIsInstance(first, BoundMethod)
- self.assertEqual(first.bound.name, 'A')
-
- second = next(ast_nodes[1].infer())
- self.assertIsInstance(second, UnboundMethod)
- self.assertIsInstance(second.parent, nodes.ClassDef)
- self.assertEqual(second.parent.name, 'A')
-
- third = next(ast_nodes[2].infer())
- self.assertIsInstance(third, BoundMethod)
- # Bound to E, but the provider is B.
- self.assertEqual(third.bound.name, 'E')
- self.assertEqual(third._proxied._proxied.parent.name, 'B')
-
- fourth = next(ast_nodes[3].infer())
- self.assertIsInstance(fourth, BoundMethod)
- self.assertEqual(fourth.bound.name, 'E')
- self.assertEqual(third._proxied._proxied.parent.name, 'B')
-
- fifth = next(ast_nodes[4].infer())
- self.assertIsInstance(fifth, BoundMethod)
- self.assertEqual(fifth.bound.name, 'X')
-
- def test_lambda(self):
- node = extract_node('''
- getattr(lambda x: x, 'f') #@
- ''')
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
-
- class HasattrTest(unittest.TestCase):
-
- def test_inference_errors(self):
- ast_nodes = extract_node('''
- from missing import Missing
-
- hasattr(Unknown, 'ala') #@
-
- hasattr(Missing, 'bala') #@
- hasattr('portocala', Missing) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_attribute_is_missing(self):
- ast_nodes = extract_node('''
- class A: pass
- hasattr(int, 'ala') #@
- hasattr({}, 'bala') #@
- hasattr(A(), 'portocala') #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertFalse(inferred.value)
-
- def test_attribute_is_not_missing(self):
- ast_nodes = extract_node('''
- class A(object):
- def test(self): pass
- class B(A):
- def test_b(self): pass
- class C(A): pass
- class E(C, B):
- def test_e(self): pass
-
- hasattr(A(), 'test') #@
- hasattr(A, 'test') #@
- hasattr(E(), 'test_b') #@
- hasattr(E(), 'test') #@
-
- class X(object):
- def test(self):
- hasattr(self, 'test') #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertTrue(inferred.value)
-
- def test_lambda(self):
- node = extract_node('''
- hasattr(lambda x: x, 'f') #@
- ''')
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
-
- class BoolOpTest(unittest.TestCase):
-
- def test_bool_ops(self):
- expected = [
- ('1 and 2', 2),
- ('0 and 2', 0),
- ('1 or 2', 1),
- ('0 or 2', 2),
- ('0 or 0 or 1', 1),
- ('1 and 2 and 3', 3),
- ('1 and 2 or 3', 2),
- ('1 and 0 or 3', 3),
- ('1 or 0 and 2', 1),
- ('(1 and 2) and (2 and 3)', 3),
- ('not 2 and 3', False),
- ('2 and not 3', False),
- ('not 0 and 3', 3),
- ('True and False', False),
- ('not (True or False) and True', False),
- ]
- for code, expected_value in expected:
- node = extract_node(code)
- inferred = next(node.infer())
- self.assertEqual(inferred.value, expected_value)
-
- def test_yes_when_unknown(self):
- ast_nodes = extract_node('''
- from unknown import unknown, any, not_any
- 0 and unknown #@
- unknown or 0 #@
- any or not_any and unknown #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_other_nodes(self):
- ast_nodes = extract_node('''
- def test(): pass
- test and 0 #@
- 1 and test #@
- ''')
- first = next(ast_nodes[0].infer())
- self.assertEqual(first.value, 0)
- second = next(ast_nodes[1].infer())
- self.assertIsInstance(second, nodes.FunctionDef)
- self.assertEqual(second.name, 'test')
-
-
- class TestCallable(unittest.TestCase):
-
- def test_callable(self):
- expected = [
- ('callable(len)', True),
- ('callable("a")', False),
- ('callable(callable)', True),
- ('callable(lambda x, y: x+y)', True),
- ('import os; __(callable(os))', False),
- ('callable(int)', True),
- ('''
- def test(): pass
- callable(test) #@''', True),
- ('''
- class C1:
- def meth(self): pass
- callable(C1) #@''', True),
- ]
- for code, expected_value in expected:
- node = extract_node(code)
- inferred = next(node.infer())
- self.assertEqual(inferred.value, expected_value)
-
- def test_callable_methods(self):
- ast_nodes = extract_node('''
- class C:
- def test(self): pass
- @staticmethod
- def static(): pass
- @classmethod
- def class_method(cls): pass
- def __call__(self): pass
- class D(C):
- pass
- class NotReallyCallableDueToPythonMisfeature(object):
- __call__ = 42
- callable(C.test) #@
- callable(C.static) #@
- callable(C.class_method) #@
- callable(C().test) #@
- callable(C().static) #@
- callable(C().class_method) #@
- C #@
- C() #@
- NotReallyCallableDueToPythonMisfeature() #@
- staticmethod #@
- classmethod #@
- property #@
- D #@
- D() #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertTrue(inferred)
-
- def test_inference_errors(self):
- ast_nodes = extract_node('''
- from unknown import unknown
- callable(unknown) #@
- def test():
- return unknown
- callable(test()) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_not_callable(self):
- ast_nodes = extract_node('''
- callable("") #@
- callable(1) #@
- callable(True) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertFalse(inferred.value)
-
-
- class TestBool(unittest.TestCase):
-
- def test_bool(self):
- pairs = [
- ('bool()', False),
- ('bool(1)', True),
- ('bool(0)', False),
- ('bool([])', False),
- ('bool([1])', True),
- ('bool({})', False),
- ('bool(True)', True),
- ('bool(False)', False),
- ('bool(None)', False),
- ('from unknown import Unknown; __(bool(Unknown))', util.Uninferable),
- ]
- for code, expected in pairs:
- node = extract_node(code)
- inferred = next(node.infer())
- if expected is util.Uninferable:
- self.assertEqual(expected, inferred)
- else:
- self.assertEqual(inferred.value, expected)
-
- def test_bool_bool_special_method(self):
- ast_nodes = extract_node('''
- class FalseClass:
- def {method}(self):
- return False
- class TrueClass:
- def {method}(self):
- return True
- class C(object):
- def __call__(self):
- return False
- class B(object):
- {method} = C()
- class LambdaBoolFalse(object):
- {method} = lambda self: self.foo
- @property
- def foo(self): return 0
- class FalseBoolLen(object):
- __len__ = lambda self: self.foo
- @property
- def foo(self): return 0
- bool(FalseClass) #@
- bool(TrueClass) #@
- bool(FalseClass()) #@
- bool(TrueClass()) #@
- bool(B()) #@
- bool(LambdaBoolFalse()) #@
- bool(FalseBoolLen()) #@
- '''.format(method=BOOL_SPECIAL_METHOD))
- expected = [True, True, False, True, False, False, False]
- for node, expected_value in zip(ast_nodes, expected):
- inferred = next(node.infer())
- self.assertEqual(inferred.value, expected_value)
-
- def test_bool_instance_not_callable(self):
- ast_nodes = extract_node('''
- class BoolInvalid(object):
- {method} = 42
- class LenInvalid(object):
- __len__ = "a"
- bool(BoolInvalid()) #@
- bool(LenInvalid()) #@
- '''.format(method=BOOL_SPECIAL_METHOD))
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
-
- class TestType(unittest.TestCase):
-
- def test_type(self):
- pairs = [
- ('type(1)', 'int'),
- ('type(type)', 'type'),
- ('type(None)', 'NoneType'),
- ('type(object)', 'type'),
- ('type(dict())', 'dict'),
- ('type({})', 'dict'),
- ('type(frozenset())', 'frozenset'),
- ]
- for code, expected in pairs:
- node = extract_node(code)
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
- self.assertEqual(inferred.name, expected)
-
-
- class ArgumentsTest(unittest.TestCase):
-
- @staticmethod
- def _get_dict_value(inferred):
- items = inferred.items
- return sorted((key.value, value.value) for key, value in items)
-
- @staticmethod
- def _get_tuple_value(inferred):
- elts = inferred.elts
- return tuple(elt.value for elt in elts)
-
- def test_args(self):
- expected_values = [(), (1, ), (2, 3), (4, 5),
- (3, ), (), (3, 4, 5),
- (), (), (4, ), (4, 5),
- (), (3, ), (), (), (3, ), (42, )]
- ast_nodes = extract_node('''
- def func(*args):
- return args
- func() #@
- func(1) #@
- func(2, 3) #@
- func(*(4, 5)) #@
- def func(a, b, *args):
- return args
- func(1, 2, 3) #@
- func(1, 2) #@
- func(1, 2, 3, 4, 5) #@
- def func(a, b, c=42, *args):
- return args
- func(1, 2) #@
- func(1, 2, 3) #@
- func(1, 2, 3, 4) #@
- func(1, 2, 3, 4, 5) #@
- func = lambda a, b, *args: args
- func(1, 2) #@
- func(1, 2, 3) #@
- func = lambda a, b=42, *args: args
- func(1) #@
- func(1, 2) #@
- func(1, 2, 3) #@
- func(1, 2, *(42, )) #@
- ''')
- for node, expected_value in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Tuple)
- self.assertEqual(self._get_tuple_value(inferred), expected_value)
-
- @test_utils.require_version('3.5')
- def test_multiple_starred_args(self):
- expected_values = [
- (1, 2, 3),
- (1, 4, 2, 3, 5, 6, 7),
- ]
- ast_nodes = extract_node('''
- def func(a, b, *args):
- return args
- func(1, 2, *(1, ), *(2, 3)) #@
- func(1, 2, *(1, ), 4, *(2, 3), 5, *(6, 7)) #@
- ''')
- for node, expected_value in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Tuple)
- self.assertEqual(self._get_tuple_value(inferred), expected_value)
-
- def test_defaults(self):
- expected_values = [42, 3, 41, 42]
- ast_nodes = extract_node('''
- def func(a, b, c=42, *args):
- return c
- func(1, 2) #@
- func(1, 2, 3) #@
- func(1, 2, c=41) #@
- func(1, 2, 42, 41) #@
- ''')
- for node, expected_value in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, expected_value)
-
- @test_utils.require_version('3.0')
- def test_kwonly_args(self):
- expected_values = [24, 24, 42, 23, 24, 24, 54]
- ast_nodes = extract_node('''
- def test(*, f, b): return f
- test(f=24, b=33) #@
- def test(a, *, f): return f
- test(1, f=24) #@
- def test(a, *, f=42): return f
- test(1) #@
- test(1, f=23) #@
- def test(a, b, c=42, *args, f=24):
- return f
- test(1, 2, 3) #@
- test(1, 2, 3, 4) #@
- test(1, 2, 3, 4, 5, f=54) #@
- ''')
- for node, expected_value in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, expected_value)
-
- def test_kwargs(self):
- expected = [
- [('a', 1), ('b', 2), ('c', 3)],
- [('a', 1)],
- [('a', 'b')],
- ]
- ast_nodes = extract_node('''
- def test(**kwargs):
- return kwargs
- test(a=1, b=2, c=3) #@
- test(a=1) #@
- test(**{'a': 'b'}) #@
- ''')
- for node, expected_value in zip(ast_nodes, expected):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Dict)
- value = self._get_dict_value(inferred)
- self.assertEqual(value, expected_value)
-
- def test_kwargs_and_other_named_parameters(self):
- ast_nodes = extract_node('''
- def test(a=42, b=24, **kwargs):
- return kwargs
- test(42, 24, c=3, d=4) #@
- test(49, b=24, d=4) #@
- test(a=42, b=33, c=3, d=42) #@
- test(a=42, **{'c':42}) #@
- ''')
- expected_values = [
- [('c', 3), ('d', 4)],
- [('d', 4)],
- [('c', 3), ('d', 42)],
- [('c', 42)],
- ]
- for node, expected_value in zip(ast_nodes, expected_values):
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Dict)
- value = self._get_dict_value(inferred)
- self.assertEqual(value, expected_value)
-
- def test_kwargs_access_by_name(self):
- expected_values = [42, 42, 42, 24]
- ast_nodes = extract_node('''
- def test(**kwargs):
- return kwargs['f']
- test(f=42) #@
- test(**{'f': 42}) #@
- test(**dict(f=42)) #@
- def test(f=42, **kwargs):
- return kwargs['l']
- test(l=24) #@
- ''')
- for ast_node, value in zip(ast_nodes, expected_values):
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertEqual(inferred.value, value)
-
- @test_utils.require_version('3.5')
- def test_multiple_kwargs(self):
- expected_value = [
- ('a', 1),
- ('b', 2),
- ('c', 3),
- ('d', 4),
- ('f', 42),
- ]
- ast_node = extract_node('''
- def test(**kwargs):
- return kwargs
- test(a=1, b=2, **{'c': 3}, **{'d': 4}, f=42) #@
- ''')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.Dict)
- value = self._get_dict_value(inferred)
- self.assertEqual(value, expected_value)
-
- def test_kwargs_are_overridden(self):
- ast_nodes = extract_node('''
- def test(f):
- return f
- test(f=23, **{'f': 34}) #@
- def test(f=None):
- return f
- test(f=23, **{'f':23}) #@
- ''')
- for ast_node in ast_nodes:
- inferred = next(ast_node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
- def test_fail_to_infer_args(self):
- ast_nodes = extract_node('''
- def test(a, **kwargs): return a
- test(*missing) #@
- test(*object) #@
- test(*1) #@
-
-
- def test(**kwargs): return kwargs
- test(**miss) #@
- test(**(1, 2)) #@
- test(**1) #@
- test(**{misss:1}) #@
- test(**{object:1}) #@
- test(**{1:1}) #@
- test(**{'a':1, 'a':1}) #@
-
- def test(a): return a
- test() #@
- test(1, 2, 3) #@
-
- from unknown import unknown
- test(*unknown) #@
- def test(*args): return args
- test(*unknown) #@
- ''')
- for node in ast_nodes:
- inferred = next(node.infer())
- self.assertEqual(inferred, util.Uninferable)
-
-
- class SliceTest(unittest.TestCase):
-
- def test_slice(self):
- ast_nodes = [
- ('[1, 2, 3][slice(None)]', [1, 2, 3]),
- ('[1, 2, 3][slice(None, None)]', [1, 2, 3]),
- ('[1, 2, 3][slice(None, None, None)]', [1, 2, 3]),
- ('[1, 2, 3][slice(1, None)]', [2, 3]),
- ('[1, 2, 3][slice(None, 1, None)]', [1]),
- ('[1, 2, 3][slice(0, 1)]', [1]),
- ('[1, 2, 3][slice(0, 3, 2)]', [1, 3]),
- ]
- for node, expected_value in ast_nodes:
- ast_node = extract_node("__({})".format(node))
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.List)
- self.assertEqual([elt.value for elt in inferred.elts], expected_value)
-
- def test_slice_inference_error(self):
- ast_nodes = extract_node('''
- from unknown import unknown
- [1, 2, 3][slice(None, unknown, unknown)] #@
- [1, 2, 3][slice(None, missing, missing)] #@
- [1, 2, 3][slice(object, list, tuple)] #@
- [1, 2, 3][slice(b'a')] #@
- [1, 2, 3][slice(1, 'aa')] #@
- [1, 2, 3][slice(1, 2.0, 3.0)] #@
- [1, 2, 3][slice()] #@
- [1, 2, 3][slice(1, 2, 3, 4)] #@
- ''')
- for node in ast_nodes:
- self.assertRaises(InferenceError, next, node.infer())
-
- def test_slice_attributes(self):
- ast_nodes = [
- ('slice(2, 3, 4)', (2, 3, 4)),
- ('slice(None, None, 4)', (None, None, 4)),
- ('slice(None, 1, None)', (None, 1, None)),
- ]
- for code, values in ast_nodes:
- lower, upper, step = values
- node = extract_node(code)
- inferred = next(node.infer())
- self.assertIsInstance(inferred, nodes.Slice)
- lower_value = next(inferred.igetattr('start'))
- self.assertIsInstance(lower_value, nodes.Const)
- self.assertEqual(lower_value.value, lower)
- higher_value = next(inferred.igetattr('stop'))
- self.assertIsInstance(higher_value, nodes.Const)
- self.assertEqual(higher_value.value, upper)
- step_value = next(inferred.igetattr('step'))
- self.assertIsInstance(step_value, nodes.Const)
- self.assertEqual(step_value.value, step)
- self.assertEqual(inferred.pytype(), '%s.slice' % BUILTINS)
-
- def test_slice_type(self):
- ast_node = extract_node('type(slice(None, None, None))')
- inferred = next(ast_node.infer())
- self.assertIsInstance(inferred, nodes.ClassDef)
- self.assertEqual(inferred.name, 'slice')
-
-
- class CallSiteTest(unittest.TestCase):
-
- @staticmethod
- def _call_site_from_call(call):
- return arguments.CallSite.from_call(call)
-
- def _test_call_site_pair(self, code, expected_args, expected_keywords):
- ast_node = extract_node(code)
- call_site = self._call_site_from_call(ast_node)
- self.assertEqual(len(call_site.positional_arguments), len(expected_args))
- self.assertEqual([arg.value for arg in call_site.positional_arguments],
- expected_args)
- self.assertEqual(len(call_site.keyword_arguments), len(expected_keywords))
- for keyword, value in expected_keywords.items():
- self.assertIn(keyword, call_site.keyword_arguments)
- self.assertEqual(call_site.keyword_arguments[keyword].value, value)
-
- def _test_call_site(self, pairs):
- for pair in pairs:
- self._test_call_site_pair(*pair)
-
- @test_utils.require_version('3.5')
- def test_call_site_starred_args(self):
- pairs = [
- (
- "f(*(1, 2), *(2, 3), *(3, 4), **{'a':1}, **{'b': 2})",
- [1, 2, 2, 3, 3, 4],
- {'a': 1, 'b': 2}
- ),
- (
- "f(1, 2, *(3, 4), 5, *(6, 7), f=24, **{'c':3})",
- [1, 2, 3, 4, 5, 6, 7],
- {'f':24, 'c': 3},
- ),
- # Too many fs passed into.
- (
- "f(f=24, **{'f':24})", [], {},
- ),
- ]
- self._test_call_site(pairs)
-
- def test_call_site(self):
- pairs = [
- (
- "f(1, 2)", [1, 2], {}
- ),
- (
- "f(1, 2, *(1, 2))", [1, 2, 1, 2], {}
- ),
- (
- "f(a=1, b=2, c=3)", [], {'a':1, 'b':2, 'c':3}
- )
- ]
- self._test_call_site(pairs)
-
- def _test_call_site_valid_arguments(self, values, invalid):
- for value in values:
- ast_node = extract_node(value)
- call_site = self._call_site_from_call(ast_node)
- self.assertEqual(call_site.has_invalid_arguments(), invalid)
-
- def test_call_site_valid_arguments(self):
- values = [
- "f(*lala)", "f(*1)", "f(*object)",
- ]
- self._test_call_site_valid_arguments(values, invalid=True)
- values = [
- "f()", "f(*(1, ))", "f(1, 2, *(2, 3))",
- ]
- self._test_call_site_valid_arguments(values, invalid=False)
-
- def test_duplicated_keyword_arguments(self):
- ast_node = extract_node('f(f=24, **{"f": 25})')
- site = self._call_site_from_call(ast_node)
- self.assertIn('f', site.duplicated_keywords)
-
-
- class ObjectDunderNewTest(unittest.TestCase):
- def test_object_dunder_new_is_inferred_if_decorator(self):
- node = extract_node('''
- @object.__new__
- class instance(object):
- pass
- ''')
- inferred = next(node.infer())
- self.assertIsInstance(inferred, Instance)
-
-
- def test_augassign_recursion():
- """Make sure inference doesn't throw a RecursionError
-
- Regression test for augmented assign dropping context.path
- causing recursion errors
-
- """
- # infinitely recurses in python
- code = """
- def rec():
- a = 0
- a += rec()
- return a
- rec()
- """
- cls_node = extract_node(code)
- assert next(cls_node.infer()) is util.Uninferable
-
-
- if __name__ == '__main__':
- unittest.main()
|