[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