Author: Maciej Fijalkowski <[email protected]>
Branch: missing-ndarray-attributes
Changeset: r60814:ea7b827e513f
Date: 2013-02-02 15:08 +0200
http://bitbucket.org/pypy/pypy/changeset/ea7b827e513f/

Log:    * support staticmethods on mixins
        * make sure sorting is RPython

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
@@ -5,7 +5,6 @@
 
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib.listsort import make_timsort_class
-from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rawstorage import raw_storage_getitem, raw_storage_setitem, \
         free_raw_storage, alloc_raw_storage
 from pypy.interpreter.error import OperationError
@@ -15,7 +14,6 @@
 
 INT_SIZE = rffi.sizeof(lltype.Signed)
 
[email protected]()
 def make_sort_classes(space, itemtype):
     TP = itemtype.T
     
@@ -81,10 +79,9 @@
     return ArgArrayRepresentation, ArgSort
 
 def argsort_array(arr, space, w_axis):
+    space.fromcache(SortCache) # that populates SortClasses
     itemtype = arr.dtype.itemtype
-    if (not isinstance(itemtype, types.Float) and
-        not isinstance(itemtype, types.Integer) and 
-        not isinstance(itemtype, types.ComplexFloating)):
+    if itemtype.Sort is None:
         # XXX this should probably be changed
         raise OperationError(space.w_NotImplementedError,
                space.wrap("sorting of non-numeric types " + \
@@ -98,6 +95,8 @@
         axis = -1
     else:
         axis = space.int_w(w_axis)
+    Repr = itemtype.SortRepr
+    Sort = itemtype.Sort
     itemsize = itemtype.get_element_size()
     # create array of indexes
     dtype = interp_dtype.get_dtype_cache(space).w_longdtype
@@ -106,7 +105,6 @@
     if len(arr.get_shape()) == 1:
         for i in range(arr.get_size()):
             raw_storage_setitem(storage, i * INT_SIZE, i)
-        Repr, Sort = make_sort_classes(space, itemtype)
         r = Repr(INT_SIZE, itemsize, arr.get_size(), arr.get_storage(),
                  storage, 0, arr.start)
         Sort(r).sort()
@@ -124,7 +122,6 @@
         stride_size = arr.strides[axis]
         index_stride_size = index_impl.strides[axis]
         axis_size = arr.shape[axis]
-        Repr, Sort = make_sort_classes(space, itemtype)
         while not iter.done():
             for i in range(axis_size):
                 raw_storage_setitem(storage, i * index_stride_size +
@@ -135,3 +132,16 @@
             iter.next()
             index_iter.next()
     return index_arr
+
+class SortCache(object):
+    built = False
+    
+    def __init__(self, space):
+        if self.built:
+            return
+        for cls in types.all_float_types:
+            cls.SortRepr, cls.Sort = make_sort_classes(space, cls)
+        for cls in types.all_int_types:
+            cls.SortRepr, cls.Sort = make_sort_classes(space, cls)
+        for cls in types.all_complex_types:
+            cls.SortRepr, cls.Sort = make_sort_classes(space, cls)
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
@@ -115,6 +115,9 @@
 class BaseType(object):
     _attrs_ = ()
 
+    SortRepr = None # placeholders for sorting classes, overloaded in sort.py
+    Sort = None
+
     def _unimplemented_ufunc(self, *args):
         raise NotImplementedError
 
@@ -384,7 +387,7 @@
         return str(self.for_computation(self.unbox(box)))
 
     @staticmethod
-    def for_computation(self, v):
+    def for_computation(v):
         return widen(v)
 
     def default_fromstring(self, space):
@@ -650,7 +653,7 @@
                             rfloat.DTSF_STR_PRECISION)
 
     @staticmethod
-    def for_computation(self, v):
+    def for_computation(v):
         return float(v)
 
     def default_fromstring(self, space):
@@ -951,7 +954,9 @@
         swapped_value = byteswap(rffi.cast(self.T, value))
         raw_storage_setitem(storage, i + offset, swapped_value)
 
-class Float16(BaseType, Float):
+class BaseFloat16(Float):
+    _mixin_ = True
+
     _attrs_ = ()
     _STORAGE_T = rffi.USHORT
     T = rffi.DOUBLE
@@ -966,13 +971,16 @@
         fval = unpack_float(s, native_is_bigendian)
         return self.box(fval)
 
-    @staticmethod
-    def for_computation(self, v):
-        return float(v)
-
     def default_fromstring(self, space):
         return self.box(-1.0)
 
+    def byteswap(self, w_v):
+        value = self.unbox(w_v)
+        hbits = float_pack(value,2)
+        swapped = byteswap(rffi.cast(self._STORAGE_T, hbits))
+        return self.box(float_unpack(r_ulonglong(swapped), 2))
+
+class Float16(BaseType, BaseFloat16):
     def _read(self, storage, i, offset):
         hbits = raw_storage_getitem(self._STORAGE_T, storage, i + offset)
         return float_unpack(r_ulonglong(hbits), 2)
@@ -980,18 +988,9 @@
     def _write(self, storage, i, offset, value):
         hbits = float_pack(value,2)
         raw_storage_setitem(storage, i + offset,
-                rffi.cast(self._STORAGE_T, hbits))
+                rffi.cast(self._STORAGE_T, hbits))    
 
-    def byteswap(self, w_v):
-        value = self.unbox(w_v)
-        hbits = float_pack(value,2)
-        swapped = byteswap(rffi.cast(self._STORAGE_T, hbits))
-        return self.box(float_unpack(r_ulonglong(swapped), 2))
-
-class NonNativeFloat16(Float16):
-    _attrs_ = ()
-    BoxType = interp_boxes.W_Float16Box
-
+class NonNativeFloat16(BaseType, BaseFloat16):
     def _read(self, storage, i, offset):
         hbits = raw_storage_getitem(self._STORAGE_T, storage, i + offset)
         return float_unpack(r_ulonglong(byteswap(hbits)), 2)
@@ -1072,7 +1071,7 @@
         return ''.join(['(', real_str, op, imag_str, ')'])
 
     @staticmethod
-    def for_computation(self, v):   
+    def for_computation(v):   
         return float(v[0]), float(v[1])
 
     def read_bool(self, arr, i, offset):
@@ -1607,8 +1606,7 @@
             pack_float80(result, value, 16, not native_is_bigendian)
             return self.box(unpack_float128(result.build(), 
native_is_bigendian))
 
-    class NonNativeFloat128(Float128):
-        pass
+    NonNativeFloat128 = Float128
 
     class Complex256(ComplexFloating, BaseType):
         _attrs_ = ()
@@ -1756,10 +1754,20 @@
         break
 del tp
 
+all_float_types = []
+all_int_types = []
+all_complex_types = []
+
 def _setup():
     # compute alignment
     for tp in globals().values():
         if isinstance(tp, type) and hasattr(tp, 'T'):
             tp.alignment = clibffi.cast_type_to_ffitype(tp.T).c_alignment
+            if issubclass(tp, Float):
+                all_float_types.append(tp)
+            if issubclass(tp, Integer):
+                all_int_types.append(tp)
+            if issubclass(tp, ComplexFloating):
+                all_complex_types.append(tp)
 _setup()
 del _setup
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -447,7 +447,7 @@
             if (x is type(None) or      # add cases here if needed
                 x.__module__ == 'rpython.rtyper.lltypesystem.lltype'):
                 result = SomeType()
-            elif getattr(x, '_mixin_', False):
+            elif x.__dict__.get('_mixin_', False):
                 raise Exception("Creating a PBC of a mixin class is not 
RPython")
             else:
                 result = SomePBC([self.getdesc(x)])
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -4,7 +4,7 @@
 from rpython.flowspace.model import Constant, FunctionGraph
 from rpython.flowspace.bytecode import cpython_code_signature
 from rpython.flowspace.argument import rawshape, ArgErr
-from rpython.tool.sourcetools import valid_identifier
+from rpython.tool.sourcetools import valid_identifier, func_with_new_name
 from rpython.tool.pairtype import extendabletype
 
 class CallFamily(object):
@@ -495,6 +495,10 @@
             # that the py lib has its own AssertionError.__init__ which
             # is of type FunctionType.  But bookkeeper.immutablevalue()
             # will do the right thing in s_get_value().
+        if isinstance(value, staticmethod) and mixin:
+            # make a new copy of staticmethod
+            value =  staticmethod(func_with_new_name(value.__func__,
+                                                     value.__func__.__name__))
 
         if type(value) in MemberDescriptorTypes:
             # skip __slots__, showing up in the class as 'member' objects
diff --git a/rpython/annotator/test/test_annrpython.py 
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -2359,6 +2359,41 @@
         assert isinstance(s.items[1], annmodel.SomeChar)
         assert isinstance(s.items[2], annmodel.SomeChar)
 
+    def test_mixin_staticmethod(self):
+        class Mixin(object):
+            _mixin_ = True
+
+            @staticmethod
+            def m(v):
+                return v
+
+        class Base(object):
+            pass
+
+        class A(Base, Mixin):
+            pass
+
+        class B(Base, Mixin):
+            pass
+
+        class C(B):
+            pass
+
+        def f():
+            a = A()
+            v0 = a.m(2)
+            b = B()
+            v1 = b.m('x')
+            c = C()
+            v2 = c.m('y')
+            return v0, v1, v2
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s.items[0], annmodel.SomeInteger)
+        assert isinstance(s.items[1], annmodel.SomeChar)
+        assert isinstance(s.items[2], annmodel.SomeChar)
+
     def test_mixin_first(self):
         class Mixin(object):
             _mixin_ = True
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to