mirror of
				https://gitlab.alpinelinux.org/alpine/aports.git
				synced 2025-10-31 08:21:49 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			128 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 3a816a4db9b498eb64eb837fdcca0fa8ddbe063e Mon Sep 17 00:00:00 2001
 | |
| From: Allan Haldane <allan.haldane@gmail.com>
 | |
| Date: Sat, 17 Oct 2015 14:00:36 -0400
 | |
| Subject: [PATCH] BUG: recarrays viewed as subarrays don't convert to np.record
 | |
|  type
 | |
| 
 | |
| Record array views were updated in #5943 to return np.record dtype
 | |
| where possible, but forgot about the case of sub-arrays.
 | |
| 
 | |
| That's fixed here, so accessing subarray fields by attribute or index
 | |
| works sensibly, as well as viewing a record array as a subarray dtype,
 | |
| and printing subarrays.
 | |
| 
 | |
| This also happens to fix #6459, since it affects the same lines.
 | |
| 
 | |
| Fixes #6497 #6459
 | |
| ---
 | |
|  numpy/core/records.py            | 30 +++++++++++++++++++-----------
 | |
|  numpy/core/tests/test_records.py | 23 +++++++++++++++++++++++
 | |
|  2 files changed, 42 insertions(+), 11 deletions(-)
 | |
| 
 | |
| diff --git a/numpy/core/records.py b/numpy/core/records.py
 | |
| index 4a99553..4ce3fe9 100644
 | |
| --- a/numpy/core/records.py
 | |
| +++ b/numpy/core/records.py
 | |
| @@ -448,12 +448,14 @@ def __getattribute__(self, attr):
 | |
|  
 | |
|          # At this point obj will always be a recarray, since (see
 | |
|          # PyArray_GetField) the type of obj is inherited. Next, if obj.dtype is
 | |
| -        # non-structured, convert it to an ndarray. If obj is structured leave
 | |
| -        # it as a recarray, but make sure to convert to the same dtype.type (eg
 | |
| -        # to preserve numpy.record type if present), since nested structured
 | |
| -        # fields do not inherit type.
 | |
| +        # non-structured, convert it to an ndarray. Then if obj is structured
 | |
| +        # with void type convert it to the same dtype.type (eg to preserve
 | |
| +        # numpy.record type if present), since nested structured fields do not
 | |
| +        # inherit type. Don't do this for non-void structures though.
 | |
|          if obj.dtype.fields:
 | |
| -            return obj.view(dtype=(self.dtype.type, obj.dtype.fields))
 | |
| +            if issubclass(obj.dtype.type, nt.void):
 | |
| +                return obj.view(dtype=(self.dtype.type, obj.dtype))
 | |
| +            return obj
 | |
|          else:
 | |
|              return obj.view(ndarray)
 | |
|  
 | |
| @@ -463,8 +465,9 @@ def __getattribute__(self, attr):
 | |
|      # Thus, you can't create attributes on-the-fly that are field names.
 | |
|      def __setattr__(self, attr, val):
 | |
|  
 | |
| -        # Automatically convert (void) dtypes to records.
 | |
| -        if attr == 'dtype' and issubclass(val.type, nt.void):
 | |
| +        # Automatically convert (void) structured types to records
 | |
| +        # (but not non-void structures, subarrays, or non-structured voids)
 | |
| +        if attr == 'dtype' and issubclass(val.type, nt.void) and val.fields:
 | |
|              val = sb.dtype((record, val))
 | |
|  
 | |
|          newattr = attr not in self.__dict__
 | |
| @@ -499,7 +502,9 @@ def __getitem__(self, indx):
 | |
|          # we might also be returning a single element
 | |
|          if isinstance(obj, ndarray):
 | |
|              if obj.dtype.fields:
 | |
| -                return obj.view(dtype=(self.dtype.type, obj.dtype.fields))
 | |
| +                if issubclass(obj.dtype.type, nt.void):
 | |
| +                    return obj.view(dtype=(self.dtype.type, obj.dtype))
 | |
| +                return obj
 | |
|              else:
 | |
|                  return obj.view(type=ndarray)
 | |
|          else:
 | |
| @@ -519,11 +524,14 @@ def __repr__(self):
 | |
|              # If this is a full record array (has numpy.record dtype),
 | |
|              # or if it has a scalar (non-void) dtype with no records,
 | |
|              # represent it using the rec.array function. Since rec.array
 | |
| -            # converts dtype to a numpy.record for us, use only dtype.descr,
 | |
| -            # not repr(dtype).
 | |
| +            # converts dtype to a numpy.record for us, convert back
 | |
| +            # to non-record before printing
 | |
| +            plain_dtype = self.dtype
 | |
| +            if plain_dtype.type is record:
 | |
| +                plain_dtype = sb.dtype((nt.void, plain_dtype))
 | |
|              lf = '\n'+' '*len("rec.array(")
 | |
|              return ('rec.array(%s, %sdtype=%s)' %
 | |
| -                          (lst, lf, repr(self.dtype.descr)))
 | |
| +                          (lst, lf, plain_dtype))
 | |
|          else:
 | |
|              # otherwise represent it using np.array plus a view
 | |
|              # This should only happen if the user is playing
 | |
| diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py
 | |
| index 7a18f29..290bc4f 100644
 | |
| --- a/numpy/core/tests/test_records.py
 | |
| +++ b/numpy/core/tests/test_records.py
 | |
| @@ -121,6 +121,23 @@ def test_recarray_views(self):
 | |
|          assert_equal(type(rv), np.recarray)
 | |
|          assert_equal(rv.dtype.type, np.record)
 | |
|  
 | |
| +        # check that accessing nested structures keep record type, but
 | |
| +        # not for subarrays, non-void structures, non-structured voids
 | |
| +        test_dtype = [('a', 'f4,f4'), ('b', 'V8'), ('c', ('f4',2)),
 | |
| +                      ('d', ('i8', 'i4,i4'))]
 | |
| +        r = np.rec.array([((1,1), b'11111111', [1,1], 1),
 | |
| +                          ((1,1), b'11111111', [1,1], 1)], dtype=test_dtype)
 | |
| +        assert_equal(r.a.dtype.type, np.record)
 | |
| +        assert_equal(r.b.dtype.type, np.void)
 | |
| +        assert_equal(r.c.dtype.type, np.float32)
 | |
| +        assert_equal(r.d.dtype.type, np.int64)
 | |
| +        # check the same, but for views
 | |
| +        r = np.rec.array(np.ones(4, dtype='i4,i4'))
 | |
| +        assert_equal(r.view('f4,f4').dtype.type, np.record)
 | |
| +        assert_equal(r.view(('i4',2)).dtype.type, np.int32)
 | |
| +        assert_equal(r.view('V8').dtype.type, np.void)
 | |
| +        assert_equal(r.view(('i8', 'i4,i4')).dtype.type, np.int64)
 | |
| +
 | |
|          #check that we can undo the view
 | |
|          arrs = [np.ones(4, dtype='f4,i4'), np.ones(4, dtype='f8')]
 | |
|          for arr in arrs:
 | |
| @@ -135,6 +152,12 @@ def test_recarray_repr(self):
 | |
|          a = np.array(np.ones(4, dtype='f8'))
 | |
|          assert_(repr(np.rec.array(a)).startswith('rec.array'))
 | |
|  
 | |
| +        # check that the 'np.record' part of the dtype isn't shown
 | |
| +        a = np.rec.array(np.ones(3, dtype='i4,i4'))
 | |
| +        assert_equal(repr(a).find('numpy.record'), -1)
 | |
| +        a = np.rec.array(np.ones(3, dtype='i4'))
 | |
| +        assert_(repr(a).find('dtype=int32') != -1)
 | |
| +
 | |
|      def test_recarray_from_names(self):
 | |
|          ra = np.rec.array([
 | |
|              (1, 'abc', 3.7000002861022949, 0),
 |