Author: Manuel Jacob Branch: refactor-str-types Changeset: r66679:a8ceea5620aa Date: 2013-08-30 16:07 +0100 http://bitbucket.org/pypy/pypy/changeset/a8ceea5620aa/
Log: hg merge default diff --git a/lib-python/2.7/uuid.py b/lib-python/2.7/uuid.py --- a/lib-python/2.7/uuid.py +++ b/lib-python/2.7/uuid.py @@ -44,6 +44,8 @@ UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') """ +import struct + __author__ = 'Ka-Ping Yee <p...@zesty.ca>' RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ @@ -142,7 +144,8 @@ if bytes is not None: if len(bytes) != 16: raise ValueError('bytes is not a 16-char string') - int = long(('%02x'*16) % tuple(map(ord, bytes)), 16) + int = (struct.unpack('>Q', bytes[:8])[0] << 64 | + struct.unpack('>Q', bytes[8:])[0]) if fields is not None: if len(fields) != 6: raise ValueError('fields is not a 6-tuple') diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1229,7 +1229,10 @@ if cvt is not None: param = cvt(param) - param = adapt(param) + try: + param = adapt(param) + except: + pass # And use previous value if param is None: rc = _lib.sqlite3_bind_null(self._statement, idx) diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py --- a/lib_pypy/datetime.py +++ b/lib_pypy/datetime.py @@ -40,9 +40,9 @@ # for all computations. See the book for algorithms for converting between # proleptic Gregorian ordinals and many other calendar systems. -_DAYS_IN_MONTH = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] +_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] -_DAYS_BEFORE_MONTH = [None] +_DAYS_BEFORE_MONTH = [-1] dbm = 0 for dim in _DAYS_IN_MONTH[1:]: _DAYS_BEFORE_MONTH.append(dbm) diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -396,6 +396,8 @@ class W_UnicodeBox(W_CharacterBox): def descr__new__unicode_box(space, w_subtype, w_arg): + raise OperationError(space.w_NotImplementedError, space.wrap("Unicode is not supported yet")) + from pypy.module.micronumpy.interp_dtype import new_unicode_dtype arg = space.unicode_w(space.unicode_from_object(w_arg)) diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -88,13 +88,27 @@ w_res = W_NDimArray.from_shape(space, res_shape, self.get_dtype(), w_instance=self) return loop.getitem_filter(w_res, self, arr) - def setitem_filter(self, space, idx, val): + def setitem_filter(self, space, idx, value): + from pypy.module.micronumpy.interp_boxes import Box + val = value if len(idx.get_shape()) > 1 and idx.get_shape() != self.get_shape(): raise OperationError(space.w_ValueError, space.wrap("boolean index array should have 1 dimension")) if idx.get_size() > self.get_size(): raise OperationError(space.w_ValueError, space.wrap("index out of range for array")) + idx_iter = idx.create_iter(self.get_shape()) + size = loop.count_all_true_iter(idx_iter, self.get_shape(), idx.get_dtype()) + if len(val.get_shape()) > 0 and val.get_shape()[0] > 1 and size > val.get_shape()[0]: + raise OperationError(space.w_ValueError, space.wrap("NumPy boolean array indexing assignment " + "cannot assign %d input values to " + "the %d output values where the mask is true" % (val.get_shape()[0],size))) + if val.get_shape() == [1]: + box = val.descr_getitem(space, space.wrap(0)) + assert isinstance(box, Box) + val = W_NDimArray(scalar.Scalar(val.get_dtype(), box)) + elif val.get_shape() == [0]: + val.implementation.dtype = self.implementation.dtype loop.setitem_filter(self, idx, val) def _prepare_array_index(self, space, w_index): diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py --- a/pypy/module/micronumpy/loop.py +++ b/pypy/module/micronumpy/loop.py @@ -318,23 +318,27 @@ lefti.next() return result -count_all_true_driver = jit.JitDriver(name = 'numpy_count', - greens = ['shapelen', 'dtype'], - reds = 'auto') def count_all_true(arr): - s = 0 if arr.is_scalar(): return arr.get_dtype().itemtype.bool(arr.get_scalar_value()) iter = arr.create_iter() - shapelen = len(arr.get_shape()) - dtype = arr.get_dtype() + return count_all_true_iter(iter, arr.get_shape(), arr.get_dtype()) + +count_all_true_iter_driver = jit.JitDriver(name = 'numpy_count', + greens = ['shapelen', 'dtype'], + reds = 'auto') +def count_all_true_iter(iter, shape, dtype): + s = 0 + shapelen = len(shape) + dtype = dtype while not iter.done(): - count_all_true_driver.jit_merge_point(shapelen=shapelen, dtype=dtype) + count_all_true_iter_driver.jit_merge_point(shapelen=shapelen, dtype=dtype) s += iter.getitem_bool() iter.next() return s + getitem_filter_driver = jit.JitDriver(name = 'numpy_getitem_bool', greens = ['shapelen', 'arr_dtype', 'index_dtype'], @@ -370,7 +374,7 @@ def setitem_filter(arr, index, value): arr_iter = arr.create_iter() - index_iter = index.create_iter() + index_iter = index.create_iter(arr.get_shape()) value_iter = value.create_iter() shapelen = len(arr.get_shape()) index_dtype = index.get_dtype() diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1922,6 +1922,29 @@ a = numpy.arange(10.).reshape((5, 2))[::2] assert (loads(dumps(a)) == a).all() + def test_string_filling(self): + import numpypy as numpy + a = numpy.empty((10,10), dtype='c1') + a.fill(12) + assert (a == '1').all() + + def test_boolean_indexing(self): + import numpypy as np + a = np.zeros((1, 3)) + b = np.array([True]) + + assert (a[b] == a).all() + + a[b] = 1. + + assert (a == [[1., 1., 1.]]).all() + + @py.test.mark.xfail + def test_boolean_array(self): + import numpypy as np + a = np.ndarray([1], dtype=bool) + assert a[0] == True + class AppTestMultiDim(BaseNumpyAppTest): def test_init(self): import numpypy @@ -2329,6 +2352,21 @@ a[a & 1 == 0] = 15 assert (a == [[15, 1], [15, 5], [15, 9]]).all() + def test_array_indexing_bool_specialcases(self): + from numpypy import arange, array + a = arange(6) + try: + a[a < 3] = [1, 2] + assert False, "Should not work" + except ValueError: + pass + a = arange(6) + a[a > 3] = array([15]) + assert (a == [0, 1, 2, 3, 15, 15]).all() + a = arange(6).reshape(3, 2) + a[a & 1 == 1] = [] # here, Numpy sticks garbage into the array + assert a.shape == (3, 2) + def test_copy_kwarg(self): from numpypy import array x = array([1, 2, 3]) diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -1764,12 +1764,16 @@ arr.storage[i] = arg[i] return interp_boxes.W_StringBox(arr, 0, arr.dtype) - @jit.unroll_safe def store(self, arr, i, offset, box): assert isinstance(box, interp_boxes.W_StringBox) # XXX simplify to range(box.dtype.get_size()) ? + return self._store(arr.storage, i, offset, box) + + @jit.unroll_safe + def _store(self, storage, i, offset, box): + assert isinstance(box, interp_boxes.W_StringBox) for k in range(min(self.size, box.arr.size-offset)): - arr.storage[k + i] = box.arr.storage[k + offset] + storage[k + i] = box.arr.storage[k + offset] def read(self, arr, i, offset, dtype=None): if dtype is None: @@ -1859,6 +1863,11 @@ arr.storage[j] = '\x00' return interp_boxes.W_StringBox(arr, 0, arr.dtype) + def fill(self, storage, width, box, start, stop, offset): + from pypy.module.micronumpy.arrayimpl.concrete import ConcreteArrayNotOwning + for i in xrange(start, stop, width): + self._store(storage, i, offset, box) + NonNativeStringType = StringType class UnicodeType(BaseType, BaseStringType): diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py --- a/pypy/module/pypyjit/test_pypy_c/test_containers.py +++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py @@ -1,5 +1,3 @@ - -import py, sys from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC @@ -51,27 +49,6 @@ ... """) - def test_list(self): - def main(n): - i = 0 - while i < n: - z = list(()) - z.append(1) - i += z[-1] / len(z) - return i - - log = self.run(main, [1000]) - assert log.result == main(1000) - loop, = log.loops_by_filename(self.filepath) - assert loop.match(""" - i7 = int_lt(i5, i6) - guard_true(i7, descr=...) - guard_not_invalidated(descr=...) - i9 = int_add(i5, 1) - --TICK-- - jump(..., descr=...) - """) - def test_non_virtual_dict(self): def main(n): i = 0 @@ -119,6 +96,30 @@ jump(..., descr=...) """) + + +class TestOtherContainers(BaseTestPyPyC): + def test_list(self): + def main(n): + i = 0 + while i < n: + z = list(()) + z.append(1) + i += z[-1] / len(z) + return i + + log = self.run(main, [1000]) + assert log.result == main(1000) + loop, = log.loops_by_filename(self.filepath) + assert loop.match(""" + i7 = int_lt(i5, i6) + guard_true(i7, descr=...) + guard_not_invalidated(descr=...) + i9 = int_add(i5, 1) + --TICK-- + jump(..., descr=...) + """) + def test_floatlist_unpack_without_calls(self): def fn(n): l = [2.3, 3.4, 4.5] @@ -130,8 +131,7 @@ ops = loop.ops_by_id('look') assert 'call' not in log.opnames(ops) - #XXX the following tests only work with strategies enabled - + # XXX the following tests only work with strategies enabled def test_should_not_create_intobject_with_sets(self): def main(n): i = 0 @@ -241,3 +241,22 @@ loop, = log.loops_by_filename(self.filepath) ops = loop.ops_by_id('getitem', include_guard_not_invalidated=False) assert log.opnames(ops) == [] + + def test_list_count_virtual_list(self): + def main(n): + i = 0 + while i < n: + i += [n].count(n) + return i + + log = self.run(main, [1000]) + assert log.result == main(1000) + loop, = log.loops_by_filename(self.filepath) + assert loop.match(""" + i7 = int_lt(i5, i6) + guard_true(i7, descr=...) + i9 = int_add(i5, 1) + guard_not_invalidated(descr=...) + --TICK-- + jump(..., descr=...) + """) diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -228,3 +228,18 @@ cur = con.cursor() cur.execute(u'SELECT 1 as méil') assert cur.description[0][0] == u"méil".encode('utf-8') + +def test_adapter_exception(con): + def cast(obj): + raise ZeroDivisionError + + _sqlite3.register_adapter(int, cast) + try: + cur = con.cursor() + cur.execute("select ?", (4,)) + val = cur.fetchone()[0] + # Adapter error is ignored, and parameter is passed as is. + assert val == 4 + assert type(val) is int + finally: + del _sqlite3.adapters[(int, _sqlite3.PrepareProtocol)] diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -562,6 +562,8 @@ 'L.reverse() -- reverse *IN PLACE*' self.reverse() + @jit.look_inside_iff(lambda self, space, w_value: + jit.loop_unrolling_heuristic(self, self.length(), UNROLL_CUTOFF)) def descr_count(self, space, w_value): '''L.count(value) -> integer -- return number of occurrences of value''' diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py --- a/rpython/annotator/annrpython.py +++ b/rpython/annotator/annrpython.py @@ -5,7 +5,7 @@ from rpython.tool.ansi_print import ansi_log from rpython.tool.pairtype import pair from rpython.tool.error import (format_blocked_annotation_error, - AnnotatorError, gather_error, ErrorWrapper) + gather_error, source_lines) from rpython.flowspace.model import (Variable, Constant, FunctionGraph, c_last_exception, checkgraph) from rpython.translator import simplify, transform @@ -18,7 +18,6 @@ FAIL = object() - class RPythonAnnotator(object): """Block annotator for RPython. See description in doc/translation.txt.""" @@ -137,9 +136,7 @@ checkgraph(flowgraph) nbarg = len(flowgraph.getargs()) - if len(inputcells) != nbarg: - raise TypeError("%s expects %d args, got %d" %( - flowgraph, nbarg, len(inputcells))) + assert len(inputcells) == nbarg # wrong number of args # register the entry point self.addpendinggraph(flowgraph, inputcells) @@ -160,7 +157,7 @@ else: return object else: - raise TypeError, ("Variable or Constant instance expected, " + raise TypeError("Variable or Constant instance expected, " "got %r" % (variable,)) def getuserclassdefinitions(self): @@ -221,7 +218,7 @@ text = format_blocked_annotation_error(self, self.blocked_blocks) #raise SystemExit() - raise AnnotatorError(text) + raise annmodel.AnnotatorError(text) for graph in newgraphs: v = graph.getreturnvar() if v not in self.bindings: @@ -244,7 +241,7 @@ # return annmodel.s_ImpossibleValue return self.bookkeeper.immutableconstant(arg) else: - raise TypeError, 'Variable or Constant expected, got %r' % (arg,) + raise TypeError('Variable or Constant expected, got %r' % (arg,)) def typeannotation(self, t): return signature.annotation(t, self.bookkeeper) @@ -383,8 +380,8 @@ try: unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)] except annmodel.UnionError, e: - e.args = e.args + ( - ErrorWrapper(gather_error(self, graph, block, None)),) + # Add source code to the UnionError + e.source = '\n'.join(source_lines(graph, block, None, long=True)) raise # if the merged cells changed, we must redo the analysis if unions != oldcells: @@ -603,10 +600,9 @@ raise BlockedInference(self, op, opindex) try: resultcell = consider_meth(*argcells) - except Exception, e: + except annmodel.AnnotatorError as e: # note that UnionError is a subclass graph = self.bookkeeper.position_key[0] - e.args = e.args + ( - ErrorWrapper(gather_error(self, graph, block, opindex)),) + e.source = gather_error(self, graph, block, opindex) raise if resultcell is None: resultcell = self.noreturnvalue(op) diff --git a/rpython/annotator/argument.py b/rpython/annotator/argument.py --- a/rpython/annotator/argument.py +++ b/rpython/annotator/argument.py @@ -115,9 +115,7 @@ elif num_args > co_argcount: raise ArgErrCount(num_args, num_kwds, signature, defaults_w, 0) - # if a **kwargs argument is needed, explode - if signature.has_kwarg(): - raise TypeError("Keyword arguments as **kwargs is not supported by RPython") + assert not signature.has_kwarg() # XXX should not happen? # handle keyword arguments num_remainingkwds = 0 diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py --- a/rpython/annotator/binaryop.py +++ b/rpython/annotator/binaryop.py @@ -20,7 +20,7 @@ from rpython.annotator.bookkeeper import getbookkeeper from rpython.flowspace.model import Variable, Constant from rpython.rlib import rarithmetic -from rpython.tool.error import AnnotatorError +from rpython.annotator.model import AnnotatorError # convenience only! def immutablevalue(x): @@ -243,14 +243,16 @@ if t2 is int: if int2.nonneg == False: - raise UnionError, "Merging %s and a possibly negative int is not allowed" % t1 + raise UnionError(int1, int2, "RPython cannot prove that these " + \ + "integers are of the same signedness") knowntype = t1 elif t1 is int: if int1.nonneg == False: - raise UnionError, "Merging %s and a possibly negative int is not allowed" % t2 + raise UnionError(int1, int2, "RPython cannot prove that these " + \ + "integers are of the same signedness") knowntype = t2 else: - raise UnionError, "Merging these types (%s, %s) is not supported" % (t1, t2) + raise UnionError(int1, int2) return SomeInteger(nonneg=int1.nonneg and int2.nonneg, knowntype=knowntype) @@ -455,7 +457,7 @@ class __extend__(pairtype(SomeString, SomeUnicodeString), pairtype(SomeUnicodeString, SomeString)): def mod((str, unistring)): - raise NotImplementedError( + raise AnnotatorError( "string formatting mixing strings and unicode not supported") @@ -469,7 +471,7 @@ if (is_unicode and isinstance(s_item, (SomeChar, SomeString)) or is_string and isinstance(s_item, (SomeUnicodeCodePoint, SomeUnicodeString))): - raise NotImplementedError( + raise AnnotatorError( "string formatting mixing strings and unicode not supported") getbookkeeper().count('strformat', s_string, s_tuple) no_nul = s_string.no_nul @@ -551,9 +553,9 @@ def union((tup1, tup2)): if len(tup1.items) != len(tup2.items): - raise UnionError("cannot take the union of a tuple of length %d " - "and a tuple of length %d" % (len(tup1.items), - len(tup2.items))) + raise UnionError(tup1, tup2, "RPython cannot unify tuples of " + "different length: %d versus %d" % \ + (len(tup1.items), len(tup2.items))) else: unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)] return SomeTuple(items = unions) @@ -726,7 +728,8 @@ else: basedef = ins1.classdef.commonbase(ins2.classdef) if basedef is None: - raise UnionError(ins1, ins2) + raise UnionError(ins1, ins2, "RPython cannot unify instances " + "with no common base class") flags = ins1.flags if flags: flags = flags.copy() @@ -768,7 +771,8 @@ def union((iter1, iter2)): s_cont = unionof(iter1.s_container, iter2.s_container) if iter1.variant != iter2.variant: - raise UnionError("merging incompatible iterators variants") + raise UnionError(iter1, iter2, + "RPython cannot unify incompatible iterator variants") return SomeIterator(s_cont, *iter1.variant) @@ -778,8 +782,7 @@ if (bltn1.analyser != bltn2.analyser or bltn1.methodname != bltn2.methodname or bltn1.s_self is None or bltn2.s_self is None): - raise UnionError("cannot merge two different builtin functions " - "or methods:\n %r\n %r" % (bltn1, bltn2)) + raise UnionError(bltn1, bltn2) s_self = unionof(bltn1.s_self, bltn2.s_self) return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) @@ -976,8 +979,8 @@ class __extend__(pairtype(SomeAddress, SomeObject)): def union((s_addr, s_obj)): - raise UnionError, "union of address and anything else makes no sense" + raise UnionError(s_addr, s_obj) class __extend__(pairtype(SomeObject, SomeAddress)): def union((s_obj, s_addr)): - raise UnionError, "union of address and anything else makes no sense" + raise UnionError(s_obj, s_addr) diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py --- a/rpython/annotator/builtin.py +++ b/rpython/annotator/builtin.py @@ -337,7 +337,7 @@ return SomeAddress() def unicodedata_decimal(s_uchr): - raise TypeError, "unicodedate.decimal() calls should not happen at interp-level" + raise TypeError("unicodedate.decimal() calls should not happen at interp-level") def test(*args): return s_Bool diff --git a/rpython/annotator/classdef.py b/rpython/annotator/classdef.py --- a/rpython/annotator/classdef.py +++ b/rpython/annotator/classdef.py @@ -2,7 +2,7 @@ Type inference for user-defined classes. """ from rpython.annotator.model import SomePBC, s_ImpossibleValue, unionof -from rpython.annotator.model import SomeInteger, SomeTuple, SomeString +from rpython.annotator.model import SomeInteger, SomeTuple, SomeString, AnnotatorError from rpython.annotator import description @@ -429,7 +429,7 @@ result.extend(slots) return result -class NoSuchAttrError(Exception): +class NoSuchAttrError(AnnotatorError): """Raised when an attribute is found on a class where __slots__ or _attrs_ forbits it.""" diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py --- a/rpython/annotator/description.py +++ b/rpython/annotator/description.py @@ -6,6 +6,7 @@ from rpython.annotator.argument import rawshape, ArgErr from rpython.tool.sourcetools import valid_identifier, func_with_new_name from rpython.tool.pairtype import extendabletype +from rpython.annotator.model import AnnotatorError class CallFamily(object): """A family of Desc objects that could be called from common call sites. @@ -263,7 +264,7 @@ try: inputcells = args.match_signature(signature, defs_s) except ArgErr, e: - raise TypeError("signature mismatch: %s() %s" % + raise AnnotatorError("signature mismatch: %s() %s" % (self.name, e.getmsg())) return inputcells @@ -680,7 +681,7 @@ value = value.__get__(42) classdef = None # don't bind elif isinstance(value, classmethod): - raise AssertionError("classmethods are not supported") + raise AnnotatorError("classmethods are not supported") s_value = self.bookkeeper.immutablevalue(value) if classdef is not None: s_value = s_value.bind_callables_under(classdef, name) diff --git a/rpython/annotator/listdef.py b/rpython/annotator/listdef.py --- a/rpython/annotator/listdef.py +++ b/rpython/annotator/listdef.py @@ -1,12 +1,12 @@ from rpython.annotator.model import s_ImpossibleValue from rpython.annotator.model import SomeList, SomeString -from rpython.annotator.model import unionof, TLS, UnionError +from rpython.annotator.model import unionof, TLS, UnionError, AnnotatorError -class TooLateForChange(Exception): +class TooLateForChange(AnnotatorError): pass -class ListChangeUnallowed(Exception): +class ListChangeUnallowed(AnnotatorError): pass class ListItem(object): @@ -58,7 +58,7 @@ def merge(self, other): if self is not other: if getattr(TLS, 'no_side_effects_in_union', 0): - raise UnionError("merging list/dict items") + raise UnionError(self, other) if other.dont_change_any_more: if self.dont_change_any_more: diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -676,10 +676,42 @@ # ____________________________________________________________ -class UnionError(Exception): + +class AnnotatorError(Exception): + def __init__(self, msg=None): + self.msg = msg + self.source = None + + def __str__(self): + s = "\n\n%s" % self.msg + if self.source is not None: + s += "\n\n" + s += self.source + + return s + +class UnionError(AnnotatorError): """Signals an suspicious attempt at taking the union of deeply incompatible SomeXxx instances.""" + def __init__(self, s_obj1, s_obj2, msg=None): + """ + This exception expresses the fact that s_obj1 and s_obj2 cannot be unified. + The msg paramter is appended to a generic message. This can be used to + give the user a little more information. + """ + s = "" + if msg is not None: + s += "%s\n\n" % msg + s += "Offending annotations:\n" + s += " %s\n %s" % (s_obj1, s_obj2) + self.s_obj1 = s_obj1 + self.s_obj2 = s_obj2 + self.msg = s + self.source = None + + def __repr__(self): + return str(self) def unionof(*somevalues): "The most precise SomeValue instance that contains all the values." diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py --- a/rpython/annotator/signature.py +++ b/rpython/annotator/signature.py @@ -5,7 +5,7 @@ from rpython.annotator.model import SomeBool, SomeInteger, SomeString,\ SomeFloat, SomeList, SomeDict, s_None, \ SomeObject, SomeInstance, SomeTuple, lltype_to_annotation,\ - unionof, SomeUnicodeString, SomeType + unionof, SomeUnicodeString, SomeType, AnnotatorError from rpython.annotator.listdef import ListDef from rpython.annotator.dictdef import DictDef @@ -118,25 +118,28 @@ else: args_s.append(annotation(argtype, bookkeeper=funcdesc.bookkeeper)) if len(inputcells) != len(args_s): - raise Exception("%r: expected %d args, got %d" % (funcdesc, + raise SignatureError("%r: expected %d args, got %d" % (funcdesc, len(args_s), len(inputcells))) for i, (s_arg, s_input) in enumerate(zip(args_s, inputcells)): s_input = unionof(s_input, s_arg) if not s_arg.contains(s_input): - raise Exception("%r argument %d:\n" + raise SignatureError("%r argument %d:\n" "expected %s,\n" " got %s" % (funcdesc, i+1, s_arg, s_input)) inputcells[:] = args_s +class SignatureError(AnnotatorError): + pass + def finish_type(paramtype, bookkeeper, func): from rpython.rlib.types import SelfTypeMarker, AnyTypeMarker if isinstance(paramtype, SomeObject): return paramtype elif isinstance(paramtype, SelfTypeMarker): - raise Exception("%r argument declared as annotation.types.self(); class needs decorator rlib.signature.finishsigs()" % (func,)) + raise SignatureError("%r argument declared as annotation.types.self(); class needs decorator rlib.signature.finishsigs()" % (func,)) elif isinstance(paramtype, AnyTypeMarker): return None else: @@ -149,7 +152,7 @@ if s_param is None: # can be anything continue if not s_param.contains(s_actual): - raise Exception("%r argument %d:\n" + raise SignatureError("%r argument %d:\n" "expected %s,\n" " got %s" % (funcdesc, i+1, s_param, s_actual)) for i, s_param in enumerate(params_s): @@ -160,7 +163,7 @@ def enforce_signature_return(funcdesc, sigtype, inferredtype): s_sigret = finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj) if s_sigret is not None and not s_sigret.contains(inferredtype): - raise Exception("%r return value:\n" + raise SignatureError("%r return value:\n" "expected %s,\n" " got %s" % (funcdesc, s_sigret, inferredtype)) return s_sigret diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -228,7 +228,7 @@ def f(): return X().meth() a = self.RPythonAnnotator() - py.test.raises(AssertionError, a.build_types, f, []) + py.test.raises(annmodel.AnnotatorError, a.build_types, f, []) def test_methodcall1(self): a = self.RPythonAnnotator() @@ -3381,22 +3381,22 @@ return '%s' % unichr(x) a = self.RPythonAnnotator() - py.test.raises(NotImplementedError, a.build_types, f, [int]) + py.test.raises(annmodel.AnnotatorError, a.build_types, f, [int]) def f(x): return '%s' % (unichr(x) * 3) a = self.RPythonAnnotator() - py.test.raises(NotImplementedError, a.build_types, f, [int]) + py.test.raises(annmodel.AnnotatorError, a.build_types, f, [int]) def f(x): return '%s%s' % (1, unichr(x)) a = self.RPythonAnnotator() - py.test.raises(NotImplementedError, a.build_types, f, [int]) + py.test.raises(annmodel.AnnotatorError, a.build_types, f, [int]) def f(x): return '%s%s' % (1, unichr(x) * 15) a = self.RPythonAnnotator() - py.test.raises(NotImplementedError, a.build_types, f, [int]) + py.test.raises(annmodel.AnnotatorError, a.build_types, f, [int]) def test_strformatting_tuple(self): @@ -3434,7 +3434,7 @@ return [1, 2, 3][s:e] a = self.RPythonAnnotator() - py.test.raises(TypeError, "a.build_types(f, [int, int])") + py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])") a.build_types(f, [annmodel.SomeInteger(nonneg=True), annmodel.SomeInteger(nonneg=True)]) def f(x): @@ -4023,6 +4023,101 @@ a = self.RPythonAnnotator() assert not a.build_types(fn, [int]).nonneg + def test_unionerror_attrs(self): + def f(x): + if x < 10: + return 1 + else: + return "bbb" + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + the_exc = exc.value + s_objs = set([type(the_exc.s_obj1), type(the_exc.s_obj2)]) + + assert s_objs == set([annmodel.SomeInteger, annmodel.SomeString]) + + def test_unionerror_tuple_size(self): + def f(x): + if x < 10: + return (1, ) + else: + return (1, 2) + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert "RPython cannot unify tuples of different length: 2 versus 1" in exc.value.msg + + def test_unionerror_signedness(self): + def f(x): + if x < 10: + return r_uint(99) + else: + return -1 + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert ("RPython cannot prove that these integers are of the " + "same signedness" in exc.value.msg) + + def test_unionerror_instance(self): + class A(object): pass + class B(object): pass + + def f(x): + if x < 10: + return A() + else: + return B() + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert ("RPython cannot unify instances with no common base class" + in exc.value.msg) + + def test_unionerror_iters(self): + + def f(x): + d = { 1 : "a", 2 : "b" } + if x < 10: + return d.iterkeys() + else: + return d.itervalues() + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert ("RPython cannot unify incompatible iterator variants" in + exc.value.msg) + + def test_variable_getattr(self): + class A(object): pass + def f(y): + a = A() + return getattr(a, y) + a = self.RPythonAnnotator() + with py.test.raises(annmodel.AnnotatorError) as exc: + a.build_types(f, [str]) + assert ("variable argument to getattr" in exc.value.msg) + + def test_bad_call(self): + def f(x): + return x() + a = self.RPythonAnnotator() + with py.test.raises(annmodel.AnnotatorError) as exc: + a.build_types(f, [str]) + assert ("Cannot prove that the object is callable" in exc.value.msg) + + def g(n): return [0, 1, 2, n] diff --git a/rpython/annotator/test/test_argument.py b/rpython/annotator/test/test_argument.py --- a/rpython/annotator/test/test_argument.py +++ b/rpython/annotator/test/test_argument.py @@ -77,10 +77,6 @@ new_args = args.unmatch_signature(sig, data) assert args.unpack() == new_args.unpack() - args = make_arguments_for_translation(space, [1], {'c': 5, 'd': 7}) - sig = Signature(['a', 'b', 'c'], None, 'kw') - py.test.raises(TypeError, args.match_signature, sig, [2, 3]) - def test_rawshape(self): space = DummySpace() args = make_arguments_for_translation(space, [1,2,3]) diff --git a/rpython/annotator/test/test_model.py b/rpython/annotator/test/test_model.py --- a/rpython/annotator/test/test_model.py +++ b/rpython/annotator/test/test_model.py @@ -2,6 +2,7 @@ from rpython.annotator.model import * from rpython.annotator.listdef import ListDef +from rpython.translator.translator import TranslationContext listdef1 = ListDef(None, SomeTuple([SomeInteger(nonneg=True), SomeString()])) @@ -174,6 +175,28 @@ assert f2.contains(f1) assert f1.contains(f2) +def compile_function(function, annotation=[]): + t = TranslationContext() + t.buildannotator().build_types(function, annotation) + +class AAA(object): + pass + +def test_blocked_inference1(): + def blocked_inference(): + return AAA().m() + + py.test.raises(AnnotatorError, compile_function, blocked_inference) + +def test_blocked_inference2(): + def blocked_inference(): + a = AAA() + b = a.x + return b + + py.test.raises(AnnotatorError, compile_function, blocked_inference) + + if __name__ == '__main__': for name, value in globals().items(): if name.startswith('test_'): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -14,7 +14,7 @@ from rpython.annotator.bookkeeper import getbookkeeper from rpython.annotator import builtin from rpython.annotator.binaryop import _clone ## XXX where to put this? -from rpython.tool.error import AnnotatorError +from rpython.annotator.model import AnnotatorError # convenience only! def immutablevalue(x): @@ -84,8 +84,7 @@ return obj.is_true() def hash(obj): - raise TypeError, ("cannot use hash() in RPython; " - "see objectmodel.compute_xxx()") + raise AnnotatorError("cannot use hash() in RPython") def str(obj): getbookkeeper().count('str', obj) @@ -158,9 +157,7 @@ return obj.call(getbookkeeper().build_args("call_args", args_s)) def call(obj, args, implicit_init=False): - #raise Exception, "cannot follow call_args%r" % ((obj, args),) - getbookkeeper().warning("cannot follow call(%r, %r)" % (obj, args)) - return SomeObject() + raise AnnotatorError("Cannot prove that the object is callable") def op_contains(obj, s_element): return s_Bool @@ -341,10 +338,10 @@ def check_negative_slice(s_start, s_stop): if isinstance(s_start, SomeInteger) and not s_start.nonneg: - raise TypeError("slicing: not proven to have non-negative start") + raise AnnotatorError("slicing: not proven to have non-negative start") if isinstance(s_stop, SomeInteger) and not s_stop.nonneg and \ getattr(s_stop, 'const', 0) != -1: - raise TypeError("slicing: not proven to have non-negative stop") + raise AnnotatorError("slicing: not proven to have non-negative stop") class __extend__(SomeDict): @@ -529,10 +526,10 @@ class __extend__(SomeUnicodeString): def method_encode(uni, s_enc): if not s_enc.is_constant(): - raise TypeError("Non-constant encoding not supported") + raise AnnotatorError("Non-constant encoding not supported") enc = s_enc.const if enc not in ('ascii', 'latin-1', 'utf-8'): - raise TypeError("Encoding %s not supported for unicode" % (enc,)) + raise AnnotatorError("Encoding %s not supported for unicode" % (enc,)) return SomeString() method_encode.can_only_throw = [UnicodeEncodeError] @@ -562,10 +559,10 @@ def method_decode(str, s_enc): if not s_enc.is_constant(): - raise TypeError("Non-constant encoding not supported") + raise AnnotatorError("Non-constant encoding not supported") enc = s_enc.const if enc not in ('ascii', 'latin-1', 'utf-8'): - raise TypeError("Encoding %s not supported for strings" % (enc,)) + raise AnnotatorError("Encoding %s not supported for strings" % (enc,)) return SomeUnicodeString() method_decode.can_only_throw = [UnicodeDecodeError] @@ -653,7 +650,7 @@ if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const return ins._true_getattr(attr) - return SomeObject() + raise AnnotatorError("A variable argument to getattr is not RPython") getattr.can_only_throw = [] def setattr(ins, s_attr, s_value): @@ -729,7 +726,7 @@ def setattr(pbc, s_attr, s_value): if not pbc.isNone(): - raise AnnotatorError("setattr on %r" % pbc) + raise AnnotatorError("Cannot modify attribute of a pre-built constant") def call(pbc, args): bookkeeper = getbookkeeper() @@ -751,7 +748,8 @@ # whose length is the constant 0; so let's tentatively answer 0. return immutablevalue(0) else: - return SomeObject() # len() on a pbc? no chance + # This should probably never happen + raise AnnotatorError("Cannot call len on a pbc") # annotation of low-level types from rpython.annotator.model import SomePtr, SomeLLADTMeth diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py --- a/rpython/flowspace/flowcontext.py +++ b/rpython/flowspace/flowcontext.py @@ -24,8 +24,9 @@ self.frame = frame def __str__(self): - msg = ['-+' * 30] + msg = ["\n"] msg += map(str, self.args) + msg += [""] msg += source_lines(self.frame.graph, None, offset=self.frame.last_instr) return "\n".join(msg) @@ -293,7 +294,7 @@ _unsupported_ops = [ ('BINARY_POWER', "a ** b"), - ('BUILD_CLASS', 'creating new classes'), + ('BUILD_CLASS', 'defining classes inside functions'), ('EXEC_STMT', 'exec statement'), ('STOP_CODE', '???'), ('STORE_NAME', 'modifying globals'), diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1015,9 +1015,6 @@ @arguments("int", "boxes3", "jitcode_position", "boxes3", "orgpc") def opimpl_jit_merge_point(self, jdindex, greenboxes, jcposition, redboxes, orgpc): - resumedescr = compile.ResumeAtPositionDescr() - self.metainterp.capture_resumedata(resumedescr, orgpc) - any_operation = len(self.metainterp.history.operations) > 0 jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] self.verify_green_args(jitdriver_sd, greenboxes) @@ -1049,6 +1046,9 @@ # much less expensive to blackhole out of. saved_pc = self.pc self.pc = orgpc + resumedescr = compile.ResumeAtPositionDescr() + self.metainterp.capture_resumedata(resumedescr, orgpc) + self.metainterp.reached_loop_header(greenboxes, redboxes, resumedescr) self.pc = saved_pc # no exception, which means that the jit_merge_point did not diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -509,12 +509,13 @@ if hasattr(_c, 'fcntl'): def _setblocking(self, block): - delay_flag = intmask(_c.fcntl(self.fd, _c.F_GETFL, 0)) + orig_delay_flag = intmask(_c.fcntl(self.fd, _c.F_GETFL, 0)) if block: - delay_flag &= ~_c.O_NONBLOCK + delay_flag = orig_delay_flag & ~_c.O_NONBLOCK else: - delay_flag |= _c.O_NONBLOCK - _c.fcntl(self.fd, _c.F_SETFL, delay_flag) + delay_flag = orig_delay_flag | _c.O_NONBLOCK + if orig_delay_flag != delay_flag: + _c.fcntl(self.fd, _c.F_SETFL, delay_flag) elif hasattr(_c, 'ioctlsocket'): def _setblocking(self, block): flag = lltype.malloc(rffi.ULONGP.TO, 1, flavor='raw') diff --git a/rpython/rlib/test/test_signature.py b/rpython/rlib/test/test_signature.py --- a/rpython/rlib/test/test_signature.py +++ b/rpython/rlib/test/test_signature.py @@ -2,6 +2,7 @@ from rpython.rlib.signature import signature, finishsigs, FieldSpec, ClassSpec from rpython.rlib import types from rpython.annotator import model +from rpython.annotator.signature import SignatureError from rpython.translator.translator import TranslationContext, graphof from rpython.rtyper.lltypesystem import rstr from rpython.rtyper.annlowlevel import LowLevelAnnotatorPolicy @@ -24,8 +25,8 @@ 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) + exc = py.test.raises(model.AnnotatorError, annotate_at, caller).value + assert caller.func_name in str(exc) def test_bookkeeping(): @@ -245,9 +246,9 @@ 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) + exc = py.test.raises(SignatureError, annotate_at, C.incomplete_sig_meth).value + assert 'incomplete_sig_meth' in str(exc) + assert 'finishsigs' in str(exc) def test_any_as_argument(): @signature(types.any(), types.int(), returns=types.float()) @@ -268,8 +269,8 @@ @signature(types.str(), returns=types.int()) def cannot_add_string(x): return f(x, 2) - exc = py.test.raises(Exception, annotate_at, cannot_add_string).value - assert 'Blocked block' in repr(exc.args) + exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value + assert 'Blocked block' in str(exc) def test_return_any(): @signature(types.int(), returns=types.any()) @@ -281,9 +282,9 @@ @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) + 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) diff --git a/rpython/tool/error.py b/rpython/tool/error.py --- a/rpython/tool/error.py +++ b/rpython/tool/error.py @@ -68,19 +68,6 @@ lines = source_lines1(graph, *args, **kwds) return ['In %r:' % (graph,)] + lines -class AnnotatorError(Exception): - pass - -class NoSuchAttrError(Exception): - pass - -class ErrorWrapper(object): - def __init__(self, msg): - self.msg = msg - - def __repr__(self): - return '<%s>' % (self.msg,) - def gather_error(annotator, graph, block, operindex): msg = [""] @@ -90,23 +77,28 @@ format_simple_call(annotator, oper, msg) else: oper = None - msg.append(" " + str(oper)) + msg.append(" %s\n" % str(oper)) msg += source_lines(graph, block, operindex, long=True) if oper is not None: if SHOW_ANNOTATIONS: - msg.append("Known variable annotations:") - for arg in oper.args + [oper.result]: - if isinstance(arg, Variable): - try: - msg.append(" " + str(arg) + " = " + str(annotator.binding(arg))) - except KeyError: - pass + msg += format_annotations(annotator, oper) + msg += [''] return "\n".join(msg) +def format_annotations(annotator, oper): + msg = [] + msg.append("Known variable annotations:") + for arg in oper.args + [oper.result]: + if isinstance(arg, Variable): + try: + msg.append(" " + str(arg) + " = " + str(annotator.binding(arg))) + except KeyError: + pass + return msg + def format_blocked_annotation_error(annotator, blocked_blocks): text = [] for block, (graph, index) in blocked_blocks.items(): - text.append('-+' * 30) text.append("Blocked block -- operation cannot succeed") text.append(gather_error(annotator, graph, block, index)) return '\n'.join(text) diff --git a/rpython/tool/test/test_error.py b/rpython/tool/test/test_error.py --- a/rpython/tool/test/test_error.py +++ b/rpython/tool/test/test_error.py @@ -3,12 +3,10 @@ """ from rpython.translator.translator import TranslationContext -from rpython.tool.error import AnnotatorError from rpython.annotator.model import UnionError import py - def compile_function(function, annotation=[]): t = TranslationContext() t.buildannotator().build_types(function, annotation) @@ -16,20 +14,6 @@ class AAA(object): pass -def test_blocked_inference1(): - def blocked_inference(): - return AAA().m() - - py.test.raises(AnnotatorError, compile_function, blocked_inference) - -def test_blocked_inference2(): - def blocked_inference(): - a = AAA() - b = a.x - return b - - py.test.raises(AnnotatorError, compile_function, blocked_inference) - def test_someobject(): def someobject_degeneration(n): if n == 3: diff --git a/rpython/translator/goal/translate.py b/rpython/translator/goal/translate.py --- a/rpython/translator/goal/translate.py +++ b/rpython/translator/goal/translate.py @@ -246,17 +246,19 @@ tb = None if got_error: import traceback - errmsg = ["Error:\n"] + stacktrace_errmsg = ["Error:\n"] exc, val, tb = sys.exc_info() - errmsg.extend([" %s" % line for line in traceback.format_exception(exc, val, tb)]) + stacktrace_errmsg.extend([" %s" % line for line in traceback.format_tb(tb)]) + summary_errmsg = traceback.format_exception_only(exc, val) block = getattr(val, '__annotator_block', None) if block: class FileLike: def write(self, s): - errmsg.append(" %s" % s) - errmsg.append("Processing block:\n") + summary_errmsg.append(" %s" % s) + summary_errmsg.append("Processing block:\n") t.about(block, FileLike()) - log.ERROR(''.join(errmsg)) + log.info(''.join(stacktrace_errmsg)) + log.ERROR(''.join(summary_errmsg)) else: log.event('Done.') _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit