/rpython/annotator/test/test_annrpython.py
Python | 4652 lines | 4237 code | 333 blank | 82 comment | 134 complexity | 110d1c09fbd137bc641194cbba8997c5 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- from __future__ import with_statement
- import py.test
- import sys
- from collections import OrderedDict
- from rpython.conftest import option
- from rpython.annotator import model as annmodel
- from rpython.annotator.model import AnnotatorError, UnionError
- from rpython.annotator.annrpython import RPythonAnnotator as _RPythonAnnotator
- from rpython.annotator.classdesc import NoSuchAttrError
- from rpython.translator.translator import graphof as tgraphof
- from rpython.annotator.policy import AnnotatorPolicy
- from rpython.annotator.signature import Sig, SignatureError
- from rpython.annotator.listdef import ListDef, ListChangeUnallowed
- from rpython.annotator.dictdef import DictDef
- from rpython.flowspace.model import *
- from rpython.rlib.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
- from rpython.rlib.rarithmetic import r_singlefloat
- from rpython.rlib import objectmodel
- from rpython.flowspace.flowcontext import FlowingError
- from rpython.flowspace.operation import op
- from rpython.translator.test import snippet
- def graphof(a, func):
- return tgraphof(a.translator, func)
- def listitem(s_list):
- assert isinstance(s_list, annmodel.SomeList)
- return s_list.listdef.listitem.s_value
- def somelist(s_type):
- return annmodel.SomeList(ListDef(None, s_type))
- def dictkey(s_dict):
- assert isinstance(s_dict, annmodel.SomeDict)
- return s_dict.dictdef.dictkey.s_value
- def dictvalue(s_dict):
- assert isinstance(s_dict, annmodel.SomeDict)
- return s_dict.dictdef.dictvalue.s_value
- def somedict(annotator, s_key, s_value):
- return annmodel.SomeDict(DictDef(annotator.bookkeeper, s_key, s_value))
- class TestAnnotateTestCase:
- def teardown_method(self, meth):
- assert annmodel.s_Bool == annmodel.SomeBool()
- class RPythonAnnotator(_RPythonAnnotator):
- def build_types(self, *args):
- s = _RPythonAnnotator.build_types(self, *args)
- self.validate()
- if option.view:
- self.translator.view()
- return s
- def test_simple_func(self):
- """
- one test source:
- def f(x):
- return x+1
- """
- x = Variable("x")
- oper = op.add(x, Constant(1))
- block = Block([x])
- fun = FunctionGraph("f", block)
- block.operations.append(oper)
- block.closeblock(Link([oper.result], fun.returnblock))
- a = self.RPythonAnnotator()
- a.addpendingblock(fun, fun.startblock, [annmodel.SomeInteger()])
- a.complete()
- assert a.gettype(fun.getreturnvar()) == int
- def test_while(self):
- """
- one test source:
- def f(i):
- while i > 0:
- i = i - 1
- return i
- """
- i1 = Variable("i1")
- i2 = Variable("i2")
- conditionop = op.gt(i1, Constant(0))
- decop = op.add(i2, Constant(-1))
- headerblock = Block([i1])
- whileblock = Block([i2])
- fun = FunctionGraph("f", headerblock)
- headerblock.operations.append(conditionop)
- headerblock.exitswitch = conditionop.result
- headerblock.closeblock(Link([i1], fun.returnblock, False),
- Link([i1], whileblock, True))
- whileblock.operations.append(decop)
- whileblock.closeblock(Link([decop.result], headerblock))
- a = self.RPythonAnnotator()
- a.addpendingblock(fun, fun.startblock, [annmodel.SomeInteger()])
- a.complete()
- assert a.gettype(fun.getreturnvar()) == int
- def test_while_sum(self):
- """
- one test source:
- def f(i):
- sum = 0
- while i > 0:
- sum = sum + i
- i = i - 1
- return sum
- """
- i1 = Variable("i1")
- i2 = Variable("i2")
- i3 = Variable("i3")
- sum2 = Variable("sum2")
- sum3 = Variable("sum3")
- conditionop = op.gt(i2, Constant(0))
- decop = op.add(i3, Constant(-1))
- addop = op.add(i3, sum3)
- startblock = Block([i1])
- headerblock = Block([i2, sum2])
- whileblock = Block([i3, sum3])
- fun = FunctionGraph("f", startblock)
- startblock.closeblock(Link([i1, Constant(0)], headerblock))
- headerblock.operations.append(conditionop)
- headerblock.exitswitch = conditionop.result
- headerblock.closeblock(Link([sum2], fun.returnblock, False),
- Link([i2, sum2], whileblock, True))
- whileblock.operations.append(addop)
- whileblock.operations.append(decop)
- whileblock.closeblock(Link([decop.result, addop.result], headerblock))
- a = self.RPythonAnnotator()
- a.addpendingblock(fun, fun.startblock, [annmodel.SomeInteger()])
- a.complete()
- assert a.gettype(fun.getreturnvar()) == int
- def test_f_calls_g(self):
- a = self.RPythonAnnotator()
- s = a.build_types(f_calls_g, [int])
- # result should be an integer
- assert s.knowntype == int
- def test_lists(self):
- a = self.RPythonAnnotator()
- end_cell = a.build_types(snippet.poor_man_rev_range, [int])
- # result should be a list of integers
- assert listitem(end_cell).knowntype == int
- def test_factorial(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.factorial, [int])
- # result should be an integer
- assert s.knowntype == int
- def test_factorial2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.factorial2, [int])
- # result should be an integer
- assert s.knowntype == int
- def test_build_instance(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.build_instance, [])
- # result should be a snippet.C instance
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef == a.bookkeeper.getuniqueclassdef(snippet.C)
- def test_set_attr(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.set_attr, [])
- # result should be an integer
- assert s.knowntype == int
- def test_merge_setattr(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.merge_setattr, [int])
- # result should be an integer
- assert s.knowntype == int
- def test_inheritance1(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.inheritance1, [])
- # result should be exactly:
- assert s == annmodel.SomeTuple([
- a.bookkeeper.immutablevalue(()),
- annmodel.SomeInteger()
- ])
- def test_poor_man_range(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.poor_man_range, [int])
- # result should be a list of integers
- assert listitem(s).knowntype == int
- def test_staticmethod(self):
- class X(object):
- @staticmethod
- def stat(value):
- return value + 4
- def f(v):
- return X().stat(v)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [int])
- assert isinstance(s, annmodel.SomeInteger)
- def test_classmethod(self):
- class X(object):
- @classmethod
- def meth(cls):
- return None
- def f():
- return X().meth()
- a = self.RPythonAnnotator()
- py.test.raises(AnnotatorError, a.build_types, f, [])
- def test_methodcall1(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet._methodcall1, [int])
- # result should be a tuple of (C, positive_int)
- assert s.knowntype == tuple
- assert len(s.items) == 2
- s0 = s.items[0]
- assert isinstance(s0, annmodel.SomeInstance)
- assert s0.classdef == a.bookkeeper.getuniqueclassdef(snippet.C)
- assert s.items[1].knowntype == int
- assert s.items[1].nonneg == True
- def test_classes_methodcall1(self):
- a = self.RPythonAnnotator()
- a.build_types(snippet._methodcall1, [int])
- # the user classes should have the following attributes:
- getcdef = a.bookkeeper.getuniqueclassdef
- assert getcdef(snippet.F).attrs.keys() == ['m']
- assert getcdef(snippet.G).attrs.keys() == ['m2']
- assert getcdef(snippet.H).attrs.keys() == ['attr']
- assert getcdef(snippet.H).about_attribute('attr') == (
- a.bookkeeper.immutablevalue(1))
- def test_generaldict(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.generaldict, [str, int, str, int])
- # result should be an integer
- assert s.knowntype == int
- def test_somebug1(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet._somebug1, [int])
- # result should be a built-in method
- assert isinstance(s, annmodel.SomeBuiltin)
- def test_with_init(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.with_init, [int])
- # result should be an integer
- assert s.knowntype == int
- def test_with_more_init(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.with_more_init, [int, bool])
- # the user classes should have the following attributes:
- getcdef = a.bookkeeper.getuniqueclassdef
- # XXX on which class should the attribute 'a' appear? We only
- # ever flow WithInit.__init__ with a self which is an instance
- # of WithMoreInit, so currently it appears on WithMoreInit.
- assert getcdef(snippet.WithMoreInit).about_attribute('a') == (
- annmodel.SomeInteger())
- assert getcdef(snippet.WithMoreInit).about_attribute('b') == (
- annmodel.SomeBool())
- def test_global_instance(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.global_instance, [])
- # currently this returns the constant 42.
- # XXX not sure this is the best behavior...
- assert s == a.bookkeeper.immutablevalue(42)
- def test_call_five(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.call_five, [])
- # returns should be a list of constants (= 5)
- assert listitem(s) == a.bookkeeper.immutablevalue(5)
- def test_call_five_six(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.call_five_six, [])
- # returns should be a list of positive integers
- assert listitem(s) == annmodel.SomeInteger(nonneg=True)
- def test_constant_result(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.constant_result, [])
- #a.translator.simplify()
- # must return "yadda"
- assert s == a.bookkeeper.immutablevalue("yadda")
- graphs = a.translator.graphs
- assert len(graphs) == 2
- assert graphs[0].func is snippet.constant_result
- assert graphs[1].func is snippet.forty_two
- a.simplify()
- #a.translator.view()
- def test_flow_type_info(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_type_info, [int])
- a.simplify()
- assert s.knowntype == int
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_type_info, [str])
- a.simplify()
- assert s.knowntype == int
- def test_flow_type_info_2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_type_info,
- [annmodel.SomeInteger(nonneg=True)])
- # this checks that isinstance(i, int) didn't lose the
- # actually more precise information that i is non-negative
- assert s == annmodel.SomeInteger(nonneg=True)
- def test_flow_usertype_info(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_usertype_info, [snippet.WithInit])
- #a.translator.view()
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef == a.bookkeeper.getuniqueclassdef(snippet.WithInit)
- def test_flow_usertype_info2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_usertype_info, [snippet.WithMoreInit])
- #a.translator.view()
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef == a.bookkeeper.getuniqueclassdef(snippet.WithMoreInit)
- def test_mergefunctions(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.mergefunctions, [int])
- # the test is mostly that the above line hasn't blown up
- # but let's at least check *something*
- assert isinstance(s, annmodel.SomePBC)
- def test_func_calls_func_which_just_raises(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.funccallsex, [])
- # the test is mostly that the above line hasn't blown up
- # but let's at least check *something*
- #self.assert_(isinstance(s, SomeCallable))
- def test_tuple_unpack_from_const_tuple_with_different_types(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.func_arg_unpack, [])
- assert isinstance(s, annmodel.SomeInteger)
- assert s.const == 3
- def test_star_unpack_list(self):
- def g():
- pass
- def f(l):
- return g(*l)
- a = self.RPythonAnnotator()
- with py.test.raises(AnnotatorError):
- a.build_types(f, [[int]])
- def test_star_unpack_and_keywords(self):
- def g(a, b, c=0, d=0):
- return a + b + c + d
- def f(a, b):
- return g(a, *(b,), d=5)
- a = self.RPythonAnnotator()
- s_result = a.build_types(f, [int, int])
- assert isinstance(s_result, annmodel.SomeInteger)
- def test_pbc_attr_preserved_on_instance(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.preserve_pbc_attr_on_instance, [bool])
- #a.simplify()
- #a.translator.view()
- assert s == annmodel.SomeInteger(nonneg=True)
- #self.assertEquals(s.__class__, annmodel.SomeInteger)
- def test_pbc_attr_preserved_on_instance_with_slots(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.preserve_pbc_attr_on_instance_with_slots,
- [bool])
- assert s == annmodel.SomeInteger(nonneg=True)
- def test_is_and_knowntype_data(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.is_and_knowntype, [str])
- #a.simplify()
- #a.translator.view()
- assert s == a.bookkeeper.immutablevalue(None)
- def test_isinstance_and_knowntype_data(self):
- a = self.RPythonAnnotator()
- x = a.bookkeeper.immutablevalue(snippet.apbc)
- s = a.build_types(snippet.isinstance_and_knowntype, [x])
- #a.simplify()
- #a.translator.view()
- assert s == x
- def test_somepbc_simplify(self):
- a = self.RPythonAnnotator()
- # this example used to trigger an AssertionError
- a.build_types(snippet.somepbc_simplify, [])
- def test_builtin_methods(self):
- a = self.RPythonAnnotator()
- iv = a.bookkeeper.immutablevalue
- # this checks that some built-in methods are really supported by
- # the annotator (it doesn't check that they operate property, though)
- for example, methname, s_example in [
- ('', 'join', annmodel.SomeString()),
- ([], 'append', somelist(annmodel.s_Int)),
- ([], 'extend', somelist(annmodel.s_Int)),
- ([], 'reverse', somelist(annmodel.s_Int)),
- ([], 'insert', somelist(annmodel.s_Int)),
- ([], 'pop', somelist(annmodel.s_Int)),
- ]:
- constmeth = getattr(example, methname)
- s_constmeth = iv(constmeth)
- assert isinstance(s_constmeth, annmodel.SomeBuiltin)
- s_meth = s_example.getattr(iv(methname))
- assert isinstance(s_constmeth, annmodel.SomeBuiltin)
- def test_str_join(self):
- a = self.RPythonAnnotator()
- def g(n):
- if n:
- return ["foo", "bar"]
- def f(n):
- g(0)
- return ''.join(g(n))
- s = a.build_types(f, [int])
- assert s.knowntype == str
- assert s.no_nul
- def test_unicode_join(self):
- a = self.RPythonAnnotator()
- def g(n):
- if n:
- return [u"foo", u"bar"]
- def f(n):
- g(0)
- return u''.join(g(n))
- s = a.build_types(f, [int])
- assert s.knowntype == unicode
- assert s.no_nul
- def test_str_split(self):
- a = self.RPythonAnnotator()
- def g(n):
- if n:
- return "test string"
- def f(n):
- if n:
- return g(n).split(' ')
- s = a.build_types(f, [int])
- assert isinstance(s, annmodel.SomeList)
- s_item = s.listdef.listitem.s_value
- assert s_item.no_nul
- def test_unicode_split(self):
- a = self.RPythonAnnotator()
- def g(n):
- if n:
- return u"test string"
- def f(n):
- if n:
- return g(n).split(u' ')
- s = a.build_types(f, [int])
- assert isinstance(s, annmodel.SomeList)
- s_item = s.listdef.listitem.s_value
- assert s_item.no_nul
- def test_str_split_nul(self):
- def f(n):
- return n.split('\0')[0]
- a = self.RPythonAnnotator()
- a.translator.config.translation.check_str_without_nul = True
- s = a.build_types(f, [annmodel.SomeString(no_nul=False, can_be_None=False)])
- assert isinstance(s, annmodel.SomeString)
- assert not s.can_be_None
- assert s.no_nul
- def g(n):
- return n.split('\0', 1)[0]
- a = self.RPythonAnnotator()
- a.translator.config.translation.check_str_without_nul = True
- s = a.build_types(g, [annmodel.SomeString(no_nul=False, can_be_None=False)])
- assert isinstance(s, annmodel.SomeString)
- assert not s.can_be_None
- assert not s.no_nul
- def test_unicode_split_nul(self):
- def f(n):
- return n.split(u'\0')[0]
- a = self.RPythonAnnotator()
- a.translator.config.translation.check_str_without_nul = True
- s = a.build_types(f, [annmodel.SomeUnicodeString(
- no_nul=False, can_be_None=False)])
- assert isinstance(s, annmodel.SomeUnicodeString)
- assert not s.can_be_None
- assert s.no_nul
- def g(n):
- return n.split(u'\0', 1)[0]
- a = self.RPythonAnnotator()
- a.translator.config.translation.check_str_without_nul = True
- s = a.build_types(g, [annmodel.SomeUnicodeString(
- no_nul=False, can_be_None=False)])
- assert isinstance(s, annmodel.SomeUnicodeString)
- assert not s.can_be_None
- assert not s.no_nul
- def test_str_splitlines(self):
- a = self.RPythonAnnotator()
- def f(a_str):
- return a_str.splitlines()
- s = a.build_types(f, [str])
- assert isinstance(s, annmodel.SomeList)
- assert s.listdef.listitem.resized
- def test_str_strip(self):
- a = self.RPythonAnnotator()
- def f(n, a_str):
- if n == 0:
- return a_str.strip(' ')
- elif n == 1:
- return a_str.rstrip(' ')
- else:
- return a_str.lstrip(' ')
- s = a.build_types(f, [int, annmodel.SomeString(no_nul=True)])
- assert s.no_nul
- def test_unicode_strip(self):
- a = self.RPythonAnnotator()
- def f(n, a_str):
- if n == 0:
- return a_str.strip(u' ')
- elif n == 1:
- return a_str.rstrip(u' ')
- else:
- return a_str.lstrip(u' ')
- s = a.build_types(f, [int, annmodel.SomeUnicodeString(no_nul=True)])
- assert s.no_nul
- def test_str_mul(self):
- a = self.RPythonAnnotator()
- def f(a_str):
- return a_str * 3
- s = a.build_types(f, [str])
- assert isinstance(s, annmodel.SomeString)
- def test_str_isalpha(self):
- def f(s):
- return s.isalpha()
- a = self.RPythonAnnotator()
- s = a.build_types(f, [str])
- assert isinstance(s, annmodel.SomeBool)
- def test_simple_slicing(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.simple_slice, [somelist(annmodel.s_Int)])
- assert isinstance(s, annmodel.SomeList)
- def test_simple_iter_list(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.simple_iter, [somelist(annmodel.s_Int)])
- assert isinstance(s, annmodel.SomeIterator)
- def test_simple_iter_next(self):
- def f(x):
- i = iter(range(x))
- return i.next()
- a = self.RPythonAnnotator()
- s = a.build_types(f, [int])
- assert isinstance(s, annmodel.SomeInteger)
- def test_simple_iter_dict(self):
- a = self.RPythonAnnotator()
- t = somedict(a, annmodel.SomeInteger(), annmodel.SomeInteger())
- s = a.build_types(snippet.simple_iter, [t])
- assert isinstance(s, annmodel.SomeIterator)
- def test_simple_zip(self):
- a = self.RPythonAnnotator()
- x = somelist(annmodel.SomeInteger())
- y = somelist(annmodel.SomeString())
- s = a.build_types(snippet.simple_zip, [x,y])
- assert s.knowntype == list
- assert listitem(s).knowntype == tuple
- assert listitem(s).items[0].knowntype == int
- assert listitem(s).items[1].knowntype == str
- def test_dict_copy(self):
- a = self.RPythonAnnotator()
- t = somedict(a, annmodel.SomeInteger(), annmodel.SomeInteger())
- s = a.build_types(snippet.dict_copy, [t])
- assert isinstance(dictkey(s), annmodel.SomeInteger)
- assert isinstance(dictvalue(s), annmodel.SomeInteger)
- def test_dict_update(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_update, [int])
- assert isinstance(dictkey(s), annmodel.SomeInteger)
- assert isinstance(dictvalue(s), annmodel.SomeInteger)
- def test_dict_update_2(self):
- a = self.RPythonAnnotator()
- def g(n):
- if n:
- return {3: 4}
- def f(n):
- g(0)
- d = {}
- d.update(g(n))
- return d
- s = a.build_types(f, [int])
- assert dictkey(s).knowntype == int
- def test_dict_keys(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_keys, [])
- assert isinstance(listitem(s), annmodel.SomeString)
- def test_dict_keys2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_keys2, [])
- assert type(listitem(s)) is annmodel.SomeString
- def test_dict_values(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_values, [])
- assert isinstance(listitem(s), annmodel.SomeString)
- def test_dict_values2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_values2, [])
- assert type(listitem(s)) is annmodel.SomeString
- def test_dict_items(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_items, [])
- assert isinstance(listitem(s), annmodel.SomeTuple)
- s_key, s_value = listitem(s).items
- assert isinstance(s_key, annmodel.SomeString)
- assert isinstance(s_value, annmodel.SomeInteger)
- def test_dict_setdefault(self):
- a = self.RPythonAnnotator()
- def f():
- d = {}
- d.setdefault('a', 2)
- d.setdefault('a', -3)
- return d
- s = a.build_types(f, [])
- assert isinstance(s, annmodel.SomeDict)
- assert isinstance(dictkey(s), annmodel.SomeString)
- assert isinstance(dictvalue(s), annmodel.SomeInteger)
- assert not dictvalue(s).nonneg
- def test_exception_deduction(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exception_deduction, [])
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
- def test_exception_deduction_we_are_dumb(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exception_deduction_we_are_dumb, [])
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
- def test_nested_exception_deduction(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.nested_exception_deduction, [])
- assert isinstance(s, annmodel.SomeTuple)
- assert isinstance(s.items[0], annmodel.SomeInstance)
- assert isinstance(s.items[1], annmodel.SomeInstance)
- assert s.items[0].classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
- assert s.items[1].classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc2)
- def test_exc_deduction_our_exc_plus_others(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exc_deduction_our_exc_plus_others, [])
- assert isinstance(s, annmodel.SomeInteger)
- def test_exc_deduction_our_excs_plus_others(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exc_deduction_our_excs_plus_others, [])
- assert isinstance(s, annmodel.SomeInteger)
- def test_complex_exception_deduction(self):
- class InternalError(Exception):
- def __init__(self, msg):
- self.msg = msg
- class AppError(Exception):
- def __init__(self, msg):
- self.msg = msg
- def apperror(msg):
- return AppError(msg)
- def f(string):
- if not string:
- raise InternalError('Empty string')
- return string, None
- def cleanup():
- pass
- def g(string):
- try:
- try:
- string, _ = f(string)
- except ZeroDivisionError:
- raise apperror('ZeroDivisionError')
- try:
- result, _ = f(string)
- finally:
- cleanup()
- except InternalError as e:
- raise apperror(e.msg)
- return result
- a = self.RPythonAnnotator()
- s_result = a.build_types(g, [str])
- assert isinstance(s_result, annmodel.SomeString)
- def test_method_exception_specialization(self):
- def f(l):
- try:
- return l.pop()
- except Exception:
- raise
- a = self.RPythonAnnotator()
- s = a.build_types(f, [[int]])
- graph = graphof(a, f)
- etype, evalue = graph.exceptblock.inputargs
- assert evalue.annotation.classdefs == {
- a.bookkeeper.getuniqueclassdef(IndexError)}
- assert etype.annotation.const == IndexError
- def test_operation_always_raising(self):
- def operation_always_raising(n):
- lst = []
- try:
- return lst[n]
- except IndexError:
- return 24
- a = self.RPythonAnnotator()
- s = a.build_types(operation_always_raising, [int])
- assert s == a.bookkeeper.immutablevalue(24)
- def test_propagation_of_fresh_instances_through_attrs(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.propagation_of_fresh_instances_through_attrs, [int])
- assert s is not None
- def test_propagation_of_fresh_instances_through_attrs_rec_0(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.make_r, [int])
- Rdef = a.bookkeeper.getuniqueclassdef(snippet.R)
- assert s.classdef == Rdef
- assert Rdef.attrs['r'].s_value.classdef == Rdef
- assert Rdef.attrs['n'].s_value.knowntype == int
- assert Rdef.attrs['m'].s_value.knowntype == int
- def test_propagation_of_fresh_instances_through_attrs_rec_eo(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.make_eo, [int])
- assert s.classdef == a.bookkeeper.getuniqueclassdef(snippet.B)
- Even_def = a.bookkeeper.getuniqueclassdef(snippet.Even)
- Odd_def = a.bookkeeper.getuniqueclassdef(snippet.Odd)
- assert listitem(Even_def.attrs['x'].s_value).classdef == Odd_def
- assert listitem(Even_def.attrs['y'].s_value).classdef == Even_def
- assert listitem(Odd_def.attrs['x'].s_value).classdef == Even_def
- assert listitem(Odd_def.attrs['y'].s_value).classdef == Odd_def
- def test_flow_rev_numbers(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_rev_numbers, [int])
- assert s.knowntype == int
- assert not s.is_constant() # !
- def test_methodcall_is_precise(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.methodcall_is_precise, [bool])
- getcdef = a.bookkeeper.getuniqueclassdef
- assert 'x' not in getcdef(snippet.CBase).attrs
- assert (getcdef(snippet.CSub1).attrs['x'].s_value ==
- a.bookkeeper.immutablevalue(42))
- assert (getcdef(snippet.CSub2).attrs['x'].s_value ==
- a.bookkeeper.immutablevalue('world'))
- assert s == a.bookkeeper.immutablevalue(42)
- def test_call_star_args(self):
- a = self.RPythonAnnotator(policy=AnnotatorPolicy())
- s = a.build_types(snippet.call_star_args, [int])
- assert s.knowntype == int
- def test_call_star_args_multiple(self):
- a = self.RPythonAnnotator(policy=AnnotatorPolicy())
- s = a.build_types(snippet.call_star_args_multiple, [int])
- assert s.knowntype == int
- def test_exception_deduction_with_raise1(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exception_deduction_with_raise1, [bool])
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
- def test_exception_deduction_with_raise2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exception_deduction_with_raise2, [bool])
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
- def test_exception_deduction_with_raise3(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.exception_deduction_with_raise3, [bool])
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
- def test_type_is(self):
- class B(object):
- pass
- class C(B):
- pass
- def f(x):
- assert type(x) is C
- return x
- a = self.RPythonAnnotator()
- s = a.build_types(f, [B])
- assert s.classdef is a.bookkeeper.getuniqueclassdef(C)
- @py.test.mark.xfail
- def test_union_type_some_pbc(self):
- class A(object):
- name = "A"
- def f(self):
- return type(self)
- class B(A):
- name = "B"
- def f(tp):
- return tp
- def main(n):
- if n:
- if n == 1:
- inst = A()
- else:
- inst = B()
- arg = inst.f()
- else:
- arg = B
- return f(arg).name
- a = self.RPythonAnnotator()
- s = a.build_types(main, [int])
- assert isinstance(s, annmodel.SomeString)
- def test_ann_assert(self):
- def assert_(x):
- assert x,"XXX"
- a = self.RPythonAnnotator()
- s = a.build_types(assert_, [int])
- assert s.const is None
- def test_string_and_none(self):
- def f(n):
- if n:
- return 'y'
- else:
- return 'n'
- def g(n):
- if n:
- return 'y'
- else:
- return None
- a = self.RPythonAnnotator()
- s = a.build_types(f, [bool])
- assert s.knowntype == str
- assert not s.can_be_None
- s = a.build_types(g, [bool])
- assert s.knowntype == str
- assert s.can_be_None
- def test_implicit_exc(self):
- def f(l):
- try:
- l[0]
- except (KeyError, IndexError) as e:
- return e
- return None
- a = self.RPythonAnnotator()
- s = a.build_types(f, [somelist(annmodel.s_Int)])
- assert s.classdef is a.bookkeeper.getuniqueclassdef(IndexError) # KeyError ignored because l is a list
- def test_freeze_protocol(self):
- class Stuff:
- def __init__(self):
- self.called = False
- def _freeze_(self):
- self.called = True
- return True
- myobj = Stuff()
- a = self.RPythonAnnotator()
- s = a.build_types(lambda: myobj, [])
- assert myobj.called
- assert isinstance(s, annmodel.SomePBC)
- assert s.const == myobj
- def test_cleanup_protocol(self):
- class Stuff:
- def __init__(self):
- self.called = False
- def _cleanup_(self):
- self.called = True
- myobj = Stuff()
- a = self.RPythonAnnotator()
- s = a.build_types(lambda: myobj, [])
- assert myobj.called
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef is a.bookkeeper.getuniqueclassdef(Stuff)
- def test_circular_mutable_getattr(self):
- class C:
- pass
- c = C()
- c.x = c
- def f():
- return c.x
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert isinstance(s, annmodel.SomeInstance)
- assert s.classdef == a.bookkeeper.getuniqueclassdef(C)
- def test_circular_list_type(self):
- def f(n):
- lst = []
- for i in range(n):
- lst = [lst]
- return lst
- a = self.RPythonAnnotator()
- s = a.build_types(f, [int])
- assert listitem(s) == s
- def test_harmonic(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.harmonic, [int])
- assert s.knowntype == float
- # check that the list produced by range() is not mutated or resized
- graph = graphof(a, snippet.harmonic)
- all_vars = set().union(*[block.getvariables() for block in graph.iterblocks()])
- print all_vars
- for var in all_vars:
- s_value = var.annotation
- if isinstance(s_value, annmodel.SomeList):
- assert not s_value.listdef.listitem.resized
- assert not s_value.listdef.listitem.mutated
- assert s_value.listdef.listitem.range_step
- def test_bool(self):
- def f(a,b):
- return bool(a) or bool(b)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [int, somelist(annmodel.s_Int)])
- assert s.knowntype == bool
- def test_float(self):
- def f(n):
- return float(n)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [int])
- assert s.knowntype == float
- def test_r_uint(self):
- def f(n):
- return n + constant_unsigned_five
- a = self.RPythonAnnotator()
- s = a.build_types(f, [r_uint])
- assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
- def test_large_unsigned(self):
- large_constant = sys.maxint * 2 + 1 # 0xFFFFFFFF on 32-bit platforms
- def f():
- return large_constant
- a = self.RPythonAnnotator()
- with py.test.raises(ValueError):
- a.build_types(f, [])
- # if you want to get a r_uint, you have to be explicit about it
- def test_add_different_ints(self):
- def f(a, b):
- return a + b
- a = self.RPythonAnnotator()
- with py.test.raises(UnionError):
- a.build_types(f, [r_uint, int])
- def test_merge_different_ints(self):
- def f(a, b):
- if a:
- c = a
- else:
- c = b
- return c
- a = self.RPythonAnnotator()
- with py.test.raises(UnionError):
- a.build_types(f, [r_uint, int])
- def test_merge_ruint_zero(self):
- def f(a):
- if a:
- c = a
- else:
- c = 0
- return c
- a = self.RPythonAnnotator()
- s = a.build_types(f, [r_uint])
- assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
- def test_merge_ruint_nonneg_signed(self):
- def f(a, b):
- if a:
- c = a
- else:
- assert b >= 0
- c = b
- return c
- a = self.RPythonAnnotator()
- s = a.build_types(f, [r_uint, int])
- assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
- def test_prebuilt_long_that_is_not_too_long(self):
- small_constant = 12L
- def f():
- return small_constant
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.const == 12
- assert s.nonneg
- assert not s.unsigned
- #
- small_constant = -23L
- def f():
- return small_constant
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.const == -23
- assert not s.nonneg
- assert not s.unsigned
- def test_pbc_getattr(self):
- class C:
- def __init__(self, v1, v2):
- self.v2 = v2
- self.v1 = v1
- def _freeze_(self):
- return True
- c1 = C(1,'a')
- c2 = C(2,'b')
- c3 = C(3,'c')
- def f1(l, c):
- l.append(c.v1)
- def f2(l, c):
- l.append(c.v2)
- def g():
- l1 = []
- l2 = []
- f1(l1, c1)
- f1(l1, c2)
- f2(l2, c2)
- f2(l2, c3)
- return l1,l2
- a = self.RPythonAnnotator()
- s = a.build_types(g,[])
- l1, l2 = s.items
- assert listitem(l1).knowntype == int
- assert listitem(l2).knowntype == str
- acc1 = a.bookkeeper.getdesc(c1).getattrfamily()
- acc2 = a.bookkeeper.getdesc(c2).getattrfamily()
- acc3 = a.bookkeeper.getdesc(c3).getattrfamily()
- assert acc1 is acc2 is acc3
- assert len(acc1.descs) == 3
- assert dict.fromkeys(acc1.attrs) == {'v1': None, 'v2': None}
- def test_single_pbc_getattr(self):
- class C:
- def __init__(self, v1, v2):
- self.v1 = v1
- self.v2 = v2
- def _freeze_(self):
- return True
- c1 = C(11, "hello")
- c2 = C(22, 623)
- def f1(l, c):
- l.append(c.v1)
- def f2(c):
- return c.v2
- def f3(c):
- return c.v2
- def g():
- l = []
- f1(l, c1)
- f1(l, c2)
- return l, f2(c1), f3(c2)
- a = self.RPythonAnnotator()
- s = a.build_types(g,[])
- s_l, s_c1v2, s_c2v2 = s.items
- assert listitem(s_l).knowntype == int
- assert s_c1v2.const == "hello"
- assert s_c2v2.const == 623
- acc1 = a.bookkeeper.getdesc(c1).getattrfamily()
- acc2 = a.bookkeeper.getdesc(c2).getattrfamily()
- assert acc1 is acc2
- assert acc1.attrs.keys() == ['v1']
- def test_isinstance_unsigned_1(self):
- def f(x):
- return isinstance(x, r_uint)
- def g():
- v = r_uint(1)
- return f(v)
- a = self.RPythonAnnotator()
- s = a.build_types(g, [])
- assert s.const == True
- def test_isinstance_unsigned_2(self):
- class Foo:
- pass
- def f(x):
- return isinstance(x, r_uint)
- def g():
- v = Foo()
- return f(v)
- a = self.RPythonAnnotator()
- s = a.build_types(g, [])
- assert s.const == False
- def test_isinstance_base_int(self):
- def f(x):
- return isinstance(x, base_int)
- def g(n):
- v = r_uint(n)
- return f(v)
- a = self.RPythonAnnotator()
- s = a.build_types(g, [int])
- assert s.const == True
- def test_isinstance_basic(self):
- def f():
- return isinstance(IndexError(), type)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.const == False
- def test_alloc_like(self):
- class Base(object):
- pass
- class C1(Base):
- pass
- class C2(Base):
- pass
- def inst(cls):
- return cls()
- def alloc(cls):
- i = inst(cls)
- assert isinstance(i, cls)
- return i
- alloc._annspecialcase_ = "specialize:arg(0)"
- def f():
- c1 = alloc(C1)
- c2 = alloc(C2)
- return c1,c2
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- C1df = a.bookkeeper.getuniqueclassdef(C1)
- C2df = a.bookkeeper.getuniqueclassdef(C2)
- assert s.items[0].classdef == C1df
- assert s.items[1].classdef == C2df
- allocdesc = a.bookkeeper.getdesc(alloc)
- s_C1 = a.bookkeeper.immutablevalue(C1)
- s_C2 = a.bookkeeper.immutablevalue(C2)
- graph1 = allocdesc.specialize([s_C1], None)
- graph2 = allocdesc.specialize([s_C2], None)
- assert a.binding(graph1.getreturnvar()).classdef == C1df
- assert a.binding(graph2.getreturnvar()).classdef == C2df
- assert graph1 in a.translator.graphs
- assert graph2 in a.translator.graphs
- def test_specialcase_args(self):
- class C1(object):
- pass
- class C2(object):
- pass
- def alloc(cls, cls2):
- i = cls()
- assert isinstance(i, cls)
- j = cls2()
- assert isinstance(j, cls2)
- return i
- def f():
- alloc(C1, C1)
- alloc(C1, C2)
- alloc(C2, C1)
- alloc(C2, C2)
- alloc._annspecialcase_ = "specialize:arg(0,1)"
- a = self.RPythonAnnotator()
- C1df = a.bookkeeper.getuniqueclassdef(C1)
- C2df = a.bookkeeper.getuniqueclassdef(C2)
- s = a.build_types(f, [])
- allocdesc = a.bookkeeper.getdesc(alloc)
- s_C1 = a.bookkeeper.immutablevalue(C1)
- s_C2 = a.bookkeeper.immutablevalue(C2)
- graph1 = allocdesc.specialize([s_C1, s_C2], None)
- graph2 = allocdesc.specialize([s_C2, s_C2], None)
- assert a.binding(graph1.getreturnvar()).classdef == C1df
- assert a.binding(graph2.getreturnvar()).classdef == C2df
- assert graph1 in a.translator.graphs
- assert graph2 in a.translator.graphs
- def test_specialize_arg_bound_method(self):
- class GC(object):
- def trace(self, callback, *args):
- return callback(*args)
- trace._annspecialcase_ = "specialize:arg(1)"
- def callback1(self, arg1):
- self.x = arg1
- return "hello"
- def callback2(self, arg2, arg3):
- self.y = arg2
- self.z = arg3
- return 6
- def f():
- gc = GC()
- s1 = gc.trace(gc.callback1, "foo")
- n2 = gc.trace(gc.callback2, 7, 2)
- return (s1, n2, gc.x, gc.y, gc.z)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.items[0].const == "hello"
- assert s.items[1].const == 6
- assert s.items[2].const == "foo"
- assert s.items[3].const == 7
- assert s.items[4].const == 2
- def test_specialize_and_star_args(self):
- class I(object):
- def execute(self, op, *args):
- if op == 0:
- return args[0]+args[1]
- if op == 1:
- return args[0] * args[1] + args[2]
- execute._annspecialcase_ = "specialize:arg(1)"
- def f(x, y):
- i = I()
- a = i.execute(0, x, y)
- b = i.execute(1, y, y, 5)
- return a+b
- a = self.RPythonAnnotator()
- s = a.build_types(f, [int, int])
- executedesc = a.bookkeeper.getdesc(I.execute.im_func)
- assert len(executedesc._cache) == 2
- assert len(executedesc._cache[(0, 'star', 2)].startblock.inputargs) == 4
- assert len(executedesc._cache[(1, 'star', 3)].startblock.inputargs) == 5
- def test_specialize_arg_or_var(self):
- def f(a):
- return 1
- f._annspecialcase_ = 'specialize:arg_or_var(0)'
- def fn(a):
- return f(3) + f(a)
- a = self.RPythonAnnotator()
- a.build_types(fn, [int])
- executedesc = a.bookkeeper.getdesc(f)
- assert sorted(executedesc._cache.keys()) == [None, (3,)]
- # we got two different special
- def test_specialize_call_location(self):
- def g(a):
- return a
- g._annspecialcase_ = "specialize:call_location"
- def f(x):
- return g(x)
- f._annspecialcase_ = "specialize:argtype(0)"
- def h(y):
- w = f(y)
- return int(f(str(y))) + w
- a = self.RPythonAnnotator()
- assert a.build_types(h, [int]) == annmodel.SomeInteger()
- def test_assert_list_doesnt_lose_info(self):
- class T(object):
- pass
- def g(l):
- assert isinstance(l, list)
- return l
- def f():
- l = [T()]
- return g(l)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- s_item = listitem(s)
- assert isinstance(s_item, annmodel.SomeInstance)
- assert s_item.classdef is a.bookkeeper.getuniqueclassdef(T)
- def test_int_str_mul(self):
- def f(x,a,b):
- return a*x+x*b
- a = self.RPythonAnnotator()
- s = a.build_types(f, [str,int,int])
- assert s.knowntype == str
- def test_list_tuple(self):
- def g0(x):
- return list(x)
- def g1(x):
- return list(x)
- def f(n):
- l1 = g0(())
- l2 = g1((1,))
- if n:
- t = (1,)
- else:
- t = (2,)
- l3 = g1(t)
- return l1, l2, l3
- a = self.RPythonAnnotator()
- s = a.build_types(f, [bool])
- assert listitem(s.items[0]) == annmodel.SomeImpossibleValue()
- assert listitem(s.items[1]).knowntype == int
- assert listitem(s.items[2]).knowntype == int
- def test_empty_list(self):
- def f():
- l = []
- return bool(l)
- def g():
- l = []
- x = bool(l)
- l.append(1)
- return x, bool(l)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.const == False
- a = self.RPythonAnnotator()
- s = a.build_types(g, [])
- assert s.items[0].knowntype == bool and not s.items[0].is_constant()
- assert s.items[1].knowntype == bool and not s.items[1].is_constant()
- def test_empty_dict(self):
- def f():
- d = {}
- return bool(d)
- def g():
- d = {}
- x = bool(d)
- d['a'] = 1
- return x, bool(d)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.const == False
- a = self.RPythonAnnotator()
- s = a.build_types(g, [])
- assert s.items[0].knowntype == bool and not s.items[0].is_constant()
- assert s.items[1].knowntype == bool and not s.items[1].is_constant()
- def test_call_two_funcs_but_one_can_only_raise(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.call_two_funcs_but_one_can_only_raise,
- [int])
- assert s == a.bookkeeper.immutablevalue(None)
- def test_reraiseKeyError(self):
- def f(dic):
- try:
- dic[5]
- except KeyError:
- raise
- a = self.RPythonAnnotator()
- a.build_types(f, [somedict(a, annmodel.s_Int, annmodel.s_Int)])
- fg = graphof(a, f)
- et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeTypeOf([ev])
- t.const = KeyError
- assert et.annotation == t
- s_ev = ev.annotation
- assert s_ev == a.bookkeeper.new_exception([KeyError])
- def test_reraiseAnything(self):
- def f(dic):
- try:
- dic[5]
- except:
- raise
- a = self.RPythonAnnotator()
- a.build_types(f, [somedict(a, annmodel.s_Int, annmodel.s_Int)])
- fg = graphof(a, f)
- et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeTypeOf([ev])
- t.const = KeyError # IndexError ignored because 'dic' is a dict
- assert et.annotation == t
- s_ev = ev.annotation
- assert s_ev == a.bookkeeper.new_exception([KeyError])
- def test_exception_mixing(self):
- def h():
- pass
- def g():
- pass
- class X(Exception):
- def __init__(self, x=0):
- self.x = x
- def f(a, l):
- if a==1:
- raise X
- elif a==2:
- raise X(1)
- elif a==3:
- raise X(4)
- else:
- try:
- l[0]
- x,y = l
- g()
- finally:
- h()
- a = self.RPythonAnnotator()
- a.build_types(f, [int, somelist(annmodel.s_Int)])
- fg = graphof(a, f)
- et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeTypeOf([ev])
- assert et.annotation == t
- s_ev = ev.annotation
- assert (isinstance(s_ev, annmodel.SomeInstance) and
- s_ev.classdef == a.bookkeeper.getuniqueclassdef(Exception))
- def test_try_except_raise_finally1(self):
- def h(): pass
- def g(): pass
- class …
Large files files are truncated, but you can click here to view the full file