Author: Maciej Fijalkowski <[email protected]>
Branch: numpy-record-dtypes
Changeset: r52254:a3f0a909959f
Date: 2012-02-08 20:44 +0100
http://bitbucket.org/pypy/pypy/changeset/a3f0a909959f/
Log: (fijal, agaynor) start implementing record types
diff --git a/pypy/module/micronumpy/__init__.py
b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -68,9 +68,10 @@
'float64': 'interp_boxes.W_Float64Box',
'intp': 'types.IntP.BoxType',
'uintp': 'types.UIntP.BoxType',
+ 'flexible': 'interp_boxes.W_FlexibleBox',
#'str_': 'interp_boxes.W_StringBox',
#'unicode_': 'interp_boxes.W_UnicodeBox',
- #'void': 'interp_boxes.W_VoidBox',
+ 'void': 'interp_boxes.W_VoidBox',
}
# ufuncs
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
@@ -163,6 +163,12 @@
descr__new__, get_dtype = new_dtype_getter("float64")
+class W_FlexibleBox(W_GenericBox):
+ pass
+
+class W_VoidBox(W_FlexibleBox):
+ pass
+
W_GenericBox.typedef = TypeDef("generic",
__module__ = "numpypy",
@@ -285,3 +291,12 @@
__new__ = interp2app(W_Float64Box.descr__new__.im_func),
)
+
+
+W_FlexibleBox.typedef = TypeDef("flexible", W_GenericBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_VoidBox.typedef = TypeDef("void", W_FlexibleBox.typedef,
+ __module__ = "numpypy",
+)
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
@@ -2,7 +2,7 @@
import sys
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
interp_attrproperty, interp_attrproperty_w)
from pypy.module.micronumpy import types, interp_boxes
@@ -15,7 +15,7 @@
SIGNEDLTR = "i"
BOOLLTR = "b"
FLOATINGLTR = "f"
-VOID = 'V'
+VOIDLTR = 'V'
VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True,
'render_as_void': True})
@@ -23,7 +23,8 @@
class W_Dtype(Wrappable):
_immutable_fields_ = ["itemtype", "num", "kind"]
- def __init__(self, itemtype, num, kind, name, char, w_box_type,
alternate_constructors=[], aliases=[]):
+ def __init__(self, itemtype, num, kind, name, char, w_box_type,
alternate_constructors=[], aliases=[],
+ fields=None, fieldnames=None):
self.itemtype = itemtype
self.num = num
self.kind = kind
@@ -32,6 +33,8 @@
self.w_box_type = w_box_type
self.alternate_constructors = alternate_constructors
self.aliases = aliases
+ self.fields = fields
+ self.fieldnames = fieldnames
def malloc(self, length):
# XXX find out why test_zjit explodes with tracking of allocations
@@ -85,6 +88,29 @@
def descr_ne(self, space, w_other):
return space.wrap(not self.eq(space, w_other))
+ def descr_get_fields(self, space):
+ if self.fields is None:
+ return space.w_None
+ w_d = space.newdict()
+ for name, (offset, subdtype) in self.fields.iteritems():
+ space.setitem(w_d, space.wrap(name), space.newtuple([subdtype,
+
space.wrap(offset)]))
+ return w_d
+
+ def descr_get_names(self, space):
+ if self.fieldnames is None:
+ return space.w_None
+ return space.newtuple([space.wrap(name) for name in self.fieldnames])
+
+ @unwrap_spec(item=str)
+ def descr_getitem(self, item):
+ if self.fields is None:
+ raise OperationError(space.w_KeyError, space.wrap("There are no
keys in dtypes %s" % self.name))
+ try:
+ return self.fields[item][1]
+ except KeyError:
+ raise OperationError(space.w_KeyError, space.wrap("Field named %s
not found" % item))
+
def is_int_type(self):
return (self.kind == SIGNEDLTR or self.kind == UNSIGNEDLTR or
self.kind == BOOLLTR)
@@ -94,15 +120,24 @@
def dtype_from_list(space, w_lst):
lst_w = space.listview(w_lst)
- fieldlist = []
+ fields = {}
offset = 0
+ ofs_and_items = []
+ fieldnames = []
for w_elem in lst_w:
w_fldname, w_flddesc = space.fixedview(w_elem, 2)
- subdtype = descr__new__(space.gettypefor(W_Dtype), w_flddesc)
- align = subdtype.alignment
- offset = (offset + (align-1)) & ~ (align-1)
- fieldlist.append((offset, space.str_w(w_fldname), subdtype))
- xxx
+ subdtype = descr__new__(space, space.gettypefor(W_Dtype), w_flddesc)
+ fldname = space.str_w(w_fldname)
+ if fldname in fields:
+ raise OperationError(space.w_ValueError, space.wrap("two fields
with the same name"))
+ fields[fldname] = (offset, subdtype)
+ ofs_and_items.append((offset, subdtype.itemtype))
+ offset += subdtype.itemtype.get_element_size()
+ fieldnames.append(fldname)
+ itemtype = types.RecordType(ofs_and_items)
+ return W_Dtype(itemtype, 20, VOIDLTR, "void" + str(8 *
itemtype.get_element_size()),
+ "V", space.gettypefor(interp_boxes.W_VoidBox),
fields=fields,
+ fieldnames=fieldnames)
def descr__new__(space, w_subtype, w_dtype):
cache = get_dtype_cache(space)
@@ -135,14 +170,18 @@
__repr__ = interp2app(W_Dtype.descr_repr),
__eq__ = interp2app(W_Dtype.descr_eq),
__ne__ = interp2app(W_Dtype.descr_ne),
+ __getitem__ = interp2app(W_Dtype.descr_getitem),
num = interp_attrproperty("num", cls=W_Dtype),
kind = interp_attrproperty("kind", cls=W_Dtype),
+ char = interp_attrproperty("char", cls=W_Dtype),
type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
alignment = GetSetProperty(W_Dtype.descr_get_alignment),
shape = GetSetProperty(W_Dtype.descr_get_shape),
name = interp_attrproperty('name', cls=W_Dtype),
+ fields = GetSetProperty(W_Dtype.descr_get_fields),
+ names = GetSetProperty(W_Dtype.descr_get_names),
)
W_Dtype.typedef.acceptable_as_base_class = False
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
@@ -13,6 +13,7 @@
assert dtype(d) is d
assert dtype(None) is dtype(float)
assert dtype('int8').name == 'int8'
+ assert dtype(int).fields is None
raises(TypeError, dtype, 1042)
def test_dtype_eq(self):
@@ -454,3 +455,21 @@
def test_alignment(self):
from _numpypy import dtype
assert dtype('i4').alignment == 4
+
+class AppTestRecordDtypes(BaseNumpyAppTest):
+ def test_create(self):
+ from _numpypy import dtype, void
+
+ raises(ValueError, "dtype([('x', int), ('x', float)])")
+ d = dtype([("x", "int32"), ("y", "int32"), ("z", "int32"), ("value",
float)])
+ assert d.fields['x'] == (dtype('int32'), 0)
+ assert d.fields['value'] == (dtype(float), 12)
+ assert d['x'] == dtype('int32')
+ assert d.name == "void160"
+ assert d.num == 20
+ assert d.itemsize == 20
+ assert d.kind == 'V'
+ assert d.type is void
+ assert d.char == 'V'
+ assert d.names == ("x", "y", "z", "value")
+
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
@@ -594,6 +594,18 @@
BoxType = interp_boxes.W_Float64Box
format_code = "d"
+class CompositeType(BaseType):
+ def __init__(self, offsets_and_types):
+ self.offsets_and_types = offsets_and_types
+ last_item = offsets_and_types[-1]
+ self.size = last_item[0] + last_item[1].get_element_size()
+
+ def get_element_size(self):
+ return self.size
+
+class RecordType(CompositeType):
+ pass
+
for tp in [Int32, Int64]:
if tp.T == lltype.Signed:
IntP = tp
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit