[pypy-commit] pypy py3k: hg merge default

amauryfa noreply at buildbot.pypy.org
Sun Jan 29 23:51:06 CET 2012


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r51961:a5bd7b8f5f80
Date: 2012-01-29 23:50 +0100
http://bitbucket.org/pypy/pypy/changeset/a5bd7b8f5f80/

Log:	hg merge default

diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -20,6 +20,8 @@
 # 2. Altered source versions must be plainly marked as such, and must not be
 #    misrepresented as being the original software.
 # 3. This notice may not be removed or altered from any source distribution.
+#
+# Note: This software has been modified for use in PyPy.
 
 from ctypes import c_void_p, c_int, c_double, c_int64, c_char_p, cdll
 from ctypes import POINTER, byref, string_at, CFUNCTYPE, cast
@@ -27,7 +29,6 @@
 from collections import OrderedDict
 import datetime
 import sys
-import time
 import weakref
 from threading import _get_ident as thread_get_ident
 
@@ -606,7 +607,7 @@
             def authorizer(userdata, action, arg1, arg2, dbname, source):
                 try:
                     return int(callback(action, arg1, arg2, dbname, source))
-                except Exception as e:
+                except Exception:
                     return SQLITE_DENY
             c_authorizer = AUTHORIZER(authorizer)
 
@@ -653,7 +654,7 @@
                 if not aggregate_ptr[0]:
                     try:
                         aggregate = cls()
-                    except Exception as e:
+                    except Exception:
                         msg = ("user-defined aggregate's '__init__' "
                                "method raised error")
                         sqlite.sqlite3_result_error(context, msg, len(msg))
@@ -667,7 +668,7 @@
                 params = _convert_params(context, argc, c_params)
                 try:
                     aggregate.step(*params)
-                except Exception as e:
+                except Exception:
                     msg = ("user-defined aggregate's 'step' "
                            "method raised error")
                     sqlite.sqlite3_result_error(context, msg, len(msg))
@@ -683,7 +684,7 @@
                     aggregate = self.aggregate_instances[aggregate_ptr[0]]
                     try:
                         val = aggregate.finalize()
-                    except Exception as e:
+                    except Exception:
                         msg = ("user-defined aggregate's 'finalize' "
                                "method raised error")
                         sqlite.sqlite3_result_error(context, msg, len(msg))
@@ -771,7 +772,7 @@
             self.statement.item = None
             self.statement.exhausted = True
 
-        if self.statement.kind == DML or self.statement.kind == DDL:
+        if self.statement.kind == DML:
             self.statement.reset()
 
         self.rowcount = -1
@@ -861,8 +862,6 @@
         except StopIteration:
             return None
 
-        return nextrow
-
     def fetchmany(self, size=None):
         self._check_closed()
         self._check_reset()
@@ -1050,7 +1049,7 @@
                 param_name = param_name[1:]
                 try:
                     param = params[param_name]
-                except KeyError as e:
+                except KeyError:
                     raise ProgrammingError("missing parameter '%s'" %param)
                 self.set_param(idx, param)
 
@@ -1261,7 +1260,7 @@
     params = _convert_params(context, nargs, c_params)
     try:
         val = real_cb(*params)
-    except Exception as e:
+    except Exception:
         msg = "user-defined function raised exception"
         sqlite.sqlite3_result_error(context, msg, len(msg))
     else:
diff --git a/lib_pypy/numpypy/core/__init__.py b/lib_pypy/numpypy/core/__init__.py
--- a/lib_pypy/numpypy/core/__init__.py
+++ b/lib_pypy/numpypy/core/__init__.py
@@ -1,1 +1,2 @@
 from .fromnumeric import *
+from .numeric import *
diff --git a/lib_pypy/numpypy/core/_methods.py b/lib_pypy/numpypy/core/_methods.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/_methods.py
@@ -0,0 +1,98 @@
+# Array methods which are called by the both the C-code for the method
+# and the Python code for the NumPy-namespace function
+
+import _numpypy as mu
+um = mu
+#from numpypy.core import umath as um
+from numpypy.core.numeric import asanyarray
+
+def _amax(a, axis=None, out=None, skipna=False, keepdims=False):
+    return um.maximum.reduce(a, axis=axis,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _amin(a, axis=None, out=None, skipna=False, keepdims=False):
+    return um.minimum.reduce(a, axis=axis,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _sum(a, axis=None, dtype=None, out=None, skipna=False, keepdims=False):
+    return um.add.reduce(a, axis=axis, dtype=dtype,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _prod(a, axis=None, dtype=None, out=None, skipna=False, keepdims=False):
+    return um.multiply.reduce(a, axis=axis, dtype=dtype,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _mean(a, axis=None, dtype=None, out=None, skipna=False, keepdims=False):
+    arr = asanyarray(a)
+
+    # Upgrade bool, unsigned int, and int to float64
+    if dtype is None and arr.dtype.kind in ['b','u','i']:
+        ret = um.add.reduce(arr, axis=axis, dtype='f8',
+                            out=out, skipna=skipna, keepdims=keepdims)
+    else:
+        ret = um.add.reduce(arr, axis=axis, dtype=dtype,
+                            out=out, skipna=skipna, keepdims=keepdims)
+    rcount = mu.count_reduce_items(arr, axis=axis,
+                            skipna=skipna, keepdims=keepdims)
+    if isinstance(ret, mu.ndarray):
+        ret = um.true_divide(ret, rcount,
+                        casting='unsafe', subok=False)
+    else:
+        ret = ret / float(rcount)
+    return ret
+
+def _var(a, axis=None, dtype=None, out=None, ddof=0,
+                            skipna=False, keepdims=False):
+    arr = asanyarray(a)
+
+    # First compute the mean, saving 'rcount' for reuse later
+    if dtype is None and arr.dtype.kind in ['b','u','i']:
+        arrmean = um.add.reduce(arr, axis=axis, dtype='f8',
+                            skipna=skipna, keepdims=True)
+    else:
+        arrmean = um.add.reduce(arr, axis=axis, dtype=dtype,
+                            skipna=skipna, keepdims=True)
+    rcount = mu.count_reduce_items(arr, axis=axis,
+                            skipna=skipna, keepdims=True)
+    if isinstance(arrmean, mu.ndarray):
+        arrmean = um.true_divide(arrmean, rcount,
+                                  casting='unsafe', subok=False)
+    else:
+        arrmean = arrmean / float(rcount)
+
+    # arr - arrmean
+    x = arr - arrmean
+
+    # (arr - arrmean) ** 2
+    if arr.dtype.kind == 'c':
+        x = um.multiply(x, um.conjugate(x)).real
+    else:
+        x = um.multiply(x, x)
+
+    # add.reduce((arr - arrmean) ** 2, axis)
+    ret = um.add.reduce(x, axis=axis, dtype=dtype, out=out,
+                        skipna=skipna, keepdims=keepdims)
+
+    # add.reduce((arr - arrmean) ** 2, axis) / (n - ddof)
+    if not keepdims and isinstance(rcount, mu.ndarray):
+        rcount = rcount.squeeze(axis=axis)
+    rcount -= ddof
+    if isinstance(ret, mu.ndarray):
+        ret = um.true_divide(ret, rcount,
+                        casting='unsafe', subok=False)
+    else:
+        ret = ret / float(rcount)
+
+    return ret
+
+def _std(a, axis=None, dtype=None, out=None, ddof=0,
+                            skipna=False, keepdims=False):
+    ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
+                                skipna=skipna, keepdims=keepdims)
+
+    if isinstance(ret, mu.ndarray):
+        ret = um.sqrt(ret)
+    else:
+        ret = um.sqrt(ret)
+
+    return ret
diff --git a/lib_pypy/numpypy/core/arrayprint.py b/lib_pypy/numpypy/core/arrayprint.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/arrayprint.py
@@ -0,0 +1,789 @@
+"""Array printing function
+
+$Id: arrayprint.py,v 1.9 2005/09/13 13:58:44 teoliphant Exp $
+"""
+__all__ = ["array2string", "set_printoptions", "get_printoptions"]
+__docformat__ = 'restructuredtext'
+
+#
+# Written by Konrad Hinsen <hinsenk at ere.umontreal.ca>
+# last revision: 1996-3-13
+# modified by Jim Hugunin 1997-3-3 for repr's and str's (and other details)
+# and by Perry Greenfield 2000-4-1 for numarray
+# and by Travis Oliphant  2005-8-22 for numpy
+
+import sys
+import _numpypy as _nt
+from _numpypy import maximum, minimum, absolute, not_equal, isinf, isnan, isna
+#from _numpypy import format_longfloat, datetime_as_string, datetime_data
+from .fromnumeric import ravel
+
+
+def product(x, y): return x*y
+
+_summaryEdgeItems = 3     # repr N leading and trailing items of each dimension
+_summaryThreshold = 1000 # total items > triggers array summarization
+
+_float_output_precision = 8
+_float_output_suppress_small = False
+_line_width = 75
+_nan_str = 'nan'
+_inf_str = 'inf'
+_na_str = 'NA'
+_formatter = None  # formatting function for array elements
+
+if sys.version_info[0] >= 3:
+    from functools import reduce
+
+def set_printoptions(precision=None, threshold=None, edgeitems=None,
+                     linewidth=None, suppress=None,
+                     nanstr=None, infstr=None, nastr=None,
+                     formatter=None):
+    """
+    Set printing options.
+
+    These options determine the way floating point numbers, arrays and
+    other NumPy objects are displayed.
+
+    Parameters
+    ----------
+    precision : int, optional
+        Number of digits of precision for floating point output (default 8).
+    threshold : int, optional
+        Total number of array elements which trigger summarization
+        rather than full repr (default 1000).
+    edgeitems : int, optional
+        Number of array items in summary at beginning and end of
+        each dimension (default 3).
+    linewidth : int, optional
+        The number of characters per line for the purpose of inserting
+        line breaks (default 75).
+    suppress : bool, optional
+        Whether or not suppress printing of small floating point values
+        using scientific notation (default False).
+    nanstr : str, optional
+        String representation of floating point not-a-number (default nan).
+    infstr : str, optional
+        String representation of floating point infinity (default inf).
+    nastr : str, optional
+        String representation of NA missing value (default NA).
+    formatter : dict of callables, optional
+        If not None, the keys should indicate the type(s) that the respective
+        formatting function applies to.  Callables should return a string.
+        Types that are not specified (by their corresponding keys) are handled
+        by the default formatters.  Individual types for which a formatter
+        can be set are::
+
+            - 'bool'
+            - 'int'
+            - 'timedelta' : a `numpy.timedelta64`
+            - 'datetime' : a `numpy.datetime64`
+            - 'float'
+            - 'longfloat' : 128-bit floats
+            - 'complexfloat'
+            - 'longcomplexfloat' : composed of two 128-bit floats
+            - 'numpy_str' : types `numpy.string_` and `numpy.unicode_`
+            - 'str' : all other strings
+
+        Other keys that can be used to set a group of types at once are::
+
+            - 'all' : sets all types
+            - 'int_kind' : sets 'int'
+            - 'float_kind' : sets 'float' and 'longfloat'
+            - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
+            - 'str_kind' : sets 'str' and 'numpystr'
+
+    See Also
+    --------
+    get_printoptions, set_string_function, array2string
+
+    Notes
+    -----
+    `formatter` is always reset with a call to `set_printoptions`.
+
+    Examples
+    --------
+    Floating point precision can be set:
+
+    >>> np.set_printoptions(precision=4)
+    >>> print np.array([1.123456789])
+    [ 1.1235]
+
+    Long arrays can be summarised:
+
+    >>> np.set_printoptions(threshold=5)
+    >>> print np.arange(10)
+    [0 1 2 ..., 7 8 9]
+
+    Small results can be suppressed:
+
+    >>> eps = np.finfo(float).eps
+    >>> x = np.arange(4.)
+    >>> x**2 - (x + eps)**2
+    array([ -4.9304e-32,  -4.4409e-16,   0.0000e+00,   0.0000e+00])
+    >>> np.set_printoptions(suppress=True)
+    >>> x**2 - (x + eps)**2
+    array([-0., -0.,  0.,  0.])
+
+    A custom formatter can be used to display array elements as desired:
+
+    >>> np.set_printoptions(formatter={'all':lambda x: 'int: '+str(-x)})
+    >>> x = np.arange(3)
+    >>> x
+    array([int: 0, int: -1, int: -2])
+    >>> np.set_printoptions()  # formatter gets reset
+    >>> x
+    array([0, 1, 2])
+
+    To put back the default options, you can use:
+
+    >>> np.set_printoptions(edgeitems=3,infstr='inf',
+    ... linewidth=75, nanstr='nan', precision=8,
+    ... suppress=False, threshold=1000, formatter=None)
+    """
+
+    global _summaryThreshold, _summaryEdgeItems, _float_output_precision, \
+           _line_width, _float_output_suppress_small, _nan_str, _inf_str, \
+           _na_str, _formatter
+    if linewidth is not None:
+        _line_width = linewidth
+    if threshold is not None:
+        _summaryThreshold = threshold
+    if edgeitems is not None:
+        _summaryEdgeItems = edgeitems
+    if precision is not None:
+        _float_output_precision = precision
+    if suppress is not None:
+        _float_output_suppress_small = not not suppress
+    if nanstr is not None:
+        _nan_str = nanstr
+    if infstr is not None:
+        _inf_str = infstr
+    if nastr is not None:
+        _na_str = nastr
+    _formatter = formatter
+
+def get_printoptions():
+    """
+    Return the current print options.
+
+    Returns
+    -------
+    print_opts : dict
+        Dictionary of current print options with keys
+
+          - precision : int
+          - threshold : int
+          - edgeitems : int
+          - linewidth : int
+          - suppress : bool
+          - nanstr : str
+          - infstr : str
+          - formatter : dict of callables
+
+        For a full description of these options, see `set_printoptions`.
+
+    See Also
+    --------
+    set_printoptions, set_string_function
+
+    """
+    d = dict(precision=_float_output_precision,
+             threshold=_summaryThreshold,
+             edgeitems=_summaryEdgeItems,
+             linewidth=_line_width,
+             suppress=_float_output_suppress_small,
+             nanstr=_nan_str,
+             infstr=_inf_str,
+             nastr=_na_str,
+             formatter=_formatter)
+    return d
+
+def _leading_trailing(a):
+    import numeric as _nc
+    if a.ndim == 1:
+        if len(a) > 2*_summaryEdgeItems:
+            b = _nc.concatenate((a[:_summaryEdgeItems],
+                                     a[-_summaryEdgeItems:]))
+        else:
+            b = a
+    else:
+        if len(a) > 2*_summaryEdgeItems:
+            l = [_leading_trailing(a[i]) for i in range(
+                min(len(a), _summaryEdgeItems))]
+            l.extend([_leading_trailing(a[-i]) for i in range(
+                min(len(a), _summaryEdgeItems),0,-1)])
+        else:
+            l = [_leading_trailing(a[i]) for i in range(0, len(a))]
+        b = _nc.concatenate(tuple(l))
+    return b
+
+def _boolFormatter(x):
+    if isna(x):
+        return str(x).replace('NA', _na_str, 1)
+    elif x:
+        return ' True'
+    else:
+        return 'False'
+
+
+def repr_format(x):
+    if isna(x):
+        return str(x).replace('NA', _na_str, 1)
+    else:
+        return repr(x)
+
+def _array2string(a, max_line_width, precision, suppress_small, separator=' ',
+                  prefix="", formatter=None):
+
+    if max_line_width is None:
+        max_line_width = _line_width
+
+    if precision is None:
+        precision = _float_output_precision
+
+    if suppress_small is None:
+        suppress_small = _float_output_suppress_small
+
+    if formatter is None:
+        formatter = _formatter
+
+    if a.size > _summaryThreshold:
+        summary_insert = "..., "
+        data = _leading_trailing(a)
+    else:
+        summary_insert = ""
+        data = ravel(a)
+
+    formatdict = {'bool' : _boolFormatter,
+                  'int' : IntegerFormat(data),
+                  'float' : FloatFormat(data, precision, suppress_small),
+                  'longfloat' : LongFloatFormat(precision),
+                  #'complexfloat' : ComplexFormat(data, precision,
+                  #                               suppress_small),
+                  #'longcomplexfloat' : LongComplexFormat(precision),
+                  #'datetime' : DatetimeFormat(data),
+                  #'timedelta' : TimedeltaFormat(data),
+                  'numpystr' : repr_format,
+                  'str' : str}
+
+    if formatter is not None:
+        fkeys = [k for k in formatter.keys() if formatter[k] is not None]
+        if 'all' in fkeys:
+            for key in formatdict.keys():
+                formatdict[key] = formatter['all']
+        if 'int_kind' in fkeys:
+            for key in ['int']:
+                formatdict[key] = formatter['int_kind']
+        if 'float_kind' in fkeys:
+            for key in ['float', 'longfloat']:
+                formatdict[key] = formatter['float_kind']
+        if 'complex_kind' in fkeys:
+            for key in ['complexfloat', 'longcomplexfloat']:
+                formatdict[key] = formatter['complex_kind']
+        if 'str_kind' in fkeys:
+            for key in ['numpystr', 'str']:
+                formatdict[key] = formatter['str_kind']
+        for key in formatdict.keys():
+            if key in fkeys:
+                formatdict[key] = formatter[key]
+
+    try:
+        format_function = a._format
+        msg = "The `_format` attribute is deprecated in Numpy 2.0 and " \
+              "will be removed in 2.1. Use the `formatter` kw instead."
+        import warnings
+        warnings.warn(msg, DeprecationWarning)
+    except AttributeError:
+        # find the right formatting function for the array
+        dtypeobj = a.dtype.type
+        if issubclass(dtypeobj, _nt.bool_):
+            format_function = formatdict['bool']
+        elif issubclass(dtypeobj, _nt.integer):
+            #if issubclass(dtypeobj, _nt.timedelta64):
+            #    format_function = formatdict['timedelta']
+            #else:
+            format_function = formatdict['int']
+        elif issubclass(dtypeobj, _nt.floating):
+            #if issubclass(dtypeobj, _nt.longfloat):
+            #    format_function = formatdict['longfloat']
+            #else:
+            format_function = formatdict['float']
+        elif issubclass(dtypeobj, _nt.complexfloating):
+            if issubclass(dtypeobj, _nt.clongfloat):
+                format_function = formatdict['longcomplexfloat']
+            else:
+                format_function = formatdict['complexfloat']
+        elif issubclass(dtypeobj, (_nt.unicode_, _nt.string_)):
+            format_function = formatdict['numpystr']
+        elif issubclass(dtypeobj, _nt.datetime64):
+            format_function = formatdict['datetime']
+        else:
+            format_function = formatdict['str']
+
+    # skip over "["
+    next_line_prefix = " "
+    # skip over array(
+    next_line_prefix += " "*len(prefix)
+
+    lst = _formatArray(a, format_function, len(a.shape), max_line_width,
+                       next_line_prefix, separator,
+                       _summaryEdgeItems, summary_insert)[:-1]
+    return lst
+
+def _convert_arrays(obj):
+    import numeric as _nc
+    newtup = []
+    for k in obj:
+        if isinstance(k, _nc.ndarray):
+            k = k.tolist()
+        elif isinstance(k, tuple):
+            k = _convert_arrays(k)
+        newtup.append(k)
+    return tuple(newtup)
+
+
+def array2string(a, max_line_width=None, precision=None,
+                 suppress_small=None, separator=' ', prefix="",
+                 style=repr, formatter=None):
+    """
+    Return a string representation of an array.
+
+    Parameters
+    ----------
+    a : ndarray
+        Input array.
+    max_line_width : int, optional
+        The maximum number of columns the string should span. Newline
+        characters splits the string appropriately after array elements.
+    precision : int, optional
+        Floating point precision. Default is the current printing
+        precision (usually 8), which can be altered using `set_printoptions`.
+    suppress_small : bool, optional
+        Represent very small numbers as zero. A number is "very small" if it
+        is smaller than the current printing precision.
+    separator : str, optional
+        Inserted between elements.
+    prefix : str, optional
+        An array is typically printed as::
+
+          'prefix(' + array2string(a) + ')'
+
+        The length of the prefix string is used to align the
+        output correctly.
+    style : function, optional
+        A function that accepts an ndarray and returns a string.  Used only
+        when the shape of `a` is equal to ``()``, i.e. for 0-D arrays.
+    formatter : dict of callables, optional
+        If not None, the keys should indicate the type(s) that the respective
+        formatting function applies to.  Callables should return a string.
+        Types that are not specified (by their corresponding keys) are handled
+        by the default formatters.  Individual types for which a formatter
+        can be set are::
+
+            - 'bool'
+            - 'int'
+            - 'timedelta' : a `numpy.timedelta64`
+            - 'datetime' : a `numpy.datetime64`
+            - 'float'
+            - 'longfloat' : 128-bit floats
+            - 'complexfloat'
+            - 'longcomplexfloat' : composed of two 128-bit floats
+            - 'numpy_str' : types `numpy.string_` and `numpy.unicode_`
+            - 'str' : all other strings
+
+        Other keys that can be used to set a group of types at once are::
+
+            - 'all' : sets all types
+            - 'int_kind' : sets 'int'
+            - 'float_kind' : sets 'float' and 'longfloat'
+            - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
+            - 'str_kind' : sets 'str' and 'numpystr'
+
+    Returns
+    -------
+    array_str : str
+        String representation of the array.
+
+    Raises
+    ------
+    TypeError : if a callable in `formatter` does not return a string.
+
+    See Also
+    --------
+    array_str, array_repr, set_printoptions, get_printoptions
+
+    Notes
+    -----
+    If a formatter is specified for a certain type, the `precision` keyword is
+    ignored for that type.
+
+    Examples
+    --------
+    >>> x = np.array([1e-16,1,2,3])
+    >>> print np.array2string(x, precision=2, separator=',',
+    ...                       suppress_small=True)
+    [ 0., 1., 2., 3.]
+
+    >>> x  = np.arange(3.)
+    >>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x})
+    '[0.00 1.00 2.00]'
+
+    >>> x  = np.arange(3)
+    >>> np.array2string(x, formatter={'int':lambda x: hex(x)})
+    '[0x0L 0x1L 0x2L]'
+
+    """
+
+    if a.shape == ():
+        x = a.item()
+        if isna(x):
+            lst = str(x).replace('NA', _na_str, 1)
+        else:
+            try:
+                lst = a._format(x)
+                msg = "The `_format` attribute is deprecated in Numpy " \
+                      "2.0 and will be removed in 2.1. Use the " \
+                      "`formatter` kw instead."
+                import warnings
+                warnings.warn(msg, DeprecationWarning)
+            except AttributeError:
+                if isinstance(x, tuple):
+                    x = _convert_arrays(x)
+                lst = style(x)
+    elif reduce(product, a.shape) == 0:
+        # treat as a null array if any of shape elements == 0
+        lst = "[]"
+    else:
+        lst = _array2string(a, max_line_width, precision, suppress_small,
+                            separator, prefix, formatter=formatter)
+    return lst
+
+def _extendLine(s, line, word, max_line_len, next_line_prefix):
+    if len(line.rstrip()) + len(word.rstrip()) >= max_line_len:
+        s += line.rstrip() + "\n"
+        line = next_line_prefix
+    line += word
+    return s, line
+
+
+def _formatArray(a, format_function, rank, max_line_len,
+                 next_line_prefix, separator, edge_items, summary_insert):
+    """formatArray is designed for two modes of operation:
+
+    1. Full output
+
+    2. Summarized output
+
+    """
+    if rank == 0:
+        obj = a.item()
+        if isinstance(obj, tuple):
+            obj = _convert_arrays(obj)
+        return str(obj)
+
+    if summary_insert and 2*edge_items < len(a):
+        leading_items, trailing_items, summary_insert1 = \
+                       edge_items, edge_items, summary_insert
+    else:
+        leading_items, trailing_items, summary_insert1 = 0, len(a), ""
+
+    if rank == 1:
+        s = ""
+        line = next_line_prefix
+        for i in xrange(leading_items):
+            word = format_function(a[i]) + separator
+            s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
+
+        if summary_insert1:
+            s, line = _extendLine(s, line, summary_insert1, max_line_len, next_line_prefix)
+
+        for i in xrange(trailing_items, 1, -1):
+            word = format_function(a[-i]) + separator
+            s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
+
+        word = format_function(a[-1])
+        s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
+        s += line + "]\n"
+        s = '[' + s[len(next_line_prefix):]
+    else:
+        s = '['
+        sep = separator.rstrip()
+        for i in xrange(leading_items):
+            if i > 0:
+                s += next_line_prefix
+            s += _formatArray(a[i], format_function, rank-1, max_line_len,
+                              " " + next_line_prefix, separator, edge_items,
+                              summary_insert)
+            s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1,1)
+
+        if summary_insert1:
+            s += next_line_prefix + summary_insert1 + "\n"
+
+        for i in xrange(trailing_items, 1, -1):
+            if leading_items or i != trailing_items:
+                s += next_line_prefix
+            s += _formatArray(a[-i], format_function, rank-1, max_line_len,
+                              " " + next_line_prefix, separator, edge_items,
+                              summary_insert)
+            s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1,1)
+        if leading_items or trailing_items > 1:
+            s += next_line_prefix
+        s += _formatArray(a[-1], format_function, rank-1, max_line_len,
+                          " " + next_line_prefix, separator, edge_items,
+                          summary_insert).rstrip()+']\n'
+    return s
+
+class FloatFormat(object):
+    def __init__(self, data, precision, suppress_small, sign=False):
+        self.precision = precision
+        self.suppress_small = suppress_small
+        self.sign = sign
+        self.exp_format = False
+        self.large_exponent = False
+        self.max_str_len = 0
+        #try:
+        self.fillFormat(data)
+        #except (TypeError, NotImplementedError):
+            # if reduce(data) fails, this instance will not be called, just
+            # instantiated in formatdict.
+            #pass
+
+    def fillFormat(self, data):
+        import numeric as _nc
+        # XXX pypy unimplemented
+        #errstate = _nc.seterr(all='ignore')
+        try:
+            special = isnan(data) | isinf(data) | isna(data)
+            special[isna(data)] = False
+            valid = not_equal(data, 0) & ~special
+            valid[isna(data)] = False
+            non_zero = absolute(data.compress(valid))
+            if len(non_zero) == 0:
+                max_val = 0.
+                min_val = 0.
+            else:
+                max_val = maximum.reduce(non_zero, skipna=True)
+                min_val = minimum.reduce(non_zero, skipna=True)
+                if max_val >= 1.e8:
+                    self.exp_format = True
+                if not self.suppress_small and (min_val < 0.0001
+                                           or max_val/min_val > 1000.):
+                    self.exp_format = True
+        finally:
+            pass
+            # XXX pypy unimplemented
+            #_nc.seterr(**errstate)
+
+        if self.exp_format:
+            self.large_exponent = 0 < min_val < 1e-99 or max_val >= 1e100
+            self.max_str_len = 8 + self.precision
+            if self.large_exponent:
+                self.max_str_len += 1
+            if self.sign:
+                format = '%+'
+            else:
+                format = '%'
+            format = format + '%d.%de' % (self.max_str_len, self.precision)
+        else:
+            format = '%%.%df' % (self.precision,)
+            if len(non_zero):
+                precision = max([_digits(x, self.precision, format)
+                                 for x in non_zero])
+            else:
+                precision = 0
+            precision = min(self.precision, precision)
+            self.max_str_len = len(str(int(max_val))) + precision + 2
+            if special.any():
+                self.max_str_len = max(self.max_str_len,
+                                       len(_nan_str),
+                                       len(_inf_str)+1,
+                                       len(_na_str))
+            if self.sign:
+                format = '%#+'
+            else:
+                format = '%#'
+            format = format + '%d.%df' % (self.max_str_len, precision)
+
+        self.special_fmt = '%%%ds' % (self.max_str_len,)
+        self.format = format
+
+    def __call__(self, x, strip_zeros=True):
+        import numeric as _nc
+        #err = _nc.seterr(invalid='ignore')
+        try:
+            if isna(x):
+                return self.special_fmt % (str(x).replace('NA', _na_str, 1),)
+            elif isnan(x):
+                if self.sign:
+                    return self.special_fmt % ('+' + _nan_str,)
+                else:
+                    return self.special_fmt % (_nan_str,)
+            elif isinf(x):
+                if x > 0:
+                    if self.sign:
+                        return self.special_fmt % ('+' + _inf_str,)
+                    else:
+                        return self.special_fmt % (_inf_str,)
+                else:
+                    return self.special_fmt % ('-' + _inf_str,)
+        finally:
+            pass
+            #_nc.seterr(**err)
+
+        s = self.format % x
+        if self.large_exponent:
+            # 3-digit exponent
+            expsign = s[-3]
+            if expsign == '+' or expsign == '-':
+                s = s[1:-2] + '0' + s[-2:]
+        elif self.exp_format:
+            # 2-digit exponent
+            if s[-3] == '0':
+                s = ' ' + s[:-3] + s[-2:]
+        elif strip_zeros:
+            z = s.rstrip('0')
+            s = z + ' '*(len(s)-len(z))
+        return s
+
+
+def _digits(x, precision, format):
+    s = format % x
+    z = s.rstrip('0')
+    return precision - len(s) + len(z)
+
+
+_MAXINT = sys.maxint
+_MININT = -sys.maxint-1
+class IntegerFormat(object):
+    def __init__(self, data):
+        try:
+            max_str_len = max(len(str(maximum.reduce(data, skipna=True))),
+                              len(str(minimum.reduce(data, skipna=True))))
+            self.format = '%' + str(max_str_len) + 'd'
+        except TypeError, NotImplementedError:
+            # if reduce(data) fails, this instance will not be called, just
+            # instantiated in formatdict.
+            pass
+        except ValueError:
+            # this occurs when everything is NA
+            pass
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        elif _MININT < x < _MAXINT:
+            return self.format % x
+        else:
+            return "%s" % x
+
+class LongFloatFormat(object):
+    # XXX Have to add something to determine the width to use a la FloatFormat
+    # Right now, things won't line up properly
+    def __init__(self, precision, sign=False):
+        self.precision = precision
+        self.sign = sign
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        elif isnan(x):
+            if self.sign:
+                return '+' + _nan_str
+            else:
+                return ' ' + _nan_str
+        elif isinf(x):
+            if x > 0:
+                if self.sign:
+                    return '+' + _inf_str
+                else:
+                    return ' ' + _inf_str
+            else:
+                return '-' + _inf_str
+        elif x >= 0:
+            if self.sign:
+                return '+' + format_longfloat(x, self.precision)
+            else:
+                return ' ' + format_longfloat(x, self.precision)
+        else:
+            return format_longfloat(x, self.precision)
+
+
+class LongComplexFormat(object):
+    def __init__(self, precision):
+        self.real_format = LongFloatFormat(precision)
+        self.imag_format = LongFloatFormat(precision, sign=True)
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            r = self.real_format(x.real)
+            i = self.imag_format(x.imag)
+            return r + i + 'j'
+
+
+class ComplexFormat(object):
+    def __init__(self, x, precision, suppress_small):
+        self.real_format = FloatFormat(x.real, precision, suppress_small)
+        self.imag_format = FloatFormat(x.imag, precision, suppress_small,
+                                       sign=True)
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            r = self.real_format(x.real, strip_zeros=False)
+            i = self.imag_format(x.imag, strip_zeros=False)
+            if not self.imag_format.exp_format:
+                z = i.rstrip('0')
+                i = z + 'j' + ' '*(len(i)-len(z))
+            else:
+                i = i + 'j'
+            return r + i
+
+class DatetimeFormat(object):
+    def __init__(self, x, unit=None,
+                timezone=None, casting='same_kind'):
+        # Get the unit from the dtype
+        if unit is None:
+            if x.dtype.kind == 'M':
+                unit = datetime_data(x.dtype)[0]
+            else:
+                unit = 's'
+
+        # If timezone is default, make it 'local' or 'UTC' based on the unit
+        if timezone is None:
+            # Date units -> UTC, time units -> local
+            if unit in ('Y', 'M', 'W', 'D'):
+                self.timezone = 'UTC'
+            else:
+                self.timezone = 'local'
+        else:
+            self.timezone = timezone
+        self.unit = unit
+        self.casting = casting
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            return "'%s'" % datetime_as_string(x,
+                                        unit=self.unit,
+                                        timezone=self.timezone,
+                                        casting=self.casting)
+
+class TimedeltaFormat(object):
+    def __init__(self, data):
+        if data.dtype.kind == 'm':
+            v = data.view('i8')
+            max_str_len = max(len(str(maximum.reduce(v))),
+                              len(str(minimum.reduce(v))))
+            self.format = '%' + str(max_str_len) + 'd'
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            return self.format % x.astype('i8')
+
diff --git a/lib_pypy/numpypy/core/fromnumeric.py b/lib_pypy/numpypy/core/fromnumeric.py
--- a/lib_pypy/numpypy/core/fromnumeric.py
+++ b/lib_pypy/numpypy/core/fromnumeric.py
@@ -30,7 +30,7 @@
            'rank', 'size', 'around', 'round_', 'mean', 'std', 'var', 'squeeze',
            'amax', 'amin',
           ]
-          
+
 def take(a, indices, axis=None, out=None, mode='raise'):
     """
     Take elements from an array along an axis.
@@ -149,6 +149,7 @@
            [5, 6]])
 
     """
+    assert order == 'C'
     if not hasattr(a, 'reshape'):
        a = numpypy.array(a)
     return a.reshape(newshape)
@@ -690,6 +691,7 @@
     1
 
     """
+    assert axis is None
     if not hasattr(a, 'argmax'):
         a = numpypy.array(a)
     return a.argmax()
@@ -705,6 +707,7 @@
         documentation.
 
     """
+    assert axis is None
     if not hasattr(a, 'argmin'):
         a = numpypy.array(a)
     return a.argmin()
@@ -1051,8 +1054,9 @@
     array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
 
     """
-    raise NotImplementedError('Waiting on interp level method')
-
+    if not hasattr(a, 'ravel'):
+        a = numpypy.array(a)
+    return a.ravel(order=order)
 
 def nonzero(a):
     """
@@ -1354,9 +1358,11 @@
     -128
 
     """
+    assert dtype is None
+    assert out is None
     if not hasattr(a, "sum"):
         a = numpypy.array(a)
-    return a.sum()
+    return a.sum(axis=axis)
 
 
 def product (a, axis=None, dtype=None, out=None):
@@ -1382,6 +1388,8 @@
     any : equivalent function
 
     """
+    assert axis is None
+    assert out is None
     if not hasattr(a, 'any'):
         a = numpypy.array(a)
     return a.any()
@@ -1396,6 +1404,8 @@
     numpy.all : Equivalent function; see for details.
 
     """
+    assert axis is None
+    assert out is None
     if not hasattr(a, 'all'):
         a = numpypy.array(a)
     return a.all()
@@ -1464,6 +1474,8 @@
     (191614240, 191614240)
 
     """
+    assert axis is None
+    assert out is None
     if not hasattr(a, 'any'):
         a = numpypy.array(a)
     return a.any()
@@ -1526,6 +1538,8 @@
     (28293632, 28293632, array([ True], dtype=bool))
 
     """
+    assert axis is None
+    assert out is None
     if not hasattr(a, 'all'):
         a = numpypy.array(a)
     return a.all()
@@ -1705,6 +1719,8 @@
     4.0
 
     """
+    assert axis is None
+    assert out is None
     if not hasattr(a, "max"):
         a = numpypy.array(a)
     return a.max()
@@ -1766,6 +1782,8 @@
 
     """
     # amin() is equivalent to min()
+    assert axis is None
+    assert out is None
     if not hasattr(a, 'min'):
         a = numpypy.array(a)
     return a.min()
@@ -2214,9 +2232,11 @@
     0.55000000074505806
 
     """
+    assert dtype is None
+    assert out is None
     if not hasattr(a, "mean"):
         a = numpypy.array(a)
-    return a.mean()
+    return a.mean(axis=axis)
 
 
 def std(a, axis=None, dtype=None, out=None, ddof=0):
@@ -2305,9 +2325,12 @@
     0.44999999925552653
 
     """
+    assert dtype is None
+    assert out is None
+    assert ddof == 0
     if not hasattr(a, "std"):
         a = numpypy.array(a)
-    return a.std()
+    return a.std(axis=axis)
 
 
 def var(a, axis=None, dtype=None, out=None, ddof=0):
@@ -2398,6 +2421,9 @@
     0.20250000000000001
 
     """
+    assert dtype is None
+    assert out is None
+    assert ddof == 0
     if not hasattr(a, "var"):
         a = numpypy.array(a)
-    return a.var()
+    return a.var(axis=axis)
diff --git a/lib_pypy/numpypy/core/numeric.py b/lib_pypy/numpypy/core/numeric.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/numeric.py
@@ -0,0 +1,311 @@
+
+from _numpypy import array, ndarray, int_, float_ #, complex_# , longlong
+from _numpypy import concatenate
+import sys
+import _numpypy as multiarray # ARGH
+from numpypy.core.arrayprint import array2string
+
+
+
+def asanyarray(a, dtype=None, order=None, maskna=None, ownmaskna=False):
+    """
+    Convert the input to an ndarray, but pass ndarray subclasses through.
+
+    Parameters
+    ----------
+    a : array_like
+        Input data, in any form that can be converted to an array.  This
+        includes scalars, lists, lists of tuples, tuples, tuples of tuples,
+        tuples of lists, and ndarrays.
+    dtype : data-type, optional
+        By default, the data-type is inferred from the input data.
+    order : {'C', 'F'}, optional
+        Whether to use row-major ('C') or column-major ('F') memory
+        representation.  Defaults to 'C'.
+   maskna : bool or None, optional
+        If this is set to True, it forces the array to have an NA mask.
+        If this is set to False, it forces the array to not have an NA
+        mask.
+    ownmaskna : bool, optional
+        If this is set to True, forces the array to have a mask which
+        it owns.
+
+    Returns
+    -------
+    out : ndarray or an ndarray subclass
+        Array interpretation of `a`.  If `a` is an ndarray or a subclass
+        of ndarray, it is returned as-is and no copy is performed.
+
+    See Also
+    --------
+    asarray : Similar function which always returns ndarrays.
+    ascontiguousarray : Convert input to a contiguous array.
+    asfarray : Convert input to a floating point ndarray.
+    asfortranarray : Convert input to an ndarray with column-major
+                     memory order.
+    asarray_chkfinite : Similar function which checks input for NaNs and
+                        Infs.
+    fromiter : Create an array from an iterator.
+    fromfunction : Construct an array by executing a function on grid
+                   positions.
+
+    Examples
+    --------
+    Convert a list into an array:
+
+    >>> a = [1, 2]
+    >>> np.asanyarray(a)
+    array([1, 2])
+
+    Instances of `ndarray` subclasses are passed through as-is:
+
+    >>> a = np.matrix([1, 2])
+    >>> np.asanyarray(a) is a
+    True
+
+    """
+    return array(a, dtype, copy=False, order=order, subok=True,
+                                maskna=maskna, ownmaskna=ownmaskna)
+
+def base_repr(number, base=2, padding=0):
+    """
+    Return a string representation of a number in the given base system.
+
+    Parameters
+    ----------
+    number : int
+        The value to convert. Only positive values are handled.
+    base : int, optional
+        Convert `number` to the `base` number system. The valid range is 2-36,
+        the default value is 2.
+    padding : int, optional
+        Number of zeros padded on the left. Default is 0 (no padding).
+
+    Returns
+    -------
+    out : str
+        String representation of `number` in `base` system.
+
+    See Also
+    --------
+    binary_repr : Faster version of `base_repr` for base 2.
+
+    Examples
+    --------
+    >>> np.base_repr(5)
+    '101'
+    >>> np.base_repr(6, 5)
+    '11'
+    >>> np.base_repr(7, base=5, padding=3)
+    '00012'
+
+    >>> np.base_repr(10, base=16)
+    'A'
+    >>> np.base_repr(32, base=16)
+    '20'
+
+    """
+    digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+    if base > len(digits):
+        raise ValueError("Bases greater than 36 not handled in base_repr.")
+
+    num = abs(number)
+    res = []
+    while num:
+        res.append(digits[num % base])
+        num //= base
+    if padding:
+        res.append('0' * padding)
+    if number < 0:
+        res.append('-')
+    return ''.join(reversed(res or '0'))
+
+_typelessdata = [int_, float_]#, complex_]
+# XXX
+#if issubclass(intc, int):
+#    _typelessdata.append(intc)
+
+#if issubclass(longlong, int):
+#    _typelessdata.append(longlong)
+
+def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
+    """
+    Return the string representation of an array.
+
+    Parameters
+    ----------
+    arr : ndarray
+        Input array.
+    max_line_width : int, optional
+        The maximum number of columns the string should span. Newline
+        characters split the string appropriately after array elements.
+    precision : int, optional
+        Floating point precision. Default is the current printing precision
+        (usually 8), which can be altered using `set_printoptions`.
+    suppress_small : bool, optional
+        Represent very small numbers as zero, default is False. Very small
+        is defined by `precision`, if the precision is 8 then
+        numbers smaller than 5e-9 are represented as zero.
+
+    Returns
+    -------
+    string : str
+      The string representation of an array.
+
+    See Also
+    --------
+    array_str, array2string, set_printoptions
+
+    Examples
+    --------
+    >>> np.array_repr(np.array([1,2]))
+    'array([1, 2])'
+    >>> np.array_repr(np.ma.array([0.]))
+    'MaskedArray([ 0.])'
+    >>> np.array_repr(np.array([], np.int32))
+    'array([], dtype=int32)'
+
+    >>> x = np.array([1e-6, 4e-7, 2, 3])
+    >>> np.array_repr(x, precision=6, suppress_small=True)
+    'array([ 0.000001,  0.      ,  2.      ,  3.      ])'
+
+    """
+    if arr.size > 0 or arr.shape==(0,):
+        lst = array2string(arr, max_line_width, precision, suppress_small,
+                           ', ', "array(")
+    else: # show zero-length shape unless it is (0,)
+        lst = "[], shape=%s" % (repr(arr.shape),)
+
+    if arr.__class__ is not ndarray:
+        cName= arr.__class__.__name__
+    else:
+        cName = "array"
+
+    skipdtype = (arr.dtype.type in _typelessdata) and arr.size > 0
+
+    # XXX pypy lacks support
+    if 0 and arr.flags.maskna:
+        whichna = isna(arr)
+        # If nothing is NA, explicitly signal the NA-mask
+        if not any(whichna):
+            lst += ", maskna=True"
+        # If everything is NA, can't skip the dtype
+        if skipdtype and all(whichna):
+            skipdtype = False
+
+    if skipdtype:
+        return "%s(%s)" % (cName, lst)
+    else:
+        typename = arr.dtype.name
+        # Quote typename in the output if it is "complex".
+        if typename and not (typename[0].isalpha() and typename.isalnum()):
+            typename = "'%s'" % typename
+
+        lf = ''
+        if 0: # or issubclass(arr.dtype.type, flexible):
+            if arr.dtype.names:
+                typename = "%s" % str(arr.dtype)
+            else:
+                typename = "'%s'" % str(arr.dtype)
+            lf = '\n'+' '*len("array(")
+        return cName + "(%s, %sdtype=%s)" % (lst, lf, typename)
+
+def array_str(a, max_line_width=None, precision=None, suppress_small=None):
+    """
+    Return a string representation of the data in an array.
+
+    The data in the array is returned as a single string.  This function is
+    similar to `array_repr`, the difference being that `array_repr` also
+    returns information on the kind of array and its data type.
+
+    Parameters
+    ----------
+    a : ndarray
+        Input array.
+    max_line_width : int, optional
+        Inserts newlines if text is longer than `max_line_width`.  The
+        default is, indirectly, 75.
+    precision : int, optional
+        Floating point precision.  Default is the current printing precision
+        (usually 8), which can be altered using `set_printoptions`.
+    suppress_small : bool, optional
+        Represent numbers "very close" to zero as zero; default is False.
+        Very close is defined by precision: if the precision is 8, e.g.,
+        numbers smaller (in absolute value) than 5e-9 are represented as
+        zero.
+
+    See Also
+    --------
+    array2string, array_repr, set_printoptions
+
+    Examples
+    --------
+    >>> np.array_str(np.arange(3))
+    '[0 1 2]'
+
+    """
+    return array2string(a, max_line_width, precision, suppress_small, ' ', "", str)
+
+def set_string_function(f, repr=True):
+    """
+    Set a Python function to be used when pretty printing arrays.
+
+    Parameters
+    ----------
+    f : function or None
+        Function to be used to pretty print arrays. The function should expect
+        a single array argument and return a string of the representation of
+        the array. If None, the function is reset to the default NumPy function
+        to print arrays.
+    repr : bool, optional
+        If True (default), the function for pretty printing (``__repr__``)
+        is set, if False the function that returns the default string
+        representation (``__str__``) is set.
+
+    See Also
+    --------
+    set_printoptions, get_printoptions
+
+    Examples
+    --------
+    >>> def pprint(arr):
+    ...     return 'HA! - What are you going to do now?'
+    ...
+    >>> np.set_string_function(pprint)
+    >>> a = np.arange(10)
+    >>> a
+    HA! - What are you going to do now?
+    >>> print a
+    [0 1 2 3 4 5 6 7 8 9]
+
+    We can reset the function to the default:
+
+    >>> np.set_string_function(None)
+    >>> a
+    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+
+    `repr` affects either pretty printing or normal string representation.
+    Note that ``__repr__`` is still affected by setting ``__str__``
+    because the width of each array element in the returned string becomes
+    equal to the length of the result of ``__str__()``.
+
+    >>> x = np.arange(4)
+    >>> np.set_string_function(lambda x:'random', repr=False)
+    >>> x.__str__()
+    'random'
+    >>> x.__repr__()
+    'array([     0,      1,      2,      3])'
+
+    """
+    if f is None:
+        if repr:
+            return multiarray.set_string_function(array_repr, 1)
+        else:
+            return multiarray.set_string_function(array_str, 0)
+    else:
+        return multiarray.set_string_function(f, repr)
+
+set_string_function(array_str, 0)
+set_string_function(array_repr, 1)
+
+little_endian = (sys.byteorder == 'little')
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -37,16 +37,16 @@
     for i in range(256):
         c = chr(i)
         if c not in uc_map:
-            uc_map[c] = u'\\%03o'%i 
+            uc_map[c] = u'\\%03o'%i
     return uc_map
 
 # disp_str proved to be a bottleneck for large inputs, so it's been
 # rewritten in C; it's not required though.
 try:
     raise ImportError # currently it's borked by the unicode support
-    
+
     from _pyrepl_utils import disp_str, init_unctrl_map
-    
+
     init_unctrl_map(_make_unctrl_map())
 
     del init_unctrl_map
@@ -118,7 +118,7 @@
      (r'\C-x\C-u', 'upcase-region'),
      (r'\C-y', 'yank'),
      (r'\C-z', 'suspend'),
-     
+
      (r'\M-b', 'backward-word'),
      (r'\M-c', 'capitalize-word'),
      (r'\M-d', 'kill-word'),
@@ -303,7 +303,7 @@
 
     def process_prompt(self, prompt):
         """ Process the prompt.
-        
+
         This means calculate the length of the prompt. The character \x01
         and \x02 are used to bracket ANSI control sequences and need to be
         excluded from the length calculation.  So also a copy of the prompt
@@ -372,7 +372,7 @@
         while p >= 0 and b[p] <> '\n':
             p -= 1
         return p + 1
-    
+
     def eol(self, p=None):
         """Return the 0-based index of the line break following p most
         immediately.
@@ -463,7 +463,7 @@
         """This function is called to allow post command cleanup."""
         if getattr(cmd, "kills_digit_arg", 1):
             if self.arg is not None:
-                self.dirty = 1                
+                self.dirty = 1
             self.arg = None
 
     def prepare(self):
@@ -575,13 +575,15 @@
     def push_char(self, char):
         self.console.push_char(char)
         self.handle1(0)
-    
-    def readline(self, returns_unicode=False):
+
+    def readline(self, returns_unicode=False, startup_hook=None):
         """Read a line.  The implementation of this method also shows
         how to drive Reader if you want more control over the event
         loop."""
         self.prepare()
         try:
+            if startup_hook is not None:
+                startup_hook()
             self.refresh()
             while not self.finished:
                 self.handle1()
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -193,10 +193,8 @@
             reader = self.get_reader()
         except _error:
             return _old_raw_input(prompt)
-        if self.startup_hook is not None:
-            self.startup_hook()
         reader.ps1 = prompt
-        return reader.readline()
+        return reader.readline(reader, startup_hook=self.startup_hook)
 
     def multiline_input(self, more_lines, ps1, ps2, returns_unicode=False):
         """Read an input on possibly multiple lines, asking for more
@@ -390,7 +388,7 @@
     global _old_raw_input
     if _old_raw_input is not None:
         return # don't run _setup twice
-    
+
     try:
         f_in = sys.stdin.fileno()
         f_out = sys.stdout.fileno()
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -441,6 +441,12 @@
     def method_popitem(dct):
         return dct.getanyitem('items')
 
+    def method_pop(dct, s_key, s_dfl=None):
+        dct.dictdef.generalize_key(s_key)
+        if s_dfl is not None:
+            dct.dictdef.generalize_value(s_dfl)
+        return dct.dictdef.read_value()
+
     def _can_only_throw(dic, *ignore):
         if dic1.dictdef.dictkey.custom_eq_hash:
             return None    # r_dict: can throw anything
diff --git a/pypy/bin/py.py b/pypy/bin/py.py
--- a/pypy/bin/py.py
+++ b/pypy/bin/py.py
@@ -76,6 +76,8 @@
     config.objspace.suggest(allworkingmodules=False)
     if config.objspace.allworkingmodules:
         pypyoption.enable_allworkingmodules(config)
+    if config.objspace.usemodules._continuation:
+        config.translation.continuation = True
     if config.objspace.usemodules.thread:
         config.translation.thread = True
 
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -53,11 +53,11 @@
 PyPy is ready to be executed as soon as you unpack the tarball or the zip
 file, with no need to install it in any specific location::
 
-    $ tar xf pypy-1.6-linux.tar.bz2
+    $ tar xf pypy-1.7-linux.tar.bz2
 
-    $ ./pypy-1.6/bin/pypy
+    $ ./pypy-1.7/bin/pypy
     Python 2.7.1 (?, Apr 27 2011, 12:44:21)
-    [PyPy 1.6.0 with GCC 4.4.3] on linux2
+    [PyPy 1.7.0 with GCC 4.4.3] on linux2
     Type "help", "copyright", "credits" or "license" for more information.
     And now for something completely different: ``implementing LOGO in LOGO:
     "turtles all the way down"''
@@ -75,14 +75,14 @@
 
     $ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
 
-    $ ./pypy-1.6/bin/pypy distribute_setup.py
+    $ ./pypy-1.7/bin/pypy distribute_setup.py
 
-    $ ./pypy-1.6/bin/pypy get-pip.py
+    $ ./pypy-1.7/bin/pypy get-pip.py
 
-    $ ./pypy-1.6/bin/pip install pygments  # for example
+    $ ./pypy-1.7/bin/pip install pygments  # for example
 
-3rd party libraries will be installed in ``pypy-1.6/site-packages``, and
-the scripts in ``pypy-1.6/bin``.
+3rd party libraries will be installed in ``pypy-1.7/site-packages``, and
+the scripts in ``pypy-1.7/bin``.
 
 Installing using virtualenv
 ---------------------------
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -445,6 +445,7 @@
         AsyncAction.__init__(self, space)
         self.dying_objects = []
         self.finalizers_lock_count = 0
+        self.enabled_at_app_level = True
 
     def register_callback(self, w_obj, callback, descrname):
         self.dying_objects.append((w_obj, callback, descrname))
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -394,13 +394,13 @@
     This is the class supporting --gcrootfinder=shadowstack.
     """
     is_shadow_stack = True
-    MARKER = 8
+    MARKER_FRAME = 8       # this marker now *follows* the frame addr
 
     # The "shadowstack" is a portable way in which the GC finds the
     # roots that live in the stack.  Normally it is just a list of
     # pointers to GC objects.  The pointers may be moved around by a GC
-    # collection.  But with the JIT, an entry can also be MARKER, in
-    # which case the next entry points to an assembler stack frame.
+    # collection.  But with the JIT, an entry can also be MARKER_FRAME,
+    # in which case the previous entry points to an assembler stack frame.
     # During a residual CALL from the assembler (which may indirectly
     # call the GC), we use the force_index stored in the assembler
     # stack frame to identify the call: we can go from the force_index
@@ -433,11 +433,16 @@
         class RootIterator:
             _alloc_flavor_ = "raw"
 
-            def next(iself, gc, next, range_highest):
-                # Return the "next" valid GC object' address.  This usually
-                # means just returning "next", until we reach "range_highest",
-                # except that we are skipping NULLs.  If "next" contains a
-                # MARKER instead, then we go into JIT-frame-lookup mode.
+            def setcontext(iself, context):
+                iself.context = context
+
+            def nextleft(iself, gc, range_lowest, prev):
+                # Return the next valid GC object's address, in right-to-left
+                # order from the shadowstack array.  This usually means just
+                # returning "prev - sizeofaddr", until we reach "range_lowest",
+                # except that we are skipping NULLs.  If "prev - sizeofaddr"
+                # contains a MARKER_FRAME instead, then we go into
+                # JIT-frame-lookup mode.
                 #
                 while True:
                     #
@@ -446,20 +451,20 @@
                         #
                         # Look for the next shadowstack address that
                         # contains a valid pointer
-                        while next != range_highest:
-                            if next.signed[0] == self.MARKER:
+                        while prev != range_lowest:
+                            prev -= llmemory.sizeof(llmemory.Address)
+                            if prev.signed[0] == self.MARKER_FRAME:
                                 break
-                            if gc.points_to_valid_gc_object(next):
-                                return next
-                            next += llmemory.sizeof(llmemory.Address)
+                            if gc.points_to_valid_gc_object(prev):
+                                return prev
                         else:
                             return llmemory.NULL     # done
                         #
-                        # It's a JIT frame.  Save away 'next' for later, and
+                        # It's a JIT frame.  Save away 'prev' for later, and
                         # go into JIT-frame-exploring mode.
-                        next += llmemory.sizeof(llmemory.Address)
-                        frame_addr = next.signed[0]
-                        iself.saved_next = next
+                        prev -= llmemory.sizeof(llmemory.Address)
+                        frame_addr = prev.signed[0]
+                        iself.saved_prev = prev
                         iself.frame_addr = frame_addr
                         addr = llmemory.cast_int_to_adr(frame_addr +
                                                         self.force_index_ofs)
@@ -499,8 +504,7 @@
                     #
                     # Restore 'prev' and loop back to the start.
                     iself.frame_addr = 0
-                    next = iself.saved_next
-                    next += llmemory.sizeof(llmemory.Address)
+                    prev = iself.saved_prev
 
         # ---------------
         #
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -774,7 +774,7 @@
         self.mc.RET()
 
     def _call_header_shadowstack(self, gcrootmap):
-        # we need to put two words into the shadowstack: the MARKER
+        # we need to put two words into the shadowstack: the MARKER_FRAME
         # and the address of the frame (ebp, actually)
         rst = gcrootmap.get_root_stack_top_addr()
         if rx86.fits_in_32bits(rst):
@@ -783,9 +783,10 @@
             self.mc.MOV_ri(r13.value, rst)            # MOV r13, rootstacktop
             self.mc.MOV_rm(eax.value, (r13.value, 0)) # MOV eax, [r13]
         #
-        self.mc.LEA_rm(ebx.value, (eax.value, 2*WORD))  # LEA ebx, [eax+2*WORD]
-        self.mc.MOV_mi((eax.value, 0), gcrootmap.MARKER)    # MOV [eax], MARKER
-        self.mc.MOV_mr((eax.value, WORD), ebp.value)      # MOV [eax+WORD], ebp
+        MARKER = gcrootmap.MARKER_FRAME
+        self.mc.LEA_rm(ebx.value, (eax.value, 2*WORD)) # LEA ebx, [eax+2*WORD]
+        self.mc.MOV_mi((eax.value, WORD), MARKER)      # MOV [eax+WORD], MARKER
+        self.mc.MOV_mr((eax.value, 0), ebp.value)      # MOV [eax], ebp
         #
         if rx86.fits_in_32bits(rst):
             self.mc.MOV_jr(rst, ebx.value)            # MOV [rootstacktop], ebx
diff --git a/pypy/jit/codewriter/assembler.py b/pypy/jit/codewriter/assembler.py
--- a/pypy/jit/codewriter/assembler.py
+++ b/pypy/jit/codewriter/assembler.py
@@ -81,10 +81,15 @@
             if not isinstance(value, (llmemory.AddressAsInt,
                                       ComputedIntSymbolic)):
                 value = lltype.cast_primitive(lltype.Signed, value)
-                if allow_short and -128 <= value <= 127:
-                    # emit the constant as a small integer
-                    self.code.append(chr(value & 0xFF))
-                    return True
+                if allow_short:
+                    try:
+                        short_num = -128 <= value <= 127
+                    except TypeError:    # "Symbolics cannot be compared!"
+                        short_num = False
+                    if short_num:
+                        # emit the constant as a small integer
+                        self.code.append(chr(value & 0xFF))
+                        return True
             constants = self.constants_i
         elif kind == 'ref':
             value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
@@ -126,13 +131,14 @@
         self.code.append("temporary placeholder")
         #
         argcodes = []
+        allow_short = (insn[0] in USE_C_FORM)
         for x in insn[1:]:
             if isinstance(x, Register):
                 self.emit_reg(x)
                 argcodes.append(x.kind[0])
             elif isinstance(x, Constant):
                 kind = getkind(x.concretetype)
-                is_short = self.emit_const(x, kind, allow_short=True)
+                is_short = self.emit_const(x, kind, allow_short=allow_short)
                 if is_short:
                     argcodes.append('c')
                 else:
@@ -252,3 +258,43 @@
         for func in callinfocollection.all_function_addresses_as_int():
             func = heaptracker.int2adr(func)
             self.see_raw_object(func.ptr)
+
+
+# A set of instructions that use the 'c' encoding for small constants.
+# Allowing it anywhere causes the number of instruction variants to
+# expode, growing past 256.  So we list here only the most common
+# instructions where the 'c' variant might be useful.
+USE_C_FORM = set([
+    'copystrcontent',
+    'getarrayitem_gc_pure_i',
+    'getarrayitem_gc_pure_r',
+    'getarrayitem_gc_i',
+    'getarrayitem_gc_r',
+    'goto_if_not_int_eq',
+    'goto_if_not_int_ge',
+    'goto_if_not_int_gt',
+    'goto_if_not_int_le',
+    'goto_if_not_int_lt',
+    'goto_if_not_int_ne',
+    'int_add',
+    'int_and',
+    'int_copy',
+    'int_eq',
+    'int_ge',
+    'int_gt',
+    'int_le',
+    'int_lt',
+    'int_ne',
+    'int_return',
+    'int_sub',
+    'jit_merge_point',
+    'new_array',
+    'newstr',
+    'setarrayitem_gc_i',
+    'setarrayitem_gc_r',
+    'setfield_gc_i',
+    'strgetitem',
+    'strsetitem',
+
+    'foobar', 'baz',    # for tests
+])
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -7,6 +7,7 @@
 from pypy.jit.metainterp import quasiimmut
 from pypy.jit.metainterp.history import getkind
 from pypy.jit.metainterp.typesystem import deref, arrayItem
+from pypy.jit.metainterp.blackhole import BlackholeInterpreter
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant, c_last_exception
 from pypy.rlib import objectmodel
 from pypy.rlib.jit import _we_are_jitted
@@ -199,9 +200,9 @@
         try:
             rewrite = _rewrite_ops[op.opname]
         except KeyError:
-            return op     # default: keep the operation unchanged
-        else:
-            return rewrite(self, op)
+            raise Exception("the JIT doesn't support the operation %r"
+                            " in %r" % (op, getattr(self, 'graph', '?')))
+        return rewrite(self, op)
 
     def rewrite_op_same_as(self, op):
         if op.args[0] in self.vable_array_vars:
@@ -1720,4 +1721,18 @@
             result[name[len(prefix):]] = getattr(Transformer, name)
     return result
 
+def keep_operation_unchanged(jtransform, op):
+    return op
+
+def _add_default_ops(rewrite_ops):
+    # All operations present in the BlackholeInterpreter as bhimpl_xxx
+    # but not explicitly listed in this file are supposed to be just
+    # passed in unmodified.  All other operations are forbidden.
+    for key, value in BlackholeInterpreter.__dict__.items():
+        if key.startswith('bhimpl_'):
+            opname = key[len('bhimpl_'):]
+            rewrite_ops.setdefault(opname, keep_operation_unchanged)
+    rewrite_ops.setdefault('-live-', keep_operation_unchanged)
+
 _rewrite_ops = _with_prefix('rewrite_op_')
+_add_default_ops(_rewrite_ops)
diff --git a/pypy/jit/codewriter/test/test_assembler.py b/pypy/jit/codewriter/test/test_assembler.py
--- a/pypy/jit/codewriter/test/test_assembler.py
+++ b/pypy/jit/codewriter/test/test_assembler.py
@@ -157,15 +157,18 @@
         ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])),
         ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])),
         ('baz', Constant(42, lltype.Signed)),
+        ('bok', Constant(41, lltype.Signed)),
         ]
     assembler = Assembler()
     jitcode = assembler.assemble(ssarepr)
     assert jitcode.code == ("\x00\x01\xFF"
                             "\x00\x01\xFF"
-                            "\x01\x2A")
+                            "\x01\x2A"
+                            "\x02\xFE")
     assert assembler.insns == {'foobar/I': 0,
-                               'baz/c': 1}
-    assert jitcode.constants_i == [42]
+                               'baz/c': 1,    # in USE_C_FORM
+                               'bok/i': 2}    # not in USE_C_FORM
+    assert jitcode.constants_i == [42, 41]
 
 def test_assemble_descr():
     class FooDescr(AbstractDescr):
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1210,3 +1210,11 @@
     assert op1.args == [v1]
     assert op1.result is None
     assert op2 is None
+
+def test_unknown_operation():
+    op = SpaceOperation('foobar', [], varoftype(lltype.Void))
+    tr = Transformer()
+    try:
+        tr.rewrite_operation(op)
+    except Exception, e:
+        assert 'foobar' in str(e)
diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ b/pypy/module/_hashlib/interp_hashlib.py
@@ -75,8 +75,12 @@
 
         ctx = lltype.malloc(ropenssl.EVP_MD_CTX.TO, flavor='raw')
         rgc.add_memory_pressure(HASH_MALLOC_SIZE + self.digest_size)
-        ropenssl.EVP_DigestInit(ctx, digest_type)
-        self.ctx = ctx
+        try:
+            ropenssl.EVP_DigestInit(ctx, digest_type)
+            self.ctx = ctx
+        except:
+            lltype.free(ctx, flavor='raw')
+            raise
 
     def __del__(self):
         # self.lock.free()
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -349,6 +349,8 @@
         try:
             s = os.read(self.fd, size)
         except OSError, e:
+            if e.errno == errno.EAGAIN:
+                return space.w_None
             raise wrap_oserror(space, e,
                                exception_name='w_IOError')
 
@@ -362,6 +364,8 @@
         try:
             buf = os.read(self.fd, length)
         except OSError, e:
+            if e.errno == errno.EAGAIN:
+                return space.w_None
             raise wrap_oserror(space, e,
                                exception_name='w_IOError')
         rwbuffer.setslice(0, buf)
diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -133,6 +133,19 @@
         f.close()
         assert a == b'a\nbxxxxxxx'
 
+    def test_nonblocking_read(self):
+        import os, fcntl
+        r_fd, w_fd = os.pipe()
+        # set nonblocking
+        fcntl.fcntl(r_fd, fcntl.F_SETFL, os.O_NONBLOCK)
+        import _io
+        f = _io.FileIO(r_fd, 'r')
+        # Read from stream sould return None
+        assert f.read() is None
+        assert f.read(10) is None
+        a = bytearray('x' * 10)
+        assert f.readinto(a) is None
+
     def test_repr(self):
         import _io
         f = _io.FileIO(self.tmpfile, 'r')
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
@@ -78,9 +78,6 @@
             self.connect(self.addr_from_object(space, w_addr))
         except SocketError, e:
             raise converted_error(space, e)
-        except TypeError, e:
-            raise OperationError(space.w_TypeError,
-                                 space.wrap(str(e)))
 
     def connect_ex_w(self, space, w_addr):
         """connect_ex(address) -> errno
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
@@ -530,27 +530,32 @@
         import _socket, os
         if not hasattr(_socket, 'AF_UNIX'):
             skip('AF_UNIX not supported.')
-        sockpath = os.path.join(self.udir, 'app_test_unix_socket_connect')
+        oldcwd = os.getcwd()
+        os.chdir(self.udir)
+        try:
+            sockpath = 'app_test_unix_socket_connect'
 
-        serversock = _socket.socket(_socket.AF_UNIX)
-        serversock.bind(sockpath)
-        serversock.listen(1)
+            serversock = _socket.socket(_socket.AF_UNIX)
+            serversock.bind(sockpath)
+            serversock.listen(1)
 
-        clientsock = _socket.socket(_socket.AF_UNIX)
-        clientsock.connect(sockpath)
-        fileno, addr = serversock._accept()
-        s = _socket.socket(fileno=fileno)
-        assert not addr
+            clientsock = _socket.socket(_socket.AF_UNIX)
+            clientsock.connect(sockpath)
+            fileno, addr = serversock._accept()
+            s = _socket.socket(fileno=fileno)
+            assert not addr
 
-        s.send(b'X')
-        data = clientsock.recv(100)
-        assert data == b'X'
-        clientsock.send(b'Y')
-        data = s.recv(100)
-        assert data == b'Y'
+            s.send(b'X')
+            data = clientsock.recv(100)
+            assert data == b'X'
+            clientsock.send(b'Y')
+            data = s.recv(100)
+            assert data == b'Y'
 
-        clientsock.close()
-        s.close()
+            clientsock.close()
+            s.close()
+        finally:
+            os.chdir(oldcwd)
 
     def test_subclass(self):
         # Socket is not created in __new__, but in __init__.
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
@@ -96,7 +96,8 @@
 
         # Defaults
         libssl_SSL_CTX_set_verify(self.ctx, SSL_VERIFY_NONE, None)
-        libssl_SSL_CTX_set_options(self.ctx, SSL_OP_ALL)
+        libssl_SSL_CTX_set_options(
+            self.ctx, SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
         libssl_SSL_CTX_set_session_id_context(self.ctx, "Python", len("Python"))
 
     def __del__(self):
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -64,8 +64,8 @@
 
     def test_sslwrap(self):
         import ssl, _socket, sys, gc
-        if sys.platform == 'darwin':
-            skip("hangs indefinitely on OSX (also on CPython)")
+        if sys.platform == 'darwin' or 'freebsd' in sys.platform:
+            skip("hangs indefinitely on OSX & FreeBSD (also on CPython)")
         s = _socket.socket()
         ss = ssl.wrap_socket(s)
 
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -32,11 +32,10 @@
     Py_DecRef(space, w_item)
     if not isinstance(w_list, W_ListObject):
         PyErr_BadInternalCall(space)
-    wrappeditems = w_list.getitems()
-    if index < 0 or index >= len(wrappeditems):
+    if index < 0 or index >= w_list.length():
         raise OperationError(space.w_IndexError, space.wrap(
             "list assignment index out of range"))
-    wrappeditems[index] = w_item
+    w_list.setitem(index, w_item)
     return 0
 
 @cpython_api([PyObject, Py_ssize_t], PyObject)
@@ -74,7 +73,7 @@
     """Macro form of PyList_Size() without error checking.
     """
     assert isinstance(w_list, W_ListObject)
-    return len(w_list.getitems())
+    return w_list.length()
 
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
diff --git a/pypy/module/cpyext/test/test_listobject.py b/pypy/module/cpyext/test/test_listobject.py
--- a/pypy/module/cpyext/test/test_listobject.py
+++ b/pypy/module/cpyext/test/test_listobject.py
@@ -128,3 +128,6 @@
         module.setslice(l, None)
         assert l == [0, 4, 5]
 
+        l = [1, 2, 3]
+        module.setlistitem(l,0)
+        assert l == [None, 2, 3]
diff --git a/pypy/module/fcntl/test/test_fcntl.py b/pypy/module/fcntl/test/test_fcntl.py
--- a/pypy/module/fcntl/test/test_fcntl.py
+++ b/pypy/module/fcntl/test/test_fcntl.py
@@ -42,13 +42,9 @@
         else:
             start_len = "qq"
 
-        if sys.platform in ('netbsd1', 'netbsd2', 'netbsd3',
-                            'Darwin1.2', 'darwin',
-                            'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
-                            'freebsd6', 'freebsd7', 'freebsd8', 'freebsd9',
-                            'bsdos2', 'bsdos3', 'bsdos4',
-                            'openbsd', 'openbsd2', 'openbsd3', 'openbsd4',
-                            'openbsd5'):
+        if any(substring in sys.platform.lower()
+               for substring in ('netbsd', 'darwin', 'freebsd', 'bsdos',
+                                 'openbsd')):
             if struct.calcsize('l') == 8:
                 off_t = 'l'
                 pid_t = 'i'
@@ -182,7 +178,8 @@
 
     def test_large_flag(self):
         import sys
-        if sys.platform == "darwin" or sys.platform.startswith("openbsd"):
+        if any(plat in sys.platform
+               for plat in ('darwin', 'openbsd', 'freebsd')):
             skip("Mac OS doesn't have any large flag in fcntl.h")
         import fcntl, sys
         if sys.maxint == 2147483647:
diff --git a/pypy/module/gc/__init__.py b/pypy/module/gc/__init__.py
--- a/pypy/module/gc/__init__.py
+++ b/pypy/module/gc/__init__.py
@@ -1,18 +1,18 @@
 from pypy.interpreter.mixedmodule import MixedModule
     
 class Module(MixedModule):
-    appleveldefs = {
-        'enable': 'app_gc.enable',
-        'disable': 'app_gc.disable',
-        'isenabled': 'app_gc.isenabled',
-    }
     interpleveldefs = {
         'collect': 'interp_gc.collect',
+        'enable': 'interp_gc.enable',
+        'disable': 'interp_gc.disable',
+        'isenabled': 'interp_gc.isenabled',
         'enable_finalizers': 'interp_gc.enable_finalizers',
         'disable_finalizers': 'interp_gc.disable_finalizers',
         'garbage' : 'space.newlist([])',
         #'dump_heap_stats': 'interp_gc.dump_heap_stats',
     }
+    appleveldefs = {
+    }
 
     def __init__(self, space, w_name):
         if (not space.config.translating or
diff --git a/pypy/module/gc/app_gc.py b/pypy/module/gc/app_gc.py
deleted file mode 100644
--- a/pypy/module/gc/app_gc.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# NOT_RPYTHON
-
-enabled = True
-
-def isenabled():
-    global enabled
-    return enabled
-
-def enable():
-    global enabled
-    import gc
-    if not enabled:
-        gc.enable_finalizers()
-        enabled = True
-
-def disable():
-    global enabled
-    import gc
-    if enabled:
-        gc.disable_finalizers()
-        enabled = False
diff --git a/pypy/module/gc/interp_gc.py b/pypy/module/gc/interp_gc.py
--- a/pypy/module/gc/interp_gc.py
+++ b/pypy/module/gc/interp_gc.py
@@ -17,6 +17,26 @@
     rgc.collect()
     return space.wrap(0)
 
+def enable(space):
+    """Non-recursive version.  Enable finalizers now.
+    If they were already enabled, no-op.
+    If they were disabled even several times, enable them anyway.
+    """
+    if not space.user_del_action.enabled_at_app_level:
+        space.user_del_action.enabled_at_app_level = True
+        enable_finalizers(space)
+
+def disable(space):
+    """Non-recursive version.  Disable finalizers now.  Several calls
+    to this function are ignored.
+    """
+    if space.user_del_action.enabled_at_app_level:
+        space.user_del_action.enabled_at_app_level = False
+        disable_finalizers(space)
+
+def isenabled(space):
+    return space.newbool(space.user_del_action.enabled_at_app_level)
+
 def enable_finalizers(space):
     if space.user_del_action.finalizers_lock_count == 0:
         raise OperationError(space.w_ValueError,
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
@@ -27,6 +27,12 @@
         'dot': 'interp_numarray.dot',
         'fromstring': 'interp_support.fromstring',
         'flatiter': 'interp_numarray.W_FlatIterator',
+        'isna': 'interp_numarray.isna',
+        'concatenate': 'interp_numarray.concatenate',
+
+        'set_string_function': 'appbridge.set_string_function',
+        
+        'count_reduce_items': 'interp_numarray.count_reduce_items',
 
         'True_': 'types.Bool.True',
         'False_': 'types.Bool.False',
@@ -66,6 +72,7 @@
         ("copysign", "copysign"),
         ("cos", "cos"),
         ("divide", "divide"),
+        ("true_divide", "true_divide"),
         ("equal", "equal"),
         ("exp", "exp"),
         ("fabs", "fabs"),
@@ -88,6 +95,9 @@
         ("tan", "tan"),
         ('bitwise_and', 'bitwise_and'),
         ('bitwise_or', 'bitwise_or'),
+        ('bitwise_not', 'invert'),
+        ('isnan', 'isnan'),
+        ('isinf', 'isinf'),
     ]:
         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
@@ -59,7 +59,7 @@
     if not hasattr(a, "max"):
         a = _numpypy.array(a)
     return a.max(axis)
-
+    
 def arange(start, stop=None, step=1, dtype=None):
     '''arange([start], stop[, step], dtype=None)
     Generate values in the half-interval [start, stop).
diff --git a/pypy/module/micronumpy/appbridge.py b/pypy/module/micronumpy/appbridge.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/appbridge.py
@@ -0,0 +1,38 @@
+
+from pypy.rlib.objectmodel import specialize
+
+class AppBridgeCache(object):
+    w__var = None
+    w__std = None
+    w_module = None
+    w_array_repr = None
+    w_array_str = None
+
+    def __init__(self, space):
+        self.w_import = space.appexec([], """():
+        def f():
+            import sys
+            __import__('numpypy.core._methods')
+            return sys.modules['numpypy.core._methods']
+        return f
+        """)
+    
+    @specialize.arg(2)
+    def call_method(self, space, name, *args):
+        w_meth = getattr(self, 'w_' + name)
+        if w_meth is None:
+            if self.w_module is None:
+                self.w_module = space.call_function(self.w_import)
+            w_meth = space.getattr(self.w_module, space.wrap(name))
+            setattr(self, 'w_' + name, w_meth)
+        return space.call_function(w_meth, *args)
+
+def set_string_function(space, w_f, w_repr):
+    cache = get_appbridge_cache(space)
+    if space.is_true(w_repr):
+        cache.w_array_repr = w_f
+    else:
+        cache.w_array_str = w_f
+
+def get_appbridge_cache(space):
+    return space.fromcache(AppBridgeCache)
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
@@ -32,13 +32,16 @@
 class BadToken(Exception):
     pass
 
-SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any", "unegative"]
+SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
+                        "unegative", "flat"]
+TWO_ARG_FUNCTIONS = ['take']
 
 class FakeSpace(object):
     w_ValueError = None
     w_TypeError = None
     w_IndexError = None
     w_OverflowError = None
+    w_NotImplementedError = None
     w_None = None
 
     w_bool = "bool"
@@ -53,6 +56,9 @@
         """NOT_RPYTHON"""
         self.fromcache = InternalSpaceCache(self).getorbuild
 
+    def _freeze_(self):
+        return True
+
     def issequence_w(self, w_obj):
         return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
 
@@ -144,6 +150,9 @@
     def allocate_instance(self, klass, w_subtype):
         return instantiate(klass)
 
+    def newtuple(self, list_w):
+        raise ValueError
+
     def len_w(self, w_obj):
         if isinstance(w_obj, ListObject):
             return len(w_obj.items)
@@ -371,12 +380,12 @@
                                                  for arg in self.args]))
 
     def execute(self, interp):
+        arr = self.args[0].execute(interp)
+        if not isinstance(arr, BaseArray):
+            raise ArgumentNotAnArray
         if self.name in SINGLE_ARG_FUNCTIONS:
             if len(self.args) != 1 and self.name != 'sum':
                 raise ArgumentMismatch
-            arr = self.args[0].execute(interp)
-            if not isinstance(arr, BaseArray):
-                raise ArgumentNotAnArray
             if self.name == "sum":
                 if len(self.args)>1:
                     w_res = arr.descr_sum(interp.space,
@@ -396,21 +405,31 @@
             elif self.name == "unegative":
                 neg = interp_ufuncs.get(interp.space).negative
                 w_res = neg.call(interp.space, [arr])
+            elif self.name == "flat":
+                w_res = arr.descr_get_flatiter(interp.space)
             else:
                 assert False # unreachable code
-            if isinstance(w_res, BaseArray):
-                return w_res
-            if isinstance(w_res, FloatObject):
-                dtype = get_dtype_cache(interp.space).w_float64dtype
-            elif isinstance(w_res, BoolObject):
-                dtype = get_dtype_cache(interp.space).w_booldtype
-            elif isinstance(w_res, interp_boxes.W_GenericBox):
-                dtype = w_res.get_dtype(interp.space)
+        elif self.name in TWO_ARG_FUNCTIONS:
+            arg = self.args[1].execute(interp)
+            if not isinstance(arg, BaseArray):
+                raise ArgumentNotAnArray
+            if self.name == 'take':
+                w_res = arr.descr_take(interp.space, arg)
             else:
-                dtype = None
-            return scalar_w(interp.space, dtype, w_res)
+                assert False # unreachable
         else:
             raise WrongFunctionName
+        if isinstance(w_res, BaseArray):
+            return w_res
+        if isinstance(w_res, FloatObject):
+            dtype = get_dtype_cache(interp.space).w_float64dtype
+        elif isinstance(w_res, BoolObject):
+            dtype = get_dtype_cache(interp.space).w_booldtype
+        elif isinstance(w_res, interp_boxes.W_GenericBox):
+            dtype = w_res.get_dtype(interp.space)
+        else:
+            dtype = None
+        return scalar_w(interp.space, dtype, w_res)
 
 _REGEXES = [
     ('-?[\d\.]+', 'number'),
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -8,6 +8,7 @@
 from pypy.tool.sourcetools import func_with_new_name
 
 
+MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else ()
 MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
 
 def new_dtype_getter(name):
@@ -28,6 +29,7 @@
     def convert_to(self, dtype):
         return dtype.box(self.value)
 
+
 class W_GenericBox(Wrappable):
     _attrs_ = ()
 
@@ -93,7 +95,7 @@
     descr_neg = _unaryop_impl("negative")
     descr_abs = _unaryop_impl("absolute")
 
-    def descr_tolist(self, space):
+    def item(self, space):
         return self.get_dtype(space).itemtype.to_builtin_type(space, self)
 
 
@@ -104,7 +106,8 @@
     _attrs_ = ()
 
 class W_IntegerBox(W_NumberBox):
-    pass
+    def int_w(self, space):
+        return space.int_w(self.descr_int(space))
 
 class W_SignedIntegerBox(W_IntegerBox):
     pass
@@ -187,7 +190,7 @@
     __neg__ = interp2app(W_GenericBox.descr_neg),
     __abs__ = interp2app(W_GenericBox.descr_abs),
 
-    tolist = interp2app(W_GenericBox.descr_tolist),
+    tolist = interp2app(W_GenericBox.item),
 )
 
 W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
@@ -231,7 +234,7 @@
     __new__ = interp2app(W_UInt16Box.descr__new__.im_func),
 )
 
-W_Int32Box.typedef = TypeDef("int32", W_SignedIntegerBox.typedef,
+W_Int32Box.typedef = TypeDef("int32", (W_SignedIntegerBox.typedef,) + MIXIN_32,
     __module__ = "numpypy",
     __new__ = interp2app(W_Int32Box.descr__new__.im_func),
 )
@@ -241,24 +244,18 @@
     __new__ = interp2app(W_UInt32Box.descr__new__.im_func),
 )
 
-if LONG_BIT == 32:
-    long_name = "int32"
-elif LONG_BIT == 64:
-    long_name = "int64"
-W_LongBox.typedef = TypeDef(long_name, (W_SignedIntegerBox.typedef, int_typedef,),
-    __module__ = "numpypy",
-   __new__ = interp2app(W_LongBox.descr__new__.im_func),
-)
-
-W_ULongBox.typedef = TypeDef("u" + long_name, W_UnsignedIntegerBox.typedef,
-    __module__ = "numpypy",
-)
-
 W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
     __module__ = "numpypy",
     __new__ = interp2app(W_Int64Box.descr__new__.im_func),
 )
 
+if LONG_BIT == 32:
+    W_LongBox = W_Int32Box
+    W_ULongBox = W_UInt32Box
+elif LONG_BIT == 64:
+    W_LongBox = W_Int64Box
+    W_ULongBox = W_UInt64Box
+
 W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntegerBox.typedef,
     __module__ = "numpypy",
     __new__ = interp2app(W_UInt64Box.descr__new__.im_func),
@@ -283,3 +280,4 @@
 
     __new__ = interp2app(W_Float64Box.descr__new__.im_func),
 )
+
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -89,8 +89,19 @@
     def descr_get_shape(self, space):
         return space.newtuple([])
 
+    def eq(self, space, w_other):
+        w_other = space.call_function(space.gettypefor(W_Dtype), w_other)
+        return space.is_w(self, w_other)
+
+    def descr_eq(self, space, w_other):
+        return space.wrap(self.eq(space, w_other))
+
+    def descr_ne(self, space, w_other):
+        return space.wrap(not self.eq(space, w_other))
+
     def is_int_type(self):
-        return self.kind == SIGNEDLTR or self.kind == UNSIGNEDLTR
+        return (self.kind == SIGNEDLTR or self.kind == UNSIGNEDLTR or
+                self.kind == BOOLLTR)
 
     def is_bool_type(self):
         return self.kind == BOOLLTR
@@ -101,12 +112,15 @@
 
     __str__= interp2app(W_Dtype.descr_str),
     __repr__ = interp2app(W_Dtype.descr_repr),
+    __eq__ = interp2app(W_Dtype.descr_eq),
+    __ne__ = interp2app(W_Dtype.descr_ne),
 
     num = interp_attrproperty("num", cls=W_Dtype),
     kind = interp_attrproperty("kind", cls=W_Dtype),
     type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
     itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
     shape = GetSetProperty(W_Dtype.descr_get_shape),
+    name = interp_attrproperty('name', cls=W_Dtype),
 )
 W_Dtype.typedef.acceptable_as_base_class = False
 
diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py
--- a/pypy/module/micronumpy/interp_iter.py
+++ b/pypy/module/micronumpy/interp_iter.py
@@ -4,6 +4,49 @@
 from pypy.module.micronumpy.strides import calculate_broadcast_strides,\
      calculate_slice_strides
 
+""" This is a mini-tutorial on iterators, strides, and
+memory layout. It assumes you are familiar with the terms, see
+http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html
+for a more gentle introduction.
+
+Given an array x: x.shape == [5,6],
+
+At which byte in x.data does the item x[3,4] begin?
+if x.strides==[1,5]:
+    pData = x.pData + (x.start + 3*1 + 4*5)*sizeof(x.pData[0])
+    pData = x.pData + (x.start + 24) * sizeof(x.pData[0])
+so the offset of the element is 24 elements after the first
+
+What is the next element in x after coordinates [3,4]?
+if x.order =='C':
+   next == [3,5] => offset is 28
+if x.order =='F':
+   next == [4,4] => offset is 24
+so for the strides [1,5] x is 'F' contiguous
+likewise, for the strides [6,1] x would be 'C' contiguous.
+
+Iterators have an internal representation of the current coordinates
+(indices), the array, strides, and backstrides. A short digression to
+explain backstrides: what is the coordinate and offset after [3,5] in
+the example above?
+if x.order == 'C':
+   next == [4,0] => offset is 4
+if x.order == 'F':
+   next == [4,5] => offset is 25
+Note that in 'C' order we stepped BACKWARDS 24 while 'overflowing' a
+shape dimension
+  which is back 25 and forward 1,
+  which is x.strides[1] * (x.shape[1] - 1) + x.strides[0]
+so if we precalculate the overflow backstride as 
+[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_step_x() tries to do the iteration for a number of steps at once,
+but then we cannot gaurentee that we only overflow one single shape 
+dimension, perhaps we could overflow times in one big step.
+"""
+
 # structures to describe slicing
 
 class Chunk(object):
@@ -17,6 +60,10 @@
         if self.step != 0:
             shape.append(self.lgt)
 
+    def __repr__(self):
+        return 'Chunk(%d, %d, %d, %d)' % (self.start, self.stop, self.step,
+                                          self.lgt)
+
 class BaseTransform(object):
     pass
 
@@ -51,9 +98,9 @@
         self.size = size
 
     def next(self, shapelen):
-        return self._next(1)
+        return self.next_skip_x(1)
 
-    def _next(self, ofs):
+    def next_skip_x(self, ofs):
         arr = instantiate(ArrayIterator)
         arr.size = self.size
         arr.offset = self.offset + ofs
@@ -61,7 +108,7 @@
 
     def next_no_increase(self, shapelen):
         # a hack to make JIT believe this is always virtual
-        return self._next(0)
+        return self.next_skip_x(0)
 
     def done(self):
         return self.offset >= self.size
@@ -133,6 +180,36 @@
         res._done = done
         return res
 
+    @jit.unroll_safe
+    def next_skip_x(self, shapelen, step):
+        shapelen = jit.promote(len(self.res_shape))
+        offset = self.offset
+        indices = [0] * shapelen
+        for i in range(shapelen):
+            indices[i] = self.indices[i]
+        done = False
+        for i in range(shapelen - 1, -1, -1):
+            if indices[i] < self.res_shape[i] - step:
+                indices[i] += step
+                offset += self.strides[i] * step
+                break
+            else:
+                remaining_step = (indices[i] + step) // self.res_shape[i]
+                this_i_step = step - remaining_step * self.res_shape[i]
+                offset += self.strides[i] * this_i_step
+                indices[i] = indices[i] +  this_i_step
+                step = remaining_step
+        else:
+            done = True
+        res = instantiate(ViewIterator)
+        res.offset = offset
+        res.indices = indices
+        res.strides = self.strides
+        res.backstrides = self.backstrides
+        res.res_shape = self.res_shape
+        res._done = done
+        return res
+
     def apply_transformations(self, arr, transformations):
         v = BaseIterator.apply_transformations(self, arr, transformations)
         if len(arr.shape) == 1:
@@ -153,8 +230,13 @@
 class AxisIterator(BaseIterator):
     def __init__(self, start, dim, shape, strides, backstrides):
         self.res_shape = shape[:]
-        self.strides = strides[:dim] + [0] + strides[dim:]
-        self.backstrides = backstrides[:dim] + [0] + backstrides[dim:]
+        if len(shape) == len(strides):
+            # keepdims = True
+            self.strides = strides[:dim] + [0] + strides[dim + 1:]
+            self.backstrides = backstrides[:dim] + [0] + backstrides[dim + 1:]
+        else:
+            self.strides = strides[:dim] + [0] + strides[dim:]
+            self.backstrides = backstrides[:dim] + [0] + backstrides[dim:]
         self.first_line = True
         self.indices = [0] * len(shape)
         self._done = False
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -1,16 +1,20 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.module.micronumpy import interp_ufuncs, interp_dtype, signature,\
-     interp_boxes
-from pypy.module.micronumpy.strides import calculate_slice_strides
+from pypy.module.micronumpy import (interp_ufuncs, interp_dtype, interp_boxes,
+    signature, support)
+from pypy.module.micronumpy.strides import (calculate_slice_strides,
+    shape_agreement, find_shape_and_elems, get_shape_from_iterable,
+    calc_new_strides, to_coords)
 from pypy.rlib import jit
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.rstring import StringBuilder
-from pypy.module.micronumpy.interp_iter import ArrayIterator, OneDimIterator,\
-     SkipLastAxisIterator, Chunk, ViewIterator
+from pypy.module.micronumpy.interp_iter import (ArrayIterator, OneDimIterator,
+    SkipLastAxisIterator, Chunk, ViewIterator)
+from pypy.module.micronumpy.appbridge import get_appbridge_cache
+
 
 numpy_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
@@ -58,176 +62,21 @@
     reds=['idx', 'idxi', 'frame', 'arr'],
     name='numpy_filterset',
 )
-
-def _find_shape_and_elems(space, w_iterable):
-    shape = [space.len_w(w_iterable)]
-    batch = space.listview(w_iterable)
-    while True:
-        new_batch = []
-        if not batch:
-            return shape, []
-        if not space.issequence_w(batch[0]):
-            for elem in batch:
-                if space.issequence_w(elem):
-                    raise OperationError(space.w_ValueError, space.wrap(
-                        "setting an array element with a sequence"))
-            return shape, batch
-        size = space.len_w(batch[0])
-        for w_elem in batch:
-            if not space.issequence_w(w_elem) or space.len_w(w_elem) != size:
-                raise OperationError(space.w_ValueError, space.wrap(
-                    "setting an array element with a sequence"))
-            new_batch += space.listview(w_elem)
-        shape.append(size)
-        batch = new_batch
-
-def shape_agreement(space, shape1, shape2):
-    ret = _shape_agreement(shape1, shape2)
-    if len(ret) < max(len(shape1), len(shape2)):
-        raise OperationError(space.w_ValueError,
-            space.wrap("operands could not be broadcast together with shapes (%s) (%s)" % (
-                ",".join([str(x) for x in shape1]),
-                ",".join([str(x) for x in shape2]),
-            ))
-        )
-    return ret
-
-def _shape_agreement(shape1, shape2):
-    """ Checks agreement about two shapes with respect to broadcasting. Returns
-    the resulting shape.
-    """
-    lshift = 0
-    rshift = 0
-    if len(shape1) > len(shape2):
-        m = len(shape1)
-        n = len(shape2)
-        rshift = len(shape2) - len(shape1)
-        remainder = shape1
-    else:
-        m = len(shape2)
-        n = len(shape1)
-        lshift = len(shape1) - len(shape2)
-        remainder = shape2
-    endshape = [0] * m
-    indices1 = [True] * m
-    indices2 = [True] * m
-    for i in range(m - 1, m - n - 1, -1):
-        left = shape1[i + lshift]
-        right = shape2[i + rshift]
-        if left == right:
-            endshape[i] = left
-        elif left == 1:
-            endshape[i] = right
-            indices1[i + lshift] = False
-        elif right == 1:
-            endshape[i] = left
-            indices2[i + rshift] = False
-        else:
-            return []
-            #raise OperationError(space.w_ValueError, space.wrap(
-            #    "frames are not aligned"))
-    for i in range(m - n):
-        endshape[i] = remainder[i]
-    return endshape
-
-def get_shape_from_iterable(space, old_size, w_iterable):
-    new_size = 0
-    new_shape = []
-    if space.isinstance_w(w_iterable, space.w_int):
-        new_size = space.int_w(w_iterable)
-        if new_size < 0:
-            new_size = old_size
-        new_shape = [new_size]
-    else:
-        neg_dim = -1
-        batch = space.listview(w_iterable)
-        new_size = 1
-        if len(batch) < 1:
-            if old_size == 1:
-                # Scalars can have an empty size.
-                new_size = 1
-            else:
-                new_size = 0
-        new_shape = []
-        i = 0
-        for elem in batch:
-            s = space.int_w(elem)
-            if s < 0:
-                if neg_dim >= 0:
-                    raise OperationError(space.w_ValueError, space.wrap(
-                             "can only specify one unknown dimension"))
-                s = 1
-                neg_dim = i
-            new_size *= s
-            new_shape.append(s)
-            i += 1
-        if neg_dim >= 0:
-            new_shape[neg_dim] = old_size / new_size
-            new_size *= new_shape[neg_dim]
-    if new_size != old_size:
-        raise OperationError(space.w_ValueError,
-                space.wrap("total size of new array must be unchanged"))
-    return new_shape
-
-# Recalculating strides. Find the steps that the iteration does for each
-# dimension, given the stride and shape. Then try to create a new stride that
-# fits the new shape, using those steps. If there is a shape/step mismatch
-# (meaning that the realignment of elements crosses from one step into another)
-# return None so that the caller can raise an exception.
-def calc_new_strides(new_shape, old_shape, old_strides):
-    # Assumes that prod(old_shape) == prod(new_shape), len(old_shape) > 1, and
-    # len(new_shape) > 0
-    steps = []
-    last_step = 1
-    oldI = 0
-    new_strides = []
-    if old_strides[0] < old_strides[-1]:
-        #Start at old_shape[0], old_stides[0]
-        for i in range(len(old_shape)):
-            steps.append(old_strides[i] / last_step)
-            last_step *= old_shape[i]
-        cur_step = steps[0]
-        n_new_elems_used = 1
-        n_old_elems_to_use = old_shape[0]
-        for s in new_shape:
-            new_strides.append(cur_step * n_new_elems_used)
-            n_new_elems_used *= s
-            while n_new_elems_used > n_old_elems_to_use:
-                oldI += 1
-                if steps[oldI] != steps[oldI - 1]:
-                    return None
-                n_old_elems_to_use *= old_shape[oldI]
-            if n_new_elems_used == n_old_elems_to_use:
-                oldI += 1
-                if oldI >= len(old_shape):
-                    continue
-                cur_step = steps[oldI]
-                n_old_elems_to_use *= old_shape[oldI]
-    else:
-        #Start at old_shape[-1], old_strides[-1]
-        for i in range(len(old_shape) - 1, -1, -1):
-            steps.insert(0, old_strides[i] / last_step)
-            last_step *= old_shape[i]
-        cur_step = steps[-1]
-        n_new_elems_used = 1
-        oldI = -1
-        n_old_elems_to_use = old_shape[-1]
-        for i in range(len(new_shape) - 1, -1, -1):
-            s = new_shape[i]
-            new_strides.insert(0, cur_step * n_new_elems_used)
-            n_new_elems_used *= s
-            while n_new_elems_used > n_old_elems_to_use:
-                oldI -= 1
-                if steps[oldI] != steps[oldI + 1]:
-                    return None
-                n_old_elems_to_use *= old_shape[oldI]
-            if n_new_elems_used == n_old_elems_to_use:
-                oldI -= 1
-                if oldI < -len(old_shape):
-                    continue
-                cur_step = steps[oldI]
-                n_old_elems_to_use *= old_shape[oldI]
-    return new_strides
+take_driver = jit.JitDriver(
+    greens=['shapelen', 'sig'],
+    reds=['index_i', 'res_i', 'concr', 'index', 'res'],
+    name='numpy_take',
+)
+flat_get_driver = jit.JitDriver(
+    greens=['shapelen', 'base'],
+    reds=['step', 'ri', 'basei', 'res'],
+    name='numpy_flatget',
+)
+flat_set_driver = jit.JitDriver(
+    greens=['shapelen', 'base'],
+    reds=['step', 'ai', 'lngth', 'arr', 'basei'],
+    name='numpy_flatset',
+)
 
 class BaseArray(Wrappable):
     _attrs_ = ["invalidates", "shape", 'size']
@@ -268,6 +117,7 @@
     descr_pos = _unaryop_impl("positive")
     descr_neg = _unaryop_impl("negative")
     descr_abs = _unaryop_impl("absolute")
+    descr_invert = _unaryop_impl("invert")
 
     def _binop_impl(ufunc_name):
         def impl(self, space, w_other):
@@ -310,9 +160,11 @@
     def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False):
         def impl(self, space, w_axis=None):
             if space.is_w(w_axis, space.w_None):
-                w_axis = space.wrap(-1)
+                axis = -1
+            else:
+                axis = space.int_w(w_axis)
             return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space,
-                                        self, True, promote_to_largest, w_axis)
+                                        self, True, promote_to_largest, axis)
         return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
 
     descr_sum = _reduce_ufunc_impl("add")
@@ -430,9 +282,23 @@
     def descr_copy(self, space):
         return self.copy(space)
 
+    def descr_flatten(self, space, w_order=None):
+        if isinstance(self, Scalar):
+            # scalars have no storage
+            return self.descr_reshape(space, [space.wrap(1)])
+        concr = self.get_concrete()
+        w_res = concr.descr_ravel(space, w_order)
+        if w_res.storage == concr.storage:
+            return w_res.copy(space)
+        return w_res
+
     def copy(self, space):
         return self.get_concrete().copy(space)
 
+    def empty_copy(self, space, dtype):
+        shape = self.shape
+        return W_NDimArray(support.product(shape), shape[:], dtype, 'C')
+
     def descr_len(self, space):
         if len(self.shape):
             return space.wrap(self.shape[0])
@@ -440,33 +306,32 @@
             "len() of unsized object"))
 
     def descr_repr(self, space):
-        res = StringBuilder()
-        res.append("array(")
-        concrete = self.get_concrete_or_scalar()
-        dtype = concrete.find_dtype()
-        if not concrete.size:
-            res.append('[]')
-            if len(self.shape) > 1:
-                # An empty slice reports its shape
-                res.append(", shape=(")
-                self_shape = str(self.shape)
-                res.append_slice(str(self_shape), 1, len(self_shape) - 1)
-                res.append(')')
-        else:
-            concrete.to_str(space, 1, res, indent='       ')
-        if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
-            not (dtype.kind == interp_dtype.SIGNEDLTR and
-            dtype.itemtype.get_element_size() == rffi.sizeof(lltype.Signed)) or
-            not self.size):
-            res.append(", dtype=" + dtype.name)
-        res.append(")")
-        return space.wrap(res.build())
+        cache = get_appbridge_cache(space)
+        if cache.w_array_repr is None:
+            return space.wrap(self.dump_data())
+        return space.call_function(cache.w_array_repr, self)
+
+    def dump_data(self):
+        concr = self.get_concrete()
+        i = concr.create_iter()
+        first = True
+        s = StringBuilder()
+        s.append('array([')
+        while not i.done():
+            if first:
+                first = False
+            else:
+                s.append(', ')
+            s.append(concr.dtype.itemtype.str_format(concr.getitem(i.offset)))
+            i = i.next(len(concr.shape))
+        s.append('])')
+        return s.build()
 
     def descr_str(self, space):
-        ret = StringBuilder()
-        concrete = self.get_concrete_or_scalar()
-        concrete.to_str(space, 0, ret, ' ')
-        return space.wrap(ret.build())
+        cache = get_appbridge_cache(space)
+        if cache.w_array_str is None:
+            return space.wrap(self.dump_data())
+        return space.call_function(cache.w_array_str, self)
 
     @jit.unroll_safe
     def _single_item_result(self, space, w_idx):
@@ -506,7 +371,7 @@
 
     def count_all_true(self, arr):
         sig = arr.find_sig()
-        frame = sig.create_frame(self)
+        frame = sig.create_frame(arr)
         shapelen = len(arr.shape)
         s = 0
         iter = None
@@ -520,6 +385,9 @@
 
     def getitem_filter(self, space, arr):
         concr = arr.get_concrete()
+        if concr.size > self.size:
+            raise OperationError(space.w_IndexError,
+                                 space.wrap("index out of range for array"))
         size = self.count_all_true(concr)
         res = W_NDimArray(size, [size], self.find_dtype())
         ri = ArrayIterator(size)
@@ -528,7 +396,7 @@
         sig = self.find_sig()
         frame = sig.create_frame(self)
         v = None
-        while not frame.done():
+        while not ri.done():
             filter_driver.jit_merge_point(concr=concr, argi=argi, ri=ri,
                                           frame=frame, v=v, res=res, sig=sig,
                                           shapelen=shapelen, self=self)
@@ -568,7 +436,7 @@
             item = concrete._index_of_single_item(space, w_idx)
             return concrete.getitem(item)
         chunks = self._prepare_slice_args(space, w_idx)
-        return space.wrap(self.create_slice(chunks))
+        return self.create_slice(chunks)
 
     def descr_setitem(self, space, w_idx, w_value):
         self.invalidated()
@@ -622,11 +490,14 @@
             w_shape = args_w[0]
         else:
             w_shape = space.newtuple(args_w)
+        new_shape = get_shape_from_iterable(space, self.size, w_shape)
+        return self.reshape(space, new_shape)
+        
+    def reshape(self, space, new_shape):
         concrete = self.get_concrete()
-        new_shape = get_shape_from_iterable(space, concrete.size, w_shape)
         # Since we got to here, prod(new_shape) == self.size
-        new_strides = calc_new_strides(new_shape,
-                                       concrete.shape, concrete.strides)
+        new_strides = calc_new_strides(new_shape, concrete.shape,
+                                     concrete.strides, concrete.order)
         if new_strides:
             # We can create a view, strides somehow match up.
             ndims = len(new_shape)
@@ -634,7 +505,7 @@
             for nd in range(ndims):
                 new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
             arr = W_NDimSlice(concrete.start, new_strides, new_backstrides,
-                              new_shape, self)
+                              new_shape, concrete)
         else:
             # Create copy with contiguous data
             arr = concrete.copy(space)
@@ -644,7 +515,7 @@
     def descr_tolist(self, space):
         if len(self.shape) == 0:
             assert isinstance(self, Scalar)
-            return self.value.descr_tolist(space)
+            return self.value.item(space)
         w_result = space.newlist([])
         for i in range(self.shape[0]):
             space.call_method(w_result, "append",
@@ -661,17 +532,13 @@
             w_denom = space.wrap(self.shape[dim])
         return space.div(self.descr_sum_promote(space, w_axis), w_denom)
 
-    def descr_var(self, space):
-        # var = mean((values - mean(values)) ** 2)
-        w_res = self.descr_sub(space, self.descr_mean(space, space.w_None))
-        assert isinstance(w_res, BaseArray)
-        w_res = w_res.descr_pow(space, space.wrap(2))
-        assert isinstance(w_res, BaseArray)
-        return w_res.descr_mean(space, space.w_None)
+    def descr_var(self, space, w_axis=None):
+        return get_appbridge_cache(space).call_method(space, '_var', self,
+                                                      w_axis)
 
-    def descr_std(self, space):
-        # std(v) = sqrt(var(v))
-        return interp_ufuncs.get(space).sqrt.call(space, [self.descr_var(space)])
+    def descr_std(self, space, w_axis=None):
+        return get_appbridge_cache(space).call_method(space, '_std', self,
+                                                      w_axis)
 
     def descr_fill(self, space, w_value):
         concr = self.get_concrete_or_scalar()
@@ -704,6 +571,16 @@
         return space.wrap(W_NDimSlice(concrete.start, strides,
                                       backstrides, shape, concrete))
 
+    def descr_ravel(self, space, w_order=None):
+        if w_order is None or space.is_w(w_order, space.w_None):
+            order = 'C'
+        else:
+            order = space.str_w(w_order)
+        if order != 'C':
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "order not implemented"))
+        return self.descr_reshape(space, [space.wrap(-1)])
+
     def descr_get_flatiter(self, space):
         return space.wrap(W_FlatIterator(self))
 
@@ -733,6 +610,60 @@
     def supports_fast_slicing(self):
         return False
 
+    def descr_compress(self, space, w_obj, w_axis=None):
+        index = convert_to_array(space, w_obj)
+        return self.getitem_filter(space, index)
+
+    def descr_take(self, space, w_obj, w_axis=None):
+        index = convert_to_array(space, w_obj).get_concrete()
+        concr = self.get_concrete()
+        if space.is_w(w_axis, space.w_None):
+            concr = concr.descr_ravel(space)
+        else:
+            raise OperationError(space.w_NotImplementedError,
+                                 space.wrap("axis unsupported for take"))
+        index_i = index.create_iter()
+        res_shape = index.shape
+        size = support.product(res_shape)
+        res = W_NDimArray(size, res_shape[:], concr.dtype, concr.order)
+        res_i = res.create_iter()
+        shapelen = len(index.shape)
+        sig = concr.find_sig()
+        while not index_i.done():
+            take_driver.jit_merge_point(index_i=index_i, index=index,
+                                        res_i=res_i, concr=concr,
+                                        res=res,
+                                        shapelen=shapelen, sig=sig)
+            w_item = index._getitem_long(space, index_i.offset)
+            res.setitem(res_i.offset, concr.descr_getitem(space, w_item))
+            index_i = index_i.next(shapelen)
+            res_i = res_i.next(shapelen)
+        return res
+
+    def _getitem_long(self, space, offset):
+        # an obscure hack to not have longdtype inside a jitted loop
+        longdtype = interp_dtype.get_dtype_cache(space).w_longdtype
+        return self.getitem(offset).convert_to(longdtype).item(
+            space)
+
+    def descr_item(self, space, w_arg=None):
+        if space.is_w(w_arg, space.w_None):
+            if not isinstance(self, Scalar):
+                raise OperationError(space.w_ValueError, space.wrap("index out of bounds"))
+            return self.value.item(space)
+        if space.isinstance_w(w_arg, space.w_int):
+            if isinstance(self, Scalar):
+                raise OperationError(space.w_ValueError, space.wrap("index out of bounds"))
+            concr = self.get_concrete()
+            i = to_coords(space, self.shape, concr.size, concr.order, w_arg)[0]
+            # XXX a bit around
+            item = self.descr_getitem(space, space.newtuple([space.wrap(x)
+                                             for x in i]))
+            assert isinstance(item, interp_boxes.W_GenericBox)
+            return item.item(space)
+        raise OperationError(space.w_NotImplementedError, space.wrap(
+            "non-int arg not supported"))
+
 def convert_to_array(space, w_obj):
     if isinstance(w_obj, BaseArray):
         return w_obj
@@ -758,14 +689,12 @@
         self.shape = []
         BaseArray.__init__(self, [])
         self.dtype = dtype
+        assert isinstance(value, interp_boxes.W_GenericBox)
         self.value = value
 
     def find_dtype(self):
         return self.dtype
 
-    def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
-        builder.append(self.dtype.itemtype.str_format(self.value))
-
     def copy(self, space):
         return Scalar(self.dtype, self.value)
 
@@ -778,6 +707,11 @@
     def get_concrete_or_scalar(self):
         return self
 
+    def reshape(self, space, new_shape):
+        size = support.product(new_shape)
+        res = W_NDimArray(size, new_shape, self.dtype, 'C')
+        res.setitem(0, self.value)
+        return res
 
 class VirtualArray(BaseArray):
     """
@@ -834,12 +768,9 @@
 
 class VirtualSlice(VirtualArray):
     def __init__(self, child, chunks, shape):
-        size = 1
-        for sh in shape:
-            size *= sh
         self.child = child
         self.chunks = chunks
-        self.size = size
+        self.size = support.product(shape)
         VirtualArray.__init__(self, 'slice', shape, child.find_dtype())
 
     def create_sig(self):
@@ -858,11 +789,12 @@
 
 
 class Call1(VirtualArray):
-    def __init__(self, ufunc, name, shape, res_dtype, values):
+    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values):
         VirtualArray.__init__(self, name, shape, res_dtype)
         self.values = values
         self.size = values.size
         self.ufunc = ufunc
+        self.calc_dtype = calc_dtype
 
     def _del_sources(self):
         self.values = None
@@ -884,9 +816,7 @@
         self.left = left
         self.right = right
         self.calc_dtype = calc_dtype
-        self.size = 1
-        for s in self.shape:
-            self.size *= s
+        self.size = support.product(self.shape)
 
     def _del_sources(self):
         self.left = None
@@ -914,14 +844,15 @@
                                self.left.create_sig(), self.right.create_sig())
 
 class SliceArray(Call2):
-    def __init__(self, shape, dtype, left, right):
+    def __init__(self, shape, dtype, left, right, no_broadcast=False):
+        self.no_broadcast = no_broadcast
         Call2.__init__(self, None, 'sliceloop', shape, dtype, dtype, left,
                        right)
 
     def create_sig(self):
         lsig = self.left.create_sig()
         rsig = self.right.create_sig()
-        if self.shape != self.right.shape:
+        if not self.no_broadcast and self.shape != self.right.shape:
             return signature.SliceloopBroadcastSignature(self.ufunc,
                                                          self.name,
                                                          self.calc_dtype,
@@ -995,89 +926,6 @@
         self.strides = strides
         self.backstrides = backstrides
 
-    def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
-        '''Modifies builder with a representation of the array/slice
-        The items will be seperated by a comma if comma is 1
-        Multidimensional arrays/slices will span a number of lines,
-        each line will begin with indent.
-        '''
-        size = self.size
-        ccomma = ',' * comma
-        ncomma = ',' * (1 - comma)
-        dtype = self.find_dtype()
-        if size < 1:
-            builder.append('[]')
-            return
-        if size > 1000:
-            # Once this goes True it does not go back to False for recursive
-            # calls
-            use_ellipsis = True
-        ndims = len(self.shape)
-        if ndims == 0:
-            builder.append(dtype.itemtype.str_format(self.getitem(0)))
-            return
-        i = 0
-        builder.append('[')
-        if ndims > 1:
-            if use_ellipsis:
-                for i in range(min(3, self.shape[0])):
-                    if i > 0:
-                        builder.append(ccomma + '\n')
-                        if ndims >= 3:
-                            builder.append('\n' + indent)
-                        else:
-                            builder.append(indent)
-                    view = self.create_slice([Chunk(i, 0, 0, 1)]).get_concrete()
-                    view.to_str(space, comma, builder, indent=indent + ' ',
-                                                    use_ellipsis=use_ellipsis)
-                if i < self.shape[0] - 1:
-                    builder.append(ccomma + '\n' + indent + '...' + ncomma)
-                    i = self.shape[0] - 3
-                else:
-                    i += 1
-            while i < self.shape[0]:
-                if i > 0:
-                    builder.append(ccomma + '\n')
-                    if ndims >= 3:
-                        builder.append('\n' + indent)
-                    else:
-                        builder.append(indent)
-                # create_slice requires len(chunks) > 1 in order to reduce
-                # shape
-                view = self.create_slice([Chunk(i, 0, 0, 1)]).get_concrete()
-                view.to_str(space, comma, builder, indent=indent + ' ',
-                                                    use_ellipsis=use_ellipsis)
-                i += 1
-        elif ndims == 1:
-            spacer = ccomma + ' '
-            item = self.start
-            # An iterator would be a nicer way to walk along the 1d array, but
-            # how do I reset it if printing ellipsis? iterators have no
-            # "set_offset()"
-            i = 0
-            if use_ellipsis:
-                for i in range(min(3, self.shape[0])):
-                    if i > 0:
-                        builder.append(spacer)
-                    builder.append(dtype.itemtype.str_format(self.getitem(item)))
-                    item += self.strides[0]
-                if i < self.shape[0] - 1:
-                    # Add a comma only if comma is False - this prevents adding
-                    # two commas
-                    builder.append(spacer + '...' + ncomma)
-                    # Ugly, but can this be done with an iterator?
-                    item = self.start + self.backstrides[0] - 2 * self.strides[0]
-                    i = self.shape[0] - 3
-                else:
-                    i += 1
-            while i < self.shape[0]:
-                if i > 0:
-                    builder.append(spacer)
-                builder.append(dtype.itemtype.str_format(self.getitem(item)))
-                item += self.strides[0]
-                i += 1
-        builder.append(']')
-
     @jit.unroll_safe
     def _index_of_single_item(self, space, w_idx):
         if space.isinstance_w(w_idx, space.w_int):
@@ -1164,13 +1012,10 @@
         assert isinstance(parent, ConcreteArray)
         if isinstance(parent, W_NDimSlice):
             parent = parent.parent
-        size = 1
-        for sh in shape:
-            size *= sh
         self.strides = strides
         self.backstrides = backstrides
-        ViewArray.__init__(self, size, shape, parent.dtype, parent.order,
-                               parent)
+        ViewArray.__init__(self, support.product(shape), shape, parent.dtype,
+                           parent.order, parent)
         self.start = start
 
     def create_iter(self):
@@ -1200,7 +1045,8 @@
             self.backstrides = backstrides
             self.shape = new_shape
             return
-        new_strides = calc_new_strides(new_shape, self.shape, self.strides)
+        new_strides = calc_new_strides(new_shape, self.shape, self.strides,
+                                                   self.order)
         if new_strides is None:
             raise OperationError(space.w_AttributeError, space.wrap(
                           "incompatible shape for a non-contiguous array"))
@@ -1245,27 +1091,42 @@
             shape.append(item)
     return size, shape
 
-def array(space, w_item_or_iterable, w_dtype=None, w_order=NoneNotWrapped):
+ at unwrap_spec(subok=bool, copy=bool, ownmaskna=bool)
+def array(space, w_item_or_iterable, w_dtype=None, w_order=None,
+          subok=True, copy=True, w_maskna=None, ownmaskna=False):
     # find scalar
+    if w_maskna is None:
+        w_maskna = space.w_None
+    if (not subok or not space.is_w(w_maskna, space.w_None) or
+        ownmaskna):
+        raise OperationError(space.w_NotImplementedError, space.wrap("Unsupported args"))
     if not space.issequence_w(w_item_or_iterable):
-        if space.is_w(w_dtype, space.w_None):
+        if w_dtype is None or space.is_w(w_dtype, space.w_None):
             w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
                                                           w_item_or_iterable)
         dtype = space.interp_w(interp_dtype.W_Dtype,
             space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
         )
         return scalar_w(space, dtype, w_item_or_iterable)
-    if w_order is None:
+    if space.is_w(w_order, space.w_None) or w_order is None:
         order = 'C'
     else:
         order = space.str_w(w_order)
         if order != 'C':  # or order != 'F':
             raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
                                   order)
-    shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
+    if isinstance(w_item_or_iterable, BaseArray):
+        if (not space.is_w(w_dtype, space.w_None) and
+            w_item_or_iterable.find_dtype() is not w_dtype):
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "copying over different dtypes unsupported"))
+        if copy:
+            return w_item_or_iterable.copy(space)
+        return w_item_or_iterable
+    shape, elems_w = find_shape_and_elems(space, w_item_or_iterable)
     # they come back in C order
     size = len(elems_w)
-    if space.is_w(w_dtype, space.w_None):
+    if w_dtype is None or space.is_w(w_dtype, space.w_None):
         w_dtype = None
         for w_elem in elems_w:
             w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
@@ -1293,6 +1154,8 @@
         space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
     )
     size, shape = _find_size_and_shape(space, w_size)
+    if not shape:
+        return scalar_w(space, dtype, space.wrap(0))
     return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
 
 def ones(space, w_size, w_dtype=None):
@@ -1301,17 +1164,66 @@
     )
 
     size, shape = _find_size_and_shape(space, w_size)
+    if not shape:
+        return scalar_w(space, dtype, space.wrap(1))
     arr = W_NDimArray(size, shape[:], dtype=dtype)
     one = dtype.box(1)
     arr.dtype.fill(arr.storage, one, 0, size)
     return space.wrap(arr)
 
+ at unwrap_spec(arr=BaseArray, skipna=bool, keepdims=bool)
+def count_reduce_items(space, arr, w_axis=None, skipna=False, keepdims=True):
+    if not keepdims:
+        raise OperationError(space.w_NotImplementedError, space.wrap("unsupported"))
+    if space.is_w(w_axis, space.w_None):
+        return space.wrap(support.product(arr.shape))
+    if space.isinstance_w(w_axis, space.w_int):
+        return space.wrap(arr.shape[space.int_w(w_axis)])
+    s = 1
+    elems = space.fixedview(w_axis)
+    for w_elem in elems:
+        s *= arr.shape[space.int_w(w_elem)]
+    return space.wrap(s)
+
 def dot(space, w_obj, w_obj2):
     w_arr = convert_to_array(space, w_obj)
     if isinstance(w_arr, Scalar):
         return convert_to_array(space, w_obj2).descr_dot(space, w_arr)
     return w_arr.descr_dot(space, w_obj2)
 
+ at unwrap_spec(axis=int)
+def concatenate(space, w_args, axis=0):
+    args_w = space.listview(w_args)
+    if len(args_w) == 0:
+        raise OperationError(space.w_ValueError, space.wrap("concatenation of zero-length sequences is impossible"))
+    args_w = [convert_to_array(space, w_arg) for w_arg in args_w]
+    dtype = args_w[0].find_dtype()
+    shape = args_w[0].shape[:]
+    if len(shape) <= axis:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("bad axis argument"))
+    for arr in args_w[1:]:
+        dtype = interp_ufuncs.find_binop_result_dtype(space, dtype,
+                                                      arr.find_dtype())
+        if len(arr.shape) <= axis:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("bad axis argument"))
+        for i, axis_size in enumerate(arr.shape):
+            if len(arr.shape) != len(shape) or (i != axis and axis_size != shape[i]):
+                raise OperationError(space.w_ValueError, space.wrap(
+                    "array dimensions must agree except for axis being concatenated"))
+            elif i == axis:
+                shape[i] += axis_size
+    res = W_NDimArray(support.product(shape), shape, dtype, 'C')
+    chunks = [Chunk(0, i, 1, i) for i in shape]
+    axis_start = 0
+    for arr in args_w:
+        chunks[axis] = Chunk(axis_start, axis_start + arr.shape[axis], 1,
+                             arr.shape[axis])
+        res.create_slice(chunks).setslice(space, arr)
+        axis_start += arr.shape[axis]
+    return res
+
 BaseArray.typedef = TypeDef(
     'ndarray',
     __module__ = "numpypy",
@@ -1349,6 +1261,7 @@
 
     __and__ = interp2app(BaseArray.descr_and),
     __or__ = interp2app(BaseArray.descr_or),
+    __invert__ = interp2app(BaseArray.descr_invert),
 
     __repr__ = interp2app(BaseArray.descr_repr),
     __str__ = interp2app(BaseArray.descr_str),
@@ -1359,9 +1272,11 @@
                            BaseArray.descr_set_shape),
     size = GetSetProperty(BaseArray.descr_get_size),
     ndim = GetSetProperty(BaseArray.descr_get_ndim),
+    item = interp2app(BaseArray.descr_item),
 
     T = GetSetProperty(BaseArray.descr_get_transpose),
     flat = GetSetProperty(BaseArray.descr_get_flatiter),
+    ravel = interp2app(BaseArray.descr_ravel),
 
     mean = interp2app(BaseArray.descr_mean),
     sum = interp2app(BaseArray.descr_sum),
@@ -1379,8 +1294,11 @@
     fill = interp2app(BaseArray.descr_fill),
 
     copy = interp2app(BaseArray.descr_copy),
+    flatten = interp2app(BaseArray.descr_flatten),
     reshape = interp2app(BaseArray.descr_reshape),
     tolist = interp2app(BaseArray.descr_tolist),
+    take = interp2app(BaseArray.descr_take),
+    compress = interp2app(BaseArray.descr_compress),
 )
 
 
@@ -1389,30 +1307,129 @@
     @jit.unroll_safe
     def __init__(self, arr):
         arr = arr.get_concrete()
-        size = 1
-        for sh in arr.shape:
-            size *= sh
         self.strides = [arr.strides[-1]]
         self.backstrides = [arr.backstrides[-1]]
-        ViewArray.__init__(self, size, [size], arr.dtype, arr.order,
-                               arr)
         self.shapelen = len(arr.shape)
-        self.iter = OneDimIterator(arr.start, self.strides[0],
-                                   self.shape[0])
+        sig = arr.find_sig()
+        self.iter = sig.create_frame(arr).get_final_iter()
+        self.base = arr
+        self.index = 0
+        ViewArray.__init__(self, arr.size, [arr.size], arr.dtype, arr.order,
+                           arr)
 
     def descr_next(self, space):
         if self.iter.done():
             raise OperationError(space.w_StopIteration, space.w_None)
-        result = self.getitem(self.iter.offset)
+        result = self.base.getitem(self.iter.offset)
         self.iter = self.iter.next(self.shapelen)
+        self.index += 1
         return result
 
     def descr_iter(self):
         return self
 
+    def descr_index(self, space):
+        return space.wrap(self.index)
+
+    def descr_coords(self, space):
+        coords, step, lngth = to_coords(space, self.base.shape, 
+                            self.base.size, self.base.order, 
+                            space.wrap(self.index))
+        return space.newtuple([space.wrap(c) for c in coords])
+
+    @jit.unroll_safe
+    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 OperationError(space.w_IndexError,
+                                 space.wrap('unsupported iterator index'))
+        base = self.base
+        start, stop, step, lngth = space.decode_index4(w_idx, base.size)
+        # setslice would have been better, but flat[u:v] for arbitrary
+        # shapes of array a cannot be represented as a[x1:x2, y1:y2]
+        basei = ViewIterator(base.start, base.strides,
+                               base.backstrides,base.shape)
+        shapelen = len(base.shape)
+        basei = basei.next_skip_x(shapelen, start)
+        if lngth <2:
+            return base.getitem(basei.offset)
+        ri = ArrayIterator(lngth)
+        res = W_NDimArray(lngth, [lngth], base.dtype,
+                                    base.order)
+        while not ri.done():
+            flat_get_driver.jit_merge_point(shapelen=shapelen,
+                                             base=base,
+                                             basei=basei,
+                                             step=step,
+                                             res=res,
+                                             ri=ri,
+                                            ) 
+            w_val = base.getitem(basei.offset)
+            res.setitem(ri.offset,w_val)
+            basei = basei.next_skip_x(shapelen, step)
+            ri = ri.next(shapelen)
+        return res
+
+    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 OperationError(space.w_IndexError,
+                                 space.wrap('unsupported iterator index'))
+        base = self.base
+        start, stop, step, lngth = space.decode_index4(w_idx, base.size)
+        arr = convert_to_array(space, w_value)
+        ai = 0
+        basei = ViewIterator(base.start, base.strides,
+                               base.backstrides,base.shape)
+        shapelen = len(base.shape)
+        basei = basei.next_skip_x(shapelen, start)
+        while lngth > 0:
+            flat_set_driver.jit_merge_point(shapelen=shapelen,
+                                             basei=basei,
+                                             base=base,
+                                             step=step,
+                                             arr=arr,
+                                             ai=ai,
+                                             lngth=lngth,
+                                            ) 
+            v = arr.getitem(ai).convert_to(base.dtype)
+            base.setitem(basei.offset, v)
+            # need to repeat input values until all assignments are done
+            ai = (ai + 1) % arr.size
+            basei = basei.next_skip_x(shapelen, step)
+            lngth -= 1
+
+    def create_sig(self):
+        return signature.FlatSignature(self.base.dtype)
+
+    def descr_base(self, space):
+        return space.wrap(self.base)
+
 W_FlatIterator.typedef = TypeDef(
     'flatiter',
+    #__array__  = #MISSING
+    __iter__ = interp2app(W_FlatIterator.descr_iter),
+    __getitem__ = interp2app(W_FlatIterator.descr_getitem),
+    __setitem__ = interp2app(W_FlatIterator.descr_setitem),
+    __eq__ = interp2app(BaseArray.descr_eq),
+    __ne__ = interp2app(BaseArray.descr_ne),
+    __lt__ = interp2app(BaseArray.descr_lt),
+    __le__ = interp2app(BaseArray.descr_le),
+    __gt__ = interp2app(BaseArray.descr_gt),
+    __ge__ = interp2app(BaseArray.descr_ge),
+    #__sizeof__ #MISSING
+    base = GetSetProperty(W_FlatIterator.descr_base),
+    index = GetSetProperty(W_FlatIterator.descr_index),
+    coords = GetSetProperty(W_FlatIterator.descr_coords),
     next = interp2app(W_FlatIterator.descr_next),
-    __iter__ = interp2app(W_FlatIterator.descr_iter),
+
 )
 W_FlatIterator.acceptable_as_base_class = False
+
+def isna(space, w_obj):
+    if isinstance(w_obj, BaseArray):
+        arr = w_obj.empty_copy(space,
+                               interp_dtype.get_dtype_cache(space).w_booldtype)
+        arr.fill(space, space.wrap(False))
+        return arr
+    return space.wrap(False)
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -1,14 +1,15 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_boxes, interp_dtype
-from pypy.module.micronumpy.signature import ReduceSignature,\
-     find_sig, new_printable_location, AxisReduceSignature, ScalarSignature
+from pypy.module.micronumpy import interp_boxes, interp_dtype, support
+from pypy.module.micronumpy.signature import (ReduceSignature, find_sig,
+    new_printable_location, AxisReduceSignature, ScalarSignature)
 from pypy.rlib import jit
 from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.tool.sourcetools import func_with_new_name
 
+
 reduce_driver = jit.JitDriver(
     greens=['shapelen', "sig"],
     virtualizables=["frame"],
@@ -30,12 +31,14 @@
     _attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
     _immutable_fields_ = ["promote_to_float", "promote_bools", "name"]
 
-    def __init__(self, name, promote_to_float, promote_bools, identity):
+    def __init__(self, name, promote_to_float, promote_bools, identity,
+                 int_only):
         self.name = name
         self.promote_to_float = promote_to_float
         self.promote_bools = promote_bools
 
         self.identity = identity
+        self.int_only = int_only
 
     def descr_repr(self, space):
         return space.wrap("<ufunc '%s'>" % self.name)
@@ -46,19 +49,31 @@
         return self.identity
 
     def descr_call(self, space, __args__):
-        if __args__.keywords or len(__args__.arguments_w) < self.argcount:
+        args_w, kwds_w = __args__.unpack()
+        # it occurs to me that we don't support any datatypes that
+        # require casting, change it later when we do
+        kwds_w.pop('casting', None)
+        w_subok = kwds_w.pop('subok', None)
+        w_out = kwds_w.pop('out', space.w_None)
+        if ((w_subok is not None and space.is_true(w_subok)) or
+            not space.is_w(w_out, space.w_None)):
+            raise OperationError(space.w_NotImplementedError,
+                                 space.wrap("parameters unsupported"))
+        if kwds_w or len(args_w) < self.argcount:
             raise OperationError(space.w_ValueError,
                 space.wrap("invalid number of arguments")
             )
-        elif len(__args__.arguments_w) > self.argcount:
+        elif len(args_w) > self.argcount:
             # The extra arguments should actually be the output array, but we
             # don't support that yet.
             raise OperationError(space.w_TypeError,
                 space.wrap("invalid number of arguments")
             )
-        return self.call(space, __args__.arguments_w)
+        return self.call(space, args_w)
 
-    def descr_reduce(self, space, w_obj, w_dim=0):
+    @unwrap_spec(skipna=bool, keepdims=bool)
+    def descr_reduce(self, space, w_obj, w_axis=NoneNotWrapped, w_dtype=None,
+                     skipna=False, keepdims=False, w_out=None):
         """reduce(...)
         reduce(a, axis=0)
 
@@ -111,15 +126,24 @@
         array([[ 1,  5],
                [ 9, 13]])
         """
-        return self.reduce(space, w_obj, False, False, w_dim)
+        if not space.is_w(w_out, space.w_None):
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "out not supported"))
+        if w_axis is None:
+            axis = 0
+        elif space.is_w(w_axis, space.w_None):
+            axis = -1
+        else:
+            axis = space.int_w(w_axis)
+        return self.reduce(space, w_obj, False, False, axis, keepdims)
 
-    def reduce(self, space, w_obj, multidim, promote_to_largest, w_dim):
+    def reduce(self, space, w_obj, multidim, promote_to_largest, dim,
+               keepdims=False):
         from pypy.module.micronumpy.interp_numarray import convert_to_array, \
                                                            Scalar
         if self.argcount != 2:
             raise OperationError(space.w_ValueError, space.wrap("reduce only "
                 "supported for binary functions"))
-        dim = space.int_w(w_dim)
         assert isinstance(self, W_Ufunc2)
         obj = convert_to_array(space, w_obj)
         if dim >= len(obj.shape):
@@ -140,7 +164,7 @@
             raise operationerrfmt(space.w_ValueError, "zero-size array to "
                     "%s.reduce without identity", self.name)
         if shapelen > 1 and dim >= 0:
-            res = self.do_axis_reduce(obj, dtype, dim)
+            res = self.do_axis_reduce(obj, dtype, dim, keepdims)
             return space.wrap(res)
         scalarsig = ScalarSignature(dtype)
         sig = find_sig(ReduceSignature(self.func, self.name, dtype,
@@ -154,15 +178,15 @@
             value = self.identity.convert_to(dtype)
         return self.reduce_loop(shapelen, sig, frame, value, obj, dtype)
 
-    def do_axis_reduce(self, obj, dtype, dim):
+    def do_axis_reduce(self, obj, dtype, dim, keepdims):
         from pypy.module.micronumpy.interp_numarray import AxisReduce,\
              W_NDimArray
-        
-        shape = obj.shape[0:dim] + obj.shape[dim + 1:len(obj.shape)]
-        size = 1
-        for s in shape:
-            size *= s
-        result = W_NDimArray(size, shape, dtype)
+
+        if keepdims:
+            shape = obj.shape[:dim] + [1] + obj.shape[dim + 1:]
+        else:
+            shape = obj.shape[:dim] + obj.shape[dim + 1:]
+        result = W_NDimArray(support.product(shape), shape, dtype)
         rightsig = obj.create_sig()
         # note - this is just a wrapper so signature can fetch
         #        both left and right, nothing more, especially
@@ -224,10 +248,12 @@
     _immutable_fields_ = ["func", "name"]
 
     def __init__(self, func, name, promote_to_float=False, promote_bools=False,
-        identity=None):
+        identity=None, bool_result=False, int_only=False):
 
-        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
+        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity,
+                         int_only)
         self.func = func
+        self.bool_result = bool_result
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call1,
@@ -235,15 +261,19 @@
 
         [w_obj] = args_w
         w_obj = convert_to_array(space, w_obj)
-        res_dtype = find_unaryop_result_dtype(space,
-            w_obj.find_dtype(),
-            promote_to_float=self.promote_to_float,
-            promote_bools=self.promote_bools,
-        )
+        calc_dtype = find_unaryop_result_dtype(space,
+                                  w_obj.find_dtype(),
+                                  promote_to_float=self.promote_to_float,
+                                  promote_bools=self.promote_bools)
+        if self.bool_result:
+            res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+        else:
+            res_dtype = calc_dtype
         if isinstance(w_obj, Scalar):
-            return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
+            return space.wrap(self.func(calc_dtype, w_obj.value.convert_to(calc_dtype)))
 
-        w_res = Call1(self.func, self.name, w_obj.shape, res_dtype, w_obj)
+        w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, res_dtype,
+                      w_obj)
         w_obj.add_invalidates(w_res)
         return w_res
 
@@ -255,10 +285,10 @@
     def __init__(self, func, name, promote_to_float=False, promote_bools=False,
         identity=None, comparison_func=False, int_only=False):
 
-        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
+        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity,
+                         int_only)
         self.func = func
         self.comparison_func = comparison_func
-        self.int_only = int_only
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call2,
@@ -278,10 +308,10 @@
         else:
             res_dtype = calc_dtype
         if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
-            return self.func(calc_dtype,
+            return space.wrap(self.func(calc_dtype,
                 w_lhs.value.convert_to(calc_dtype),
                 w_rhs.value.convert_to(calc_dtype)
-            )
+            ))
 
         new_shape = shape_agreement(space, w_lhs.shape, w_rhs.shape)
         w_res = Call2(self.func, self.name,
@@ -404,12 +434,16 @@
     return interp_dtype.get_dtype_cache(space).w_float64dtype
 
 
-def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
+def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func,
+                       bool_result):
+    dtype_cache = interp_dtype.get_dtype_cache(space)
     if argcount == 1:
         def impl(res_dtype, value):
-            return getattr(res_dtype.itemtype, op_name)(value)
+            res = getattr(res_dtype.itemtype, op_name)(value)
+            if bool_result:
+                return dtype_cache.w_booldtype.box(res)
+            return res
     elif argcount == 2:
-        dtype_cache = interp_dtype.get_dtype_cache(space)
         def impl(res_dtype, lvalue, rvalue):
             res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue)
             if comparison_func:
@@ -428,7 +462,9 @@
                                                'int_only': True}),
             ("bitwise_or", "bitwise_or", 2, {"identity": 0,
                                              'int_only': True}),
+            ("invert", "invert", 1, {"int_only": True}),
             ("divide", "div", 2, {"promote_bools": True}),
+            ("true_divide", "div", 2, {"promote_to_float": True}),
             ("mod", "mod", 2, {"promote_bools": True}),
             ("power", "pow", 2, {"promote_bools": True}),
 
@@ -438,6 +474,8 @@
             ("less_equal", "le", 2, {"comparison_func": True}),
             ("greater", "gt", 2, {"comparison_func": True}),
             ("greater_equal", "ge", 2, {"comparison_func": True}),
+            ("isnan", "isnan", 1, {"bool_result": True}),
+            ("isinf", "isinf", 1, {"bool_result": True}),
 
             ("maximum", "max", 2),
             ("minimum", "min", 2),
@@ -480,6 +518,7 @@
 
         func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
             comparison_func=extra_kwargs.get("comparison_func", False),
+            bool_result=extra_kwargs.get("bool_result", False),
         )
         if argcount == 1:
             ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs)
@@ -489,3 +528,4 @@
 
 def get(space):
     return space.fromcache(UfuncState)
+
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -224,6 +224,18 @@
         return ViewIterator(arr.start, arr.strides, arr.backstrides,
                             arr.shape).apply_transformations(arr, transforms)
 
+class FlatSignature(ViewSignature):
+    def debug_repr(self):
+        return 'Flat'
+
+    def allocate_iter(self, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import W_FlatIterator
+        assert isinstance(arr, W_FlatIterator)
+        return ViewIterator(arr.base.start, arr.base.strides, 
+                    arr.base.backstrides,
+                    arr.base.shape).apply_transformations(arr.base,
+                                                         transforms)
+
 class VirtualSliceSignature(Signature):
     def __init__(self, child):
         self.child = child
@@ -293,8 +305,8 @@
     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import Call1
         assert isinstance(arr, Call1)
-        v = self.child.eval(frame, arr.values).convert_to(arr.res_dtype)
-        return self.unfunc(arr.res_dtype, v)
+        v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype)
+        return self.unfunc(arr.calc_dtype, v)
 
 class Call2(Signature):
     _immutable_fields_ = ['binfunc', 'name', 'calc_dtype', 'left', 'right']
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -1,5 +1,5 @@
 from pypy.rlib import jit
-
+from pypy.interpreter.error import OperationError
 
 @jit.look_inside_iff(lambda shape, start, strides, backstrides, chunks:
     jit.isconstant(len(chunks))
@@ -37,3 +37,196 @@
     rstrides = [0] * (len(res_shape) - len(orig_shape)) + rstrides
     rbackstrides = [0] * (len(res_shape) - len(orig_shape)) + rbackstrides
     return rstrides, rbackstrides
+
+def find_shape_and_elems(space, w_iterable):
+    shape = [space.len_w(w_iterable)]
+    batch = space.listview(w_iterable)
+    while True:
+        new_batch = []
+        if not batch:
+            return shape, []
+        if not space.issequence_w(batch[0]):
+            for elem in batch:
+                if space.issequence_w(elem):
+                    raise OperationError(space.w_ValueError, space.wrap(
+                        "setting an array element with a sequence"))
+            return shape, batch
+        size = space.len_w(batch[0])
+        for w_elem in batch:
+            if not space.issequence_w(w_elem) or space.len_w(w_elem) != size:
+                raise OperationError(space.w_ValueError, space.wrap(
+                    "setting an array element with a sequence"))
+            new_batch += space.listview(w_elem)
+        shape.append(size)
+        batch = new_batch
+
+def to_coords(space, shape, size, order, w_item_or_slice):
+    '''Returns a start coord, step, and length.
+    '''
+    start = lngth = step = 0
+    if not (space.isinstance_w(w_item_or_slice, space.w_int) or
+        space.isinstance_w(w_item_or_slice, space.w_slice)):
+        raise OperationError(space.w_IndexError,
+                             space.wrap('unsupported iterator index'))
+            
+    start, stop, step, lngth = space.decode_index4(w_item_or_slice, size)
+        
+    coords = [0] * len(shape)
+    i = start
+    if order == 'C':
+        for s in range(len(shape) -1, -1, -1):
+            coords[s] = i % shape[s]
+            i //= shape[s]
+    else:
+        for s in range(len(shape)):
+            coords[s] = i % shape[s]
+            i //= shape[s]
+    return coords, step, lngth
+
+def shape_agreement(space, shape1, shape2):
+    ret = _shape_agreement(shape1, shape2)
+    if len(ret) < max(len(shape1), len(shape2)):
+        raise OperationError(space.w_ValueError,
+            space.wrap("operands could not be broadcast together with shapes (%s) (%s)" % (
+                ",".join([str(x) for x in shape1]),
+                ",".join([str(x) for x in shape2]),
+            ))
+        )
+    return ret
+
+def _shape_agreement(shape1, shape2):
+    """ Checks agreement about two shapes with respect to broadcasting. Returns
+    the resulting shape.
+    """
+    lshift = 0
+    rshift = 0
+    if len(shape1) > len(shape2):
+        m = len(shape1)
+        n = len(shape2)
+        rshift = len(shape2) - len(shape1)
+        remainder = shape1
+    else:
+        m = len(shape2)
+        n = len(shape1)
+        lshift = len(shape1) - len(shape2)
+        remainder = shape2
+    endshape = [0] * m
+    indices1 = [True] * m
+    indices2 = [True] * m
+    for i in range(m - 1, m - n - 1, -1):
+        left = shape1[i + lshift]
+        right = shape2[i + rshift]
+        if left == right:
+            endshape[i] = left
+        elif left == 1:
+            endshape[i] = right
+            indices1[i + lshift] = False
+        elif right == 1:
+            endshape[i] = left
+            indices2[i + rshift] = False
+        else:
+            return []
+            #raise OperationError(space.w_ValueError, space.wrap(
+            #    "frames are not aligned"))
+    for i in range(m - n):
+        endshape[i] = remainder[i]
+    return endshape
+
+def get_shape_from_iterable(space, old_size, w_iterable):
+    new_size = 0
+    new_shape = []
+    if space.isinstance_w(w_iterable, space.w_int):
+        new_size = space.int_w(w_iterable)
+        if new_size < 0:
+            new_size = old_size
+        new_shape = [new_size]
+    else:
+        neg_dim = -1
+        batch = space.listview(w_iterable)
+        new_size = 1
+        if len(batch) < 1:
+            if old_size == 1:
+                # Scalars can have an empty size.
+                new_size = 1
+            else:
+                new_size = 0
+        new_shape = []
+        i = 0
+        for elem in batch:
+            s = space.int_w(elem)
+            if s < 0:
+                if neg_dim >= 0:
+                    raise OperationError(space.w_ValueError, space.wrap(
+                             "can only specify one unknown dimension"))
+                s = 1
+                neg_dim = i
+            new_size *= s
+            new_shape.append(s)
+            i += 1
+        if neg_dim >= 0:
+            new_shape[neg_dim] = old_size / new_size
+            new_size *= new_shape[neg_dim]
+    if new_size != old_size:
+        raise OperationError(space.w_ValueError,
+                space.wrap("total size of new array must be unchanged"))
+    return new_shape
+
+# Recalculating strides. Find the steps that the iteration does for each
+# dimension, given the stride and shape. Then try to create a new stride that
+# fits the new shape, using those steps. If there is a shape/step mismatch
+# (meaning that the realignment of elements crosses from one step into another)
+# return None so that the caller can raise an exception.
+def calc_new_strides(new_shape, old_shape, old_strides, order):
+    # Return the proper strides for new_shape, or None if the mapping crosses
+    # stepping boundaries
+
+    # Assumes that prod(old_shape) == prod(new_shape), len(old_shape) > 1, and
+    # len(new_shape) > 0
+    steps = []
+    last_step = 1
+    oldI = 0
+    new_strides = []
+    if order == 'F':
+        for i in range(len(old_shape)):
+            steps.append(old_strides[i] / last_step)
+            last_step *= old_shape[i]
+        cur_step = steps[0]
+        n_new_elems_used = 1
+        n_old_elems_to_use = old_shape[0]
+        for s in new_shape:
+            new_strides.append(cur_step * n_new_elems_used)
+            n_new_elems_used *= s
+            while n_new_elems_used > n_old_elems_to_use:
+                oldI += 1
+                if steps[oldI] != steps[oldI - 1]:
+                    return None
+                n_old_elems_to_use *= old_shape[oldI]
+            if n_new_elems_used == n_old_elems_to_use:
+                oldI += 1
+                if oldI < len(old_shape):
+                    cur_step = steps[oldI]
+                    n_old_elems_to_use *= old_shape[oldI]
+    elif order == 'C':
+        for i in range(len(old_shape) - 1, -1, -1):
+            steps.insert(0, old_strides[i] / last_step)
+            last_step *= old_shape[i]
+        cur_step = steps[-1]
+        n_new_elems_used = 1
+        oldI = -1
+        n_old_elems_to_use = old_shape[-1]
+        for i in range(len(new_shape) - 1, -1, -1):
+            s = new_shape[i]
+            new_strides.insert(0, cur_step * n_new_elems_used)
+            n_new_elems_used *= s
+            while n_new_elems_used > n_old_elems_to_use:
+                oldI -= 1
+                if steps[oldI] != steps[oldI + 1]:
+                    return None
+                n_old_elems_to_use *= old_shape[oldI]
+            if n_new_elems_used == n_old_elems_to_use:
+                oldI -= 1
+                if oldI >= -len(old_shape):
+                    cur_step = steps[oldI]
+                    n_old_elems_to_use *= old_shape[oldI]
+    assert len(new_strides) == len(new_shape)
+    return new_strides
diff --git a/pypy/module/micronumpy/support.py b/pypy/module/micronumpy/support.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/support.py
@@ -0,0 +1,5 @@
+def product(s):
+    i = 1
+    for x in s:
+        i *= x
+    return i
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -3,9 +3,17 @@
 from pypy.module.micronumpy.interp_numarray import W_NDimArray, Scalar
 from pypy.module.micronumpy.interp_ufuncs import (find_binop_result_dtype,
         find_unaryop_result_dtype)
+from pypy.module.micronumpy.interp_boxes import W_Float64Box
+from pypy.conftest import option
+import sys
 
 class BaseNumpyAppTest(object):
     def setup_class(cls):
+        if option.runappdirect:
+            if '__pypy__' not in sys.builtin_module_names:
+                import numpy
+                sys.modules['numpypy'] = numpy
+                sys.modules['_numpypy'] = numpy
         cls.space = gettestobjspace(usemodules=['micronumpy'])
 
 class TestSignature(object):
@@ -16,7 +24,7 @@
         ar = W_NDimArray(10, [10], dtype=float64_dtype)
         ar2 = W_NDimArray(10, [10], dtype=float64_dtype)
         v1 = ar.descr_add(space, ar)
-        v2 = ar.descr_add(space, Scalar(float64_dtype, 2.0))
+        v2 = ar.descr_add(space, Scalar(float64_dtype, W_Float64Box(2.0)))
         sig1 = v1.find_sig()
         sig2 = v2.find_sig()
         assert v1 is not v2
@@ -26,7 +34,7 @@
         sig1b = ar2.descr_add(space, ar).find_sig()
         assert sig1b.left.array_no != sig1b.right.array_no
         assert sig1b is not sig1
-        v3 = ar.descr_add(space, Scalar(float64_dtype, 1.0))
+        v3 = ar.descr_add(space, Scalar(float64_dtype, W_Float64Box(1.0)))
         sig3 = v3.find_sig()
         assert sig2 is sig3
         v4 = ar.descr_add(space, ar)
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
@@ -245,3 +245,19 @@
         a -> 3
         """)
         assert interp.results[0].value == 11
+
+    def test_flat_iter(self):
+        interp = self.run('''
+        a = |30|
+        b = flat(a)
+        b -> 3
+        ''')
+        assert interp.results[0].value == 3
+
+    def test_take(self):
+        interp = self.run("""
+        a = |10|
+        b = take(a, [1, 1, 3, 2])
+        b -> 2
+        """)
+        assert interp.results[0].value == 3
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -11,8 +11,17 @@
         assert dtype('int8').num == 1
         assert dtype(d) is d
         assert dtype(None) is dtype(float)
+        assert dtype('int8').name == 'int8'
         raises(TypeError, dtype, 1042)
 
+    def test_dtype_eq(self):
+        from _numpypy import dtype
+
+        assert dtype("int8") == "int8"
+        assert "int8" == dtype("int8")
+        raises(TypeError, lambda: dtype("int8") == 3)
+        assert dtype(bool) == bool
+
     def test_dtype_with_types(self):
         from _numpypy import dtype
 
@@ -30,7 +39,7 @@
     def test_repr_str(self):
         from _numpypy import dtype
 
-        assert repr(dtype) == "<type 'numpypy.dtype'>"
+        assert '.dtype' in repr(dtype)
         d = dtype('?')
         assert repr(d) == "dtype('bool')"
         assert str(d) == "bool"
@@ -376,3 +385,19 @@
         b = X(10)
         assert type(b) is X
         assert b.m() == 12
+
+    def test_long_as_index(self):
+        skip("waiting for removal of multimethods of __index__")
+        from _numpypy import int_
+        assert (1, 2, 3)[int_(1)] == 2
+
+    def test_int(self):
+        import sys
+        from _numpypy import int32, int64, int_
+        assert issubclass(int_, int)
+        if sys.maxint == (1<<31) - 1:
+            assert issubclass(int32, int)
+            assert int_ is int32
+        else:
+            assert issubclass(int64, int)
+            assert int_ is int64
diff --git a/pypy/module/micronumpy/test/test_iter.py b/pypy/module/micronumpy/test/test_iter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_iter.py
@@ -0,0 +1,88 @@
+from pypy.module.micronumpy.interp_iter import ViewIterator
+
+class TestIterDirect(object):
+    def test_C_viewiterator(self):
+        #Let's get started, simple iteration in C order with
+        #contiguous layout => strides[-1] is 1
+        start = 0
+        shape = [3, 5] 
+        strides = [5, 1]
+        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+        assert backstrides == [10, 4]
+        i = ViewIterator(start, strides, backstrides, shape)
+        i = i.next(2)
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 3
+        assert not i.done()
+        assert i.indices == [0,3]
+        #cause a dimension overflow
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 5
+        assert i.indices == [1,0]
+
+        #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 = ViewIterator(start, strides, backstrides, shape)
+        i = i.next(2)
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 9
+        assert not i.done()
+        assert i.indices == [0,3]
+        #cause a dimension overflow
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 1
+        assert i.indices == [1,0]
+
+    def test_C_viewiterator_step(self):
+        #iteration in C order with #contiguous layout => strides[-1] is 1
+        #skip less than the shape
+        start = 0
+        shape = [3, 5] 
+        strides = [5, 1]
+        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+        assert backstrides == [10, 4]
+        i = ViewIterator(start, strides, backstrides, shape)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        assert i.offset == 6
+        assert not i.done()
+        assert i.indices == [1,1]
+        #And for some big skips
+        i = i.next_skip_x(2,5)
+        assert i.offset == 11
+        assert i.indices == [2,1]
+        i = i.next_skip_x(2,5)
+        # Note: the offset does not overflow but recycles,
+        # this is good for broadcast
+        assert i.offset == 1
+        assert i.indices == [0,1]
+        assert i.done()
+
+        #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 = ViewIterator(start, strides, backstrides, shape)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        assert i.offset == 4
+        assert i.indices == [1,1]
+        assert not i.done()
+        i = i.next_skip_x(2,5)
+        assert i.offset == 5
+        assert i.indices == [2,1]
+        assert not i.done()
+        i = i.next_skip_x(2,5)
+        assert i.indices == [0,1]
+        assert i.offset == 3
+        assert i.done()
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -154,14 +154,36 @@
 
     def test_calc_new_strides(self):
         from pypy.module.micronumpy.interp_numarray import calc_new_strides
-        assert calc_new_strides([2, 4], [4, 2], [4, 2]) == [8, 2]
-        assert calc_new_strides([2, 4, 3], [8, 3], [1, 16]) == [1, 2, 16]
-        assert calc_new_strides([2, 3, 4], [8, 3], [1, 16]) is None
-        assert calc_new_strides([24], [2, 4, 3], [48, 6, 1]) is None
-        assert calc_new_strides([24], [2, 4, 3], [24, 6, 2]) == [2]
-        assert calc_new_strides([105, 1], [3, 5, 7], [35, 7, 1]) == [1, 1]
-        assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1]) == [105, 1]
+        assert calc_new_strides([2, 4], [4, 2], [4, 2], "C") == [8, 2]
+        assert calc_new_strides([2, 4, 3], [8, 3], [1, 16], 'F') == [1, 2, 16]
+        assert calc_new_strides([2, 3, 4], [8, 3], [1, 16], 'F') is None
+        assert calc_new_strides([24], [2, 4, 3], [48, 6, 1], 'C') is None
+        assert calc_new_strides([24], [2, 4, 3], [24, 6, 2], 'C') == [2]
+        assert calc_new_strides([105, 1], [3, 5, 7], [35, 7, 1],'C') == [1, 1]
+        assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1],'C') == [105, 1]
+        assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1],'F') is None
+        assert calc_new_strides([1, 1, 1, 105, 1], [15, 7], [7, 1],'C') == \
+                                    [105, 105, 105, 1, 1]
+        assert calc_new_strides([1, 1, 105, 1, 1], [7, 15], [1, 7],'F') == \
+                                    [1, 1, 1, 105, 105]
 
+    def test_to_coords(self):
+        from pypy.module.micronumpy.strides import to_coords
+
+        def _to_coords(index, order):
+            return to_coords(self.space, [2, 3, 4], 24, order,
+                             self.space.wrap(index))[0]
+        
+        assert _to_coords(0, 'C') == [0, 0, 0]
+        assert _to_coords(1, 'C') == [0, 0, 1]
+        assert _to_coords(-1, 'C') == [1, 2, 3]
+        assert _to_coords(5, 'C') == [0, 1, 1]
+        assert _to_coords(13, 'C') == [1, 0, 1]
+        assert _to_coords(0, 'F') == [0, 0, 0]
+        assert _to_coords(1, 'F') == [1, 0, 0]
+        assert _to_coords(-1, 'F') == [1, 2, 3]
+        assert _to_coords(5, 'F') == [1, 2, 0]
+        assert _to_coords(13, 'F') == [1, 0, 2]
 
 class AppTestNumArray(BaseNumpyAppTest):
     def test_ndarray(self):
@@ -206,6 +228,7 @@
         # And check that changes stick.
         a[13] = 5.3
         assert a[13] == 5.3
+        assert zeros(()).shape == ()
 
     def test_size(self):
         from _numpypy import array
@@ -249,6 +272,7 @@
         b = a[::2]
         c = b.copy()
         assert (c == b).all()
+        assert ((a + a).copy() == (a + a)).all()
 
         a = arange(15).reshape(5,3)
         b = a.copy()
@@ -278,6 +302,12 @@
         for i in xrange(5):
             assert a[i] == b[i]
 
+    def test_getitem_nd(self):
+        from _numpypy import arange
+        a = arange(15).reshape(3, 5)
+        assert a[1, 3] == 8
+        assert a.T[1, 2] == 11 
+
     def test_setitem(self):
         from _numpypy import array
         a = array(range(5))
@@ -365,6 +395,7 @@
         assert b.shape == (5,)
         c = a[:3]
         assert c.shape == (3,)
+        assert array([]).shape == (0,)
 
     def test_set_shape(self):
         from _numpypy import array, zeros
@@ -385,6 +416,8 @@
         a.shape = ()
         #numpy allows this
         a.shape = (1,)
+        a = array(range(6)).reshape(2,3).T
+        raises(AttributeError, 'a.shape = 6')
 
     def test_reshape(self):
         from _numpypy import array, zeros
@@ -398,6 +431,7 @@
         assert (a == [1000, 1, 2, 3, 1000, 5, 6, 7, 1000, 9, 10, 11]).all()
         a = zeros((4, 2, 3))
         a.shape = (12, 2)
+        (a + a).reshape(2, 12) # assert did not explode
 
     def test_slice_reshape(self):
         from _numpypy import zeros, arange
@@ -441,6 +475,13 @@
         y = z.reshape(4, 3, 8)
         assert y.shape == (4, 3, 8)
 
+    def test_scalar_reshape(self):
+        from numpypy import array
+        a = array(3)
+        assert a.reshape([1, 1]).shape == (1, 1)
+        assert a.reshape([1]).shape == (1,)
+        raises(ValueError, "a.reshape(3)")
+
     def test_add(self):
         from _numpypy import array
         a = array(range(5))
@@ -728,7 +769,7 @@
         assert d[1] == 12
 
     def test_mean(self):
-        from _numpypy import array
+        from _numpypy import array, arange
         a = array(range(5))
         assert a.mean() == 2.0
         assert a[:4].mean() == 1.5
@@ -738,6 +779,7 @@
         assert a.mean(axis=0)[0, 0] == 35
         assert (b == array(range(35, 70), dtype=float).reshape(5, 7)).all()
         assert (a.mean(2) == array(range(0, 15), dtype=float).reshape(3, 5) * 7 + 3).all()
+        assert (arange(10).reshape(5, 2).mean(axis=1) == [0.5, 2.5, 4.5, 6.5, 8.5]).all()
 
     def test_sum(self):
         from _numpypy import array
@@ -948,7 +990,7 @@
         assert debug_repr(a + a) == 'Call2(add, Array, Array)'
         assert debug_repr(a[::2]) == 'Slice'
         assert debug_repr(a + 2) == 'Call2(add, Array, Scalar)'
-        assert debug_repr(a + a.flat) == 'Call2(add, Array, Slice)'
+        assert debug_repr(a + a.flat) == 'Call2(add, Array, Flat)'
         assert debug_repr(sin(a)) == 'Call1(sin, Array)'
 
         b = a + a
@@ -1021,11 +1063,49 @@
         assert a[0].tolist() == [17.1, 27.2]
 
     def test_var(self):
-        from _numpypy import array
+        from _numpypy import array, arange
         a = array(range(10))
         assert a.var() == 8.25
         a = array([5.0])
         assert a.var() == 0.0
+        a = arange(10).reshape(5, 2)
+        assert a.var() == 8.25
+        assert (a.var(0) == [8, 8]).all()
+        assert (a.var(1) == [.25] * 5).all()
+
+    def test_concatenate(self):
+        from numpypy import array, concatenate, dtype
+        a1 = array([0,1,2])
+        a2 = array([3,4,5])
+        a = concatenate((a1, a2))
+        assert len(a) == 6
+        assert (a == [0,1,2,3,4,5]).all()
+        assert a.dtype is dtype(int)
+        b1 = array([[1, 2], [3, 4]])
+        b2 = array([[5, 6]])
+        b = concatenate((b1, b2), axis=0)
+        assert (b == [[1, 2],[3, 4],[5, 6]]).all()
+        c = concatenate((b1, b2.T), axis=1)
+        assert (c == [[1, 2, 5],[3, 4, 6]]).all()
+        d = concatenate(([0],[1]))
+        assert (d == [0,1]).all()
+        e1 = array([[0,1],[2,3]])
+        e = concatenate(e1)
+        assert (e == [0,1,2,3]).all()
+        f1 = array([0,1])
+        f = concatenate((f1, [2], f1, [7]))
+        assert (f == [0,1,2,0,1,7]).all()
+        
+        bad_axis = raises(ValueError, concatenate, (a1,a2), axis=1)
+        assert str(bad_axis.value) == "bad axis argument"
+        
+        concat_zero = raises(ValueError, concatenate, ())
+        assert str(concat_zero.value) == \
+            "concatenation of zero-length sequences is impossible"
+        
+        dims_disagree = raises(ValueError, concatenate, (a1, b1), axis=0)
+        assert str(dims_disagree.value) == \
+            "array dimensions must agree except for axis being concatenated"
 
     def test_std(self):
         from _numpypy import array
@@ -1034,6 +1114,28 @@
         a = array([5.0])
         assert a.std() == 0.0
 
+    def test_flatten(self):
+        from _numpypy import array
+
+        assert array(3).flatten().shape == (1,)
+        a = array([[1, 2], [3, 4]])
+        b = a.flatten()
+        c = a.ravel()
+        a[0, 0] = 15
+        assert b[0] == 1
+        assert c[0] == 15
+        a = array([[1, 2, 3], [4, 5, 6]])
+        assert (a.flatten() == [1, 2, 3, 4, 5, 6]).all()
+        a = array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
+        assert (a.flatten() == [1, 2, 3, 4, 5, 6, 7, 8]).all()
+        a = array([1, 2, 3, 4, 5, 6, 7, 8])
+        assert (a[::2].flatten() == [1, 3, 5, 7]).all()
+        a = array([1, 2, 3])
+        assert ((a + a).flatten() == [2, 4, 6]).all()
+        a = array(2)
+        assert (a.flatten() == [2]).all()
+        a = array([[1, 2], [3, 4]])
+        assert (a.T.flatten() == [1, 3, 2, 4]).all()
 
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
@@ -1049,7 +1151,7 @@
         assert _numpypy.array([[1], [2], [3]]).shape == (3, 1)
         assert len(_numpypy.zeros((3, 1, 2))) == 3
         raises(TypeError, len, _numpypy.zeros(()))
-        raises(ValueError, _numpypy.array, [[1, 2], 3])
+        raises(ValueError, _numpypy.array, [[1, 2], 3], dtype=float)
 
     def test_getsetitem(self):
         import _numpypy
@@ -1264,7 +1366,7 @@
         assert(b[:, 0] == a[0, :]).all()
 
     def test_flatiter(self):
-        from _numpypy import array, flatiter
+        from _numpypy import array, flatiter, arange
         a = array([[10, 30], [40, 60]])
         f_iter = a.flat
         assert f_iter.next() == 10
@@ -1277,6 +1379,9 @@
         for k in a.flat:
             s += k
         assert s == 140
+        a = arange(10).reshape(5, 2)
+        raises(IndexError, 'a.flat[(1, 2)]')
+        assert a.flat.base is a
 
     def test_flatiter_array_conv(self):
         from _numpypy import array, dot
@@ -1288,6 +1393,75 @@
         a = ones((2, 2))
         assert list(((a + a).flat)) == [2, 2, 2, 2]
 
+    def test_flatiter_getitem(self):
+        from _numpypy import arange
+        a = arange(10)
+        assert a.flat[3] == 3
+        assert a[2:].flat[3] == 5
+        assert (a + a).flat[3] == 6
+        assert a[::2].flat[3] == 6
+        assert a.reshape(2,5).flat[3] == 3
+        b = a.reshape(2,5).flat
+        b.next()
+        b.next()
+        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 == 3
+        assert b.coords == (0,3)
+
+    def test_flatiter_setitem(self):
+        from _numpypy import arange, array
+        a = arange(12).reshape(3,4)
+        b = a.T.flat
+        b[6::2] = [-1, -2]
+        assert (a == [[0, 1, -1, 3], [4, 5, 6, -1], [8, 9, -2, 11]]).all()
+        b[0:2] = [[[100]]]
+        assert(a[0,0] == 100)
+        assert(a[1,0] == 100)
+        raises(IndexError, 'b[array([10, 11])] == [-20, -40]')
+
+    def test_flatiter_ops(self):
+        from _numpypy import arange, array
+        a = arange(12).reshape(3,4)
+        b = a.T.flat
+        assert (b == [0,  4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]).all()
+        assert not (b != [0,  4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]).any()
+        assert ((b >= range(12)) == [True, True, True,False, True, True, 
+                             False, False, True, False, False, True]).all()
+        assert ((b < range(12)) != [True, True, True,False, True, True, 
+                             False, False, True, False, False, True]).all()
+        assert ((b <= range(12)) != [False, True, True,False, True, True, 
+                            False, False, True, False, False, False]).all()
+        assert ((b > range(12)) == [False, True, True,False, True, True, 
+                            False, False, True, False, False, False]).all()
+    def test_flatiter_view(self):
+        from _numpypy import arange
+        a = arange(10).reshape(5, 2)
+        #no == yet.
+        # a[::2].flat == [0, 1, 4, 5, 8, 9]
+        isequal = True
+        for y,z in zip(a[::2].flat, [0, 1, 4, 5, 8, 9]):
+            if y != z:
+                isequal = False
+        assert isequal == True
+
+    def test_flatiter_transpose(self):
+        from _numpypy import arange
+        a = arange(10).reshape(2,5).T
+        b = a.flat
+        assert (b[:5] == [0, 5, 1, 6, 2]).all()
+        b.next()
+        b.next()
+        b.next()
+        assert b.index == 3
+        assert b.coords == (1,1)
+
     def test_slice_copy(self):
         from _numpypy import zeros
         a = zeros((10, 10))
@@ -1353,7 +1527,61 @@
         a[a & 1 == 1] = array([8, 9, 10])
         assert (a == [[0, 8], [2, 9], [4, 10]]).all()
 
+    def test_copy_kwarg(self):
+        from _numpypy import array
+        x = array([1, 2, 3])
+        assert (array(x) == x).all()
+        assert array(x) is not x
+        assert array(x, copy=False) is x
+        assert array(x, copy=True) is not x
 
+    def test_isna(self):
+        from _numpypy import isna, array
+        # XXX for now
+        assert not isna(3)
+        assert (isna(array([1, 2, 3, 4])) == [False, False, False, False]).all()
+
+    def test_ravel(self):
+        from _numpypy import arange
+        assert (arange(3).ravel() == arange(3)).all()
+        assert (arange(6).reshape(2, 3).ravel() == arange(6)).all()
+        assert (arange(6).reshape(2, 3).T.ravel() == [0, 3, 1, 4, 2, 5]).all()
+
+    def test_take(self):
+        from _numpypy import arange
+        assert (arange(10).take([1, 2, 1, 1]) == [1, 2, 1, 1]).all()
+        raises(IndexError, "arange(3).take([15])")
+        a = arange(6).reshape(2, 3)
+        assert (a.take([1, 0, 3]) == [1, 0, 3]).all()
+        assert ((a + a).take([3]) == [6]).all()
+        a = arange(12).reshape(2, 6)
+        assert (a[:,::2].take([3, 2, 1]) == [6, 4, 2]).all()
+
+    def test_compress(self):
+        from _numpypy import arange
+        a = arange(10)
+        assert (a.compress([True, False, True]) == [0, 2]).all()
+        assert (a.compress([1, 0, 13]) == [0, 2]).all()
+        assert (a.compress([1, 0, 13.5]) == [0, 2]).all()
+        a = arange(10).reshape(2, 5)
+        assert (a.compress([True, False, True]) == [0, 2]).all()
+        raises(IndexError, "a.compress([1] * 100)")
+
+    def test_item(self):
+        from _numpypy import array
+        assert array(3).item() == 3
+        assert type(array(3).item()) is int
+        assert type(array(True).item()) is bool
+        assert type(array(3.5).item()) is float
+        raises((ValueError, IndexError), "array(3).item(15)")
+        raises(ValueError, "array([1, 2, 3]).item()")
+        assert array([3]).item(0) == 3
+        assert type(array([3]).item(0)) is int
+        assert array([1, 2, 3]).item(-1) == 3
+        a = array([1, 2, 3])
+        assert a[::2].item(1) == 3
+        assert (a + a).item(1) == 4
+        raises(ValueError, "array(5).item(1)")
 
 class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
@@ -1465,128 +1693,6 @@
         raises(ValueError, fromstring, "\x01\x02\x03", count=5, dtype=uint8)
 
 
-class AppTestRepr(BaseNumpyAppTest):
-    def test_repr(self):
-        from _numpypy import array, zeros
-        int_size = array(5).dtype.itemsize
-        a = array(range(5), float)
-        assert repr(a) == "array([0.0, 1.0, 2.0, 3.0, 4.0])"
-        a = array([], float)
-        assert repr(a) == "array([], dtype=float64)"
-        a = zeros(1001)
-        assert repr(a) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
-        a = array(range(5), long)
-        if a.dtype.itemsize == int_size:
-            assert repr(a) == "array([0, 1, 2, 3, 4])"
-        else:
-            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int64)"
-        a = array(range(5), 'int32')
-        if a.dtype.itemsize == int_size:
-            assert repr(a) == "array([0, 1, 2, 3, 4])"
-        else:
-            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int32)"
-        a = array([], long)
-        assert repr(a) == "array([], dtype=int64)"
-        a = array([True, False, True, False], "?")
-        assert repr(a) == "array([True, False, True, False], dtype=bool)"
-        a = zeros([])
-        assert repr(a) == "array(0.0)"
-        a = array(0.2)
-        assert repr(a) == "array(0.2)"
-        a = array([2])
-        assert repr(a) == "array([2])"
-
-    def test_repr_multi(self):
-        from _numpypy import arange, zeros, array
-        a = zeros((3, 4))
-        assert repr(a) == '''array([[0.0, 0.0, 0.0, 0.0],
-       [0.0, 0.0, 0.0, 0.0],
-       [0.0, 0.0, 0.0, 0.0]])'''
-        a = zeros((2, 3, 4))
-        assert repr(a) == '''array([[[0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0]],
-
-       [[0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0]]])'''
-        a = arange(1002).reshape((2, 501))
-        assert repr(a) == '''array([[0, 1, 2, ..., 498, 499, 500],
-       [501, 502, 503, ..., 999, 1000, 1001]])'''
-        assert repr(a.T) == '''array([[0, 501],
-       [1, 502],
-       [2, 503],
-       ...,
-       [498, 999],
-       [499, 1000],
-       [500, 1001]])'''
-        a = arange(2).reshape((2,1))
-        assert repr(a) == '''array([[0],
-       [1]])'''
-
-    def test_repr_slice(self):
-        from _numpypy import array, zeros
-        a = array(range(5), float)
-        b = a[1::2]
-        assert repr(b) == "array([1.0, 3.0])"
-        a = zeros(2002)
-        b = a[::2]
-        assert repr(b) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
-        a = array((range(5), range(5, 10)), dtype="int16")
-        b = a[1, 2:]
-        assert repr(b) == "array([7, 8, 9], dtype=int16)"
-        # an empty slice prints its shape
-        b = a[2:1, ]
-        assert repr(b) == "array([], shape=(0, 5), dtype=int16)"
-
-    def test_str(self):
-        from _numpypy import array, zeros
-        a = array(range(5), float)
-        assert str(a) == "[0.0 1.0 2.0 3.0 4.0]"
-        assert str((2 * a)[:]) == "[0.0 2.0 4.0 6.0 8.0]"
-        a = zeros(1001)
-        assert str(a) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
-
-        a = array(range(5), dtype=long)
-        assert str(a) == "[0 1 2 3 4]"
-        a = array([True, False, True, False], dtype="?")
-        assert str(a) == "[True False True False]"
-
-        a = array(range(5), dtype="int8")
-        assert str(a) == "[0 1 2 3 4]"
-
-        a = array(range(5), dtype="int16")
-        assert str(a) == "[0 1 2 3 4]"
-
-        a = array((range(5), range(5, 10)), dtype="int16")
-        assert str(a) == "[[0 1 2 3 4]\n [5 6 7 8 9]]"
-
-        a = array(3, dtype=int)
-        assert str(a) == "3"
-
-        a = zeros((400, 400), dtype=int)
-        assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n" \
-           " [0 0 0 ..., 0 0 0]\n ...,\n [0 0 0 ..., 0 0 0]\n" \
-           " [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
-        a = zeros((2, 2, 2))
-        r = str(a)
-        assert r == '[[[0.0 0.0]\n  [0.0 0.0]]\n\n [[0.0 0.0]\n  [0.0 0.0]]]'
-
-    def test_str_slice(self):
-        from _numpypy import array, zeros
-        a = array(range(5), float)
-        b = a[1::2]
-        assert str(b) == "[1.0 3.0]"
-        a = zeros(2002)
-        b = a[::2]
-        assert str(b) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
-        a = array((range(5), range(5, 10)), dtype="int16")
-        b = a[1, 2:]
-        assert str(b) == "[7 8 9]"
-        b = a[2:1, ]
-        assert str(b) == "[]"
-
-
 class AppTestRanges(BaseNumpyAppTest):
     def test_arange(self):
         from _numpypy import arange, array, dtype
@@ -1607,3 +1713,24 @@
         a = arange(0, 0.8, 0.1)
         assert len(a) == 8
         assert arange(False, True, True).dtype is dtype(int)
+
+from pypy.module.micronumpy.appbridge import get_appbridge_cache
+
+class AppTestRepr(BaseNumpyAppTest):
+    def setup_class(cls):
+        BaseNumpyAppTest.setup_class.im_func(cls)
+        cache = get_appbridge_cache(cls.space)
+        cls.old_array_repr = cache.w_array_repr
+        cls.old_array_str = cache.w_array_str
+        cache.w_array_str = None
+        cache.w_array_repr = None
+
+    def test_repr_str(self):
+        from _numpypy import array
+        assert repr(array([1, 2, 3])) == 'array([1, 2, 3])'
+        assert str(array([1, 2, 3])) == 'array([1, 2, 3])'
+
+    def teardown_class(cls):
+        cache = get_appbridge_cache(cls.space)
+        cache.w_array_repr = cls.old_array_repr
+        cache.w_array_str = cls.old_array_str
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -344,7 +344,7 @@
         from _numpypy import sin, add
 
         raises(ValueError, sin.reduce, [1, 2, 3])
-        raises(ValueError, add.reduce, 1)
+        raises((ValueError, TypeError), add.reduce, 1)
 
     def test_reduce_1d(self):
         from _numpypy import add, maximum
@@ -360,6 +360,14 @@
         assert (add.reduce(a, 0) == [12, 15, 18, 21]).all()
         assert (add.reduce(a, 1) == [6.0, 22.0, 38.0]).all()
 
+    def test_reduce_keepdims(self):
+        from _numpypy import add, arange
+        a = arange(12).reshape(3, 4)
+        b = add.reduce(a, 0, keepdims=True)
+        assert b.shape == (1, 4)
+        assert (add.reduce(a, 0, keepdims=True) == [12, 15, 18, 21]).all()
+        
+
     def test_bitwise(self):
         from _numpypy import bitwise_and, bitwise_or, arange, array
         a = arange(6).reshape(2, 3)
@@ -369,6 +377,12 @@
         assert (a | 1 == bitwise_or(a, 1)).all()
         raises(TypeError, 'array([1.0]) & 1')
 
+    def test_unary_bitops(self):
+        from _numpypy import bitwise_not, array
+        a = array([1, 2, 3, 4])
+        assert (~a == [-2, -3, -4, -5]).all()
+        assert (bitwise_not(a) == ~a).all()
+
     def test_comparisons(self):
         import operator
         from _numpypy import equal, not_equal, less, less_equal, greater, greater_equal
@@ -394,3 +408,28 @@
                 (3, 3.5),
             ]:
                 assert ufunc(a, b) == func(a, b)
+
+    def test_count_reduce_items(self):
+        from _numpypy import count_reduce_items, arange
+        a = arange(24).reshape(2, 3, 4)
+        assert count_reduce_items(a) == 24
+        assert count_reduce_items(a, 1) == 3
+        assert count_reduce_items(a, (1, 2)) == 3 * 4
+        
+    def test_true_divide(self):
+        from _numpypy import arange, array, true_divide
+        assert (true_divide(arange(3), array([2, 2, 2])) == array([0, 0.5, 1])).all()
+
+    def test_isnan_isinf(self):
+        from _numpypy import isnan, isinf, float64, array
+        assert isnan(float('nan'))
+        assert isnan(float64(float('nan')))
+        assert not isnan(3)
+        assert isinf(float('inf'))
+        assert not isnan(3.5)
+        assert not isinf(3.5)
+        assert not isnan(float('inf'))
+        assert not isinf(float('nan'))
+        assert (isnan(array([0.2, float('inf'), float('nan')])) == [False, False, True]).all()
+        assert (isinf(array([0.2, float('inf'), float('nan')])) == [False, True, False]).all()
+        assert isinf(array([0.2])).dtype.kind == 'b'
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -12,7 +12,7 @@
 from pypy.module.micronumpy.compile import (FakeSpace,
     IntObject, Parser, InterpreterState)
 from pypy.module.micronumpy.interp_numarray import (W_NDimArray,
-     BaseArray)
+     BaseArray, W_FlatIterator)
 from pypy.rlib.nonconst import NonConstant
 
 
@@ -287,6 +287,27 @@
                                 'jump': 1,
                                 'arraylen_gc': 1})
 
+    def define_take():
+        return """
+        a = |10|
+        b = take(a, [1, 1, 3, 2])
+        b -> 2
+        """
+
+    def test_take(self):
+        result = self.run("take")
+        assert result == 3
+        self.check_simple_loop({'getinteriorfield_raw': 2,
+                                'cast_float_to_int': 1,
+                                'int_lt': 1,
+                                'int_ge': 2,
+                                'guard_false': 3,
+                                'setinteriorfield_raw': 1,
+                                'int_mul': 1,
+                                'int_add': 3,
+                                'jump': 1,
+                                'arraylen_gc': 2})
+
     def define_multidim():
         return """
         a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
@@ -369,7 +390,71 @@
                                 'setinteriorfield_raw': 1, 'int_add': 2,
                                 'int_ge': 1, 'guard_false': 1, 'jump': 1,
                                 'arraylen_gc': 1})
+    def define_flat_iter():
+        return '''
+        a = |30|
+        b = flat(a)
+        c = b + a
+        c -> 3
+        '''
 
+    def test_flat_iter(self):
+        result = self.run("flat_iter")
+        assert result == 6
+        self.check_trace_count(1)
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
+                                'int_ge': 1, 'guard_false': 1,
+                                'arraylen_gc': 1, 'jump': 1})
+
+    def define_flat_getitem():
+        return '''
+        a = |30|
+        b = flat(a)
+        b -> 4: -> 6
+        '''
+
+    def test_flat_getitem(self):
+        result = self.run("flat_getitem")
+        assert result == 10.0
+        self.check_trace_count(1)
+        self.check_simple_loop({'getinteriorfield_raw': 1,
+                                'setinteriorfield_raw': 1,
+                                'int_lt': 1,
+                                'int_ge': 1,
+                                'int_add': 3,
+                                'guard_true': 1,
+                                'guard_false': 1,
+                                'arraylen_gc': 2,
+                                'jump': 1})
+
+    def define_flat_setitem():
+        return '''
+        a = |30|
+        b = flat(a)
+        b[4:] = a->:26
+        a -> 5
+        '''
+
+    def test_flat_setitem(self):
+        result = self.run("flat_setitem")
+        assert result == 1.0
+        self.check_trace_count(1)
+        # XXX not ideal, but hey, let's ignore it for now
+        self.check_simple_loop({'getinteriorfield_raw': 1,
+                                'setinteriorfield_raw': 1,
+                                'int_lt': 1,
+                                'int_gt': 1,
+                                'int_add': 4,
+                                'guard_true': 2,
+                                'arraylen_gc': 2,
+                                'jump': 1,
+                                'int_sub': 1,
+                                # XXX bad part
+                                'int_and': 1,
+                                'int_mod': 1,
+                                'int_rshift': 1,
+                                })
 
 class TestNumpyOld(LLJitMixin):
     def setup_class(cls):
diff --git a/pypy/module/micronumpy/tool/numready/__init__.py b/pypy/module/micronumpy/tool/numready/__init__.py
new file mode 100644
diff --git a/pypy/module/micronumpy/tool/numready/__main__.py b/pypy/module/micronumpy/tool/numready/__main__.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/tool/numready/__main__.py
@@ -0,0 +1,6 @@
+import sys
+
+from .main import main
+
+
+main(sys.argv)
diff --git a/pypy/module/micronumpy/tool/numready/kinds.py b/pypy/module/micronumpy/tool/numready/kinds.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/tool/numready/kinds.py
@@ -0,0 +1,4 @@
+KINDS = {
+    "UNKNOWN": "U",
+    "TYPE": "T",
+}
diff --git a/pypy/module/micronumpy/tool/numready/main.py b/pypy/module/micronumpy/tool/numready/main.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/tool/numready/main.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+This should be run under PyPy.
+"""
+
+import os
+import platform
+import subprocess
+import tempfile
+import webbrowser
+from collections import OrderedDict
+
+import jinja2
+
+from .kinds import KINDS
+
+
+class SearchableSet(object):
+    def __init__(self, items=()):
+        self._items = {}
+        for item in items:
+            self.add(item)
+
+    def __iter__(self):
+        return iter(self._items)
+
+    def __contains__(self, other):
+        return other in self._items
+
+    def __getitem__(self, idx):
+        return self._items[idx]
+
+    def add(self, item):
+        self._items[item] = item
+
+    def __len__(self):
+        return len(self._items)
+
+class Item(object):
+    def __init__(self, name, kind, subitems=None):
+        self.name = name
+        self.kind = kind
+        self.subitems = subitems
+
+    def __hash__(self):
+        return hash(self.name)
+
+    def __eq__(self, other):
+        if isinstance(other, str):
+            return self.name == other
+        return self.name == other.name
+
+
+class ItemStatus(object):
+    def __init__(self, name, pypy_exists):
+        self.name = name
+        self.cls = 'exists' if pypy_exists else ''
+        self.symbol = u"&#10004;" if pypy_exists else u'&#10006;'
+
+    def __lt__(self, other):
+        return self.name < other.name
+
+def find_numpy_items(python, modname="numpy", attr=None):
+    args = [
+        python, os.path.join(os.path.dirname(__file__), "search.py"), modname
+    ]
+    if attr is not None:
+        args.append(attr)
+    lines = subprocess.check_output(args).splitlines()
+    items = SearchableSet()
+    for line in lines:
+        kind, name = line.split(" : ", 1)
+        subitems = None
+        if kind == KINDS["TYPE"] and name in SPECIAL_NAMES and attr is None:
+            subitems = find_numpy_items(python, modname, name)
+        items.add(Item(name, kind, subitems))
+    return items
+
+def split(lst):
+    SPLIT = 5
+    lgt = len(lst) // SPLIT + 1
+    l = [[] for i in range(lgt)]
+    for i in range(lgt):
+        for k in range(SPLIT):
+            if k * lgt + i < len(lst):
+                l[i].append(lst[k * lgt + i])
+    return l
+
+SPECIAL_NAMES = ["ndarray", "dtype", "generic", "flatiter"]
+
+def main(argv):
+    cpy_items = find_numpy_items("/usr/bin/python")
+    pypy_items = find_numpy_items(argv[1], "numpypy")
+    all_items = []
+
+    msg = "{:d}/{:d} names".format(len(pypy_items), len(cpy_items)) + " "
+    msg += ", ".join(
+        "{:d}/{:d} {} attributes".format(
+            len(pypy_items[name].subitems), len(cpy_items[name].subitems), name
+        )
+        for name in SPECIAL_NAMES
+    )
+    for item in cpy_items:
+        pypy_exists = item in pypy_items
+        if item.subitems:
+            for sub in item.subitems:
+                all_items.append(
+                    ItemStatus(item.name + "." + sub.name, pypy_exists=pypy_exists and pypy_items[item].subitems and sub in pypy_items[item].subitems)
+                )
+        all_items.append(ItemStatus(item.name, pypy_exists=item in pypy_items))
+    env = jinja2.Environment(
+        loader=jinja2.FileSystemLoader(os.path.dirname(__file__))
+    )
+    html = env.get_template("page.html").render(all_items=split(sorted(all_items)), msg=msg)
+    if len(argv) > 2:
+        with open(argv[2], 'w') as f:
+            f.write(html.encode("utf-8"))
+    else:
+        with tempfile.NamedTemporaryFile(delete=False, suffix=".html") as f:
+            f.write(html.encode("utf-8"))
+        print "Saved in: %s" % f.name
diff --git a/pypy/module/micronumpy/tool/numready/page.html b/pypy/module/micronumpy/tool/numready/page.html
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/tool/numready/page.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>NumPyPy Status</title>
+        <meta http-equiv="content-type" content="text/html; charset=utf-8">
+        <style type="text/css">
+            body {
+                font-family: 'Consolas', 'Bitstream Vera Sans Mono', monospace;
+            }
+            h1 {
+                text-align: center;
+            }
+            h3 {
+                text-align: center;
+            }
+            table {
+                border: 8px solid #DFDECB;
+                margin: 30px auto;
+                font-size: 12px;
+            }
+            table th {
+                text-align: left;
+            }
+            table td {
+                padding: 4px 10px;
+                text-align: center;
+            }
+            .exists {
+                background-color: #337792;
+                color: white;
+                border: 1px solid #234F61;
+            }
+        </style>
+    </head>
+    <body>
+        <h1>NumPyPy Status</h1>
+        <h3>Overall: {{ msg }}</h3>
+        <table>
+            <thead>
+                <tr>
+                    <th></th>
+                    <th>PyPy</th>
+                    <th></th>
+                    <th>PyPy</th>
+                    <th></th>
+                    <th>PyPy</th>
+                    <th></th>
+                    <th>PyPy</th>
+                    <th></th>
+                    <th>PyPy</th>
+                </tr>
+            </thead>
+            <tbody>
+                {% for chunk in all_items %}
+                    <tr>
+                    {% for item in chunk %}
+                        <th class='{{ item.cls }}'>{{ item.name }}</th>
+                        <td class='{{ item.cls }}'>{{ item.symbol }}</td>
+                    {% endfor %}
+                    </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </body>
+</html>
diff --git a/pypy/module/micronumpy/tool/numready/search.py b/pypy/module/micronumpy/tool/numready/search.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/tool/numready/search.py
@@ -0,0 +1,33 @@
+import sys
+import types
+
+# Evil implicit relative import.
+from kinds import KINDS
+
+
+def main(argv):
+    if len(argv) == 2:
+        [_, modname] = argv
+        attr = None
+    elif len(argv) == 3:
+        [_, modname, attr] = argv
+    else:
+        sys.exit("Wrong number of args")
+    __import__(modname)
+    obj = sys.modules[modname]
+
+    if attr is not None:
+        obj = getattr(obj, attr)
+
+    for name in dir(obj):
+        if attr is None and name.startswith("_"):
+            continue
+        subobj = getattr(obj, name)
+        if isinstance(subobj, types.TypeType):
+            kind = KINDS["TYPE"]
+        else:
+            kind = KINDS["UNKNOWN"]
+        print kind, ":", name
+
+if __name__ == "__main__":
+    main(sys.argv)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -23,6 +23,16 @@
         )
     return dispatcher
 
+def raw_unary_op(func):
+    specialize.argtype(1)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v):
+        return func(
+            self,
+            self.for_computation(self.unbox(v))
+        )
+    return dispatcher
+
 def simple_binary_op(func):
     specialize.argtype(1, 2)(func)
     @functools.wraps(func)
@@ -95,7 +105,9 @@
         ))
 
     def read_bool(self, storage, width, i, offset):
-        raise NotImplementedError
+        return bool(self.for_computation(
+            libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+                                 width, storage, i, offset)))
 
     def store(self, storage, width, i, offset, box):
         value = self.unbox(box)
@@ -137,6 +149,14 @@
     def abs(self, v):
         return abs(v)
 
+    @raw_unary_op
+    def isnan(self, v):
+        return False
+
+    @raw_unary_op
+    def isinf(self, v):
+        return False
+
     @raw_binary_op
     def eq(self, v1, v2):
         return v1 == v2
@@ -171,7 +191,7 @@
     @simple_binary_op
     def min(self, v1, v2):
         return min(v1, v2)
-    
+
 
 class Bool(BaseType, Primitive):
     T = lltype.Bool
@@ -189,11 +209,6 @@
         else:
             return self.False
 
-
-    def read_bool(self, storage, width, i, offset):
-        return libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
-                                    width, storage, i, offset)
-
     def coerce_subtype(self, space, w_subtype, w_item):
         # Doesn't return subclasses so it can return the constants.
         return self._coerce(space, w_item)
@@ -214,6 +229,18 @@
     def default_fromstring(self, space):
         return self.box(False)
 
+    @simple_binary_op
+    def bitwise_and(self, v1, v2):
+        return v1 & v2
+
+    @simple_binary_op
+    def bitwise_or(self, v1, v2):
+        return v1 | v2
+
+    @simple_unary_op
+    def invert(self, v):
+        return ~v
+
 class Integer(Primitive):
     _mixin_ = True
 
@@ -270,6 +297,10 @@
     def bitwise_or(self, v1, v2):
         return v1 | v2
 
+    @simple_unary_op
+    def invert(self, v):
+        return ~v
+
 class Int8(BaseType, Integer):
     T = rffi.SIGNEDCHAR
     BoxType = interp_boxes.W_Int8Box
@@ -448,6 +479,14 @@
         except ValueError:
             return rfloat.NAN
 
+    @raw_unary_op
+    def isnan(self, v):
+        return rfloat.isnan(v)
+
+    @raw_unary_op
+    def isinf(self, v):
+        return rfloat.isinf(v)
+
 
 class Float32(BaseType, Float):
     T = rffi.FLOAT
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -371,6 +371,8 @@
     if hasattr(__import__(os.name), "forkpty"):
         def test_forkpty(self):
             import sys
+            if 'freebsd' in sys.platform:
+                skip("hangs indifinitly on FreeBSD (also on CPython).")
             os = self.posix
             childpid, master_fd = os.forkpty()
             assert isinstance(childpid, int)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_math.py b/pypy/module/pypyjit/test_pypy_c/test_math.py
--- a/pypy/module/pypyjit/test_pypy_c/test_math.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_math.py
@@ -90,3 +90,19 @@
             --TICK--
             jump(..., descr=)
         """)
+
+    def test_pow_two(self):
+        def main(n):
+            s = 0.123
+            while n > 0:
+                s -= s ** 2   # ID: pow
+                n -= 1
+            return s
+        log = self.run(main, [500])
+        assert abs(log.result - main(500)) < 1e-9
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match_by_id("pow", """
+            guard_not_invalidated(descr=...)
+            f38 = float_mul(f30, f30)
+            f39 = float_sub(f30, f38)
+        """)
diff --git a/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
--- a/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
@@ -18,8 +18,8 @@
         from numpypy import array, arange, argmin
         a = arange(6).reshape((2,3))
         assert argmin(a) == 0
-        assert (argmin(a, axis=0) == array([0, 0, 0])).all()
-        assert (argmin(a, axis=1) == array([0, 0])).all()
+        #assert (argmin(a, axis=0) == array([0, 0, 0])).all()
+        #assert (argmin(a, axis=1) == array([0, 0])).all()
         b = arange(6)
         b[1] = 0
         assert argmin(b) == 0
@@ -40,8 +40,8 @@
         assert sum([0.5, 1.5])== 2.0
         assert sum([[0, 1], [0, 5]]) == 6
         # assert sum([0.5, 0.7, 0.2, 1.5], dtype=int32) == 1
-        # assert (sum([[0, 1], [0, 5]], axis=0) == array([0, 6])).all()
-        # assert (sum([[0, 1], [0, 5]], axis=1) == array([1, 5])).all()
+        assert (sum([[0, 1], [0, 5]], axis=0) == array([0, 6])).all()
+        assert (sum([[0, 1], [0, 5]], axis=1) == array([1, 5])).all()
         # If the accumulator is too small, overflow occurs:
         # assert ones(128, dtype=int8).sum(dtype=int8) == -128
 
@@ -98,20 +98,22 @@
         from numpypy import array, var
         a = array([[1,2],[3,4]])
         assert var(a) == 1.25
-        # assert (np.var(a,0) == array([ 1.,  1.])).all()
-        # assert (np.var(a,1) == array([ 0.25,  0.25])).all()
+        assert (var(a,0) == array([ 1.,  1.])).all()
+        assert (var(a,1) == array([ 0.25,  0.25])).all()
 
     def test_std(self):
         from numpypy import array, std
         a = array([[1, 2], [3, 4]])
         assert std(a) ==  1.1180339887498949
-        # assert (std(a, axis=0) == array([ 1.,  1.])).all()
-        # assert (std(a, axis=1) == array([ 0.5,  0.5]).all()
+        assert (std(a, axis=0) == array([ 1.,  1.])).all()
+        assert (std(a, axis=1) == array([ 0.5,  0.5])).all()
 
     def test_mean(self):
-        from numpypy import array, mean
+        from numpypy import array, mean, arange
         assert mean(array(range(5))) == 2.0
         assert mean(range(5)) == 2.0
+        assert (mean(arange(10).reshape(5, 2), axis=0) == [4, 5]).all()
+        assert (mean(arange(10).reshape(5, 2), axis=1) == [0.5, 2.5, 4.5, 6.5, 8.5]).all()
 
     def test_reshape(self):
         from numpypy import arange, array, dtype, reshape
@@ -134,4 +136,4 @@
         raises(NotImplementedError, "transpose(x, axes=(1, 0, 2))")
         # x = ones((1, 2, 3))
         # assert transpose(x, (1, 0, 2)).shape == (2, 1, 3)
-
+        
diff --git a/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
@@ -0,0 +1,144 @@
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestBaseRepr(BaseNumpyAppTest):
+    def test_base3(self):
+        from numpypy import base_repr
+        assert base_repr(3**5, 3) == '100000'
+
+    def test_positive(self):
+        from numpypy import base_repr
+        assert base_repr(12, 10) == '12'
+        assert base_repr(12, 10, 4) == '000012'
+        assert base_repr(12, 4) == '30'
+        assert base_repr(3731624803700888, 36) == '10QR0ROFCEW'
+
+    def test_negative(self):
+        from numpypy import base_repr
+        assert base_repr(-12, 10) == '-12'
+        assert base_repr(-12, 10, 4) == '-000012'
+        assert base_repr(-12, 4) == '-30'
+
+class AppTestRepr(BaseNumpyAppTest):
+    def test_repr(self):
+        from numpypy import array
+        assert repr(array([1, 2, 3, 4])) == 'array([1, 2, 3, 4])'
+
+    def test_repr_2(self):
+        from numpypy import array, zeros
+        int_size = array(5).dtype.itemsize
+        a = array(range(5), float)
+        assert repr(a) == "array([ 0.,  1.,  2.,  3.,  4.])"
+        a = array([], float)
+        assert repr(a) == "array([], dtype=float64)"
+        a = zeros(1001)
+        assert repr(a) == "array([ 0.,  0.,  0., ...,  0.,  0.,  0.])"
+        a = array(range(5), long)
+        if a.dtype.itemsize == int_size:
+            assert repr(a) == "array([0, 1, 2, 3, 4])"
+        else:
+            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int64)"
+        a = array(range(5), 'int32')
+        if a.dtype.itemsize == int_size:
+            assert repr(a) == "array([0, 1, 2, 3, 4])"
+        else:
+            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int32)"
+        a = array([], long)
+        assert repr(a) == "array([], dtype=int64)"
+        a = array([True, False, True, False], "?")
+        assert repr(a) == "array([ True, False,  True, False], dtype=bool)"
+        a = zeros([])
+        assert repr(a) == "array(0.0)"
+        a = array(0.2)
+        assert repr(a) == "array(0.2)"
+        a = array([2])
+        assert repr(a) == "array([2])"
+
+    def test_repr_multi(self):
+        from numpypy import arange, zeros, array
+        a = zeros((3, 4))
+        assert repr(a) == '''array([[ 0.,  0.,  0.,  0.],
+       [ 0.,  0.,  0.,  0.],
+       [ 0.,  0.,  0.,  0.]])'''
+        a = zeros((2, 3, 4))
+        assert repr(a) == '''array([[[ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.]],
+
+       [[ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.]]])'''
+        a = arange(1002).reshape((2, 501))
+        assert repr(a) == '''array([[   0,    1,    2, ...,  498,  499,  500],
+       [ 501,  502,  503, ...,  999, 1000, 1001]])'''
+        assert repr(a.T) == '''array([[   0,  501],
+       [   1,  502],
+       [   2,  503],
+       ..., 
+       [ 498,  999],
+       [ 499, 1000],
+       [ 500, 1001]])'''
+        a = arange(2).reshape((2,1))
+        assert repr(a) == '''array([[0],
+       [1]])'''
+
+    def test_repr_slice(self):
+        from numpypy import array, zeros
+        a = array(range(5), float)
+        b = a[1::2]
+        assert repr(b) == "array([ 1.,  3.])"
+        a = zeros(2002)
+        b = a[::2]
+        assert repr(b) == "array([ 0.,  0.,  0., ...,  0.,  0.,  0.])"
+        a = array((range(5), range(5, 10)), dtype="int16")
+        b = a[1, 2:]
+        assert repr(b) == "array([7, 8, 9], dtype=int16)"
+        # an empty slice prints its shape
+        b = a[2:1, ]
+        assert repr(b) == "array([], shape=(0, 5), dtype=int16)"
+
+    def test_str(self):
+        from numpypy import array, zeros
+        a = array(range(5), float)
+        assert str(a) == "[ 0.  1.  2.  3.  4.]"
+        assert str((2 * a)[:]) == "[ 0.  2.  4.  6.  8.]"
+        a = zeros(1001)
+        assert str(a) == "[ 0.  0.  0. ...,  0.  0.  0.]"
+
+        a = array(range(5), dtype=long)
+        assert str(a) == "[0 1 2 3 4]"
+        a = array([True, False, True, False], dtype="?")
+        assert str(a) == "[ True False  True False]"
+
+        a = array(range(5), dtype="int8")
+        assert str(a) == "[0 1 2 3 4]"
+
+        a = array(range(5), dtype="int16")
+        assert str(a) == "[0 1 2 3 4]"
+
+        a = array((range(5), range(5, 10)), dtype="int16")
+        assert str(a) == "[[0 1 2 3 4]\n [5 6 7 8 9]]"
+
+        a = array(3, dtype=int)
+        assert str(a) == "3"
+
+        a = zeros((400, 400), dtype=int)
+        assert str(a) == '[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]'
+        a = zeros((2, 2, 2))
+        r = str(a)
+        assert r == '[[[ 0.  0.]\n  [ 0.  0.]]\n\n [[ 0.  0.]\n  [ 0.  0.]]]'
+
+    def test_str_slice(self):
+        from numpypy import array, zeros
+        a = array(range(5), float)
+        b = a[1::2]
+        assert str(b) == "[ 1.  3.]"
+        a = zeros(2002)
+        b = a[::2]
+        assert str(b) == "[ 0.  0.  0. ...,  0.  0.  0.]"
+        a = array((range(5), range(5, 10)), dtype="int16")
+        b = a[1, 2:]
+        assert str(b) == "[7 8 9]"
+        b = a[2:1, ]
+        assert str(b) == "[]"
diff --git a/pypy/module/test_lib_pypy/test_datetime.py b/pypy/module/test_lib_pypy/test_datetime.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/test_datetime.py
@@ -0,0 +1,24 @@
+"""Additional tests for datetime."""
+
+import time
+import datetime
+import os
+
+def test_utcfromtimestamp():
+    """Confirm that utcfromtimestamp and fromtimestamp give consistent results.
+
+    Based on danchr's test script in https://bugs.pypy.org/issue986
+    """
+    try:
+        prev_tz = os.environ.get("TZ")
+        os.environ["TZ"] = "GMT"
+        for unused in xrange(100):
+            now = time.time()
+            delta = (datetime.datetime.utcfromtimestamp(now) -
+                     datetime.datetime.fromtimestamp(now))
+            assert delta.days * 86400 + delta.seconds == 0
+    finally:
+        if prev_tz is None:
+            del os.environ["TZ"]
+        else:
+            os.environ["TZ"] = prev_tz
diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/test_sqlite3.py
@@ -0,0 +1,10 @@
+"""Tests for _sqlite3.py"""
+
+def test_list_ddl():
+    """From issue996.  Mostly just looking for lack of exceptions."""
+    from sqlite3.dbapi2 import connect
+    connection = connect(':memory:')
+    cursor = connection.cursor()
+    cursor.execute('CREATE TABLE foo (bar INTEGER)')
+    result = list(cursor)
+    assert result == []
diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -4,7 +4,7 @@
 import py
 from pypy.rlib import jit, rgc
 from pypy.rlib.debug import ll_assert
-from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.tool import rffi_platform
 from pypy.tool import autopath
@@ -89,6 +89,7 @@
 def allocate_lock():
     return Lock(allocate_ll_lock())
 
+ at specialize.arg(0)
 def ll_start_new_thread(func):
     ident = c_thread_start(func)
     if ident == -1:
@@ -101,6 +102,7 @@
 def get_ident():
     return rffi.cast(lltype.Signed, c_thread_get_ident())
 
+ at specialize.arg(0)
 def start_new_thread(x, y):
     """In RPython, no argument can be passed.  You have to use global
     variables to pass information to the new thread.  That's not very
diff --git a/pypy/module/thread/test/test_ll_thread.py b/pypy/module/thread/test/test_ll_thread.py
--- a/pypy/module/thread/test/test_ll_thread.py
+++ b/pypy/module/thread/test/test_ll_thread.py
@@ -34,72 +34,34 @@
     use_threads = True
 
     def test_start_new_thread(self):
-        py.test.skip("xxx ideally, investigate why it fails randomly")
-        # xxx but in practice start_new_thread() is also tested by the
-        # next test, and it's a mess to test start_new_thread() without
-        # the proper GIL to protect the GC
         import time
 
         class State:
             pass
         state = State()
 
-        class Z:
-            def __init__(self, value):
-                self.value = value
-            def __del__(self):
-                state.freed_counter += 1
-
-        def bootstrap():
-            state.my_thread_ident = state.z.ident = get_ident()
-            assert state.my_thread_ident == get_ident()
-            assert get_ident() == state.z.ident
-            state.seen_value = state.z.value
-            state.z = None
-            # I think that we would need here a memory barrier in order
-            # to make the test pass reliably.  The issue is that the
-            # main thread may see 'state.done = 1' before seeing the
-            # effect of the other assignments done above.  For now let's
-            # emulate the write barrier by doing a system call and
-            # waiting a bit...
-            time.sleep(0.012)
-            state.done = 1
-
-        def g(i):
-            state.z = Z(i)
-            return start_new_thread(bootstrap, ())
-        g._dont_inline_ = True
+        def bootstrap1():
+            state.my_thread_ident1 = get_ident()
+        def bootstrap2():
+            state.my_thread_ident2 = get_ident()
 
         def f():
-            main_ident = get_ident()
-            assert main_ident == get_ident()
-            state.freed_counter = 0
-            for i in range(50):
-                state.done = 0
-                state.seen_value = 0
-                ident = g(i)
-                gc.collect()
-                willing_to_wait_more = 1000
-                while not state.done:
-                    willing_to_wait_more -= 1
-                    if not willing_to_wait_more:
-                        raise Exception("thread didn't start?")
-                    time.sleep(0.01)
-                assert state.my_thread_ident != main_ident
-                assert state.my_thread_ident == ident
-                assert state.seen_value == i
-            # try to force Boehm to do some freeing
-            for i in range(3):
-                gc.collect()
-            return state.freed_counter
+            state.my_thread_ident1 = get_ident()
+            state.my_thread_ident2 = get_ident()
+            start_new_thread(bootstrap1, ())
+            start_new_thread(bootstrap2, ())
+            willing_to_wait_more = 1000
+            while (state.my_thread_ident1 == get_ident() or
+                   state.my_thread_ident2 == get_ident()):
+                willing_to_wait_more -= 1
+                if not willing_to_wait_more:
+                    raise Exception("thread didn't start?")
+                time.sleep(0.01)
+            return 42
 
         fn = self.getcompiled(f, [])
-        freed_counter = fn()
-        print freed_counter
-        if self.gcpolicy == 'boehm':
-            assert freed_counter > 0
-        else:
-            assert freed_counter == 50
+        res = fn()
+        assert res == 42
 
     def test_gc_locking(self):
         import time
@@ -202,6 +164,9 @@
     def getcompiled(self, f, argtypes):
         return f
 
+    def test_start_new_thread(self):
+        py.test.skip("deadlocks occasionally -- why???")
+
 class TestUsingBoehm(AbstractThreadTests):
     gcpolicy = 'boehm'
 
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -150,6 +150,8 @@
                 self._see_getsetproperty(x)
         if isinstance(x, r_singlefloat):
             self._wrap_not_rpython(x)
+        if isinstance(x, list):
+            self._wrap_not_rpython(x)
         return w_some_obj()
     wrap._annspecialcase_ = "specialize:argtype(1)"
 
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -565,8 +565,8 @@
 
     if step == 1:
         assert start >= 0
-        assert slicelength >= 0
-        del items[start:start+slicelength]
+        if slicelength > 0:
+            del items[start:start+slicelength]
     else:
         n = len(items)
         i = start
@@ -603,10 +603,11 @@
             while i >= lim:
                 items[i] = items[i-delta]
                 i -= 1
-        elif start >= 0:
+        elif delta == 0:
+            pass
+        else:
+            assert start >= 0   # start<0 is only possible with slicelength==0
             del items[start:start+delta]
-        else:
-            assert delta==0   # start<0 is only possible with slicelength==0
     elif len2 != slicelength:  # No resize for extended slices
         raise operationerrfmt(space.w_ValueError, "attempt to "
               "assign sequence of size %d to extended slice of size %d",
diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -9,6 +9,7 @@
 from pypy.rlib.rfloat import (
     formatd, DTSF_STR_PRECISION, isinf, isnan, copysign)
 from pypy.rlib.objectmodel import HASH_IMAG
+from pypy.rlib import jit
 
 import math
 
@@ -119,10 +120,10 @@
             ir = len * math.sin(phase)
         return W_ComplexObject(rr, ir)
 
-    def pow_int(self, n):
-        if n > 100 or n < -100:
-            return self.pow(W_ComplexObject(1.0 * n, 0.0))
-        elif n > 0:
+    def pow_small_int(self, n):
+        if n >= 0:
+            if jit.isconstant(n) and n == 2:
+                return self.mul(self)
             return self.pow_positive_int(n)
         else:
             return w_one.div(self.pow_positive_int(-n))
@@ -187,10 +188,10 @@
 def pow__Complex_Complex_ANY(space, w_complex, w_exponent, thirdArg):
     if not space.is_w(thirdArg, space.w_None):
         raise OperationError(space.w_ValueError, space.wrap('complex modulo'))
-    int_exponent = int(w_exponent.realval)
     try:
-        if w_exponent.imagval == 0.0 and w_exponent.realval == int_exponent:
-            w_p = w_complex.pow_int(int_exponent)
+        r = w_exponent.realval
+        if w_exponent.imagval == 0.0 and -100.0 <= r <= 100.0 and r == int(r):
+            w_p = w_complex.pow_small_int(int(r))
         else:
             w_p = w_complex.pow(w_exponent)
     except ZeroDivisionError:
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -442,6 +442,8 @@
     y = w_float2.floatval
 
     # Sort out special cases here instead of relying on pow()
+    if y == 2.0:                      # special case for performance:
+        return W_FloatObject(x * x)   # x * x is always correct
     if y == 0.0:
         # x**0 is 1, even 0**0
         return W_FloatObject(1.0)
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -110,7 +110,10 @@
         return list(items)
 
     def switch_to_object_strategy(self):
-        list_w = self.getitems()
+        if self.strategy is self.space.fromcache(EmptyListStrategy):
+            list_w = []
+        else:
+            list_w = self.getitems()
         self.strategy = self.space.fromcache(ObjectListStrategy)
         # XXX this is quite indirect
         self.init_from_list_w(list_w)
@@ -344,8 +347,6 @@
 
     def __init__(self, space):
         ListStrategy.__init__(self, space)
-        # cache an empty list that is used whenever getitems is called (i.e. sorting)
-        self.cached_emptylist_w = []
 
     def init_from_list_w(self, w_list, list_w):
         assert len(list_w) == 0
@@ -373,10 +374,10 @@
     def getslice(self, w_list, start, stop, step, length):
         # will never be called because the empty list case is already caught in
         # getslice__List_ANY_ANY and getitem__List_Slice
-        return W_ListObject(self.space, self.cached_emptylist_w)
+        return W_ListObject(self.space, [])
 
     def getitems(self, w_list):
-        return self.cached_emptylist_w
+        return []
 
     def getitems_copy(self, w_list):
         return []
@@ -804,10 +805,11 @@
                 while i >= lim:
                     items[i] = items[i-delta]
                     i -= 1
-            elif start >= 0:
+            elif delta == 0:
+                pass
+            else:
+                assert start >= 0 # start<0 is only possible with slicelength==0
                 del items[start:start+delta]
-            else:
-                assert delta==0   # start<0 is only possible with slicelength==0
         elif len2 != slicelength:  # No resize for extended slices
             raise operationerrfmt(self.space.w_ValueError, "attempt to "
                   "assign sequence of size %d to extended slice of size %d",
@@ -851,8 +853,8 @@
 
         if step == 1:
             assert start >= 0
-            assert slicelength >= 0
-            del items[start:start+slicelength]
+            if slicelength > 0:
+                del items[start:start+slicelength]
         else:
             n = len(items)
             i = start
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -1,5 +1,9 @@
+from pypy import conftest
 
 class AppTestBytesArray:
+    def setup_class(cls):
+        cls.w_runappdirect = cls.space.wrap(conftest.option.runappdirect)
+
     def test_basics(self):
         b = bytearray()
         assert type(b) is bytearray
@@ -434,3 +438,15 @@
     def test_reduce(self):
         assert bytearray(b'caf\xe9').__reduce__() == (
             bytearray, (u'caf\xe9', 'latin-1'), None)
+
+    def test_setitem_slice_performance(self):
+        # because of a complexity bug, this used to take forever on a
+        # translated pypy.  On CPython2.6 -A, it takes around 8 seconds.
+        if self.runappdirect:
+            count = 16*1024*1024
+        else:
+            count = 1024
+        b = bytearray(count)
+        for i in range(count):
+            b[i:i+1] = 'y'
+        assert str(b) == 'y' * count
diff --git a/pypy/objspace/std/test/test_complexobject.py b/pypy/objspace/std/test/test_complexobject.py
--- a/pypy/objspace/std/test/test_complexobject.py
+++ b/pypy/objspace/std/test/test_complexobject.py
@@ -74,7 +74,7 @@
         assert _powu((0.0,1.0),2) == (-1.0,0.0)
 
         def _powi((r1, i1), n):
-            w_res = W_ComplexObject(r1, i1).pow_int(n)
+            w_res = W_ComplexObject(r1, i1).pow_small_int(n)
             return w_res.realval, w_res.imagval
         assert _powi((0.0,2.0),0) == (1.0,0.0)
         assert _powi((0.0,0.0),2) == (0.0,0.0)
@@ -213,6 +213,7 @@
         assert a ** 105 == a ** 105
         assert a ** -105 == a ** -105
         assert a ** -30 == a ** -30
+        assert a ** 2 == a * a
 
         assert 0.0j ** 0 == 1
 
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -397,6 +397,7 @@
         on_cpython = (option.runappdirect and
                             not hasattr(sys, 'pypy_translation_info'))
         cls.w_on_cpython = cls.space.wrap(on_cpython)
+        cls.w_runappdirect = cls.space.wrap(option.runappdirect)
 
     def test_getstrategyfromlist_w(self):
         l0 = ["a", "2", "a", True]
@@ -885,6 +886,18 @@
         l[::-1] = l
         assert l == [6,5,4,3,2,1]
 
+    def test_setitem_slice_performance(self):
+        # because of a complexity bug, this used to take forever on a
+        # translated pypy.  On CPython2.6 -A, it takes around 5 seconds.
+        if self.runappdirect:
+            count = 16*1024*1024
+        else:
+            count = 1024
+        b = [None] * count
+        for i in range(count):
+            b[i:i+1] = ['y']
+        assert b == ['y'] * count
+
     def test_recursive_repr(self):
         l = []
         assert repr(l) == '[]'
@@ -1113,6 +1126,21 @@
         assert l == []
         assert list(g) == []
 
+class AppTestWithoutStrategies(object):
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withliststrategies" :
+                                       False})
+
+    def test_no_shared_empty_list(self):
+        l = []
+        copy = l[:]
+        copy.append({})
+        assert copy == [{}]
+
+        notshared = l[:]
+        assert notshared == []
+
 class AppTestListFastSubscr:
 
     def setup_class(cls):
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -130,19 +130,29 @@
         if self is other:
             return 0
         else:
-            raise TypeError("Symbolics can not be compared!")
+            raise TypeError("Symbolics cannot be compared! (%r, %r)"
+                            % (self, other))
 
     def __hash__(self):
-        raise TypeError("Symbolics are not hashable!")
+        raise TypeError("Symbolics are not hashable! %r" % (self,))
 
     def __nonzero__(self):
-        raise TypeError("Symbolics are not comparable")
+        raise TypeError("Symbolics are not comparable! %r" % (self,))
 
 class ComputedIntSymbolic(Symbolic):
 
     def __init__(self, compute_fn):
         self.compute_fn = compute_fn
 
+    def __repr__(self):
+        # repr(self.compute_fn) can arrive back here in an
+        # infinite recursion
+        try:
+            name = self.compute_fn.__name__
+        except (AttributeError, TypeError):
+            name = hex(id(self.compute_fn))
+        return '%s(%r)' % (self.__class__.__name__, name)
+
     def annotation(self):
         from pypy.annotation import model
         return model.SomeInteger()
@@ -157,6 +167,9 @@
         self.expr = expr
         self.default = default
 
+    def __repr__(self):
+        return '%s(%r)' % (self.__class__.__name__, self.expr)
+
     def annotation(self):
         from pypy.annotation import model
         return model.SomeInteger()
diff --git a/pypy/rlib/rdynload.py b/pypy/rlib/rdynload.py
--- a/pypy/rlib/rdynload.py
+++ b/pypy/rlib/rdynload.py
@@ -14,7 +14,7 @@
 _MINGW = platform.name == "mingw32"
 _WIN32 = _MSVC or _MINGW
 _MAC_OS = platform.name == "darwin"
-_FREEBSD = platform.name == "freebsd"
+_FREEBSD = sys.platform.startswith("freebsd")
 
 if _WIN32:
     from pypy.rlib import rwin32
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -70,6 +70,8 @@
     SSL_OP_NO_SSLv2 = rffi_platform.ConstantInteger("SSL_OP_NO_SSLv2")
     SSL_OP_NO_SSLv3 = rffi_platform.ConstantInteger("SSL_OP_NO_SSLv3")
     SSL_OP_NO_TLSv1 = rffi_platform.ConstantInteger("SSL_OP_NO_TLSv1")
+    SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = rffi_platform.ConstantInteger(
+        "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS")
     HAS_SNI = rffi_platform.Defined("SSL_CTRL_SET_TLSEXT_HOSTNAME")
     SSL_VERIFY_NONE = rffi_platform.ConstantInteger("SSL_VERIFY_NONE")
     SSL_VERIFY_PEER = rffi_platform.ConstantInteger("SSL_VERIFY_PEER")
diff --git a/pypy/rlib/rsocket.py b/pypy/rlib/rsocket.py
--- a/pypy/rlib/rsocket.py
+++ b/pypy/rlib/rsocket.py
@@ -310,10 +310,7 @@
 
     def from_object(space, w_address):
         # Parse an app-level object representing an AF_INET address
-        try:
-            w_host, w_port = space.unpackiterable(w_address, 2)
-        except ValueError:
-            raise TypeError("AF_INET address must be a tuple of length 2")
+        w_host, w_port = space.unpackiterable(w_address, 2)
         host = space.str_w(w_host)
         port = space.int_w(w_port)
         port = Address.make_ushort_port(space, port)
@@ -549,10 +546,7 @@
                                    space.wrap(self.get_groups())])
 
         def from_object(space, w_address):
-            try:
-                w_pid, w_groups = space.unpackiterable(w_address, 2)
-            except ValueError:
-                raise TypeError("AF_NETLINK address must be a tuple of length 2")
+            w_pid, w_groups = space.unpackiterable(w_address, 2)
             return NETLINKAddress(space.uint_w(w_pid), space.uint_w(w_groups))
         from_object = staticmethod(from_object)
 
diff --git a/pypy/rlib/rstacklet.py b/pypy/rlib/rstacklet.py
--- a/pypy/rlib/rstacklet.py
+++ b/pypy/rlib/rstacklet.py
@@ -1,3 +1,4 @@
+import sys
 from pypy.rlib import _rffi_stacklet as _c
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import we_are_translated
@@ -72,6 +73,11 @@
     if translated:
         assert config is not None, ("you have to pass a valid config, "
                                     "e.g. from 'driver.config'")
+    elif '__pypy__' in sys.builtin_module_names:
+        import py
+        py.test.skip("cannot run the stacklet tests on top of pypy: "
+                     "calling directly the C function stacklet_switch() "
+                     "will crash, depending on details of your config")
     if config is not None:
         assert config.translation.continuation, (
             "stacklet: you have to translate with --continuation")
diff --git a/pypy/rlib/rweakref.py b/pypy/rlib/rweakref.py
--- a/pypy/rlib/rweakref.py
+++ b/pypy/rlib/rweakref.py
@@ -1,11 +1,14 @@
 """
-Weakref support in RPython.  Supports ref() without callbacks,
+Weakref support in RPython.  Basic regular weakrefs without callbacks
+are supported.  This file contains the following additions:
 a form of WeakKeyDictionary, and a limited version of WeakValueDictionary.
 LLType only for now!
 """
 
 import weakref
 
+ref = weakref.ref    # basic regular weakrefs are supported in RPython
+
 
 class RWeakValueDictionary(object):
     """A dictionary containing weak values."""
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -1390,7 +1390,8 @@
             def _where_is_errno():
                 return standard_c_lib.__errno_location()
 
-        elif sys.platform in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9'):
+        elif any(plat in sys.platform
+                 for plat in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9')):
             standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)
             def _where_is_errno():
                 return standard_c_lib.__error()
diff --git a/pypy/rpython/lltypesystem/llgroup.py b/pypy/rpython/lltypesystem/llgroup.py
--- a/pypy/rpython/lltypesystem/llgroup.py
+++ b/pypy/rpython/lltypesystem/llgroup.py
@@ -76,6 +76,10 @@
         self.index = memberindex
         self.member = grp.members[memberindex]._as_ptr()
 
+    def __repr__(self):
+        return '%s(%s, %s)' % (self.__class__.__name__,
+                               self.grpptr, self.index)
+
     def __nonzero__(self):
         return True
 
diff --git a/pypy/rpython/lltypesystem/llmemory.py b/pypy/rpython/lltypesystem/llmemory.py
--- a/pypy/rpython/lltypesystem/llmemory.py
+++ b/pypy/rpython/lltypesystem/llmemory.py
@@ -32,7 +32,8 @@
             self.known_nonneg()):
             return True
         else:
-            raise TypeError("Symbolics can not be compared!")
+            raise TypeError("Symbolics cannot be compared! (%r, %r)"
+                            % (self, other))
 
     def __lt__(self, other):
         return not self.__ge__(other)
diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -330,6 +330,17 @@
         hop.exception_is_here()
         return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
 
+    def rtype_method_pop(self, hop):
+        if hop.nb_args == 2:
+            v_args = hop.inputargs(self, self.key_repr)
+            target = ll_pop
+        elif hop.nb_args == 3:
+            v_args = hop.inputargs(self, self.key_repr, self.value_repr)
+            target = ll_pop_default
+        hop.exception_is_here()
+        v_res = hop.gendirectcall(target, *v_args)
+        return self.recast_value(hop.llops, v_res)
+
 class __extend__(pairtype(DictRepr, rmodel.Repr)):
 
     def rtype_getitem((r_dict, r_key), hop):
@@ -890,3 +901,18 @@
     r.item1 = recast(ELEM.TO.item1, entry.value)
     _ll_dict_del(dic, i)
     return r
+
+def ll_pop(dic, key):
+    i = ll_dict_lookup(dic, key, dic.keyhash(key))
+    if not i & HIGHEST_BIT:
+        value = ll_get_value(dic, i)
+        _ll_dict_del(dic, i)
+        return value
+    else:
+        raise KeyError
+
+def ll_pop_default(dic, key, dfl):
+    try:
+        return ll_pop(dic, key)
+    except KeyError:
+        return dfl
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -27,6 +27,10 @@
         self.c_name = c_name
         self.TP = TP
 
+    def __repr__(self):
+        return '%s(%r, %s)' % (self.__class__.__name__,
+                               self.c_name, self.TP)
+
     def annotation(self):
         return lltype_to_annotation(self.TP)
 
@@ -755,6 +759,7 @@
     alloc_buffer._annenforceargs_ = [int]
 
     # (char*, str, int, int) -> None
+    @jit.dont_look_inside
     def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size):
         """
         Converts from a pair returned by alloc_buffer to a high-level string.
@@ -780,6 +785,7 @@
         return hlstrtype(new_buf)
 
     # (char*, str) -> None
+    @jit.dont_look_inside
     def keep_buffer_alive_until_here(raw_buf, gc_buf):
         """
         Keeps buffers alive or frees temporary buffers created by alloc_buffer.
diff --git a/pypy/rpython/memory/gc/env.py b/pypy/rpython/memory/gc/env.py
--- a/pypy/rpython/memory/gc/env.py
+++ b/pypy/rpython/memory/gc/env.py
@@ -116,7 +116,7 @@
     def get_total_memory():
         return get_total_memory_darwin(get_darwin_sysctl_signed('hw.memsize'))
 
-elif sys.platform.startswith('freebsd'):
+elif 'freebsd' in sys.platform:
     def get_total_memory():
         return get_total_memory_darwin(get_darwin_sysctl_signed('hw.usermem'))
 
diff --git a/pypy/rpython/memory/gctransform/shadowstack.py b/pypy/rpython/memory/gctransform/shadowstack.py
--- a/pypy/rpython/memory/gctransform/shadowstack.py
+++ b/pypy/rpython/memory/gctransform/shadowstack.py
@@ -27,28 +27,17 @@
             return top
         self.decr_stack = decr_stack
 
-        translator = gctransformer.translator
-        if (hasattr(translator, '_jit2gc') and
-                'root_iterator' in translator._jit2gc):
-            root_iterator = translator._jit2gc['root_iterator']
-            def jit_walk_stack_root(callback, addr, end):
-                root_iterator.context = NonConstant(llmemory.NULL)
-                gc = self.gc
-                while True:
-                    addr = root_iterator.next(gc, addr, end)
-                    if addr == llmemory.NULL:
-                        return
-                    callback(gc, addr)
-                    addr += sizeofaddr
-            self.rootstackhook = jit_walk_stack_root
-        else:
-            def default_walk_stack_root(callback, addr, end):
-                gc = self.gc
-                while addr != end:
-                    if gc.points_to_valid_gc_object(addr):
-                        callback(gc, addr)
-                    addr += sizeofaddr
-            self.rootstackhook = default_walk_stack_root
+        root_iterator = get_root_iterator(gctransformer)
+        def walk_stack_root(callback, start, end):
+            root_iterator.setcontext(NonConstant(llmemory.NULL))
+            gc = self.gc
+            addr = end
+            while True:
+                addr = root_iterator.nextleft(gc, start, addr)
+                if addr == llmemory.NULL:
+                    return
+                callback(gc, addr)
+        self.rootstackhook = walk_stack_root
 
         self.shadow_stack_pool = ShadowStackPool(gcdata)
         rsd = gctransformer.root_stack_depth
@@ -331,6 +320,30 @@
                 raise MemoryError
 
 
+def get_root_iterator(gctransformer):
+    if hasattr(gctransformer, '_root_iterator'):
+        return gctransformer._root_iterator     # if already built
+    translator = gctransformer.translator
+    if (hasattr(translator, '_jit2gc') and
+            'root_iterator' in translator._jit2gc):
+        result = translator._jit2gc['root_iterator']
+    else:
+        class RootIterator(object):
+            def _freeze_(self):
+                return True
+            def setcontext(self, context):
+                pass
+            def nextleft(self, gc, start, addr):
+                while addr != start:
+                    addr -= sizeofaddr
+                    if gc.points_to_valid_gc_object(addr):
+                        return addr
+                return llmemory.NULL
+        result = RootIterator()
+    gctransformer._root_iterator = result
+    return result
+
+
 def get_shadowstackref(gctransformer):
     if hasattr(gctransformer, '_SHADOWSTACKREF'):
         return gctransformer._SHADOWSTACKREF
@@ -344,28 +357,15 @@
                                      rtti=True)
     SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF)
 
-    translator = gctransformer.translator
-    if hasattr(translator, '_jit2gc'):
-        gc = gctransformer.gcdata.gc
-        root_iterator = translator._jit2gc['root_iterator']
-        def customtrace(obj, prev):
-            obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
-            if not prev:
-                root_iterator.context = obj.context
-                next = obj.base
-            else:
-                next = prev + sizeofaddr
-            return root_iterator.next(gc, next, obj.top)
-    else:
-        def customtrace(obj, prev):
-            # a simple but not JIT-ready version
-            if not prev:
-                next = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).base
-            else:
-                next = prev + sizeofaddr
-            if next == llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).top:
-                next = llmemory.NULL
-            return next
+    gc = gctransformer.gcdata.gc
+    root_iterator = get_root_iterator(gctransformer)
+
+    def customtrace(obj, prev):
+        obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
+        if not prev:
+            root_iterator.setcontext(obj.context)
+            prev = obj.top
+        return root_iterator.nextleft(gc, obj.base, prev)
 
     CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
                                       llmemory.Address)
diff --git a/pypy/rpython/module/ll_time.py b/pypy/rpython/module/ll_time.py
--- a/pypy/rpython/module/ll_time.py
+++ b/pypy/rpython/module/ll_time.py
@@ -41,7 +41,7 @@
         RUSAGE = platform.Struct('struct rusage', [('ru_utime', TIMEVAL),
                                                    ('ru_stime', TIMEVAL)])
 
-if "freebsd" in sys.platform:
+if sys.platform.startswith('freebsd'):
     libraries = ['compat']
 else:
     libraries = []
diff --git a/pypy/rpython/ootypesystem/rdict.py b/pypy/rpython/ootypesystem/rdict.py
--- a/pypy/rpython/ootypesystem/rdict.py
+++ b/pypy/rpython/ootypesystem/rdict.py
@@ -167,6 +167,16 @@
         hop.exception_is_here()
         return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
 
+    def rtype_method_pop(self, hop):
+        if hop.nb_args == 2:
+            v_args = hop.inputargs(self, self.key_repr)
+            target = ll_pop
+        elif hop.nb_args == 3:
+            v_args = hop.inputargs(self, self.key_repr, self.value_repr)
+            target = ll_pop_default
+        hop.exception_is_here()
+        return hop.gendirectcall(target, *v_args)
+
     def __get_func(self, interp, r_func, fn, TYPE):
         if isinstance(r_func, MethodOfFrozenPBCRepr):
             obj = r_func.r_im_self.convert_const(fn.im_self)
@@ -385,6 +395,20 @@
         return res
     raise KeyError
 
+def ll_pop(d, key):
+    if d.ll_contains(key):
+        value = d.ll_get(key)
+        d.ll_remove(key)
+        return value
+    else:
+        raise KeyError
+
+def ll_pop_default(d, key, dfl):
+    try:
+        return ll_pop(d, key)
+    except KeyError:
+        return dfl
+
 # ____________________________________________________________
 #
 #  Iteration.
diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -25,37 +25,37 @@
 class BaseTestRdict(BaseRtypingTest):
 
     def test_dict_creation(self):
-        def createdict(i): 
+        def createdict(i):
             d = {'hello' : i}
             return d['hello']
 
         res = self.interpret(createdict, [42])
         assert res == 42
 
-    def test_dict_getitem_setitem(self): 
-        def func(i): 
+    def test_dict_getitem_setitem(self):
+        def func(i):
             d = {'hello' : i}
             d['world'] = i + 1
-            return d['hello'] * d['world'] 
+            return d['hello'] * d['world']
         res = self.interpret(func, [6])
         assert res == 42
 
-    def test_dict_getitem_keyerror(self): 
-        def func(i): 
+    def test_dict_getitem_keyerror(self):
+        def func(i):
             d = {'hello' : i}
             try:
                 return d['world']
             except KeyError:
-                return 0 
+                return 0
         res = self.interpret(func, [6])
         assert res == 0
 
     def test_dict_del_simple(self):
-        def func(i): 
+        def func(i):
             d = {'hello' : i}
             d['world'] = i + 1
             del d['hello']
-            return len(d) 
+            return len(d)
         res = self.interpret(func, [6])
         assert res == 1
 
@@ -71,7 +71,7 @@
         assert res == True
 
     def test_empty_strings(self):
-        def func(i): 
+        def func(i):
             d = {'' : i}
             del d['']
             try:
@@ -83,7 +83,7 @@
         res = self.interpret(func, [6])
         assert res == 1
 
-        def func(i): 
+        def func(i):
             d = {'' : i}
             del d['']
             d[''] = i + 1
@@ -146,8 +146,8 @@
             d1 = {}
             d1['hello'] = i + 1
             d2 = {}
-            d2['world'] = d1 
-            return d2['world']['hello'] 
+            d2['world'] = d1
+            return d2['world']['hello']
         res = self.interpret(func, [5])
         assert res == 6
 
@@ -307,7 +307,7 @@
             a = 0
             for k, v in items:
                 b += isinstance(k, B)
-                a += isinstance(v, A) 
+                a += isinstance(v, A)
             return 3*b+a
         res = self.interpret(func, [])
         assert res == 8
@@ -326,7 +326,7 @@
             a = 0
             for k, v in dic.iteritems():
                 b += isinstance(k, B)
-                a += isinstance(v, A) 
+                a += isinstance(v, A)
             return 3*b+a
         res = self.interpret(func, [])
         assert res == 8
@@ -352,11 +352,11 @@
     def test_dict_contains_with_constant_dict(self):
         dic = {'4':1000, ' 8':200}
         def func(i):
-            return chr(i) in dic 
-        res = self.interpret(func, [ord('4')]) 
+            return chr(i) in dic
+        res = self.interpret(func, [ord('4')])
         assert res is True
-        res = self.interpret(func, [1]) 
-        assert res is False 
+        res = self.interpret(func, [1])
+        assert res is False
 
     def test_dict_or_none(self):
         class A:
@@ -423,7 +423,7 @@
             return g(get)
 
         res = self.interpret(f, [])
-        assert res == 2    
+        assert res == 2
 
     def test_specific_obscure_bug(self):
         class A: pass
@@ -632,6 +632,42 @@
         res = self.interpret(func, [])
         assert res in [5263, 6352]
 
+    def test_dict_pop(self):
+        def f(n, default):
+            d = {}
+            d[2] = 3
+            d[4] = 5
+            if default == -1:
+                try:
+                    x = d.pop(n)
+                except KeyError:
+                    x = -1
+            else:
+                x = d.pop(n, default)
+            return x * 10 + len(d)
+        res = self.interpret(f, [2, -1])
+        assert res == 31
+        res = self.interpret(f, [3, -1])
+        assert res == -8
+        res = self.interpret(f, [2, 5])
+        assert res == 31
+
+    def test_dict_pop_instance(self):
+        class A(object):
+            pass
+        def f(n):
+            d = {}
+            d[2] = A()
+            x = d.pop(n, None)
+            if x is None:
+                return 12
+            else:
+                return 15
+        res = self.interpret(f, [2])
+        assert res == 15
+        res = self.interpret(f, [700])
+        assert res == 12
+
 class TestLLtype(BaseTestRdict, LLRtypeMixin):
     def test_dict_but_not_with_char_keys(self):
         def func(i):
@@ -643,19 +679,19 @@
         res = self.interpret(func, [6])
         assert res == 0
 
-    def test_deleted_entry_reusage_with_colliding_hashes(self): 
-        def lowlevelhash(value): 
+    def test_deleted_entry_reusage_with_colliding_hashes(self):
+        def lowlevelhash(value):
             p = rstr.mallocstr(len(value))
             for i in range(len(value)):
                 p.chars[i] = value[i]
-            return rstr.LLHelpers.ll_strhash(p) 
+            return rstr.LLHelpers.ll_strhash(p)
 
-        def func(c1, c2): 
-            c1 = chr(c1) 
-            c2 = chr(c2) 
+        def func(c1, c2):
+            c1 = chr(c1)
+            c2 = chr(c2)
             d = {}
             d[c1] = 1
-            d[c2] = 2 
+            d[c2] = 2
             del d[c1]
             return d[c2]
 
@@ -663,7 +699,7 @@
         base = rdict.DICT_INITSIZE
         for y in range(0, 256):
             y = chr(y)
-            y_hash = lowlevelhash(y) % base 
+            y_hash = lowlevelhash(y) % base
             char_by_hash.setdefault(y_hash, []).append(y)
 
         x, y = char_by_hash[0][:2]   # find a collision
@@ -671,18 +707,18 @@
         res = self.interpret(func, [ord(x), ord(y)])
         assert res == 2
 
-        def func2(c1, c2): 
-            c1 = chr(c1) 
-            c2 = chr(c2) 
+        def func2(c1, c2):
+            c1 = chr(c1)
+            c2 = chr(c2)
             d = {}
             d[c1] = 1
-            d[c2] = 2 
+            d[c2] = 2
             del d[c1]
             d[c1] = 3
-            return d 
+            return d
 
         res = self.interpret(func2, [ord(x), ord(y)])
-        for i in range(len(res.entries)): 
+        for i in range(len(res.entries)):
             assert not (res.entries.everused(i) and not res.entries.valid(i))
 
         def func3(c0, c1, c2, c3, c4, c5, c6, c7):
@@ -697,9 +733,9 @@
             c7 = chr(c7) ; d[c7] = 1; del d[c7]
             return d
 
-        if rdict.DICT_INITSIZE != 8: 
+        if rdict.DICT_INITSIZE != 8:
             py.test.skip("make dict tests more indepdent from initsize")
-        res = self.interpret(func3, [ord(char_by_hash[i][0]) 
+        res = self.interpret(func3, [ord(char_by_hash[i][0])
                                    for i in range(rdict.DICT_INITSIZE)])
         count_frees = 0
         for i in range(len(res.entries)):
@@ -717,9 +753,9 @@
                     del d[chr(ord('a') + i)]
             return d
         res = self.interpret(func, [0])
-        assert len(res.entries) > rdict.DICT_INITSIZE 
+        assert len(res.entries) > rdict.DICT_INITSIZE
         res = self.interpret(func, [1])
-        assert len(res.entries) == rdict.DICT_INITSIZE 
+        assert len(res.entries) == rdict.DICT_INITSIZE
 
     def test_dict_valid_resize(self):
         # see if we find our keys after resize
@@ -854,7 +890,7 @@
 
     def test_prebuilt_list_of_addresses(self):
         from pypy.rpython.lltypesystem import llmemory
-        
+
         TP = lltype.Struct('x', ('y', lltype.Signed))
         a = lltype.malloc(TP, flavor='raw', immortal=True)
         b = lltype.malloc(TP, flavor='raw', immortal=True)
@@ -868,7 +904,7 @@
 
         d = {a_a: 3, a_b: 4, a_c: 5}
         d[a0] = 8
-        
+
         def func(i):
             if i == 0:
                 ptr = a
@@ -898,7 +934,7 @@
             return a == b
         def rhash(a):
             return 3
-        
+
         def func(i):
             d = r_dict(eq, rhash, force_non_null=True)
             if not i:
diff --git a/pypy/translator/c/src/profiling.c b/pypy/translator/c/src/profiling.c
--- a/pypy/translator/c/src/profiling.c
+++ b/pypy/translator/c/src/profiling.c
@@ -29,33 +29,33 @@
     profiling_setup = 0;
   }
 }
-
-#elif defined(_WIN32)
-#include <windows.h>
-
-DWORD_PTR base_affinity_mask;
-int profiling_setup = 0;
-
-void pypy_setup_profiling() { 
-    if (!profiling_setup) {
-        DWORD_PTR affinity_mask, system_affinity_mask;
-        GetProcessAffinityMask(GetCurrentProcess(),
-            &base_affinity_mask, &system_affinity_mask);
-        affinity_mask = 1;
-        /* Pick one cpu allowed by the system */
-        if (system_affinity_mask)
-            while ((affinity_mask & system_affinity_mask) == 0)
-                affinity_mask <<= 1;
-        SetProcessAffinityMask(GetCurrentProcess(), affinity_mask);
-        profiling_setup = 1;
-    }
-}
-
-void pypy_teardown_profiling() {
-    if (profiling_setup) {
-        SetProcessAffinityMask(GetCurrentProcess(), base_affinity_mask);
-        profiling_setup = 0;
-    }
+
+#elif defined(_WIN32)
+#include <windows.h>
+
+DWORD_PTR base_affinity_mask;
+int profiling_setup = 0;
+
+void pypy_setup_profiling() { 
+    if (!profiling_setup) {
+        DWORD_PTR affinity_mask, system_affinity_mask;
+        GetProcessAffinityMask(GetCurrentProcess(),
+            &base_affinity_mask, &system_affinity_mask);
+        affinity_mask = 1;
+        /* Pick one cpu allowed by the system */
+        if (system_affinity_mask)
+            while ((affinity_mask & system_affinity_mask) == 0)
+                affinity_mask <<= 1;
+        SetProcessAffinityMask(GetCurrentProcess(), affinity_mask);
+        profiling_setup = 1;
+    }
+}
+
+void pypy_teardown_profiling() {
+    if (profiling_setup) {
+        SetProcessAffinityMask(GetCurrentProcess(), base_affinity_mask);
+        profiling_setup = 0;
+    }
 }
 
 #else
diff --git a/pypy/translator/goal/targetnopstandalone.py b/pypy/translator/goal/targetnopstandalone.py
--- a/pypy/translator/goal/targetnopstandalone.py
+++ b/pypy/translator/goal/targetnopstandalone.py
@@ -7,10 +7,8 @@
 actually implementing argv of the executable.
 """
 
-import os, sys
-
-def debug(msg): 
-    os.write(2, "debug: " + msg + '\n')
+def debug(msg):
+    print "debug:", msg
 
 # __________  Entry point  __________
 
diff --git a/pypy/translator/goal/translate.py b/pypy/translator/goal/translate.py
--- a/pypy/translator/goal/translate.py
+++ b/pypy/translator/goal/translate.py
@@ -293,17 +293,18 @@
             drv.exe_name = targetspec_dic['__name__'] + '-%(backend)s'
 
         # Double check to ensure we are not overwriting the current interpreter
-        try:
-            this_exe = py.path.local(sys.executable).new(ext='')
-            exe_name = drv.compute_exe_name()
-            samefile = this_exe.samefile(exe_name)
-            assert not samefile, (
-                'Output file %s is the currently running '
-                'interpreter (use --output=...)'% exe_name)
-        except EnvironmentError:
-            pass
+        goals = translateconfig.goals
+        if not goals or 'compile' in goals:
+            try:
+                this_exe = py.path.local(sys.executable).new(ext='')
+                exe_name = drv.compute_exe_name()
+                samefile = this_exe.samefile(exe_name)
+                assert not samefile, (
+                    'Output file %s is the currently running '
+                    'interpreter (use --output=...)'% exe_name)
+            except EnvironmentError:
+                pass
 
-        goals = translateconfig.goals
         try:
             drv.proceed(goals)
         finally:
diff --git a/pypy/translator/platform/freebsd.py b/pypy/translator/platform/freebsd.py
--- a/pypy/translator/platform/freebsd.py
+++ b/pypy/translator/platform/freebsd.py
@@ -18,8 +18,9 @@
 class Freebsd(posix.BasePosix):
     name = "freebsd"
 
-    link_flags = get_env_vector("LDFLAGS", '-pthread')
-    cflags = get_env_vector("CFLAGS", "-O3 -pthread -fomit-frame-pointer")
+    link_flags = ['-pthread'] + get_env_vector('LDFLAGS', '')
+    cflags = ['-O3', '-pthread', '-fomit-frame-pointer'
+             ] + get_env_vector('CFLAGS', '')
     standalone_only = []
     shared_only = []
     so_ext = 'so'
diff --git a/pypy/translator/platform/linux.py b/pypy/translator/platform/linux.py
--- a/pypy/translator/platform/linux.py
+++ b/pypy/translator/platform/linux.py
@@ -1,15 +1,20 @@
 """Support for Linux."""
 
+import os
 import sys
 from pypy.translator.platform.posix import BasePosix
 
 class BaseLinux(BasePosix):
     name = "linux"
     
-    link_flags = ('-pthread',)
+    link_flags = tuple(
+                 ['-pthread',]
+                 + os.environ.get('LDFLAGS', '').split())
     extra_libs = ('-lrt',)
-    cflags = ('-O3', '-pthread', '-fomit-frame-pointer',
-              '-Wall', '-Wno-unused')
+    cflags = tuple(
+             ['-O3', '-pthread', '-fomit-frame-pointer',
+              '-Wall', '-Wno-unused']
+             + os.environ.get('CFLAGS', '').split())
     standalone_only = ()
     shared_only = ('-fPIC',)
     so_ext = 'so'


More information about the pypy-commit mailing list