diff options
author | Travis Oliphant <oliphant@enthought.com> | 2005-12-13 05:33:13 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2005-12-13 05:33:13 +0000 |
commit | f0995b54db038fa8e1ecfecf51c2519e48e10043 (patch) | |
tree | 456bd1ad7f3817ea948004305812b73094d749e6 | |
parent | aea56a2d4c50cbedd4591aa970c1ac2578666d5a (diff) | |
download | numpy-f0995b54db038fa8e1ecfecf51c2519e48e10043.tar.gz |
Fixed array pickle to handle subclasses.
-rw-r--r-- | scipy/base/__init__.py | 1 | ||||
-rw-r--r-- | scipy/base/_internal.py | 5 | ||||
-rw-r--r-- | scipy/base/chararray.py | 23 | ||||
-rw-r--r-- | scipy/base/records.py | 65 | ||||
-rw-r--r-- | scipy/base/src/arraymethods.c | 11 | ||||
-rw-r--r-- | scipy/base/src/arrayobject.c | 6 | ||||
-rw-r--r-- | scipy/base/src/ufuncobject.c | 6 |
7 files changed, 61 insertions, 56 deletions
diff --git a/scipy/base/__init__.py b/scipy/base/__init__.py index 60c4fb723..2cffbf759 100644 --- a/scipy/base/__init__.py +++ b/scipy/base/__init__.py @@ -21,6 +21,7 @@ from polynomial import * from machar import * from getlimits import * import ma +import chararray as char import records as rec from records import * from memmap import * diff --git a/scipy/base/_internal.py b/scipy/base/_internal.py index a39ac2641..7dcfdd882 100644 --- a/scipy/base/_internal.py +++ b/scipy/base/_internal.py @@ -2,7 +2,7 @@ #A place for code to be called from C-code # that implements more complicated stuff. -from multiarray import _flagdict, dtypedescr +from multiarray import _flagdict, dtypedescr, ndarray _defflags = _flagdict.keys() @@ -280,3 +280,6 @@ def _array_descr(descriptor): result.append(tup) return result + +def _reconstruct(subtype, shape, dtype): + return ndarray.__new__(subtype, shape, dtype) diff --git a/scipy/base/chararray.py b/scipy/base/chararray.py index 6a6195b04..3133de07b 100644 --- a/scipy/base/chararray.py +++ b/scipy/base/chararray.py @@ -3,12 +3,14 @@ from numerictypes import character, string, unicode_, \ from numeric import ndarray, broadcast, empty, array import sys +__all__ = ['chararray'] + # special sub-class for character arrays (string and unicode_) # This adds equality testing and methods of str and unicode types # which operate on an element-by-element basis -class ndchararray(ndarray): +class chararray(ndarray): def __new__(subtype, shape, itemlen=1, unicode=False, buffer=None, offset=0, strides=None, swap=0, fortran=0): @@ -28,9 +30,6 @@ class ndchararray(ndarray): swap=swap, fortran=fortran) return self - def __reduce__(self): - pass - def _richcmpfunc(self, other, op): b = broadcast(self, other) result = empty(b.shape, dtype=bool) @@ -282,9 +281,9 @@ class ndchararray(ndarray): def zfill(self, width): return self._generalmethod('zfill', broadcast(self, width)) - -def chararray(obj, itemlen=7, copy=True, unicode=False, fortran=False): - + +def array(obj, itemlen=7, copy=True, unicode=False, fortran=False): + if isinstance(obj, ndchararray): if copy or (itemlen != obj.itemlen) \ or (not unicode and obj.dtype == unicode_) \ @@ -320,10 +319,10 @@ def chararray(obj, itemlen=7, copy=True, unicode=False, fortran=False): val = array(obj, dtype=dtype, fortran=fortran, subok=1) - return ndchararray(val.shape, itemlen, unicode, buffer=val, - strides=val.strides, swap=val.flags.swapped, - fortran=fortran) - -def aschararray(obj, itemlen=7, unicode=False, fortran=False): + return chararray(val.shape, itemlen, unicode, buffer=val, + strides=val.strides, swap=val.flags.swapped, + fortran=fortran) + +def asarray(obj, itemlen=7, unicode=False, fortran=False): return chararray(obj, itemlen, copy=False, unicode=unicode, fortran=fortran) diff --git a/scipy/base/records.py b/scipy/base/records.py index 62eb76777..0b2a6be6a 100644 --- a/scipy/base/records.py +++ b/scipy/base/records.py @@ -247,9 +247,8 @@ class record(nt.void): # The recarray is almost identical to a standard array (which supports -# named fields already) The biggest difference is that it is always of -# record data-type, has fields, and can use attribute-lookup to access -# those fields. +# named fields already) The biggest difference is that it can use +# attribute-lookup to the fields. class recarray(sb.ndarray): @@ -257,7 +256,7 @@ class recarray(sb.ndarray): buf=None, offset=0, strides=None, swap=0, aligned=0): if isinstance(formats, sb.dtypedescr): - descr = formats + descr = formats elif isinstance(formats,str): parsed = format_parser(formats, names, titles, aligned) descr = parsed._descr @@ -312,6 +311,9 @@ def fromarrays(arrayList, formats=None, names=None, titles=None, shape=None, if shape is None or shape == 0: shape = arrayList[0].shape + + if isinstance(shape, int): + shape = (shape,) if formats is None: # go through each object in the list to see if it is an ndarray @@ -344,7 +346,8 @@ def fromarrays(arrayList, formats=None, names=None, titles=None, shape=None, return _array -def fromrecords(recList, formats=None, names=None, shape=0, swap=0, aligned=0): +def fromrecords(recList, formats=None, names=None, titles=None, shape=None, + swap=0, aligned=0): """ create a Record Array from a list of records in text form The data in the same field can be heterogeneous, they will be promoted @@ -358,9 +361,9 @@ def fromrecords(recList, formats=None, names=None, shape=0, swap=0, aligned=0): >>> r=fromrecords([[456,'dbe',1.2],[2,'de',1.3]],names='col1,col2,col3') >>> print r[0] (456, 'dbe', 1.2) - >>> r.field('col1') + >>> r.col1 array([456, 2]) - >>> r.field('col2') + >>> r.col2 array(['dbe', 'de']) >>> import cPickle >>> print cPickle.loads(cPickle.dumps(r)) @@ -370,30 +373,28 @@ def fromrecords(recList, formats=None, names=None, shape=0, swap=0, aligned=0): ] """ - if shape == 0: - _shape = len(recList) - else: - _shape = shape - - _nfields = len(recList[0]) - for _rec in recList: - if len(_rec) != _nfields: - raise ValueError, "inconsistent number of objects in each record" - arrlist = [0]*_nfields - for col in range(_nfields): - tmp = [0]*_shape - for row in range(_shape): - tmp[row] = recList[row][col] - try: - arrlist[col] = num.array(tmp) - except: - try: - arrlist[col] = chararray.array(tmp) - except: - raise ValueError, "inconsistent data at row %d,field %d" % (row, col) - _array = fromarrays(arrlist, formats=formats, shape=_shape, names=names, - byteorder=byteorder, aligned=aligned) - del arrlist - del tmp + if (shape is None or shape == 0): + shape = len(recList) + + if isinstance(shape, int): + shape = (shape,) + + nfields = len(recList[0]) + if formats is None: # slower + obj = sb.array(recList,dtype=object) + arrlist = [sb.array(obj[:,i].tolist()) for i in xrange(nfields)] + return fromarrays(arrlist, formats=formats, shape=shape, names=names, + titles=titles, swap=swap, aligned=aligned) + + parsed = format_parser(formats, names, titles, aligned) + _names = parsed._names + _array = recarray(shape, parsed._descr, swap=swap) + + farr = _array.flat + + for k in xrange(_array.size): + for j in xrange(nfields): + farr[k][_names[j]] = recList[k][j] + return _array diff --git a/scipy/base/src/arraymethods.c b/scipy/base/src/arraymethods.c index 0cca98896..089aedf23 100644 --- a/scipy/base/src/arraymethods.c +++ b/scipy/base/src/arraymethods.c @@ -863,19 +863,18 @@ array_reduce(PyArrayObject *self, PyObject *args) ret = PyTuple_New(3); if (ret == NULL) return NULL; - mod = PyImport_ImportModule("scipy.base.multiarray"); + mod = PyImport_ImportModule("scipy.base._internal"); if (mod == NULL) {Py_DECREF(ret); return NULL;} - obj = PyObject_GetAttrString(mod, "empty"); + obj = PyObject_GetAttrString(mod, "_reconstruct"); Py_DECREF(mod); - if (obj == NULL) {Py_DECREF(ret); return NULL;} PyTuple_SET_ITEM(ret, 0, obj); PyTuple_SET_ITEM(ret, 1, - Py_BuildValue("NNN", + Py_BuildValue("ONN", + (PyObject *)self->ob_type, Py_BuildValue("(N)", PyInt_FromLong(0)), PyObject_GetAttrString((PyObject *)self, - "dtypechar"), - PyInt_FromLong((long) self->descr->elsize))); + "dtypechar"))); /* Now fill in object's state. This is a tuple with 4 arguments diff --git a/scipy/base/src/arrayobject.c b/scipy/base/src/arrayobject.c index ba4d17762..2610fe59c 100644 --- a/scipy/base/src/arrayobject.c +++ b/scipy/base/src/arrayobject.c @@ -8047,7 +8047,7 @@ arraydescr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) } if (!PyArray_DescrConverter(odescr, &conv)) return NULL; - /* Get a new copy of it */ + /* Get a new copy of it (so it can be changed in setstate) */ descr = PyArray_DescrNew(conv); Py_DECREF(conv); return (PyObject *)descr; @@ -8072,7 +8072,9 @@ arraydescr_reduce(PyArray_Descr *self, PyObject *args) Py_DECREF(mod); if (obj == NULL) {Py_DECREF(ret); return NULL;} PyTuple_SET_ITEM(ret, 0, obj); - if (PyTypeNum_ISUSERDEF(self->type_num)) { + if (PyTypeNum_ISUSERDEF(self->type_num) || \ + ((self->type_num == PyArray_VOID && \ + self->typeobj != &PyVoidArrType_Type))) { obj = (PyObject *)self->typeobj; Py_INCREF(obj); } diff --git a/scipy/base/src/ufuncobject.c b/scipy/base/src/ufuncobject.c index a3d508a7d..4cf5b9c41 100644 --- a/scipy/base/src/ufuncobject.c +++ b/scipy/base/src/ufuncobject.c @@ -1374,10 +1374,10 @@ _printcastbuf(PyUFuncLoopObject *loop, int bufnum) /* currently generic ufuncs cannot be built for use on flexible arrays. The cast functions in the generic loop would need to be fixed to pass - something besides NULL, NULL. + in something besides NULL, NULL. - Also the underlying ufunc loops would not know the array size unless - that were passed in as data. + Also the underlying ufunc loops would not know the element-size unless + that was passed in as data (which could be arranged). */ |