Kano001's picture
Upload 376 files
122d3ff verified
raw
history blame
10.1 kB
# This file is part of h5py, a Python interface to the HDF5 library.
#
# http://www.h5py.org
#
# Copyright 2008-2013 Andrew Collette and contributors
#
# License: Standard 3-clause BSD; see "license.txt" for full license terms
# and contributor agreement.
"""
Attribute data transfer testing module
Covers all data read/write and type-conversion operations for attributes.
"""
import numpy as np
from .common import TestCase, ut
import h5py
from h5py import h5a, h5s, h5t
from h5py import File
from h5py._hl.base import is_empty_dataspace
class BaseAttrs(TestCase):
def setUp(self):
self.f = File(self.mktemp(), 'w')
def tearDown(self):
if self.f:
self.f.close()
class TestScalar(BaseAttrs):
"""
Feature: Scalar types map correctly to array scalars
"""
def test_int(self):
""" Integers are read as correct NumPy type """
self.f.attrs['x'] = np.array(1, dtype=np.int8)
out = self.f.attrs['x']
self.assertIsInstance(out, np.int8)
def test_compound(self):
""" Compound scalars are read as numpy.void """
dt = np.dtype([('a', 'i'), ('b', 'f')])
data = np.array((1, 4.2), dtype=dt)
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertIsInstance(out, np.void)
self.assertEqual(out, data)
self.assertEqual(out['b'], data['b'])
def test_compound_with_vlen_fields(self):
""" Compound scalars with vlen fields can be written and read """
dt = np.dtype([('a', h5py.vlen_dtype(np.int32)),
('b', h5py.vlen_dtype(np.int32))])
data = np.array((np.array(list(range(1, 5)), dtype=np.int32),
np.array(list(range(8, 10)), dtype=np.int32)), dtype=dt)[()]
self.f.attrs['x'] = data
out = self.f.attrs['x']
# Specifying check_alignment=False because vlen fields have 8 bytes of padding
# because the vlen datatype in hdf5 occupies 16 bytes
self.assertArrayEqual(out, data, check_alignment=False)
def test_nesting_compound_with_vlen_fields(self):
""" Compound scalars with nested compound vlen fields can be written and read """
dt_inner = np.dtype([('a', h5py.vlen_dtype(np.int32)),
('b', h5py.vlen_dtype(np.int32))])
dt = np.dtype([('f1', h5py.vlen_dtype(dt_inner)),
('f2', np.int64)])
inner1 = (np.array(range(1, 3), dtype=np.int32),
np.array(range(6, 9), dtype=np.int32))
inner2 = (np.array(range(10, 14), dtype=np.int32),
np.array(range(16, 20), dtype=np.int32))
data = np.array((np.array([inner1, inner2], dtype=dt_inner),
2),
dtype=dt)[()]
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertArrayEqual(out, data, check_alignment=False)
def test_vlen_compound_with_vlen_string(self):
""" Compound scalars with vlen compounds containing vlen strings can be written and read """
dt_inner = np.dtype([('a', h5py.string_dtype()),
('b', h5py.string_dtype())])
dt = np.dtype([('f', h5py.vlen_dtype(dt_inner))])
data = np.array((np.array([(b"apples", b"bananas"), (b"peaches", b"oranges")], dtype=dt_inner),),dtype=dt)[()]
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertArrayEqual(out, data, check_alignment=False)
class TestArray(BaseAttrs):
"""
Feature: Non-scalar types are correctly retrieved as ndarrays
"""
def test_single(self):
""" Single-element arrays are correctly recovered """
data = np.ndarray((1,), dtype='f')
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, (1,))
def test_multi(self):
""" Rank-1 arrays are correctly recovered """
data = np.ndarray((42,), dtype='f')
data[:] = 42.0
data[10:35] = -47.0
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, (42,))
self.assertArrayEqual(out, data)
class TestTypes(BaseAttrs):
"""
Feature: All supported types can be stored in attributes
"""
def test_int(self):
""" Storage of integer types """
dtypes = (np.int8, np.int16, np.int32, np.int64,
np.uint8, np.uint16, np.uint32, np.uint64)
for dt in dtypes:
data = np.ndarray((1,), dtype=dt)
data[...] = 42
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertEqual(out.dtype, dt)
self.assertArrayEqual(out, data)
def test_float(self):
""" Storage of floating point types """
dtypes = tuple(np.dtype(x) for x in ('<f4', '>f4', '>f8', '<f8'))
for dt in dtypes:
data = np.ndarray((1,), dtype=dt)
data[...] = 42.3
self.f.attrs['x'] = data
out = self.f.attrs['x']
# TODO: Clean up after issue addressed !
print("dtype: ", out.dtype, dt)
print("value: ", out, data)
self.assertEqual(out.dtype, dt)
self.assertArrayEqual(out, data)
def test_complex(self):
""" Storage of complex types """
dtypes = tuple(np.dtype(x) for x in ('<c8', '>c8', '<c16', '>c16'))
for dt in dtypes:
data = np.ndarray((1,), dtype=dt)
data[...] = -4.2j + 35.9
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertEqual(out.dtype, dt)
self.assertArrayEqual(out, data)
def test_string(self):
""" Storage of fixed-length strings """
dtypes = tuple(np.dtype(x) for x in ('|S1', '|S10'))
for dt in dtypes:
data = np.ndarray((1,), dtype=dt)
data[...] = 'h'
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertEqual(out.dtype, dt)
self.assertEqual(out[0], data[0])
def test_bool(self):
""" Storage of NumPy booleans """
data = np.ndarray((2,), dtype=np.bool_)
data[...] = True, False
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertEqual(out.dtype, data.dtype)
self.assertEqual(out[0], data[0])
self.assertEqual(out[1], data[1])
def test_vlen_string_array(self):
""" Storage of vlen byte string arrays"""
dt = h5py.string_dtype(encoding='ascii')
data = np.ndarray((2,), dtype=dt)
data[...] = "Hello", "Hi there! This is HDF5!"
self.f.attrs['x'] = data
out = self.f.attrs['x']
self.assertEqual(out.dtype, dt)
self.assertEqual(out[0], data[0])
self.assertEqual(out[1], data[1])
def test_string_scalar(self):
""" Storage of variable-length byte string scalars (auto-creation) """
self.f.attrs['x'] = b'Hello'
out = self.f.attrs['x']
self.assertEqual(out, 'Hello')
self.assertEqual(type(out), str)
aid = h5py.h5a.open(self.f.id, b"x")
tid = aid.get_type()
self.assertEqual(type(tid), h5py.h5t.TypeStringID)
self.assertEqual(tid.get_cset(), h5py.h5t.CSET_ASCII)
self.assertTrue(tid.is_variable_str())
def test_unicode_scalar(self):
""" Storage of variable-length unicode strings (auto-creation) """
self.f.attrs['x'] = u"Hello" + chr(0x2340) + u"!!"
out = self.f.attrs['x']
self.assertEqual(out, u"Hello" + chr(0x2340) + u"!!")
self.assertEqual(type(out), str)
aid = h5py.h5a.open(self.f.id, b"x")
tid = aid.get_type()
self.assertEqual(type(tid), h5py.h5t.TypeStringID)
self.assertEqual(tid.get_cset(), h5py.h5t.CSET_UTF8)
self.assertTrue(tid.is_variable_str())
class TestEmpty(BaseAttrs):
def setUp(self):
BaseAttrs.setUp(self)
sid = h5s.create(h5s.NULL)
tid = h5t.C_S1.copy()
tid.set_size(10)
aid = h5a.create(self.f.id, b'x', tid, sid)
self.empty_obj = h5py.Empty(np.dtype("S10"))
def test_read(self):
self.assertEqual(
self.empty_obj, self.f.attrs['x']
)
def test_write(self):
self.f.attrs["y"] = self.empty_obj
self.assertTrue(is_empty_dataspace(h5a.open(self.f.id, b'y')))
def test_modify(self):
with self.assertRaises(OSError):
self.f.attrs.modify('x', 1)
def test_values(self):
# list() is for Py3 where these are iterators
values = list(self.f.attrs.values())
self.assertEqual(
[self.empty_obj], values
)
def test_items(self):
items = list(self.f.attrs.items())
self.assertEqual(
[(u"x", self.empty_obj)], items
)
def test_itervalues(self):
values = list(self.f.attrs.values())
self.assertEqual(
[self.empty_obj], values
)
def test_iteritems(self):
items = list(self.f.attrs.items())
self.assertEqual(
[(u"x", self.empty_obj)], items
)
class TestWriteException(BaseAttrs):
"""
Ensure failed attribute writes don't leave garbage behind.
"""
def test_write(self):
""" ValueError on string write wipes out attribute """
s = b"Hello\x00Hello"
try:
self.f.attrs['x'] = s
except ValueError:
pass
with self.assertRaises(KeyError):
self.f.attrs['x']