[pypy-commit] pypy default: Move struct.Struct to be RPYthon so we can mark fields as immutable

alex_gaynor noreply at buildbot.pypy.org
Tue Jan 21 05:20:09 CET 2014


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r68797:496deb64bcef
Date: 2014-01-20 22:19 -0600
http://bitbucket.org/pypy/pypy/changeset/496deb64bcef/

Log:	Move struct.Struct to be RPYthon so we can mark fields as immutable

diff --git a/pypy/module/struct/__init__.py b/pypy/module/struct/__init__.py
--- a/pypy/module/struct/__init__.py
+++ b/pypy/module/struct/__init__.py
@@ -49,11 +49,12 @@
         'calcsize': 'interp_struct.calcsize',
         'pack': 'interp_struct.pack',
         'unpack': 'interp_struct.unpack',
-        }
+
+        'Struct': 'interp_struct.W_Struct',
+    }
 
     appleveldefs = {
         'error': 'app_struct.error',
         'pack_into': 'app_struct.pack_into',
         'unpack_from': 'app_struct.unpack_from',
-        'Struct': 'app_struct.Struct',
-        }
+    }
diff --git a/pypy/module/struct/app_struct.py b/pypy/module/struct/app_struct.py
--- a/pypy/module/struct/app_struct.py
+++ b/pypy/module/struct/app_struct.py
@@ -4,6 +4,7 @@
 """
 import struct
 
+
 class error(Exception):
     """Exception raised on various occasions; argument is a string
     describing what is wrong."""
@@ -21,21 +22,3 @@
         raise error("unpack_from requires a buffer of at least %d bytes"
                     % (size,))
     return struct.unpack(fmt, data)
-
-# XXX inefficient
-class Struct(object):
-    def __init__(self, format):
-        self.format = format
-        self.size = struct.calcsize(format)
-
-    def pack(self, *args):
-        return struct.pack(self.format, *args)
-
-    def unpack(self, s):
-        return struct.unpack(self.format, s)
-
-    def pack_into(self, buffer, offset, *args):
-        return pack_into(self.format, buffer, offset, *args)
-
-    def unpack_from(self, buffer, offset=0):
-        return unpack_from(self.format, buffer, offset)
diff --git a/pypy/module/struct/interp_struct.py b/pypy/module/struct/interp_struct.py
--- a/pypy/module/struct/interp_struct.py
+++ b/pypy/module/struct/interp_struct.py
@@ -1,15 +1,23 @@
-from pypy.interpreter.gateway import unwrap_spec
-from pypy.interpreter.error import OperationError
-from pypy.module.struct.formatiterator import PackFormatIterator, UnpackFormatIterator
 from rpython.rlib import jit
 from rpython.rlib.rstruct.error import StructError, StructOverflowError
 from rpython.rlib.rstruct.formatiterator import CalcSizeFormatIterator
 
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.typedef import (
+    TypeDef, interp_attrproperty, interp_attrproperty_w
+)
+from pypy.module.struct.formatiterator import (
+    PackFormatIterator, UnpackFormatIterator
+)
+
 
 @unwrap_spec(format=str)
 def calcsize(space, format):
     return space.wrap(_calcsize(space, format))
 
+
 def _calcsize(space, format):
     fmtiter = CalcSizeFormatIterator()
     try:
@@ -52,3 +60,44 @@
         w_error = space.getattr(w_module, space.wrap('error'))
         raise OperationError(w_error, space.wrap(e.msg))
     return space.newtuple(fmtiter.result_w[:])
+
+
+class W_Struct(W_Root):
+    _immutable_fields_ = ["format", "size"]
+
+    def __init__(self, space, format):
+        self.format = format
+        self.size = _calcsize(space, format)
+
+    @unwrap_spec(format=str)
+    def descr__new__(space, w_subtype, format):
+        self = space.allocate_instance(W_Struct, w_subtype)
+        W_Struct.__init__(self, space, format)
+        return self
+
+    def wrap_struct_method(name):
+        def impl(self, space, __args__):
+            w_module = space.getbuiltinmodule('struct')
+            w_method = space.getattr(w_module, space.wrap(name))
+            return space.call_obj_args(
+                w_method, space.wrap(self.format), __args__
+            )
+
+        return impl
+
+    descr_pack = wrap_struct_method("pack")
+    descr_unpack = wrap_struct_method("unpack")
+    descr_pack_into = wrap_struct_method("pack_into")
+    descr_unpack_from = wrap_struct_method("unpack_from")
+
+
+W_Struct.typedef = TypeDef("Struct",
+    __new__=interp2app(W_Struct.descr__new__.im_func),
+    format=interp_attrproperty("format", cls=W_Struct),
+    size=interp_attrproperty("size", cls=W_Struct),
+
+    pack=interp2app(W_Struct.descr_pack),
+    unpack=interp2app(W_Struct.descr_unpack),
+    pack_into=interp2app(W_Struct.descr_pack_into),
+    unpack_from=interp2app(W_Struct.descr_unpack_from),
+)


More information about the pypy-commit mailing list