diff options
-rw-r--r-- | numpy/core/_internal.py | 17 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 10 |
2 files changed, 20 insertions, 7 deletions
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py index 49216c646..9463b5099 100644 --- a/numpy/core/_internal.py +++ b/numpy/core/_internal.py @@ -436,8 +436,10 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): spec = spec[j+1:] # Byte order - if spec[0] in ('@', '=', '<', '>', '^'): + if spec[0] in ('@', '=', '<', '>', '^', '!'): byteorder = spec[0] + if byteorder == '!': + byteorder = '>' spec = spec[1:] # Byte order characters also control native vs. standard type sizes @@ -462,10 +464,10 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): is_padding = False if spec[:2] == 'T{': - value, spec, align = _dtype_from_pep3118(spec[2:], - byteorder=byteorder, - is_subdtype=True) + value, spec, align, next_byteorder = _dtype_from_pep3118( + spec[2:], byteorder=byteorder, is_subdtype=True) elif spec[0] in type_map_chars: + next_byteorder = byteorder if spec[0] == 'Z': j = 2 else: @@ -533,6 +535,8 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): next_dummy_name() last_offset = offset + byteorder = next_byteorder + offset += value.itemsize offset += extra_offset @@ -541,13 +545,14 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): name = get_dummy_name() fields[name] = ('V%d' % (offset - last_offset), last_offset) - if len(fields.keys()) == 1 and not explicit_name and fields['f0'][1] == 0: + if len(fields.keys()) == 1 and not explicit_name and fields['f0'][1] == 0 \ + and not is_subdtype: ret = fields['f0'][0] else: ret = dtype(fields) if is_subdtype: - return ret, spec, common_alignment + return ret, spec, common_alignment, byteorder else: return ret diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 542cdd30b..f2974a82d 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -1476,12 +1476,20 @@ if sys.version_info >= (2, 6): 'f1': ('i', 1+j)}) def test_native_padding_2(self): + # Native padding should work also for structs and sub-arrays self._check('x3T{xi}', {'f0': (({'f0': ('i', 4)}, (3,)), 4)}) - self._check('=x3T{xi}', {'f0': (({'f0': ('i', 1)}, (3,)), 1)}) + self._check('^x3T{xi}', {'f0': (({'f0': ('i', 1)}, (3,)), 1)}) def test_trailing_padding(self): + # Trailing padding should be included self._check('ix', [('f0', 'i'), ('f1', 'V1')]) + def test_byteorder_inside_struct(self): + # The byte order after @T{=i} should be '=', not '@'. + # Check this by noting the absence of native alignment. + self._check('@T{^i}xi', {'f0': ({'f0': (np.int32, 0)}, 0), + 'f1': (np.int32, 5)}) + class TestNewBufferProtocol(object): def _check_roundtrip(self, obj): obj = np.asarray(obj) |