[pypy-commit] pypy pypy_swappedbytes: Final modifications , 1 test still unskipped in test_byteswap.py

smihnea pypy.commits at gmail.com
Sun Aug 27 02:54:07 EDT 2017


Author: Mihnea Saracin <mihnea.saracin at rinftech.com>
Branch: pypy_swappedbytes
Changeset: r92263:f611791f1958
Date: 2017-08-10 15:10 +0300
http://bitbucket.org/pypy/pypy/changeset/f611791f1958/

Log:	Final modifications , 1 test still unskipped in test_byteswap.py

diff --git a/lib-python/2.7/ctypes/test/test_byteswap.py b/lib-python/2.7/ctypes/test/test_byteswap.py
--- a/lib-python/2.7/ctypes/test/test_byteswap.py
+++ b/lib-python/2.7/ctypes/test/test_byteswap.py
@@ -23,7 +23,6 @@
             setattr(bits, "i%s" % i, 1)
             dump(bits)
 
-    @xfail
     def test_endian_short(self):
         if sys.byteorder == "little":
             self.assertIs(c_short.__ctype_le__, c_short)
@@ -51,7 +50,6 @@
         self.assertEqual(bin(s), "3412")
         self.assertEqual(s.value, 0x1234)
 
-    @xfail
     def test_endian_int(self):
         if sys.byteorder == "little":
             self.assertIs(c_int.__ctype_le__, c_int)
@@ -80,7 +78,6 @@
         self.assertEqual(bin(s), "78563412")
         self.assertEqual(s.value, 0x12345678)
 
-    @xfail
     def test_endian_longlong(self):
         if sys.byteorder == "little":
             self.assertIs(c_longlong.__ctype_le__, c_longlong)
@@ -109,7 +106,6 @@
         self.assertEqual(bin(s), "EFCDAB9078563412")
         self.assertEqual(s.value, 0x1234567890ABCDEF)
 
-    @xfail
     def test_endian_float(self):
         if sys.byteorder == "little":
             self.assertIs(c_float.__ctype_le__, c_float)
@@ -128,7 +124,6 @@
         self.assertAlmostEqual(s.value, math.pi, 6)
         self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s))
 
-    @xfail
     def test_endian_double(self):
         if sys.byteorder == "little":
             self.assertIs(c_double.__ctype_le__, c_double)
@@ -156,7 +151,6 @@
         self.assertIs(c_char.__ctype_le__, c_char)
         self.assertIs(c_char.__ctype_be__, c_char)
 
-    @xfail
     def test_struct_fields_1(self):
         if sys.byteorder == "little":
             base = BigEndianStructure
@@ -221,7 +215,6 @@
                 self.assertEqual(s.point.x, 1)
                 self.assertEqual(s.point.y, 2)
 
-    @xfail
     def test_struct_fields_2(self):
         # standard packing in struct uses no alignment.
         # So, we have to align using pad bytes.
@@ -245,7 +238,6 @@
         s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
         self.assertEqual(bin(s1), bin(s2))
 
-    @xfail
     def test_unaligned_nonnative_struct_fields(self):
         if sys.byteorder == "little":
             base = BigEndianStructure
diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py
--- a/lib_pypy/_ctypes/primitive.py
+++ b/lib_pypy/_ctypes/primitive.py
@@ -61,6 +61,54 @@
 
 pyobj_container = GlobalPyobjContainer()
 
+def swap_bytes(value, sizeof, typeof, get_or_set):
+    def swap_2():
+        return ((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00)
+
+    def swap_4():
+        return ((value & 0x000000FF) << 24) | \
+               ((value & 0x0000FF00) << 8) | \
+               ((value & 0x00FF0000) >> 8) | \
+               ((value >> 24) & 0xFF)
+
+    def swap_8():
+        return ((value & 0x00000000000000FFL) << 56) | \
+               ((value & 0x000000000000FF00L) << 40) | \
+               ((value & 0x0000000000FF0000L) << 24) | \
+               ((value & 0x00000000FF000000L) << 8) | \
+               ((value & 0x000000FF00000000L) >> 8) | \
+               ((value & 0x0000FF0000000000L) >> 24) | \
+               ((value & 0x00FF000000000000L) >> 40) | \
+               ((value >> 56) & 0xFF)
+
+    def swap_double_float(typ):
+        from struct import pack, unpack
+        if get_or_set == 'set':
+            if sys.byteorder == 'little':
+                st = pack(''.join(['>', typ]), value)
+            else:
+                st = pack(''.join(['<', typ]), value)
+            return unpack(typ, st)[0]
+        else:
+            packed = pack(typ, value)
+            if sys.byteorder == 'little':
+                st = unpack(''.join(['>', typ]), packed)
+            else:
+                st = unpack(''.join(['<', typ]), packed)
+            return st[0]
+
+    if typeof in ('c_float', 'c_float_le', 'c_float_be'):
+        return swap_double_float('f')
+    elif typeof in ('c_double', 'c_double_le', 'c_double_be'):
+        return swap_double_float('d')
+    else:
+        if sizeof == 2:
+            return swap_2()
+        elif sizeof == 4:
+            return swap_4()
+        elif sizeof == 8:
+            return swap_8()
+
 def generic_xxx_p_from_param(cls, value):
     if value is None:
         return cls(None)
@@ -271,6 +319,31 @@
             def _as_ffi_pointer_(self, ffitype):
                 return as_ffi_pointer(self, ffitype)
             result._as_ffi_pointer_ = _as_ffi_pointer_
+        if name[-2:] != '_p' and name[-3:] not in ('_le', '_be') \
+                and name not in ('c_wchar', '_SimpleCData', 'c_longdouble', 'c_bool', 'py_object'):
+            from sys import byteorder
+            if byteorder == 'big':
+                name += '_le'
+                swapped = self.__new__(self, name, bases, dct)
+                result.__ctype_le__ = swapped
+                result.__ctype_be__ = result
+                swapped.__ctype_be__ = result
+                swapped.__ctype_le__ = swapped
+            else:
+                name += '_be'
+                swapped = self.__new__(self, name, bases, dct)
+                result.__ctype_be__ = swapped
+                result.__ctype_le__ = result
+                swapped.__ctype_le__ = result
+                swapped.__ctype_be__ = swapped
+            from _ctypes import sizeof
+            def _getval(self):
+                return swap_bytes(self._buffer[0], sizeof(self), name, 'get')
+            def _setval(self, value):
+                d = result()
+                d.value = value
+                self._buffer[0] = swap_bytes(d.value, sizeof(self), name, 'set')
+            swapped.value = property(_getval, _setval)
 
         return result
 
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -40,6 +40,22 @@
         else:
             rawfields.append((f[0], f[1]._ffishape_))
 
+    # hack for duplicate field names
+    already_seen = set()
+    names1 = names
+    names = []
+    for f in names1:
+        if f not in already_seen:
+            names.append(f)
+            already_seen.add(f)
+    already_seen = set()
+    for i in reversed(range(len(rawfields))):
+        if rawfields[i][0] in already_seen:
+            rawfields[i] = (('$DUP%d$%s' % (i, rawfields[i][0]),)
+                            + rawfields[i][1:])
+        already_seen.add(rawfields[i][0])
+    # /hack
+
     _set_shape(self, rawfields, self._is_union)
 
     fields = {}
@@ -230,10 +246,22 @@
 
     def __new__(cls, *args, **kwds):
         from _ctypes import union
-        self = super(_CData, cls).__new__(cls)
-        if ('_abstract_' in cls.__dict__ or cls is Structure 
+        if ('_abstract_' in cls.__dict__ or cls is Structure
                                          or cls is union.Union):
             raise TypeError("abstract class")
+        if hasattr(cls, '_swappedbytes_'):
+            fields = [None] * len(cls._fields_)
+            for i in range(len(cls._fields_)):
+                if cls._fields_[i][1] == cls._fields_[i][1].__dict__.get('__ctype_be__', None):
+                    swapped = cls._fields_[i][1].__dict__.get('__ctype_le__', cls._fields_[i][1])
+                else:
+                    swapped = cls._fields_[i][1].__dict__.get('__ctype_be__', cls._fields_[i][1])
+                if len(cls._fields_[i]) < 3:
+                    fields[i] = (cls._fields_[i][0], swapped)
+                else:
+                    fields[i] = (cls._fields_[i][0], swapped, cls._fields_[i][2])
+            names_and_fields(cls, fields, _CData, cls.__dict__.get('_anonymous_', None))
+        self = super(_CData, cls).__new__(cls)
         if hasattr(cls, '_ffistruct_'):
             self.__dict__['_buffer'] = self._ffistruct_(autofree=True)
         return self
@@ -250,17 +278,6 @@
         for name, arg in kwds.items():
             self.__setattr__(name, arg)
 
-    def __getattribute__(self, item):
-        if item in (field[0] for field in object.__getattribute__(self, "_fields_"))\
-                and hasattr(self.__class__, '_swappedbytes_'):
-            self._swap_bytes(item, 'get')
-        return object.__getattribute__(self, item)
-
-    def __setattr__(self, key, value):
-        object.__setattr__(self,  key, value)
-        if key in (field[0] for field in self._fields_) and hasattr(self.__class__, '_swappedbytes_'):
-            self._swap_bytes(key, 'set')
-
     def _subarray(self, fieldtype, name):
         """Return a _rawffi array of length 1 whose address is the same as
         the address of the field 'name' of self."""
@@ -277,63 +294,6 @@
     def _to_ffi_param(self):
         return self._buffer
 
-    def _swap_bytes(self, field, get_or_set):
-        def swap_2(v):
-            return ((v >> 8) & 0x00FF) | ((v << 8) & 0xFF00)
-
-        def swap_4(v):
-            return ((v & 0x000000FF) << 24) | \
-                   ((v & 0x0000FF00) << 8) | \
-                   ((v & 0x00FF0000) >> 8) | \
-                   ((v >> 24) & 0xFF)
-
-        def swap_8(v):
-            return ((v & 0x00000000000000FFL) << 56) | \
-                   ((v & 0x000000000000FF00L) << 40) | \
-                   ((v & 0x0000000000FF0000L) << 24) | \
-                   ((v & 0x00000000FF000000L) << 8) | \
-                   ((v & 0x000000FF00000000L) >> 8) | \
-                   ((v & 0x0000FF0000000000L) >> 24) | \
-                   ((v & 0x00FF000000000000L) >> 40) | \
-                   ((v >> 56) & 0xFF)
-
-        def swap_double_float(v, typ):
-            from struct import pack, unpack
-            st = ''
-            if get_or_set == 'set':
-                if sys.byteorder == 'little':
-                    st = pack(''.join(['>', typ]), v)
-                else:
-                    st = pack(''.join(['<', typ]), v)
-                return unpack(typ, st)[0]
-            else:
-                packed = pack(typ, v)
-                if sys.byteorder == 'little':
-                    st = unpack(''.join(['>', typ]), packed)
-                else:
-                    st = unpack(''.join(['<', typ]), packed)
-                return st[0]
-
-        from ctypes import sizeof, c_double, c_float
-        sizeof_field = 0
-        typeof_field = None
-        for i in self._fields_:
-            if i[0] == field:
-                sizeof_field = sizeof(i[1])
-                typeof_field = i[1]
-        field_value = object.__getattribute__(self, field)
-        if typeof_field == c_float:
-            object.__setattr__(self, field, swap_double_float(field_value, 'f'))
-        elif typeof_field == c_double:
-            object.__setattr__(self, field, swap_double_float(field_value, 'd'))
-        else:
-            if sizeof_field == 2:
-                object.__setattr__(self, field, swap_2(field_value))
-            elif sizeof_field == 4:
-                object.__setattr__(self, field, swap_4(field_value))
-            elif sizeof_field == 8:
-                object.__setattr__(self, field, swap_8(field_value))
-
 
 class StructureMeta(StructOrUnionMeta):
     _is_union = False
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
@@ -22,7 +22,6 @@
         assert X._fields_ == [("a", c_int)]
         assert Y._fields_ == [("b", c_int)]
         assert Z._fields_ == [("a", c_int)]
-
         assert Y._names_ == ['a', 'b']
 
     def test_subclass_delayed(self):
@@ -594,3 +593,13 @@
 
         x = X()
         assert x.x == 0
+
+    def test_duplicate_names(self):
+        class S(Structure):
+            _fields_ = [('a', c_int),
+                        ('b', c_int),
+                        ('a', c_byte)]
+        s = S(260, -123)
+        assert sizeof(s) == 3 * sizeof(c_int)
+        assert s.a == 4     # 256 + 4
+        assert s.b == -123


More information about the pypy-commit mailing list