[pypy-svn] r50692 - pypy/dist/pypy/lib/_ctypes

fijal at codespeak.net fijal at codespeak.net
Wed Jan 16 23:39:26 CET 2008


Author: fijal
Date: Wed Jan 16 23:39:25 2008
New Revision: 50692

Modified:
   pypy/dist/pypy/lib/_ctypes/structure.py
Log:
Another portion of very broken logic. Two more bugs replicated.


Modified: pypy/dist/pypy/lib/_ctypes/structure.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/structure.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/structure.py	Wed Jan 16 23:39:25 2008
@@ -3,41 +3,60 @@
 from _ctypes.basics import _CData, _CDataMeta
 import inspect
 
+def names_and_fields(_fields_, superclass):
+    all_fields = _fields_[:]
+    for cls in inspect.getmro(superclass):
+        all_fields += getattr(cls, '_fields_', [])
+    names = [name for name, ctype in all_fields]
+    rawfields = [(name, ctype._ffiletter)
+                 for name, ctype in all_fields]
+    return names, rawfields, dict(all_fields)
+
 class StructureMeta(_CDataMeta):
     def __new__(self, name, cls, typedict):
         res = type.__new__(self, name, cls, typedict)
         if '_fields_' in typedict:
-            all_fields = typedict['_fields_'][:]
-            for cls in inspect.getmro(cls[0]):
-                all_fields += getattr(cls, '_fields_', [])
-            names = [name for name, ctype in all_fields]
-            res._fieldtypes = dict(all_fields)
-            rawfields = [(name, ctype._ffiletter)
-                         for name, ctype in all_fields]
-            ffistruct = _rawffi.Structure(rawfields)
-            res._ffistruct = ffistruct
-
-            def __init__(self, *args, **kwds):
-                self.__dict__['_buffer'] = ffistruct()
-                if len(args) > len(names):
-                    raise TypeError("too many arguments")
-                for name, arg in zip(names, args):
-                    if name in kwds:
-                        raise TypeError("duplicate value for argument %r" % (
-                            name,))
-                    self.__setattr__(name, arg)
-                for name, arg in kwds.items():
-                    self.__setattr__(name, arg)
-            res.__init__ = __init__
+            res._names, rawfields, res._fieldtypes = names_and_fields(
+                typedict['_fields_'], cls[0])
+            res._ffistruct = _rawffi.Structure(rawfields)            
+
+        def __init__(self, *args, **kwds):
+            if not hasattr(self, '_ffistruct'):
+                raise TypeError("Cannot instantiate structure, has no _fields_")
+            self.__dict__['_buffer'] = self._ffistruct()
+            if len(args) > len(self._names):
+                raise TypeError("too many arguments")
+            for name, arg in zip(self._names, args):
+                if name in kwds:
+                    raise TypeError("duplicate value for argument %r" % (
+                        name,))
+                self.__setattr__(name, arg)
+            for name, arg in kwds.items():
+                self.__setattr__(name, arg)
+        res.__init__ = __init__
+
 
         return res
 
+    def __setattr__(self, name, value):
+        if name == '_fields_':
+            if self.__dict__.get('_fields_', None):
+                raise TypeError("Fields already final")
+            self._names, rawfields, self._fieldtypes = names_and_fields(
+                value, self.__bases__[0])
+            self._ffistruct = _rawffi.Structure(rawfields)
+            _CDataMeta.__setattr__(self, '_fields_', value)
+            return
+        _CDataMeta.__setattr__(self, name, value)
+
     def from_address(self, address):
         instance = self.__new__(self)
         instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address)
         return instance
 
     def _sizeofinstances(self):
+        if not hasattr(self, '_ffistruct'):
+            return 0
         return self._ffistruct.size
 
 class Structure(_CData):



More information about the Pypy-commit mailing list