importpyfrompypy.rlib.objectmodelimport*frompypy.annotationimporttypes,modelfrompypy.translator.translatorimportTranslationContext,graphoffrompypy.rpython.test.toolimportBaseRtypingTest,LLRtypeMixin,OORtypeMixinfrompypy.rpython.test.test_llinterpimportinterpretfrompypy.conftestimportoptiondefstrange_key_eq(key1,key2):returnkey1[0]==key2[0]# only the 1st character is relevantdefstrange_key_hash(key):returnord(key[0])defplay_with_r_dict(d):d['hello']=41d['hello']=42assertd['hi there']==42try:unexpected=d["dumb"]exceptKeyError:passelse:assertFalse,"should have raised, got %s"%unexpectedassertlen(d)==1assert'oops'notindcount=0forxind:assertx=='hello'count+=1assertcount==1assertd.get('hola',-1)==42assertd.get('salut',-1)==-1d1=d.copy()deld['hu!']assertlen(d)==0assertd1.keys()==['hello']d.update(d1)assertd.values()==[42]lst=d.items()assertlen(lst)==1andlen(lst[0])==2assertlst[0][0]=='hello'andlst[0][1]==42count=0forxind.iterkeys():assertx=='hello'count+=1assertcount==1count=0forxind.itervalues():assertx==42count+=1assertcount==1count=0forxind.iteritems():assertlen(x)==2andx[0]=='hello'andx[1]==42count+=1assertcount==1d.clear()assertd.keys()==[]returnTrue# for the tests belowdeftest_recursive_r_dict_repr():importoperatorrdic=r_dict(operator.eq,hash)rdic['x']=rdicassertstr(rdic)=="r_dict({'x': r_dict({...})})"assertrepr(rdic)=="r_dict({'x': r_dict({...})})"deftest_r_dict():# NB. this test function is also annotated/rtyped by the next testsd=r_dict(strange_key_eq,strange_key_hash)returnplay_with_r_dict(d)classStrange:defkey_eq(strange,key1,key2):returnkey1[0]==key2[0]# only the 1st character is relevantdefkey_hash(strange,key):returnord(key[0])deftest_r_dict_bm():# NB. this test function is also annotated by the next testsstrange=Strange()d=r_dict(strange.key_eq,strange.key_hash)returnplay_with_r_dict(d)deftest_annotate_r_dict():t=TranslationContext()a=t.buildannotator()a.build_types(test_r_dict,[])#t.view()graph=graphof(t,strange_key_eq)asserta.binding(graph.getargs()[0]).knowntype==strasserta.binding(graph.getargs()[1]).knowntype==strgraph=graphof(t,strange_key_hash)asserta.binding(graph.getargs()[0]).knowntype==strdeftest_annotate_r_dict_bm():t=TranslationContext()a=t.buildannotator()a.build_types(test_r_dict_bm,[])#t.view()strange_key_eq=Strange.key_eq.im_funcstrange_key_hash=Strange.key_hash.im_funcStrange_def=a.bookkeeper.getuniqueclassdef(Strange)graph=graphof(t,strange_key_eq)asserta.binding(graph.getargs()[0]).knowntype==Strange_defasserta.binding(graph.getargs()[1]).knowntype==strasserta.binding(graph.getargs()[2]).knowntype==strgraph=graphof(t,strange_key_hash)asserta.binding(graph.getargs()[0]).knowntype==Strange_defasserta.binding(graph.getargs()[1]).knowntype==strdeftest_unboxed_value():classBase(object):__slots__=()classC(Base,UnboxedValue):__slots__='smallint'assertC(17).smallint==17assertC(17).get_untagged_value()==17classA(UnboxedValue):__slots__=['value']assertA(12098).value==12098assertA(12098).get_untagged_value()==12098deftest_symbolic():py.test.skip("xxx no test here")deftest_symbolic_raises():s1=Symbolic()s2=Symbolic()py.test.raises(TypeError,"s1 < s2")py.test.raises(TypeError,"hash(s1)")deftest_compute_hash():frompypy.rlib.objectmodelimport_hash_string,_hash_float,_hash_tupleassertcompute_hash("Hello")==_hash_string("Hello")assertcompute_hash(7)==7assertcompute_hash(-3.5)==_hash_float(-3.5)assertcompute_hash(None)==0assertcompute_hash(("world",None,7))==_hash_tuple(("world",None,7))#classFoo(object):def__hash__(self):return42foo=Foo()h=compute_hash(foo)asserth==object.__hash__(foo)asserth==getattr(foo,'__precomputed_identity_hash')assertcompute_hash(None)==0deftest_compute_hash_float():frompypy.rlib.rfloatimportINFINITY,NANassertcompute_hash(INFINITY)==314159assertcompute_hash(-INFINITY)==-271828assertcompute_hash(NAN)==0deftest_compute_identity_hash():classFoo(object):def__hash__(self):return42foo=Foo()h=compute_identity_hash(foo)asserth==object.__hash__(foo)asserth==getattr(foo,'__precomputed_identity_hash')deftest_compute_unique_id():classFoo(object):passfoo=Foo()assertcompute_unique_id(foo)==id(foo)deftest_current_object_addr_as_int():frompypy.rlib.rarithmeticimportintmaskclassFoo(object):passfoo=Foo()assertcurrent_object_addr_as_int(foo)==intmask(id(foo))classBaseTestObjectModel(BaseRtypingTest):deftest_we_are_translated(self):assertwe_are_translated()==Falsedeffn():returnwe_are_translated()res=self.interpret(fn,[])assertresisTruedeftest_rtype_r_dict(self):res=self.interpret(test_r_dict,[])assertresisTruedeftest_rtype_r_dict_bm(self):res=self.interpret(test_r_dict_bm,[])assertresisTruedeftest_rtype_constant_r_dicts(self):d1=r_dict(strange_key_eq,strange_key_hash)d1['hello']=666d2=r_dict(strange_key_eq,strange_key_hash)d2['hello']=777d2['world']=888deffn(i):ifi==1:d=d1else:d=d2returnlen(d)res=self.interpret(fn,[1])assertres==1res=self.interpret(fn,[2])assertres==2deftest_rtype_r_dict_singlefrozen_func(self):classFreezingClass(Strange):def_freeze_(self):returnTrueobj=FreezingClass()deffn():d=r_dict(obj.key_eq,obj.key_hash)returnplay_with_r_dict(d)assertself.interpret(fn,[])isTruedeftest_rtype_r_dict_singlefrozen_func_pbc(self):classFreezingClass(Strange):def_freeze_(self):returnTrueobj=FreezingClass()pbc_d=r_dict(obj.key_eq,obj.key_hash)deffn():returnplay_with_r_dict(pbc_d)assertself.interpret(fn,[])isTruedeftest_rtype_r_dict_exceptions(self):defraising_hash(obj):ifobj.startswith("bla"):raiseTypeErrorreturn1defeq(obj1,obj2):returnobj1isobj2deff():d1=r_dict(eq,raising_hash)d1['xxx']=1try:x=d1["blabla"]exceptException:return42returnxres=self.interpret(f,[])assertres==42deff():d1=r_dict(eq,raising_hash)d1['xxx']=1try:x=d1["blabla"]exceptTypeError:return42returnxres=self.interpret(f,[])assertres==42deff():d1=r_dict(eq,raising_hash)d1['xxx']=1try:d1["blabla"]=2exceptTypeError:return42return0res=self.interpret(f,[])assertres==42deftest_access_in_try(self):h=lambdax:1eq=lambdax,y:x==ydeff(d):try:returnd[2]exceptZeroDivisionError:return42return-1defg(n):d=r_dict(eq,h)d[1]=nd[2]=2*nreturnf(d)res=self.interpret(g,[3])assertres==6deftest_access_in_try_set(self):h=lambdax:1eq=lambdax,y:x==ydeff(d):try:d[2]=77exceptZeroDivisionError:return42return-1defg(n):d=r_dict(eq,h)d[1]=nf(d)returnd[2]res=self.interpret(g,[3])assertres==77deftest_compute_hash(self):classFoo(object):passdeff(i):assertcompute_hash(i)==compute_hash(42)assertcompute_hash(i+1.0)==compute_hash(43.0)assertcompute_hash("Hello"+str(i))==compute_hash("Hello42")ifi==42:p=Noneelse:p=Foo()assertcompute_hash(p)==compute_hash(None)assert(compute_hash(("world",None,i,7.5))==compute_hash(("world",None,42,7.5)))q=Foo()assertcompute_hash(q)==compute_identity_hash(q)frompypy.rlib.rfloatimportINFINITY,NANassertcompute_hash(INFINITY)==314159assertcompute_hash(-INFINITY)==-271828assertcompute_hash(NAN)==0returni*2res=self.interpret(f,[42])assertres==84deftest_isconstant(self):frompypy.rlib.objectmodelimportis_annotation_constant,specialize@specialize.arg_or_var(0)deff(arg):ifis_annotation_constant(arg):return1return10deffn(arg):returnf(arg)+f(3)assertself.interpret(fn,[15])==11classTestLLtype(BaseTestObjectModel,LLRtypeMixin):deftest_rtype_keepalive(self):frompypy.rlibimportobjectmodeldeff():x=[1]y=['b']objectmodel.keepalive_until_here(x,y)return1res=self.interpret(f,[])assertres==1deftest_compute_hash_across_translation(self):classFoo(object):passq=Foo()deff(i):assertcompute_hash(None)==0assertcompute_hash(i)==h_42assertcompute_hash(i+1.0)==h_43_dot_0assertcompute_hash((i+3)/6.0)==h_7_dot_5assertcompute_hash("Hello"+str(i))==h_Hello42ifi==42:p=Noneelse:p=Foo()assertcompute_hash(p)==h_Noneassertcompute_hash(("world",None,i,7.5))==h_tupleassertcompute_hash(q)==h_qreturni*2h_42=compute_hash(42)h_43_dot_0=compute_hash(43.0)h_7_dot_5=compute_hash(7.5)h_Hello42=compute_hash("Hello42")h_None=compute_hash(None)h_tuple=compute_hash(("world",None,42,7.5))h_q=compute_hash(q)res=self.interpret(f,[42])assertres==84classTestOOtype(BaseTestObjectModel,OORtypeMixin):passdeftest_specialize_decorator():deff():passspecialize.memo()(f)assertf._annspecialcase_=='specialize:memo'specialize.arg(0)(f)assertf._annspecialcase_=='specialize:arg(0)'specialize.arg(1)(f)assertf._annspecialcase_=='specialize:arg(1)'deftest_enforceargs_decorator():@enforceargs(int,str,None)deff(a,b,c):returna,b,cf.foo='foo'assertf._annenforceargs_==(int,str,None)assertf.func_name=='f'assertf.foo=='foo'assertf(1,'hello',42)==(1,'hello',42)exc=py.test.raises(TypeError,"f(1, 2, 3)")assertexc.value.message=="f argument 'b' must be of type <type 'str'>"py.test.raises(TypeError,"f('hello', 'world', 3)")deftest_enforceargs_defaults():@enforceargs(int,int)deff(a,b=40):returna+bassertf(2)==42deftest_enforceargs_keywords():@enforceargs(b=int)deff(a,b,c):returna+bassertf._annenforceargs_==(None,int,None)deftest_enforceargs_int_float_promotion():@enforceargs(float)deff(x):returnx# in RPython there is an implicit int->float promotionassertf(42)==42deftest_enforceargs_None_string():@enforceargs(str,unicode)deff(a,b):returna,bassertf(None,None)==(None,None)deftest_enforceargs_complex_types():@enforceargs([int],{str:int})deff(a,b):returna,bx=[0,1,2]y={'a':1,'b':2}assertf(x,y)==(x,y)assertf([],{})==([],{})assertf(None,None)==(None,None)py.test.raises(TypeError,"f(['hello'], y)")py.test.raises(TypeError,"f(x, {'a': 'hello'})")py.test.raises(TypeError,"f(x, {0: 42})")deftest_enforceargs_no_typecheck():@enforceargs(int,str,None,typecheck=False)deff(a,b,c):returna,b,cassertf._annenforceargs_==(int,str,None)assertf(1,2,3)==(1,2,3)# no typecheckdeftest_enforceargs_translates():frompypy.rpython.lltypesystemimportlltype@enforceargs(int,float)deff(a,b):returna,bgraph=getgraph(f,[int,int])TYPES=[v.concretetypeforvingraph.getargs()]assertTYPES==[lltype.Signed,lltype.Float]deftest_signature_bookkeeping():@signature('x','y',returns='z')deff(a,b):returna+len(b)f.foo='foo'assertf._signature_==(('x','y'),'z')assertf.func_name=='f'assertf.foo=='foo'assertf(1,'hello')==6defannotate_at(f):t=TranslationContext()a=t.buildannotator()a.annotate_helper(f,[model.s_ImpossibleValue]*f.func_code.co_argcount)returnadefsigof(a,f):# returns [param1, param2, ..., ret]g=graphof(a.translator,f)return[a.bindings[v]forving.startblock.inputargs]+[a.bindings[g.getreturnvar()]]defgetsig(f):a=annotate_at(f)returnsigof(a,f)defcheck_annotator_fails(caller):exc=py.test.raises(Exception,annotate_at,caller).valueassertcaller.func_nameinrepr(exc.args)deftest_signature_basic():@signature(types.int(),types.str(),returns=types.char())deff(a,b):returnb[a]assertgetsig(f)==[model.SomeInteger(),model.SomeString(),model.SomeChar()]deftest_signature_arg_errors():@signature(types.int(),types.str(),returns=types.int())deff(a,b):returna+len(b)@check_annotator_failsdefok_for_body():# would give no error without signaturef(2.0,'b')@check_annotator_failsdefbad_for_body():# would give error inside 'f' body, instead errors at callf('a','b')deftest_signature_return():@signature(returns=types.str())deff():return'a'assertgetsig(f)==[model.SomeString()]@signature(types.str(),returns=types.str())deff(x):returnxdefg():returnf('a')a=annotate_at(g)assertsigof(a,f)==[model.SomeString(),model.SomeString()]deftest_signature_return_errors():@check_annotator_fails@signature(returns=types.int())defint_not_char():return'a'@check_annotator_fails@signature(types.str(),returns=types.int())defstr_to_int(s):returnsdeftest_signature_list():@signature(types.list(types.int()),returns=types.int())deff(a):returnlen(a)argtype=getsig(f)[0]assertisinstance(argtype,model.SomeList)item=argtype.listdef.listitemassertitem.s_value==model.SomeInteger()assertitem.resized==True@check_annotator_failsdefok_for_body():f(['a'])@check_annotator_failsdefbad_for_body():f('a')@signature(returns=types.list(types.char()))defff():return['a']@check_annotator_failsdefmutate_broader():ff()[0]='abc'@check_annotator_failsdefmutate_unrelated():ff()[0]=1@check_annotator_fails@signature(types.list(types.char()),returns=types.int())defmutate_in_body(l):l[0]='abc'returnlen(l)defcan_append():l=ff()l.append('b')getsig(can_append)deftest_signature_array():@signature(returns=types.array(types.int()))deff():return[1]rettype=getsig(f)[0]assertisinstance(rettype,model.SomeList)item=rettype.listdef.listitemassertitem.s_value==model.SomeInteger()assertitem.resized==Falsedeftry_append():l=f()l.append(2)check_annotator_fails(try_append)defgetgraph(f,argtypes):frompypy.translator.translatorimportTranslationContext,graphoffrompypy.translator.backendopt.allimportbackend_optimizationst=TranslationContext()a=t.buildannotator()typer=t.buildrtyper()a.build_types(f,argtypes)typer.specialize()backend_optimizations(t)graph=graphof(t,f)ifoption.view:graph.show()returngraphdeftest_newlist():frompypy.annotation.modelimportSomeIntegerdeff(z):x=newlist_hint(sizehint=38)ifz<0:x.append(1)returnlen(x)graph=getgraph(f,[SomeInteger()])forllopingraph.startblock.operations:ifllop.opname=='malloc_varsize':breakassertllop.args[2].value==38deftest_newlist_nonconst():frompypy.annotation.modelimportSomeIntegerdeff(z):x=newlist_hint(sizehint=z)returnlen(x)graph=getgraph(f,[SomeInteger()])forllopingraph.startblock.operations:ifllop.opname=='malloc_varsize':breakassertllop.args[2]isgraph.startblock.inputargs[0]deftest_resizelist_hint():frompypy.annotation.modelimportSomeIntegerdeff(z):x=[]resizelist_hint(x,39)returnlen(x)graph=getgraph(f,[SomeInteger()])for_,opingraph.iterblockops():ifop.opname=='direct_call':breakcall_name=op.args[0].value._obj.graph.nameassertcall_name.startswith('_ll_list_resize_hint')call_arg2=op.args[2].valueassertcall_arg2==39deftest_resizelist_hint_len():deff(i):l=[44]resizelist_hint(l,i)returnlen(l)r=interpret(f,[29])assertr==1