[pypy-commit] pypy default: refactor how fields are handled in ctypes structures: instead of relying on __getattr__/__setattr__, make them descriptors and store them directly in the __dict__ of the class
antocuni
noreply at buildbot.pypy.org
Wed Aug 10 18:16:27 CEST 2011
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r46423:39aa92506023
Date: 2011-08-10 18:08 +0200
http://bitbucket.org/pypy/pypy/changeset/39aa92506023/
Log: refactor how fields are handled in ctypes structures: instead of
relying on __getattr__/__setattr__, make them descriptors and store
them directly in the __dict__ of the class
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
@@ -60,6 +60,7 @@
names = resnames
self._names = names
self._fieldtypes = fields
+ self.__dict__.update(fields)
class Field(object):
def __init__(self, name, offset, size, ctype, num, is_bitfield):
@@ -73,6 +74,35 @@
return "<Field '%s' offset=%d size=%d>" % (self.name, self.offset,
self.size)
+ def __get__(self, obj, cls=None):
+ if obj is None:
+ return self
+ if self.is_bitfield:
+ # bitfield member, use direct access
+ return obj._buffer.__getattr__(self.name)
+ else:
+ fieldtype = self.ctype
+ offset = self.num
+ suba = obj._subarray(fieldtype, self.name)
+ return fieldtype._CData_output(suba, obj, offset)
+
+
+ def __set__(self, obj, value):
+ fieldtype = self.ctype
+ cobj = fieldtype.from_param(value)
+ if ensure_objects(cobj) is not None:
+ key = keepalive_key(self.num)
+ store_reference(obj, key, cobj._objects)
+ arg = cobj._get_buffer_value()
+ if fieldtype._fficompositesize is not None:
+ from ctypes import memmove
+ dest = obj._buffer.fieldaddress(self.name)
+ memmove(dest, arg, fieldtype._fficompositesize)
+ else:
+ obj._buffer.__setattr__(self.name, arg)
+
+
+
# ________________________________________________________________
def _set_shape(tp, rawfields, is_union=False):
@@ -81,11 +111,6 @@
tp._ffiargshape = tp._ffishape = (tp._ffistruct, 1)
tp._fficompositesize = tp._ffistruct.size
-def struct_getattr(self, name):
- if name not in ('_fields_', '_fieldtypes'):
- if hasattr(self, '_fieldtypes') and name in self._fieldtypes:
- return self._fieldtypes[name]
- return _CDataMeta.__getattribute__(self, name)
def struct_setattr(self, name, value):
if name == '_fields_':
@@ -132,7 +157,6 @@
self._fieldtypes = {}
_set_shape(self, [], self._is_union)
- __getattr__ = struct_getattr
__setattr__ = struct_setattr
def from_address(self, address):
@@ -202,40 +226,6 @@
A = _rawffi.Array(fieldtype._ffishape)
return A.fromaddress(address, 1)
- def __setattr__(self, name, value):
- try:
- field = self._fieldtypes[name]
- except KeyError:
- return _CData.__setattr__(self, name, value)
- fieldtype = field.ctype
- cobj = fieldtype.from_param(value)
- if ensure_objects(cobj) is not None:
- key = keepalive_key(field.num)
- store_reference(self, key, cobj._objects)
- arg = cobj._get_buffer_value()
- if fieldtype._fficompositesize is not None:
- from ctypes import memmove
- dest = self._buffer.fieldaddress(name)
- memmove(dest, arg, fieldtype._fficompositesize)
- else:
- self._buffer.__setattr__(name, arg)
-
- def __getattribute__(self, name):
- if name == '_fieldtypes':
- return _CData.__getattribute__(self, '_fieldtypes')
- try:
- field = self._fieldtypes[name]
- except KeyError:
- return _CData.__getattribute__(self, name)
- if field.is_bitfield:
- # bitfield member, use direct access
- return self._buffer.__getattr__(name)
- else:
- fieldtype = field.ctype
- offset = field.num
- suba = self._subarray(fieldtype, name)
- return fieldtype._CData_output(suba, self, offset)
-
def _get_buffer_for_param(self):
return self
More information about the pypy-commit
mailing list