Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r61308:c44d9205dbb4 Date: 2013-02-16 10:29 +0100 http://bitbucket.org/pypy/pypy/changeset/c44d9205dbb4/
Log: Update to cffi/70927696eb9c diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py --- a/pypy/module/_cffi_backend/newtype.py +++ b/pypy/module/_cffi_backend/newtype.py @@ -264,8 +264,8 @@ # ____________________________________________________________ -@unwrap_spec(name=str) -def new_enum_type(space, name, w_enumerators, w_enumvalues): +@unwrap_spec(name=str, basectype=ctypeobj.W_CType) +def new_enum_type(space, name, w_enumerators, w_enumvalues, basectype): enumerators_w = space.fixedview(w_enumerators) enumvalues_w = space.fixedview(w_enumvalues) if len(enumerators_w) != len(enumvalues_w): @@ -273,53 +273,26 @@ space.wrap("tuple args must have the same size")) enumerators = [space.str_w(w) for w in enumerators_w] # - smallest_value = 0 - largest_value = r_uint(0) - i = 0 + if (not isinstance(basectype, ctypeprim.W_CTypePrimitiveSigned) and + not isinstance(basectype, ctypeprim.W_CTypePrimitiveUnsigned)): + raise OperationError(space.w_TypeError, + space.wrap("expected a primitive signed or unsigned base type")) + # + lvalue = lltype.malloc(rffi.CCHARP.TO, basectype.size, flavor='raw') try: for w in enumvalues_w: - try: - ulvalue = space.uint_w(w) - except OperationError, e: - if not e.match(space, space.w_ValueError): - raise - lvalue = space.int_w(w) - if lvalue < smallest_value: - smallest_value = lvalue - else: - if ulvalue > largest_value: - largest_value = ulvalue - i += 1 # 'i' is here for the exception case, see below - except OperationError, e: - if not e.match(space, space.w_OverflowError): - raise - raise operationerrfmt(space.w_OverflowError, - "enum '%s' declaration for '%s' does not fit " - "a long or unsigned long", - name, enumerators[i]) + # detects out-of-range or badly typed values + basectype.convert_from_object(lvalue, w) + finally: + lltype.free(lvalue, flavor='raw') # - if smallest_value < 0: - if (smallest_value >= intmask(most_neg_value_of(rffi.INT)) and - largest_value <= r_uint(most_pos_value_of(rffi.INT))): - size = rffi.sizeof(rffi.INT) - align = alignment(rffi.INT) - elif largest_value <= r_uint(most_pos_value_of(rffi.LONG)): - size = rffi.sizeof(rffi.LONG) - align = alignment(rffi.LONG) - else: - raise operationerrfmt(space.w_OverflowError, - "enum '%s' values don't all fit into either 'long' " - "or 'unsigned long'", name) + size = basectype.size + align = basectype.align + if isinstance(basectype, ctypeprim.W_CTypePrimitiveSigned): enumvalues = [space.int_w(w) for w in enumvalues_w] ctype = ctypeenum.W_CTypeEnumSigned(space, name, size, align, enumerators, enumvalues) else: - if largest_value <= r_uint(most_pos_value_of(rffi.UINT)): - size = rffi.sizeof(rffi.UINT) - align = alignment(rffi.UINT) - else: - size = rffi.sizeof(rffi.ULONG) - align = alignment(rffi.ULONG) enumvalues = [space.uint_w(w) for w in enumvalues_w] ctype = ctypeenum.W_CTypeEnumUnsigned(space, name, size, align, enumerators, enumvalues) diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1264,25 +1264,29 @@ py.test.raises(TypeError, callback, BFunc, cb, -42) def test_enum_type(): - BEnum = new_enum_type("foo", (), ()) + BUInt = new_primitive_type("unsigned int") + BEnum = new_enum_type("foo", (), (), BUInt) assert repr(BEnum) == "<ctype 'enum foo'>" assert BEnum.kind == "enum" assert BEnum.cname == "enum foo" assert BEnum.elements == {} # - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20)) + BInt = new_primitive_type("int") + BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) assert BEnum.kind == "enum" assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'} # 'elements' is not the real dict, but merely a copy BEnum.elements[2] = '??' assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'} # - BEnum = new_enum_type("bar", ('ab', 'cd'), (5, 5)) + BEnum = new_enum_type("bar", ('ab', 'cd'), (5, 5), BUInt) assert BEnum.elements == {5: 'ab'} assert BEnum.relements == {'ab': 5, 'cd': 5} def test_cast_to_enum(): - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20)) + BInt = new_primitive_type("int") + BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) + assert sizeof(BEnum) == sizeof(BInt) e = cast(BEnum, 0) assert repr(e) == "<cdata 'enum foo' 0: def>" assert repr(cast(BEnum, -42)) == "<cdata 'enum foo' -42>" @@ -1294,18 +1298,27 @@ assert int(cast(BEnum, -242 + 2**128)) == -242 assert string(cast(BEnum, -242 + 2**128)) == '-242' # - BEnum = new_enum_type("bar", ('def', 'c', 'ab'), (0, 1, 20)) + BUInt = new_primitive_type("unsigned int") + BEnum = new_enum_type("bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt) e = cast(BEnum, -1) assert repr(e) == "<cdata 'enum bar' 4294967295>" # unsigned int + # + BLong = new_primitive_type("long") + BEnum = new_enum_type("baz", (), (), BLong) + assert sizeof(BEnum) == sizeof(BLong) + e = cast(BEnum, -1) + assert repr(e) == "<cdata 'enum baz' -1>" def test_enum_with_non_injective_mapping(): - BEnum = new_enum_type("foo", ('ab', 'cd'), (7, 7)) + BInt = new_primitive_type("int") + BEnum = new_enum_type("foo", ('ab', 'cd'), (7, 7), BInt) e = cast(BEnum, 7) assert repr(e) == "<cdata 'enum foo' 7: ab>" assert string(e) == 'ab' def test_enum_in_struct(): - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20)) + BInt = new_primitive_type("int") + BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) BStruct = new_struct_type("bar") BStructPtr = new_pointer_type(BStruct) complete_struct_or_union(BStruct, [('a1', BEnum, -1)]) @@ -1318,7 +1331,7 @@ "unsupported operand type for int(): 'NoneType'" in str(e.value)) #PyPy py.test.raises(TypeError, 'p.a1 = "def"') if sys.version_info < (3,): - BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,)) + BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt) assert string(cast(BEnum2, 5)) == 'abc' assert type(string(cast(BEnum2, 5))) is str @@ -1327,66 +1340,25 @@ max_int = max_uint // 2 max_ulong = 2 ** (size_of_long()*8) - 1 max_long = max_ulong // 2 - # 'unsigned int' case - e = new_enum_type("foo", ('a', 'b'), (0, 3)) - assert sizeof(e) == size_of_int() - assert int(cast(e, -1)) == max_uint # 'e' is unsigned - e = new_enum_type("foo", ('a', 'b'), (0, max_uint)) - assert sizeof(e) == size_of_int() - assert int(cast(e, -1)) == max_uint - assert e.elements == {0: 'a', max_uint: 'b'} - assert e.relements == {'a': 0, 'b': max_uint} - # 'signed int' case - e = new_enum_type("foo", ('a', 'b'), (-1, max_int)) - assert sizeof(e) == size_of_int() - assert int(cast(e, -1)) == -1 - assert e.elements == {-1: 'a', max_int: 'b'} - assert e.relements == {'a': -1, 'b': max_int} - e = new_enum_type("foo", ('a', 'b'), (-max_int-1, max_int)) - assert sizeof(e) == size_of_int() - assert int(cast(e, -1)) == -1 - assert e.elements == {-max_int-1: 'a', max_int: 'b'} - assert e.relements == {'a': -max_int-1, 'b': max_int} - # 'unsigned long' case - e = new_enum_type("foo", ('a', 'b'), (0, max_long)) - assert sizeof(e) == size_of_long() - assert int(cast(e, -1)) == max_ulong # 'e' is unsigned - e = new_enum_type("foo", ('a', 'b'), (0, max_ulong)) - assert sizeof(e) == size_of_long() - assert int(cast(e, -1)) == max_ulong - assert e.elements == {0: 'a', max_ulong: 'b'} - assert e.relements == {'a': 0, 'b': max_ulong} - # 'signed long' case - e = new_enum_type("foo", ('a', 'b'), (-1, max_long)) - assert sizeof(e) == size_of_long() - assert int(cast(e, -1)) == -1 - assert e.elements == {-1: 'a', max_long: 'b'} - assert e.relements == {'a': -1, 'b': max_long} - e = new_enum_type("foo", ('a', 'b'), (-max_long-1, max_long)) - assert sizeof(e) == size_of_long() - assert int(cast(e, -1)) == -1 - assert e.elements == {-max_long-1: 'a', max_long: 'b'} - assert e.relements == {'a': -max_long-1, 'b': max_long} - # overflow: both negative items and items larger than max_long - e = py.test.raises(OverflowError, new_enum_type, "foo", ('a', 'b'), - (-1, max_long + 1)) - assert str(e.value) == ( - "enum 'foo' values don't all fit into either 'long' " - "or 'unsigned long'") - # overflow: items smaller than -max_long-1 - e = py.test.raises(OverflowError, new_enum_type, "foo", ('a', 'b'), - (-max_long-2, 5)) - assert str(e.value) == ( - "enum 'foo' declaration for 'a' does not fit a long or unsigned long") - # overflow: items larger than max_ulong - e = py.test.raises(OverflowError, new_enum_type, "foo", ('a', 'b'), - (5, max_ulong+1)) - assert str(e.value) == ( - "enum 'foo' declaration for 'b' does not fit a long or unsigned long") + for BPrimitive in [new_primitive_type("int"), + new_primitive_type("unsigned int"), + new_primitive_type("long"), + new_primitive_type("unsigned long")]: + for x in [max_uint, max_int, max_ulong, max_long]: + for testcase in [x, x+1, -x-1, -x-2]: + if int(cast(BPrimitive, testcase)) == testcase: + # fits + BEnum = new_enum_type("foo", ("AA",), (testcase,), + BPrimitive) + assert int(cast(BEnum, testcase)) == testcase + else: + # overflows + py.test.raises(OverflowError, new_enum_type, + "foo", ("AA",), (testcase,), BPrimitive) def test_callback_returning_enum(): BInt = new_primitive_type("int") - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20)) + BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) def cb(n): if n & 1: return cast(BEnum, n) @@ -1402,7 +1374,8 @@ def test_callback_returning_enum_unsigned(): BInt = new_primitive_type("int") - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, 20)) + BUInt = new_primitive_type("unsigned int") + BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, 20), BUInt) def cb(n): if n & 1: return cast(BEnum, n) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit