[pypy-commit] pypy default: Update to cffi/70927696eb9c

arigo noreply at buildbot.pypy.org
Sat Feb 16 10:29:22 CET 2013


Author: Armin Rigo <arigo at 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 @@
 
 # ____________________________________________________________
 
- at unwrap_spec(name=str)
-def new_enum_type(space, name, w_enumerators, w_enumvalues):
+ at 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)


More information about the pypy-commit mailing list