Author: Manuel Jacob <m...@manueljacob.de>
Branch: improve-docs
Changeset: r74027:0019c149a635
Date: 2014-10-21 11:59 +0200
http://bitbucket.org/pypy/pypy/changeset/0019c149a635/

Log:    hg merge default

diff too long, truncating to 2000 out of 17847 lines

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -3,8 +3,8 @@
 
 Except when otherwise stated (look for LICENSE files in directories or
 information at the beginning of each file) all software and documentation in
-the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', 'demo', and 'lib_pypy'
-directories is licensed as follows: 
+the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', 'demo', 'lib_pypy',
+'py', and '_pytest' directories is licensed as follows: 
 
     The MIT License
 
@@ -367,3 +367,43 @@
 Detailed license information is contained in the NOTICE file in the
 directory.
 
+
+Licenses and Acknowledgements for Incorporated Software
+=======================================================
+
+This section is an incomplete, but growing list of licenses and
+acknowledgements for third-party software incorporated in the PyPy
+distribution.
+
+License for 'Tcl/Tk'
+--------------------
+
+This copy of PyPy contains library code that may, when used, result in
+the Tcl/Tk library to be loaded.  PyPy also includes code that may be
+regarded as being a copy of some parts of the Tcl/Tk header files.
+You may see a copy of the License for Tcl/Tk in the file
+`lib_pypy/_tkinter/license.terms` included here.
+
+License for 'bzip2'
+-------------------
+
+This copy of PyPy may be linked (dynamically or statically) with the
+bzip2 library.  You may see a copy of the License for bzip2/libbzip2 at
+
+    http://www.bzip.org/1.0.5/bzip2-manual-1.0.5.html
+
+License for 'openssl'
+---------------------
+
+This copy of PyPy may be linked (dynamically or statically) with the
+openssl library.  You may see a copy of the License for OpenSSL at
+
+    https://www.openssl.org/source/license.html
+
+License for 'gdbm'
+------------------
+
+The gdbm module includes code from gdbm.h, which is distributed under
+the terms of the GPL license version 2 or any later version.  Thus the
+gdbm module, provided in the file lib_pypy/gdbm.py, is redistributed
+under the terms of the GPL license as well.
diff --git a/lib-python/2.7/test/test_select.py 
b/lib-python/2.7/test/test_select.py
--- a/lib-python/2.7/test/test_select.py
+++ b/lib-python/2.7/test/test_select.py
@@ -57,7 +57,17 @@
                 del a[-1]
                 return sys.__stdout__.fileno()
         a[:] = [F()] * 10
-        self.assertEqual(select.select([], a, []), ([], a[:5], []))
+        result = select.select([], a, [])
+        # CPython: 'a' ends up with 5 items, because each fileno()
+        # removes an item and at the middle the iteration stops.
+        # PyPy: 'a' ends up empty, because the iteration is done on
+        # a copy of the original list: fileno() is called 10 times.
+        if test_support.check_impl_detail(cpython=True):
+            self.assertEqual(len(result[1]), 5)
+            self.assertEqual(len(a), 5)
+        if test_support.check_impl_detail(pypy=True):
+            self.assertEqual(len(result[1]), 10)
+            self.assertEqual(len(a), 0)
 
 def test_main():
     test_support.run_unittest(SelectTestCase)
diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
--- a/lib_pypy/_curses.py
+++ b/lib_pypy/_curses.py
@@ -286,6 +286,13 @@
 
 
 lib = ffi.verify("""
+#ifdef __APPLE__
+/* the following define is necessary for OS X 10.6+; without it, the
+   Apple-supplied ncurses.h sets NCURSES_OPAQUE to 1, and then Python
+   can't get at the WINDOW flags field. */
+#define NCURSES_OPAQUE 0
+#endif
+
 #include <ncurses.h>
 #include <panel.h>
 #include <term.h>
diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -1242,7 +1242,7 @@
                         (other._hour, other._minute, other._second,
                          other._microsecond))
         if myoff is None or otoff is None:
-            raise TypeError("cannot compare naive and aware times")
+            raise TypeError("can't compare offset-naive and offset-aware 
times")
         myhhmm = self._hour * 60 + self._minute - myoff
         othhmm = other._hour * 60 + other._minute - otoff
         return _cmp((myhhmm, self._second, self._microsecond),
@@ -1838,7 +1838,7 @@
                          other._hour, other._minute, other._second,
                          other._microsecond))
         if myoff is None or otoff is None:
-            raise TypeError("cannot compare naive and aware datetimes")
+            raise TypeError("can't compare offset-naive and offset-aware 
datetimes")
         # XXX What follows could be done more efficiently...
         diff = self - other     # this will take offsets into account
         if diff.days < 0:
@@ -1885,7 +1885,7 @@
         if myoff == otoff:
             return base
         if myoff is None or otoff is None:
-            raise TypeError("cannot mix naive and timezone-aware time")
+            raise TypeError("can't subtract offset-naive and offset-aware 
datetimes")
         return base + timedelta(minutes = otoff-myoff)
 
     def __hash__(self):
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -80,7 +80,7 @@
 the selection of scientific software) will also work for a build with the
 builtin backend.
 
-.. _download: http://cern.ch/wlav/reflex-2013-08-14.tar.bz2
+.. _download: http://cern.ch/wlav/reflex-2014-10-20.tar.bz2
 .. _ROOT: http://root.cern.ch/
 
 Besides Reflex, you probably need a version of `gccxml`_ installed, which is
@@ -95,8 +95,8 @@
 
 To install the standalone version of Reflex, after download::
 
-    $ tar jxf reflex-2013-08-14.tar.bz2
-    $ cd reflex-2013-08-14
+    $ tar jxf reflex-2014-10-20.tar.bz2
+    $ cd reflex-2014-10-20
     $ ./build/autogen
     $ ./configure <usual set of options such as --prefix>
     $ make && make install
@@ -796,7 +796,7 @@
 also means that you can't actually find out whether it is in use, other than
 by running a micro-benchmark or a JIT test).
 
-.. _provided: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2
+.. _provided: http://cern.ch/wlav/reflex-2014-10-20.tar.bz2
 .. _genreflex-methptrgetter.patch: 
https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch
 
 CPython
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -38,14 +38,16 @@
     no JIT: windows, linux, os/x
     sandbox: linux, os/x
 
+* repackage and upload source tar.bz2 to bitbucket and to cobra, as some 
packagers 
+  prefer a clearly labeled source package
 * write release announcement pypy/doc/release-x.y(.z).txt
   the release announcement should contain a direct link to the download page
 * update pypy.org (under extradoc/pypy.org), rebuild and commit
 
 * post announcement on morepypy.blogspot.com
-* send announcements to pypy-dev, python-list,
+* send announcements to twitter.com, pypy-dev, python-list,
   python-announce, python-dev ...
 
 * add a tag on the pypy/jitviewer repo that corresponds to pypy release
 * add a tag on the codespeed web site that corresponds to pypy release
-
+* revise versioning at https://readthedocs.org/projects/pypy
diff --git a/pypy/doc/release-2.4.0.rst b/pypy/doc/release-2.4.0.rst
--- a/pypy/doc/release-2.4.0.rst
+++ b/pypy/doc/release-2.4.0.rst
@@ -5,7 +5,7 @@
 We're pleased to announce PyPy 2.4, which contains significant performance
 enhancements and bug fixes. 
 
-You can already download the PyPy 2.4-beta1 pre-release here:
+You can download the PyPy 2.4.0 release here:
 
     http://pypy.org/download.html
 
@@ -63,6 +63,8 @@
 
 PyPy now uses Python 2.7.8 standard library.
 
+We fixed a memory leak in IO in the sandbox_ code
+
 We welcomed more than 12 new contributors, and conducted two Google
 Summer of Code projects, as well as other student projects not
 directly related to Summer of Code.
@@ -103,8 +105,9 @@
   
 * Many issues were resolved_ since the 2.3.1 release on June 8
 
-.. _`whats-new`: http://doc.pypy.org/en/latest/whatsnew-2.3.1.html
+.. _`whats-new`: http://doc.pypy.org/en/latest/whatsnew-2.4.0.html
 .. _resolved: https://bitbucket.org/pypy/pypy/issues?status=resolved
+.. _sandbox: http://doc.pypy.org/en/latest/sandbox.html   
 
 We have further improvements on the way: rpython file handling,
 numpy linalg compatibility, as well
diff --git a/pypy/doc/release-pypy3-2.4.0.rst b/pypy/doc/release-pypy3-2.4.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy3-2.4.0.rst
@@ -0,0 +1,126 @@
+=================================================
+PyPy3 2.4 - Snow White
+=================================================
+
+We're pleased to announce PyPy3 2.4, which contains significant performance
+enhancements and bug fixes.
+
+You can download the PyPy3 2.4.0 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project, and for those who donate to our three sub-projects.
+We've shown quite a bit of progress, but we're slowly running out of funds.
+Please consider donating more, or even better convince your employer to donate,
+so we can finish those projects! The three sub-projects are:
+
+* `Py3k`_ (supporting Python 3.x): This is a Python 3.2.5 compatible
+   version we call PyPy3 2.4, and we are working toward a Python 3.3
+   compatible version
+
+* `STM`_ (software transactional memory): We have released a first working 
version,
+  and continue to try out new promising paths of achieving a fast 
multithreaded Python
+
+* `NumPy`_ which requires installation of our fork of upstream numpy,
+  available `on bitbucket`_
+
+.. _`Py3k`: http://pypy.org/py3donate.html
+.. _`STM`: http://pypy.org/tmdonate2.html
+.. _`NumPy`: http://pypy.org/numpydonate.html
+.. _`on bitbucket`: https://www.bitbucket.org/pypy/numpy
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7 or 3.2.5. It's fast (`pypy 2.4 and cpython 2.7.x`_ performance
+comparison) due to its integrated tracing JIT compiler.
+
+This release supports **x86** machines on most common operating systems
+(Linux 32/64, Mac OS X 64, Windows, and OpenBSD),
+as well as newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux.
+
+While we support 32 bit python on Windows, work on the native Windows 64
+bit python is still stalling, we would welcome a volunteer
+to `handle that`_.
+
+.. _`pypy 2.4 and cpython 2.7.x`: http://speed.pypy.org
+.. _`handle that`: 
http://doc.pypy.org/en/latest/windows.html#what-is-missing-for-a-full-64-bit-translation
+
+PyPy3 Highlights
+================
+
+Issues reported with our previous release were fixed after reports from users 
on
+our new issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
+#pypy. Here is a summary of the user-facing PyPy3 specific changes:
+
+* Better Windows compatibility, e.g. the nt module functions _getfinalpathname
+  & _getfileinformation are now supported (the former is required for the
+  popular pathlib library for example)
+
+* Various fsencode PEP 383 related fixes to the posix module (readlink, uname,
+  ttyname and ctermid) and improved locale handling
+
+* Switched default binary name os POSIX distributions to 'pypy3' (which
+  symlinks to to 'pypy3.2')
+
+* Fixed a couple different crashes related to parsing Python 3 source code
+
+Further Highlights (shared w/ PyPy2)
+====================================
+
+Benchmarks improved after internal enhancements in string and
+bytearray handling, and a major rewrite of the GIL handling. This means
+that external calls are now a lot faster, especially the CFFI ones. It also
+means better performance in a lot of corner cases with handling strings or
+bytearrays. The main bugfix is handling of many socket objects in your
+program which in the long run used to "leak" memory.
+
+We fixed a memory leak in IO in the sandbox_ code
+
+We welcomed more than 12 new contributors, and conducted two Google
+Summer of Code projects, as well as other student projects not
+directly related to Summer of Code.
+
+* Reduced internal copying of bytearray operations
+
+* Tweak the internal structure of StringBuilder to speed up large string
+  handling, which becomes advantageous on large programs at the cost of 
slightly
+  slower small *benchmark* type programs.
+
+* Boost performance of thread-local variables in both unjitted and jitted code,
+  this mostly affects errno handling on linux, which makes external calls
+  faster.
+
+* Move to a mixed polling and mutex GIL model that make mutlithreaded jitted
+  code run *much* faster
+
+* Optimize errno handling in linux (x86 and x86-64 only)
+
+* Remove ctypes pythonapi and ctypes.PyDLL, which never worked on PyPy
+
+* Classes in the ast module are now distinct from structures used by
+  the compiler, which simplifies and speeds up translation of our
+  source code to the PyPy binary interpreter
+
+* Win32 now links statically to zlib, expat, bzip, and openssl-1.0.1i.
+  No more missing DLLs
+
+* Many issues were resolved_ since the 2.3.1 release in June
+
+.. _`whats-new`: http://doc.pypy.org/en/latest/whatsnew-2.4.0.html
+.. _resolved: https://bitbucket.org/pypy/pypy/issues?status=resolved
+.. _sandbox: http://doc.pypy.org/en/latest/sandbox.html
+
+We have further improvements on the way: rpython file handling,
+numpy linalg compatibility, as well
+as improved GC and many smaller improvements.
+
+Please try it out and let us know what you think. We especially welcome
+success stories, we know you are using PyPy, please tell us about it!
+
+Cheers
+
+The PyPy Team
+
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
@@ -6,3 +6,19 @@
 .. this is a revision shortly after release-2.4.x
 .. startrev: 7026746cbb1b
 
+.. branch: win32-fixes5
+Fix c code generation for msvc so empty "{ }" are avoided in unions,
+Avoid re-opening files created with NamedTemporaryFile,
+Allocate by 4-byte chunks in rffi_platform,
+Skip testing objdump if it does not exist,
+and other small adjustments in own tests
+
+.. branch: rtyper-stuff
+Small internal refactorings in the rtyper.
+
+.. branch: var-in-Some
+Store annotations on the Variable objects, rather than in a big dict.
+Introduce a new framework for double-dispatched annotation implementations.
+
+.. branch: ClassRepr
+Refactor ClassRepr and make normalizecalls independent of the rtyper.
diff --git a/pypy/doc/whatsnew-pypy3-2.4.0.rst 
b/pypy/doc/whatsnew-pypy3-2.4.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy3-2.4.0.rst
@@ -0,0 +1,6 @@
+=========================
+What's new in PyPy3 2.4.0
+=========================
+
+.. this is a revision shortly after pypy3-release-2.4.x
+.. startrev: 12b940544622
diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -251,6 +251,8 @@
             enable_translationmodules(config)
 
         config.translation.suggest(check_str_without_nul=True)
+        if sys.platform.startswith('linux'):
+            config.translation.suggest(shared=True)
 
         if config.translation.thread:
             config.objspace.usemodules.thread = True
diff --git a/pypy/interpreter/astcompiler/ast.py 
b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -22,9 +22,11 @@
 
 def get_field(space, w_node, name, optional):
     w_obj = w_node.getdictvalue(space, name)
-    if w_obj is None and not optional:
-        raise oefmt(space.w_TypeError,
+    if w_obj is None:
+        if not optional:
+            raise oefmt(space.w_TypeError,
                 "required field \"%s\" missing from %T", name, w_node)
+        w_obj = space.w_None
     return w_obj
 
 
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py 
b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -405,9 +405,11 @@
 
 def get_field(space, w_node, name, optional):
     w_obj = w_node.getdictvalue(space, name)
-    if w_obj is None and not optional:
-        raise oefmt(space.w_TypeError,
+    if w_obj is None:
+        if not optional:
+            raise oefmt(space.w_TypeError,
                 "required field \"%s\" missing from %T", name, w_node)
+        w_obj = space.w_None
     return w_obj
 
 
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -38,18 +38,15 @@
 def cpython_code_signature(code):
     "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
     argcount = code.co_argcount
+    varnames = code.co_varnames
     assert argcount >= 0     # annotator hint
-    argnames = list(code.co_varnames[:argcount])
+    argnames = list(varnames[:argcount])
     if code.co_flags & CO_VARARGS:
-        varargname = code.co_varnames[argcount]
+        varargname = varnames[argcount]
         argcount += 1
     else:
         varargname = None
-    if code.co_flags & CO_VARKEYWORDS:
-        kwargname = code.co_varnames[argcount]
-        argcount += 1
-    else:
-        kwargname = None
+    kwargname = varnames[argcount] if code.co_flags & CO_VARKEYWORDS else None
     return Signature(argnames, varargname, kwargname)
 
 
diff --git a/pypy/interpreter/pyparser/parsestring.py 
b/pypy/interpreter/pyparser/parsestring.py
--- a/pypy/interpreter/pyparser/parsestring.py
+++ b/pypy/interpreter/pyparser/parsestring.py
@@ -83,12 +83,6 @@
     v = PyString_DecodeEscape(space, substr, 'strict', enc)
     return space.wrap(v)
 
-def hexbyte(val):
-    result = "%x" % val
-    if len(result) == 1:
-        result = "0" + result
-    return result
-
 def decode_unicode_utf8(space, s, ps, q):
     # ****The Python 2.7 version, producing UTF-32 escapes****
     # String is utf8-encoded, but 'unicode_escape' expects
@@ -108,15 +102,14 @@
                 # instead.
                 lis.append("u005c")
         if ord(s[ps]) & 0x80: # XXX inefficient
-            w, ps = decode_utf8(space, s, ps, end, "utf-32-be")
-            rn = len(w)
-            assert rn % 4 == 0
-            for i in range(0, rn, 4):
-                lis.append('\\U')
-                lis.append(hexbyte(ord(w[i])))
-                lis.append(hexbyte(ord(w[i+1])))
-                lis.append(hexbyte(ord(w[i+2])))
-                lis.append(hexbyte(ord(w[i+3])))
+            w, ps = decode_utf8(space, s, ps, end)
+            for c in w:
+                # The equivalent of %08x, which is not supported by RPython.
+                # 7 zeroes are enough for the unicode range, and the
+                # result still fits in 32-bit.
+                hexa = hex(ord(c) + 0x10000000)
+                lis.append('\\U0')
+                lis.append(hexa[3:])  # Skip 0x and the leading 1
         else:
             lis.append(s[ps])
             ps += 1
@@ -136,7 +129,7 @@
             # note that the C code has a label here.
             # the logic is the same.
             if recode_encoding and ord(s[ps]) & 0x80:
-                w, ps = decode_utf8(space, s, ps, end, recode_encoding)
+                w, ps = decode_utf8_recode(space, s, ps, end, recode_encoding)
                 # Append bytes to output buffer.
                 builder.append(w)
             else:
@@ -222,14 +215,18 @@
             ch >= 'A' and ch <= 'F')
 
 
-def decode_utf8(space, s, ps, end, encoding):
+def decode_utf8(space, s, ps, end):
     assert ps >= 0
     pt = ps
     # while (s < end && *s != '\\') s++; */ /* inefficient for u".."
     while ps < end and ord(s[ps]) & 0x80:
         ps += 1
-    w_u = space.wrap(unicodehelper.decode_utf8(space, s[pt:ps]))
-    w_v = unicodehelper.encode(space, w_u, encoding)
+    u = unicodehelper.decode_utf8(space, s[pt:ps])
+    return u, ps
+
+def decode_utf8_recode(space, s, ps, end, recode_encoding):
+    u, ps = decode_utf8(space, s, ps, end)
+    w_v = unicodehelper.encode(space, space.wrap(u), recode_encoding)
     v = space.str_w(w_v)
     return v, ps
 
diff --git a/pypy/interpreter/pyparser/test/test_parsestring.py 
b/pypy/interpreter/pyparser/test/test_parsestring.py
--- a/pypy/interpreter/pyparser/test/test_parsestring.py
+++ b/pypy/interpreter/pyparser/test/test_parsestring.py
@@ -73,11 +73,11 @@
 
     def test_simple_enc_roundtrip(self):
         space = self.space
-        s = "'\x81'"
+        s = "'\x81\\t'"
         s = s.decode("koi8-u").encode("utf8")
         w_ret = parsestring.parsestr(self.space, 'koi8-u', s)
         ret = space.unwrap(w_ret)
-        assert ret == eval("# -*- coding: koi8-u -*-\n'\x81'") 
+        assert ret == eval("# -*- coding: koi8-u -*-\n'\x81\\t'") 
 
     def test_multiline_unicode_strings_with_backslash(self):
         space = self.space
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -5,6 +5,7 @@
 
 @specialize.memo()
 def decode_error_handler(space):
+    # Fast version of the "strict" errors handler.
     def raise_unicode_exception_decode(errors, encoding, msg, s,
                                        startingpos, endingpos):
         raise OperationError(space.w_UnicodeDecodeError,
@@ -17,6 +18,7 @@
 
 @specialize.memo()
 def encode_error_handler(space):
+    # Fast version of the "strict" errors handler.
     def raise_unicode_exception_encode(errors, encoding, msg, u,
                                        startingpos, endingpos):
         raise OperationError(space.w_UnicodeEncodeError,
diff --git a/pypy/module/_ast/test/test_ast.py 
b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -425,3 +425,8 @@
         str_node2 = copy.deepcopy(str_node)
         dict_res = str_node2.__dict__
         assert dict_res == {'n':2, 'lineno':2}
+
+    def test_bug_null_in_objspace_type(self):
+        import ast
+        code = ast.Expression(lineno=1, col_offset=1, 
body=ast.ListComp(lineno=1, col_offset=1, elt=ast.Call(lineno=1, col_offset=1, 
func=ast.Name(lineno=1, col_offset=1, id='str', ctx=ast.Load(lineno=1, 
col_offset=1)), args=[ast.Name(lineno=1, col_offset=1, id='x', 
ctx=ast.Load(lineno=1, col_offset=1))], keywords=[]), 
generators=[ast.comprehension(lineno=1, col_offset=1, target=ast.Name(lineno=1, 
col_offset=1, id='x', ctx=ast.Store(lineno=1, col_offset=1)), 
iter=ast.List(lineno=1, col_offset=1, elts=[ast.Num(lineno=1, col_offset=1, 
n=23)], ctx=ast.Load(lineno=1, col_offset=1, )), ifs=[])]))
+        compile(code, '<template>', 'eval')
diff --git a/pypy/module/_cffi_backend/ctypefunc.py 
b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -8,6 +8,7 @@
 from rpython.rlib.jit_libffi import (CIF_DESCRIPTION, CIF_DESCRIPTION_P,
     FFI_TYPE, FFI_TYPE_P, FFI_TYPE_PP, SIZE_OF_FFI_ARG)
 from rpython.rlib.objectmodel import we_are_translated, instantiate
+from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 
 from pypy.interpreter.error import OperationError, oefmt
@@ -160,6 +161,7 @@
                         raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
                         lltype.free(raw_cdata, flavor='raw')
             lltype.free(buffer, flavor='raw')
+            keepalive_until_here(args_w)
         return w_res
 
 def get_mustfree_flag(data):
diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py
--- a/pypy/module/_socket/__init__.py
+++ b/pypy/module/_socket/__init__.py
@@ -17,8 +17,6 @@
     def startup(self, space):
         from rpython.rlib.rsocket import rsocket_startup
         rsocket_startup()
-        from pypy.module._socket.interp_func import State
-        space.fromcache(State).startup(space)
 
     def buildloaders(cls):
         from rpython.rlib import rsocket
diff --git a/pypy/module/_socket/interp_func.py 
b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -1,5 +1,6 @@
 from rpython.rlib import rsocket
 from rpython.rlib.rsocket import SocketError, INVALID_SOCKET
+from rpython.rlib.rarithmetic import intmask
 
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
@@ -46,9 +47,8 @@
     Return the true host name, a list of aliases, and a list of IP addresses,
     for a host.  The host argument is a string giving a host name or IP number.
     """
-    lock = space.fromcache(State).netdb_lock
     try:
-        res = rsocket.gethostbyname_ex(host, lock)
+        res = rsocket.gethostbyname_ex(host)
     except SocketError, e:
         raise converted_error(space, e)
     return common_wrapgethost(space, res)
@@ -60,9 +60,8 @@
     Return the true host name, a list of aliases, and a list of IP addresses,
     for a host.  The host argument is a string giving a host name or IP number.
     """
-    lock = space.fromcache(State).netdb_lock
     try:
-        res = rsocket.gethostbyaddr(host, lock)
+        res = rsocket.gethostbyaddr(host)
     except SocketError, e:
         raise converted_error(space, e)
     return common_wrapgethost(space, res)
@@ -174,7 +173,7 @@
 
     Convert a 16-bit integer from network to host byte order.
     """
-    return space.wrap(rsocket.ntohs(x))
+    return space.wrap(rsocket.ntohs(intmask(x)))
 
 @unwrap_spec(x="c_uint")
 def ntohl(space, x):
@@ -190,7 +189,7 @@
 
     Convert a 16-bit integer from host to network byte order.
     """
-    return space.wrap(rsocket.htons(x))
+    return space.wrap(rsocket.htons(intmask(x)))
 
 @unwrap_spec(x="c_uint")
 def htonl(space, x):
@@ -319,10 +318,3 @@
             raise OperationError(space.w_ValueError,
                                  space.wrap('Timeout value out of range'))
     rsocket.setdefaulttimeout(timeout)
-
-class State(object):
-    def __init__(self, space):
-        self.netdb_lock = None
-
-    def startup(self, space):
-        self.netdb_lock = space.allocate_lock()
diff --git a/pypy/module/_socket/interp_socket.py 
b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -109,10 +109,11 @@
 
 # XXX Hack to seperate rpython and pypy
 def make_ushort_port(space, port):
+    assert isinstance(port, int)
     if port < 0 or port > 0xffff:
         raise OperationError(space.w_OverflowError, space.wrap(
             "port must be 0-65535."))
-    return rffi.cast(rffi.USHORT, port)
+    return port
 
 def make_unsigned_flowinfo(space, flowinfo):
     if flowinfo < 0 or flowinfo > 0xfffff:
@@ -401,8 +402,10 @@
         The value argument can either be an integer or a string.
         """
         try:
-            optval = space.int_w(w_optval)
-        except:
+            optval = space.c_int_w(w_optval)
+        except OperationError, e:
+            if e.async(space):
+                raise
             optval = space.str_w(w_optval)
             try:
                 self.sock.setsockopt(level, optname, optval)
diff --git a/pypy/module/_socket/test/test_sock_app.py 
b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -498,6 +498,13 @@
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
         assert reuse == 0
+        #
+        raises(TypeError, s.setsockopt, socket.SOL_SOCKET,
+                          socket.SO_REUSEADDR, 2 ** 31)
+        raises(TypeError, s.setsockopt, socket.SOL_SOCKET,
+                          socket.SO_REUSEADDR, 2 ** 32 + 1)
+        assert s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 0
+        #
         s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
         assert reuse != 0
diff --git a/pypy/module/_winreg/interp_winreg.py 
b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -266,10 +266,16 @@
     buf = None
 
     if typ == rwinreg.REG_DWORD:
-        if space.isinstance_w(w_value, space.w_int):
+        if space.is_none(w_value) or (
+                space.isinstance_w(w_value, space.w_int) or
+                space.isinstance_w(w_value, space.w_long)):
+            if space.is_none(w_value):
+                value = r_uint(0)
+            else:
+                value = space.c_uint_w(w_value)
             buflen = rffi.sizeof(rwin32.DWORD)
             buf1 = lltype.malloc(rffi.CArray(rwin32.DWORD), 1, flavor='raw')
-            buf1[0] = space.uint_w(w_value)
+            buf1[0] = value
             buf = rffi.cast(rffi.CCHARP, buf1)
 
     elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ:
diff --git a/pypy/module/_winreg/test/test_winreg.py 
b/pypy/module/_winreg/test/test_winreg.py
--- a/pypy/module/_winreg/test/test_winreg.py
+++ b/pypy/module/_winreg/test/test_winreg.py
@@ -40,7 +40,7 @@
         cls.w_tmpfilename = space.wrap(str(udir.join('winreg-temp')))
 
         test_data = [
-            ("Int Value", 45, _winreg.REG_DWORD),
+            ("Int Value", 0xFEDCBA98, _winreg.REG_DWORD),
             ("Str Value", "A string Value", _winreg.REG_SZ),
             ("Unicode Value", u"A unicode Value", _winreg.REG_SZ),
             ("Str Expand", "The path is %path%", _winreg.REG_EXPAND_SZ),
@@ -137,9 +137,11 @@
             assert 0, "Did not raise"
 
     def test_SetValueEx(self):
-        from _winreg import CreateKey, SetValueEx, REG_BINARY
+        from _winreg import CreateKey, SetValueEx, REG_BINARY, REG_DWORD
         key = CreateKey(self.root_key, self.test_key_name)
         sub_key = CreateKey(key, "sub_key")
+        SetValueEx(sub_key, 'Int Value', 0, REG_DWORD, None)
+        SetValueEx(sub_key, 'Int Value', 0, REG_DWORD, 45)
         for name, value, type in self.test_data:
             SetValueEx(sub_key, name, 0, type, value)
         exc = raises(TypeError, SetValueEx, sub_key, 'test_name', None,
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -116,6 +116,8 @@
     validate_fd(fileno(fp))
     return _feof(fp)
 
+def is_valid_fp(fp):
+    return is_valid_fd(fileno(fp))
 
 constant_names = """
 Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py
--- a/pypy/module/cpyext/eval.py
+++ b/pypy/module/cpyext/eval.py
@@ -3,7 +3,7 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
     cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP,
-    cpython_struct)
+    cpython_struct, is_valid_fp)
 from pypy.module.cpyext.pyobject import PyObject, borrow_from
 from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno
 from pypy.module.cpyext.funcobject import PyCodeObject
@@ -154,6 +154,10 @@
     source = ""
     filename = rffi.charp2str(filename)
     buf = lltype.malloc(rffi.CCHARP.TO, BUF_SIZE, flavor='raw')
+    if not is_valid_fp(fp):
+        lltype.free(buf, flavor='raw')
+        PyErr_SetFromErrno(space, space.w_IOError)
+        return None
     try:
         while True:
             count = fread(buf, 1, BUF_SIZE, fp)
diff --git a/pypy/module/cpyext/test/test_eval.py 
b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -89,12 +89,12 @@
                 rffi.free_charp(buf)
 
         assert 0 == run("42 * 43")
-        
+
         assert -1 == run("4..3 * 43")
-        
+
         assert api.PyErr_Occurred()
         api.PyErr_Clear()
-        
+
     def test_run_string(self, space, api):
         def run(code, start, w_globals, w_locals):
             buf = rffi.str2charp(code)
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
@@ -20,6 +20,7 @@
         'concatenate': 'arrayops.concatenate',
         'count_nonzero': 'arrayops.count_nonzero',
         'dot': 'arrayops.dot',
+        'result_type': 'arrayops.result_type',
         'where': 'arrayops.where',
 
         'set_string_function': 'appbridge.set_string_function',
diff --git a/pypy/module/micronumpy/app_numpy.py 
b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -16,9 +16,9 @@
         dtype = test.dtype
     length = math.ceil((float(stop) - start) / step)
     length = int(length)
-    arr = _numpypy.multiarray.zeros(length, dtype=dtype)
+    arr = _numpypy.multiarray.empty(length, dtype=dtype)
     i = start
-    for j in range(arr.size):
+    for j in xrange(arr.size):
         arr[j] = i
         i += step
     return arr
diff --git a/pypy/module/micronumpy/arrayops.py 
b/pypy/module/micronumpy/arrayops.py
--- a/pypy/module/micronumpy/arrayops.py
+++ b/pypy/module/micronumpy/arrayops.py
@@ -1,3 +1,4 @@
+from rpython.rlib import jit
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.module.micronumpy import loop, descriptor, ufuncs, support, \
@@ -6,6 +7,7 @@
 from pypy.module.micronumpy.converters import clipmode_converter
 from pypy.module.micronumpy.strides import Chunk, Chunks, shape_agreement, \
     shape_agreement_multiple
+from .boxes import W_GenericBox
 
 
 def where(space, w_arr, w_x=None, w_y=None):
@@ -283,3 +285,28 @@
     else:
         loop.diagonal_array(space, arr, out, offset, axis1, axis2, shape)
     return out
+
+
+@jit.unroll_safe
+def result_type(space, __args__):
+    args_w, kw_w = __args__.unpack()
+    if kw_w:
+        raise oefmt(space.w_TypeError, "result_type() takes no keyword 
arguments")
+    if not args_w:
+        raise oefmt(space.w_ValueError, "at least one array or dtype is 
required")
+    result = None
+    for w_arg in args_w:
+        if isinstance(w_arg, W_NDimArray):
+            dtype = w_arg.get_dtype()
+        elif isinstance(w_arg, W_GenericBox) or (
+                space.isinstance_w(w_arg, space.w_int) or
+                space.isinstance_w(w_arg, space.w_float) or
+                space.isinstance_w(w_arg, space.w_complex) or
+                space.isinstance_w(w_arg, space.w_long) or
+                space.isinstance_w(w_arg, space.w_bool)):
+            dtype = ufuncs.find_dtype_for_scalar(space, w_arg)
+        else:
+            dtype = space.interp_w(descriptor.W_Dtype,
+                space.call_function(space.gettypefor(descriptor.W_Dtype), 
w_arg))
+        result = ufuncs.find_binop_result_dtype(space, result, dtype)
+    return result
diff --git a/pypy/module/micronumpy/compile.py 
b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -36,7 +36,7 @@
 SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
                         "unegative", "flat", "tostring","count_nonzero",
                         "argsort"]
-TWO_ARG_FUNCTIONS = ["dot", 'take']
+TWO_ARG_FUNCTIONS = ["dot", 'take', 'searchsorted']
 TWO_ARG_FUNCTIONS_OR_NONE = ['view', 'astype']
 THREE_ARG_FUNCTIONS = ['where']
 
@@ -109,6 +109,9 @@
             if stop < 0:
                 stop += size + 1
             if step < 0:
+                start, stop = stop, start
+                start -= 1
+                stop -= 1
                 lgt = (stop - start + 1) / step + 1
             else:
                 lgt = (stop - start - 1) / step + 1
@@ -475,7 +478,6 @@
 
 class SliceConstant(Node):
     def __init__(self, start, stop, step):
-        # no negative support for now
         self.start = start
         self.stop = stop
         self.step = step
@@ -582,6 +584,9 @@
                 w_res = arr.descr_dot(interp.space, arg)
             elif self.name == 'take':
                 w_res = arr.descr_take(interp.space, arg)
+            elif self.name == "searchsorted":
+                w_res = arr.descr_searchsorted(interp.space, arg,
+                                               interp.space.wrap('left'))
             else:
                 assert False # unreachable code
         elif self.name in THREE_ARG_FUNCTIONS:
diff --git a/pypy/module/micronumpy/concrete.py 
b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -19,6 +19,7 @@
                           'strides[*]', 'backstrides[*]', 'order']
     start = 0
     parent = None
+    flags = 0
 
     # JIT hints that length of all those arrays is a constant
 
@@ -357,11 +358,11 @@
         self.dtype = dtype
 
     def argsort(self, space, w_axis):
-        from pypy.module.micronumpy.sort import argsort_array
+        from .selection import argsort_array
         return argsort_array(self, space, w_axis)
 
     def sort(self, space, w_axis, w_order):
-        from pypy.module.micronumpy.sort import sort_array
+        from .selection import sort_array
         return sort_array(self, space, w_axis, w_order)
 
     def base(self):
diff --git a/pypy/module/micronumpy/constants.py 
b/pypy/module/micronumpy/constants.py
--- a/pypy/module/micronumpy/constants.py
+++ b/pypy/module/micronumpy/constants.py
@@ -65,6 +65,9 @@
 FLOATINGLTR = 'f'
 COMPLEXLTR = 'c'
 
+SEARCHLEFT = 0
+SEARCHRIGHT = 1
+
 ANYORDER = -1
 CORDER = 0
 FORTRANORDER = 1
@@ -74,6 +77,9 @@
 WRAP = 1
 RAISE = 2
 
+ARRAY_C_CONTIGUOUS = 0x0001
+ARRAY_F_CONTIGUOUS = 0x0002
+
 LITTLE = '<'
 BIG = '>'
 NATIVE = '='
diff --git a/pypy/module/micronumpy/converters.py 
b/pypy/module/micronumpy/converters.py
--- a/pypy/module/micronumpy/converters.py
+++ b/pypy/module/micronumpy/converters.py
@@ -1,4 +1,4 @@
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, oefmt
 from pypy.module.micronumpy import constants as NPY
 
 
@@ -41,6 +41,23 @@
                          space.wrap("clipmode not understood"))
 
 
+def searchside_converter(space, w_obj):
+    try:
+        s = space.str_w(w_obj)
+    except OperationError:
+        s = None
+    if not s:
+        raise oefmt(space.w_ValueError,
+                    "expected nonempty string for keyword 'side'")
+    if s[0] == 'l' or s[0] == 'L':
+        return NPY.SEARCHLEFT
+    elif s[0] == 'r' or s[0] == 'R':
+        return NPY.SEARCHRIGHT
+    else:
+        raise oefmt(space.w_ValueError,
+                    "'%s' is an invalid value for keyword 'side'", s)
+
+
 def order_converter(space, w_order, default):
     if space.is_none(w_order):
         return default
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -3,7 +3,7 @@
 from rpython.rlib.buffer import SubBuffer
 from rpython.rlib.rstring import strip_spaces
 from rpython.rtyper.lltypesystem import lltype, rffi
-from pypy.module.micronumpy import descriptor, loop
+from pypy.module.micronumpy import descriptor, loop, support
 from pypy.module.micronumpy.base import (
     W_NDimArray, convert_to_array, W_NumpyObject)
 from pypy.module.micronumpy.converters import shape_converter
@@ -134,6 +134,15 @@
     if dtype.is_str_or_unicode() and dtype.elsize < 1:
         dtype = descriptor.variable_dtype(space, dtype.char + '1')
     shape = shape_converter(space, w_shape, dtype)
+    for dim in shape:
+        if dim < 0:
+            raise OperationError(space.w_ValueError, space.wrap(
+                "negative dimensions are not allowed"))
+    try:
+        support.product(shape)
+    except OverflowError:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "array is too big."))
     return W_NDimArray.from_shape(space, shape, dtype=dtype, zero=zero)
 
 def empty(space, w_shape, w_dtype=None, w_order=None):
diff --git a/pypy/module/micronumpy/flagsobj.py 
b/pypy/module/micronumpy/flagsobj.py
--- a/pypy/module/micronumpy/flagsobj.py
+++ b/pypy/module/micronumpy/flagsobj.py
@@ -2,6 +2,46 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.module.micronumpy import constants as NPY
+
+
+def enable_flags(arr, flags):
+    arr.flags |= flags
+
+
+def clear_flags(arr, flags):
+    arr.flags &= ~flags
+
+
+def _update_contiguous_flags(arr):
+    shape = arr.shape
+    strides = arr.strides
+
+    is_c_contig = True
+    sd = arr.dtype.elsize
+    for i in range(len(shape) - 1, -1, -1):
+        dim = shape[i]
+        if strides[i] != sd:
+            is_c_contig = False
+            break
+        if dim == 0:
+            break
+        sd *= dim
+    if is_c_contig:
+        enable_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
+    else:
+        clear_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
+
+    sd = arr.dtype.elsize
+    for i in range(len(shape)):
+        dim = shape[i]
+        if strides[i] != sd:
+            clear_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
+            return
+        if dim == 0:
+            break
+        sd *= dim
+    enable_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
 
 
 class W_FlagsObject(W_Root):
diff --git a/pypy/module/micronumpy/flatiter.py 
b/pypy/module/micronumpy/flatiter.py
--- a/pypy/module/micronumpy/flatiter.py
+++ b/pypy/module/micronumpy/flatiter.py
@@ -1,7 +1,10 @@
 from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.module.micronumpy import loop
-from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
+from pypy.module.micronumpy.base import convert_to_array
 from pypy.module.micronumpy.concrete import BaseConcreteArray
+from .ndarray import W_NDimArray
 
 
 class FakeArrayImplementation(BaseConcreteArray):
@@ -27,12 +30,22 @@
 class W_FlatIterator(W_NDimArray):
     def __init__(self, arr):
         self.base = arr
+        self.iter, self.state = arr.create_iter()
         # this is needed to support W_NDimArray interface
         self.implementation = FakeArrayImplementation(self.base)
-        self.reset()
 
-    def reset(self):
-        self.iter, self.state = self.base.create_iter()
+    def descr_base(self, space):
+        return space.wrap(self.base)
+
+    def descr_index(self, space):
+        return space.wrap(self.state.index)
+
+    def descr_coords(self, space):
+        self.state = self.iter.update(self.state)
+        return space.newtuple([space.wrap(c) for c in self.state.indices])
+
+    def descr_iter(self):
+        return self
 
     def descr_len(self, space):
         return space.wrap(self.iter.size)
@@ -44,40 +57,59 @@
         self.state = self.iter.next(self.state)
         return w_res
 
-    def descr_index(self, space):
-        return space.wrap(self.state.index)
-
-    def descr_coords(self, space):
-        return space.newtuple([space.wrap(c) for c in self.state.indices])
-
     def descr_getitem(self, space, w_idx):
         if not (space.isinstance_w(w_idx, space.w_int) or
                 space.isinstance_w(w_idx, space.w_slice)):
             raise oefmt(space.w_IndexError, 'unsupported iterator index')
-        self.reset()
-        base = self.base
-        start, stop, step, length = space.decode_index4(w_idx, base.get_size())
-        base_iter, base_state = base.create_iter()
-        base_state = base_iter.next_skip_x(base_state, start)
-        if length == 1:
-            return base_iter.getitem(base_state)
-        res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
-                                     base.get_order(), w_instance=base)
-        return loop.flatiter_getitem(res, base_iter, base_state, step)
+        try:
+            start, stop, step, length = space.decode_index4(w_idx, 
self.iter.size)
+            state = self.iter.goto(start)
+            if length == 1:
+                return self.iter.getitem(state)
+            base = self.base
+            res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
+                                         base.get_order(), w_instance=base)
+            return loop.flatiter_getitem(res, self.iter, state, step)
+        finally:
+            self.state = self.iter.reset(self.state)
 
     def descr_setitem(self, space, w_idx, w_value):
         if not (space.isinstance_w(w_idx, space.w_int) or
                 space.isinstance_w(w_idx, space.w_slice)):
             raise oefmt(space.w_IndexError, 'unsupported iterator index')
-        base = self.base
-        start, stop, step, length = space.decode_index4(w_idx, base.get_size())
-        arr = convert_to_array(space, w_value)
-        loop.flatiter_setitem(space, self.base, arr, start, step, length)
+        start, stop, step, length = space.decode_index4(w_idx, self.iter.size)
+        try:
+            state = self.iter.goto(start)
+            dtype = self.base.get_dtype()
+            if length == 1:
+                try:
+                    val = dtype.coerce(space, w_value)
+                except OperationError:
+                    raise oefmt(space.w_ValueError, "Error setting single item 
of array.")
+                self.iter.setitem(state, val)
+                return
+            arr = convert_to_array(space, w_value)
+            loop.flatiter_setitem(space, dtype, arr, self.iter, state, step, 
length)
+        finally:
+            self.state = self.iter.reset(self.state)
 
-    def descr_iter(self):
-        return self
 
-    def descr_base(self, space):
-        return space.wrap(self.base)
+W_FlatIterator.typedef = TypeDef("numpy.flatiter",
+    base = GetSetProperty(W_FlatIterator.descr_base),
+    index = GetSetProperty(W_FlatIterator.descr_index),
+    coords = GetSetProperty(W_FlatIterator.descr_coords),
 
-# typedef is in interp_ndarray, so we see the additional arguments
+    __iter__ = interp2app(W_FlatIterator.descr_iter),
+    __len__ = interp2app(W_FlatIterator.descr_len),
+    next = interp2app(W_FlatIterator.descr_next),
+
+    __getitem__ = interp2app(W_FlatIterator.descr_getitem),
+    __setitem__ = interp2app(W_FlatIterator.descr_setitem),
+
+    __eq__ = interp2app(W_FlatIterator.descr_eq),
+    __ne__ = interp2app(W_FlatIterator.descr_ne),
+    __lt__ = interp2app(W_FlatIterator.descr_lt),
+    __le__ = interp2app(W_FlatIterator.descr_le),
+    __gt__ = interp2app(W_FlatIterator.descr_gt),
+    __ge__ = interp2app(W_FlatIterator.descr_ge),
+)
diff --git a/pypy/module/micronumpy/iterators.py 
b/pypy/module/micronumpy/iterators.py
--- a/pypy/module/micronumpy/iterators.py
+++ b/pypy/module/micronumpy/iterators.py
@@ -35,14 +35,11 @@
 [x.strides[i] * (x.shape[i] - 1) for i in range(len(x.shape))]
 we can go faster.
 All the calculations happen in next()
-
-next_skip_x(steps) tries to do the iteration for a number of steps at once,
-but then we cannot guarantee that we only overflow one single shape
-dimension, perhaps we could overflow times in one big step.
 """
 from rpython.rlib import jit
-from pypy.module.micronumpy import support
+from pypy.module.micronumpy import support, constants as NPY
 from pypy.module.micronumpy.base import W_NDimArray
+from pypy.module.micronumpy.flagsobj import _update_contiguous_flags
 
 
 class PureShapeIter(object):
@@ -80,7 +77,7 @@
 
 
 class IterState(object):
-    _immutable_fields_ = ['iterator', 'index', 'indices[*]', 'offset']
+    _immutable_fields_ = ['iterator', 'index', 'indices', 'offset']
 
     def __init__(self, iterator, index, indices, offset):
         self.iterator = iterator
@@ -90,11 +87,18 @@
 
 
 class ArrayIter(object):
-    _immutable_fields_ = ['array', 'size', 'ndim_m1', 'shape_m1[*]',
-                          'strides[*]', 'backstrides[*]']
+    _immutable_fields_ = ['contiguous', 'array', 'size', 'ndim_m1', 
'shape_m1[*]',
+                          'strides[*]', 'backstrides[*]', 'factors[*]',
+                          'track_index']
+
+    track_index = True
 
     def __init__(self, array, size, shape, strides, backstrides):
         assert len(shape) == len(strides) == len(backstrides)
+        _update_contiguous_flags(array)
+        self.contiguous = (array.flags & NPY.ARRAY_C_CONTIGUOUS and
+                           array.shape == shape and array.strides == strides)
+
         self.array = array
         self.size = size
         self.ndim_m1 = len(shape) - 1
@@ -102,52 +106,79 @@
         self.strides = strides
         self.backstrides = backstrides
 
-    def reset(self):
-        return IterState(self, 0, [0] * len(self.shape_m1), self.array.start)
+        ndim = len(shape)
+        factors = [0] * ndim
+        for i in xrange(ndim):
+            if i == 0:
+                factors[ndim-1] = 1
+            else:
+                factors[ndim-i-1] = factors[ndim-i] * shape[ndim-i]
+        self.factors = factors
+
+    @jit.unroll_safe
+    def reset(self, state=None):
+        if state is None:
+            indices = [0] * len(self.shape_m1)
+        else:
+            assert state.iterator is self
+            indices = state.indices
+            for i in xrange(self.ndim_m1, -1, -1):
+                indices[i] = 0
+        return IterState(self, 0, indices, self.array.start)
 
     @jit.unroll_safe
     def next(self, state):
         assert state.iterator is self
-        index = state.index + 1
+        index = state.index
+        if self.track_index:
+            index += 1
         indices = state.indices
         offset = state.offset
-        for i in xrange(self.ndim_m1, -1, -1):
-            idx = indices[i]
-            if idx < self.shape_m1[i]:
-                indices[i] = idx + 1
-                offset += self.strides[i]
-                break
-            else:
-                indices[i] = 0
-                offset -= self.backstrides[i]
+        if self.contiguous:
+            offset += self.array.dtype.elsize
+        else:
+            for i in xrange(self.ndim_m1, -1, -1):
+                idx = indices[i]
+                if idx < self.shape_m1[i]:
+                    indices[i] = idx + 1
+                    offset += self.strides[i]
+                    break
+                else:
+                    indices[i] = 0
+                    offset -= self.backstrides[i]
         return IterState(self, index, indices, offset)
 
     @jit.unroll_safe
-    def next_skip_x(self, state, step):
+    def goto(self, index):
+        offset = self.array.start
+        if self.contiguous:
+            offset += index * self.array.dtype.elsize
+        else:
+            current = index
+            for i in xrange(len(self.shape_m1)):
+                offset += (current / self.factors[i]) * self.strides[i]
+                current %= self.factors[i]
+        return IterState(self, index, None, offset)
+
+    @jit.unroll_safe
+    def update(self, state):
         assert state.iterator is self
-        assert step >= 0
-        if step == 0:
+        assert self.track_index
+        if not self.contiguous:
             return state
-        index = state.index + step
+        current = state.index
         indices = state.indices
-        offset = state.offset
-        for i in xrange(self.ndim_m1, -1, -1):
-            idx = indices[i]
-            if idx < (self.shape_m1[i] + 1) - step:
-                indices[i] = idx + step
-                offset += self.strides[i] * step
-                break
+        for i in xrange(len(self.shape_m1)):
+            if self.factors[i] != 0:
+                indices[i] = current / self.factors[i]
+                current %= self.factors[i]
             else:
-                rem_step = (idx + step) // (self.shape_m1[i] + 1)
-                cur_step = step - rem_step * (self.shape_m1[i] + 1)
-                indices[i] = idx + cur_step
-                offset += self.strides[i] * cur_step
-                step = rem_step
-                assert step > 0
-        return IterState(self, index, indices, offset)
+                indices[i] = 0
+        return IterState(self, state.index, indices, state.offset)
 
     def done(self, state):
         assert state.iterator is self
+        assert self.track_index
         return state.index >= self.size
 
     def getitem(self, state):
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -48,6 +48,7 @@
     left_iter, left_state = w_lhs.create_iter(shape)
     right_iter, right_state = w_rhs.create_iter(shape)
     out_iter, out_state = out.create_iter(shape)
+    left_iter.track_index = right_iter.track_index = False
     shapelen = len(shape)
     while not out_iter.done(out_state):
         call2_driver.jit_merge_point(shapelen=shapelen, func=func,
@@ -71,6 +72,7 @@
         out = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
     obj_iter, obj_state = w_obj.create_iter(shape)
     out_iter, out_state = out.create_iter(shape)
+    obj_iter.track_index = False
     shapelen = len(shape)
     while not out_iter.done(out_state):
         call1_driver.jit_merge_point(shapelen=shapelen, func=func,
@@ -182,6 +184,9 @@
             iter, state = y_iter, y_state
     else:
         iter, state = x_iter, x_state
+    out_iter.track_index = x_iter.track_index = False
+    arr_iter.track_index = y_iter.track_index = False
+    iter.track_index = True
     shapelen = len(shape)
     while not iter.done(state):
         where_driver.jit_merge_point(shapelen=shapelen, dtype=dtype,
@@ -229,6 +234,7 @@
                                             dtype=dtype)
         assert not arr_iter.done(arr_state)
         w_val = arr_iter.getitem(arr_state).convert_to(space, dtype)
+        out_state = out_iter.update(out_state)
         if out_state.indices[axis] == 0:
             if identity is not None:
                 w_val = func(dtype, identity, w_val)
@@ -298,6 +304,7 @@
     assert left_shape[-1] == right_shape[right_critical_dim]
     assert result.get_dtype() == dtype
     outi, outs = result.create_iter()
+    outi.track_index = False
     lefti = AllButAxisIter(left_impl, len(left_shape) - 1)
     righti = AllButAxisIter(right_impl, right_critical_dim)
     lefts = lefti.reset()
@@ -322,7 +329,7 @@
             outi.setitem(outs, oval)
             outs = outi.next(outs)
             rights = righti.next(rights)
-        rights = righti.reset()
+        rights = righti.reset(rights)
         lefts = lefti.next(lefts)
     return result
 
@@ -360,6 +367,7 @@
     while not arr_iter.done(arr_state):
         nonzero_driver.jit_merge_point(shapelen=shapelen, dims=dims, 
dtype=dtype)
         if arr_iter.getitem_bool(arr_state):
+            arr_state = arr_iter.update(arr_state)
             for d in dims:
                 res_iter.setitem(res_state, box(arr_state.indices[d]))
                 res_state = res_iter.next(res_state)
@@ -435,7 +443,7 @@
     while not ri.done(rs):
         flatiter_getitem_driver.jit_merge_point(dtype=dtype)
         ri.setitem(rs, base_iter.getitem(base_state))
-        base_state = base_iter.next_skip_x(base_state, step)
+        base_state = base_iter.goto(base_state.index + step)
         rs = ri.next(rs)
     return res
 
@@ -443,11 +451,8 @@
                                         greens = ['dtype'],
                                         reds = 'auto')
 
-def flatiter_setitem(space, arr, val, start, step, length):
-    dtype = arr.get_dtype()
-    arr_iter, arr_state = arr.create_iter()
+def flatiter_setitem(space, dtype, val, arr_iter, arr_state, step, length):
     val_iter, val_state = val.create_iter()
-    arr_state = arr_iter.next_skip_x(arr_state, start)
     while length > 0:
         flatiter_setitem_driver.jit_merge_point(dtype=dtype)
         val = val_iter.getitem(val_state)
@@ -456,9 +461,10 @@
         else:
             val = val.convert_to(space, dtype)
         arr_iter.setitem(arr_state, val)
-        # need to repeat i_nput values until all assignments are done
-        arr_state = arr_iter.next_skip_x(arr_state, step)
+        arr_state = arr_iter.goto(arr_state.index + step)
         val_state = val_iter.next(val_state)
+        if val_iter.done(val_state):
+            val_state = val_iter.reset(val_state)
         length -= 1
 
 fromstring_driver = jit.JitDriver(name = 'numpy_fromstring',
@@ -694,3 +700,43 @@
         out_iter.setitem(out_state, arr.getitem_index(space, indexes))
         iter.next()
         out_state = out_iter.next(out_state)
+
+def _new_binsearch(side, op_name):
+    binsearch_driver = jit.JitDriver(name='numpy_binsearch_' + side,
+                                     greens=['dtype'],
+                                     reds='auto')
+
+    def binsearch(space, arr, key, ret):
+        assert len(arr.get_shape()) == 1
+        dtype = key.get_dtype()
+        op = getattr(dtype.itemtype, op_name)
+        key_iter, key_state = key.create_iter()
+        ret_iter, ret_state = ret.create_iter()
+        ret_iter.track_index = False
+        size = arr.get_size()
+        min_idx = 0
+        max_idx = size
+        last_key_val = key_iter.getitem(key_state)
+        while not key_iter.done(key_state):
+            key_val = key_iter.getitem(key_state)
+            if dtype.itemtype.lt(last_key_val, key_val):
+                max_idx = size
+            else:
+                min_idx = 0
+                max_idx = max_idx + 1 if max_idx < size else size
+            last_key_val = key_val
+            while min_idx < max_idx:
+                binsearch_driver.jit_merge_point(dtype=dtype)
+                mid_idx = min_idx + ((max_idx - min_idx) >> 1)
+                mid_val = arr.getitem(space, [mid_idx]).convert_to(space, 
dtype)
+                if op(mid_val, key_val):
+                    min_idx = mid_idx + 1
+                else:
+                    max_idx = mid_idx
+            ret_iter.setitem(ret_state, ret.get_dtype().box(min_idx))
+            ret_state = ret_iter.next(ret_state)
+            key_state = key_iter.next(key_state)
+    return binsearch
+
+binsearch_left = _new_binsearch('left', 'lt')
+binsearch_right = _new_binsearch('right', 'le')
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
@@ -16,9 +16,8 @@
     ArrayArgumentException, wrap_impl
 from pypy.module.micronumpy.concrete import BaseConcreteArray
 from pypy.module.micronumpy.converters import multi_axis_converter, \
-    order_converter, shape_converter
+    order_converter, shape_converter, searchside_converter
 from pypy.module.micronumpy.flagsobj import W_FlagsObject
-from pypy.module.micronumpy.flatiter import W_FlatIterator
 from pypy.module.micronumpy.strides import get_shape_from_iterable, \
     shape_agreement, shape_agreement_multiple
 
@@ -407,8 +406,19 @@
         --------
         numpy.swapaxes : equivalent function
         """
-        if self.is_scalar():
+        if axis1 == axis2:
             return self
+        n = len(self.get_shape())
+        if n <= 1:
+            return self
+        if axis1 < 0:
+            axis1 += n
+        if axis2 < 0:
+            axis2 += n
+        if axis1 < 0 or axis1 >= n:
+            raise oefmt(space.w_ValueError, "bad axis1 argument to swapaxes")
+        if axis2 < 0 or axis2 >= n:
+            raise oefmt(space.w_ValueError, "bad axis2 argument to swapaxes")
         return self.implementation.swapaxes(space, self, axis1, axis2)
 
     def descr_nonzero(self, space):
@@ -464,10 +474,13 @@
         return repeat(space, self, repeats, w_axis)
 
     def descr_set_flatiter(self, space, w_obj):
+        iter, state = self.create_iter()
+        dtype = self.get_dtype()
         arr = convert_to_array(space, w_obj)
-        loop.flatiter_setitem(space, self, arr, 0, 1, self.get_size())
+        loop.flatiter_setitem(space, dtype, arr, iter, state, 1, iter.size)
 
     def descr_get_flatiter(self, space):
+        from .flatiter import W_FlatIterator
         return space.wrap(W_FlatIterator(self))
 
     def descr_item(self, space, __args__):
@@ -715,29 +728,22 @@
         loop.round(space, self, calc_dtype, self.get_shape(), decimals, out)
         return out
 
-    @unwrap_spec(side=str, w_sorter=WrappedDefault(None))
-    def descr_searchsorted(self, space, w_v, side='left', w_sorter=None):
+    @unwrap_spec(w_side=WrappedDefault('left'), w_sorter=WrappedDefault(None))
+    def descr_searchsorted(self, space, w_v, w_side=None, w_sorter=None):
         if not space.is_none(w_sorter):
             raise OperationError(space.w_NotImplementedError, space.wrap(
                 'sorter not supported in searchsort'))
-        if not side or len(side) < 1:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "expected nonempty string for keyword 'side'"))
-        elif side[0] == 'l' or side[0] == 'L':
-            side = 'l'
-        elif side[0] == 'r' or side[0] == 'R':
-            side = 'r'
-        else:
-            raise oefmt(space.w_ValueError,
-                        "'%s' is an invalid value for keyword 'side'", side)
-        if len(self.get_shape()) > 1:
+        side = searchside_converter(space, w_side)
+        if len(self.get_shape()) != 1:
             raise oefmt(space.w_ValueError, "a must be a 1-d array")
         v = convert_to_array(space, w_v)
-        if len(v.get_shape()) > 1:
-            raise oefmt(space.w_ValueError, "v must be a 1-d array-like")
         ret = W_NDimArray.from_shape(
             space, v.get_shape(), 
descriptor.get_dtype_cache(space).w_longdtype)
-        app_searchsort(space, self, v, space.wrap(side), ret)
+        if side == NPY.SEARCHLEFT:
+            binsearch = loop.binsearch_left
+        else:
+            binsearch = loop.binsearch_right
+        binsearch(space, self, v, ret)
         if ret.is_scalar():
             return ret.get_scalar_value()
         return ret
@@ -1295,31 +1301,6 @@
         return res
 """, filename=__file__).interphook('ptp')
 
-app_searchsort = applevel(r"""
-    def searchsort(arr, v, side, result):
-        import operator
-        def func(a, op, val):
-            imin = 0
-            imax = a.size
-            while imin < imax:
-                imid = imin + ((imax - imin) >> 1)
-                if op(a[imid], val):
-                    imin = imid +1
-                else:
-                    imax = imid
-            return imin
-        if side == 'l':
-            op = operator.lt
-        else:
-            op = operator.le
-        if v.size < 2:
-            result[...] = func(arr, op, v)
-        else:
-            for i in range(v.size):
-                result[i] = func(arr, op, v[i])
-        return result
-""", filename=__file__).interphook('searchsort')
-
 W_NDimArray.typedef = TypeDef("numpy.ndarray",
     __new__ = interp2app(descr_new_array),
 
@@ -1407,6 +1388,7 @@
     flags = GetSetProperty(W_NDimArray.descr_get_flags),
 
     fill = interp2app(W_NDimArray.descr_fill),
+    tobytes = interp2app(W_NDimArray.descr_tostring),
     tostring = interp2app(W_NDimArray.descr_tostring),
 
     mean = interp2app(W_NDimArray.descr_mean),
@@ -1485,23 +1467,3 @@
 
 def _reconstruct(space, w_subtype, w_shape, w_dtype):
     return descr_new_array(space, w_subtype, w_shape, w_dtype)
-
-
-W_FlatIterator.typedef = TypeDef("numpy.flatiter",
-    __iter__ = interp2app(W_FlatIterator.descr_iter),
-    __getitem__ = interp2app(W_FlatIterator.descr_getitem),
-    __setitem__ = interp2app(W_FlatIterator.descr_setitem),
-    __len__ = interp2app(W_FlatIterator.descr_len),
-
-    __eq__ = interp2app(W_FlatIterator.descr_eq),
-    __ne__ = interp2app(W_FlatIterator.descr_ne),
-    __lt__ = interp2app(W_FlatIterator.descr_lt),
-    __le__ = interp2app(W_FlatIterator.descr_le),
-    __gt__ = interp2app(W_FlatIterator.descr_gt),
-    __ge__ = interp2app(W_FlatIterator.descr_ge),
-
-    next = interp2app(W_FlatIterator.descr_next),
-    base = GetSetProperty(W_FlatIterator.descr_base),
-    index = GetSetProperty(W_FlatIterator.descr_index),
-    coords = GetSetProperty(W_FlatIterator.descr_coords),
-)
diff --git a/pypy/module/micronumpy/nditer.py b/pypy/module/micronumpy/nditer.py
--- a/pypy/module/micronumpy/nditer.py
+++ b/pypy/module/micronumpy/nditer.py
@@ -313,6 +313,7 @@
         # create an iterator for each operand
         for i in range(len(self.seq)):
             it = get_iter(space, self.order, self.seq[i], iter_shape, 
self.dtypes[i])
+            it.contiguous = False
             self.iters.append((it, it.reset()))
 
     def set_op_axes(self, space, w_op_axes):
diff --git a/pypy/module/micronumpy/sort.py 
b/pypy/module/micronumpy/selection.py
rename from pypy/module/micronumpy/sort.py
rename to pypy/module/micronumpy/selection.py
diff --git a/pypy/module/micronumpy/support.py 
b/pypy/module/micronumpy/support.py
--- a/pypy/module/micronumpy/support.py
+++ b/pypy/module/micronumpy/support.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.error import OperationError, oefmt
 from rpython.rlib import jit
+from rpython.rlib.rarithmetic import ovfcheck
 
 
 def issequence_w(space, w_obj):
@@ -23,7 +24,7 @@
 def product(s):
     i = 1
     for x in s:
-        i *= x
+        i = ovfcheck(i * x)
     return i
 
 
diff --git a/pypy/module/micronumpy/test/test_arrayops.py 
b/pypy/module/micronumpy/test/test_arrayops.py
--- a/pypy/module/micronumpy/test/test_arrayops.py
+++ b/pypy/module/micronumpy/test/test_arrayops.py
@@ -199,3 +199,19 @@
         a.put(23, -1, mode=1)  # wrap
         assert (a == array([0, 1, -10, -1, -15])).all()
         raises(TypeError, "arange(5).put(22, -5, mode='zzzz')")  # 
unrecognized mode
+
+    def test_result_type(self):
+        import numpy as np
+        exc = raises(ValueError, np.result_type)
+        assert str(exc.value) == "at least one array or dtype is required"
+        exc = raises(TypeError, np.result_type, a=2)
+        assert str(exc.value) == "result_type() takes no keyword arguments"
+        assert np.result_type(True) is np.dtype('bool')
+        assert np.result_type(1) is np.dtype('int')
+        assert np.result_type(1.) is np.dtype('float64')
+        assert np.result_type(1+2j) is np.dtype('complex128')
+        assert np.result_type(1, 1.) is np.dtype('float64')
+        assert np.result_type(np.array([1, 2])) is np.dtype('int')
+        assert np.result_type(np.array([1, 2]), 1, 1+2j) is 
np.dtype('complex128')
+        assert np.result_type(np.array([1, 2]), 1, 'float64') is 
np.dtype('float64')
+        assert np.result_type(np.array([1, 2]), 1, None) is np.dtype('float64')
diff --git a/pypy/module/micronumpy/test/test_compile.py 
b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -330,3 +330,12 @@
         results = interp.results[0]
         assert isinstance(results, W_NDimArray)
         assert results.get_dtype().is_int()
+
+    def test_searchsorted(self):
+        interp = self.run('''
+        a = [1, 4, 5, 6, 9]
+        b = |30| -> ::-1
+        c = searchsorted(a, b)
+        c -> -1
+        ''')
+        assert interp.results[0].value == 0
diff --git a/pypy/module/micronumpy/test/test_iterators.py 
b/pypy/module/micronumpy/test/test_iterators.py
--- a/pypy/module/micronumpy/test/test_iterators.py
+++ b/pypy/module/micronumpy/test/test_iterators.py
@@ -3,7 +3,15 @@
 
 
 class MockArray(object):
-    start = 0
+    flags = 0
+
+    class dtype:
+        elsize = 1
+
+    def __init__(self, shape, strides, start=0):
+        self.shape = shape
+        self.strides = strides
+        self.start = start
 
 
 class TestIterDirect(object):
@@ -14,19 +22,24 @@
         strides = [5, 1]
         backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
         assert backstrides == [10, 4]
-        i = ArrayIter(MockArray, support.product(shape), shape,
+        i = ArrayIter(MockArray(shape, strides), support.product(shape), shape,
                       strides, backstrides)
+        assert i.contiguous
         s = i.reset()
         s = i.next(s)
         s = i.next(s)
         s = i.next(s)
         assert s.offset == 3
         assert not i.done(s)
+        assert s.indices == [0,0]
+        s = i.update(s)
         assert s.indices == [0,3]
         #cause a dimension overflow
         s = i.next(s)
         s = i.next(s)
         assert s.offset == 5
+        assert s.indices == [0,3]
+        s = i.update(s)
         assert s.indices == [1,0]
 
         #Now what happens if the array is transposed? strides[-1] != 1
@@ -34,8 +47,9 @@
         strides = [1, 3]
         backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
         assert backstrides == [2, 12]
-        i = ArrayIter(MockArray, support.product(shape), shape,
+        i = ArrayIter(MockArray(shape, strides), support.product(shape), shape,
                       strides, backstrides)
+        assert not i.contiguous
         s = i.reset()
         s = i.next(s)
         s = i.next(s)
@@ -49,52 +63,20 @@
         assert s.offset == 1
         assert s.indices == [1,0]
 
-    def test_iterator_step(self):
-        #iteration in C order with #contiguous layout => strides[-1] is 1
-        #skip less than the shape
+    def test_iterator_goto(self):
         shape = [3, 5]
-        strides = [5, 1]
-        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
-        assert backstrides == [10, 4]
-        i = ArrayIter(MockArray, support.product(shape), shape,
-                      strides, backstrides)
-        s = i.reset()
-        s = i.next_skip_x(s, 2)
-        s = i.next_skip_x(s, 2)
-        s = i.next_skip_x(s, 2)
-        assert s.offset == 6
-        assert not i.done(s)
-        assert s.indices == [1,1]
-        #And for some big skips
-        s = i.next_skip_x(s, 5)
-        assert s.offset == 11
-        assert s.indices == [2,1]
-        s = i.next_skip_x(s, 5)
-        # Note: the offset does not overflow but recycles,
-        # this is good for broadcast
-        assert s.offset == 1
-        assert s.indices == [0,1]
-        assert i.done(s)
-
-        #Now what happens if the array is transposed? strides[-1] != 1
-        # therefore layout is non-contiguous
         strides = [1, 3]
         backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
         assert backstrides == [2, 12]
-        i = ArrayIter(MockArray, support.product(shape), shape,
+        a = MockArray(shape, strides, 42)
+        i = ArrayIter(a, support.product(shape), shape,
                       strides, backstrides)
+        assert not i.contiguous
         s = i.reset()
-        s = i.next_skip_x(s, 2)
-        s = i.next_skip_x(s, 2)
-        s = i.next_skip_x(s, 2)
-        assert s.offset == 4
-        assert s.indices == [1,1]
-        assert not i.done(s)
-        s = i.next_skip_x(s, 5)
-        assert s.offset == 5
-        assert s.indices == [2,1]
-        assert not i.done(s)
-        s = i.next_skip_x(s, 5)
-        assert s.indices == [0,1]
-        assert s.offset == 3
-        assert i.done(s)
+        assert s.index == 0
+        assert s.indices == [0, 0]
+        assert s.offset == a.start
+        s = i.goto(11)
+        assert s.index == 11
+        assert s.indices is None
+        assert s.offset == a.start + 5
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
@@ -384,6 +384,19 @@
         assert zeros((), dtype='S').shape == ()
         assert zeros((), dtype='S').dtype == '|S1'
 
+    def test_check_shape(self):
+        import numpy as np
+        for func in [np.zeros, np.empty]:
+            exc = raises(ValueError, func, [0, -1, 1], 'int8')
+            assert str(exc.value) == "negative dimensions are not allowed"
+            exc = raises(ValueError, func, [2, -1, 3], 'int8')
+            assert str(exc.value) == "negative dimensions are not allowed"
+
+            exc = raises(ValueError, func, [975]*7, 'int8')
+            assert str(exc.value) == "array is too big."
+            exc = raises(ValueError, func, [26244]*5, 'int8')
+            assert str(exc.value) == "array is too big."
+
     def test_empty_like(self):
         import numpy as np
         a = np.empty_like(np.zeros(()))
@@ -2020,6 +2033,14 @@
 
     def test_swapaxes(self):
         from numpypy import array
+        x = array([])
+        assert x.swapaxes(0, 2) is x
+        x = array([[1, 2]])
+        assert x.swapaxes(0, 0) is x
+        exc = raises(ValueError, x.swapaxes, -3, 0)
+        assert exc.value.message == "bad axis1 argument to swapaxes"
+        exc = raises(ValueError, x.swapaxes, 0, 3)
+        assert exc.value.message == "bad axis2 argument to swapaxes"
         # testcases from numpy docstring
         x = array([[1, 2, 3]])
         assert (x.swapaxes(0, 1) == array([[1], [2], [3]])).all()
@@ -2706,15 +2727,35 @@
         b.next()
         assert b.index == 3
         assert b.coords == (0, 3)
+        b.next()
         assert b[3] == 3
-        assert (b[::3] == [0, 3, 6, 9]).all()
-        assert (b[2::5] == [2, 7]).all()
-        assert b[-2] == 8
-        raises(IndexError, "b[11]")
-        raises(IndexError, "b[-11]")
-        raises(IndexError, 'b[0, 1]')
         assert b.index == 0
         assert b.coords == (0, 0)
+        b.next()
+        assert (b[::3] == [0, 3, 6, 9]).all()
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        assert (b[2::5] == [2, 7]).all()
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        assert b[-2] == 8
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        raises(IndexError, "b[11]")
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        raises(IndexError, "b[-11]")
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        exc = raises(IndexError, 'b[0, 1]')
+        assert str(exc.value) == "unsupported iterator index"
+        assert b.index == 1
+        assert b.coords == (0, 1)
 
     def test_flatiter_setitem(self):
         from numpypy import arange, array
@@ -2722,9 +2763,25 @@
         b = a.T.flat
         b[6::2] = [-1, -2]
         assert (a == [[0, 1, -1, 3], [4, 5, 6, -1], [8, 9, -2, 11]]).all()
+        assert b[2] == 8
+        assert b.index == 0
+        b.next()
+        b[6::2] = [-21, -42]
+        assert (a == [[0, 1, -21, 3], [4, 5, 6, -21], [8, 9, -42, 11]]).all()
         b[0:2] = [[[100]]]
         assert(a[0,0] == 100)
         assert(a[1,0] == 100)
+        b.next()
+        assert b.index == 1
+        exc = raises(ValueError, "b[0] = [1, 2]")
+        assert str(exc.value) == "Error setting single item of array."
+        assert b.index == 0
+        b.next()
+        raises(IndexError, "b[100] = 42")
+        assert b.index == 1
+        exc = raises(IndexError, "b[0, 1] = 42")
+        assert str(exc.value) == "unsupported iterator index"
+        assert b.index == 1
 
     def test_flatiter_ops(self):
         from numpypy import arange, array
@@ -3348,6 +3405,7 @@
             '@\x01\x99\x99\x99\x99\x99\x9a\xbf\xf1\x99\x99\x99\x99\x99\x9a'
         assert array(2.2-1.1j, dtype='<c16').tostring() == \
             '\x9a\x99\x99\x99\x99\x99\x01@\x9a\x99\x99\x99\x99\x99\xf1\xbf'
+        assert a.tostring == a.tobytes
 
     def test_str(self):
         from numpypy import array
diff --git a/pypy/module/micronumpy/test/test_sorting.py 
b/pypy/module/micronumpy/test/test_selection.py
rename from pypy/module/micronumpy/test/test_sorting.py
rename to pypy/module/micronumpy/test/test_selection.py
--- a/pypy/module/micronumpy/test/test_sorting.py
+++ b/pypy/module/micronumpy/test/test_selection.py
@@ -352,21 +352,49 @@
 
     def test_searchsort(self):
         import numpy as np
-        import sys
+
+        a = np.array(2)
+        raises(ValueError, a.searchsorted, 3)
+
         a = np.arange(1, 6)
+
         ret = a.searchsorted(3)
         assert ret == 2
         assert isinstance(ret, np.generic)
+
         ret = a.searchsorted(np.array(3))
         assert ret == 2
         assert isinstance(ret, np.generic)
+
+        ret = a.searchsorted(np.array([]))
+        assert isinstance(ret, np.ndarray)
+        assert ret.shape == (0,)
+
         ret = a.searchsorted(np.array([3]))
         assert ret == 2
         assert isinstance(ret, np.ndarray)
+
+        ret = a.searchsorted(np.array([[2, 3]]))
+        assert (ret == [1, 2]).all()
+        assert ret.shape == (1, 2)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to