pypy / pypy / rlib / test / test_signature.py

Greg Price 69dc4f2 
Greg Price aefa224 
Greg Price 69dc4f2 






















Greg Price 668eb51 










Greg Price 69dc4f2 








































Greg Price f48ed5f 
Greg Price 0bfc606 





Greg Price f48ed5f 





Greg Price f731001 





Greg Price f48ed5f 
Greg Price 69dc4f2 


















































Greg Price 2fcd49f 
Greg Price 27a3d71 








Greg Price f48ed5f 
Greg Price 2fcd49f 






















Greg Price aefa224 



























import py
from pypy.rlib.signature import signature, finishsigs
from pypy.annotation import types, model
from pypy.translator.translator import TranslationContext, graphof


def annotate_at(f):
    t = TranslationContext()
    a = t.buildannotator()
    a.annotate_helper(f, [model.s_ImpossibleValue]*f.func_code.co_argcount)
    return a

def sigof(a, f):
    # returns [param1, param2, ..., ret]
    g = graphof(a.translator, f)
    return [a.bindings[v] for v in g.startblock.inputargs] + [a.bindings[g.getreturnvar()]]

def getsig(f):
    a = annotate_at(f)
    return sigof(a, f)

def check_annotator_fails(caller):
    exc = py.test.raises(Exception, annotate_at, caller).value
    assert caller.func_name in repr(exc.args)


def test_signature_bookkeeping():
    @signature('x', 'y', returns='z')
    def f(a, b):
        return a + len(b)
    f.foo = 'foo'
    assert f._signature_ == (('x', 'y'), 'z')
    assert f.func_name == 'f'
    assert f.foo == 'foo'
    assert f(1, 'hello') == 6

def test_signature_basic():
    @signature(types.int(), types.str(), returns=types.char())
    def f(a, b):
        return b[a]
    assert getsig(f) == [model.SomeInteger(), model.SomeString(), model.SomeChar()]

def test_signature_arg_errors():
    @signature(types.int(), types.str(), returns=types.int())
    def f(a, b):
        return a + len(b)
    @check_annotator_fails
    def ok_for_body(): # would give no error without signature
        f(2.0, 'b')
    @check_annotator_fails
    def bad_for_body(): # would give error inside 'f' body, instead errors at call
        f('a', 'b')

def test_signature_return():
    @signature(returns=types.str())
    def f():
        return 'a'
    assert getsig(f) == [model.SomeString()]

    @signature(types.str(), returns=types.str())
    def f(x):
        return x
    def g():
        return f('a')
    a = annotate_at(g)
    assert sigof(a, f) == [model.SomeString(), model.SomeString()]

def test_signature_return_errors():
    @check_annotator_fails
    @signature(returns=types.int())
    def int_not_char():
        return 'a'
    @check_annotator_fails
    @signature(types.str(), returns=types.int())
    def str_to_int(s):
        return s


def test_signature_none():
    @signature(returns=types.none())
    def f():
        pass
    assert getsig(f) == [model.s_None]

def test_signature_float():
    @signature(types.longfloat(), types.singlefloat(), returns=types.float())
    def f(a, b):
        return 3.0
    assert getsig(f) == [model.SomeLongFloat(), model.SomeSingleFloat(), model.SomeFloat()]

def test_signature_unicode():
    @signature(types.unicode(), returns=types.int())
    def f(u):
        return len(u)
    assert getsig(f) == [model.SomeUnicodeString(), model.SomeInteger()]


def test_signature_list():
    @signature(types.list(types.int()), returns=types.int())
    def f(a):
        return len(a)
    argtype = getsig(f)[0]
    assert isinstance(argtype, model.SomeList)
    item = argtype.listdef.listitem
    assert item.s_value == model.SomeInteger()
    assert item.resized == True

    @check_annotator_fails
    def ok_for_body():
        f(['a'])
    @check_annotator_fails
    def bad_for_body():
        f('a')

    @signature(returns=types.list(types.char()))
    def ff():
        return ['a']
    @check_annotator_fails
    def mutate_broader():
        ff()[0] = 'abc'
    @check_annotator_fails
    def mutate_unrelated():
        ff()[0] = 1
    @check_annotator_fails
    @signature(types.list(types.char()), returns=types.int())
    def mutate_in_body(l):
        l[0] = 'abc'
        return len(l)

    def can_append():
        l = ff()
        l.append('b')
    getsig(can_append)

def test_signature_array():
    @signature(returns=types.array(types.int()))
    def f():
        return [1]
    rettype = getsig(f)[0]
    assert isinstance(rettype, model.SomeList)
    item = rettype.listdef.listitem
    assert item.s_value == model.SomeInteger()
    assert item.resized == False

    def try_append():
        l = f()
        l.append(2)
    check_annotator_fails(try_append)

def test_signature_dict():
    @signature(returns=types.dict(types.str(), types.int()))
    def f():
        return {'a': 1, 'b': 2}
    rettype = getsig(f)[0]
    assert isinstance(rettype, model.SomeDict)
    assert rettype.dictdef.dictkey.s_value   == model.SomeString()
    assert rettype.dictdef.dictvalue.s_value == model.SomeInteger()


def test_signature_instance():
    class C1(object):
        pass
    class C2(C1):
        pass
    class C3(C2):
        pass
    @signature(types.instance(C3), returns=types.instance(C2))
    def f(x):
        assert isinstance(x, C2)
        return x
    argtype, rettype = getsig(f)
    assert isinstance(argtype, model.SomeInstance)
    assert argtype.classdef.classdesc.pyobj == C3
    assert isinstance(rettype, model.SomeInstance)
    assert rettype.classdef.classdesc.pyobj == C2

    @check_annotator_fails
    def ok_for_body():
        f(C2())
    @check_annotator_fails
    def bad_for_body():
        f(C1())

def test_signature_self():
    @finishsigs
    class C(object):
        @signature(types.self(), types.self(), returns=types.none())
        def f(self, other):
            pass
    class D1(C):
        pass
    class D2(C):
        pass

    def g():
        D1().f(D2())
    a = annotate_at(g)

    argtype = sigof(a, C.__dict__['f'])[0]
    assert isinstance(argtype, model.SomeInstance)
    assert argtype.classdef.classdesc.pyobj == C

def test_signature_self_error():
    class C(object):
        @signature(types.self(), returns=types.none())
        def incomplete_sig_meth(self):
            pass

    exc = py.test.raises(Exception, annotate_at, C.incomplete_sig_meth).value
    assert 'incomplete_sig_meth' in repr(exc.args)
    assert 'finishsigs' in repr(exc.args)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.