[pypy-commit] pypy release-5.x: merge default into release

mattip pypy.commits at gmail.com
Sun Mar 6 14:48:14 EST 2016


Author: mattip <matti.picus at gmail.com>
Branch: release-5.x
Changeset: r82827:a4efe1285120
Date: 2016-03-06 21:43 +0200
http://bitbucket.org/pypy/pypy/changeset/a4efe1285120/

Log:	merge default into release

diff --git a/pypy/doc/release-5.0.0.rst b/pypy/doc/release-5.0.0.rst
--- a/pypy/doc/release-5.0.0.rst
+++ b/pypy/doc/release-5.0.0.rst
@@ -3,8 +3,20 @@
 ==========
 
 We have released PyPy 5.0.0, about three months after PyPy 4.0.0. 
-We encourage all users of PyPy to update to this version. There are 
-bug fixes and a major upgrade to our c-api layer (cpyext)
+We encourage all users of PyPy to update to this version. Apart from the usual
+bug fixes, there is an ongoing effort to improve the warmup time and memory
+usage of JIT-related metadata. The exact effects depend vastly on the program
+you're running and can range from insignificant to warmup being up to 30%
+faster and memory dropping by about 30%. 
+
+We also merged a major upgrade to our C-API layer (cpyext), simplifying the
+interaction between c-level objects and PyPy interpreter level objects. As a
+result, lxml  with its cython compiled component `passes all tests`_ on PyPy
+
+Users who have gotten used to vmprof_ on Linux, and those on other platforms
+who have not yet tried its awesomeness, will be happy to hear that vmprof
+now just works on MacOS and Windows too, in both PyPy (built-in support) and
+CPython (as an installed module).
 
 You can download the PyPy 5.0.0 release here:
 
@@ -33,6 +45,8 @@
 .. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
 .. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
 .. _`numpy`: https://bitbucket.org/pypy/numpy
+.. _`passes all tests`: https://bitbucket.org/pypy/compatibility/wiki/lxml
+.. _vmprof: http://vmprof.readthedocs.org
 
 What is PyPy?
 =============
@@ -53,44 +67,156 @@
 .. _`dynamic languages`: http://pypyjs.org
 
 Other Highlights (since 4.0.1 released in November 2015)
-=======================================================
+=========================================================
+
+* New features:
+
+  * Support embedding PyPy in a C-program via cffi and static callbacks in cffi.
+    This deprecates the old method of embedding PyPy
+
+  * Refactor vmprof to work cross-operating-system, deprecate using buggy
+    libunwind on Linux platforms. Vmprof even works on Windows now.
+
+  * Support more of the C-API type slots, like tp_getattro, and fix C-API
+    macros, functions, and structs such as _PyLong_FromByteArray(),
+    PyString_GET_SIZE, f_locals in PyFrameObject, Py_NAN, co_filename in
+    PyCodeObject
+
+  * Use a more stable approach for allocating PyObjects in cpyext. (see
+    `blog post`_). Once the PyObject corresponding to a PyPy object is created,
+    it stays around at the same location until the death of the PyPy object.
+    Done with a little bit of custom GC support.  It allows us to kill the
+    notion of "borrowing" inside cpyext, reduces 4 dictionaries down to 1, and
+    significantly simplifies the whole approach (which is why it is a new
+    feature while technically a refactoring) and allows PyPy to support the
+    populart lxml module (as of the *next* release) with no PyPy specific
+    patches needed
+
+  * Make the default filesystem encoding ASCII, like CPython
+
+  * Use `hypothesis`_ in test creation, which is great for randomizing tests
 
 * Bug Fixes
 
-  * 
+  * Backport always using os.urandom for uuid4 from cpython and fix the JIT as well
+    (issue #2202)
 
-  * 
+  * More completely support datetime, optimize timedelta creation
 
-  * 
+  * Fix for issue 2185 which caused an inconsistent list of operations to be
+    generated by the unroller, appeared in a complicated DJango app
+
+  * Fix an elusive issue with stacklets on shadowstack which showed up when
+    forgetting stacklets without resuming them
+
+  * Fix entrypoint() which now acquires the GIL
+
+  * Fix direct_ffi_call() so failure does not bail out before setting CALL_MAY_FORCE
+
+  * Fix (de)pickling long values by simplifying the implementation
+
+  * Fix RPython rthread so that objects stored as threadlocal do not force minor
+    GC collection and are kept alive automatically. This improves perfomance of
+    short-running Python callbacks and prevents resetting such object between
+    calls
+
+  * Support floats as parameters to itertools.isslice()
+
+  * Check for the existence of CODESET, ignoring it should have prevented PyPy
+    from working on FreeBSD
+
+  * Fix for corner case (likely shown by Krakatau) for consecutive guards with
+    interdependencies
+
+  * Fix applevel bare class method comparisons which should fix pretty printing
+    in IPython
 
   * Issues reported with our previous release were resolved_ after reports from users on
     our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
     #pypy
 
-* New features:
-
-  * 
-
-  * 
-
-  * 
-
 * Numpy:
 
-  * 
+  * Updates to numpy 1.10.2 (incompatibilities and not-implemented features
+    still exist)
 
-  * 
+  * Support dtype=(('O', spec)) union while disallowing record arrays with
+    mixed object, non-object values
 
+  * Remove all traces of micronumpy from cpyext if --withoutmod-micronumpy option used
+
+  * Support indexing filtering with a boolean ndarray
+
+  * Support partition() as an app-level function, together with a cffi wrapper
+    in pypy/numpy, this now provides partial support for partition()
 
 * Performance improvements and refactorings:
 
-  * 
+  * Refactor and improve exception analysis in the annotator
 
-  * 
+  * Remove unnecessary special handling of space.wrap().
 
-  * 
+  * Improve the memory signature of numbering instances in the JIT. This should
+    massively decrease the amount of memory consumed by the JIT, which is
+    significant for most programs. Also compress the numberings using variable-
+    size encoding
+
+  * Support list-resizing setslice operations in RPython
+
+  * Tweak the trace-too-long heuristic for multiple jit drivers
+
+  * Refactor bookkeeping (such a cool word - three double letters) in the
+    annotater
+    
+  * Refactor wrappers for OS functions from rtyper to rlib and simplify them
+
+  * Simplify backend loading instructions to only use four variants
+
+  * Optimize string concatination
+
+  * Simplify GIL handling in non-jitted code
+
+  * Use INT_LSHIFT instead of INT_MUL when possible
+
+  * Improve struct.unpack by casting directly from the underlying buffer. 
+    Unpacking floats and doubles is about 15 times faster, and integer types
+    about 50% faster (on 64 bit integers). This was then subsequently
+    improved further in optimizeopt.py.
+
+  * Refactor naming in optimizeopt
+
+  * Change GraphAnalyzer to use a more precise way to recognize external
+    functions and fix null pointer handling, generally clean up external
+    function handling
+
+  * Optimize global lookups
+
+  * Optimize two-tuple lookups in mapdict
+
+  * Remove pure variants of ``getfield_gc_*`` operations from the JIT by
+    determining purity while tracing
+
+  * Refactor databasing
+
+  * Simplify bootstrapping in cpyext
+
+  * Refactor rtyper debug code into python.rtyper.debug
+
+  * Seperate structmember.h from Python.h Also enhance creating api functions
+    to specify which header file they appear in (previously only pypy_decl.h) 
+
+  * Reduce all guards from int_floordiv_ovf if one of the arguments is constant
+
+  * Fix tokenizer to enforce universal newlines, needed for Python 3 support
+
+  * Identify permutations of attributes at instance creation, reducing the
+    number of bridges created
+
+  * Greatly improve re.sub() performance
 
 .. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.0.0.html
+.. _`hypothesis`: http://hypothesis.readthedocs.org
+.. _`blog post`: http://morepypy.blogspot.com/2016/02/c-api-support-update.html
 
 Please update, and continue to help us make PyPy better.
 
diff --git a/pypy/doc/whatsnew-5.0.0.rst b/pypy/doc/whatsnew-5.0.0.rst
--- a/pypy/doc/whatsnew-5.0.0.rst
+++ b/pypy/doc/whatsnew-5.0.0.rst
@@ -191,3 +191,7 @@
 
 Fix boolean-array indexing in micronumpy
 
+.. branch: numpy_partition
+Support ndarray.partition() as an app-level function numpy.core._partition_use,
+provided as a cffi wrapper to upstream's implementation in the pypy/numpy repo
+
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
@@ -3,6 +3,5 @@
 =========================
 
 .. this is a revision shortly after release-5.0.0
-.. startrev: 6d13e55b962a
+.. startrev: 7bb6381d084c
 
-
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -13,6 +13,9 @@
 from pypy.interpreter.argument import Arguments
 from rpython.rlib import jit
 
+from rpython.rlib.rarithmetic import LONG_BIT
+from rpython.rlib.rbigint import rbigint
+
 
 funccallunrolling = unrolling_iterable(range(4))
 
@@ -557,6 +560,26 @@
                 return space.w_False
         return space.eq(self.w_function, w_other.w_function)
 
+    def is_w(self, space, other):
+        if not isinstance(other, Method):
+            return False
+        return (self.w_instance is other.w_instance and
+                self.w_function is other.w_function and
+                self.w_class is other.w_class)
+
+    def immutable_unique_id(self, space):
+        from pypy.objspace.std.util import IDTAG_METHOD as tag
+        from pypy.objspace.std.util import IDTAG_SHIFT
+        if self.w_instance is not None:
+            id = space.bigint_w(space.id(self.w_instance))
+            id = id.lshift(LONG_BIT)
+        else:
+            id = rbigint.fromint(0)
+        id = id.or_(space.bigint_w(space.id(self.w_function)))
+        id = id.lshift(LONG_BIT).or_(space.bigint_w(space.id(self.w_class)))
+        id = id.lshift(IDTAG_SHIFT).int_or_(tag)
+        return space.newlong_from_rbigint(id)
+
     def descr_method_hash(self):
         space = self.space
         w_result = space.hash(self.w_function)
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -1,5 +1,4 @@
-
-import unittest
+import pytest
 from pypy.interpreter import eval
 from pypy.interpreter.function import Function, Method, descr_function_get
 from pypy.interpreter.pycode import PyCode
@@ -187,6 +186,7 @@
         raises(
             TypeError, func, 42, {'arg1': 23})
 
+    @pytest.mark.skipif("config.option.runappdirect")
     def test_kwargs_nondict_mapping(self):
         class Mapping:
             def keys(self):
@@ -257,6 +257,14 @@
         meth = func.__get__(obj, object)
         assert meth() == obj
 
+    def test_none_get_interaction(self):
+        skip("XXX issue #2083")
+        assert type(None).__repr__(None) == 'None'
+
+    def test_none_get_interaction_2(self):
+        f = None.__repr__
+        assert f() == 'None'
+
     def test_no_get_builtin(self):
         assert not hasattr(dir, '__get__')
         class A(object):
@@ -284,6 +292,7 @@
         raises(TypeError, len, s, some_unknown_keyword=s)
         raises(TypeError, len, s, s, some_unknown_keyword=s)
 
+    @pytest.mark.skipif("config.option.runappdirect")
     def test_call_error_message(self):
         try:
             len()
@@ -325,6 +334,7 @@
         f = lambda: 42
         assert f.func_doc is None
 
+    @pytest.mark.skipif("config.option.runappdirect")
     def test_setstate_called_with_wrong_args(self):
         f = lambda: 42
         # not sure what it should raise, since CPython doesn't have setstate
@@ -550,6 +560,37 @@
         assert A().m == X()
         assert X() == A().m
 
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_method_identity(self):
+        class A(object):
+            def m(self):
+                pass
+            def n(self):
+                pass
+
+        class B(A):
+            pass
+
+        class X(object):
+            def __eq__(self, other):
+                return True
+
+        a = A()
+        a2 = A()
+        assert a.m is a.m
+        assert id(a.m) == id(a.m)
+        assert a.m is not a.n
+        assert id(a.m) != id(a.n)
+        assert a.m is not a2.m
+        assert id(a.m) != id(a2.m)
+
+        assert A.m is A.m
+        assert id(A.m) == id(A.m)
+        assert A.m is not A.n
+        assert id(A.m) != id(A.n)
+        assert A.m is not B.m
+        assert id(A.m) != id(B.m)
+
 
 class TestMethod:
     def setup_method(self, method):
diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -79,6 +79,7 @@
 W_Super.typedef = TypeDef(
     'super',
     __new__          = interp2app(descr_new_super),
+    __thisclass__    = interp_attrproperty_w("w_starttype", W_Super),
     __getattribute__ = interp2app(W_Super.getattribute),
     __get__          = interp2app(W_Super.get),
     __doc__          =     """super(type) -> unbound super object
diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -214,7 +214,7 @@
         c = C()
         assert C.goo(1) == (C, 1)
         assert c.goo(1) == (C, 1)
-        
+
         assert c.foo(1) == (c, 1)
         class D(C):
             pass
@@ -238,6 +238,17 @@
         meth = classmethod(1).__get__(1)
         raises(TypeError, meth)
 
+    def test_super_thisclass(self):
+        class A(object):
+            pass
+
+        assert super(A, A()).__thisclass__ is A
+
+        class B(A):
+            pass
+
+        assert super(B, B()).__thisclass__ is B
+        assert super(A, B()).__thisclass__ is A
 
     def test_property_docstring(self):
         assert property.__doc__.startswith('property')
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -12,6 +12,7 @@
 
 class defaultdict(dict):
     __slots__ = ['default_factory']
+    __module__ = 'collections'
 
     def __init__(self, *args, **kwds):
         if len(args) > 0:
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -14,6 +14,12 @@
         d[5].append(44)
         assert l == [42, 43] and l2 == [44]
 
+    def test_module(self):
+        from _collections import defaultdict
+        assert repr(defaultdict) in (
+            "<class 'collections.defaultdict'>",   # on PyPy
+            "<type 'collections.defaultdict'>")    # on CPython
+
     def test_keyerror_without_factory(self):
         from _collections import defaultdict
         for d1 in [defaultdict(), defaultdict(None)]:
diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py
--- a/pypy/module/_sre/interp_sre.py
+++ b/pypy/module/_sre/interp_sre.py
@@ -7,6 +7,7 @@
 from pypy.interpreter.error import OperationError
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import jit
+from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
 
 # ____________________________________________________________
 #
@@ -36,6 +37,8 @@
     if 0 <= start <= end:
         if isinstance(ctx, rsre_core.BufMatchContext):
             return space.wrap(ctx._buffer.getslice(start, end, 1, end-start))
+        if isinstance(ctx, rsre_core.StrMatchContext):
+            return space.wrap(ctx._string[start:end])
         elif isinstance(ctx, rsre_core.UnicodeMatchContext):
             return space.wrap(ctx._unicodestr[start:end])
         else:
@@ -98,8 +101,8 @@
                              space.wrap("cannot copy this pattern object"))
 
     def make_ctx(self, w_string, pos=0, endpos=sys.maxint):
-        """Make a BufMatchContext or a UnicodeMatchContext for searching
-        in the given w_string object."""
+        """Make a StrMatchContext, BufMatchContext or a UnicodeMatchContext for
+        searching in the given w_string object."""
         space = self.space
         if pos < 0:
             pos = 0
@@ -113,6 +116,14 @@
                 endpos = len(unicodestr)
             return rsre_core.UnicodeMatchContext(self.code, unicodestr,
                                                  pos, endpos, self.flags)
+        elif space.isinstance_w(w_string, space.w_str):
+            str = space.str_w(w_string)
+            if pos > len(str):
+                pos = len(str)
+            if endpos > len(str):
+                endpos = len(str)
+            return rsre_core.StrMatchContext(self.code, str,
+                                             pos, endpos, self.flags)
         else:
             buf = space.readbuf_w(w_string)
             size = buf.getlength()
@@ -216,6 +227,11 @@
 
     def subx(self, w_ptemplate, w_string, count):
         space = self.space
+        # use a (much faster) string/unicode builder if w_ptemplate and
+        # w_string are both string or both unicode objects, and if w_ptemplate
+        # is a literal
+        use_builder = False
+        filter_as_unicode = filter_as_string = None
         if space.is_true(space.callable(w_ptemplate)):
             w_filter = w_ptemplate
             filter_is_callable = True
@@ -223,6 +239,8 @@
             if space.isinstance_w(w_ptemplate, space.w_unicode):
                 filter_as_unicode = space.unicode_w(w_ptemplate)
                 literal = u'\\' not in filter_as_unicode
+                use_builder = (
+                    space.isinstance_w(w_string, space.w_unicode) and literal)
             else:
                 try:
                     filter_as_string = space.str_w(w_ptemplate)
@@ -232,6 +250,8 @@
                     literal = False
                 else:
                     literal = '\\' not in filter_as_string
+                    use_builder = (
+                        space.isinstance_w(w_string, space.w_str) and literal)
             if literal:
                 w_filter = w_ptemplate
                 filter_is_callable = False
@@ -242,19 +262,44 @@
                                              space.wrap(self), w_ptemplate)
                 filter_is_callable = space.is_true(space.callable(w_filter))
         #
+        # XXX this is a bit of a mess, but it improves performance a lot
         ctx = self.make_ctx(w_string)
-        sublist_w = []
+        sublist_w = strbuilder = unicodebuilder = None
+        if use_builder:
+            if filter_as_unicode is not None:
+                unicodebuilder = UnicodeBuilder(ctx.end)
+            else:
+                assert filter_as_string is not None
+                strbuilder = StringBuilder(ctx.end)
+        else:
+            sublist_w = []
         n = last_pos = 0
         while not count or n < count:
+            sub_jitdriver.jit_merge_point(
+                self=self,
+                use_builder=use_builder,
+                filter_is_callable=filter_is_callable,
+                filter_type=type(w_filter),
+                ctx=ctx,
+                w_filter=w_filter,
+                strbuilder=strbuilder,
+                unicodebuilder=unicodebuilder,
+                filter_as_string=filter_as_string,
+                filter_as_unicode=filter_as_unicode,
+                count=count,
+                w_string=w_string,
+                n=n, last_pos=last_pos, sublist_w=sublist_w
+                )
+            space = self.space
             if not searchcontext(space, ctx):
                 break
             if last_pos < ctx.match_start:
-                sublist_w.append(slice_w(space, ctx, last_pos,
-                                         ctx.match_start, space.w_None))
+                _sub_append_slice(
+                    ctx, space, use_builder, sublist_w,
+                    strbuilder, unicodebuilder, last_pos, ctx.match_start)
             start = ctx.match_end
             if start == ctx.match_start:
                 start += 1
-            nextctx = ctx.fresh_copy(start)
             if not (last_pos == ctx.match_start
                              == ctx.match_end and n > 0):
                 # the above ignores empty matches on latest position
@@ -262,28 +307,71 @@
                     w_match = self.getmatch(ctx, True)
                     w_piece = space.call_function(w_filter, w_match)
                     if not space.is_w(w_piece, space.w_None):
+                        assert strbuilder is None and unicodebuilder is None
+                        assert not use_builder
                         sublist_w.append(w_piece)
                 else:
-                    sublist_w.append(w_filter)
+                    if use_builder:
+                        if strbuilder is not None:
+                            assert filter_as_string is not None
+                            strbuilder.append(filter_as_string)
+                        else:
+                            assert unicodebuilder is not None
+                            assert filter_as_unicode is not None
+                            unicodebuilder.append(filter_as_unicode)
+                    else:
+                        sublist_w.append(w_filter)
                 last_pos = ctx.match_end
                 n += 1
             elif last_pos >= ctx.end:
                 break    # empty match at the end: finished
-            ctx = nextctx
+            ctx.reset(start)
 
         if last_pos < ctx.end:
-            sublist_w.append(slice_w(space, ctx, last_pos, ctx.end,
-                                     space.w_None))
+            _sub_append_slice(ctx, space, use_builder, sublist_w,
+                              strbuilder, unicodebuilder, last_pos, ctx.end)
+        if use_builder:
+            if strbuilder is not None:
+                return space.wrap(strbuilder.build()), n
+            else:
+                assert unicodebuilder is not None
+                return space.wrap(unicodebuilder.build()), n
+        else:
+            if space.isinstance_w(w_string, space.w_unicode):
+                w_emptystr = space.wrap(u'')
+            else:
+                w_emptystr = space.wrap('')
+            w_item = space.call_method(w_emptystr, 'join',
+                                       space.newlist(sublist_w))
+            return w_item, n
 
-        if space.isinstance_w(w_string, space.w_unicode):
-            w_emptystr = space.wrap(u'')
-        else:
-            w_emptystr = space.wrap('')
-        w_item = space.call_method(w_emptystr, 'join',
-                                   space.newlist(sublist_w))
-        return w_item, n
+sub_jitdriver = jit.JitDriver(
+    reds="""count n last_pos
+            ctx w_filter
+            strbuilder unicodebuilder
+            filter_as_string
+            filter_as_unicode
+            w_string sublist_w
+            self""".split(),
+    greens=["filter_is_callable", "use_builder", "filter_type", "ctx.pattern"])
 
 
+def _sub_append_slice(ctx, space, use_builder, sublist_w,
+                      strbuilder, unicodebuilder, start, end):
+    if use_builder:
+        if isinstance(ctx, rsre_core.BufMatchContext):
+            assert strbuilder is not None
+            return strbuilder.append(ctx._buffer.getslice(start, end, 1, end-start))
+        if isinstance(ctx, rsre_core.StrMatchContext):
+            assert strbuilder is not None
+            return strbuilder.append_slice(ctx._string, start, end)
+        elif isinstance(ctx, rsre_core.UnicodeMatchContext):
+            assert unicodebuilder is not None
+            return unicodebuilder.append_slice(ctx._unicodestr, start, end)
+        assert 0, "unreachable"
+    else:
+        sublist_w.append(slice_w(space, ctx, start, end, space.w_None))
+
 @unwrap_spec(flags=int, groups=int, w_groupindex=WrappedDefault(None),
              w_indexgroup=WrappedDefault(None))
 def SRE_Pattern__new__(space, w_subtype, w_pattern, flags, w_code,
@@ -482,6 +570,8 @@
         ctx = self.ctx
         if isinstance(ctx, rsre_core.BufMatchContext):
             return space.wrap(ctx._buffer.as_str())
+        elif isinstance(ctx, rsre_core.StrMatchContext):
+            return space.wrap(ctx._string)
         elif isinstance(ctx, rsre_core.UnicodeMatchContext):
             return space.wrap(ctx._unicodestr)
         else:
diff --git a/pypy/module/micronumpy/appbridge.py b/pypy/module/micronumpy/appbridge.py
--- a/pypy/module/micronumpy/appbridge.py
+++ b/pypy/module/micronumpy/appbridge.py
@@ -9,6 +9,7 @@
     w_array_repr = None
     w_array_str = None
     w__usefields = None
+    w_partition = None
 
     def __init__(self, space):
         pass
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -557,8 +557,12 @@
             return self.get_scalar_value().item(space)
         l_w = []
         for i in range(self.get_shape()[0]):
-            l_w.append(space.call_method(self.descr_getitem(space,
-                                         space.wrap(i)), "tolist"))
+            item_w = self.descr_getitem(space, space.wrap(i))
+            if (isinstance(item_w, W_NDimArray) or 
+                    isinstance(item_w, boxes.W_GenericBox)):
+                l_w.append(space.call_method(item_w, "tolist"))
+            else:
+                l_w.append(item_w)
         return space.newlist(l_w)
 
     def descr_ravel(self, space, w_order=None):
@@ -934,6 +938,10 @@
             return
         return self.implementation.sort(space, w_axis, w_order)
 
+    def descr_partition(self, space, __args__):
+        return get_appbridge_cache(space).call_method(
+            space, 'numpy.core._partition_use', 'partition', __args__.prepend(self))
+
     def descr_squeeze(self, space, w_axis=None):
         cur_shape = self.get_shape()
         if not space.is_none(w_axis):
@@ -1658,6 +1666,7 @@
 
     argsort  = interp2app(W_NDimArray.descr_argsort),
     sort  = interp2app(W_NDimArray.descr_sort),
+    partition  = interp2app(W_NDimArray.descr_partition),
     astype   = interp2app(W_NDimArray.descr_astype),
     base     = GetSetProperty(W_NDimArray.descr_get_base),
     byteswap = interp2app(W_NDimArray.descr_byteswap),
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -1936,6 +1936,22 @@
         a = array([[1, 2], [3, 4]])
         assert (a + a).tolist() == [[2, 4], [6, 8]]
 
+    def test_tolist_object(self):
+        from numpy import array
+        a = array([0], dtype=object)
+        assert a.tolist() == [0]
+
+    def test_tolist_object_slice(self):
+        from numpy import array
+        list_expected = [slice(0, 1), 0]
+        a = array(list_expected, dtype=object)
+        assert a.tolist() == list_expected
+
+    def test_tolist_object_slice_2d(self):
+        from numpy import array
+        a = array([(slice(0, 1), 1), (0, 1)], dtype=object)
+        assert a.tolist() == [[slice(0, 1, None), 1], [0, 1]]
+
     def test_tolist_slice(self):
         from numpy import array
         a = array([[17.1, 27.2], [40.3, 50.3]])
diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -266,11 +266,12 @@
             return None
         from rpython.rlib.longlong2float import float2longlong
         from pypy.objspace.std.util import IDTAG_COMPLEX as tag
+        from pypy.objspace.std.util import IDTAG_SHIFT
         real = space.float_w(space.getattr(self, space.wrap("real")))
         imag = space.float_w(space.getattr(self, space.wrap("imag")))
         real_b = rbigint.fromrarith_int(float2longlong(real))
         imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag)))
-        val = real_b.lshift(64).or_(imag_b).lshift(3).int_or_(tag)
+        val = real_b.lshift(64).or_(imag_b).lshift(IDTAG_SHIFT).int_or_(tag)
         return space.newlong_from_rbigint(val)
 
     def int(self, space):
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -181,9 +181,10 @@
             return None
         from rpython.rlib.longlong2float import float2longlong
         from pypy.objspace.std.util import IDTAG_FLOAT as tag
+        from pypy.objspace.std.util import IDTAG_SHIFT
         val = float2longlong(space.float_w(self))
         b = rbigint.fromrarith_int(val)
-        b = b.lshift(3).int_or_(tag)
+        b = b.lshift(IDTAG_SHIFT).int_or_(tag)
         return space.newlong_from_rbigint(b)
 
     def __repr__(self):
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -24,7 +24,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.objspace.std import newformat
 from pypy.objspace.std.util import (
-    BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, wrap_parsestringerror)
+    BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, IDTAG_SHIFT, wrap_parsestringerror)
 
 SENTINEL = object()
 
@@ -46,7 +46,7 @@
         if self.user_overridden_class:
             return None
         b = space.bigint_w(self)
-        b = b.lshift(3).int_or_(IDTAG_INT)
+        b = b.lshift(IDTAG_SHIFT).int_or_(IDTAG_INT)
         return space.newlong_from_rbigint(b)
 
     def int(self, space):
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -16,7 +16,7 @@
 from pypy.objspace.std import newformat
 from pypy.objspace.std.intobject import W_AbstractIntObject
 from pypy.objspace.std.util import (
-    BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, wrap_parsestringerror)
+    BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, IDTAG_SHIFT, wrap_parsestringerror)
 
 
 def delegate_other(func):
@@ -45,7 +45,7 @@
         if self.user_overridden_class:
             return None
         b = space.bigint_w(self)
-        b = b.lshift(3).int_or_(IDTAG_LONG)
+        b = b.lshift(IDTAG_SHIFT).int_or_(IDTAG_LONG)
         return space.newlong_from_rbigint(b)
 
     def unwrap(self, space):
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -172,15 +172,15 @@
     def test_id_on_primitives(self):
         if self.cpython_apptest:
             skip("cpython behaves differently")
-        assert id(1) == (1 << 3) + 1
-        assert id(1l) == (1 << 3) + 3
+        assert id(1) == (1 << 4) + 1
+        assert id(1l) == (1 << 4) + 3
         class myint(int):
             pass
         assert id(myint(1)) != id(1)
 
         assert id(1.0) & 7 == 5
         assert id(-0.0) != id(0.0)
-        assert hex(id(2.0)) == '0x20000000000000005L'
+        assert hex(id(2.0)) == '0x40000000000000005L'
         assert id(0.0) == 5
 
     def test_id_on_strs(self):
diff --git a/pypy/objspace/std/util.py b/pypy/objspace/std/util.py
--- a/pypy/objspace/std/util.py
+++ b/pypy/objspace/std/util.py
@@ -2,11 +2,13 @@
 
 from pypy.interpreter.error import OperationError, oefmt
 
+IDTAG_SHIFT   = 4
 
 IDTAG_INT     = 1
 IDTAG_LONG    = 3
 IDTAG_FLOAT   = 5
 IDTAG_COMPLEX = 7
+IDTAG_METHOD  = 9
 
 CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=')
 BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>',
diff --git a/pypy/tool/release/force-builds.py b/pypy/tool/release/force-builds.py
--- a/pypy/tool/release/force-builds.py
+++ b/pypy/tool/release/force-builds.py
@@ -9,7 +9,7 @@
 modified by PyPy team
 """
 
-import os, sys, urllib
+import os, sys, urllib, subprocess
 
 from twisted.internet import reactor, defer
 from twisted.python import log
@@ -83,4 +83,9 @@
     (options, args) = parser.parse_args()
     if  not options.branch:
         parser.error("branch option required")
+    try:
+        subprocess.check_call(['hg','id','-r', options.branch])
+    except subprocess.CalledProcessError:
+        print 'branch',  options.branch, 'could not be found in local repository'
+        sys.exit(-1) 
     main(options.branch, options.server, user=options.user)
diff --git a/rpython/doc/translation.rst b/rpython/doc/translation.rst
--- a/rpython/doc/translation.rst
+++ b/rpython/doc/translation.rst
@@ -33,7 +33,7 @@
 The RPython translation toolchain never sees Python source code or syntax
 trees, but rather starts with the *code objects* that define the
 behaviour of the function objects one gives it as input.  The
-`bytecode evaluator`_ and the :ref:`flow graph builder<flow-graphs>` work through these
+:ref:`flow graph builder<flow-graphs>` works through these
 code objects using `abstract interpretation`_ to produce a control
 flow graph (one per function): yet another representation of the
 source program, but one which is suitable for applying type inference
@@ -85,7 +85,6 @@
 
 
 .. _PDF color version: _static/translation.pdf
-.. _bytecode evaluator: interpreter.html
 .. _abstract interpretation: http://en.wikipedia.org/wiki/Abstract_interpretation
 
 


More information about the pypy-commit mailing list