[pypy-commit] pypy numpy-dtype-refactor: subclassing types, failing tests for bools (why are they so special :()

alex_gaynor noreply at buildbot.pypy.org
Thu Nov 17 22:53:38 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy-dtype-refactor
Changeset: r49502:057601b01a65
Date: 2011-11-17 16:53 -0500
http://bitbucket.org/pypy/pypy/changeset/057601b01a65/

Log:	subclassing types, failing tests for bools (why are they so special
	:()

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
@@ -9,7 +9,7 @@
 from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
      descr_new_array, scalar_w, SingleDimArray)
 from pypy.module.micronumpy import interp_ufuncs
-from pypy.rlib.objectmodel import specialize
+from pypy.rlib.objectmodel import specialize, instantiate
 
 
 class BogusBytecode(Exception):
@@ -112,6 +112,9 @@
         assert isinstance(what, tp)
         return what
 
+    def allocate_instance(self, klass, w_subtype):
+        return instantiate(klass)
+
 class FloatObject(W_Root):
     tp = FakeSpace.w_float
     def __init__(self, floatval):
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
@@ -11,12 +11,14 @@
 
 MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
 
-def dtype_getter(name):
-    @staticmethod
+def new_dtype_getter(name):
     def get_dtype(space):
         from pypy.module.micronumpy.interp_dtype import get_dtype_cache
         return getattr(get_dtype_cache(space), "w_%sdtype" % name)
-    return get_dtype
+    def new(space, w_subtype, w_value):
+        dtype = get_dtype(space)
+        return dtype.itemtype.coerce_subtype(space, w_subtype, w_value)
+    return new, staticmethod(get_dtype)
 
 class PrimitiveBox(object):
     _mixin_ = True
@@ -30,13 +32,7 @@
 class W_GenericBox(Wrappable):
     _attrs_ = ()
 
-    def descr__new__(space, w_subtype, w_value):
-        from pypy.module.micronumpy.interp_dtype import get_dtype_cache
-        # XXX: not correct if w_subtype is a user defined subclass of a builtin
-        # type, this whole thing feels a little wrong.
-        for dtype in get_dtype_cache(space).builtin_dtypes:
-            if w_subtype is dtype.w_box_type:
-                return dtype.coerce(space, w_value)
+    def descr__new__(space, w_subtype, __args__):
         assert isinstance(w_subtype, W_TypeObject)
         raise operationerrfmt(space.w_TypeError, "cannot create '%s' instances",
             w_subtype.get_module_type_name()
@@ -98,7 +94,7 @@
 
 
 class W_BoolBox(W_GenericBox, PrimitiveBox):
-    get_dtype = dtype_getter("bool")
+    descr__new__, get_dtype = new_dtype_getter("bool")
 
 class W_NumberBox(W_GenericBox):
     _attrs_ = ()
@@ -113,7 +109,7 @@
     pass
 
 class W_Int8Box(W_SignedIntegerBox, PrimitiveBox):
-    get_dtype = dtype_getter("int8")
+    descr__new__, get_dtype = new_dtype_getter("int8")
 
 class W_UInt8Box(W_UnsignedIntgerBox, PrimitiveBox):
     pass
@@ -131,13 +127,13 @@
     pass
 
 class W_LongBox(W_SignedIntegerBox, PrimitiveBox):
-    get_dtype = dtype_getter("long")
+    descr__new__, get_dtype = new_dtype_getter("long")
 
 class W_ULongBox(W_UnsignedIntgerBox, PrimitiveBox):
     pass
 
 class W_Int64Box(W_SignedIntegerBox, PrimitiveBox):
-    get_dtype = dtype_getter("int64")
+    descr__new__, get_dtype = new_dtype_getter("int64")
 
 class W_UInt64Box(W_UnsignedIntgerBox, PrimitiveBox):
     pass
@@ -149,10 +145,10 @@
     _attrs_ = ()
 
 class W_Float32Box(W_FloatingBox, PrimitiveBox):
-    get_dtype = dtype_getter("float32")
+    descr__new__, get_dtype = new_dtype_getter("float32")
 
 class W_Float64Box(W_FloatingBox, PrimitiveBox):
-    get_dtype = dtype_getter("float64")
+    descr__new__, get_dtype = new_dtype_getter("float64")
 
 
 
@@ -160,6 +156,7 @@
     __module__ = "numpy",
 
     __new__ = interp2app(W_GenericBox.descr__new__.im_func),
+
     __str__ = interp2app(W_GenericBox.descr_str),
     __repr__ = interp2app(W_GenericBox.descr_repr),
     __int__ = interp2app(W_GenericBox.descr_int),
@@ -186,6 +183,7 @@
 
 W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
     __module__ = "numpy",
+    __new__ = interp2app(W_BoolBox.descr__new__.im_func),
 )
 
 W_NumberBox.typedef = TypeDef("number", W_GenericBox.typedef,
@@ -202,6 +200,7 @@
 
 W_Int8Box.typedef = TypeDef("int8", W_SignedIntegerBox.typedef,
     __module__ = "numpy",
+    __new__ = interp2app(W_Int8Box.descr__new__.im_func),
 )
 
 W_UInt8Box.typedef = TypeDef("uint8", W_UnsignedIntgerBox.typedef,
@@ -258,4 +257,6 @@
 
 W_Float64Box.typedef = TypeDef("float64", (W_FloatingBox.typedef, float_typedef),
     __module__ = "numpy",
+
+    __new__ = interp2app(W_Float64Box.descr__new__.im_func),
 )
\ No newline at end of file
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
@@ -186,6 +186,12 @@
         assert numpy.bool_("") is numpy.False_
         assert type(numpy.True_) is type(numpy.False_) is numpy.bool_
 
+        class X(numpy.bool_):
+            pass
+
+        assert type(X(True)) is numpy.bool_
+        assert X(True) is numpy.True_
+
     def test_int8(self):
         import numpy
 
@@ -206,8 +212,19 @@
 
         assert numpy.float64.mro() == [numpy.float64, numpy.floating, numpy.inexact, numpy.number, numpy.generic, float, object]
 
-        a  = numpy.array([1, 2, 3], numpy.float64)
+        a = numpy.array([1, 2, 3], numpy.float64)
         assert type(a[1]) is numpy.float64
         assert numpy.dtype(float).type is numpy.float64
 
         assert numpy.float64(2.0) == 2.0
+
+    def test_subclass_type(self):
+        import numpy
+
+        class X(numpy.float64):
+            def m(self):
+                return self + 2
+
+        b = X(10)
+        assert type(b) is X
+        assert b.m() == 12
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
@@ -65,7 +65,14 @@
     def coerce(self, space, w_item):
         if isinstance(w_item, self.BoxType):
             return w_item
-        return self._coerce(space, w_item)
+        return self.coerce_subtype(space, space.gettypefor(self.BoxType), w_item)
+
+    def coerce_subtype(self, space, w_subtype, w_item):
+        # XXX: ugly
+        w_obj = space.allocate_instance(self.BoxType, w_subtype)
+        assert isinstance(w_obj, self.BoxType)
+        w_obj.__init__(self._coerce(space, w_item).value)
+        return w_obj
 
     def _coerce(self, space, w_item):
         raise NotImplementedError


More information about the pypy-commit mailing list