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

Manuel Jacob noreply at buildbot.pypy.org
Sat Jul 27 03:44:14 CEST 2013


Author: Manuel Jacob
Branch: refactor-str-types
Changeset: r65700:1b8a81ea64cc
Date: 2013-07-26 22:47 +0200
http://bitbucket.org/pypy/pypy/changeset/1b8a81ea64cc/

Log:	hg merge default

diff --git a/lib_pypy/_pypy_irc_topic.py b/lib_pypy/_pypy_irc_topic.py
--- a/lib_pypy/_pypy_irc_topic.py
+++ b/lib_pypy/_pypy_irc_topic.py
@@ -165,6 +165,63 @@
 Nyy rkprcgoybpxf frrz fnar.
 N cvax tyvggrel ebgngvat ynzoqn
 "vg'f yvxryl grzcbenel hagvy sberire" nevtb
+"Lbh xabj jung'f avpr nobhg EClguba?  Ybatre fjbeq svtugf."
+nccneragyl pbashfvba vf n srngher
+nccneragyl pbashfvba vf n srngher... be vf vg?
+ClCl 1.7 eryrnfrq
+vs lbh jnag gb or penml, lbh qba'g unir gb sbepr vg
+vs lbh jnag vg gb or iveghny, lbh fubhyq abg sbepr vg
+<Nyrk_Tnlabe> svwny: V whfg... fgnegrq pbqvat naq fhqqragyl... nobzvangvba
+fabj, fabj! :-)
+fabj, fabj, fabj, fabj
+clcl 1.8 eryrnfrq
+vg jnf srj lnxf gbb yngr
+ClCl vf n enpr orgjrra hf funivat lnxf, naq gur havirefr gelvat gb cebqhpr zber naq zber lnxf
+Jevgvat na SC7 nabalzbhf cebcbfny sbe ClCl vf yvxr znxvat n gi nq sbe n uvtu cresbeznapr fcbegf pne jvgubhg orvat noyr gb zragvba vgf zbqry be znahsnpghere
+Fabj, fabj (ntnva)
+Fgvyy fabjvat
+thrff jung, fabj
+"lbh haqrerfgvzngr gur vzcbegnapr bs zvpebnepuvgrpgher" "ab, vg'f zber gung jr ner fgvyy unccvyl va gur ynaq bs ernpunoyr sehvg"
+Jub nz V?  Naq vs lrf, ubj znal?
+ClCl vf nyjnlf n cynfzn
+"genafyngvba gbbypunva" = "EClgure"?  gb jevgr vagrEClguref va
+"sberire" va clcl grezf zrnaf yvxr srj zbaguf :)
+"Onu.  PClguba bofphevgl. - Nezva Evtb"
+svwny: pna V vavgvngr lbh ba gur (rnfl ohg) aba-gevivny gbcvp bs jevgvat P shapgvba glcrf? :-)
+nyy fbsgjner vzcebirzragf unccra ol n ovg
+gur genprf qba'g yvr
+:-) be engure ":-/" bss-ol-bar-xrl reebe
+Be Nezva Evtb. V guvax ur'f noyr gb haqrefgnaq k86 gur jnl Plcure pna frr jbzra va gur zngevk.
+V zvtug, ohg abobql erfcrpgf zr
+cerohvyg vafgnapr Ryyvcfvf unf ab nggevohgr 'reeab'
+guvf frnfba'f svefg "fabj! fabj!" vf urer
+ClCl 2.0 orgn1 eryrnfrq - orggre yngr guna arire
+Fjvgreynaq 2012: zber fabj va Qrprzore guna rire fvapr clcl fgnegrq
+Fjvgmreynaq 2012: zber fabj va Qrprzore guna rire fvapr clcl fgnegrq
+<nevtngb> n sngny reebe, ol qrsvavgvba, vf sngny
+<nagbphav> V'z tynq gung jr cebtenz va Clguba naq jr qba'g qrny jvgu gubfr vffhrf rirel qnl. Ncneg gur snpg gung jr unir gb qrny jvgu gurz naljnl, vg frrzf
+unccl arj lrne!
+"zrffl" vf abg n whqtrzrag, ohg whfg n snpg bs pbzcyvpngrqarff
+n ybg bs fabj
+qb lbh xabj nobhg n gbnfgre jvgu 8XO bs ENZ naq 64XO bs EBZ?
+vg'f orra fabjvat rirelqnl sbe n juvyr, V pna'g whfg chg "fabj, fabj" hc urer rirel qnl
+fabjonyy svtugf!
+sbejneq pbzcngvovyvgl jvgu bcgvzvmngvbaf gung unira'g orra vairagrq lrg
+jr fgvyy unir gb jevgr fbsgjner jvgu n zrgnfcnpr ohooyr va vg
+cebonoyl gur ynfg gvzr va gur frnfba, ohg: fabj, fabj!
+ClCl 2.0-orgn2 eryrnfrq
+Gur ceboyrz vf gung sbe nyzbfg nal aba-gevivny cebtenz, vg'f abg pyrne jung 'pbeerpg' zrnaf.
+ClCl 2.0 nyzbfg eryrnfrq
+ClCl 2.0 eryrnfrq
+WVG pbzcvyref fubhyq or jevggra ol crbcyr jub npghnyyl unir snvgu va WVG pbzcvyref' novyvgl gb znxrf guvatf tb fpernzvat snfg
+ClCl 2.0.1 eryrnfrq
+arire haqrerfgvzngr gur vzcebonoyr jura lbh qb fbzrguvat ng 2TUm
+ClCl 2.0.2 eryrnfrq
+nyy jr arrq vf n angvir Cebybt znpuvar
+V haqrefgnaq ubj qravnyvfz vf n onq qrohttvat grpuavdhr
+rirel IZ fubhyq pbzr jvgu arheny argjbex genvarq gb erpbtavmr zvpeborapuznexf naq enaqbzyl syhpghngr gurz +/-9000%
+lbh qvq abg nccebnpu clcl sebz gur rnfl raq: fgz, gura wvg. vg'f n ovg gur Abegu snpr
+va ClCl orvat bayl zbqrengryl zntvp vf n tbbq guvat <psobym>
 """
 
 from string import ascii_uppercase, ascii_lowercase
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -91,8 +91,8 @@
      python ../../rpython/bin/rpython --opt=jit targetpypystandalone.py
 
    possibly replacing ``--opt=jit`` with another `optimization level`_
-   of your choice like ``--opt=2`` if you do not want to include the JIT
-   compiler, which makes the Python interpreter much slower.  
+   of your choice.  Typical example: ``--opt=2`` gives a good (but of
+   course slower) Python interpreter without the JIT.
 
 .. _`optimization level`: config/opt.html
 
diff --git a/pypy/doc/release-2.1.0-beta2.rst b/pypy/doc/release-2.1.0-beta2.rst
--- a/pypy/doc/release-2.1.0-beta2.rst
+++ b/pypy/doc/release-2.1.0-beta2.rst
@@ -3,14 +3,20 @@
 ===============
 
 We're pleased to announce the second beta of the upcoming 2.1 release of PyPy.
-This beta does not add any new features to the 2.1 release, but contains several bugfixes listed below.
+This beta adds one new feature to the 2.1 release and contains several bugfixes listed below.
+
+You can download the PyPy 2.1 beta 1 release here:
+
+    http://pypy.org/download.html
 
 Highlights
 ==========
 
+* Support for os.statvfs and os.fstatvfs on unix systems.
+
 * Fixed issue `1533`_: fix an RPython-level OverflowError for space.float_w(w_big_long_number). 
 
-* Fixed issue `1552`_: GreenletExit should inherit from BaseException
+* Fixed issue `1552`_: GreenletExit should inherit from BaseException.
 
 * Fixed issue `1537`_: numpypy __array_interface__
   
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -31,3 +31,18 @@
 more precise information about which functions can be called. Needed for Topaz.
 
 .. branch: ssl_moving_write_buffer
+
+.. branch: pythoninspect-fix
+Make PyPy respect PYTHONINSPECT variable set via os.putenv in the same process
+to start interactive prompt when the script execution finishes. This adds
+new __pypy__.os.real_getenv call that bypasses Python cache and looksup env
+in the underlying OS. Translatorshell now works on PyPy.
+
+.. branch: add-statvfs
+Added os.statvfs and os.fstatvfs
+
+.. branch: statvfs_tests
+Added some addition tests for statvfs.
+
+.. branch: ndarray-subtypes
+Allow subclassing ndarray, i.e. matrix
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -556,8 +556,15 @@
         # or
         #     * PYTHONINSPECT is set and stdin is a tty.
         #
+        try:
+            # we need a version of getenv that bypasses Python caching
+            from __pypy__.os import real_getenv
+        except ImportError:
+            # dont fail on CPython here
+            real_getenv = os.getenv
+
         return (interactive or
-                ((inspect or (readenv and os.getenv('PYTHONINSPECT')))
+                ((inspect or (readenv and real_getenv('PYTHONINSPECT')))
                  and sys.stdin.isatty()))
 
     success = True
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -48,7 +48,7 @@
     pdir = _get_next_path(ext='')
     p = pdir.ensure(dir=1).join('__main__.py')
     p.write(str(py.code.Source(source)))
-    # return relative path for testing purposes 
+    # return relative path for testing purposes
     return py.path.local().bestrelpath(pdir)
 
 demo_script = getscript("""
@@ -706,6 +706,20 @@
         assert 'hello world\n' in data
         assert '42\n' in data
 
+    def test_putenv_fires_interactive_within_process(self):
+        try:
+            import __pypy__
+        except ImportError:
+            py.test.skip("This can be only tested on PyPy with real_getenv")
+
+        # should be noninteractive when piped in
+        data = 'import os\nos.putenv("PYTHONINSPECT", "1")\n'
+        self.run('', senddata=data, expect_prompt=False)
+
+        # should go interactive with -c
+        data = data.replace('\n', ';')
+        self.run("-c '%s'" % data, expect_prompt=True)
+
     def test_option_S_copyright(self):
         data = self.run('-S -i', expect_prompt=True, expect_banner=True)
         assert 'copyright' not in data
@@ -971,7 +985,7 @@
             pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy-c')
             app_main.setup_bootstrap_path(pypy_c)
             newpath = sys.path[:]
-            # we get at least lib_pypy 
+            # we get at least lib_pypy
             # lib-python/X.Y.Z, and maybe more (e.g. plat-linux2)
             assert len(newpath) >= 2
             for p in newpath:
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -50,6 +50,13 @@
     }
 
 
+class OsModule(MixedModule):
+    appleveldefs = {}
+    interpleveldefs = {
+        'real_getenv': 'interp_os.real_getenv'
+    }
+
+
 class Module(MixedModule):
     appleveldefs = {
     }
@@ -82,6 +89,7 @@
         "time": TimeModule,
         "thread": ThreadModule,
         "intop": IntOpModule,
+        "os": OsModule,
     }
 
     def setup_after_space_initialization(self):
diff --git a/pypy/module/__pypy__/interp_os.py b/pypy/module/__pypy__/interp_os.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/interp_os.py
@@ -0,0 +1,9 @@
+import os
+
+from pypy.interpreter.gateway import unwrap_spec
+
+
+ at unwrap_spec(name='str0')
+def real_getenv(space, name):
+    """Get an OS environment value skipping Python cache"""
+    return space.wrap(os.environ.get(name))
diff --git a/pypy/module/__pypy__/test/test_os.py b/pypy/module/__pypy__/test/test_os.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/test/test_os.py
@@ -0,0 +1,16 @@
+class AppTestOs:
+    spaceconfig = dict(usemodules=['__pypy__'])
+
+    def test_real_getenv(self):
+        import __pypy__.os
+        import os
+
+        key = 'UNLIKELY_SET'
+        assert key not in os.environ
+        os.putenv(key, '42')
+        # this one skips Python cache
+        assert __pypy__.os.real_getenv(key) == '42'
+        # this one can only see things set on interpter start (cached)
+        assert os.getenv(key) is None
+        os.unsetenv(key)
+        assert __pypy__.os.real_getenv(key) is None
diff --git a/pypy/module/_cffi_backend/libraryobj.py b/pypy/module/_cffi_backend/libraryobj.py
--- a/pypy/module/_cffi_backend/libraryobj.py
+++ b/pypy/module/_cffi_backend/libraryobj.py
@@ -4,6 +4,7 @@
 from pypy.interpreter.error import operationerrfmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
+from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror
 
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose, DLOpenError
@@ -24,9 +25,7 @@
             try:
                 self.handle = dlopen(ll_libname, flags)
             except DLOpenError, e:
-                raise operationerrfmt(space.w_OSError,
-                                      "cannot load library %s: %s",
-                                      filename, e.msg)
+                raise wrap_dlopenerror(space, e, filename)
         self.name = filename
 
     def __del__(self):
diff --git a/pypy/module/_ffi/interp_funcptr.py b/pypy/module/_ffi/interp_funcptr.py
--- a/pypy/module/_ffi/interp_funcptr.py
+++ b/pypy/module/_ffi/interp_funcptr.py
@@ -14,7 +14,7 @@
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.objectmodel import we_are_translated
 from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
-from pypy.module._rawffi.interp_rawffi import got_libffi_error
+from pypy.module._rawffi.interp_rawffi import got_libffi_error, wrap_dlopenerror
 
 import os
 if os.name == 'nt':
@@ -324,8 +324,7 @@
         try:
             self.cdll = libffi.CDLL(name, mode)
         except DLOpenError, e:
-            raise operationerrfmt(space.w_OSError, '%s: %s', self.name,
-                                  e.msg or 'unspecified error')
+            raise wrap_dlopenerror(space, e, self.name)
 
     def getfunc(self, space, w_name, w_argtypes, w_restype):
         return _getfunc(space, self, w_name, w_argtypes, w_restype)
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -140,6 +140,11 @@
     raise OperationError(space.w_SystemError,
                          space.wrap("not supported by libffi"))
 
+def wrap_dlopenerror(space, e, filename):
+    msg = e.msg if e.msg else 'unspecified error'
+    return operationerrfmt(space.w_OSError, 'Cannot load library %s: %s',
+                           filename, msg)
+
 
 class W_CDLL(W_Root):
     def __init__(self, space, name, cdll):
@@ -219,8 +224,7 @@
     try:
         cdll = CDLL(name)
     except DLOpenError, e:
-        raise operationerrfmt(space.w_OSError, '%s: %s', name,
-                              e.msg or 'unspecified error')
+        raise wrap_dlopenerror(space, e, name)
     except OSError, e:
         raise wrap_oserror(space, e)
     return space.wrap(W_CDLL(space, name, cdll))
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -223,7 +223,8 @@
             _rawffi.CDLL("xxxxx_this_name_does_not_exist_xxxxx")
         except OSError, e:
             print e
-            assert str(e).startswith("xxxxx_this_name_does_not_exist_xxxxx: ")
+            assert str(e).startswith(
+                "Cannot load library xxxxx_this_name_does_not_exist_xxxxx: ")
         else:
             raise AssertionError("did not fail??")
 
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -229,7 +229,7 @@
         except IndexError:
             # not a single result
             chunks = self._prepare_slice_args(space, w_index)
-            return chunks.apply(orig_arr)
+            return chunks.apply(space, orig_arr)
 
     def descr_setitem(self, space, orig_arr, w_index, w_value):
         try:
@@ -238,7 +238,7 @@
         except IndexError:
             w_value = convert_to_array(space, w_value)
             chunks = self._prepare_slice_args(space, w_index)
-            view = chunks.apply(orig_arr)
+            view = chunks.apply(space, orig_arr)
             view.implementation.setslice(space, w_value)
 
     def transpose(self, orig_array):
@@ -269,14 +269,14 @@
                                   shape, skip)
         return iter.MultiDimViewIterator(self, self.dtype, self.start, r[0], r[1], shape)
 
-    def swapaxes(self, orig_arr, axis1, axis2):
+    def swapaxes(self, space, orig_arr, axis1, axis2):
         shape = self.get_shape()[:]
         strides = self.get_strides()[:]
         backstrides = self.get_backstrides()[:]
         shape[axis1], shape[axis2] = shape[axis2], shape[axis1]
         strides[axis1], strides[axis2] = strides[axis2], strides[axis1]
         backstrides[axis1], backstrides[axis2] = backstrides[axis2], backstrides[axis1]
-        return W_NDimArray.new_slice(self.start, strides,
+        return W_NDimArray.new_slice(space, self.start, strides,
                                      backstrides, shape, self, orig_arr)
 
     def get_storage_as_int(self, space):
@@ -289,13 +289,16 @@
         return ArrayBuffer(self)
 
     def astype(self, space, dtype):
-        new_arr = W_NDimArray.from_shape(self.get_shape(), dtype)
+        strides, backstrides = support.calc_strides(self.get_shape(), dtype,
+                                                    self.order)
+        impl = ConcreteArray(self.get_shape(), dtype, self.order,
+                             strides, backstrides)
         if self.dtype.is_str_or_unicode() and not dtype.is_str_or_unicode():
             raise OperationError(space.w_NotImplementedError, space.wrap(
                 "astype(%s) not implemented yet" % self.dtype))
         else:
-            loop.setslice(space, new_arr.get_shape(), new_arr.implementation, self)
-        return new_arr
+            loop.setslice(space, impl.get_shape(), impl, self)
+        return impl
 
 
 class ConcreteArrayNotOwning(BaseConcreteArray):
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -139,7 +139,7 @@
         if not new_shape:
             return self
         if support.product(new_shape) == 1:
-            arr = W_NDimArray.from_shape(new_shape, self.dtype)
+            arr = W_NDimArray.from_shape(space, new_shape, self.dtype)
             arr_iter = arr.create_iter(new_shape)
             arr_iter.setitem(self.value)
             return arr.implementation
@@ -152,7 +152,7 @@
     def create_axis_iter(self, shape, dim, cum):
         raise Exception("axis iter should not happen on scalar")
 
-    def swapaxes(self, orig_array, axis1, axis2):
+    def swapaxes(self, space, orig_array, axis1, axis2):
         raise Exception("should not be called")
 
     def fill(self, w_value):
@@ -166,7 +166,7 @@
         return space.wrap(0)
 
     def astype(self, space, dtype):
-        return W_NDimArray.new_scalar(space, dtype, self.value)
+        raise Exception("should not be called")
 
     def base(self):
         return None
diff --git a/pypy/module/micronumpy/arrayimpl/sort.py b/pypy/module/micronumpy/arrayimpl/sort.py
--- a/pypy/module/micronumpy/arrayimpl/sort.py
+++ b/pypy/module/micronumpy/arrayimpl/sort.py
@@ -126,7 +126,7 @@
             axis = space.int_w(w_axis)
         # create array of indexes
         dtype = interp_dtype.get_dtype_cache(space).w_longdtype
-        index_arr = W_NDimArray.from_shape(arr.get_shape(), dtype)
+        index_arr = W_NDimArray.from_shape(space, arr.get_shape(), dtype)
         storage = index_arr.implementation.get_storage()
         if len(arr.get_shape()) == 1:
             for i in range(arr.get_size()):
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -10,6 +10,15 @@
             space.isinstance_w(w_obj, space.w_list) or
             isinstance(w_obj, W_NDimArray))
 
+def wrap_impl(space, w_cls, w_instance, impl):
+    if w_cls is None or space.is_w(w_cls, space.gettypefor(W_NDimArray)):
+        w_ret = W_NDimArray(impl)
+    else:
+        w_ret = space.allocate_instance(W_NDimArray, w_cls)
+        W_NDimArray.__init__(w_ret, impl)
+        assert isinstance(w_ret, W_NDimArray)
+        space.call_method(w_ret, '__array_finalize__', w_instance)
+    return w_ret
 
 class ArrayArgumentException(Exception):
     pass
@@ -20,10 +29,11 @@
 
     def __init__(self, implementation):
         assert isinstance(implementation, BaseArrayImplementation)
+        assert isinstance(self, W_NDimArray)
         self.implementation = implementation
 
     @staticmethod
-    def from_shape(shape, dtype, order='C'):
+    def from_shape(space, shape, dtype, order='C', w_instance=None):
         from pypy.module.micronumpy.arrayimpl import concrete, scalar
 
         if not shape:
@@ -32,10 +42,12 @@
             strides, backstrides = calc_strides(shape, dtype.base, order)
             impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
                                       backstrides)
+        if w_instance:
+            return wrap_impl(space, space.type(w_instance), w_instance, impl)
         return W_NDimArray(impl)
 
     @staticmethod
-    def from_shape_and_storage(shape, storage, dtype, order='C', owning=False):
+    def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False, w_subtype=None):
         from pypy.module.micronumpy.arrayimpl import concrete
         assert shape
         strides, backstrides = calc_strides(shape, dtype, order)
@@ -46,15 +58,20 @@
         else:
             impl = concrete.ConcreteArrayNotOwning(shape, dtype, order, strides,
                                                 backstrides, storage)
+        if w_subtype:
+            w_ret = space.allocate_instance(W_NDimArray, w_subtype)
+            W_NDimArray.__init__(w_ret, impl)
+            space.call_method(w_ret, '__array_finalize__', w_subtype)
+            return w_ret
         return W_NDimArray(impl)
 
     @staticmethod
-    def new_slice(offset, strides, backstrides, shape, parent, orig_arr, dtype=None):
+    def new_slice(space, offset, strides, backstrides, shape, parent, orig_arr, dtype=None):
         from pypy.module.micronumpy.arrayimpl import concrete
 
         impl = concrete.SliceArray(offset, strides, backstrides, shape, parent,
                                    orig_arr, dtype)
-        return W_NDimArray(impl)
+        return wrap_impl(space, space.type(orig_arr), orig_arr, impl)
 
     @staticmethod
     def new_scalar(space, dtype, w_val=None):
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
@@ -35,10 +35,12 @@
 class BadToken(Exception):
     pass
 
+
 SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
                         "unegative", "flat", "tostring","count_nonzero",
                         "argsort"]
 TWO_ARG_FUNCTIONS = ["dot", 'take']
+TWO_ARG_FUNCTIONS_OR_NONE = ['view']
 THREE_ARG_FUNCTIONS = ['where']
 
 class W_TypeObject(W_Root):
@@ -184,14 +186,23 @@
 
     def is_true(self, w_obj):
         assert isinstance(w_obj, BoolObject)
-        return False
-        #return w_obj.boolval
+        return w_obj.boolval
 
     def is_w(self, w_obj, w_what):
         return w_obj is w_what
 
+    def issubtype(self, w_type1, w_type2):
+        return BoolObject(True)
+
     def type(self, w_obj):
-        return w_obj.tp
+        if self.is_none(w_obj):
+            return self.w_None
+        try:
+            return w_obj.tp
+        except AttributeError:
+            if isinstance(w_obj, W_NDimArray):
+                return W_NDimArray
+            return self.w_None
 
     def gettypefor(self, w_obj):
         return None
@@ -199,6 +210,11 @@
     def call_function(self, tp, w_dtype):
         return w_dtype
 
+    def call_method(self, w_obj, s, *args):
+        # XXX even the hacks have hacks
+        return None
+        #return getattr(w_obj, 'descr_' + s)(self, *args)
+
     @specialize.arg(1)
     def interp_w(self, tp, what):
         assert isinstance(what, tp)
@@ -329,6 +345,8 @@
         self.name = name.strip(" ")
 
     def execute(self, interp):
+        if self.name == 'None':
+            return None
         return interp.variables[self.name]
 
     def __repr__(self):
@@ -451,6 +469,32 @@
     def __repr__(self):
         return 'slice(%s,%s,%s)' % (self.start, self.stop, self.step)
 
+class ArrayClass(Node):
+    def __init__(self):
+        self.v = W_NDimArray
+
+    def execute(self, interp):
+       return self.v
+
+    def __repr__(self):
+        return '<class W_NDimArray>'
+
+class DtypeClass(Node):
+    def __init__(self, dt):
+        self.v = dt
+
+    def execute(self, interp):
+        if self.v == 'int':
+            dtype = get_dtype_cache(interp.space).w_int64dtype
+        elif self.v == 'float':
+            dtype = get_dtype_cache(interp.space).w_float64dtype
+        else:
+            raise BadToken('unknown v to dtype "%s"' % self.v)
+        return dtype
+
+    def __repr__(self):
+        return '<class %s dtype>' % self.v
+
 class Execute(Node):
     def __init__(self, expr):
         self.expr = expr
@@ -533,6 +577,14 @@
                 w_res = where(interp.space, arr, arg1, arg2)
             else:
                 assert False
+        elif self.name in TWO_ARG_FUNCTIONS_OR_NONE:
+            if len(self.args) != 2:
+                raise ArgumentMismatch
+            arg = self.args[1].execute(interp)
+            if self.name == 'view':
+                w_res = arr.descr_view(interp.space, arg)
+            else:
+                assert False
         else:
             raise WrongFunctionName
         if isinstance(w_res, W_NDimArray):
@@ -652,8 +704,14 @@
             if token.name == 'identifier':
                 if tokens.remaining() and tokens.get(0).name == 'paren_left':
                     stack.append(self.parse_function_call(token.v, tokens))
+                elif token.v.strip(' ') == 'ndarray':
+                    stack.append(ArrayClass())
+                elif token.v.strip(' ') == 'int':
+                    stack.append(DtypeClass('int'))
+                elif token.v.strip(' ') == 'float':
+                    stack.append(DtypeClass('float'))
                 else:
-                    stack.append(Variable(token.v))
+                    stack.append(Variable(token.v.strip(' ')))
             elif token.name == 'array_left':
                 stack.append(ArrayConstant(self.parse_array_const(tokens)))
             elif token.name == 'operator':
diff --git a/pypy/module/micronumpy/interp_arrayops.py b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -88,7 +88,7 @@
                                                   y.get_dtype())
     shape = shape_agreement(space, arr.get_shape(), x)
     shape = shape_agreement(space, shape, y)
-    out = W_NDimArray.from_shape(shape, dtype)
+    out = W_NDimArray.from_shape(space, shape, dtype)
     return loop.where(out, shape, arr, x, y, dtype)
 
 def dot(space, w_obj1, w_obj2):
@@ -131,7 +131,8 @@
                                                       arr.get_dtype())
         if _axis < 0 or len(arr.get_shape()) <= _axis:
             raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
-    res = W_NDimArray.from_shape(shape, dtype, 'C')
+    # concatenate does not handle ndarray subtypes, it always returns a ndarray
+    res = W_NDimArray.from_shape(space, shape, dtype, 'C')
     chunks = [Chunk(0, i, 1, i) for i in shape]
     axis_start = 0
     for arr in args_w:
@@ -139,7 +140,7 @@
             continue
         chunks[_axis] = Chunk(axis_start, axis_start + arr.get_shape()[_axis], 1,
                              arr.get_shape()[_axis])
-        Chunks(chunks).apply(res).implementation.setslice(space, arr)
+        Chunks(chunks).apply(space, res).implementation.setslice(space, arr)
         axis_start += arr.get_shape()[_axis]
     return res
 
@@ -150,22 +151,22 @@
         arr = arr.descr_flatten(space)
         orig_size = arr.get_shape()[0]
         shape = [arr.get_shape()[0] * repeats]
-        res = W_NDimArray.from_shape(shape, arr.get_dtype())
+        w_res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), w_instance=arr)
         for i in range(repeats):
             Chunks([Chunk(i, shape[0] - repeats + i, repeats,
-                          orig_size)]).apply(res).implementation.setslice(space, arr)
+                 orig_size)]).apply(space, w_res).implementation.setslice(space, arr)
     else:
         axis = space.int_w(w_axis)
         shape = arr.get_shape()[:]
         chunks = [Chunk(0, i, 1, i) for i in shape]
         orig_size = shape[axis]
         shape[axis] *= repeats
-        res = W_NDimArray.from_shape(shape, arr.get_dtype())
+        w_res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), w_instance=arr)
         for i in range(repeats):
             chunks[axis] = Chunk(i, shape[axis] - repeats + i, repeats,
                                  orig_size)
-            Chunks(chunks).apply(res).implementation.setslice(space, arr)
-    return res
+            Chunks(chunks).apply(space, w_res).implementation.setslice(space, arr)
+    return w_res
 
 def count_nonzero(space, w_obj):
     return space.wrap(loop.count_all_true(convert_to_array(space, w_obj)))
@@ -261,7 +262,7 @@
     else:
         shape = (shape[:axis2] + shape[axis2 + 1:axis1] +
                  shape[axis1 + 1:] + [size])
-    out = W_NDimArray.from_shape(shape, dtype)
+    out = W_NDimArray.from_shape(space, shape, dtype)
     if size == 0:
         return out
     if shapelen == 2:
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
@@ -41,7 +41,7 @@
     dtype = w_arr_list[0].get_dtype()
     for w_arr in w_arr_list[1:]:
         dtype = find_binop_result_dtype(space, dtype, w_arr.get_dtype())
-    out = base.W_NDimArray.from_shape(shape, dtype)
+    out = base.W_NDimArray.from_shape(space, shape, dtype)
     return out
 
 
diff --git a/pypy/module/micronumpy/interp_flatiter.py b/pypy/module/micronumpy/interp_flatiter.py
--- a/pypy/module/micronumpy/interp_flatiter.py
+++ b/pypy/module/micronumpy/interp_flatiter.py
@@ -64,8 +64,8 @@
         base_iter.next_skip_x(start)
         if length == 1:
             return base_iter.getitem()
-        res = W_NDimArray.from_shape([length], base.get_dtype(),
-                                     base.get_order())
+        res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
+                                     base.get_order(), w_instance=base)
         return loop.flatiter_getitem(res, base_iter, step)
 
     def descr_setitem(self, space, w_idx, w_value):
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
@@ -3,7 +3,7 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, make_weakref_descr
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.module.micronumpy.base import W_NDimArray, convert_to_array,\
-     ArrayArgumentException, issequence_w
+     ArrayArgumentException, issequence_w, wrap_impl
 from pypy.module.micronumpy import interp_dtype, interp_ufuncs, interp_boxes,\
      interp_arrayops
 from pypy.module.micronumpy.strides import find_shape_and_elems,\
@@ -85,8 +85,8 @@
             res_shape = [size] + self.get_shape()[1:]
         else:
             res_shape = [size]
-        res = W_NDimArray.from_shape(res_shape, self.get_dtype())
-        return loop.getitem_filter(res, self, arr)
+        w_res = W_NDimArray.from_shape(space, res_shape, self.get_dtype(), w_instance=self)
+        return loop.getitem_filter(w_res, self, arr)
 
     def setitem_filter(self, space, idx, val):
         if len(idx.get_shape()) > 1 and idx.get_shape() != self.get_shape():
@@ -145,12 +145,13 @@
         if iter_shape is None:
             # w_index is a list of slices, return a view
             chunks = self.implementation._prepare_slice_args(space, w_index)
-            return chunks.apply(self)
+            return chunks.apply(space, self)
         shape = res_shape + self.get_shape()[len(indexes):]
-        res = W_NDimArray.from_shape(shape, self.get_dtype(), self.get_order())
-        if not res.get_size():
-            return res
-        return loop.getitem_array_int(space, self, res, iter_shape, indexes,
+        w_res = W_NDimArray.from_shape(space, shape, self.get_dtype(),
+                                     self.get_order(), w_instance=self)
+        if not w_res.get_size():
+            return w_res
+        return loop.getitem_array_int(space, self, w_res, iter_shape, indexes,
                                       prefix)
 
     def setitem_array_int(self, space, w_index, w_value):
@@ -161,7 +162,7 @@
             # w_index is a list of slices
             w_value = convert_to_array(space, w_value)
             chunks = self.implementation._prepare_slice_args(space, w_index)
-            view = chunks.apply(self)
+            view = chunks.apply(space, self)
             view.implementation.setslice(space, w_value)
             return
         loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
@@ -259,14 +260,17 @@
         return self.implementation.get_scalar_value()
 
     def descr_copy(self, space):
-        return W_NDimArray(self.implementation.copy(space))
+        copy = self.implementation.copy(space)
+        w_subtype = space.type(self)
+        return wrap_impl(space, w_subtype, self, copy)
 
     def descr_get_real(self, space):
-        return W_NDimArray(self.implementation.get_real(self))
+        return wrap_impl(space, space.type(self), self,
+                         self.implementation.get_real(self))
 
     def descr_get_imag(self, space):
         ret = self.implementation.get_imag(self)
-        return W_NDimArray(ret)
+        return wrap_impl(space, space.type(self), self, ret)
 
     def descr_set_real(self, space, w_value):
         # copy (broadcast) values into self
@@ -298,7 +302,7 @@
         new_shape = get_shape_from_iterable(space, self.get_size(), w_shape)
         new_impl = self.implementation.reshape(space, self, new_shape)
         if new_impl is not None:
-            return W_NDimArray(new_impl)
+            return wrap_impl(space, space.type(self), self, new_impl)
         # Create copy with contiguous data
         arr = self.descr_copy(space)
         if arr.get_size() > 0:
@@ -326,7 +330,7 @@
         """
         if self.is_scalar():
             return self
-        return self.implementation.swapaxes(self, axis1, axis2)
+        return self.implementation.swapaxes(space, self, axis1, axis2)
 
     def descr_tolist(self, space):
         if len(self.get_shape()) == 0:
@@ -446,17 +450,24 @@
         # we must do that, because we need a working set. otherwise
         # we would modify the array in-place. Use this to our advantage
         # by converting nonnative byte order.
+        if self.is_scalar():
+            return space.wrap(0)
         s = self.get_dtype().name
         if not self.get_dtype().native:
             s = s[1:]
         dtype = interp_dtype.get_dtype_cache(space).dtypes_by_name[s]
         contig = self.implementation.astype(space, dtype)
-        return contig.implementation.argsort(space, w_axis)
+        return contig.argsort(space, w_axis)
 
     def descr_astype(self, space, w_dtype):
         dtype = space.interp_w(interp_dtype.W_Dtype,
           space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
-        return self.implementation.astype(space, dtype)
+        impl = self.implementation
+        if isinstance(impl, scalar.Scalar):
+            return W_NDimArray.new_scalar(space, dtype, impl.value)
+        else:
+            new_impl = impl.astype(space, dtype)
+            return wrap_impl(space, space.type(self), self, new_impl)
 
     def descr_get_base(self, space):
         impl = self.implementation
@@ -471,9 +482,9 @@
             loop.byteswap(self.implementation, self.implementation)
             return self
         else:
-            res = W_NDimArray.from_shape(self.get_shape(), self.get_dtype())
-            loop.byteswap(self.implementation, res.implementation)
-            return res
+            w_res = W_NDimArray.from_shape(space, self.get_shape(), self.get_dtype(), w_instance=self)
+            loop.byteswap(self.implementation, w_res.implementation)
+            return w_res
 
     @unwrap_spec(mode=str)
     def descr_choose(self, space, w_choices, w_out=None, mode='raise'):
@@ -564,7 +575,7 @@
         if space.is_none(w_out):
             if self.get_dtype().is_bool_type():
                 #numpy promotes bool.round() to float16. Go figure.
-                w_out = W_NDimArray.from_shape(self.get_shape(),
+                w_out = W_NDimArray.from_shape(space, self.get_shape(),
                        interp_dtype.get_dtype_cache(space).w_float16dtype)
             else:
                 w_out = None
@@ -578,6 +589,8 @@
         else:
             calc_dtype = out.get_dtype()
 
+        if decimals == 0:
+            out = out.descr_view(space,space.type(self))
         loop.round(space, self, calc_dtype, self.get_shape(), decimals, out)
         return out
 
@@ -619,9 +632,13 @@
             "trace not implemented yet"))
 
     def descr_view(self, space, w_dtype=None, w_type=None) :
-        if w_type is not None:
-            raise OperationError(space.w_NotImplementedError, space.wrap(
-                "view(... type=<class>) not implemented yet"))
+        if not w_type and w_dtype:
+            try:
+                if space.is_true(space.issubtype(w_dtype, space.gettypefor(W_NDimArray))):
+                    w_type = w_dtype
+                    w_dtype = None
+            except (OperationError, TypeError):
+                pass
         if w_dtype:
             dtype = space.interp_w(interp_dtype.W_Dtype,
                 space.call_function(space.gettypefor(interp_dtype.W_Dtype),
@@ -651,8 +668,9 @@
                     raise OperationError(space.w_ValueError, space.wrap(
                         "new type not compatible with array."))
                 new_shape[-1] = new_shape[-1] * old_itemsize / new_itemsize
-        return W_NDimArray(impl.get_view(self, dtype, new_shape))
-
+        v = impl.get_view(self, dtype, new_shape)
+        w_ret = wrap_impl(space, w_type, self, v)
+        return w_ret
 
     # --------------------- operations ----------------------------
 
@@ -760,9 +778,9 @@
             return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
         # Do the dims match?
         out_shape, other_critical_dim = match_dot_shapes(space, self, other)
-        result = W_NDimArray.from_shape(out_shape, dtype)
+        w_res = W_NDimArray.from_shape(space, out_shape, dtype, w_instance=self)
         # This is the place to add fpypy and blas
-        return loop.multidim_dot(space, self, other,  result, dtype,
+        return loop.multidim_dot(space, self, other,  w_res, dtype,
                                  other_critical_dim)
 
     @unwrap_spec(w_axis = WrappedDefault(None))
@@ -884,14 +902,20 @@
         isfortran = space.getitem(w_state, space.wrap(3))
         storage = space.getitem(w_state, space.wrap(4))
 
-        self.implementation = W_NDimArray.from_shape_and_storage([space.int_w(i) for i in space.listview(shape)], rffi.str2charp(space.str_w(storage), track_allocation=False), dtype, owning=True).implementation
+        self.implementation = W_NDimArray.from_shape_and_storage(space,
+                [space.int_w(i) for i in space.listview(shape)],
+                rffi.str2charp(space.str_w(storage), track_allocation=False),
+                dtype, owning=True).implementation
 
+    def descr___array_finalize__(self, space, w_obj):
+        pass
 
- at unwrap_spec(offset=int)
+ at unwrap_spec(offset=int, order=str)
 def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None,
-                    offset=0, w_strides=None, w_order=None):
+                    offset=0, w_strides=None, order='C'):
+    from pypy.module.micronumpy.arrayimpl.concrete import ConcreteArray
+    from pypy.module.micronumpy.support import calc_strides
     if (offset != 0 or not space.is_none(w_strides) or
-        not space.is_none(w_order) or
         not space.is_none(w_buffer)):
         raise OperationError(space.w_NotImplementedError,
                              space.wrap("unsupported param"))
@@ -900,10 +924,19 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype)
-    return W_NDimArray.from_shape(shape, dtype)
+    if space.is_w(w_subtype, space.gettypefor(W_NDimArray)):
+        return W_NDimArray.from_shape(space, shape, dtype, order)
+    strides, backstrides = calc_strides(shape, dtype.base, order)
+    impl = ConcreteArray(shape, dtype.base, order, strides,
+                                  backstrides)
+    w_ret = space.allocate_instance(W_NDimArray, w_subtype)
+    W_NDimArray.__init__(w_ret, impl)
+    space.call_function(space.getattr(w_ret,
+                        space.wrap('__array_finalize__')), w_subtype)
+    return w_ret
 
 @unwrap_spec(addr=int)
-def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype):
+def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, w_subtype=None):
     """
     Create an array from an existing buffer, given its address as int.
     PyPy-only implementation detail.
@@ -912,9 +945,17 @@
     from rpython.rlib.rawstorage import RAW_STORAGE_PTR
     storage = rffi.cast(RAW_STORAGE_PTR, addr)
     dtype = space.interp_w(interp_dtype.W_Dtype,
-                           space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
+                     space.call_function(space.gettypefor(interp_dtype.W_Dtype),
+                             w_dtype))
     shape = _find_shape(space, w_shape, dtype)
-    return W_NDimArray.from_shape_and_storage(shape, storage, dtype)
+    if w_subtype:
+        if not space.isinstance_w(w_subtype, space.w_type):
+            raise OperationError(space.w_ValueError, space.wrap(
+                "subtype must be a subtype of ndarray, not a class instance"))
+        return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
+                             'C', False, w_subtype)
+    else:
+        return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype)
 
 W_NDimArray.typedef = TypeDef(
     "ndarray",
@@ -1042,6 +1083,7 @@
                                    W_NDimArray.fdel___pypy_data__),
     __reduce__ = interp2app(W_NDimArray.descr_reduce),
     __setstate__ = interp2app(W_NDimArray.descr_setstate),
+    __array_finalize__ = interp2app(W_NDimArray.descr___array_finalize__),
 )
 
 @unwrap_spec(ndmin=int, copy=bool, subok=bool)
@@ -1094,12 +1136,12 @@
         dtype = interp_dtype.variable_dtype(space, dtype.char + '1')
     if ndmin > len(shape):
         shape = [1] * (ndmin - len(shape)) + shape
-    arr = W_NDimArray.from_shape(shape, dtype, order=order)
-    arr_iter = arr.create_iter()
+    w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
+    arr_iter = w_arr.create_iter()
     for w_elem in elems_w:
         arr_iter.setitem(dtype.coerce(space, w_elem))
         arr_iter.next()
-    return arr
+    return w_arr
 
 @unwrap_spec(order=str)
 def zeros(space, w_shape, w_dtype=None, order='C'):
@@ -1109,7 +1151,7 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
-    return space.wrap(W_NDimArray.from_shape(shape, dtype=dtype, order=order))
+    return space.wrap(W_NDimArray.from_shape(space, shape, dtype=dtype, order=order))
 
 @unwrap_spec(order=str)
 def ones(space, w_shape, w_dtype=None, order='C'):
@@ -1119,10 +1161,10 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
-    arr = W_NDimArray.from_shape(shape, dtype=dtype, order=order)
+    w_arr = W_NDimArray.from_shape(space, shape, dtype=dtype, order=order)
     one = dtype.box(1)
-    arr.fill(one)
-    return space.wrap(arr)
+    w_arr.fill(one)
+    return space.wrap(w_arr)
 
 def _reconstruct(space, w_subtype, w_shape, w_dtype):
     return descr_new_array(space, w_subtype, w_shape, w_dtype)
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -50,7 +50,7 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "string is smaller than requested size"))
 
-    a = W_NDimArray.from_shape([num_items], dtype=dtype)
+    a = W_NDimArray.from_shape(space, [num_items], dtype=dtype)
     ai = a.create_iter()
     for val in items:
         ai.setitem(val)
@@ -71,7 +71,7 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "string is smaller than requested size"))
 
-    a = W_NDimArray.from_shape([count], dtype=dtype)
+    a = W_NDimArray.from_shape(space, [count], dtype=dtype)
     loop.fromstring_loop(a, dtype, itemsize, s)
     return space.wrap(a)
 
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
@@ -181,7 +181,8 @@
                 temp_shape = obj_shape[:axis] + obj_shape[axis + 1:]
                 if out:
                     dtype = out.get_dtype()
-                temp = W_NDimArray.from_shape(temp_shape, dtype)
+                temp = W_NDimArray.from_shape(space, temp_shape, dtype,
+                                                w_instance=obj)
             elif keepdims:
                 shape = obj_shape[:axis] + [1] + obj_shape[axis + 1:]
             else:
@@ -207,7 +208,7 @@
                         )
                 dtype = out.get_dtype()
             else:
-                out = W_NDimArray.from_shape(shape, dtype)
+                out = W_NDimArray.from_shape(space, shape, dtype, w_instance=obj)
             return loop.do_axis_reduce(shape, self.func, obj, dtype, axis, out,
                                        self.identity, cumultative, temp)
         if cumultative:
@@ -216,7 +217,7 @@
                     raise OperationError(space.w_ValueError, space.wrap(
                         "out of incompatible size"))
             else:
-                out = W_NDimArray.from_shape([obj.get_size()], dtype)
+                out = W_NDimArray.from_shape(space, [obj.get_size()], dtype, w_instance=obj)
             loop.compute_reduce_cumultative(obj, out, dtype, self.func,
                                             self.identity)
             return out
@@ -295,7 +296,7 @@
             return out
         shape = shape_agreement(space, w_obj.get_shape(), out,
                                 broadcast_down=False)
-        return loop.call1(shape, self.func, calc_dtype, res_dtype,
+        return loop.call1(space, shape, self.func, calc_dtype, res_dtype,
                           w_obj, out)
 
 
@@ -370,7 +371,7 @@
             return out
         new_shape = shape_agreement(space, w_lhs.get_shape(), w_rhs)
         new_shape = shape_agreement(space, new_shape, out, broadcast_down=False)
-        return loop.call2(new_shape, self.func, calc_dtype,
+        return loop.call2(space, new_shape, self.func, calc_dtype,
                           res_dtype, w_lhs, w_rhs, out)
 
 
@@ -450,7 +451,7 @@
                 return dt2
             return dt1
         return dt2
-    else:    
+    else:
         # increase to the next signed type
         dtypenum = dt2.num + 1
     newdtype = interp_dtype.get_dtype_cache(space).dtypes_by_num[dtypenum]
@@ -537,7 +538,13 @@
         return current_guess
     if current_guess is complex_type:
         return complex_type
-    return interp_dtype.get_dtype_cache(space).w_float64dtype
+    if space.isinstance_w(w_obj, space.w_float):
+        return float_type
+    elif space.isinstance_w(w_obj, space.w_slice):
+        return long_dtype
+    raise operationerrfmt(space.w_NotImplementedError,
+        'unable to create dtype from objects, ' '"%T" instance not supported',
+        w_obj)
 
 
 def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func,
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -58,11 +58,11 @@
     def __init__(self, name):
         self.name = name
 
-    def apply(self, orig_arr):
+    def apply(self, space, orig_arr):
         arr = orig_arr.implementation
         ofs, subdtype = arr.dtype.fields[self.name]
         # strides backstrides are identical, ofs only changes start
-        return W_NDimArray.new_slice(arr.start + ofs, arr.get_strides(),
+        return W_NDimArray.new_slice(space, arr.start + ofs, arr.get_strides(),
                                      arr.get_backstrides(),
                                      arr.shape, arr, orig_arr, subdtype)
 
@@ -81,13 +81,13 @@
         assert s >= 0
         return shape[:] + old_shape[s:]
 
-    def apply(self, orig_arr):
+    def apply(self, space, orig_arr):
         arr = orig_arr.implementation
         shape = self.extend_shape(arr.shape)
         r = calculate_slice_strides(arr.shape, arr.start, arr.get_strides(),
                                     arr.get_backstrides(), self.l)
         _, start, strides, backstrides = r
-        return W_NDimArray.new_slice(start, strides[:], backstrides[:],
+        return W_NDimArray.new_slice(space, start, strides[:], backstrides[:],
                                      shape[:], arr, orig_arr)
 
 
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -19,9 +19,34 @@
                              reds = ['shape', 'w_lhs', 'w_rhs', 'out',
                                      'left_iter', 'right_iter', 'out_iter'])
 
-def call2(shape, func, calc_dtype, res_dtype, w_lhs, w_rhs, out):
+def call2(space, shape, func, calc_dtype, res_dtype, w_lhs, w_rhs, out):
+    # handle array_priority
+    # w_lhs and w_rhs could be of different ndarray subtypes. Numpy does:
+    # 1. if __array_priorities__ are equal and one is an ndarray and the
+    #        other is a subtype,  flip the order
+    # 2. elif rhs.__array_priority__ is higher, flip the order
+    # Now return the subtype of the first one
+
+    w_ndarray = space.gettypefor(W_NDimArray)
+    lhs_type = space.type(w_lhs)
+    rhs_type = space.type(w_rhs)
+    lhs_for_subtype = w_lhs
+    rhs_for_subtype = w_rhs
+    #it may be something like a FlatIter, which is not an ndarray
+    if not space.is_true(space.issubtype(lhs_type, w_ndarray)):
+        lhs_type = space.type(w_lhs.base)
+        lhs_for_subtype = w_lhs.base
+    if not space.is_true(space.issubtype(rhs_type, w_ndarray)):
+        rhs_type = space.type(w_rhs.base)
+        rhs_for_subtype = w_rhs.base
+    if space.is_w(lhs_type, w_ndarray) and not space.is_w(rhs_type, w_ndarray):
+        lhs_for_subtype = rhs_for_subtype
+
+    # TODO handle __array_priorities__ and maybe flip the order
+
     if out is None:
-        out = W_NDimArray.from_shape(shape, res_dtype)
+        out = W_NDimArray.from_shape(space, shape, res_dtype,
+                                     w_instance=lhs_for_subtype)
     left_iter = w_lhs.create_iter(shape)
     right_iter = w_rhs.create_iter(shape)
     out_iter = out.create_iter(shape)
@@ -48,9 +73,9 @@
                              reds = ['shape', 'w_obj', 'out', 'obj_iter',
                                      'out_iter'])
 
-def call1(shape, func, calc_dtype, res_dtype, w_obj, out):
+def call1(space, shape, func, calc_dtype, res_dtype, w_obj, out):
     if out is None:
-        out = W_NDimArray.from_shape(shape, res_dtype)
+        out = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
     obj_iter = w_obj.create_iter(shape)
     out_iter = out.create_iter(shape)
     shapelen = len(shape)
@@ -437,12 +462,12 @@
 def tostring(space, arr):
     builder = StringBuilder()
     iter = arr.create_iter()
-    res_str = W_NDimArray.from_shape([1], arr.get_dtype(), order='C')
+    w_res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype(), order='C')
     itemsize = arr.get_dtype().itemtype.get_element_size()
     res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
-                               res_str.implementation.get_storage_as_int(space))
+                               w_res_str.implementation.get_storage_as_int(space))
     while not iter.done():
-        res_str.implementation.setitem(0, iter.getitem())
+        w_res_str.implementation.setitem(0, iter.getitem())
         for i in range(itemsize):
             builder.append(res_str_casted[i])
         iter.next()
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
@@ -2,7 +2,7 @@
 import py
 from pypy.module.micronumpy.compile import (numpy_compile, Assignment,
     ArrayConstant, FloatConstant, Operator, Variable, RangeConstant, Execute,
-    FunctionCall, FakeSpace)
+    FunctionCall, FakeSpace, W_NDimArray)
 
 
 class TestCompiler(object):
@@ -84,6 +84,7 @@
         assert interp.code.statements[0] == Assignment(
             'a', Operator(Variable('b'), "+", FloatConstant(3)))
 
+
 class TestRunner(object):
     def run(self, code):
         interp = numpy_compile(code)
@@ -290,4 +291,32 @@
         ''')
         assert interp.results[0].real == 0
         assert interp.results[0].imag == 1
-        
+
+    def test_view_none(self):
+        interp = self.run('''
+        a = [1, 0, 3, 0]
+        b = None
+        c = view(a, b)
+        c -> 0
+        ''')
+        assert interp.results[0].value == 1
+
+    def test_view_ndarray(self):
+        interp = self.run('''
+        a = [1, 0, 3, 0]
+        b = ndarray
+        c = view(a, b)
+        c
+        ''')
+        results = interp.results[0]
+        assert isinstance(results, W_NDimArray)
+
+    def test_view_dtype(self):
+        interp = self.run('''
+        a = [1, 0, 3, 0]
+        b = int
+        c = view(a, b)
+        c
+        ''')
+        results = interp.results[0]
+        assert isinstance(results, W_NDimArray)
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
@@ -976,3 +976,16 @@
         assert a[0] == 1
         assert (a + a)[1] == 4
 
+class AppTestObjectDtypes(BaseNumpyAppTest):
+    def test_scalar_from_object(self):
+        from numpypy import array
+        class Polynomial(object):
+            pass
+        try:
+            a = array(Polynomial())
+            assert a.shape == ()
+        except NotImplementedError, e:
+            if e.message.find('unable to create dtype from objects')>=0:
+                skip('creating ojbect dtype not supported yet')
+
+
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
@@ -24,8 +24,8 @@
     def get_size(self):
         return 1
 
-def create_slice(a, chunks):
-    return Chunks(chunks).apply(W_NDimArray(a)).implementation
+def create_slice(space, a, chunks):
+    return Chunks(chunks).apply(space, W_NDimArray(a)).implementation
 
 
 def create_array(*args, **kwargs):
@@ -46,100 +46,100 @@
         return self.space.newtuple(args_w)
 
     def test_strides_f(self):
-        a = create_array([10, 5, 3], MockDtype(), order='F')
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
         assert a.strides == [1, 10, 50]
         assert a.backstrides == [9, 40, 100]
 
     def test_strides_c(self):
-        a = create_array([10, 5, 3], MockDtype(), order='C')
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
         assert a.strides == [15, 3, 1]
         assert a.backstrides == [135, 12, 2]
-        a = create_array([1, 0, 7], MockDtype(), order='C')
+        a = create_array(self.space, [1, 0, 7], MockDtype(), order='C')
         assert a.strides == [7, 7, 1]
         assert a.backstrides == [0, 0, 6]
 
     def test_create_slice_f(self):
-        a = create_array([10, 5, 3], MockDtype(), order='F')
-        s = create_slice(a, [Chunk(3, 0, 0, 1)])
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+        s = create_slice(self.space, a, [Chunk(3, 0, 0, 1)])
         assert s.start == 3
         assert s.strides == [10, 50]
         assert s.backstrides == [40, 100]
-        s = create_slice(a, [Chunk(1, 9, 2, 4)])
+        s = create_slice(self.space, a, [Chunk(1, 9, 2, 4)])
         assert s.start == 1
         assert s.strides == [2, 10, 50]
         assert s.backstrides == [6, 40, 100]
-        s = create_slice(a, [Chunk(1, 5, 3, 2), Chunk(1, 2, 1, 1), Chunk(1, 0, 0, 1)])
+        s = create_slice(self.space, a, [Chunk(1, 5, 3, 2), Chunk(1, 2, 1, 1), Chunk(1, 0, 0, 1)])
         assert s.shape == [2, 1]
         assert s.strides == [3, 10]
         assert s.backstrides == [3, 0]
-        s = create_slice(a, [Chunk(0, 10, 1, 10), Chunk(2, 0, 0, 1)])
+        s = create_slice(self.space, a, [Chunk(0, 10, 1, 10), Chunk(2, 0, 0, 1)])
         assert s.start == 20
         assert s.shape == [10, 3]
 
     def test_create_slice_c(self):
-        a = create_array([10, 5, 3], MockDtype(), order='C')
-        s = create_slice(a, [Chunk(3, 0, 0, 1)])
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+        s = create_slice(self.space, a, [Chunk(3, 0, 0, 1)])
         assert s.start == 45
         assert s.strides == [3, 1]
         assert s.backstrides == [12, 2]
-        s = create_slice(a, [Chunk(1, 9, 2, 4)])
+        s = create_slice(self.space, a, [Chunk(1, 9, 2, 4)])
         assert s.start == 15
         assert s.strides == [30, 3, 1]
         assert s.backstrides == [90, 12, 2]
-        s = create_slice(a, [Chunk(1, 5, 3, 2), Chunk(1, 2, 1, 1),
+        s = create_slice(self.space, a, [Chunk(1, 5, 3, 2), Chunk(1, 2, 1, 1),
                             Chunk(1, 0, 0, 1)])
         assert s.start == 19
         assert s.shape == [2, 1]
         assert s.strides == [45, 3]
         assert s.backstrides == [45, 0]
-        s = create_slice(a, [Chunk(0, 10, 1, 10), Chunk(2, 0, 0, 1)])
+        s = create_slice(self.space, a, [Chunk(0, 10, 1, 10), Chunk(2, 0, 0, 1)])
         assert s.start == 6
         assert s.shape == [10, 3]
 
     def test_slice_of_slice_f(self):
-        a = create_array([10, 5, 3], MockDtype(), order='F')
-        s = create_slice(a, [Chunk(5, 0, 0, 1)])
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+        s = create_slice(self.space, a, [Chunk(5, 0, 0, 1)])
         assert s.start == 5
-        s2 = create_slice(s, [Chunk(3, 0, 0, 1)])
+        s2 = create_slice(self.space, s, [Chunk(3, 0, 0, 1)])
         assert s2.shape == [3]
         assert s2.strides == [50]
         assert s2.parent is a
         assert s2.backstrides == [100]
         assert s2.start == 35
-        s = create_slice(a, [Chunk(1, 5, 3, 2)])
-        s2 = create_slice(s, [Chunk(0, 2, 1, 2), Chunk(2, 0, 0, 1)])
+        s = create_slice(self.space, a, [Chunk(1, 5, 3, 2)])
+        s2 = create_slice(self.space, s, [Chunk(0, 2, 1, 2), Chunk(2, 0, 0, 1)])
         assert s2.shape == [2, 3]
         assert s2.strides == [3, 50]
         assert s2.backstrides == [3, 100]
         assert s2.start == 1 * 15 + 2 * 3
 
     def test_slice_of_slice_c(self):
-        a = create_array([10, 5, 3], MockDtype(), order='C')
-        s = create_slice(a, [Chunk(5, 0, 0, 1)])
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+        s = create_slice(self.space, a, [Chunk(5, 0, 0, 1)])
         assert s.start == 15 * 5
-        s2 = create_slice(s, [Chunk(3, 0, 0, 1)])
+        s2 = create_slice(self.space, s, [Chunk(3, 0, 0, 1)])
         assert s2.shape == [3]
         assert s2.strides == [1]
         assert s2.parent is a
         assert s2.backstrides == [2]
         assert s2.start == 5 * 15 + 3 * 3
-        s = create_slice(a, [Chunk(1, 5, 3, 2)])
-        s2 = create_slice(s, [Chunk(0, 2, 1, 2), Chunk(2, 0, 0, 1)])
+        s = create_slice(self.space, a, [Chunk(1, 5, 3, 2)])
+        s2 = create_slice(self.space, s, [Chunk(0, 2, 1, 2), Chunk(2, 0, 0, 1)])
         assert s2.shape == [2, 3]
         assert s2.strides == [45, 1]
         assert s2.backstrides == [45, 2]
         assert s2.start == 1 * 15 + 2 * 3
 
     def test_negative_step_f(self):
-        a = create_array([10, 5, 3], MockDtype(), order='F')
-        s = create_slice(a, [Chunk(9, -1, -2, 5)])
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+        s = create_slice(self.space, a, [Chunk(9, -1, -2, 5)])
         assert s.start == 9
         assert s.strides == [-2, 10, 50]
         assert s.backstrides == [-8, 40, 100]
 
     def test_negative_step_c(self):
-        a = create_array([10, 5, 3], MockDtype(), order='C')
-        s = create_slice(a, [Chunk(9, -1, -2, 5)])
+        a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+        s = create_slice(self.space, a, [Chunk(9, -1, -2, 5)])
         assert s.start == 135
         assert s.strides == [-30, 3, 1]
         assert s.backstrides == [-120, 12, 2]
@@ -207,7 +207,8 @@
             raw_storage_setitem(storage, i, rffi.cast(rffi.UCHAR, i))
         #
         dtypes = get_dtype_cache(self.space)
-        w_array = W_NDimArray.from_shape_and_storage([2, 2], storage, dtypes.w_int8dtype)
+        w_array = W_NDimArray.from_shape_and_storage(self.space, [2, 2],
+                                                storage, dtypes.w_int8dtype)
         def get(i, j):
             return w_array.getitem(self.space, [i, j]).value
         assert get(0, 0) == 0
@@ -1442,7 +1443,7 @@
         assert x.view('int8').shape == (10, 3)
 
     def test_ndarray_view_empty(self):
-        from numpypy import array, int8, int16, dtype
+        from numpypy import array, int8, int16
         x = array([], dtype=[('a', int8), ('b', int8)])
         y = x.view(dtype=int16)
 
@@ -2876,6 +2877,12 @@
         assert y[0, 1] == 2
         y[0, 1] = 42
         assert x[1] == 42
+        class C(ndarray):
+            pass
+        z = ndarray._from_shape_and_storage([4, 1], addr, x.dtype, C)
+        assert isinstance(z, C)
+        assert z.shape == (4, 1)
+        assert z[1, 0] == 42
 
     def test___pypy_data__(self):
         from numpypy import array
@@ -2890,7 +2897,7 @@
 class AppTestLongDoubleDtypes(BaseNumpyAppTest):
     def setup_class(cls):
         from pypy.module.micronumpy import Module
-        print dir(Module.interpleveldefs)
+        #print dir(Module.interpleveldefs)
         if not Module.interpleveldefs.get('longfloat', None):
             py.test.skip('no longdouble types yet')
         BaseNumpyAppTest.setup_class.im_func(cls)
diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -0,0 +1,223 @@
+import py
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestSupport(BaseNumpyAppTest):
+    def setup_class(cls):
+        BaseNumpyAppTest.setup_class.im_func(cls)
+        cls.w_NoNew = cls.space.appexec([], '''():
+            from numpypy import ndarray
+            class NoNew(ndarray):
+                def __new__(cls, subtype):
+                    raise ValueError('should not call __new__')
+                def __array_finalize__(self, obj):
+
+                    self.called_finalize = True
+            return NoNew ''')
+        cls.w_SubType = cls.space.appexec([], '''():
+            from numpypy import ndarray, asarray
+            class SubType(ndarray):
+                def __new__(obj, input_array):
+                    obj = asarray(input_array).view(obj)
+                    obj.called_new = True
+                    return obj
+                def __array_finalize__(self, obj):
+                    self.called_finalize = True
+            return SubType ''')
+
+    def test_subtype_base(self):
+        from numpypy import ndarray, dtype
+        class C(ndarray):
+            def __new__(subtype, shape, dtype):
+                self = ndarray.__new__(subtype, shape, dtype)
+                self.id = 'subtype'
+                return self
+        a = C([2, 2], int)
+        assert isinstance(a, C)
+        assert isinstance(a, ndarray)
+        assert a.shape == (2, 2)
+        assert a.dtype is dtype(int)
+        assert a.id == 'subtype'
+        a = a.reshape(1, 4)
+        b = a.reshape(4, 1)
+        assert isinstance(b, C)
+        #make sure __new__ was not called
+        assert not getattr(b, 'id', None)
+        a.fill(3)
+        b = a[0]
+        assert isinstance(b, C)
+        assert (b == 3).all()
+        b[0]=100
+        assert a[0,0] == 100
+
+    def test_subtype_view(self):
+        from numpypy import ndarray, array
+        class matrix(ndarray):
+            def __new__(subtype, data, dtype=None, copy=True):
+                if isinstance(data, matrix):
+                    return data
+                return data.view(subtype)
+        a = array(range(5))
+        b = matrix(a)
+        assert isinstance(b, matrix)
+        assert (b == a).all()
+
+
+    def test_finalize(self):
+        #taken from http://docs.scipy.org/doc/numpy/user/basics.subclassing.html#simple-example-adding-an-extra-attribute-to-ndarray
+        import numpypy as np
+        class InfoArray(np.ndarray):
+            def __new__(subtype, shape, dtype=float, buffer=None, offset=0,
+                          strides=None, order='C', info=None):
+                obj = np.ndarray.__new__(subtype, shape, dtype, buffer,
+                         offset, strides, order)
+                obj.info = info
+                return obj
+
+            def __array_finalize__(self, obj):
+                if obj is None:
+                    print 'finalize with None'
+                    return
+                # printing the object itself will crash the test
+                print 'finalize with something',type(obj)
+                self.info = getattr(obj, 'info', None)
+        obj = InfoArray(shape=(3,))
+        assert isinstance(obj, InfoArray)
+        assert obj.info is None
+        obj = InfoArray(shape=(3,), info='information')
+        assert obj.info == 'information'
+        v = obj[1:]
+        assert isinstance(v, InfoArray)
+        assert v.base is obj
+        assert v.info == 'information'
+        arr = np.arange(10)
+        cast_arr = arr.view(InfoArray)
+        assert isinstance(cast_arr, InfoArray)
+        assert cast_arr.base is arr
+        assert cast_arr.info is None
+
+    def test_sub_where(self):
+        from numpypy import where, ones, zeros, array
+        a = array([1, 2, 3, 0, -3])
+        v = a.view(self.NoNew)
+        b = where(array(v) > 0, ones(5), zeros(5))
+        assert (b == [1, 1, 1, 0, 0]).all()
+        # where returns an ndarray irregardless of the subtype of v
+        assert not isinstance(b, self.NoNew)
+
+    def test_sub_repeat(self):
+        from numpypy import repeat, array
+        a = self.SubType(array([[1, 2], [3, 4]]))
+        b =  repeat(a, 3)
+        assert (b == [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]).all()
+        assert isinstance(b, self.SubType)
+
+    def test_sub_flatiter(self):
+        from numpypy import array
+        a = array(range(9)).reshape(3, 3).view(self.NoNew)
+        c = array(range(9)).reshape(3, 3)
+        assert isinstance(a.flat[:] + a.flat[:], self.NoNew)
+        assert isinstance(a.flat[:] + c.flat[:], self.NoNew)
+        assert isinstance(c.flat[:] + a.flat[:], self.NoNew)
+        assert not isinstance(c.flat[:] + c.flat[:], self.NoNew)
+
+    def test_sub_getitem_filter(self):
+        from numpypy import array
+        a = array(range(5))
+        b = self.SubType(a)
+        c = b[array([False, True, False, True, False])]
+        assert c.shape == (2,)
+        assert (c == [1, 3]).all()
+        assert isinstance(c, self.SubType)
+        assert b.called_new
+        assert not getattr(c, 'called_new', False)
+        assert c.called_finalize
+
+    def test_sub_getitem_array_int(self):
+        from numpypy import array
+        a = array(range(5))
+        b = self.SubType(a)
+        assert b.called_new
+        c = b[array([3, 2, 1, 4])]
+        assert (c == [3, 2, 1, 4]).all()
+        assert isinstance(c, self.SubType)
+        assert not getattr(c, 'called_new', False)
+        assert c.called_finalize
+
+    def test_sub_round(self):
+        from numpypy import array
+        a = array(range(10), dtype=float).view(self.NoNew)
+        # numpy compatibility
+        b = a.round(decimals=0)
+        assert isinstance(b, self.NoNew)
+        b = a.round(decimals=1)
+        assert not isinstance(b, self.NoNew)
+        b = a.round(decimals=-1)
+        assert not isinstance(b, self.NoNew)
+
+    def test_sub_dot(self):
+        # the returned type is that of the first argument
+        from numpypy import array
+        a = array(range(12)).reshape(3,4)
+        b = self.SubType(a)
+        c = array(range(12)).reshape(4,3).view(self.SubType)
+        d = c.dot(a)
+        assert isinstance(d, self.SubType)
+        assert not getattr(d, 'called_new', False)
+        assert d.called_finalize
+        d = a.dot(c)
+        assert not isinstance(d, self.SubType)
+        assert not getattr(d, 'called_new', False)
+        assert not getattr(d, 'called_finalize', False)
+
+    def test_sub_reduce(self):
+        # i.e. sum, max
+        # test for out as well
+        from numpypy import array
+        a = array(range(12)).reshape(3,4)
+        b = self.SubType(a)
+        c = b.sum(axis=0)
+        assert (c == [12, 15, 18, 21]).all()
+        assert isinstance(c, self.SubType)
+        assert not getattr(c, 'called_new', False)
+        assert c.called_finalize
+        d = array(range(4))
+        c = b.sum(axis=0, out=d)
+        assert c is d
+        assert not isinstance(c, self.SubType)
+        d = array(range(4)).view(self.NoNew)
+        c = b.sum(axis=0, out=d)
+        assert c is d
+        assert isinstance(c, self.NoNew)
+
+    def test_sub_call2(self):
+        # c + a vs. a + c, what about array priority?
+        from numpypy import array
+        a = array(range(12)).view(self.NoNew)
+        b = self.SubType(range(12))
+        c = b + a
+        assert isinstance(c, self.SubType)
+        c = a + b
+        assert isinstance(c, self.NoNew)
+        d = range(12)
+        e = a - d
+        assert isinstance(e, self.NoNew)
+
+    def test_sub_call1(self):
+        from numpypy import array, sqrt
+        a = array(range(12)).view(self.NoNew)
+        b = sqrt(a)
+        assert b.called_finalize == True
+
+    def test_sub_astype(self):
+        from numpypy import array
+        a = array(range(12)).view(self.NoNew)
+        b = a.astype(float)
+        assert b.called_finalize == True
+
+    def test_sub_reshape(self):
+        from numpypy import array
+        a = array(range(12)).view(self.NoNew)
+        b = a.reshape(3, 4)
+        assert b.called_finalize == True
+
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
@@ -184,14 +184,15 @@
                     assert isinstance(e, WindowsError)
                     assert e.winerror == 3
 
-    def test_statvfs(self):
-        st = self.posix.statvfs(".")
-        assert isinstance(st, self.posix.statvfs_result)
-        for field in [
-            'f_bsize', 'f_frsize', 'f_blocks', 'f_bfree', 'f_bavail',
-            'f_files', 'f_ffree', 'f_favail', 'f_flag', 'f_namemax',
-        ]:
-            assert hasattr(st, field)
+    if hasattr(__import__(os.name), "statvfs"):
+        def test_statvfs(self):
+            st = self.posix.statvfs(".")
+            assert isinstance(st, self.posix.statvfs_result)
+            for field in [
+                'f_bsize', 'f_frsize', 'f_blocks', 'f_bfree', 'f_bavail',
+                'f_files', 'f_ffree', 'f_favail', 'f_flag', 'f_namemax',
+            ]:
+                assert hasattr(st, field)
 
     def test_pickle(self):
         import pickle, os
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -125,12 +125,10 @@
         self.llbox = llbox
 
     def descr_getint(self, space):
-        try:
-            value = jit_hooks.box_getint(self.llbox)
-        except NotImplementedError:
+        if not jit_hooks.box_isint(self.llbox):
             raise OperationError(space.w_NotImplementedError,
                                  space.wrap("Box has no int value"))
-        return space.wrap(value)
+        return space.wrap(jit_hooks.box_getint(self.llbox))
 
 @unwrap_spec(no=int)
 def descr_new_box(space, w_tp, no):
diff --git a/rpython/jit/tool/test/f.pypylog.bz2 b/rpython/jit/tool/test/f.pypylog.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..a982e459b1daa33547576733ccc0b560f99a3f79
GIT binary patch

[cut]

diff --git a/rpython/jit/tool/test/test_traceviewer.py b/rpython/jit/tool/test/test_traceviewer.py
--- a/rpython/jit/tool/test/test_traceviewer.py
+++ b/rpython/jit/tool/test/test_traceviewer.py
@@ -1,7 +1,7 @@
 import math
 import py
 from rpython.jit.tool.traceviewer import splitloops, FinalBlock, Block,\
-     split_one_loop, postprocess, main, get_gradient_color
+     split_one_loop, postprocess, main, get_gradient_color, guard_number
 
 
 def test_gradient_color():
@@ -30,6 +30,20 @@
         loops = splitloops(data)
         assert len(loops) == 2
 
+    def test_no_of_loops_hexguards(self):
+        data = [preparse("""
+        # Loop 0 : loop with 39 ops
+        debug_merge_point('', 0)
+        guard_class(p4, 141310752, descr=<Guard0x10abcdef0>) [p0, p1]
+        p60 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+        guard_nonnull(p60, descr=<Guard0x10abcdef1>) [p0, p1]
+        """), preparse("""
+        # Loop 1 : loop with 46 ops
+        p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+        """)]
+        loops = splitloops(data)
+        assert len(loops) == 2
+
     def test_split_one_loop(self):
         real_loops = [FinalBlock(preparse("""
         p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
@@ -50,12 +64,42 @@
         assert loop.left.content == ''
         assert loop.right.content == 'extra'
 
+    def test_split_one_loop_hexguards(self):
+        real_loops = [FinalBlock(preparse("""
+        p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+        guard_class(p4, 141310752, descr=<Guard0x10abcdef2>) [p0, p1]
+        """), None), FinalBlock(preparse("""
+        p60 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+        guard_nonnull(p60, descr=<Guard0x10abcdef0>) [p0, p1]
+        """), None)]
+        real_loops[0].loop_no = 0
+        real_loops[1].loop_no = 1
+        allloops = real_loops[:]
+        split_one_loop(real_loops, 'Guard0x10abcdef0', 'extra', 1, guard_number(("0x10abcdef0", "0x")), allloops)
+        loop = real_loops[1]
+        assert isinstance(loop, Block)
+        assert loop.content.endswith('p1]')
+        loop.left = allloops[loop.left]
+        loop.right = allloops[loop.right]
+        assert loop.left.content == ''
+        assert loop.right.content == 'extra'
+
     def test_postparse(self):
         real_loops = [FinalBlock("debug_merge_point('<code object _runCallbacks, file '/tmp/x/twisted-trunk/twisted/internet/defer.py', line 357> #40 POP_TOP', 0)", None)]
         postprocess(real_loops, real_loops[:], {})
         assert real_loops[0].header.startswith("_runCallbacks, file '/tmp/x/twisted-trunk/twisted/internet/defer.py', line 357")
 
+    def test_postparse_new(self):
+        real_loops = [FinalBlock("debug_merge_point(0, 0, '<code object _optimize_charset. file '/usr/local/Cellar/pypy/2.0-beta2/lib-python/2.7/sre_compile.py'. line 207> #351 LOAD_FAST')", None)]
+        postprocess(real_loops, real_loops[:], {})
+        assert real_loops[0].header.startswith("_optimize_charset. file '/usr/local/Cellar/pypy/2.0-beta2/lib-python/2.7/sre_compile.py'. line 207")
+
     def test_load_actual(self):
         fname = py.path.local(__file__).join('..', 'data.log.bz2')
         main(str(fname), False, view=False)
         # assert did not explode
+
+    def test_load_actual_f(self):
+        fname = py.path.local(__file__).join('..', 'f.pypylog.bz2')
+        main(str(fname), False, view=False)
+        # assert did not explode
diff --git a/rpython/jit/tool/traceviewer.py b/rpython/jit/tool/traceviewer.py
--- a/rpython/jit/tool/traceviewer.py
+++ b/rpython/jit/tool/traceviewer.py
@@ -56,6 +56,18 @@
 
 BOX_COLOR = (128, 0, 96)
 
+GUARDNO_RE = "((0x)?[\da-f]+)"
+def guard_number(guardno_match):
+    if (len(guardno_match) == 1 # ("12354",)
+        or guardno_match[1] != "0x" # ("12345", None)
+    ):
+        return int(guardno_match[0])
+    else: # ("0x12ef", "0x")
+        return int(guardno_match[0], 16)
+
+def guard_number_string(guardno_match):
+    return guardno_match[0] # its always the first group
+
 class BasicBlock(object):
     counter = 0
     startlineno = 0
@@ -85,13 +97,15 @@
 
     def set_content(self, content):
         self._content = content
-        groups = re.findall('Guard(\d+)', content)
+        groups = re.findall('Guard' + GUARDNO_RE, content)
         if not groups:
             self.first_guard = -1
             self.last_guard = -1
         else:
-            self.first_guard = int(groups[0])
-            self.last_guard = int(groups[-1])
+            # guards can be out of order nowadays
+            groups = sorted(groups)
+            self.first_guard = guard_number(groups[0])
+            self.last_guard = guard_number(groups[-1])
 
     content = property(get_content, set_content)
 
@@ -197,11 +211,11 @@
             _loop.loop_no = no
             allloops.append(_loop)
         else:
-            m = re.search("bridge out of Guard (\d+)", firstline)
+            m = re.search("bridge out of Guard " + GUARDNO_RE, firstline)
             assert m
-            guard_s = 'Guard' + m.group(1)
+            guard_s = 'Guard' + guard_number_string(m.groups())
             split_one_loop(real_loops, guard_s, loop, counter,
-                           int(m.group(1)), allloops)
+                           guard_number(m.groups()), allloops)
         counter += loop.count("\n") + 2
     return real_loops, allloops
 
@@ -211,7 +225,7 @@
     memo.add(loop)
     if loop is None:
         return
-    m = re.search("debug_merge_point\('(<code object (.*?)> (.*?))'", loop.content)
+    m = re.search("debug_merge_point\((?:\d+,\ )*'(<code object (.*?)> (.*?))'", loop.content)
     if m is None:
         name = '?'
         loop.key = '?'
@@ -236,7 +250,7 @@
     content = loop.content
     loop.content = "Logfile at %d\n" % loop.startlineno + content
     loop.postprocess(loops, memo, counts)
-    
+
 def postprocess(loops, allloops, counts):
     for loop in allloops:
         if isinstance(loop, Block):
diff --git a/rpython/rlib/jit_hooks.py b/rpython/rlib/jit_hooks.py
--- a/rpython/rlib/jit_hooks.py
+++ b/rpython/rlib/jit_hooks.py
@@ -111,6 +111,11 @@
     from rpython.jit.metainterp.history import Const
     return isinstance(_cast_to_box(llbox), Const)
 
+ at register_helper(annmodel.SomeBool())
+def box_isint(llbox):
+    from rpython.jit.metainterp.history import INT
+    return _cast_to_box(llbox).type == INT
+
 # ------------------------- stats interface ---------------------------
 
 @register_helper(annmodel.SomeBool())
diff --git a/rpython/rtyper/module/test/test_ll_os.py b/rpython/rtyper/module/test/test_ll_os.py
--- a/rpython/rtyper/module/test/test_ll_os.py
+++ b/rpython/rtyper/module/test/test_ll_os.py
@@ -46,6 +46,26 @@
     data = getllimpl(os.getlogin)()
     assert data == expected
 
+def test_statvfs():
+    if not hasattr(os, 'statvfs'):
+        py.test.skip('posix specific function')
+    try:
+        expected = os.statvfs('.')
+    except OSError, e:
+        py.test.skip("the underlying os.statvfs() failed: %s" % e)
+    data = getllimpl(os.statvfs)('.')
+    assert data == expected
+
+def test_fstatvfs():
+    if not hasattr(os, 'fstatvfs'):
+        py.test.skip('posix specific function')
+    try:
+        expected = os.fstatvfs(0)
+    except OSError, e:
+        py.test.skip("the underlying os.fstatvfs() failed: %s" % e)
+    data = getllimpl(os.fstatvfs)(0)
+    assert data == expected
+
 def test_utimes():
     if os.name != 'nt':
         py.test.skip('Windows specific feature')


More information about the pypy-commit mailing list