[pypy-commit] pypy default: merge heads

arigo noreply at buildbot.pypy.org
Sat May 11 13:44:34 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r63976:1b2ce85a6d2a
Date: 2013-05-11 13:47 +0200
http://bitbucket.org/pypy/pypy/changeset/1b2ce85a6d2a/

Log:	merge heads

diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py
--- a/lib-python/2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/2.7/distutils/sysconfig_pypy.py
@@ -122,10 +122,10 @@
         compiler.compiler_so.extend(['-fPIC', '-Wimplicit'])
         compiler.shared_lib_extension = get_config_var('SO')
         if "CFLAGS" in os.environ:
-            cflags = os.environ["CFLAGS"]
-            compiler.compiler.append(cflags)
-            compiler.compiler_so.append(cflags)
-            compiler.linker_so.append(cflags)
+            cflags = os.environ["CFLAGS"].split()
+            compiler.compiler.extend(cflags)
+            compiler.compiler_so.extend(cflags)
+            compiler.linker_so.extend(cflags)
 
 
 from sysconfig_cpython import (
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -47,7 +47,7 @@
 # The short X.Y version.
 version = '2.0'
 # The full version, including alpha/beta/rc tags.
-release = '2.0-beta1'
+release = '2.0.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -105,7 +105,7 @@
 
     $ ./pypy-c
     Python 2.7.3 (7e4f0faa3d51, Nov 22 2012, 10:35:18)
-    [PyPy 2.0.0-beta1 with GCC 4.7.1] on linux2
+    [PyPy 2.0.0 with GCC 4.7.1] on linux2
     Type "help", "copyright", "credits" or "license" for more information.
     And now for something completely different: ``RPython magically makes you rich
     and famous (says so on the tin)''
@@ -235,7 +235,7 @@
 the ``bin/pypy`` executable.
 
 To install PyPy system wide on unix-like systems, it is recommended to put the
-whole hierarchy alone (e.g. in ``/opt/pypy2.0-beta1``) and put a symlink to the
+whole hierarchy alone (e.g. in ``/opt/pypy2.0``) and put a symlink to the
 ``pypy`` executable into ``/usr/bin`` or ``/usr/local/bin``
 
 If the executable fails to find suitable libraries, it will report
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -53,10 +53,10 @@
 PyPy is ready to be executed as soon as you unpack the tarball or the zip
 file, with no need to install it in any specific location::
 
-    $ tar xf pypy-2.0-beta1-linux.tar.bz2
-    $ ./pypy-2.0-beta1/bin/pypy
+    $ tar xf pypy-2.0.tar.bz2
+    $ ./pypy-2.0/bin/pypy
     Python 2.7.3 (7e4f0faa3d51, Nov 22 2012, 10:35:18)
-    [PyPy 2.0.0-beta1 with GCC 4.7.1] on linux2
+    [PyPy 2.0.0 with GCC 4.7.1] on linux2
     Type "help", "copyright", "credits" or "license" for more information.
     And now for something completely different: ``PyPy is an exciting technology
     that lets you to write fast, portable, multi-platform interpreters with less
@@ -75,14 +75,14 @@
 
     $ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
 
-    $ ./pypy-2.0-beta1/bin/pypy distribute_setup.py
+    $ ./pypy-2.0/bin/pypy distribute_setup.py
 
-    $ ./pypy-2.0-beta1/bin/pypy get-pip.py
+    $ ./pypy-2.0/bin/pypy get-pip.py
 
-    $ ./pypy-2.0-beta1/bin/pip install pygments  # for example
+    $ ./pypy-2.0/bin/pip install pygments  # for example
 
-3rd party libraries will be installed in ``pypy-2.0-beta1/site-packages``, and
-the scripts in ``pypy-2.0-beta1/bin``.
+3rd party libraries will be installed in ``pypy-2.0/site-packages``, and
+the scripts in ``pypy-2.0/bin``.
 
 Installing using virtualenv
 ---------------------------
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 2.0 beta 2`_: the latest official release
+* `Release 2.0`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -110,7 +110,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 2.0 beta 2`: http://pypy.org/download.html
+.. _`Release 2.0`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.0.0.rst b/pypy/doc/release-2.0.0.rst
--- a/pypy/doc/release-2.0.0.rst
+++ b/pypy/doc/release-2.0.0.rst
@@ -4,6 +4,8 @@
 
 We're pleased to announce PyPy 2.0. This is a stable release that brings
 a swath of bugfixes, small performance improvements and compatibility fixes.
+PyPy 2.0 is a big step for us and we hope in the future we'll be able to
+provide stable releases more often.
 
 You can download the PyPy 2.0 release here:
 
@@ -19,6 +21,10 @@
 
 .. _`cffi`: http://cffi.readthedocs.org
 
+If you're using PyPy for anything, it would help us immensely if you fill out
+the following survey: http://bit.ly/pypysurvey This is for the developers
+eyes and we will not make any information public without your agreement.
+
 What is PyPy?
 =============
 
@@ -28,8 +34,8 @@
 
 This release supports x86 machines running Linux 32/64, Mac OS X 64 or
 Windows 32.  Windows 64 work is still stalling, we would welcome a volunteer
-to handle that. ARM support is on the way and we're expecting to release
-an alpha ARM version shortly.
+to handle that. ARM support is on the way, as you can see from the recently
+released alpha for ARM.
 
 .. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
 
@@ -54,6 +60,10 @@
 
 * A lot of stability issues fixed.
 
+* Refactoring much of the numpypy array classes, which resulted in removal of
+  lazy expression evaluation. On the other hand, we now have more complete
+  dtype support and support more array attributes.  
+
 .. _`pypycore`: https://github.com/gevent-on-pypy/pypycore/
 .. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks
 
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -5,3 +5,5 @@
 .. this is a revision shortly after release-2.0
 .. startrev: a13c07067613
 
+.. branch: numpy-pickle
+Pickling of numpy arrays and dtypes (including record dtypes)
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -13,6 +13,7 @@
     # imported yet, and when it has been, it is mod.__dict__.items() just
     # after startup().
     w_initialdict = None
+    lazy = False
 
     def __init__(self, space, w_name):
         """ NOT_RPYTHON """
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -461,7 +461,7 @@
         p = os.path.abspath(p)
         monkeypatch.chdir(os.path.dirname(app_main))
         child = self.spawn(['-i',
-                            '-m', 'test2.mymodule',
+                            '-m', 'test.mymodule',
                             'extra'])
         child.expect('mymodule running')
         child.expect('Name: __main__')
@@ -472,9 +472,9 @@
         child.expect(re.escape(repr("foobar")))
         child.expect('>>> ')
         child.sendline('import sys')
-        child.sendline('"test2" in sys.modules')
+        child.sendline('"test" in sys.modules')
         child.expect('True')
-        child.sendline('"test2.mymodule" in sys.modules')
+        child.sendline('"test.mymodule" in sys.modules')
         child.expect('False')
         child.sendline('sys.path[0]')
         child.expect("''")
@@ -566,7 +566,7 @@
         child.expect('hello')
 
         monkeypatch.chdir(os.path.dirname(app_main))
-        child = self.spawn(['-mtest2.mymodule'])
+        child = self.spawn(['-mtest.mymodule'])
         child.expect('mymodule running')
 
     def test_ps1_only_if_interactive(self):
@@ -671,7 +671,7 @@
         p = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'mymodule.py')
         p = os.path.abspath(p)
         monkeypatch.chdir(os.path.dirname(app_main))
-        data = self.run('-m test2.mymodule extra')
+        data = self.run('-m test.mymodule extra')
         assert 'mymodule running' in data
         assert 'Name: __main__' in data
         # ignoring case for windows. abspath behaves different from autopath
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
 #define PY_VERSION		"2.7.3"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "2.0.0-beta2"
+#define PYPY_VERSION "2.1.0-alpha0"
 
 /* Subversion Revision number of this file (not of the repository).
  * Empty since Mercurial migration. */
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -12,6 +12,7 @@
         'zeros': 'interp_numarray.zeros',
         'empty': 'interp_numarray.zeros',
         'ones': 'interp_numarray.ones',
+        '_reconstruct' : 'interp_numarray._reconstruct',
         'dot': 'interp_arrayops.dot',
         'fromstring': 'interp_support.fromstring',
         'flatiter': 'interp_flatiter.W_FlatIterator',
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -55,6 +55,9 @@
     def get_size(self):
         return self.size // self.dtype.itemtype.get_element_size()
 
+    def get_storage_size(self):
+        return self.size
+
     def reshape(self, space, orig_array, new_shape):
         # Since we got to here, prod(new_shape) == self.size
         new_strides = None
@@ -328,13 +331,14 @@
 
 
 class ConcreteArray(ConcreteArrayNotOwning):
-    def __init__(self, shape, dtype, order, strides, backstrides):
-        # we allocate the actual storage later because we need to compute
-        # self.size first
+    def __init__(self, shape, dtype, order, strides, backstrides, storage=lltype.nullptr(RAW_STORAGE)):
         null_storage = lltype.nullptr(RAW_STORAGE)
         ConcreteArrayNotOwning.__init__(self, shape, dtype, order, strides, backstrides,
                                         null_storage)
-        self.storage = dtype.itemtype.malloc(self.size)
+        if storage == lltype.nullptr(RAW_STORAGE):
+            self.storage = dtype.itemtype.malloc(self.size)
+        else:
+            self.storage = storage
 
     def __del__(self):
         free_raw_storage(self.storage, track_allocation=False)
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -35,12 +35,17 @@
         return W_NDimArray(impl)
 
     @staticmethod
-    def from_shape_and_storage(shape, storage, dtype, order='C'):
+    def from_shape_and_storage(shape, storage, dtype, order='C', owning=False):
         from pypy.module.micronumpy.arrayimpl import concrete
         assert shape
         strides, backstrides = calc_strides(shape, dtype, order)
-        impl = concrete.ConcreteArrayNotOwning(shape, dtype, order, strides,
-                                               backstrides, storage)
+        if owning:
+            # Will free storage when GCd
+            impl = concrete.ConcreteArray(shape, dtype, order, strides,
+                                                backstrides, storage=storage)
+        else:
+            impl = concrete.ConcreteArrayNotOwning(shape, dtype, order, strides,
+                                                backstrides, storage)
         return W_NDimArray(impl)
 
     @staticmethod
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -133,11 +133,46 @@
                                                                  space.wrap(offset)]))
         return w_d
 
+    def set_fields(self, space, w_fields):
+        if w_fields == space.w_None:
+            self.fields = None
+        else:
+            ofs_and_items = []
+            size = 0
+            for key in space.listview(w_fields):
+                value = space.getitem(w_fields, key)
+
+                dtype = space.getitem(value, space.wrap(0))
+                assert isinstance(dtype, W_Dtype)
+
+                offset = space.int_w(space.getitem(value, space.wrap(1)))
+                self.fields[space.str_w(key)] = offset, dtype
+
+                ofs_and_items.append((offset, dtype.itemtype))
+                size += dtype.itemtype.get_element_size()
+
+            self.itemtype = types.RecordType(ofs_and_items, size)
+            self.name = "void" + str(8 * self.itemtype.get_element_size())
+
     def descr_get_names(self, space):
         if self.fieldnames is None:
             return space.w_None
         return space.newtuple([space.wrap(name) for name in self.fieldnames])
 
+    def set_names(self, space, w_names):
+        if w_names == space.w_None:
+            self.fieldnames = None
+        else:
+            self.fieldnames = []
+            iter = space.iter(w_names)
+            while True:
+                try:
+                    self.fieldnames.append(space.str_w(space.next(iter)))
+                except OperationError, e:
+                    if not e.match(space, space.w_StopIteration):
+                        raise
+                    break
+
     @unwrap_spec(item=str)
     def descr_getitem(self, space, item):
         if self.fields is None:
@@ -180,6 +215,51 @@
     def get_size(self):
         return self.itemtype.get_element_size()
 
+    def descr_reduce(self, space):
+        w_class = space.type(self)
+
+        kind = self.kind
+        elemsize = self.itemtype.get_element_size()
+        builder_args = space.newtuple([space.wrap("%s%d" % (kind, elemsize)), space.wrap(0), space.wrap(1)])
+
+        version = space.wrap(3)
+        order = space.wrap(byteorder_prefix if self.native else nonnative_byteorder_prefix)
+        names = self.descr_get_names(space)
+        values = self.descr_get_fields(space)
+        if self.fields:
+            #TODO: Implement this when subarrays are implemented
+            subdescr = space.w_None
+            #TODO: Change this when alignment is implemented :
+            size = 0
+            for key in self.fields:
+                dtype = self.fields[key][1]
+                assert isinstance(dtype, W_Dtype)
+                size += dtype.get_size()
+            w_size = space.wrap(size)
+            alignment = space.wrap(1)
+        else:
+            subdescr = space.w_None
+            w_size = space.wrap(-1)
+            alignment = space.wrap(-1)
+        flags = space.wrap(0)
+
+        data = space.newtuple([version, order, subdescr, names, values, w_size, alignment, flags])
+
+        return space.newtuple([w_class, builder_args, data])
+
+    def descr_setstate(self, space, w_data):
+        if space.int_w(space.getitem(w_data, space.wrap(0))) != 3:
+            raise OperationError(space.w_NotImplementedError, space.wrap("Pickling protocol version not supported"))
+
+        self.native = space.str_w(space.getitem(w_data, space.wrap(1))) == byteorder_prefix
+
+        fieldnames = space.getitem(w_data, space.wrap(3))
+        self.set_names(space, fieldnames)
+
+        fields = space.getitem(w_data, space.wrap(4))
+        self.set_fields(space, fields)
+        print self.itemtype
+
 class W_ComplexDtype(W_Dtype):
     def __init__(self, itemtype, num, kind, name, char, w_box_type,
                  alternate_constructors=[], aliases=[],
@@ -238,8 +318,7 @@
         num = 20
         basename = 'void'
         w_box_type = space.gettypefor(interp_boxes.W_VoidBox)
-        raise OperationError(space.w_NotImplementedError, space.wrap(
-            "pure void dtype"))
+        return dtype_from_list(space, space.newlist([]))
     else:
         assert char == 'U'
         basename = 'unicode'
@@ -252,9 +331,10 @@
 
 def dtype_from_spec(space, name):
         raise OperationError(space.w_NotImplementedError, space.wrap(
-            "dtype from spec"))    
+            "dtype from spec"))
 
-def descr__new__(space, w_subtype, w_dtype):
+def descr__new__(space, w_subtype, w_dtype, w_align=None, w_copy=None):
+    # w_align and w_copy are necessary for pickling
     cache = get_dtype_cache(space)
 
     if space.is_none(w_dtype):
@@ -297,6 +377,9 @@
     __ne__ = interp2app(W_Dtype.descr_ne),
     __getitem__ = interp2app(W_Dtype.descr_getitem),
 
+    __reduce__ = interp2app(W_Dtype.descr_reduce),
+    __setstate__ = interp2app(W_Dtype.descr_setstate),
+
     num = interp_attrproperty("num", cls=W_Dtype),
     kind = interp_attrproperty("kind", cls=W_Dtype),
     char = interp_attrproperty("char", cls=W_Dtype),
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -781,6 +781,42 @@
             return space.float(self.descr_getitem(space, space.wrap(0)))
         raise OperationError(space.w_TypeError, space.wrap("only length-1 arrays can be converted to Python scalars"))
 
+    def descr_reduce(self, space):
+        from rpython.rtyper.lltypesystem import rffi
+        from rpython.rlib.rstring import StringBuilder
+        from pypy.interpreter.mixedmodule import MixedModule
+
+        numpypy = space.getbuiltinmodule("_numpypy")
+        assert isinstance(numpypy, MixedModule)
+        multiarray = numpypy.get("multiarray")
+        assert isinstance(multiarray, MixedModule)
+        reconstruct = multiarray.get("_reconstruct")
+
+        parameters = space.newtuple([space.gettypefor(W_NDimArray), space.newtuple([space.wrap(0)]), space.wrap("b")])
+
+        builder = StringBuilder()
+        builder.append_charpsize(self.implementation.get_storage(), self.implementation.get_storage_size())
+
+        state = space.newtuple([
+                space.wrap(1),      # version
+                self.descr_get_shape(space),
+                self.get_dtype(),
+                space.wrap(False),  # is_fortran
+                space.wrap(builder.build()),
+            ])
+
+        return space.newtuple([reconstruct, parameters, state])
+
+    def descr_setstate(self, space, w_state):
+        from rpython.rtyper.lltypesystem import rffi
+
+        shape = space.getitem(w_state, space.wrap(1))
+        dtype = space.getitem(w_state, space.wrap(2))
+        assert isinstance(dtype, interp_dtype.W_Dtype)
+        isfortran = space.getitem(w_state, space.wrap(3))
+        storage = space.getitem(w_state, space.wrap(4))
+
+        self.implementation = W_NDimArray.from_shape_and_storage([space.int_w(i) for i in space.listview(shape)], rffi.str2charp(space.str_w(storage), track_allocation=False), dtype, owning=True).implementation
 
 
 @unwrap_spec(offset=int)
@@ -814,6 +850,7 @@
 
 W_NDimArray.typedef = TypeDef(
     "ndarray",
+    __module__ = "numpypy",
     __new__ = interp2app(descr_new_array),
 
     __len__ = interp2app(W_NDimArray.descr_len),
@@ -932,6 +969,8 @@
     __pypy_data__ = GetSetProperty(W_NDimArray.fget___pypy_data__,
                                    W_NDimArray.fset___pypy_data__,
                                    W_NDimArray.fdel___pypy_data__),
+    __reduce__ = interp2app(W_NDimArray.descr_reduce),
+    __setstate__ = interp2app(W_NDimArray.descr_setstate),
 )
 
 @unwrap_spec(ndmin=int, copy=bool, subok=bool)
@@ -1008,6 +1047,9 @@
     arr.fill(one)
     return space.wrap(arr)
 
+def _reconstruct(space, w_subtype, w_shape, w_dtype):
+    return descr_new_array(space, w_subtype, w_shape, w_dtype)
+
 W_FlatIterator.typedef = TypeDef(
     'flatiter',
     __iter__ = interp2app(W_FlatIterator.descr_iter),
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -73,8 +73,8 @@
 
         # Coerce to floats, some of these will eventually be float16, or
         # whatever our smallest float type is.
-        assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float16_dtype 
-        assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float16_dtype 
+        assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float16_dtype
+        assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float16_dtype
         assert find_unaryop_result_dtype(space, uint8_dtype, promote_to_float=True) is float16_dtype
         assert find_unaryop_result_dtype(space, int16_dtype, promote_to_float=True) is float32_dtype
         assert find_unaryop_result_dtype(space, uint16_dtype, promote_to_float=True) is float32_dtype
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -14,8 +14,9 @@
             from rpython.rtyper.lltypesystem import rffi
             ptr_size = rffi.sizeof(rffi.CCHARP)
         cls.w_ptr_size = cls.space.wrap(ptr_size)
-    
+
 class AppTestDtypes(BaseAppTestDtypes):
+    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
     def test_dtype(self):
         from numpypy import dtype
 
@@ -149,7 +150,7 @@
     def test_bool_binop_types(self):
         from numpypy import array, dtype
         types = [
-            '?', 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'f', 'd', 
+            '?', 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'f', 'd',
             'e'
         ]
         a = array([True], '?')
@@ -270,6 +271,23 @@
         ]:
             assert hash(tp(value)) == hash(value)
 
+    def test_pickle(self):
+        from numpypy import array, dtype
+        from cPickle import loads, dumps
+        a = array([1,2,3])
+        assert a.dtype.__reduce__() == (dtype, ('i8', 0, 1), (3, '<', None, None, None, -1, -1, 0))
+        assert loads(dumps(a.dtype)) == a.dtype
+
+    def test_pickle_record(self):
+        from numpypy import array, dtype
+        from cPickle import loads, dumps
+
+        d = dtype([("x", "int32"), ("y", "int32"), ("z", "int32"), ("value", float)])
+        assert d.__reduce__() == (dtype, ('V20', 0, 1), (3, '<', None, ('x', 'y', 'z', 'value'), {'y': (dtype('int32'), 4), 'x': (dtype('int32'), 0), 'z': (dtype('int32'), 8), 'value': (dtype('float64'), 12)}, 20, 1, 0))
+
+        new_d = loads(dumps(d))
+
+        assert new_d.__reduce__() == d.__reduce__()
 
 class AppTestTypes(BaseAppTestDtypes):
     def test_abstract_types(self):
@@ -340,7 +358,7 @@
         import numpypy as numpy
 
         assert numpy.int8.mro() == [numpy.int8, numpy.signedinteger,
-                                    numpy.integer, numpy.number, 
+                                    numpy.integer, numpy.number,
                                     numpy.generic, object]
 
         a = numpy.array([1, 2, 3], numpy.int8)
@@ -363,8 +381,8 @@
     def test_uint8(self):
         import numpypy as numpy
 
-        assert numpy.uint8.mro() == [numpy.uint8, numpy.unsignedinteger, 
-                                     numpy.integer, numpy.number, 
+        assert numpy.uint8.mro() == [numpy.uint8, numpy.unsignedinteger,
+                                     numpy.integer, numpy.number,
                                      numpy.generic, object]
 
         a = numpy.array([1, 2, 3], numpy.uint8)
@@ -435,8 +453,8 @@
         import numpypy as numpy
 
         assert numpy.int_ is numpy.dtype(int).type
-        assert numpy.int_.mro() == [numpy.int_, numpy.signedinteger, 
-                                    numpy.integer, numpy.number, 
+        assert numpy.int_.mro() == [numpy.int_, numpy.signedinteger,
+                                    numpy.integer, numpy.number,
                                     numpy.generic, int, object]
 
     def test_int64(self):
@@ -444,12 +462,12 @@
         import numpypy as numpy
 
         if sys.maxint == 2 ** 63 -1:
-            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, 
-                                         numpy.integer, numpy.number, 
+            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger,
+                                         numpy.integer, numpy.number,
                                          numpy.generic, int, object]
         else:
-            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, 
-                                         numpy.integer, numpy.number, 
+            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger,
+                                         numpy.integer, numpy.number,
                                          numpy.generic, object]
 
         assert numpy.dtype(numpy.int64).type is numpy.int64
@@ -465,8 +483,8 @@
         import sys
         import numpypy as numpy
 
-        assert numpy.uint64.mro() == [numpy.uint64, numpy.unsignedinteger, 
-                                      numpy.integer, numpy.number, 
+        assert numpy.uint64.mro() == [numpy.uint64, numpy.unsignedinteger,
+                                      numpy.integer, numpy.number,
                                       numpy.generic, object]
 
         assert numpy.dtype(numpy.uint64).type is numpy.uint64
@@ -481,8 +499,8 @@
 
     def test_float16(self):
         import numpypy as numpy
-        assert numpy.float16.mro() == [numpy.float16, numpy.floating, 
-                                       numpy.inexact, numpy.number, 
+        assert numpy.float16.mro() == [numpy.float16, numpy.floating,
+                                       numpy.inexact, numpy.number,
                                        numpy.generic, object]
 
         assert numpy.float16(12) == numpy.float64(12)
@@ -493,8 +511,8 @@
     def test_float32(self):
         import numpypy as numpy
 
-        assert numpy.float32.mro() == [numpy.float32, numpy.floating, 
-                                       numpy.inexact, numpy.number, 
+        assert numpy.float32.mro() == [numpy.float32, numpy.floating,
+                                       numpy.inexact, numpy.number,
                                        numpy.generic, object]
 
         assert numpy.float32(12) == numpy.float64(12)
@@ -504,8 +522,8 @@
     def test_float64(self):
         import numpypy as numpy
 
-        assert numpy.float64.mro() == [numpy.float64, numpy.floating, 
-                                       numpy.inexact, numpy.number, 
+        assert numpy.float64.mro() == [numpy.float64, numpy.floating,
+                                       numpy.inexact, numpy.number,
                                        numpy.generic, float, object]
 
         a = numpy.array([1, 2, 3], numpy.float64)
@@ -856,7 +874,7 @@
         # it can be float96 or float128
         if numpy.longfloat != numpy.float64:
             assert numpy.longfloat.mro()[1:] == [numpy.floating,
-                                       numpy.inexact, numpy.number, 
+                                       numpy.inexact, numpy.number,
                                        numpy.generic, object]
         a = numpy.array([1, 2, 3], numpy.longdouble)
         assert type(a[1]) is numpy.longdouble
@@ -898,3 +916,4 @@
         a = array([1, 2, 3], dtype=self.non_native_prefix + 'G') # clongdouble
         assert a[0] == 1
         assert (a + a)[1] == 4
+
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -214,6 +214,7 @@
         assert get(1, 1) == 3
 
 class AppTestNumArray(BaseNumpyAppTest):
+    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
     def w_CustomIndexObject(self, index):
         class CustomIndexObject(object):
             def __init__(self, index):
@@ -1786,6 +1787,17 @@
         assert raises(TypeError, "int(array([1, 2]))")
         assert int(array([1.5])) == 1
 
+    def test__reduce__(self):
+        from numpypy import array, dtype
+        from cPickle import loads, dumps
+
+        a = array([1, 2], dtype="int64")
+        data = a.__reduce__()
+
+        assert data[2][4] == '\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00'
+
+        pickled_data = dumps(a)
+        assert (loads(pickled_data) == a).all()
 
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
@@ -2534,6 +2546,8 @@
 
 
 class AppTestRecordDtype(BaseNumpyAppTest):
+    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
+
     def test_zeros(self):
         from numpypy import zeros, integer
         a = zeros(2, dtype=[('x', int), ('y', float)])
@@ -2666,6 +2680,25 @@
         assert s.replace('\n', '') == \
                       "array(['abc', 'defg', 'ab'],       dtype='|S4')"
 
+    def test_pickle(self):
+        from numpypy import dtype, array
+        from cPickle import loads, dumps
+
+        d = dtype([('x', str), ('y', 'int32')])
+        a = array([('a', 2), ('cde', 1)], dtype=d)
+
+        a = loads(dumps(a))
+        d = a.dtype
+
+        assert str(d.fields['x'][0]) == '|S0'
+        assert d.fields['x'][1] == 0
+        assert str(d.fields['y'][0]) == 'int32'
+        assert d.fields['y'][1] == 0
+        assert d.name == 'void32'
+
+        assert a[0]['y'] == 2
+        assert a[1]['y'] == 1
+
 
 class AppTestPyPy(BaseNumpyAppTest):
     def setup_class(cls):
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -11,7 +11,7 @@
 #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
-PYPY_VERSION               = (2, 0, 0, "beta", 2)    #XXX # sync patchlevel.h
+PYPY_VERSION               = (2, 1, 0, "alpha", 0)    #XXX # sync patchlevel.h
 
 if platform.name == 'msvc':
     COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -446,7 +446,7 @@
     TYPES += ['__int128_t']
 except CompilationError:
     pass
-    
+
 _TYPES_ARE_UNSIGNED = set(['size_t', 'uintptr_t'])   # plus "unsigned *"
 if os.name != 'nt':
     TYPES.append('mode_t')
@@ -693,10 +693,13 @@
         builder_class = UnicodeBuilder
 
     # str -> char*
-    def str2charp(s):
+    def str2charp(s, track_allocation=True):
         """ str -> char*
         """
-        array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw')
+        if track_allocation:
+            array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw', track_allocation=True)
+        else:
+            array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw', track_allocation=False)
         i = len(s)
         array[i] = lastchar
         i -= 1
@@ -704,10 +707,13 @@
             array[i] = s[i]
             i -= 1
         return array
-    str2charp._annenforceargs_ = [strtype]
+    str2charp._annenforceargs_ = [strtype, bool]
 
-    def free_charp(cp):
-        lltype.free(cp, flavor='raw')
+    def free_charp(cp, track_allocation=True):
+        if track_allocation:
+            lltype.free(cp, flavor='raw', track_allocation=True)
+        else:
+            lltype.free(cp, flavor='raw', track_allocation=False)
 
     # char* -> str
     # doesn't free char*


More information about the pypy-commit mailing list