def test_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_any_as_argument(): @signature(types.any(), types.int(), returns=types.float()) def f(x, y): return x + y @signature(types.int(), returns=types.float()) def g(x): return f(x, x) sig = getsig(g) assert sig == [model.SomeInteger(), model.SomeFloat()] @signature(types.float(), returns=types.float()) def g(x): return f(x, 4) sig = getsig(g) assert sig == [model.SomeFloat(), model.SomeFloat()] @signature(types.str(), returns=types.int()) def cannot_add_string(x): return f(x, 2) exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value assert 'Blocked block' in str(exc)
def test_any_as_argument(): @signature(types.any(), types.int(), returns=types.float()) def f(x, y): return x + y @signature(types.int(), returns=types.float()) def g(x): return f(x, x) sig = getsig(g) assert sig == [model.SomeInteger(), model.SomeFloat()] @signature(types.float(), returns=types.float()) def g(x): return f(x, 4) sig = getsig(g) assert sig == [model.SomeFloat(), model.SomeFloat()] @signature(types.str(), returns=types.int()) def cannot_add_string(x): return f(x, 2) exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value assert "Blocked block" in str(exc)
def test_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_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 @signature(returns=types.str()) def str_not_None(): return None @check_annotator_fails def caller_of_str_not_None(): return str_not_None()
def test_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_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_return_any(): @signature(types.int(), returns=types.any()) def f(x): return x sig = getsig(f) assert sig == [model.SomeInteger(), model.SomeInteger()] @signature(types.str(), returns=types.any()) def cannot_add_string(x): return f(3) + x exc = py.test.raises(Exception, annotate_at, cannot_add_string).value assert 'Blocked block' in repr(exc.args) assert 'cannot_add_string' in repr(exc.args)
def test_return_any(): @signature(types.int(), returns=types.any()) def f(x): return x sig = getsig(f) assert sig == [model.SomeInteger(), model.SomeInteger()] @signature(types.str(), returns=types.any()) def cannot_add_string(x): return f(3) + x exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value assert 'Blocked block' in str(exc) assert 'cannot_add_string' in str(exc)
def test_return_any(): @signature(types.int(), returns=types.any()) def f(x): return x sig = getsig(f) assert sig == [model.SomeInteger(), model.SomeInteger()] @signature(types.str(), returns=types.any()) def cannot_add_string(x): return f(3) + x exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value assert "Blocked block" in str(exc) assert "cannot_add_string" in str(exc)
def test_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()]
raise OverflowError elif error == 4: raise ValueError elif error == 5: raise ZeroDivisionError elif error == 6: raise MemoryError elif error == 7: raise KeyError elif error == 8: raise IndexError else: raise RuntimeError @signature(types.str(), returns=types.impossible()) def not_implemented_stub(msg): STDERR = 2 with rffi.scoped_str2charp(msg + '\n') as buf: writeall_not_sandboxed(STDERR, buf, len(msg) + 1) raise RuntimeError(msg) # XXX in RPython, the msg is ignored def make_stub(fnname, msg): """Build always-raising stub function to replace unsupported external.""" log.WARNING(msg) def execute(*args): not_implemented_stub(msg) execute.__name__ = 'sandboxed_%s' % (fnname, )
class Buffer(object): """ Base class for buffers of bytes. Most probably, you do NOT want to use this as a lone base class, but either inherit from RawBuffer or GCBuffer, so that you automatically get the proper implementation of typed_read and typed_write. """ _attrs_ = ['readonly'] _immutable_ = True def getlength(self): """Return the size in bytes.""" raise NotImplementedError def __len__(self): res = self.getlength() assert res >= 0 return res def as_str(self): "Returns an interp-level string with the whole content of the buffer." # May be overridden. return self.getslice(0, 1, self.getlength()) def getitem(self, index): "Returns the index'th character in the buffer." raise NotImplementedError # Must be overriden. No bounds checks. def __getitem__(self, i): return self.getitem(i) def getslice(self, start, step, size): # May be overridden. No bounds checks. lst = ['\x00'] * size for i in range(size): lst[i] = self.getitem(start) start += step return ''.join(lst) @signature(types.any(), types.int(), types.int(), returns=types.str()) def __getslice__(self, start, stop): return self.getslice(start, 1, min(stop, self.getlength()) - start) def setitem(self, index, char): "Write a character into the buffer." raise NotImplementedError # Must be overriden. No bounds checks. def __setitem__(self, i, char): return self.setitem(i, char) def setslice(self, start, string): # May be overridden. No bounds checks. for i in range(len(string)): self.setitem(start + i, string[i]) @jit.look_inside_iff(lambda self, index, count: jit.isconstant(count) and count <= 8) def setzeros(self, index, count): for i in range(index, index + count): self.setitem(i, '\x00') @specialize.ll_and_arg(1) def typed_read(self, TP, byte_offset): """ Read the value of type TP starting at byte_offset. No bounds checks """ raise CannotRead @specialize.ll_and_arg(1) def typed_write(self, TP, byte_offset, value): """ Write the value of type TP at byte_offset. No bounds checks """ raise CannotWrite def get_raw_address(self): msg = "cannot take the raw address of this buffer" if not we_are_translated(): msg += " '%s'" % (self,) raise ValueError(msg)
def test_return_errors_xfail(): @check_annotator_fails @signature(returns=types.str()) def str_not_None(): return None
# no exception; the caller will decode the actual result return loader def reraise_error(error, loader): if error == 1: raise OSError(load_int(loader), "external error") elif error == 2: raise IOError elif error == 3: raise OverflowError elif error == 4: raise ValueError elif error == 5: raise ZeroDivisionError elif error == 6: raise MemoryError elif error == 7: raise KeyError elif error == 8: raise IndexError else: raise RuntimeError @signature(types.str(), returns=types.impossible()) def not_implemented_stub(msg): STDERR = 2 with rffi.scoped_str2charp(msg + '\n') as buf: writeall_not_sandboxed(STDERR, buf, len(msg) + 1) raise RuntimeError(msg) # XXX in RPython, the msg is ignored at the moment dump_string = rmarshal.get_marshaller(str) load_int = rmarshal.get_loader(int) def get_external_function_sandbox_graph(fnobj, db, force_stub=False): """Build the graph of a helper trampoline function to be used in place of real calls to the external function 'fnobj'. The trampoline marshals its input arguments, dumps them to STDOUT, and waits for an answer on STDIN. """