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