[pypy-commit] pypy refactor-str-types: hg merge default

Manuel Jacob noreply at buildbot.pypy.org
Mon Jan 13 12:11:32 CET 2014


Author: Manuel Jacob
Branch: refactor-str-types
Changeset: r68631:1dfbad2cbd56
Date: 2014-01-13 11:05 +0100
http://bitbucket.org/pypy/pypy/changeset/1dfbad2cbd56/

Log:	hg merge default

diff too long, truncating to 2000 out of 12023 lines

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -28,7 +28,7 @@
     DEALINGS IN THE SOFTWARE.
 
 
-PyPy Copyright holders 2003-2013
+PyPy Copyright holders 2003-2014
 ----------------------------------- 
 
 Except when otherwise stated (look for LICENSE files or information at
diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py
--- a/lib-python/2.7/ctypes/__init__.py
+++ b/lib-python/2.7/ctypes/__init__.py
@@ -371,10 +371,9 @@
             self._handle = handle
 
     def __repr__(self):
-        return "<%s '%s', handle %r at %x>" % \
-               (self.__class__.__name__, self._name,
-                (self._handle),
-                id(self) & (_sys.maxint*2 + 1))
+        return "<%s '%s', handle %r at 0x%x>" % (
+            self.__class__.__name__, self._name, self._handle,
+            id(self) & (_sys.maxint * 2 + 1))
 
 
     def __getattr__(self, name):
diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py
--- a/lib-python/2.7/ctypes/test/test_python_api.py
+++ b/lib-python/2.7/ctypes/test/test_python_api.py
@@ -73,6 +73,7 @@
         del pyobj
         self.assertEqual(grc(s), ref)
 
+    @xfail
     def test_PyOS_snprintf(self):
         PyOS_snprintf = pythonapi.PyOS_snprintf
         PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p
diff --git a/lib-python/2.7/test/test_ssl.py b/lib-python/2.7/test/test_ssl.py
--- a/lib-python/2.7/test/test_ssl.py
+++ b/lib-python/2.7/test/test_ssl.py
@@ -993,7 +993,7 @@
             try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
             try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
             try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
-            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
+            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
             try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
             try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
 
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -109,7 +109,7 @@
     RegrTest('test_asynchat.py', usemodules='select fcntl'),
     RegrTest('test_asyncore.py', usemodules='select fcntl'),
     RegrTest('test_atexit.py', core=True),
-    RegrTest('test_audioop.py', skip="unsupported extension module"),
+    RegrTest('test_audioop.py', skip="incomplete module"),
     RegrTest('test_augassign.py', core=True),
     RegrTest('test_base64.py', usemodules='struct'),
     RegrTest('test_bastion.py'),
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -328,21 +328,23 @@
                 raise ValueError(
                     "native COM method call without 'this' parameter"
                     )
-            thisarg = cast(args[0], POINTER(POINTER(c_void_p)))
-            keepalives, newargs, argtypes, outargs = self._convert_args(argtypes,
-                                                                        args[1:], kwargs)
-            newargs.insert(0, args[0].value)
+            thisvalue = args.pop(0)
+            thisarg = cast(thisvalue, POINTER(POINTER(c_void_p)))
+            keepalives, newargs, argtypes, outargs, errcheckargs = (
+                        self._convert_args(argtypes, args, kwargs))
+            args.insert(0, thisvalue)
+            newargs.insert(0, thisvalue.value)
             argtypes.insert(0, c_void_p)
         else:
             thisarg = None
-            keepalives, newargs, argtypes, outargs = self._convert_args(argtypes,
-                                                                        args, kwargs)
+            keepalives, newargs, argtypes, outargs, errcheckargs = (
+                        self._convert_args(argtypes, args, kwargs))
 
         funcptr = self._getfuncptr(argtypes, self._restype_, thisarg)
         result = self._call_funcptr(funcptr, *newargs)
-        result = self._do_errcheck(result, args)
+        result, forced = self._do_errcheck(result, errcheckargs)
 
-        if not outargs:
+        if not outargs or forced:
             return result
 
         from ctypes import c_void_p
@@ -377,22 +379,22 @@
                 set_last_error(tmp)
         #
         try:
-            return self._build_result(self._restype_, result, newargs)
+            return self._build_result(self._restype_, result)
         finally:
             funcptr.free_temp_buffers()
 
     def _do_errcheck(self, result, args):
         # The 'errcheck' protocol
         if self._errcheck_:
-            v = self._errcheck_(result, self, args)
+            v = self._errcheck_(result, self, tuple(args))
             # If the errcheck funtion failed, let it throw
             # If the errcheck function returned newargs unchanged,
             # continue normal processing.
             # If the errcheck function returned something else,
             # use that as result.
             if v is not args:
-                return v
-        return result
+                return v, True
+        return result, False
 
     def _getfuncptr_fromaddress(self, argtypes, restype):
         address = self._get_address()
@@ -495,16 +497,16 @@
         newargtypes = []
         total = len(args)
         paramflags = self._paramflags
-        inargs_idx = 0
 
         if not paramflags and total < len(argtypes):
             raise TypeError("not enough arguments")
 
-        for i, argtype in enumerate(argtypes):
-            flag = 0
-            name = None
-            defval = marker
-            if paramflags:
+        if paramflags:
+            errcheckargs = []
+            inargs_idx = 0
+            for i, argtype in enumerate(argtypes):
+                flag = 0
+                defval = marker
                 paramflag = paramflags[i]
                 paramlen = len(paramflag)
                 name = None
@@ -519,6 +521,7 @@
                     val = defval
                     if val is marker:
                         val = 0
+                    errcheckargs.append(val)
                     keepalive, newarg, newargtype = self._conv_param(argtype, val)
                     keepalives.append(keepalive)
                     newargs.append(newarg)
@@ -536,27 +539,31 @@
                         raise TypeError("required argument '%s' missing" % name)
                     else:
                         raise TypeError("not enough arguments")
+                    errcheckargs.append(val)
                     keepalive, newarg, newargtype = self._conv_param(argtype, val)
                     keepalives.append(keepalive)
                     newargs.append(newarg)
                     newargtypes.append(newargtype)
                 elif flag == PARAMFLAG_FOUT:
                     if defval is not marker:
-                        outargs.append(defval)
+                        val = defval
                         keepalive, newarg, newargtype = self._conv_param(argtype, defval)
                     else:
                         import ctypes
                         val = argtype._type_()
-                        outargs.append(val)
                         keepalive = None
                         newarg = ctypes.byref(val)
                         newargtype = type(newarg)
+                    errcheckargs.append(val)
+                    outargs.append(val)
                     keepalives.append(keepalive)
                     newargs.append(newarg)
                     newargtypes.append(newargtype)
                 else:
                     raise ValueError("paramflag %d not yet implemented" % flag)
-            else:
+        else:
+            errcheckargs = args
+            for i, argtype in enumerate(argtypes):
                 try:
                     keepalive, newarg, newargtype = self._conv_param(argtype, args[i])
                 except (UnicodeError, TypeError, ValueError), e:
@@ -564,7 +571,6 @@
                 keepalives.append(keepalive)
                 newargs.append(newarg)
                 newargtypes.append(newargtype)
-                inargs_idx += 1
 
         if len(newargs) < len(args):
             extra = args[len(newargs):]
@@ -576,7 +582,7 @@
                 keepalives.append(keepalive)
                 newargs.append(newarg)
                 newargtypes.append(newargtype)
-        return keepalives, newargs, newargtypes, outargs
+        return keepalives, newargs, newargtypes, outargs, errcheckargs
 
     @staticmethod
     def _is_primitive(argtype):
@@ -601,7 +607,7 @@
         retval = restype._CData_retval(buf)
         return retval
 
-    def _build_result(self, restype, result, argsandobjs):
+    def _build_result(self, restype, result):
         """Build the function result:
            If there is no OUT parameter, return the actual function result
            If there is one OUT parameter, return it
@@ -611,11 +617,6 @@
         # i.e. an array of ints. Now it takes a result, which is already a
         # python object. All places that do "resbuffer[0]" should check that
         # result is actually an int and just use it.
-        #
-        # Also, argsandobjs used to be "args" in __call__, now it's "newargs"
-        # (i.e., the already unwrapped objects). It's used only when we have a
-        # PARAMFLAG_FOUT and it's probably wrong, I'll fix it when I find a
-        # failing test
 
         retval = None
 
@@ -704,7 +705,7 @@
             funcptr = self._getfuncptr(argtypes, restype, thisarg)
             try:
                 result = self._call_funcptr(funcptr, *args)
-                result = self._do_errcheck(result, args)
+                result, _ = self._do_errcheck(result, args)
             except (TypeError, ArgumentError, UnicodeDecodeError):
                 assert self._slowpath_allowed
                 return CFuncPtr.__call__(self, *args)
diff --git a/lib_pypy/_pypy_testcapi.py b/lib_pypy/_pypy_testcapi.py
--- a/lib_pypy/_pypy_testcapi.py
+++ b/lib_pypy/_pypy_testcapi.py
@@ -33,14 +33,13 @@
     # set link options
     output_filename = modulename + _get_c_extension_suffix()
     if sys.platform == 'win32':
-        # XXX libpypy-c.lib is currently not installed automatically
-        library = os.path.join(thisdir, '..', 'include', 'libpypy-c')
+        # XXX pyconfig.h uses a pragma to link to the import library,
+        #     which is currently python27.lib
+        library = os.path.join(thisdir, '..', 'include', 'python27')
         if not os.path.exists(library + '.lib'):
-            #For a nightly build
-            library = os.path.join(thisdir, '..', 'include', 'python27')
-        if not os.path.exists(library + '.lib'):
-            # For a local translation
-            library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c')
+            # For a local translation or nightly build
+            library = os.path.join(thisdir, '..', 'pypy', 'goal', 'python27')
+        assert os.path.exists(library + '.lib'),'Could not find import library "%s"' % library
         libraries = [library, 'oleaut32']
         extra_ldargs = ['/MANIFEST',  # needed for VC10
                         '/EXPORT:init' + modulename]
diff --git a/lib_pypy/_sha.py b/lib_pypy/_sha.py
--- a/lib_pypy/_sha.py
+++ b/lib_pypy/_sha.py
@@ -115,14 +115,14 @@
     ]
 
 class sha:
-    "An implementation of the MD5 hash function in pure Python."
+    "An implementation of the SHA hash function in pure Python."
 
     digest_size = digestsize = 20
-    block_size = 1
+    block_size = 512 // 8
 
     def __init__(self):
         "Initialisation."
-        
+
         # Initial message length in bits(!).
         self.length = 0
         self.count = [0, 0]
@@ -209,7 +209,7 @@
         self.H2 = (self.H2 + C) & 0xffffffff
         self.H3 = (self.H3 + D) & 0xffffffff
         self.H4 = (self.H4 + E) & 0xffffffff
-    
+
 
     # Down from here all methods follow the Python Standard Library
     # API of the sha module.
@@ -295,13 +295,13 @@
                  _long2bytesBigEndian(self.H3, 4) + \
                  _long2bytesBigEndian(self.H4, 4)
 
-        self.H0 = H0 
-        self.H1 = H1 
+        self.H0 = H0
+        self.H1 = H1
         self.H2 = H2
         self.H3 = H3
         self.H4 = H4
-        self.input = input 
-        self.count = count 
+        self.input = input
+        self.count = count
 
         return digest
 
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -330,6 +330,14 @@
 # SQLite version information
 sqlite_version = str(_ffi.string(_lib.sqlite3_libversion()).decode('ascii'))
 
+_STMT_TYPE_UPDATE = 0
+_STMT_TYPE_DELETE = 1
+_STMT_TYPE_INSERT = 2
+_STMT_TYPE_REPLACE = 3
+_STMT_TYPE_OTHER = 4
+_STMT_TYPE_SELECT = 5
+_STMT_TYPE_INVALID = 6
+
 
 class Error(StandardError):
     pass
@@ -992,13 +1000,18 @@
             self.__statement = self.__connection._statement_cache.get(sql)
 
             if self.__connection._isolation_level is not None:
-                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
+                if self.__statement._type in (
+                    _STMT_TYPE_UPDATE,
+                    _STMT_TYPE_DELETE,
+                    _STMT_TYPE_INSERT,
+                    _STMT_TYPE_REPLACE
+                ):
                     if not self.__connection._in_transaction:
                         self.__connection._begin()
-                elif self.__statement._type == "OTHER":
+                elif self.__statement._type == _STMT_TYPE_OTHER:
                     if self.__connection._in_transaction:
                         self.__connection.commit()
-                elif self.__statement._type == "SELECT":
+                elif self.__statement._type == _STMT_TYPE_SELECT:
                     if multiple:
                         raise ProgrammingError("You cannot execute SELECT "
                                                "statements in executemany().")
@@ -1021,12 +1034,17 @@
                     self.__statement._reset()
                     raise self.__connection._get_exception(ret)
 
-                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
+                if self.__statement._type in (
+                    _STMT_TYPE_UPDATE,
+                    _STMT_TYPE_DELETE,
+                    _STMT_TYPE_INSERT,
+                    _STMT_TYPE_REPLACE
+                ):
                     if self.__rowcount == -1:
                         self.__rowcount = 0
                     self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
 
-                if not multiple and self.__statement._type == "INSERT":
+                if not multiple and self.__statement._type == _STMT_TYPE_INSERT:
                     self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db)
                 else:
                     self.__lastrowid = None
@@ -1176,11 +1194,19 @@
 
         first_word = sql.lstrip().split(" ")[0].upper()
         if first_word == "":
-            self._type = "INVALID"
-        elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"):
-            self._type = first_word
+            self._type = _STMT_TYPE_INVALID
+        elif first_word == "SELECT":
+            self._type = _STMT_TYPE_SELECT
+        elif first_word == "INSERT":
+            self._type = _STMT_TYPE_INSERT
+        elif first_word == "UPDATE":
+            self._type = _STMT_TYPE_UPDATE
+        elif first_word == "DELETE":
+            self._type = _STMT_TYPE_DELETE
+        elif first_word == "REPLACE":
+            self._type = _STMT_TYPE_REPLACE
         else:
-            self._type = "OTHER"
+            self._type = _STMT_TYPE_OTHER
 
         if isinstance(sql, unicode):
             sql = sql.encode('utf-8')
@@ -1193,7 +1219,7 @@
 
         if ret == _lib.SQLITE_OK and not self._statement:
             # an empty statement, work around that, as it's the least trouble
-            self._type = "SELECT"
+            self._type = _STMT_TYPE_SELECT
             c_sql = _ffi.new("char[]", b"select 42")
             ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1,
                                           statement_star, next_char)
@@ -1312,7 +1338,12 @@
             raise ValueError("parameters are of unsupported type")
 
     def _get_description(self):
-        if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
+        if self._type in (
+            _STMT_TYPE_INSERT,
+            _STMT_TYPE_UPDATE,
+            _STMT_TYPE_DELETE,
+            _STMT_TYPE_REPLACE
+        ):
             return None
         desc = []
         for i in xrange(_lib.sqlite3_column_count(self._statement)):
diff --git a/lib_pypy/audioop.py b/lib_pypy/audioop.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/audioop.py
@@ -0,0 +1,29 @@
+
+import struct
+
+
+class error(Exception):
+    pass
+
+
+def _check_size(size):
+    if size != 1 and size != 2 and size != 4:
+         raise error("Size should be 1, 2 or 4")
+
+
+def _check_params(length, size):
+    _check_size(size)
+    if length % size != 0:
+        raise error("not a whole number of frames")
+
+
+def getsample(cp, size, i):
+    _check_params(len(cp), size)
+    if not (0 <= i < len(cp) / size):
+        raise error("Index out of range")
+    if size == 1:
+        return struct.unpack_from("B", buffer(cp)[i:])[0]
+    elif size == 2:
+        return struct.unpack_from("H", buffer(cp)[i * 2:])[0]
+    elif size == 4:
+        return struct.unpack_from("I", buffer(cp)[i * 4:])[0]
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,5 +4,5 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "0.8"
-__version_info__ = (0, 8)
+__version__ = "0.8.1"
+__version_info__ = (0, 8, 1)
diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -878,7 +878,6 @@
             month = self._month
         if day is None:
             day = self._day
-        year, month, day = _check_date_fields(year, month, day)
         return date(year, month, day)
 
     # Comparisons of date objects with other.
@@ -1389,8 +1388,6 @@
             microsecond = self.microsecond
         if tzinfo is True:
             tzinfo = self.tzinfo
-        hour, minute, second, microsecond = _check_time_fields(hour, minute, second, microsecond)
-        _check_tzinfo_arg(tzinfo)
         return time(hour, minute, second, microsecond, tzinfo)
 
     def __nonzero__(self):
@@ -1608,9 +1605,6 @@
             microsecond = self.microsecond
         if tzinfo is True:
             tzinfo = self.tzinfo
-        year, month, day = _check_date_fields(year, month, day)
-        hour, minute, second, microsecond = _check_time_fields(hour, minute, second, microsecond)
-        _check_tzinfo_arg(tzinfo)
         return datetime(year, month, day, hour, minute, second, microsecond,
                         tzinfo)
 
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -63,3 +63,6 @@
         except KeyboardInterrupt:
             console.write("\nKeyboardInterrupt\n")
             console.resetbuffer()
+        except MemoryError:
+            console.write("\nMemoryError\n")
+            console.resetbuffer()
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -38,7 +38,7 @@
 
 # General information about the project.
 project = u'PyPy'
-copyright = u'2013, The PyPy Project'
+copyright = u'2014, The PyPy Project'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -47,7 +47,7 @@
 # The short X.Y version.
 version = '2.2'
 # The full version, including alpha/beta/rc tags.
-release = '2.2.0'
+release = '2.2.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -83,7 +83,7 @@
 
     _winreg
 
-* Supported by being rewritten in pure Python (possibly using ``ctypes``):
+* Supported by being rewritten in pure Python (possibly using ``cffi``):
   see the `lib_pypy/`_ directory.  Examples of modules that we
   support this way: ``ctypes``, ``cPickle``, ``cmath``, ``dbm``, ``datetime``...
   Note that some modules are both in there and in the list above;
@@ -316,5 +316,4 @@
   type and vice versa. For builtin types, a dictionary will be returned that
   cannot be changed (but still looks and behaves like a normal dictionary).
 
-
 .. include:: _ref.txt
diff --git a/pypy/doc/ctypes-implementation.rst b/pypy/doc/ctypes-implementation.rst
--- a/pypy/doc/ctypes-implementation.rst
+++ b/pypy/doc/ctypes-implementation.rst
@@ -72,7 +72,13 @@
 Here is a list of the limitations and missing features of the
 current implementation:
 
-* No support for ``PyXxx`` functions from ``libpython``, for obvious reasons.
+* ``ctypes.pythonapi`` lets you access the CPython C API emulation layer
+  of PyPy, at your own risks and without doing anything sensible about
+  the GIL.  Since PyPy 2.3, these functions are also named with an extra
+  "Py", for example ``PyPyInt_FromLong()``.  Basically, don't use this,
+  but it might more or less work in simple cases if you do.  (Obviously,
+  assuming the PyObject pointers you get have any particular fields in
+  any particular order is just going to crash.)
 
 * We copy Python strings instead of having pointers to raw buffers
 
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -5,119 +5,68 @@
 This document tries to explain how to interface the PyPy python interpreter
 with any external library.
 
-Note: We try to describe state-of-the art, but it
-might fade out of date as this is the front on which things are changing
-in pypy rapidly.
+Right now, there are the following possibilities of providing
+third-party modules for the PyPy python interpreter (in order of
+usefulness):
 
-Possibilities
-=============
+* Write them in pure Python and use CFFI_.
 
-Right now, there are three possibilities of providing third-party modules
-for the PyPy python interpreter (in order of usefulness):
+* Write them in pure Python and use ctypes_.
 
-* Write them in pure python and use ctypes, see ctypes_
-  section
+* Write them in C++ and bind them through Reflex_.
 
-* Write them in pure python and use direct libffi low-level bindings, See
-  \_ffi_ module description.
+* Write them in as `RPython mixed modules`_.
 
-* Write them in RPython as mixedmodule_, using *rffi* as bindings.
 
-* Write them in C++ and bind them through Reflex_
+CFFI
+====
 
-.. _ctypes: #CTypes
-.. _\_ffi: #LibFFI
-.. _mixedmodule: #Mixed Modules
+CFFI__ is the recommended way.  It is a way to write pure Python code
+that accesses C libraries.  The idea is to support either ABI- or
+API-level access to C --- so that you can sanely access C libraries
+without depending on details like the exact field order in the C
+structures or the numerical value of all the constants.  It works on
+both CPython (as a separate ``pip install cffi``) and on PyPy, where it
+is included by default.
+
+PyPy's JIT does a quite reasonable job on the Python code that call C
+functions or manipulate C pointers with CFFI.  (As of PyPy 2.2.1, it
+could still be improved, but is already good.)
+
+See the documentation here__.
+
+.. __: http://cffi.readthedocs.org/
+.. __: http://cffi.readthedocs.org/
+
 
 CTypes
 ======
 
-The ctypes module in PyPy is ready to use.
-It's goal is to be as-compatible-as-possible with the
-`CPython ctypes`_ version. Right now it's able to support large examples,
-such as pyglet. PyPy is planning to have a 100% compatible ctypes
-implementation, without the CPython C-level API bindings (so it is very
-unlikely that direct object-manipulation trickery through this API will work).
+The goal of the ctypes module of PyPy is to be as compatible as possible
+with the `CPython ctypes`_ version.  It works for large examples, such
+as pyglet.  PyPy's implementation is not strictly 100% compatible with
+CPython, but close enough for most cases.
 
-We also provide a `ctypes-configure`_ for overcoming the platform dependencies,
-not relying on the ctypes codegen. This tool works by querying gcc about
-platform-dependent details (compiling small snippets of C code and running
-them), so it'll benefit not pypy-related ctypes-based modules as well.
+We also used to provide ``ctypes-configure`` for some API-level access.
+This is now viewed as a precursor of CFFI, which you should use instead.
+More (but older) information is available here__.
+Also, ctypes' performance is not as good as CFFI's.
 
-ctypes call are optimized by the JIT and the resulting machine code contains a
-direct call to the target C function.  However, due to the very dynamic nature
-of ctypes, some overhead over a bare C call is still present, in particular to
-check/convert the types of the parameters.  Moreover, even if most calls are
-optimized, some cannot and thus need to follow the slow path, not optimized by
-the JIT.
+.. _`CPython ctypes`: http://docs.python.org/library/ctypes.html
+.. __: ctypes-implementation.html
 
-.. _`ctypes-configure`: ctypes-implementation.html#ctypes-configure
-.. _`CPython ctypes`: http://docs.python.org/library/ctypes.html
+PyPy implements ctypes as pure Python code around two built-in modules
+called ``_ffi`` and ``_rawffi``, which give a very low-level binding to
+the C library libffi_.  Nowadays it is not recommended to use directly
+these two modules.
 
-Pros
-----
+.. _libffi: http://sourceware.org/libffi/
 
-Stable, CPython-compatible API.  Most calls are fast, optimized by JIT.
-
-Cons
-----
-
-Problems with platform-dependency (although we partially solve
-those). Although the JIT optimizes ctypes calls, some overhead is still
-present.  The slow-path is very slow.
-
-
-LibFFI
-======
-
-Mostly in order to be able to write a ctypes module, we developed a very
-low-level libffi bindings called ``_ffi``. (libffi is a C-level library for dynamic calling,
-which is used by CPython ctypes). This library provides stable and usable API,
-although it's API is a very low-level one. It does not contain any
-magic.  It is also optimized by the JIT, but has much less overhead than ctypes.
-
-Pros
-----
-
-It Works. Probably more suitable for a delicate code where ctypes magic goes
-in a way.  All calls are optimized by the JIT, there is no slow path as in
-ctypes.
-
-Cons
-----
-
-It combines disadvantages of using ctypes with disadvantages of using mixed
-modules. CPython-incompatible API, very rough and low-level.
-
-Mixed Modules
-=============
-
-This is the most advanced and powerful way of writing extension modules.
-It has some serious disadvantages:
-
-* a mixed module needs to be written in RPython, which is far more
-  complicated than Python (XXX link)
-
-* due to lack of separate compilation (as of July 2011), each
-  compilation-check requires to recompile whole PyPy python interpreter,
-  which takes 0.5-1h. We plan to solve this at some point in near future.
-
-* although rpython is a garbage-collected language, the border between
-  C and RPython needs to be managed by hand (each object that goes into the
-  C level must be explicitly freed).
-
-Some documentation is available `here`_
-
-.. _`here`: rffi.html
-
-XXX we should provide detailed docs about lltype and rffi, especially if we
-    want people to follow that way.
 
 Reflex
 ======
 
-This method is still experimental and is being exercised on a branch,
-`reflex-support`_, which adds the `cppyy`_ module.
+This method is still experimental.  It adds the `cppyy`_ module.
 The method works by using the `Reflex package`_ to provide reflection
 information of the C++ code, which is then used to automatically generate
 bindings at runtime.
@@ -168,3 +117,15 @@
 to work around it in python or with a C++ helper function.
 Although Reflex works on various platforms, the bindings with PyPy have only
 been tested on Linux.
+
+
+RPython Mixed Modules
+=====================
+
+This is the internal way to write built-in extension modules in PyPy.
+It cannot be used by any 3rd-party module: the extension modules are
+*built-in*, not independently loadable DLLs.
+
+This is reserved for special cases: it gives direct access to e.g. the
+details of the JIT, allowing us to tweak its interaction with user code.
+This is how the numpy module is being developed.
diff --git a/pypy/doc/extradoc.rst b/pypy/doc/extradoc.rst
--- a/pypy/doc/extradoc.rst
+++ b/pypy/doc/extradoc.rst
@@ -72,13 +72,13 @@
 
 .. _bibtex: https://bitbucket.org/pypy/extradoc/raw/tip/talk/bibtex.bib
 .. _`Runtime Feedback in a Meta-Tracing JIT for Efficient Dynamic Languages`: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/icooolps2011/jit-hints.pdf
-.. _`Allocation Removal by Partial Evaluation in a Tracing JIT`: http://codespeak.net/svn/pypy/extradoc/talk/pepm2011/bolz-allocation-removal.pdf
-.. _`Towards a Jitting VM for Prolog Execution`: http://www.stups.uni-duesseldorf.de/publications/bolz-prolog-jit.pdf
+.. _`Allocation Removal by Partial Evaluation in a Tracing JIT`: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/pepm2011/bolz-allocation-removal.pdf
+.. _`Towards a Jitting VM for Prolog Execution`: http://www.stups.uni-duesseldorf.de/mediawiki/images/a/a7/Pub-BoLeSch2010.pdf
 .. _`High performance implementation of Python for CLI/.NET with JIT compiler generation for dynamic languages`: http://buildbot.pypy.org/misc/antocuni-thesis.pdf
 .. _`How to *not* write Virtual Machines for Dynamic Languages`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/dyla2007/dyla.pdf
 .. _`Tracing the Meta-Level: PyPy's Tracing JIT Compiler`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/icooolps2009/bolz-tracing-jit.pdf
 .. _`Faster than C#: Efficient Implementation of Dynamic Languages on .NET`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/icooolps2009-dotnet/cli-jit.pdf
-.. _`Automatic JIT Compiler Generation with Runtime Partial Evaluation`:  http://www.stups.uni-duesseldorf.de/thesis/final-master.pdf
+.. _`Automatic JIT Compiler Generation with Runtime Partial Evaluation`: http://wwwold.cobra.cs.uni-duesseldorf.de/thesis/final-master.pdf
 .. _`RPython: A Step towards Reconciling Dynamically and Statically Typed OO Languages`: http://www.disi.unige.it/person/AnconaD/papers/Recent_abstracts.html#AACM-DLS07
 .. _`EU Reports`: index-report.html
 .. _`Hardware Transactional Memory Support for Lightweight Dynamic Language Evolution`: http://sabi.net/nriley/pubs/dls6-riley.pdf
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -444,7 +444,7 @@
 So the position of the core PyPy developers is that if anyone wants to
 make an N+1'th attempt with LLVM, they are welcome, and will be happy to
 provide help in the IRC channel, but they are left with the burden of proof
-that it works.
+that (a) it works and (b) it gives important benefits.
 
 ----------------------
 How do I compile PyPy?
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 2.2.0`_: the latest official release
+* `Release 2.2.1`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -110,7 +110,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 2.2.0`: http://pypy.org/download.html
+.. _`Release 2.2.1`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.2.1.rst b/pypy/doc/release-2.2.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.2.1.rst
@@ -0,0 +1,47 @@
+=======================================
+PyPy 2.2.1 - Incrementalism.1
+=======================================
+
+We're pleased to announce PyPy 2.2.1, which targets version 2.7.3 of the Python
+language. This is a bugfix release over 2.2.
+
+You can download the PyPy 2.2.1 release here:
+
+    http://pypy.org/download.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.2 and cpython 2.7.2`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64, Windows
+32, or ARM (ARMv6 or ARMv7, with VFPv3).
+
+Work on the native Windows 64 is still stalling, we would welcome a volunteer
+to handle that.
+
+.. _`pypy 2.2 and cpython 2.7.2`: http://speed.pypy.org
+
+Highlights
+==========
+
+This is a bugfix release.  The most important bugs fixed are:
+
+* an issue in sockets' reference counting emulation, showing up
+  notably when using the ssl module and calling ``makefile()``.
+
+* Tkinter support on Windows.
+
+* If sys.maxunicode==65535 (on Windows and maybe OS/X), the json
+  decoder incorrectly decoded surrogate pairs.
+
+* some FreeBSD fixes.
+
+Note that CFFI 0.8.1 was released.  Both versions 0.8 and 0.8.1 are
+compatible with both PyPy 2.2 and 2.2.1.
+
+
+Cheers,
+Armin Rigo & everybody
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
@@ -15,3 +15,29 @@
 
 .. branch: armhf-singlefloat
 JIT support for singlefloats on ARM using the hardfloat ABI
+
+.. branch: voidtype_strformat
+Better support for record numpy arrays
+
+.. branch: osx-eci-frameworks-makefile
+OSX: Ensure frameworks end up in Makefile when specified in External compilation info
+
+.. branch: less-stringly-ops
+Use subclasses of SpaceOperation instead of SpaceOperator objects.
+Random cleanups in flowspace and annotator.
+
+.. branch: ndarray-buffer
+adds support for the buffer= argument to the ndarray ctor
+
+.. branch: better_ftime_detect2
+On OpenBSD do not pull in libcompat.a as it is about to be removed.
+And more generally, if you have gettimeofday(2) you will not need ftime(3).
+
+.. branch: timeb_h
+Remove dependency upon <sys/timeb.h> on OpenBSD. This will be disappearing
+along with libcompat.a.
+
+.. branch: OlivierBlanvillain/fix-3-broken-links-on-pypy-published-pap-1386250839215
+Fix 3 broken links on PyPy published papers in docs.
+
+.. branch: jit-ordereddict
diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
--- a/pypy/interpreter/buffer.py
+++ b/pypy/interpreter/buffer.py
@@ -47,6 +47,9 @@
     def get_raw_address(self):
         raise ValueError("no raw buffer")
 
+    def is_writable(self):
+        return False
+
     # __________ app-level support __________
 
     def descr_len(self, space):
@@ -135,6 +138,9 @@
 
     __slots__ = ()     # no extra slot here
 
+    def is_writable(self):
+        return True
+
     def setitem(self, index, char):
         "Write a character into the buffer."
         raise NotImplementedError   # Must be overriden.  No bounds checks.
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -806,8 +806,8 @@
         raise TypeError("Varargs and keywords not supported in unwrap_spec")
     argspec = ', '.join([arg for arg in args.args[1:]])
     func_code = py.code.Source("""
-    def f(w_obj, %(args)s):
-        return w_obj.%(func_name)s(%(args)s)
+    def f(self, %(args)s):
+        return self.%(func_name)s(%(args)s)
     """ % {'args': argspec, 'func_name': func.func_name})
     d = {}
     exec func_code.compile() in d
@@ -822,7 +822,7 @@
     else:
         assert isinstance(unwrap_spec, dict)
         unwrap_spec = unwrap_spec.copy()
-    unwrap_spec['w_obj'] = base_cls
+    unwrap_spec['self'] = base_cls
     return interp2app(globals()['unwrap_spec'](**unwrap_spec)(f))
 
 class interp2app(W_Root):
diff --git a/pypy/module/__builtin__/app_operation.py b/pypy/module/__builtin__/app_operation.py
--- a/pypy/module/__builtin__/app_operation.py
+++ b/pypy/module/__builtin__/app_operation.py
@@ -1,4 +1,5 @@
+import operator
+
 def bin(x):
-    if not isinstance(x, (int, long)):
-        raise TypeError("must be int or long")
-    return x.__format__("#b")
+    value = operator.index(x)
+    return value.__format__("#b")
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -46,6 +46,15 @@
         assert bin(2L) == "0b10"
         assert bin(-2L) == "-0b10"
         raises(TypeError, bin, 0.)
+        class C(object):
+            def __index__(self):
+                return 42
+        assert bin(C()) == bin(42)
+        class D(object):
+            def __int__(self):
+                return 42
+        exc = raises(TypeError, bin, D())
+        assert "index" in exc.value.message
 
     def test_unichr(self):
         import sys
diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -5,7 +5,9 @@
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray
 
+from rpython.rtyper.annlowlevel import llstr
 from rpython.rtyper.lltypesystem import rffi
+from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
 
 
 class LLBuffer(RWBuffer):
@@ -34,8 +36,7 @@
 
     def setslice(self, start, string):
         raw_cdata = rffi.ptradd(self.raw_cdata, start)
-        for i in range(len(string)):
-            raw_cdata[i] = string[i]
+        copy_string_to_raw(llstr(string), raw_cdata, 0, len(string))
 
 
 class MiniBuffer(W_Root):
@@ -59,6 +60,9 @@
     def descr__buffer__(self, space):
         return self.buffer.descr__buffer__(space)
 
+    def descr_str(self, space):
+        return space.wrap(self.buffer.as_str())
+
 
 MiniBuffer.typedef = TypeDef(
     "buffer",
@@ -68,6 +72,7 @@
     __setitem__ = interp2app(MiniBuffer.descr_setitem),
     __buffer__ = interp2app(MiniBuffer.descr__buffer__),
     __weakref__ = make_weakref_descr(MiniBuffer),
+    __str__ = interp2app(MiniBuffer.descr_str),
     )
 MiniBuffer.typedef.acceptable_as_base_class = False
 
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -5,7 +5,7 @@
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 
-from rpython.rlib import objectmodel, rgc
+from rpython.rlib import rgc
 from rpython.rlib.objectmodel import keepalive_until_here, specialize
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.tool.sourcetools import func_with_new_name
@@ -206,8 +206,7 @@
                 w_value.get_array_length() == length):
                 # fast path: copying from exactly the correct type
                 s = w_value._cdata
-                for i in range(ctitemsize * length):
-                    cdata[i] = s[i]
+                rffi.c_memcpy(cdata, s, ctitemsize * length)
                 keepalive_until_here(w_value)
                 return
         #
@@ -259,7 +258,6 @@
         space = self.space
         if isinstance(w_other, W_CData):
             from pypy.module._cffi_backend import ctypeptr, ctypearray
-            from pypy.module._cffi_backend import ctypevoid
             ct = w_other.ctype
             if isinstance(ct, ctypearray.W_CTypeArray):
                 ct = ct.ctptr
@@ -424,6 +422,12 @@
     def get_array_length(self):
         return self.length
 
+    def _sizeof(self):
+        from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
+        ctype = self.ctype
+        assert isinstance(ctype, W_CTypePtrOrArray)
+        return self.length * ctype.ctitem.size
+
 
 class W_CDataHandle(W_CData):
     _attrs_ = ['w_keepalive']
diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py
--- a/pypy/module/_cffi_backend/handle.py
+++ b/pypy/module/_cffi_backend/handle.py
@@ -42,7 +42,7 @@
             if self.handles[d]() is None:
                 self.look_distance = d + 1
                 return d
-        # full! extend, but don't use '!=' here
+        # full! extend, but don't use '+=' here
         self.handles = self.handles + [dead_ref] * (length // 3 + 5)
         self.look_distance = length + 1
         return length
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -2143,7 +2143,13 @@
     c = newp(BCharArray, b"hi there")
     #
     buf = buffer(c)
-    assert str(buf).startswith('<_cffi_backend.buffer object at 0x')
+    assert repr(buf).startswith('<_cffi_backend.buffer object at 0x')
+    assert bytes(buf) == b"hi there\x00"
+    if sys.version_info < (3,):
+        assert str(buf) == "hi there\x00"
+        assert unicode(buf) == u+"hi there\x00"
+    else:
+        assert str(buf) == repr(buf)
     # --mb_length--
     assert len(buf) == len(b"hi there\x00")
     # --mb_item--
@@ -3125,6 +3131,12 @@
     py.test.raises(TypeError, "p + cast(new_primitive_type('int'), 42)")
     py.test.raises(TypeError, "p - cast(new_primitive_type('int'), 42)")
 
+def test_sizeof_sliced_array():
+    BInt = new_primitive_type("int")
+    BArray = new_array_type(new_pointer_type(BInt), 10)
+    p = newp(BArray, None)
+    assert sizeof(p[2:9]) == 7 * sizeof(BInt)
+
 
 def test_version():
     # this test is here mostly for PyPy
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -15,6 +15,7 @@
 from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
 from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
 from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib import rgc
 
 
 class W_Array(W_DataShape):
@@ -220,6 +221,7 @@
     def __init__(self, space, shape, length):
         W_ArrayInstance.__init__(self, space, shape, length, 0)
 
+    @rgc.must_be_light_finalizer
     def __del__(self):
         if self.ll_buffer:
             self._free()
diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -16,7 +16,7 @@
 from pypy.module._rawffi.interp_rawffi import unroll_letters_for_numbers
 from pypy.module._rawffi.interp_rawffi import size_alignment
 from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
-from rpython.rlib import clibffi
+from rpython.rlib import clibffi, rgc
 from rpython.rlib.rarithmetic import intmask, signedtype, widen
 from rpython.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong
 
@@ -226,6 +226,7 @@
                                                            fieldtypes)
         return self.ffi_struct.ffistruct
 
+    @rgc.must_be_light_finalizer
     def __del__(self):
         if self.ffi_struct:
             lltype.free(self.ffi_struct, flavor='raw')
@@ -380,6 +381,7 @@
     def __init__(self, space, shape):
         W_StructureInstance.__init__(self, space, shape, 0)
 
+    @rgc.must_be_light_finalizer
     def __del__(self):
         if self.ll_buffer:
             self._free()
diff --git a/pypy/module/_rawffi/test/test_tracker.py b/pypy/module/_rawffi/test/test_tracker.py
--- a/pypy/module/_rawffi/test/test_tracker.py
+++ b/pypy/module/_rawffi/test/test_tracker.py
@@ -1,9 +1,21 @@
+import py
+from pypy.conftest import option
 from pypy.module._rawffi.tracker import Tracker
 
+
 class AppTestTracker:
     spaceconfig = dict(usemodules=['_rawffi', 'struct'])
 
     def setup_class(cls):
+        #
+        # detect if we're running on PyPy with DO_TRACING not compiled in
+        if option.runappdirect:
+            try:
+                import _rawffi
+                _rawffi._num_of_allocated_objects()
+            except (ImportError, RuntimeError), e:
+                py.test.skip(str(e))
+        #
         Tracker.DO_TRACING = True
 
     def test_array(self):
diff --git a/pypy/module/_rawffi/tracker.py b/pypy/module/_rawffi/tracker.py
--- a/pypy/module/_rawffi/tracker.py
+++ b/pypy/module/_rawffi/tracker.py
@@ -2,9 +2,11 @@
 """ The file that keeps track about freed/kept-alive objects allocated
 by _rawffi. Used for debugging ctypes
 """
+from pypy.interpreter.error import OperationError
+
 
 class Tracker(object):
-    DO_TRACING = True
+    DO_TRACING = False      # make sure this stays False by default!
 
     def __init__(self):
         self.alloced = {}
@@ -20,6 +22,9 @@
 tracker = Tracker()
 
 def num_of_allocated_objects(space):
+    if not tracker.DO_TRACING:
+        raise OperationError(space.w_RuntimeError,
+                             space.wrap("DO_TRACING not enabled in this PyPy"))
     return space.wrap(len(tracker.alloced))
 
 def print_alloced_objects(space):
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
@@ -415,7 +415,13 @@
         except OperationError, e:
             if not e.match(space, space.w_TypeError):
                 raise
-            w_groupnum = space.getitem(self.srepat.w_groupindex, w_arg)
+            try:
+                w_groupnum = space.getitem(self.srepat.w_groupindex, w_arg)
+            except OperationError, e:
+                if not e.match(space, space.w_KeyError):
+                    raise
+                raise OperationError(space.w_IndexError,
+                                     space.wrap("no such group"))
             groupnum = space.int_w(w_groupnum)
         if groupnum == 0:
             return self.ctx.match_start, self.ctx.match_end
diff --git a/pypy/module/_sre/test/test_app_sre.py b/pypy/module/_sre/test/test_app_sre.py
--- a/pypy/module/_sre/test/test_app_sre.py
+++ b/pypy/module/_sre/test/test_app_sre.py
@@ -172,6 +172,9 @@
         assert ("1", "1", None) == m.group(1, 2, 3)
         assert ("1", None) == m.group("first", "second")
         raises(IndexError, m.group, 1, 4)
+        assert ("1", None) == m.group(1, "second")
+        raises(IndexError, m.group, 'foobarbaz')
+        raises(IndexError, m.group, 'first', 'foobarbaz')
 
     def test_expand(self):
         import re
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -711,8 +711,12 @@
             raise ssl_error(space, "SSL_CTX_use_certificate_chain_file error")
 
     # ssl compatibility
-    libssl_SSL_CTX_set_options(ss.ctx, 
-                               SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
+    options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+    if protocol != PY_SSL_VERSION_SSL2:
+        # SSLv2 is extremely broken, don't use it unless a user specifically
+        # requests it
+        options |= SSL_OP_NO_SSLv2
+    libssl_SSL_CTX_set_options(ss.ctx, options)
 
     verification_mode = SSL_VERIFY_NONE
     if cert_mode == PY_SSL_CERT_OPTIONAL:
@@ -724,7 +728,7 @@
     libssl_SSL_set_fd(ss.ssl, sock_fd) # set the socket for SSL
     # The ACCEPT_MOVING_WRITE_BUFFER flag is necessary because the address
     # of a str object may be changed by the garbage collector.
-    libssl_SSL_set_mode(ss.ssl, 
+    libssl_SSL_set_mode(ss.ssl,
                         SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
 
     # If the socket is in non-blocking mode or timeout mode, set the BIO
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -52,6 +52,7 @@
         # weakref callbacks are not invoked eagerly here.  They are
         # invoked by self.__del__() anyway.
 
+    @jit.dont_look_inside
     def get_or_make_weakref(self, w_subtype, w_obj):
         space = self.space
         w_weakreftype = space.gettypeobject(W_Weakref.typedef)
@@ -70,6 +71,7 @@
             self.append_wref_to(w_ref)
         return w_ref
 
+    @jit.dont_look_inside
     def get_or_make_proxy(self, w_obj):
         space = self.space
         if self.cached_proxy is not None:
@@ -122,6 +124,7 @@
                                               W_WeakrefBase.activate_callback,
                                               'weakref callback of ')
 
+    @jit.dont_look_inside
     def make_weakref_with_callback(self, w_subtype, w_obj, w_callable):
         space = self.space
         w_ref = space.allocate_instance(W_Weakref, w_subtype)
@@ -129,6 +132,7 @@
         self.append_wref_to(w_ref)
         return w_ref
 
+    @jit.dont_look_inside
     def make_proxy_with_callback(self, w_obj, w_callable):
         space = self.space
         if space.is_true(space.callable(w_obj)):
@@ -239,15 +243,16 @@
         w_obj.setweakref(space, lifeline)
     return lifeline
 
- at jit.dont_look_inside
+
 def get_or_make_weakref(space, w_subtype, w_obj):
     return getlifeline(space, w_obj).get_or_make_weakref(w_subtype, w_obj)
 
- at jit.dont_look_inside
+
 def make_weakref_with_callback(space, w_subtype, w_obj, w_callable):
     lifeline = getlifelinewithcallbacks(space, w_obj)
     return lifeline.make_weakref_with_callback(w_subtype, w_obj, w_callable)
 
+
 def descr__new__weakref(space, w_subtype, w_obj, w_callable=None,
                         __args__=None):
     if __args__.arguments_w:
@@ -312,15 +317,16 @@
         w_obj = force(space, self)
         return space.call_args(w_obj, __args__)
 
- at jit.dont_look_inside
+
 def get_or_make_proxy(space, w_obj):
     return getlifeline(space, w_obj).get_or_make_proxy(w_obj)
 
- at jit.dont_look_inside
+
 def make_proxy_with_callback(space, w_obj, w_callable):
     lifeline = getlifelinewithcallbacks(space, w_obj)
     return lifeline.make_proxy_with_callback(w_obj, w_callable)
 
+
 def proxy(space, w_obj, w_callable=None):
     """Create a proxy object that weakly references 'obj'.
 'callback', if given, is called with the proxy as an argument when 'obj'
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
@@ -26,6 +26,7 @@
 from pypy.module.__builtin__.descriptor import W_Property
 from pypy.module.__builtin__.interp_classobj import W_ClassObject
 from pypy.module.__builtin__.interp_memoryview import W_MemoryView
+from pypy.module.micronumpy.base import W_NDimArray
 from rpython.rlib.entrypoint import entrypoint_lowlevel
 from rpython.rlib.rposix import is_valid_fd, validate_fd
 from rpython.rlib.unroll import unrolling_iterable
@@ -399,16 +400,16 @@
     '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
 
     'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject',
-    'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', 'init_bufferobject',
+    'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', '_Py_init_bufferobject',
 
     'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr',
     'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
-    'PyCObject_Type', 'init_pycobject',
+    'PyCObject_Type', '_Py_init_pycobject',
 
     'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer',
     'PyCapsule_GetName', 'PyCapsule_GetDestructor', 'PyCapsule_GetContext',
     'PyCapsule_SetPointer', 'PyCapsule_SetName', 'PyCapsule_SetDestructor',
-    'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule',
+    'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', '_Py_init_capsule',
 
     'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
 
@@ -469,6 +470,7 @@
         "Complex": "space.w_complex",
         "ByteArray": "space.w_bytearray",
         "MemoryView": "space.gettypeobject(W_MemoryView.typedef)",
+        "Array": "space.gettypeobject(W_NDimArray.typedef)",
         "BaseObject": "space.w_object",
         'None': 'space.type(space.w_None)',
         'NotImplemented': 'space.type(space.w_NotImplemented)',
@@ -685,11 +687,15 @@
         globals()['va_get_%s' % name_no_star] = func
 
 def setup_init_functions(eci, translating):
-    init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void,
+    if translating:
+        prefix = 'PyPy'
+    else:
+        prefix = 'cpyexttest'
+    init_buffer = rffi.llexternal('_%s_init_bufferobject' % prefix, [], lltype.Void,
                                   compilation_info=eci, _nowrapper=True)
-    init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void,
+    init_pycobject = rffi.llexternal('_%s_init_pycobject' % prefix, [], lltype.Void,
                                      compilation_info=eci, _nowrapper=True)
-    init_capsule = rffi.llexternal('init_capsule', [], lltype.Void,
+    init_capsule = rffi.llexternal('_%s_init_capsule' % prefix, [], lltype.Void,
                                    compilation_info=eci, _nowrapper=True)
     INIT_FUNCTIONS.extend([
         lambda space: init_buffer(),
@@ -697,12 +703,8 @@
         lambda space: init_capsule(),
     ])
     from pypy.module.posix.interp_posix import add_fork_hook
-    if translating:
-        reinit_tls = rffi.llexternal('PyThread_ReInitTLS', [], lltype.Void,
-                                     compilation_info=eci)
-    else:
-        reinit_tls = rffi.llexternal('PyPyThread_ReInitTLS', [], lltype.Void,
-                                     compilation_info=eci)
+    reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], lltype.Void,
+                                 compilation_info=eci)
     add_fork_hook('child', reinit_tls)
 
 def init_function(func):
@@ -744,7 +746,7 @@
     from rpython.translator.c.database import LowLevelDatabase
     db = LowLevelDatabase()
 
-    generate_macros(export_symbols, rename=True, do_deref=True)
+    generate_macros(export_symbols, prefix='cpyexttest')
 
     # Structure declaration code
     members = []
@@ -810,7 +812,7 @@
 
         INTERPLEVEL_API[name] = w_obj
 
-        name = name.replace('Py', 'PyPy')
+        name = name.replace('Py', 'cpyexttest')
         if isptr:
             ptr = ctypes.c_void_p.in_dll(bridge, name)
             if typ == 'PyObject*':
@@ -822,7 +824,7 @@
             ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value),
                                     ctypes.c_void_p).value
         elif typ in ('PyObject*', 'PyTypeObject*'):
-            if name.startswith('PyPyExc_'):
+            if name.startswith('PyPyExc_') or name.startswith('cpyexttestExc_'):
                 # we already have the pointer
                 in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name)
                 py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll)
@@ -857,28 +859,27 @@
     setup_init_functions(eci, translating=False)
     return modulename.new(ext='')
 
-def generate_macros(export_symbols, rename=True, do_deref=True):
+def mangle_name(prefix, name):
+    if name.startswith('Py'):
+        return prefix + name[2:]
+    elif name.startswith('_Py'):
+        return '_' + prefix + name[3:]
+    else:
+        return None
+
+def generate_macros(export_symbols, prefix):
     "NOT_RPYTHON"
     pypy_macros = []
     renamed_symbols = []
     for name in export_symbols:
-        if name.startswith("PyPy"):
-            renamed_symbols.append(name)
-            continue
-        if not rename:
-            continue
         name = name.replace("#", "")
-        newname = name.replace('Py', 'PyPy')
-        if not rename:
-            newname = name
+        newname = mangle_name(prefix, name)
+        assert newname, name
         pypy_macros.append('#define %s %s' % (name, newname))
         if name.startswith("PyExc_"):
             pypy_macros.append('#define _%s _%s' % (name, newname))
         renamed_symbols.append(newname)
-    if rename:
-        export_symbols[:] = renamed_symbols
-    else:
-        export_symbols[:] = [sym.replace("#", "") for sym in export_symbols]
+    export_symbols[:] = renamed_symbols
 
     # Generate defines
     for macro_name, size in [
@@ -1039,7 +1040,7 @@
     from rpython.translator.c.database import LowLevelDatabase
     db = LowLevelDatabase()
 
-    generate_macros(export_symbols, rename=False, do_deref=False)
+    generate_macros(export_symbols, prefix='PyPy')
 
     functions = generate_decls_and_callbacks(db, [], api_struct=False)
     code = "#include <Python.h>\n" + "\n".join(functions)
@@ -1069,7 +1070,8 @@
         export_struct(name, struct)
 
     for name, func in FUNCTIONS.iteritems():
-        deco = entrypoint_lowlevel("cpyext", func.argtypes, name, relax=True)
+        newname = mangle_name('PyPy', name) or name
+        deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, relax=True)
         deco(func.get_wrapper(space))
 
     setup_init_functions(eci, translating=True)
diff --git a/pypy/module/cpyext/include/bufferobject.h b/pypy/module/cpyext/include/bufferobject.h
--- a/pypy/module/cpyext/include/bufferobject.h
+++ b/pypy/module/cpyext/include/bufferobject.h
@@ -37,7 +37,7 @@
 
 PyObject* PyBuffer_New(Py_ssize_t size);
 
-void init_bufferobject(void);
+void _Py_init_bufferobject(void);
 
 #ifdef __cplusplus
 }
diff --git a/pypy/module/cpyext/include/pycapsule.h b/pypy/module/cpyext/include/pycapsule.h
--- a/pypy/module/cpyext/include/pycapsule.h
+++ b/pypy/module/cpyext/include/pycapsule.h
@@ -50,7 +50,7 @@
 
 PyAPI_FUNC(void *) PyCapsule_Import(const char *name, int no_block);
 
-void init_capsule(void);
+void _Py_init_capsule(void);
 
 #ifdef __cplusplus
 }
diff --git a/pypy/module/cpyext/include/pycobject.h b/pypy/module/cpyext/include/pycobject.h
--- a/pypy/module/cpyext/include/pycobject.h
+++ b/pypy/module/cpyext/include/pycobject.h
@@ -48,7 +48,7 @@
 } PyCObject;
 #endif
 
-void init_pycobject(void);
+void _Py_init_pycobject(void);
  
 #ifdef __cplusplus
 }
diff --git a/pypy/module/cpyext/include/pyconfig.h b/pypy/module/cpyext/include/pyconfig.h
--- a/pypy/module/cpyext/include/pyconfig.h
+++ b/pypy/module/cpyext/include/pyconfig.h
@@ -25,6 +25,22 @@
 #define Py_UNICODE_SIZE 2
 #endif
 
+#ifndef Py_BUILD_CORE /* not building the core - must be an ext */
+#    if defined(_MSC_VER)
+     /* So MSVC users need not specify the .lib file in
+      * their Makefile (other compilers are generally
+      * taken care of by distutils.) */
+#        ifdef _DEBUG
+#            error("debug first with cpython")    
+#            pragma comment(lib,"python27.lib")
+#        else
+#            pragma comment(lib,"python27.lib")
+#        endif /* _DEBUG */
+#    endif
+#endif /* _MSC_VER */
+
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/src/bufferobject.c b/pypy/module/cpyext/src/bufferobject.c
--- a/pypy/module/cpyext/src/bufferobject.c
+++ b/pypy/module/cpyext/src/bufferobject.c
@@ -783,7 +783,7 @@
     return size;
 }
 
-void init_bufferobject(void)
+void _Py_init_bufferobject(void)
 {
     PyType_Ready(&PyBuffer_Type);
 }
diff --git a/pypy/module/cpyext/src/capsule.c b/pypy/module/cpyext/src/capsule.c
--- a/pypy/module/cpyext/src/capsule.c
+++ b/pypy/module/cpyext/src/capsule.c
@@ -321,7 +321,7 @@
     PyCapsule_Type__doc__	/*tp_doc*/
 };
 
-void init_capsule()
+void _Py_init_capsule()
 {
     PyType_Ready(&PyCapsule_Type);
 }
diff --git a/pypy/module/cpyext/src/cobject.c b/pypy/module/cpyext/src/cobject.c
--- a/pypy/module/cpyext/src/cobject.c
+++ b/pypy/module/cpyext/src/cobject.c
@@ -156,7 +156,7 @@
     PyCObject_Type__doc__	/*tp_doc*/
 };
 
-void init_pycobject()
+void _Py_init_pycobject()
 {
     PyType_Ready(&PyCObject_Type);
 }
diff --git a/pypy/module/cpyext/src/ndarrayobject.c b/pypy/module/cpyext/src/ndarrayobject.c
--- a/pypy/module/cpyext/src/ndarrayobject.c
+++ b/pypy/module/cpyext/src/ndarrayobject.c
@@ -3,8 +3,6 @@
 #include "numpy/arrayobject.h"
 #include <string.h>   /* memset, memcpy */
 
-PyTypeObject PyArray_Type;
-
 void 
 _PyArray_FILLWBYTE(PyObject* obj, int val) {
     memset(PyArray_DATA(obj), val, PyArray_NBYTES(obj));
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -286,3 +286,19 @@
         assert dt.num == 11
 
 
+    def test_pass_ndarray_object_to_c(self):
+        from _numpypy.multiarray import ndarray
+        mod = self.import_extension('foo', [
+                ("check_array", "METH_VARARGS",
+                '''
+                    PyObject* obj;
+                    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &obj))
+                        return NULL;
+                    Py_INCREF(obj);
+                    return obj;
+                '''),
+                ], prologue='#include <numpy/arrayobject.h>')
+        array = ndarray((3, 4), dtype='d')
+        assert mod.check_array(array) is array
+        raises(TypeError, "mod.check_array(42)")
+        
diff --git a/pypy/module/cpyext/test/test_thread.py b/pypy/module/cpyext/test/test_thread.py
--- a/pypy/module/cpyext/test/test_thread.py
+++ b/pypy/module/cpyext/test/test_thread.py
@@ -8,8 +8,10 @@
         module = self.import_extension('foo', [
             ("get_thread_ident", "METH_NOARGS",
              """
-                 /* Use the 'PyPy' prefix to ensure we access our functions */
-                 return PyInt_FromLong(PyPyThread_get_thread_ident());
+#ifndef PyThread_get_thread_ident
+#error "seems we are not accessing PyPy's functions"
+#endif
+                 return PyInt_FromLong(PyThread_get_thread_ident());
              """),
             ])
         import thread, threading
@@ -32,17 +34,19 @@
         module = self.import_extension('foo', [
             ("test_acquire_lock", "METH_NOARGS",
              """
-                 /* Use the 'PyPy' prefix to ensure we access our functions */
-                 PyThread_type_lock lock = PyPyThread_allocate_lock();
-                 if (PyPyThread_acquire_lock(lock, 1) != 1) {
+#ifndef PyThread_allocate_lock
+#error "seems we are not accessing PyPy's functions"
+#endif
+                 PyThread_type_lock lock = PyThread_allocate_lock();
+                 if (PyThread_acquire_lock(lock, 1) != 1) {
                      PyErr_SetString(PyExc_AssertionError, "first acquire");
                      return NULL;
                  }
-                 if (PyPyThread_acquire_lock(lock, 0) != 0) {
+                 if (PyThread_acquire_lock(lock, 0) != 0) {
                      PyErr_SetString(PyExc_AssertionError, "second acquire");
                      return NULL;
                  }
-                 PyPyThread_free_lock(lock);
+                 PyThread_free_lock(lock);
 
                  Py_RETURN_NONE;
              """),
@@ -53,15 +57,17 @@
         module = self.import_extension('foo', [
             ("test_release_lock", "METH_NOARGS",
              """
-                 /* Use the 'PyPy' prefix to ensure we access our functions */
-                 PyThread_type_lock lock = PyPyThread_allocate_lock();
-                 PyPyThread_acquire_lock(lock, 1);
-                 PyPyThread_release_lock(lock);
-                 if (PyPyThread_acquire_lock(lock, 0) != 1) {
+#ifndef PyThread_release_lock
+#error "seems we are not accessing PyPy's functions"
+#endif           
+                 PyThread_type_lock lock = PyThread_allocate_lock();
+                 PyThread_acquire_lock(lock, 1);
+                 PyThread_release_lock(lock);
+                 if (PyThread_acquire_lock(lock, 0) != 1) {
                      PyErr_SetString(PyExc_AssertionError, "first acquire");
                      return NULL;
                  }
-                 PyPyThread_free_lock(lock);
+                 PyThread_free_lock(lock);
 
                  Py_RETURN_NONE;
              """),
diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -342,10 +342,8 @@
             if space.is_w(w_startstop, space.w_None):
                 start = 0
             else:
-                start = space.int_w(w_startstop)
-                if start < 0:
-                    raise OperationError(space.w_ValueError, space.wrap(
-                       "Indicies for islice() must be non-negative integers."))
+                start = self.arg_int_w(w_startstop, 0,
+                 "Indicies for islice() must be None or non-negative integers")
             w_stop = args_w[0]
         else:
             raise OperationError(space.w_TypeError, space.wrap("islice() takes at most 4 arguments (" + str(num_args) + " given)"))
@@ -353,10 +351,8 @@
         if space.is_w(w_stop, space.w_None):
             stop = -1
         else:
-            stop = space.int_w(w_stop)
-            if stop < 0:
-                raise OperationError(space.w_ValueError, space.wrap(
-                    "Stop argument must be a non-negative integer or None."))
+            stop = self.arg_int_w(w_stop, 0,
+                "Stop argument must be a non-negative integer or None.")
             stop = max(start, stop)    # for obscure CPython compatibility
 
         if num_args == 2:
@@ -364,10 +360,8 @@
             if space.is_w(w_step, space.w_None):
                 step = 1
             else:
-                step = space.int_w(w_step)
-                if step < 1:
-                    raise OperationError(space.w_ValueError, space.wrap(
-                        "Step must be one or lager for islice()."))
+                step = self.arg_int_w(w_step, 1,
+                    "Step for islice() must be a positive integer or None")
         else:
             step = 1
 
@@ -375,6 +369,18 @@
         self.start = start
         self.stop = stop
 
+    def arg_int_w(self, w_obj, minimum, errormsg):
+        space = self.space
+        try:
+            result = space.int_w(w_obj)
+        except OperationError, e:
+            if e.async(space):
+                raise
+            result = -1
+        if result < minimum:
+            raise OperationError(space.w_ValueError, space.wrap(errormsg))
+        return result
+
     def iter_w(self):
         return self.space.wrap(self)
 
diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -304,6 +304,11 @@
 
         raises(TypeError, itertools.islice, [], 0, 0, 0, 0)
 
+        # why not TypeError? Because CPython
+        raises(ValueError, itertools.islice, [], "a", 1, 2)
+        raises(ValueError, itertools.islice, [], 0, "a", 2)
+        raises(ValueError, itertools.islice, [], 0, 1, "a")
+
     def test_chain(self):
         import itertools
         
diff --git a/pypy/module/math/app_math.py b/pypy/module/math/app_math.py
--- a/pypy/module/math/app_math.py
+++ b/pypy/module/math/app_math.py
@@ -1,13 +1,40 @@
 def factorial(x):
-    """Find x!."""
+    """factorial(x) -> Integral
+
+    "Find x!. Raise a ValueError if x is negative or non-integral."""
     if isinstance(x, float):
         fl = int(x)
         if fl != x:
             raise ValueError("float arguments must be integral")
         x = fl
-    if x < 0:
-        raise ValueError("x must be >= 0")
-    res = 1
-    for i in range(1, x + 1):
-        res *= i
-    return res
+
+    if x <= 100:
+        if x < 0:
+            raise ValueError("x must be >= 0")
+        res = 1
+        for i in range(2, x + 1):
+            res *= i
+        return res
+
+    # Experimentally this gap seems good
+    gap = max(100, x >> 7)
+    def _fac_odd(low, high):
+        if low + gap >= high:
+            t = 1
+            for i in range(low, high, 2):
+                t *= i
+            return t
+
+        mid = ((low + high) >> 1) | 1
+        return _fac_odd(low, mid) * _fac_odd(mid, high)
+
+    def _fac1(x):
+        if x <= 2:
+            return 1, 1, x - 1
+        x2 = x >> 1
+        f, g, shift = _fac1(x2)
+        g *= _fac_odd((x2 + 1) | 1, x + 1)
+        return (f * g, g, shift + x2)
+
+    res, _, shift = _fac1(x)
+    return res << shift
diff --git a/pypy/module/math/test/test_factorial.py b/pypy/module/math/test/test_factorial.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/math/test/test_factorial.py
@@ -0,0 +1,29 @@
+import py
+import math
+from pypy.module.math import app_math
+
+def test_factorial_extra():
+    for x in range(1000):
+        r1 = app_math.factorial(x)
+        r2 = math.factorial(x)
+        assert r1 == r2
+        assert type(r1) == type(r2)
+
+def test_timing():
+    py.test.skip("for manual running only")
+    import time
+    x = 5000
+    repeat = 1000
+    r1 = app_math.factorial(x)
+    r2 = math.factorial(x)
+    assert r1 == r2
+    t1 = time.time()
+    for i in range(repeat):
+        app_math.factorial(x)
+    t2 = time.time()
+    for i in range(repeat):
+        math.factorial(x)
+    t3 = time.time()
+    assert r1 == r2
+    print (t2 - t1) / repeat
+    print (t3 - t2) / repeat
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
@@ -10,7 +10,7 @@
         'array': 'interp_numarray.array',
         'zeros': 'interp_numarray.zeros',
         'empty': 'interp_numarray.zeros',
-        'ones': 'interp_numarray.ones',
+        'empty_like': 'interp_numarray.empty_like',
         '_reconstruct' : 'interp_numarray._reconstruct',
         'scalar' : 'interp_numarray.build_scalar',
         'dot': 'interp_arrayops.dot',
@@ -106,8 +106,6 @@
         ('logaddexp2', 'logaddexp2'),
         ('real', 'real'),
         ('imag', 'imag'),
-        ('ones_like', 'ones_like'),
-        ('zeros_like', 'zeros_like'),
     ]:
         interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
 
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
@@ -12,7 +12,9 @@
     if dtype is None:
         test = _numpypy.multiarray.array([start, stop, step, 0])
         dtype = test.dtype
-    arr = _numpypy.multiarray.zeros(int(math.ceil((stop - start) / step)), dtype=dtype)
+    length = math.ceil((float(stop) - start) / step)
+    length = int(length)
+    arr = _numpypy.multiarray.zeros(length, dtype=dtype)
     i = start
     for j in range(arr.size):
         arr[j] = i
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -47,7 +47,7 @@
     def setslice(self, space, arr):
         impl = arr.implementation
         if impl.is_scalar():
-            self.fill(impl.get_scalar_value())
+            self.fill(space, impl.get_scalar_value())
             return
         shape = shape_agreement(space, self.get_shape(), arr)
         if impl.storage == self.storage:
@@ -100,7 +100,7 @@
         tmp = self.get_real(orig_array)
         tmp.setslice(space, convert_to_array(space, w_value))
 
-    def get_imag(self, orig_array):
+    def get_imag(self, space, orig_array):
         strides = self.get_strides()
         backstrides = self.get_backstrides()
         if self.dtype.is_complex_type():
@@ -110,11 +110,11 @@
         impl = NonWritableArray(self.get_shape(), self.dtype, self.order, strides,
                              backstrides)
         if not self.dtype.is_flexible_type():
-            impl.fill(self.dtype.box(0))
+            impl.fill(space, self.dtype.box(0))
         return impl
 
     def set_imag(self, space, orig_array, w_value):
-        tmp = self.get_imag(orig_array)
+        tmp = self.get_imag(space, orig_array)
         tmp.setslice(space, convert_to_array(space, w_value))
 
     # -------------------- applevel get/setitem -----------------------
@@ -357,7 +357,7 @@
                                          self.get_backstrides(),
                                          self.get_shape())
 
-    def fill(self, box):
+    def fill(self, space, box):
         self.dtype.itemtype.fill(self.storage, self.dtype.get_size(),
                                  box, 0, self.size, 0)
 
@@ -392,6 +392,21 @@
     def __del__(self):
         free_raw_storage(self.storage, track_allocation=False)
 
+class ConcreteArrayWithBase(ConcreteArrayNotOwning):
+    def __init__(self, shape, dtype, order, strides, backstrides, storage, orig_base):
+        ConcreteArrayNotOwning.__init__(self, shape, dtype, order,
+                                        strides, backstrides, storage)
+        self.orig_base = orig_base
+
+    def base(self):
+        return self.orig_base
+
+
+class ConcreteNonWritableArrayWithBase(ConcreteArrayWithBase):
+    def descr_setitem(self, space, orig_array, w_index, w_value):
+        raise OperationError(space.w_ValueError, space.wrap(
+            "assignment destination is read-only"))
+
 
 class NonWritableArray(ConcreteArray):
     def descr_setitem(self, space, orig_array, w_index, w_value):
@@ -420,8 +435,8 @@
     def base(self):
         return self.orig_arr
 
-    def fill(self, box):
-        loop.fill(self, box.convert_to(self.dtype))
+    def fill(self, space, box):
+        loop.fill(self, box.convert_to(space, self.dtype))
 
     def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
         if shape is not None and \
@@ -487,3 +502,6 @@
 
     def getlength(self):
         return self.impl.size
+
+    def get_raw_address(self):
+        return self.impl.storage
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -54,8 +54,7 @@
         return self.value
 
     def set_scalar_value(self, w_val):
-        assert isinstance(w_val, W_GenericBox)
-        self.value = w_val.convert_to(self.dtype)
+        self.value = w_val
 
     def copy(self, space):
         scalar = Scalar(self.dtype)
@@ -96,12 +95,12 @@
                     ','.join([str(x) for x in w_arr.get_shape()],))))
         if self.dtype.is_complex_type():
             self.value = self.dtype.itemtype.composite(
-                               w_arr.get_scalar_value().convert_to(dtype),
+                               w_arr.get_scalar_value().convert_to(space, dtype),
                                self.value.convert_imag_to(dtype))
         else:
             self.value = w_arr.get_scalar_value()
 
-    def get_imag(self, orig_array):
+    def get_imag(self, space, orig_array):
         if self.dtype.is_complex_type():
             scalar = Scalar(self.dtype.float_type)
             scalar.value = self.value.convert_imag_to(scalar.dtype)
@@ -125,13 +124,23 @@
                     ','.join([str(x) for x in w_arr.get_shape()],))))
         self.value = self.dtype.itemtype.composite(
                             self.value.convert_real_to(dtype),
-                            w_arr.get_scalar_value().convert_to(dtype),
+                            w_arr.get_scalar_value().convert_to(space, dtype),
                             )
 
     def descr_getitem(self, space, _, w_idx):
         if space.isinstance_w(w_idx, space.w_tuple):
             if space.len_w(w_idx) == 0:
                 return self.get_scalar_value()
+        elif space.isinstance_w(w_idx, space.w_str):
+            if self.dtype.is_record_type():
+                w_val = self.value.descr_getitem(space, w_idx)
+                return convert_to_array(space, w_val)
+        elif space.is_none(w_idx):
+            new_shape = [1]
+            arr = W_NDimArray.from_shape(space, new_shape, self.dtype)
+            arr_iter = arr.create_iter(new_shape)
+            arr_iter.setitem(self.value)
+            return arr


More information about the pypy-commit mailing list