Import tensorflow

This commit is contained in:
2026-02-15 21:45:42 -08:00
parent f3e8b90764
commit c530630153
20524 changed files with 9017694 additions and 25 deletions
@@ -0,0 +1,21 @@
# 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.
import sys
import shlex
from importlib.util import find_spec
from subprocess import call
def run_tests(args=''):
if find_spec("pytest") is None:
print("Tests require pytest, pytest not installed")
return 1
cli = [sys.executable, "-m", "pytest", "--pyargs", "h5py"]
cli.extend(shlex.split(args))
return call(cli)
@@ -0,0 +1,238 @@
# 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.
import sys
import os
import shutil
import inspect
import tempfile
import subprocess
from contextlib import contextmanager
from functools import wraps
import numpy as np
from numpy.lib.recfunctions import repack_fields
import h5py
import unittest as ut
# Check if non-ascii filenames are supported
# Evidently this is the most reliable way to check
# See also h5py issue #263 and ipython #466
# To test for this, run the testsuite with LC_ALL=C
try:
testfile, fname = tempfile.mkstemp(chr(0x03b7))
except UnicodeError:
UNICODE_FILENAMES = False
else:
UNICODE_FILENAMES = True
os.close(testfile)
os.unlink(fname)
del fname
del testfile
class TestCase(ut.TestCase):
"""
Base class for unit tests.
"""
@classmethod
def setUpClass(cls):
cls.tempdir = tempfile.mkdtemp(prefix='h5py-test_')
@classmethod
def tearDownClass(cls):
shutil.rmtree(cls.tempdir)
def mktemp(self, suffix='.hdf5', prefix='', dir=None):
if dir is None:
dir = self.tempdir
return tempfile.mktemp(suffix, prefix, dir=dir)
def mktemp_mpi(self, comm=None, suffix='.hdf5', prefix='', dir=None):
if comm is None:
from mpi4py import MPI
comm = MPI.COMM_WORLD
fname = None
if comm.Get_rank() == 0:
fname = self.mktemp(suffix, prefix, dir)
fname = comm.bcast(fname, 0)
return fname
def setUp(self):
self.f = h5py.File(self.mktemp(), 'w')
def tearDown(self):
try:
if self.f:
self.f.close()
except:
pass
def assertSameElements(self, a, b):
for x in a:
match = False
for y in b:
if x == y:
match = True
if not match:
raise AssertionError("Item '%s' appears in a but not b" % x)
for x in b:
match = False
for y in a:
if x == y:
match = True
if not match:
raise AssertionError("Item '%s' appears in b but not a" % x)
def assertArrayEqual(self, dset, arr, message=None, precision=None, check_alignment=True):
""" Make sure dset and arr have the same shape, dtype and contents, to
within the given precision, optionally ignoring differences in dtype alignment.
Note that dset may be a NumPy array or an HDF5 dataset.
"""
if precision is None:
precision = 1e-5
if message is None:
message = ''
else:
message = ' (%s)' % message
if np.isscalar(dset) or np.isscalar(arr):
assert np.isscalar(dset) and np.isscalar(arr), \
'Scalar/array mismatch ("%r" vs "%r")%s' % (dset, arr, message)
dset = np.asarray(dset)
arr = np.asarray(arr)
assert dset.shape == arr.shape, \
"Shape mismatch (%s vs %s)%s" % (dset.shape, arr.shape, message)
if dset.dtype != arr.dtype:
if check_alignment:
normalized_dset_dtype = dset.dtype
normalized_arr_dtype = arr.dtype
else:
normalized_dset_dtype = repack_fields(dset.dtype)
normalized_arr_dtype = repack_fields(arr.dtype)
assert normalized_dset_dtype == normalized_arr_dtype, \
"Dtype mismatch (%s vs %s)%s" % (normalized_dset_dtype, normalized_arr_dtype, message)
if not check_alignment:
if normalized_dset_dtype != dset.dtype:
dset = repack_fields(np.asarray(dset))
if normalized_arr_dtype != arr.dtype:
arr = repack_fields(np.asarray(arr))
if arr.dtype.names is not None:
for n in arr.dtype.names:
message = '[FIELD %s] %s' % (n, message)
self.assertArrayEqual(dset[n], arr[n], message=message, precision=precision, check_alignment=check_alignment)
elif arr.dtype.kind in ('i', 'f'):
assert np.all(np.abs(dset[...] - arr[...]) < precision), \
"Arrays differ by more than %.3f%s" % (precision, message)
elif arr.dtype.kind == 'O':
for v1, v2 in zip(dset.flat, arr.flat, strict=True):
self.assertArrayEqual(v1, v2, message=message, precision=precision, check_alignment=check_alignment)
else:
assert np.all(dset[...] == arr[...]), \
"Arrays are not equal (dtype %s) %s" % (arr.dtype.str, message)
def assertNumpyBehavior(self, dset, arr, s, skip_fast_reader=False):
""" Apply slicing arguments "s" to both dset and arr.
Succeeds if the results of the slicing are identical, or the
exception raised is of the same type for both.
"arr" must be a Numpy array; "dset" may be a NumPy array or dataset.
"""
exc = None
try:
arr_result = arr[s]
except Exception as e:
exc = type(e)
s_fast = s if isinstance(s, tuple) else (s,)
if exc is None:
self.assertArrayEqual(dset[s], arr_result)
if not skip_fast_reader:
self.assertArrayEqual(
dset._fast_reader.read(s_fast),
arr_result,
)
else:
with self.assertRaises(exc):
dset[s]
if not skip_fast_reader:
with self.assertRaises(exc):
dset._fast_reader.read(s_fast)
NUMPY_RELEASE_VERSION = tuple([int(i) for i in np.__version__.split(".")[0:2]])
@contextmanager
def closed_tempfile(suffix='', text=None):
"""
Context manager which yields the path to a closed temporary file with the
suffix `suffix`. The file will be deleted on exiting the context. An
additional argument `text` can be provided to have the file contain `text`.
"""
with tempfile.NamedTemporaryFile(
'w+t', suffix=suffix, delete=False
) as test_file:
file_name = test_file.name
if text is not None:
test_file.write(text)
test_file.flush()
yield file_name
shutil.rmtree(file_name, ignore_errors=True)
def insubprocess(f):
"""Runs a test in its own subprocess"""
@wraps(f)
def wrapper(request, *args, **kwargs):
curr_test = inspect.getsourcefile(f) + "::" + request.node.name
# get block around test name
insub = "IN_SUBPROCESS_" + curr_test
for c in "/\\,:.":
insub = insub.replace(c, "_")
defined = os.environ.get(insub, None)
# fork process
if defined:
return f(request, *args, **kwargs)
else:
os.environ[insub] = '1'
env = os.environ.copy()
env[insub] = '1'
env.update(getattr(f, 'subproc_env', {}))
with closed_tempfile() as stdout:
with open(stdout, 'w+t') as fh:
rtn = subprocess.call([sys.executable, '-m', 'pytest', curr_test],
stdout=fh, stderr=fh, env=env)
with open(stdout, 'rt') as fh:
out = fh.read()
assert rtn == 0, "\n" + out
return wrapper
def subproc_env(d):
"""Set environment variables for the @insubprocess decorator"""
def decorator(f):
f.subproc_env = d
return f
return decorator
@@ -0,0 +1,22 @@
import h5py
import pytest
@pytest.fixture()
def writable_file(tmp_path):
with h5py.File(tmp_path / 'test.h5', 'w') as f:
yield f
def pytest_addoption(parser):
parser.addoption(
'--no-network', action='store_true', default=False, help='No network access'
)
def pytest_collection_modifyitems(config, items):
if config.getoption('--no-network'):
nonet = pytest.mark.skip(reason='No Internet')
for item in items:
if 'network' in item.keywords:
item.add_marker(nonet)
@@ -0,0 +1,7 @@
from os.path import dirname, join
def get_data_file_path(basename):
"""
Returns the path to the test data file given by `basename`
"""
return join(dirname(__file__), basename)
@@ -0,0 +1,95 @@
# 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.
"""
Tests the h5py.AttributeManager.create() method.
"""
import numpy as np
from .. import h5t, h5a
from .common import TestCase
class TestArray(TestCase):
"""
Check that top-level array types can be created and read.
"""
def test_int(self):
# See issue 498
dt = np.dtype('(3,)i')
data = np.arange(3, dtype='i')
self.f.attrs.create('x', data=data, dtype=dt)
aid = h5a.open(self.f.id, b'x')
htype = aid.get_type()
self.assertEqual(htype.get_class(), h5t.ARRAY)
out = self.f.attrs['x']
self.assertArrayEqual(out, data)
def test_string_dtype(self):
# See issue 498 discussion
self.f.attrs.create('x', data=42, dtype='i8')
def test_str(self):
# See issue 1057
self.f.attrs.create('x', chr(0x03A9))
out = self.f.attrs['x']
self.assertEqual(out, chr(0x03A9))
self.assertIsInstance(out, str)
def test_tuple_of_unicode(self):
# Test that a tuple of unicode strings can be set as an attribute. It will
# be converted to a numpy array of vlen unicode type:
data = ('a', 'b')
self.f.attrs.create('x', data=data)
result = self.f.attrs['x']
self.assertTrue(all(result == data))
self.assertEqual(result.dtype, np.dtype('O'))
# However, a numpy array of type U being passed in will not be
# automatically converted, and should raise an error as it does
# not map to a h5py dtype
data_as_U_array = np.array(data)
self.assertEqual(data_as_U_array.dtype, np.dtype('U1'))
with self.assertRaises(TypeError):
self.f.attrs.create('y', data=data_as_U_array)
def test_shape(self):
self.f.attrs.create('x', data=42, shape=1)
result = self.f.attrs['x']
self.assertEqual(result.shape, (1,))
self.f.attrs.create('y', data=np.arange(3), shape=3)
result = self.f.attrs['y']
self.assertEqual(result.shape, (3,))
def test_dtype(self):
dt = np.dtype('(3,)i')
array = np.arange(3, dtype='i')
self.f.attrs.create('x', data=array, dtype=dt)
# Array dtype shape is incompatible with data shape
array = np.arange(4, dtype='i')
with self.assertRaises(ValueError):
self.f.attrs.create('x', data=array, dtype=dt)
# Shape of new attribute conflicts with shape of data
dt = np.dtype('()i')
with self.assertRaises(ValueError):
self.f.attrs.create('x', data=array, shape=(5,), dtype=dt)
def test_key_type(self):
with self.assertRaises(TypeError):
self.f.attrs.create(1, data=('a', 'b'))
@@ -0,0 +1,299 @@
# 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.
"""
Attributes testing module
Covers all operations which access the .attrs property, with the
exception of data read/write and type conversion. Those operations
are tested by module test_attrs_data.
"""
import numpy as np
from collections.abc import MutableMapping
from .common import TestCase
import h5py
from h5py import File
from h5py import h5a, h5t
from h5py import AttributeManager
class BaseAttrs(TestCase):
def setUp(self):
self.f = File(self.mktemp(), 'w')
def tearDown(self):
if self.f:
self.f.close()
class TestRepr(TestCase):
""" Feature: AttributeManager provide a helpful
__repr__ string
"""
def test_repr(self):
grp = self.f.create_group('grp')
grp.attrs.create('att', 1)
self.assertIsInstance(repr(grp.attrs), str)
grp.id.close()
self.assertIsInstance(repr(grp.attrs), str)
class TestAccess(BaseAttrs):
"""
Feature: Attribute creation/retrieval via special methods
"""
def test_create(self):
""" Attribute creation by direct assignment """
self.f.attrs['a'] = 4.0
self.assertEqual(list(self.f.attrs.keys()), ['a'])
self.assertEqual(self.f.attrs['a'], 4.0)
def test_create_2(self):
""" Attribute creation by create() method """
self.f.attrs.create('a', 4.0)
self.assertEqual(list(self.f.attrs.keys()), ['a'])
self.assertEqual(self.f.attrs['a'], 4.0)
def test_modify(self):
""" Attributes are modified by direct assignment"""
self.f.attrs['a'] = 3
self.assertEqual(list(self.f.attrs.keys()), ['a'])
self.assertEqual(self.f.attrs['a'], 3)
self.f.attrs['a'] = 4
self.assertEqual(list(self.f.attrs.keys()), ['a'])
self.assertEqual(self.f.attrs['a'], 4)
def test_modify_2(self):
""" Attributes are modified by modify() method """
self.f.attrs.modify('a',3)
self.assertEqual(list(self.f.attrs.keys()), ['a'])
self.assertEqual(self.f.attrs['a'], 3)
self.f.attrs.modify('a', 4)
self.assertEqual(list(self.f.attrs.keys()), ['a'])
self.assertEqual(self.f.attrs['a'], 4)
# If the attribute doesn't exist, create new
self.f.attrs.modify('b', 5)
self.assertEqual(list(self.f.attrs.keys()), ['a', 'b'])
self.assertEqual(self.f.attrs['a'], 4)
self.assertEqual(self.f.attrs['b'], 5)
# Shape of new value is incompatible with the previous
new_value = np.arange(5)
with self.assertRaises(TypeError):
self.f.attrs.modify('b', new_value)
def test_overwrite(self):
""" Attributes are silently overwritten """
self.f.attrs['a'] = 4.0
self.f.attrs['a'] = 5.0
self.assertEqual(self.f.attrs['a'], 5.0)
def test_rank(self):
""" Attribute rank is preserved """
self.f.attrs['a'] = (4.0, 5.0)
self.assertEqual(self.f.attrs['a'].shape, (2,))
self.assertArrayEqual(self.f.attrs['a'], np.array((4.0,5.0)))
def test_single(self):
""" Attributes of shape (1,) don't become scalars """
self.f.attrs['a'] = np.ones((1,))
out = self.f.attrs['a']
self.assertEqual(out.shape, (1,))
self.assertEqual(out[()], 1)
def test_access_exc(self):
""" Attempt to access missing item raises KeyError """
with self.assertRaises(KeyError):
self.f.attrs['a']
def test_get_id(self):
self.f.attrs['a'] = 4.0
aid = self.f.attrs.get_id('a')
assert isinstance(aid, h5a.AttrID)
with self.assertRaises(KeyError):
self.f.attrs.get_id('b')
class TestDelete(BaseAttrs):
"""
Feature: Deletion of attributes using __delitem__
"""
def test_delete(self):
""" Deletion via "del" """
self.f.attrs['a'] = 4.0
self.assertIn('a', self.f.attrs)
del self.f.attrs['a']
self.assertNotIn('a', self.f.attrs)
def test_delete_exc(self):
""" Attempt to delete missing item raises KeyError """
with self.assertRaises(KeyError):
del self.f.attrs['a']
class TestUnicode(BaseAttrs):
"""
Feature: Attributes can be accessed via Unicode or byte strings
"""
def test_ascii(self):
""" Access via pure-ASCII byte string """
self.f.attrs[b"ascii"] = 42
out = self.f.attrs[b"ascii"]
self.assertEqual(out, 42)
def test_raw(self):
""" Access via non-ASCII byte string """
name = b"non-ascii\xfe"
self.f.attrs[name] = 42
out = self.f.attrs[name]
self.assertEqual(out, 42)
def test_unicode(self):
""" Access via Unicode string with non-ascii characters """
name = "Omega" + chr(0x03A9)
self.f.attrs[name] = 42
out = self.f.attrs[name]
self.assertEqual(out, 42)
class TestCreate(BaseAttrs):
"""
Options for explicit attribute creation
"""
def test_named(self):
""" Attributes created from named types link to the source type object
"""
self.f['type'] = np.dtype('u8')
self.f.attrs.create('x', 42, dtype=self.f['type'])
self.assertEqual(self.f.attrs['x'], 42)
aid = h5a.open(self.f.id, b'x')
htype = aid.get_type()
htype2 = self.f['type'].id
self.assertEqual(htype, htype2)
self.assertTrue(htype.committed())
def test_empty(self):
# https://github.com/h5py/h5py/issues/1540
""" Create attribute with h5py.Empty value
"""
self.f.attrs.create('empty', h5py.Empty('f'))
self.assertEqual(self.f.attrs['empty'], h5py.Empty('f'))
self.f.attrs.create('empty', h5py.Empty(None))
self.assertEqual(self.f.attrs['empty'], h5py.Empty(None))
class TestMutableMapping(BaseAttrs):
'''Tests if the registration of AttributeManager as a MutableMapping
behaves as expected
'''
def test_resolution(self):
assert issubclass(AttributeManager, MutableMapping)
assert isinstance(self.f.attrs, MutableMapping)
def test_validity(self):
'''
Test that the required functions are implemented.
'''
AttributeManager.__getitem__
AttributeManager.__setitem__
AttributeManager.__delitem__
AttributeManager.__iter__
AttributeManager.__len__
class TestVlen(BaseAttrs):
def test_vlen(self):
a = np.array([np.arange(3), np.arange(4)],
dtype=h5t.vlen_dtype(int))
self.f.attrs['a'] = a
self.assertArrayEqual(self.f.attrs['a'][0], a[0])
def test_vlen_s1(self):
dt = h5py.vlen_dtype(np.dtype('S1'))
a = np.empty((1,), dtype=dt)
a[0] = np.array([b'a', b'b'], dtype='S1')
self.f.attrs.create('test', a)
self.assertArrayEqual(self.f.attrs['test'][0], a[0])
class TestTrackOrder(BaseAttrs):
def fill_attrs(self, track_order):
attrs = self.f.create_group('test', track_order=track_order).attrs
for i in range(100):
attrs[str(i)] = i
return attrs
# https://forum.hdfgroup.org/t/bug-h5arename-fails-unexpectedly/4881
def test_track_order(self):
attrs = self.fill_attrs(track_order=True) # creation order
self.assertEqual(list(attrs),
[str(i) for i in range(100)])
def test_no_track_order(self):
attrs = self.fill_attrs(track_order=False) # name alphanumeric
self.assertEqual(list(attrs),
sorted([str(i) for i in range(100)]))
def fill_attrs2(self, track_order):
group = self.f.create_group('test', track_order=track_order)
for i in range(12):
group.attrs[str(i)] = i
return group
def test_track_order_overwrite_delete(self):
# issue 1385
group = self.fill_attrs2(track_order=True) # creation order
self.assertEqual(group.attrs["11"], 11)
# overwrite attribute
group.attrs['11'] = 42.0
self.assertEqual(group.attrs["11"], 42.0)
# delete attribute
self.assertIn('10', group.attrs)
del group.attrs['10']
self.assertNotIn('10', group.attrs)
class TestDatatype(BaseAttrs):
def test_datatype(self):
self.f['foo'] = np.dtype('f')
dt = self.f['foo']
self.assertEqual(list(dt.attrs.keys()), [])
dt.attrs.create('a', 4.0)
self.assertEqual(list(dt.attrs.keys()), ['a'])
self.assertEqual(list(dt.attrs.values()), [4.0])
def test_python_int_uint64(writable_file):
f = writable_file
data = [np.iinfo(np.int64).max, np.iinfo(np.int64).max + 1]
# Check creating a new attribute
f.attrs.create('a', data, dtype=np.uint64)
assert f.attrs['a'].dtype == np.dtype(np.uint64)
np.testing.assert_array_equal(f.attrs['a'], np.array(data, dtype=np.uint64))
# Check modifying an existing attribute
f.attrs.modify('a', data)
np.testing.assert_array_equal(f.attrs['a'], np.array(data, dtype=np.uint64))
@@ -0,0 +1,311 @@
# 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
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']
@@ -0,0 +1,146 @@
# 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.
"""
Common high-level operations test
Tests features common to all high-level objects, like the .name property.
"""
from h5py import File
from h5py._hl.base import is_hdf5, Empty
from .common import ut, TestCase, UNICODE_FILENAMES
import numpy as np
import os
import tempfile
class BaseTest(TestCase):
def setUp(self):
self.f = File(self.mktemp(), 'w')
def tearDown(self):
if self.f:
self.f.close()
class TestName(BaseTest):
"""
Feature: .name attribute returns the object name
"""
def test_anonymous(self):
""" Anonymous objects have name None """
grp = self.f.create_group(None)
self.assertIs(grp.name, None)
class TestParent(BaseTest):
"""
test the parent group of the high-level interface objects
"""
def test_object_parent(self):
# Anonymous objects
grp = self.f.create_group(None)
# Parent of an anonymous object is undefined
with self.assertRaises(ValueError):
grp.parent
# Named objects
grp = self.f.create_group("bar")
sub_grp = grp.create_group("foo")
parent = sub_grp.parent.name
self.assertEqual(parent, "/bar")
class TestMapping(BaseTest):
"""
Test if the registration of Group as a
Mapping behaves as expected
"""
def setUp(self):
super().setUp()
data = ('a', 'b')
self.grp = self.f.create_group('bar')
self.attr = self.f.attrs.create('x', data)
def test_keys(self):
key_1 = self.f.keys()
self.assertIsInstance(repr(key_1), str)
key_2 = self.grp.keys()
self.assertIsInstance(repr(key_2), str)
def test_values(self):
value_1 = self.f.values()
self.assertIsInstance(repr(value_1), str)
value_2 = self.grp.values()
self.assertIsInstance(repr(value_2), str)
def test_items(self):
item_1 = self.f.items()
self.assertIsInstance(repr(item_1), str)
item_2 = self.grp.items()
self.assertIsInstance(repr(item_1), str)
class TestRepr(BaseTest):
"""
repr() works correctly with Unicode names
"""
USTRING = chr(0xfc) + chr(0xdf)
def _check_type(self, obj):
self.assertIsInstance(repr(obj), str)
def test_group(self):
""" Group repr() with unicode """
grp = self.f.create_group(self.USTRING)
self._check_type(grp)
def test_dataset(self):
""" Dataset repr() with unicode """
dset = self.f.create_dataset(self.USTRING, (1,))
self._check_type(dset)
def test_namedtype(self):
""" Named type repr() with unicode """
self.f['type'] = np.dtype('f')
typ = self.f['type']
self._check_type(typ)
def test_empty(self):
data = Empty(dtype='f')
self.assertNotEqual(Empty(dtype='i'), data)
self._check_type(data)
@ut.skipIf(not UNICODE_FILENAMES, "Filesystem unicode support required")
def test_file(self):
""" File object repr() with unicode """
fname = tempfile.mktemp(self.USTRING+'.hdf5')
try:
with File(fname,'w') as f:
self._check_type(f)
finally:
try:
os.unlink(fname)
except Exception:
pass
def test_is_hdf5():
filename = File(tempfile.mktemp(), "w").filename
assert is_hdf5(filename)
# non-existing HDF5 file
filename = tempfile.mktemp()
assert not is_hdf5(filename)
@@ -0,0 +1,49 @@
import numpy as np
from h5py import File
from .common import TestCase
from .data_files import get_data_file_path
def test_vlen_big_endian():
with File(get_data_file_path("vlen_string_s390x.h5")) as f:
assert f.attrs["created_on_s390x"] == 1
dset = f["DSvariable"]
assert dset[0] == b"Parting"
assert dset[1] == b"is such"
assert dset[2] == b"sweet"
assert dset[3] == b"sorrow..."
dset = f["DSLEfloat"]
assert dset[0] == 3.14
assert dset[1] == 1.61
assert dset[2] == 2.71
assert dset[3] == 2.41
assert dset[4] == 1.2
assert dset.dtype == "<f8"
# Same float values with big endianness
assert f["DSBEfloat"][0] == 3.14
assert f["DSBEfloat"].dtype == ">f8"
assert f["DSLEint"][0] == 1
assert f["DSLEint"].dtype == "<u8"
# Same int values with big endianness
assert f["DSBEint"][0] == 1
assert f["DSBEint"].dtype == ">i8"
class TestEndianess(TestCase):
def test_simple_int_be(self):
fname = self.mktemp()
arr = np.ndarray(shape=(1,), dtype=">i4", buffer=bytearray([0, 1, 3, 2]))
be_number = 0 * 256 ** 3 + 1 * 256 ** 2 + 3 * 256 ** 1 + 2 * 256 ** 0
with File(fname, mode="w") as f:
f.create_dataset("int", data=arr)
with File(fname, mode="r") as f:
assert f["int"][()][0] == be_number
@@ -0,0 +1,52 @@
from .common import TestCase
class TestCompletions(TestCase):
def test_group_completions(self):
# Test completions on top-level file.
g = self.f.create_group('g')
self.f.create_group('h')
self.f.create_dataset('data', [1, 2, 3])
self.assertEqual(
self.f._ipython_key_completions_(),
['data', 'g', 'h'],
)
self.f.create_group('data2', [1, 2, 3])
self.assertEqual(
self.f._ipython_key_completions_(),
['data', 'data2', 'g', 'h'],
)
# Test on subgroup.
g.create_dataset('g_data1', [1, 2, 3])
g.create_dataset('g_data2', [4, 5, 6])
self.assertEqual(
g._ipython_key_completions_(),
['g_data1', 'g_data2'],
)
g.create_dataset('g_data3', [7, 8, 9])
self.assertEqual(
g._ipython_key_completions_(),
['g_data1', 'g_data2', 'g_data3'],
)
def test_attrs_completions(self):
attrs = self.f.attrs
# Write out of alphabetical order to test that completions come back in
# alphabetical order, as opposed to, say, insertion order.
attrs['b'] = 1
attrs['a'] = 2
self.assertEqual(
attrs._ipython_key_completions_(),
['a', 'b']
)
attrs['c'] = 3
self.assertEqual(
attrs._ipython_key_completions_(),
['a', 'b', 'c']
)
@@ -0,0 +1,618 @@
# 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.
"""
Tests the h5py.Dataset.__getitem__ method.
This module does not specifically test type conversion. The "type" axis
therefore only tests objects which interact with the slicing system in
unreliable ways; for example, compound and array types.
See test_dataset_getitem_types for type-conversion tests.
Tests are organized into TestCases by dataset shape and type. Test
methods vary by slicing arg type.
1. Dataset shape:
Empty
Scalar
1D
3D
2. Type:
Float
Compound
Array
3. Slicing arg types:
Ellipsis
Empty tuple
Regular slice
MultiBlockSlice
Indexing
Index list
Boolean mask
Field names
"""
import sys
import numpy as np
import h5py
from .common import ut, TestCase
class TestEmpty(TestCase):
def setUp(self):
TestCase.setUp(self)
sid = h5py.h5s.create(h5py.h5s.NULL)
tid = h5py.h5t.C_S1.copy()
tid.set_size(10)
dsid = h5py.h5d.create(self.f.id, b'x', tid, sid)
self.dset = h5py.Dataset(dsid)
self.empty_obj = h5py.Empty(np.dtype("S10"))
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 0)
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, None)
def test_size(self):
""" Verify shape """
self.assertEqual(self.dset.size, None)
def test_nbytes(self):
""" Verify nbytes """
self.assertEqual(self.dset.nbytes, 0)
def test_ellipsis(self):
self.assertEqual(self.dset[...], self.empty_obj)
def test_tuple(self):
self.assertEqual(self.dset[()], self.empty_obj)
def test_slice(self):
""" slice -> ValueError """
with self.assertRaises(ValueError):
self.dset[0:4]
def test_multi_block_slice(self):
""" MultiBlockSlice -> ValueError """
with self.assertRaises(ValueError):
self.dset[h5py.MultiBlockSlice()]
def test_index(self):
""" index -> ValueError """
with self.assertRaises(ValueError):
self.dset[0]
def test_indexlist(self):
""" index list -> ValueError """
with self.assertRaises(ValueError):
self.dset[[1,2,5]]
def test_mask(self):
""" mask -> ValueError """
mask = np.array(True, dtype='bool')
with self.assertRaises(ValueError):
self.dset[mask]
def test_fieldnames(self):
""" field name -> ValueError """
with self.assertRaises(ValueError):
self.dset['field']
class TestScalarFloat(TestCase):
def setUp(self):
TestCase.setUp(self)
self.data = np.array(42.5, dtype=np.double)
self.dset = self.f.create_dataset('x', data=self.data)
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 0)
def test_size(self):
""" Verify size """
self.assertEqual(self.dset.size, 1)
def test_nbytes(self):
""" Verify nbytes """
self.assertEqual(self.dset.nbytes, self.data.dtype.itemsize) # not sure if 'f' is always alias for 'f4'
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, tuple())
def test_ellipsis(self):
""" Ellipsis -> scalar ndarray """
out = self.dset[...]
self.assertArrayEqual(out, self.data)
def test_tuple(self):
""" () -> bare item """
out = self.dset[()]
self.assertArrayEqual(out, self.data.item())
def test_slice(self):
""" slice -> ValueError """
with self.assertRaises(ValueError):
self.dset[0:4]
def test_multi_block_slice(self):
""" MultiBlockSlice -> ValueError """
with self.assertRaises(ValueError):
self.dset[h5py.MultiBlockSlice()]
def test_index(self):
""" index -> ValueError """
with self.assertRaises(ValueError):
self.dset[0]
# FIXME: NumPy has IndexError instead
def test_indexlist(self):
""" index list -> ValueError """
with self.assertRaises(ValueError):
self.dset[[1,2,5]]
# FIXME: NumPy permits this
def test_mask(self):
""" mask -> ValueError """
mask = np.array(True, dtype='bool')
with self.assertRaises(ValueError):
self.dset[mask]
def test_fieldnames(self):
""" field name -> ValueError (no fields) """
with self.assertRaises(ValueError):
self.dset['field']
class TestScalarCompound(TestCase):
def setUp(self):
TestCase.setUp(self)
self.data = np.array((42.5, -118, "Hello"), dtype=[('a', 'f'), ('b', 'i'), ('c', '|S10')])
self.dset = self.f.create_dataset('x', data=self.data)
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 0)
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, tuple())
def test_size(self):
""" Verify size """
self.assertEqual(self.dset.size, 1)
def test_nbytes(self):
""" Verify nbytes """
self.assertEqual(self.dset.nbytes, self.data.dtype.itemsize)
def test_ellipsis(self):
""" Ellipsis -> scalar ndarray """
out = self.dset[...]
# assertArrayEqual doesn't work with compounds; do manually
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, self.data.shape)
self.assertEqual(out.dtype, self.data.dtype)
def test_tuple(self):
""" () -> np.void instance """
out = self.dset[()]
self.assertIsInstance(out, np.void)
self.assertEqual(out.dtype, self.data.dtype)
def test_slice(self):
""" slice -> ValueError """
with self.assertRaises(ValueError):
self.dset[0:4]
def test_multi_block_slice(self):
""" MultiBlockSlice -> ValueError """
with self.assertRaises(ValueError):
self.dset[h5py.MultiBlockSlice()]
def test_index(self):
""" index -> ValueError """
with self.assertRaises(ValueError):
self.dset[0]
# FIXME: NumPy has IndexError instead
def test_indexlist(self):
""" index list -> ValueError """
with self.assertRaises(ValueError):
self.dset[[1,2,5]]
# FIXME: NumPy permits this
def test_mask(self):
""" mask -> ValueError """
mask = np.array(True, dtype='bool')
with self.assertRaises(ValueError):
self.dset[mask]
# FIXME: NumPy returns a scalar ndarray
def test_fieldnames(self):
""" field name -> bare value """
out = self.dset['a']
self.assertIsInstance(out, np.float32)
self.assertEqual(out, self.dset['a'])
class TestScalarArray(TestCase):
def setUp(self):
TestCase.setUp(self)
self.dt = np.dtype('(3,2)f')
self.data = np.array([(3.2, -119), (42, 99.8), (3.14, 0)], dtype='f')
self.dset = self.f.create_dataset('x', (), dtype=self.dt)
self.dset[...] = self.data
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.data.ndim, 2)
self.assertEqual(self.dset.ndim, 0)
def test_size(self):
""" Verify size """
self.assertEqual(self.dset.size, 1)
def test_nbytes(self):
""" Verify nbytes """
self.assertEqual(self.dset.nbytes, self.dset.dtype.itemsize) # not sure if 'f' is always alias for 'f4'
def test_shape(self):
""" Verify shape """
self.assertEqual(self.data.shape, (3, 2))
self.assertEqual(self.dset.shape, tuple())
def test_ellipsis(self):
""" Ellipsis -> ndarray promoted to underlying shape """
out = self.dset[...]
self.assertArrayEqual(out, self.data)
def test_tuple(self):
""" () -> same as ellipsis """
out = self.dset[...]
self.assertArrayEqual(out, self.data)
def test_slice(self):
""" slice -> ValueError """
with self.assertRaises(ValueError):
self.dset[0:4]
def test_multi_block_slice(self):
""" MultiBlockSlice -> ValueError """
with self.assertRaises(ValueError):
self.dset[h5py.MultiBlockSlice()]
def test_index(self):
""" index -> ValueError """
with self.assertRaises(ValueError):
self.dset[0]
def test_indexlist(self):
""" index list -> ValueError """
with self.assertRaises(ValueError):
self.dset[[]]
def test_mask(self):
""" mask -> ValueError """
mask = np.array(True, dtype='bool')
with self.assertRaises(ValueError):
self.dset[mask]
def test_fieldnames(self):
""" field name -> ValueError (no fields) """
with self.assertRaises(ValueError):
self.dset['field']
class Test1DZeroFloat(TestCase):
def setUp(self):
TestCase.setUp(self)
self.data = np.ones((0,), dtype='f')
self.dset = self.f.create_dataset('x', data=self.data)
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 1)
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, (0,))
def test_ellipsis(self):
""" Ellipsis -> ndarray of matching shape """
self.assertNumpyBehavior(self.dset, self.data, np.s_[...])
def test_tuple(self):
""" () -> same as ellipsis """
self.assertNumpyBehavior(self.dset, self.data, np.s_[()])
def test_slice(self):
""" slice -> ndarray of shape (0,) """
self.assertNumpyBehavior(self.dset, self.data, np.s_[0:4])
def test_slice_stop_less_than_start(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[7:5])
def test_index(self):
""" index -> out of range """
with self.assertRaises(IndexError):
self.dset[0]
def test_indexlist(self):
""" index list """
self.assertNumpyBehavior(self.dset, self.data, np.s_[[]])
def test_mask(self):
""" mask -> ndarray of matching shape """
mask = np.ones((0,), dtype='bool')
self.assertNumpyBehavior(
self.dset,
self.data,
np.s_[mask],
# Fast reader doesn't work with boolean masks
skip_fast_reader=True,
)
def test_fieldnames(self):
""" field name -> ValueError (no fields) """
with self.assertRaises(ValueError):
self.dset['field']
class Test1DFloat(TestCase):
def setUp(self):
TestCase.setUp(self)
self.data = np.arange(13).astype('f')
self.dset = self.f.create_dataset('x', data=self.data)
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 1)
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, (13,))
def test_ellipsis(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[...])
def test_tuple(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[()])
def test_slice_simple(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[0:4])
def test_slice_zerosize(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[4:4])
def test_slice_strides(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[1:7:3])
def test_slice_negindexes(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[-8:-2:3])
def test_slice_stop_less_than_start(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[7:5])
def test_slice_outofrange(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[100:400:3])
def test_slice_backwards(self):
""" we disallow negative steps """
with self.assertRaises(ValueError):
self.dset[::-1]
def test_slice_zerostride(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[::0])
def test_index_simple(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[3])
def test_index_neg(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[-4])
# FIXME: NumPy permits this... it adds a new axis in front
def test_index_none(self):
with self.assertRaises(TypeError):
self.dset[None]
def test_index_illegal(self):
""" Illegal slicing argument """
with self.assertRaises(TypeError):
self.dset[{}]
def test_index_outofrange(self):
with self.assertRaises(IndexError):
self.dset[100]
def test_indexlist_simple(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[[1,2,5]])
def test_indexlist_numpyarray(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[np.array([1, 2, 5])])
def test_indexlist_single_index_ellipsis(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[[0], ...])
def test_indexlist_numpyarray_single_index_ellipsis(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[np.array([0]), ...])
def test_indexlist_numpyarray_ellipsis(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[np.array([1, 2, 5]), ...])
def test_indexlist_empty(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[[]])
def test_indexlist_outofrange(self):
with self.assertRaises(IndexError):
self.dset[[100]]
def test_indexlist_nonmonotonic(self):
""" we require index list values to be strictly increasing """
with self.assertRaises(TypeError):
self.dset[[1,3,2]]
def test_indexlist_monotonic_negative(self):
# This should work: indices are logically increasing
self.assertNumpyBehavior(self.dset, self.data, np.s_[[0, 2, -2]])
with self.assertRaises(TypeError):
self.dset[[-2, -3]]
def test_indexlist_repeated(self):
""" we forbid repeated index values """
with self.assertRaises(TypeError):
self.dset[[1,1,2]]
def test_mask_true(self):
self.assertNumpyBehavior(
self.dset,
self.data,
np.s_[self.data > -100],
# Fast reader doesn't work with boolean masks
skip_fast_reader=True,
)
def test_mask_false(self):
self.assertNumpyBehavior(
self.dset,
self.data,
np.s_[self.data > 100],
# Fast reader doesn't work with boolean masks
skip_fast_reader=True,
)
def test_mask_partial(self):
self.assertNumpyBehavior(
self.dset,
self.data,
np.s_[self.data > 5],
# Fast reader doesn't work with boolean masks
skip_fast_reader=True,
)
def test_mask_wrongsize(self):
""" we require the boolean mask shape to match exactly """
with self.assertRaises(TypeError):
self.dset[np.ones((2,), dtype='bool')]
def test_fieldnames(self):
""" field name -> ValueError (no fields) """
with self.assertRaises(ValueError):
self.dset['field']
class Test2DZeroFloat(TestCase):
def setUp(self):
TestCase.setUp(self)
self.data = np.ones((0,3), dtype='f')
self.dset = self.f.create_dataset('x', data=self.data)
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 2)
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, (0, 3))
def test_indexlist(self):
""" see issue #473 """
self.assertNumpyBehavior(self.dset, self.data, np.s_[:,[0,1,2]])
class Test2DFloat(TestCase):
def setUp(self):
TestCase.setUp(self)
self.data = np.ones((5,3), dtype='f')
self.dset = self.f.create_dataset('x', data=self.data)
def test_ndim(self):
""" Verify number of dimensions """
self.assertEqual(self.dset.ndim, 2)
def test_size(self):
""" Verify size """
self.assertEqual(self.dset.size, 15)
def test_nbytes(self):
""" Verify nbytes """
self.assertEqual(self.dset.nbytes, 15*self.data.dtype.itemsize) # not sure if 'f' is always alias for 'f4'
def test_shape(self):
""" Verify shape """
self.assertEqual(self.dset.shape, (5, 3))
def test_indexlist(self):
""" see issue #473 """
self.assertNumpyBehavior(self.dset, self.data, np.s_[:,[0,1,2]])
def test_index_emptylist(self):
self.assertNumpyBehavior(self.dset, self.data, np.s_[:, []])
self.assertNumpyBehavior(self.dset, self.data, np.s_[[]])
class TestVeryLargeArray(TestCase):
def setUp(self):
TestCase.setUp(self)
self.dset = self.f.create_dataset('x', shape=(2**15, 2**16))
@ut.skipIf(sys.maxsize < 2**31, 'Maximum integer size >= 2**31 required')
def test_size(self):
self.assertEqual(self.dset.size, 2**31)
def test_read_no_fill_value(writable_file):
# With FILL_TIME_NEVER, HDF5 doesn't write zeros in the output array for
# unallocated chunks. If we read into uninitialized memory, it can appear
# to read random values. https://github.com/h5py/h5py/issues/2069
dcpl = h5py.h5p.create(h5py.h5p.DATASET_CREATE)
dcpl.set_chunk((1,))
dcpl.set_fill_time(h5py.h5d.FILL_TIME_NEVER)
ds = h5py.Dataset(h5py.h5d.create(
writable_file.id, b'a', h5py.h5t.IEEE_F64LE, h5py.h5s.create_simple((5,)), dcpl
))
np.testing.assert_array_equal(ds[:3], np.zeros(3, np.float64))
class TestBoolIndex(TestCase):
"""
Tests for indexing with Boolean arrays
"""
def setUp(self):
super().setUp()
self.arr = np.arange(9).reshape(3,-1)
self.dset = self.f.create_dataset('x', data=self.arr)
def test_select_first_axis(self):
sel = np.s_[[False, True, False],:]
self.assertNumpyBehavior(self.dset, self.arr, sel)
def test_wrong_size(self):
sel = np.s_[[False, True, False, False],:]
with self.assertRaises(TypeError):
self.dset[sel]
@@ -0,0 +1,118 @@
import numpy as np
import h5py
from .common import TestCase
class TestDatasetSwmrRead(TestCase):
""" Testing SWMR functions when reading a dataset.
Skip this test if the HDF5 library does not have the SWMR features.
"""
def setUp(self):
TestCase.setUp(self)
self.data = np.arange(13).astype('f')
self.dset = self.f.create_dataset('data', chunks=(13,), maxshape=(None,), data=self.data)
fname = self.f.filename
self.f.close()
self.f = h5py.File(fname, 'r', swmr=True)
self.dset = self.f['data']
def test_initial_swmr_mode_on(self):
""" Verify that the file is initially in SWMR mode"""
self.assertTrue(self.f.swmr_mode)
def test_read_data(self):
self.assertArrayEqual(self.dset, self.data)
def test_refresh(self):
self.dset.refresh()
def test_force_swmr_mode_on_raises(self):
""" Verify when reading a file cannot be forcibly switched to swmr mode.
When reading with SWMR the file must be opened with swmr=True."""
with self.assertRaises(Exception):
self.f.swmr_mode = True
self.assertTrue(self.f.swmr_mode)
def test_force_swmr_mode_off_raises(self):
""" Switching SWMR write mode off is only possible by closing the file.
Attempts to forcibly switch off the SWMR mode should raise a ValueError.
"""
with self.assertRaises(ValueError):
self.f.swmr_mode = False
self.assertTrue(self.f.swmr_mode)
class TestDatasetSwmrWrite(TestCase):
""" Testing SWMR functions when reading a dataset.
Skip this test if the HDF5 library does not have the SWMR features.
"""
def setUp(self):
""" First setup a file with a small chunked and empty dataset.
No data written yet.
"""
# Note that when creating the file, the swmr=True is not required for
# write, but libver='latest' is required.
self.f = h5py.File(self.mktemp(), 'w', libver='latest')
self.data = np.arange(4).astype('f')
self.dset = self.f.create_dataset('data', shape=(0,), dtype=self.data.dtype, chunks=(2,), maxshape=(None,))
def test_initial_swmr_mode_off(self):
""" Verify that the file is not initially in SWMR mode"""
self.assertFalse(self.f.swmr_mode)
def test_switch_swmr_mode_on(self):
""" Switch to SWMR mode and verify """
self.f.swmr_mode = True
self.assertTrue(self.f.swmr_mode)
def test_switch_swmr_mode_off_raises(self):
""" Switching SWMR write mode off is only possible by closing the file.
Attempts to forcibly switch off the SWMR mode should raise a ValueError.
"""
self.f.swmr_mode = True
self.assertTrue(self.f.swmr_mode)
with self.assertRaises(ValueError):
self.f.swmr_mode = False
self.assertTrue(self.f.swmr_mode)
def test_extend_dset(self):
""" Extend and flush a SWMR dataset
"""
self.f.swmr_mode = True
self.assertTrue(self.f.swmr_mode)
self.dset.resize( self.data.shape )
self.dset[:] = self.data
self.dset.flush()
# Refresh and read back data for assertion
self.dset.refresh()
self.assertArrayEqual(self.dset, self.data)
def test_extend_dset_multiple(self):
self.f.swmr_mode = True
self.assertTrue(self.f.swmr_mode)
self.dset.resize( (4,) )
self.dset[0:] = self.data
self.dset.flush()
# Refresh and read back 1st data block for assertion
self.dset.refresh()
self.assertArrayEqual(self.dset, self.data)
self.dset.resize( (8,) )
self.dset[4:] = self.data
self.dset.flush()
# Refresh and read back 1st data block for assertion
self.dset.refresh()
self.assertArrayEqual(self.dset[0:4], self.data)
self.assertArrayEqual(self.dset[4:8], self.data)
@@ -0,0 +1,40 @@
# 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.
"""
File-resident datatype tests.
Tests "committed" file-resident datatype objects.
"""
import numpy as np
from .common import TestCase
from h5py import Datatype
class TestCreation(TestCase):
"""
Feature: repr() works sensibly on datatype objects
"""
def test_repr(self):
""" repr() on datatype objects """
self.f['foo'] = np.dtype('S10')
dt = self.f['foo']
self.assertIsInstance(repr(dt), str)
self.f.close()
self.assertIsInstance(repr(dt), str)
def test_appropriate_low_level_id(self):
" Binding a group to a non-TypeID identifier fails with ValueError "
with self.assertRaises(ValueError):
Datatype(self.f['/'].id)
@@ -0,0 +1,216 @@
# 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.
import numpy as np
from .common import TestCase
from h5py import File
import h5py
class BaseDataset(TestCase):
"""
data is a 3-dimensional dataset with dimensions [z, y, x]
The z dimension is labeled. It does not have any attached scales.
The y dimension is not labeled. It has one attached scale.
The x dimension is labeled. It has two attached scales.
data2 is a 3-dimensional dataset with no associated dimension scales.
"""
def setUp(self):
self.f = File(self.mktemp(), 'w')
self.f['data'] = np.ones((4, 3, 2), 'f')
self.f['data2'] = np.ones((4, 3, 2), 'f')
self.f['x1'] = np.ones((2), 'f')
h5py.h5ds.set_scale(self.f['x1'].id)
h5py.h5ds.attach_scale(self.f['data'].id, self.f['x1'].id, 2)
self.f['x2'] = np.ones((2), 'f')
h5py.h5ds.set_scale(self.f['x2'].id, b'x2 name')
h5py.h5ds.attach_scale(self.f['data'].id, self.f['x2'].id, 2)
self.f['y1'] = np.ones((3), 'f')
h5py.h5ds.set_scale(self.f['y1'].id, b'y1 name')
h5py.h5ds.attach_scale(self.f['data'].id, self.f['y1'].id, 1)
self.f['z1'] = np.ones((4), 'f')
h5py.h5ds.set_label(self.f['data'].id, 0, b'z')
h5py.h5ds.set_label(self.f['data'].id, 2, b'x')
def tearDown(self):
if self.f:
self.f.close()
class TestH5DSBindings(BaseDataset):
"""
Feature: Datasets can be created from existing data
"""
def test_create_dimensionscale(self):
""" Create a dimension scale from existing dataset """
self.assertTrue(h5py.h5ds.is_scale(self.f['x1'].id))
self.assertEqual(h5py.h5ds.get_scale_name(self.f['x1'].id), b'')
self.assertEqual(self.f['x1'].attrs['CLASS'], b"DIMENSION_SCALE")
self.assertEqual(h5py.h5ds.get_scale_name(self.f['x2'].id), b'x2 name')
def test_attach_dimensionscale(self):
self.assertTrue(
h5py.h5ds.is_attached(self.f['data'].id, self.f['x1'].id, 2)
)
self.assertFalse(
h5py.h5ds.is_attached(self.f['data'].id, self.f['x1'].id, 1))
self.assertEqual(h5py.h5ds.get_num_scales(self.f['data'].id, 0), 0)
self.assertEqual(h5py.h5ds.get_num_scales(self.f['data'].id, 1), 1)
self.assertEqual(h5py.h5ds.get_num_scales(self.f['data'].id, 2), 2)
def test_detach_dimensionscale(self):
self.assertTrue(
h5py.h5ds.is_attached(self.f['data'].id, self.f['x1'].id, 2)
)
h5py.h5ds.detach_scale(self.f['data'].id, self.f['x1'].id, 2)
self.assertFalse(
h5py.h5ds.is_attached(self.f['data'].id, self.f['x1'].id, 2)
)
self.assertEqual(h5py.h5ds.get_num_scales(self.f['data'].id, 2), 1)
def test_label_dimensionscale(self):
self.assertEqual(h5py.h5ds.get_label(self.f['data'].id, 0), b'z')
self.assertEqual(h5py.h5ds.get_label(self.f['data'].id, 1), b'')
self.assertEqual(h5py.h5ds.get_label(self.f['data'].id, 2), b'x')
def test_iter_dimensionscales(self):
def func(dsid):
res = h5py.h5ds.get_scale_name(dsid)
if res == b'x2 name':
return dsid
res = h5py.h5ds.iterate(self.f['data'].id, 2, func, 0)
self.assertEqual(h5py.h5ds.get_scale_name(res), b'x2 name')
class TestDimensionManager(BaseDataset):
def test_make_scale(self):
# test recreating or renaming an existing scale:
self.f['x1'].make_scale(b'foobar')
self.assertEqual(self.f['data'].dims[2]['foobar'], self.f['x1'])
# test creating entirely new scale:
self.f['data2'].make_scale(b'foobaz')
self.f['data'].dims[2].attach_scale(self.f['data2'])
self.assertEqual(self.f['data'].dims[2]['foobaz'], self.f['data2'])
def test_get_dimension(self):
with self.assertRaises(IndexError):
self.f['data'].dims[3]
def test_len(self):
self.assertEqual(len(self.f['data'].dims), 3)
self.assertEqual(len(self.f['data2'].dims), 3)
def test_iter(self):
dims = self.f['data'].dims
self.assertEqual(
[d for d in dims],
[dims[0], dims[1], dims[2]]
)
def test_repr(self):
ds = self.f.create_dataset('x', (2,3))
self.assertIsInstance(repr(ds.dims), str)
self.f.close()
self.assertIsInstance(repr(ds.dims), str)
class TestDimensionsHighLevel(BaseDataset):
def test_len(self):
self.assertEqual(len(self.f['data'].dims[0]), 0)
self.assertEqual(len(self.f['data'].dims[1]), 1)
self.assertEqual(len(self.f['data'].dims[2]), 2)
self.assertEqual(len(self.f['data2'].dims[0]), 0)
self.assertEqual(len(self.f['data2'].dims[1]), 0)
self.assertEqual(len(self.f['data2'].dims[2]), 0)
def test_get_label(self):
self.assertEqual(self.f['data'].dims[2].label, 'x')
self.assertEqual(self.f['data'].dims[1].label, '')
self.assertEqual(self.f['data'].dims[0].label, 'z')
self.assertEqual(self.f['data2'].dims[2].label, '')
self.assertEqual(self.f['data2'].dims[1].label, '')
self.assertEqual(self.f['data2'].dims[0].label, '')
def test_set_label(self):
self.f['data'].dims[0].label = 'foo'
self.assertEqual(self.f['data'].dims[2].label, 'x')
self.assertEqual(self.f['data'].dims[1].label, '')
self.assertEqual(self.f['data'].dims[0].label, 'foo')
def test_detach_scale(self):
self.f['data'].dims[2].detach_scale(self.f['x1'])
self.assertEqual(len(self.f['data'].dims[2]), 1)
self.assertEqual(self.f['data'].dims[2][0], self.f['x2'])
self.f['data'].dims[2].detach_scale(self.f['x2'])
self.assertEqual(len(self.f['data'].dims[2]), 0)
def test_attach_scale(self):
self.f['x3'] = self.f['x2'][...]
self.f['data'].dims[2].attach_scale(self.f['x3'])
self.assertEqual(len(self.f['data'].dims[2]), 3)
self.assertEqual(self.f['data'].dims[2][2], self.f['x3'])
def test_get_dimension_scale(self):
self.assertEqual(self.f['data'].dims[2][0], self.f['x1'])
with self.assertRaises(RuntimeError):
self.f['data2'].dims[2][0], self.f['x2']
self.assertEqual(self.f['data'].dims[2][''], self.f['x1'])
self.assertEqual(self.f['data'].dims[2]['x2 name'], self.f['x2'])
def test_get_items(self):
self.assertEqual(
self.f['data'].dims[2].items(),
[('', self.f['x1']), ('x2 name', self.f['x2'])]
)
def test_get_keys(self):
self.assertEqual(self.f['data'].dims[2].keys(), ['', 'x2 name'])
def test_get_values(self):
self.assertEqual(
self.f['data'].dims[2].values(),
[self.f['x1'], self.f['x2']]
)
def test_iter(self):
self.assertEqual([i for i in self.f['data'].dims[2]], ['', 'x2 name'])
def test_repr(self):
ds = self.f["data"]
self.assertEqual(repr(ds.dims[2])[1:16], '"x" dimension 2')
self.f.close()
self.assertIsInstance(repr(ds.dims), str)
def test_attributes(self):
self.f["data2"].attrs["DIMENSION_LIST"] = self.f["data"].attrs[
"DIMENSION_LIST"]
self.assertEqual(len(self.f['data2'].dims[0]), 0)
self.assertEqual(len(self.f['data2'].dims[1]), 1)
self.assertEqual(len(self.f['data2'].dims[2]), 2)
def test_is_scale(self):
"""Test Dataset.is_scale property"""
self.assertTrue(self.f['x1'].is_scale)
self.assertTrue(self.f['x2'].is_scale)
self.assertTrue(self.f['y1'].is_scale)
self.assertFalse(self.f['z1'].is_scale)
self.assertFalse(self.f['data'].is_scale)
self.assertFalse(self.f['data2'].is_scale)
@@ -0,0 +1,22 @@
# 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.
"""
Tests the h5py.Dataset.dims.DimensionProxy class.
"""
from .common import TestCase
class TestItems(TestCase):
def test_empty(self):
""" no dimension scales -> empty list """
dset = self.f.create_dataset('x', (10,))
self.assertEqual(dset.dims[0].items(), [])
@@ -0,0 +1,532 @@
"""
Tests for converting between numpy dtypes and h5py data types
"""
from itertools import count
import platform
import numpy as np
import h5py
try:
import tables
except ImportError:
tables = None
from .common import ut, TestCase
UNSUPPORTED_LONG_DOUBLE = ('i386', 'i486', 'i586', 'i686', 'ppc64le')
UNSUPPORTED_LONG_DOUBLE_TYPES = ('float96', 'float128', 'complex192',
'complex256')
class TestVlen(TestCase):
"""
Check that storage of vlen strings is carried out correctly.
"""
def assertVlenArrayEqual(self, dset, arr, message=None, precision=None):
assert dset.shape == arr.shape, \
"Shape mismatch (%s vs %s)%s" % (dset.shape, arr.shape, message)
for (i, d, a) in zip(count(), dset, arr):
self.assertArrayEqual(d, a, message, precision)
def test_compound(self):
fields = []
fields.append(('field_1', h5py.string_dtype()))
fields.append(('field_2', np.int32))
dt = np.dtype(fields)
self.f['mytype'] = np.dtype(dt)
dt_out = self.f['mytype'].dtype.fields['field_1'][0]
string_inf = h5py.check_string_dtype(dt_out)
self.assertEqual(string_inf.encoding, 'utf-8')
def test_compound_vlen_bool(self):
vidt = h5py.vlen_dtype(np.uint8)
def a(items):
return np.array(items, dtype=np.uint8)
f = self.f
dt_vb = np.dtype([
('foo', vidt),
('logical', bool)])
vb = f.create_dataset('dt_vb', shape=(4,), dtype=dt_vb)
data = np.array([(a([1, 2, 3]), True),
(a([1 ]), False),
(a([1, 5 ]), True),
(a([],), False), ],
dtype=dt_vb)
vb[:] = data
actual = f['dt_vb'][:]
self.assertVlenArrayEqual(data['foo'], actual['foo'])
self.assertArrayEqual(data['logical'], actual['logical'])
dt_vv = np.dtype([
('foo', vidt),
('bar', vidt)])
f.create_dataset('dt_vv', shape=(4,), dtype=dt_vv)
dt_vvb = np.dtype([
('foo', vidt),
('bar', vidt),
('logical', bool)])
vvb = f.create_dataset('dt_vvb', shape=(2,), dtype=dt_vvb)
dt_bvv = np.dtype([
('logical', bool),
('foo', vidt),
('bar', vidt)])
bvv = f.create_dataset('dt_bvv', shape=(2,), dtype=dt_bvv)
data = np.array([(True, a([1, 2, 3]), a([1, 2])),
(False, a([]), a([2, 4, 6])), ],
dtype=bvv)
bvv[:] = data
actual = bvv[:]
self.assertVlenArrayEqual(data['foo'], actual['foo'])
self.assertVlenArrayEqual(data['bar'], actual['bar'])
self.assertArrayEqual(data['logical'], actual['logical'])
def test_compound_vlen_enum(self):
eidt = h5py.enum_dtype({'OFF': 0, 'ON': 1}, basetype=np.uint8)
vidt = h5py.vlen_dtype(np.uint8)
def a(items):
return np.array(items, dtype=np.uint8)
f = self.f
dt_vve = np.dtype([
('foo', vidt),
('bar', vidt),
('switch', eidt)])
vve = f.create_dataset('dt_vve', shape=(2,), dtype=dt_vve)
data = np.array([(a([1, 2, 3]), a([1, 2]), 1),
(a([]), a([2, 4, 6]), 0), ],
dtype=dt_vve)
vve[:] = data
actual = vve[:]
self.assertVlenArrayEqual(data['foo'], actual['foo'])
self.assertVlenArrayEqual(data['bar'], actual['bar'])
self.assertArrayEqual(data['switch'], actual['switch'])
def test_vlen_enum(self):
fname = self.mktemp()
arr1 = [[1], [1, 2]]
dt1 = h5py.vlen_dtype(h5py.enum_dtype(dict(foo=1, bar=2), 'i'))
with h5py.File(fname, 'w') as f:
df1 = f.create_dataset('test', (len(arr1),), dtype=dt1)
df1[:] = np.array(arr1, dtype=object)
with h5py.File(fname, 'r') as f:
df2 = f['test']
dt2 = df2.dtype
arr2 = [e.tolist() for e in df2[:]]
self.assertEqual(arr1, arr2)
self.assertEqual(h5py.check_enum_dtype(h5py.check_vlen_dtype(dt1)),
h5py.check_enum_dtype(h5py.check_vlen_dtype(dt2)))
def test_write_empty_vlen(writable_file):
# vlen dtype with no entries
d = np.rec.fromarrays([[], []], names='a,b', formats='|V16,O')
dset = writable_file.create_dataset(
'test', data=d, dtype=[('a', '|V16'), ('b', h5py.special_dtype(vlen=np.float64))]
)
assert dset.size == 0
def test_write_vlen_length0_compound(writable_file):
# one entry has variable length 0 (using the variable length)
# https://github.com/h5py/h5py/issues/2693
compound_dtype = np.dtype([('id', 'i4'), ('value', 'f8'), ('name', 'S10')])
vlen_compound_dtype = h5py.special_dtype(vlen=compound_dtype)
arr0 = np.array([(1, 3.14, b'test1'), (2, 2.71, b'test2')], dtype=compound_dtype)
arr1 = np.array([], dtype=compound_dtype)
dset = writable_file.create_dataset(
'vlen_compound_data', shape=(2,), dtype=vlen_compound_dtype
)
dset[0] = arr0
dset[1] = arr1
np.testing.assert_array_equal(dset[0], arr0) # With data
np.testing.assert_array_equal(dset[1], arr1) # Without data
class TestExplicitCast(TestCase):
def test_f2_casting(self):
fname = self.mktemp()
np.random.seed(1)
A = np.random.rand(1500, 20)
# Save to HDF5 file
with h5py.File(fname, "w") as Fid:
Fid.create_dataset("Data", data=A, dtype='f2')
with h5py.File(fname, "r") as Fid:
B = Fid["Data"][:]
# Compare
self.assertTrue(np.all(A.astype('f2') == B))
class TestOffsets(TestCase):
"""
Check that compound members with aligned or manual offsets are handled
correctly.
"""
def test_compound_vlen(self):
vidt = h5py.vlen_dtype(np.uint8)
eidt = h5py.enum_dtype({'OFF': 0, 'ON': 1}, basetype=np.uint8)
for np_align in (False, True):
dt = np.dtype([
('a', eidt),
('foo', vidt),
('bar', vidt),
('switch', eidt)], align=np_align)
np_offsets = [dt.fields[i][1] for i in dt.names]
for logical in (False, True):
if logical and np_align:
# Vlen types have different size in the numpy struct
self.assertRaises(TypeError, h5py.h5t.py_create, dt,
logical=logical)
else:
ht = h5py.h5t.py_create(dt, logical=logical)
offsets = [ht.get_member_offset(i)
for i in range(ht.get_nmembers())]
if np_align:
self.assertEqual(np_offsets, offsets)
def test_aligned_offsets(self):
dt = np.dtype('i4,i8,i2', align=True)
ht = h5py.h5t.py_create(dt)
self.assertEqual(dt.itemsize, ht.get_size())
self.assertEqual(
[dt.fields[i][1] for i in dt.names],
[ht.get_member_offset(i) for i in range(ht.get_nmembers())]
)
def test_aligned_data(self):
dt = np.dtype('i4,f8,i2', align=True)
data = np.zeros(10, dtype=dt)
data['f0'] = np.array(np.random.randint(-100, 100, size=data.size),
dtype='i4')
data['f1'] = np.random.rand(data.size)
data['f2'] = np.array(np.random.randint(-100, 100, size=data.size),
dtype='i2')
fname = self.mktemp()
with h5py.File(fname, 'w') as f:
f['data'] = data
with h5py.File(fname, 'r') as f:
self.assertArrayEqual(f['data'], data)
def test_compound_robustness(self):
# make an out of order compound type with gaps in it, and larger itemsize than minimum
# Idea is to be robust to type descriptions we *could* get out of HDF5 files, from custom descriptions
# of types in addition to numpy's flakey history on unaligned fields with non-standard or padded layouts.
fields = [
('f0', np.float64, 25),
('f1', np.uint64, 9),
('f2', np.uint32, 0),
('f3', np.uint16, 5)
]
lastfield = fields[np.argmax([ x[2] for x in fields ])]
itemsize = lastfield[2] + np.dtype(lastfield[1]).itemsize + 6
extract_index = lambda index, sequence: [ x[index] for x in sequence ]
dt = np.dtype({
'names' : extract_index(0, fields),
'formats' : extract_index(1, fields),
'offsets' : extract_index(2, fields),
# 'aligned': False, - already defaults to False
'itemsize': itemsize
})
self.assertTrue(dt.itemsize == itemsize)
data = np.zeros(10, dtype=dt)
# don't trust numpy struct handling, keep fields out of band in case content insertion is erroneous
# yes... this has also been known to happen.
f1 = np.array([1 + i * 4 for i in range(data.shape[0])], dtype=dt.fields['f1'][0])
f2 = np.array([2 + i * 4 for i in range(data.shape[0])], dtype=dt.fields['f2'][0])
f3 = np.array([3 + i * 4 for i in range(data.shape[0])], dtype=dt.fields['f3'][0])
f0c = 3.14
data['f0'] = f0c
data['f3'] = f3
data['f1'] = f1
data['f2'] = f2
# numpy consistency checks
self.assertTrue(np.all(data['f0'] == f0c))
self.assertArrayEqual(data['f3'], f3)
self.assertArrayEqual(data['f1'], f1)
self.assertArrayEqual(data['f2'], f2)
fname = self.mktemp()
with h5py.File(fname, 'w') as fd:
fd.create_dataset('data', data=data)
with h5py.File(fname, 'r') as fd:
readback = fd['data']
self.assertTrue(readback.dtype == dt)
self.assertArrayEqual(readback, data)
self.assertTrue(np.all(readback['f0'] == f0c))
self.assertArrayEqual(readback['f1'], f1)
self.assertArrayEqual(readback['f2'], f2)
self.assertArrayEqual(readback['f3'], f3)
def test_out_of_order_offsets(self):
dt = np.dtype({
'names' : ['f1', 'f2', 'f3'],
'formats' : ['<f4', '<i4', '<f8'],
'offsets' : [0, 16, 8]
})
data = np.zeros(10, dtype=dt)
data['f1'] = np.random.rand(data.size)
data['f2'] = np.random.randint(-10, 11, data.size)
data['f3'] = np.random.rand(data.size) * -1
fname = self.mktemp()
with h5py.File(fname, 'w') as fd:
fd.create_dataset('data', data=data)
with h5py.File(fname, 'r') as fd:
self.assertArrayEqual(fd['data'], data)
def test_float_round_tripping(self):
dtypes = set(f for f in np.sctypeDict.values()
if (np.issubdtype(f, np.floating) or
np.issubdtype(f, np.complexfloating)))
unsupported_types = []
if platform.machine() in UNSUPPORTED_LONG_DOUBLE:
for x in UNSUPPORTED_LONG_DOUBLE_TYPES:
if hasattr(np, x):
unsupported_types.append(getattr(np, x))
dtype_dset_map = {str(j): d
for j, d in enumerate(dtypes)
if d not in unsupported_types}
fname = self.mktemp()
with h5py.File(fname, 'w') as f:
for n, d in dtype_dset_map.items():
data = np.zeros(10, dtype=d)
data[...] = np.arange(10)
f.create_dataset(n, data=data)
with h5py.File(fname, 'r') as f:
for n, d in dtype_dset_map.items():
ldata = f[n][:]
self.assertEqual(ldata.dtype, d)
class TestStrings(TestCase):
def test_vlen_utf8(self):
dt = h5py.string_dtype()
string_info = h5py.check_string_dtype(dt)
assert string_info.encoding == 'utf-8'
assert string_info.length is None
assert h5py.check_vlen_dtype(dt) is str
def test_vlen_ascii(self):
dt = h5py.string_dtype(encoding='ascii')
string_info = h5py.check_string_dtype(dt)
assert string_info.encoding == 'ascii'
assert string_info.length is None
assert h5py.check_vlen_dtype(dt) is bytes
def test_fixed_utf8(self):
dt = h5py.string_dtype(length=10)
string_info = h5py.check_string_dtype(dt)
assert string_info.encoding == 'utf-8'
assert string_info.length == 10
assert h5py.check_vlen_dtype(dt) is None
def test_fixed_ascii(self):
dt = h5py.string_dtype(encoding='ascii', length=10)
string_info = h5py.check_string_dtype(dt)
assert string_info.encoding == 'ascii'
assert string_info.length == 10
assert h5py.check_vlen_dtype(dt) is None
class TestDateTime(TestCase):
datetime_units = [
# Dates
'Y', 'M', 'D',
# Times
'h', 'm', 's', 'ms', 'us',
'ns', 'ps', 'fs', 'as',
]
def test_datetime(self):
fname = self.mktemp()
for dt_unit in self.datetime_units:
for dt_order in ['<', '>']:
dt_descr = f'{dt_order}M8[{dt_unit}]'
dt = h5py.opaque_dtype(np.dtype(dt_descr))
arr = np.array([0], dtype=np.int64).view(dtype=dt)
with h5py.File(fname, 'w') as f:
dset = f.create_dataset("default", data=arr, dtype=dt)
self.assertArrayEqual(arr, dset)
self.assertEqual(arr.dtype, dset.dtype)
def test_timedelta(self):
fname = self.mktemp()
for dt_unit in self.datetime_units:
for dt_order in ['<', '>']:
dt_descr = f'{dt_order}m8[{dt_unit}]'
dt = h5py.opaque_dtype(np.dtype(dt_descr))
arr = np.array([np.timedelta64(500, dt_unit)], dtype=dt)
with h5py.File(fname, 'w') as f:
dset = f.create_dataset("default", data=arr, dtype=dt)
self.assertArrayEqual(arr, dset)
self.assertEqual(arr.dtype, dset.dtype)
@ut.skipUnless(tables is not None, 'tables is required')
class TestBitfield(TestCase):
"""
Test H5T_NATIVE_B8 reading
"""
def test_b8_bool(self):
arr1 = np.array([False, True], dtype=bool)
self._test_b8(
arr1,
expected_default_cast_dtype=np.uint8
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.uint8,
cast_dtype=np.uint8
)
def test_b8_bool_compound(self):
arr1 = np.array([(False,), (True,)], dtype=np.dtype([('x', '?')]))
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype([('x', 'u1')])
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype([('x', 'u1')]),
cast_dtype=np.dtype([('x', 'u1')])
)
def test_b8_bool_compound_nested(self):
arr1 = np.array(
[(True, (True, False)), (True, (False, True))],
dtype=np.dtype([('x', '?'), ('y', [('a', '?'), ('b', '?')])]),
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype(
[('x', 'u1'), ('y', [('a', 'u1'), ('b', 'u1')])]
)
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype(
[('x', 'u1'), ('y', [('a', 'u1'), ('b', 'u1')])]
),
cast_dtype=np.dtype([('x', 'u1'), ('y', [('a', 'u1'), ('b', 'u1')])]),
)
def test_b8_bool_compound_mixed_types(self):
arr1 = np.array(
[(True, 0.5), (False, 0.2)], dtype=np.dtype([('x','?'), ('y', '<f8')])
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype([('x', 'u1'), ('y', '<f8')])
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype([('x', 'u1'), ('y', '<f8')]),
cast_dtype=np.dtype([('x', 'u1'), ('y', '<f8')])
)
def test_b8_bool_array(self):
arr1 = np.array(
[((True, True, False),), ((True, False, True),)],
dtype=np.dtype([('x', ('?', (3,)))]),
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype([('x', ('u1', (3,)))])
)
self._test_b8(
arr1,
expected_default_cast_dtype=np.dtype([('x', ('u1', (3,)))]),
cast_dtype=np.dtype([('x', ('?', (3,)))]),
)
def _test_b8(self, arr1, expected_default_cast_dtype, cast_dtype=None):
path = self.mktemp()
with tables.open_file(path, 'w') as f:
if arr1.dtype.names:
f.create_table('/', 'test', obj=arr1)
else:
f.create_array('/', 'test', obj=arr1)
with h5py.File(path, 'r') as f:
dset = f['test']
# This should do an implicit uint8 cast
# Expect that the "No NumPy equivalent for TypeBitfieldID exists"
# error is not thrown.
arr2 = dset[:]
self.assertArrayEqual(
arr2,
arr1.astype(expected_default_cast_dtype, copy=False)
)
# read cast dset and make sure it's equal
if cast_dtype is None:
cast_dtype = arr1.dtype
arr3 = dset.astype(cast_dtype)[:]
self.assertArrayEqual(arr3, arr1.astype(cast_dtype, copy=False))
def test_b16_uint16(self):
arr1 = np.arange(10, dtype=np.uint16)
path = self.mktemp()
with h5py.File(path, 'w') as f:
space = h5py.h5s.create_simple(arr1.shape)
dset_id = h5py.h5d.create(f.id, b'test', h5py.h5t.STD_B16LE, space)
dset = h5py.Dataset(dset_id)
dset[:] = arr1
with h5py.File(path, 'r') as f:
dset = f['test']
self.assertArrayEqual(dset[:], arr1)
def test_opaque(writable_file):
# opaque without an h5py tag corresponds to numpy void dtypes
arr = np.zeros(3, dtype='V2')
ds = writable_file.create_dataset('v', data=arr)
assert isinstance(ds.id.get_type(), h5py.h5t.TypeOpaqueID)
assert ds.id.get_type().get_size() == 2
np.testing.assert_array_equal(ds[:], arr)
@@ -0,0 +1,84 @@
# 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.
"""
Tests the h5py.File object.
"""
import threading
import h5py
def _access_not_existing_object(filename):
"""Create a file and access not existing key"""
with h5py.File(filename, 'w') as newfile:
try:
doesnt_exist = newfile['doesnt_exist'].value
except KeyError:
pass
def test_unsilence_errors(tmp_path, capfd):
"""Check that HDF5 errors can be muted/unmuted from h5py"""
filename = tmp_path / 'test.h5'
# Unmute HDF5 errors
try:
h5py._errors.unsilence_errors()
_access_not_existing_object(filename)
captured = capfd.readouterr()
assert captured.err != ''
assert captured.out == ''
# Mute HDF5 errors
finally:
h5py._errors.silence_errors()
_access_not_existing_object(filename)
captured = capfd.readouterr()
assert captured.err == ''
assert captured.out == ''
def test_thread_hdf5_silence_error_membership(tmp_path, capfd):
"""Verify the error printing is squashed in all threads.
No console messages should be shown from membership tests
"""
th = threading.Thread(target=_access_not_existing_object,
args=(tmp_path / 'test.h5',))
th.start()
th.join()
captured = capfd.readouterr()
assert captured.err == ''
assert captured.out == ''
def test_thread_hdf5_silence_error_attr(tmp_path, capfd):
"""Verify the error printing is squashed in all threads.
No console messages should be shown for non-existing attributes
"""
def test():
with h5py.File(tmp_path/'test.h5', 'w') as newfile:
newfile['newdata'] = [1, 2, 3]
try:
nonexistent_attr = newfile['newdata'].attrs['nonexistent_attr']
except KeyError:
pass
th = threading.Thread(target=test)
th.start()
th.join()
captured = capfd.readouterr()
assert captured.err == ''
assert captured.out == ''
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,333 @@
# 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.
"""
Tests the h5py.File object.
"""
import h5py
from h5py._hl.files import _drivers
from h5py import File
from .common import ut, TestCase
import pytest
import io
import tempfile
import os
def nfiles():
return h5py.h5f.get_obj_count(h5py.h5f.OBJ_ALL, h5py.h5f.OBJ_FILE)
def ngroups():
return h5py.h5f.get_obj_count(h5py.h5f.OBJ_ALL, h5py.h5f.OBJ_GROUP)
class TestDealloc(TestCase):
"""
Behavior on object deallocation. Note most of this behavior is
delegated to FileID.
"""
def test_autoclose(self):
""" File objects close automatically when out of scope, but
other objects remain open. """
start_nfiles = nfiles()
start_ngroups = ngroups()
fname = self.mktemp()
f = h5py.File(fname, 'w')
g = f['/']
self.assertEqual(nfiles(), start_nfiles+1)
self.assertEqual(ngroups(), start_ngroups+1)
del f
self.assertTrue(g)
self.assertEqual(nfiles(), start_nfiles)
self.assertEqual(ngroups(), start_ngroups+1)
f = g.file
self.assertTrue(f)
self.assertEqual(nfiles(), start_nfiles+1)
self.assertEqual(ngroups(), start_ngroups+1)
del g
self.assertEqual(nfiles(), start_nfiles+1)
self.assertEqual(ngroups(), start_ngroups)
del f
self.assertEqual(nfiles(), start_nfiles)
self.assertEqual(ngroups(), start_ngroups)
class TestDriverRegistration(TestCase):
def test_register_driver(self):
called_with = [None]
def set_fapl(plist, *args, **kwargs):
called_with[0] = args, kwargs
return _drivers['sec2'](plist)
h5py.register_driver('new-driver', set_fapl)
self.assertIn('new-driver', h5py.registered_drivers())
fname = self.mktemp()
h5py.File(fname, driver='new-driver', driver_arg_0=0, driver_arg_1=1,
mode='w')
self.assertEqual(
called_with,
[((), {'driver_arg_0': 0, 'driver_arg_1': 1})],
)
def test_unregister_driver(self):
h5py.register_driver('new-driver', lambda plist: None)
self.assertIn('new-driver', h5py.registered_drivers())
h5py.unregister_driver('new-driver')
self.assertNotIn('new-driver', h5py.registered_drivers())
with self.assertRaises(ValueError) as e:
fname = self.mktemp()
h5py.File(fname, driver='new-driver', mode='w')
self.assertEqual(str(e.exception), "Unknown driver type 'new-driver'")
class TestCache(TestCase):
def setUp(self):
MiB = 1024 * 1024
if h5py.version.hdf5_version_tuple < (2, 0, 0):
self.dflt_chunk_cache = MiB
else:
self.dflt_chunk_cache = 8 * MiB
def test_defaults(self):
fname = self.mktemp()
f = h5py.File(fname, 'w')
self.assertEqual(list(f.id.get_access_plist().get_cache()),
[0, 521, self.dflt_chunk_cache, 0.75])
def test_nbytes(self):
fname = self.mktemp()
f = h5py.File(fname, 'w', rdcc_nbytes=1024)
self.assertEqual(list(f.id.get_access_plist().get_cache()),
[0, 521, 1024, 0.75])
def test_nslots(self):
fname = self.mktemp()
f = h5py.File(fname, 'w', rdcc_nslots=125)
self.assertEqual(list(f.id.get_access_plist().get_cache()),
[0, 125, self.dflt_chunk_cache, 0.75])
def test_w0(self):
fname = self.mktemp()
f = h5py.File(fname, 'w', rdcc_w0=0.25)
self.assertEqual(list(f.id.get_access_plist().get_cache()),
[0, 521, self.dflt_chunk_cache, 0.25])
class TestFileObj(TestCase):
def check_write(self, fileobj):
f = h5py.File(fileobj, 'w')
self.assertEqual(f.driver, 'fileobj')
self.assertEqual(f.filename, repr(fileobj))
f.create_dataset('test', data=list(range(12)))
self.assertEqual(list(f), ['test'])
self.assertEqual(list(f['test'][:]), list(range(12)))
f.close()
def check_read(self, fileobj):
f = h5py.File(fileobj, 'r')
self.assertEqual(list(f), ['test'])
self.assertEqual(list(f['test'][:]), list(range(12)))
self.assertRaises(Exception, f.create_dataset, 'another.test', data=list(range(3)))
f.close()
def test_BytesIO(self):
with io.BytesIO() as fileobj:
self.assertEqual(len(fileobj.getvalue()), 0)
self.check_write(fileobj)
self.assertGreater(len(fileobj.getvalue()), 0)
self.check_read(fileobj)
def test_file(self):
fname = self.mktemp()
try:
with open(fname, 'wb+') as fileobj:
self.assertEqual(os.path.getsize(fname), 0)
self.check_write(fileobj)
self.assertGreater(os.path.getsize(fname), 0)
self.check_read(fileobj)
with open(fname, 'rb') as fileobj:
self.check_read(fileobj)
finally:
os.remove(fname)
@pytest.mark.filterwarnings(
# at least on Windows and MacOS, a resource warning may be emitted
# when this test returns
"ignore::ResourceWarning"
)
def test_TemporaryFile(self):
# in this test, we check explicitly that temp file gets
# automatically deleted upon h5py.File.close()...
fileobj = tempfile.NamedTemporaryFile()
fname = fileobj.name
f = h5py.File(fileobj, 'w')
del fileobj
# ... but in your code feel free to simply
# f = h5py.File(tempfile.TemporaryFile())
f.create_dataset('test', data=list(range(12)))
self.assertEqual(list(f), ['test'])
self.assertEqual(list(f['test'][:]), list(range(12)))
self.assertTrue(os.path.isfile(fname))
f.close()
self.assertFalse(os.path.isfile(fname))
def test_exception_open(self):
self.assertRaises(Exception, h5py.File, None,
driver='fileobj', mode='x')
self.assertRaises(Exception, h5py.File, 'rogue',
driver='fileobj', mode='x')
self.assertRaises(Exception, h5py.File, self,
driver='fileobj', mode='x')
def test_exception_read(self):
class BrokenBytesIO(io.BytesIO):
def readinto(self, b):
raise Exception('I am broken')
f = h5py.File(BrokenBytesIO(), 'w')
f.create_dataset('test', data=list(range(12)))
self.assertRaises(Exception, list, f['test'])
def test_exception_write(self):
class BrokenBytesIO(io.BytesIO):
allow_write = False
def write(self, b):
if self.allow_write:
return super().write(b)
else:
raise Exception('I am broken')
bio = BrokenBytesIO()
f = h5py.File(bio, 'w')
try:
self.assertRaises(Exception, f.create_dataset, 'test',
data=list(range(12)))
finally:
# Un-break writing so we can close: errors while closing get messy.
bio.allow_write = True
f.close()
@ut.skip("Incompletely closed files can cause segfaults")
def test_exception_close(self):
fileobj = io.BytesIO()
f = h5py.File(fileobj, 'w')
fileobj.close()
self.assertRaises(Exception, f.close)
def test_exception_writeonly(self):
# HDF5 expects read & write access to a file it's writing;
# check that we get the correct exception on a write-only file object.
fileobj = open(os.path.join(self.tempdir, 'a.h5'), 'wb')
f = h5py.File(fileobj, 'w')
group = f.create_group("group")
with self.assertRaises(io.UnsupportedOperation):
group.create_dataset("data", data='foo', dtype=h5py.string_dtype())
f.close()
fileobj.close()
def test_method_vanish(self):
fileobj = io.BytesIO()
f = h5py.File(fileobj, 'w')
f.create_dataset('test', data=list(range(12)))
self.assertEqual(list(f['test'][:]), list(range(12)))
fileobj.readinto = None
self.assertRaises(Exception, list, f['test'])
class TestTrackOrder(TestCase):
def populate(self, f):
for i in range(100):
# Mix group and dataset creation.
if i % 10 == 0:
f.create_group(str(i))
else:
f[str(i)] = [i]
def test_track_order(self):
fname = self.mktemp()
f = h5py.File(fname, 'w', track_order=True) # creation order
self.populate(f)
self.assertEqual(list(f), [str(i) for i in range(100)])
f.close()
# Check order tracking after reopening the file
f2 = h5py.File(fname)
self.assertEqual(list(f2), [str(i) for i in range(100)])
def test_no_track_order(self):
fname = self.mktemp()
f = h5py.File(fname, 'w', track_order=False) # name alphanumeric
self.populate(f)
self.assertEqual(list(f),
sorted([str(i) for i in range(100)]))
class TestFileMetaBlockSize(TestCase):
"""
Feature: The meta block size can be manipulated, changing how metadata
is aggregated and the offset of the first dataset.
"""
def test_file_create_with_meta_block_size_4096(self):
# Test a large meta block size of 4 kibibytes
meta_block_size = 4096
with File(
self.mktemp(), 'w',
meta_block_size=meta_block_size,
libver="latest"
) as f:
f["test"] = 5
self.assertEqual(f.meta_block_size, meta_block_size)
# Equality is expected for HDF5 1.10
self.assertGreaterEqual(f["test"].id.get_offset(), meta_block_size)
def test_file_create_with_meta_block_size_512(self):
# Test a small meta block size of 512 bytes
# The smallest verifiable meta_block_size is 463
meta_block_size = 512
libver = "latest"
with File(
self.mktemp(), 'w',
meta_block_size=meta_block_size,
libver=libver
) as f:
f["test"] = 3
self.assertEqual(f.meta_block_size, meta_block_size)
# Equality is expected for HDF5 1.10
self.assertGreaterEqual(f["test"].id.get_offset(), meta_block_size)
# Default meta_block_size is 2048. This should fail if meta_block_size is not set.
self.assertLess(f["test"].id.get_offset(), meta_block_size*2)
@@ -0,0 +1,103 @@
import h5py
from .common import TestCase
def is_aligned(dataset, offset=4096):
# Here we check if the dataset is aligned
return dataset.id.get_offset() % offset == 0
def dataset_name(i):
return f"data{i:03}"
class TestFileAlignment(TestCase):
"""
Ensure that setting the file alignment has the desired effect
in the internal structure.
"""
def test_no_alignment_set(self):
fname = self.mktemp()
# 881 is a prime number, so hopefully this help randomize the alignment
# enough
# A nice even number might give a pathological case where
# While we don't want the data to be aligned, it ends up aligned...
shape = (881,)
with h5py.File(fname, 'w') as h5file:
# Create up to 1000 datasets
# At least one of them should be misaligned.
# While this isn't perfect, it seems that there
# The case where 1000 datasets get created is one where the data
# is aligned. Therefore, during correct operation, this test is
# expected to finish quickly
for i in range(1000):
dataset = h5file.create_dataset(
dataset_name(i), shape, dtype='uint8')
# Assign data so that the dataset is instantiated in
# the file
dataset[...] = i
if not is_aligned(dataset):
# Break early asserting that the file is not aligned
break
else:
raise RuntimeError("Data was all found to be aligned to 4096")
def test_alignment_set_above_threshold(self):
# 2022/01/19 hmaarrfk
# UnitTest (TestCase) doesn't play well with pytest parametrization.
alignment_threshold = 1000
alignment_interval = 4096
for shape in [
(1033,), # A prime number above the threshold
(1000,), # Exactly equal to the threshold
(1001,), # one above the threshold
]:
fname = self.mktemp()
with h5py.File(fname, 'w',
alignment_threshold=alignment_threshold,
alignment_interval=alignment_interval) as h5file:
# Create up to 1000 datasets
# They are all expected to be aligned
for i in range(1000):
dataset = h5file.create_dataset(
dataset_name(i), shape, dtype='uint8')
# Assign data so that the dataset is instantiated in
# the file
dataset[...] = (i % 256) # Truncate to uint8
assert is_aligned(dataset, offset=alignment_interval)
def test_alignment_set_below_threshold(self):
# 2022/01/19 hmaarrfk
# UnitTest (TestCase) doesn't play well with pytest parametrization.
alignment_threshold = 1000
alignment_interval = 1024
for shape in [
(881,), # A prime number below the threshold
(999,), # Exactly one below the threshold
]:
fname = self.mktemp()
with h5py.File(fname, 'w',
alignment_threshold=alignment_threshold,
alignment_interval=alignment_interval) as h5file:
# Create up to 1000 datasets
# At least one of them should be misaligned.
# While this isn't perfect, it seems that there
# The case where 1000 datasets get created is one where the
# data is aligned. Therefore, during correct operation, this
# test is expected to finish quickly
for i in range(1000):
dataset = h5file.create_dataset(
dataset_name(i), shape, dtype='uint8')
# Assign data so that the dataset is instantiated in
# the file
dataset[...] = i
if not is_aligned(dataset, offset=alignment_interval):
# Break early asserting that the file is not aligned
break
else:
raise RuntimeError(
"Data was all found to be aligned to "
f"{alignment_interval}. This is highly unlikely.")
@@ -0,0 +1,54 @@
import numpy as np
import h5py
from h5py import h5f, h5p
from .common import TestCase
class TestFileImage(TestCase):
def test_load_from_image(self):
from binascii import a2b_base64
from zlib import decompress
compressed_image = 'eJzr9HBx4+WS4mIAAQ4OBhYGAQZk8B8KKjhQ+TD5BCjNCKU7oPQKJpg4I1hOAiouCDUfXV1IkKsrSPV/NACzx4AFQnMwjIKRCDxcHQNAdASUD0ulJ5hQ1ZWkFpeAaFh69KDQXkYGNohZjDA+JCUzMkIEmKHqELQAWKkAByytOoBJViAPJM7ExATWyAE0B8RgZkyAJmlYDoEAIahukJoNU6+HMTA0UOgT6oBgP38XUI6G5UMFZrzKR8EoGAUjGMDKYVgxDSsuAHcfMK8='
image = decompress(a2b_base64(compressed_image))
fapl = h5p.create(h5py.h5p.FILE_ACCESS)
fapl.set_fapl_core()
fapl.set_file_image(image)
fid = h5f.open(self.mktemp().encode(), h5py.h5f.ACC_RDONLY, fapl=fapl)
f = h5py.File(fid)
self.assertTrue('test' in f)
def test_open_from_image(self):
from binascii import a2b_base64
from zlib import decompress
compressed_image = 'eJzr9HBx4+WS4mIAAQ4OBhYGAQZk8B8KKjhQ+TD5BCjNCKU7oPQKJpg4I1hOAiouCDUfXV1IkKsrSPV/NACzx4AFQnMwjIKRCDxcHQNAdASUD0ulJ5hQ1ZWkFpeAaFh69KDQXkYGNohZjDA+JCUzMkIEmKHqELQAWKkAByytOoBJViAPJM7ExATWyAE0B8RgZkyAJmlYDoEAIahukJoNU6+HMTA0UOgT6oBgP38XUI6G5UMFZrzKR8EoGAUjGMDKYVgxDSsuAHcfMK8='
image = decompress(a2b_base64(compressed_image))
fid = h5f.open_file_image(image)
f = h5py.File(fid)
self.assertTrue('test' in f)
def test_in_memory():
arr = np.arange(10)
# Passing one fcpl & one fapl parameter to exercise the code splitting them:
with h5py.File.in_memory(track_order=True, rdcc_nbytes=2_000_000) as f1:
f1['a'] = arr
f1.flush()
img = f1.id.get_file_image()
# Open while f1 is still open
with h5py.File.in_memory(img) as f2:
np.testing.assert_array_equal(f2['a'][:], arr)
# Reuse image now that previous files are closed
with h5py.File.in_memory(img) as f3:
np.testing.assert_array_equal(f3['a'][:], arr)
@@ -0,0 +1,93 @@
# 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.
"""
Tests the h5py._hl.filters module.
"""
import os
import numpy as np
import h5py
from .common import ut, TestCase
class TestFilters(TestCase):
def setUp(self):
""" like TestCase.setUp but also store the file path """
self.path = self.mktemp()
self.f = h5py.File(self.path, 'w')
@ut.skipUnless(h5py.h5z.filter_avail(h5py.h5z.FILTER_SZIP), 'szip filter required')
def test_wr_szip_fletcher32_64bit(self):
""" test combination of szip, fletcher32, and 64bit arrays
The fletcher32 checksum must be computed after the szip
compression is applied.
References:
- GitHub issue #953
- https://forum.hdfgroup.org/t/fletcher32-checksum-error-with-szip-compression-and-64bit-data/4141
"""
self.f.create_dataset("test_data",
data=np.zeros(10000, dtype=np.float64),
fletcher32=True,
compression="szip",
)
self.f.close()
with h5py.File(self.path, "r") as h5:
# Access the data which will compute the fletcher32
# checksum and raise an OSError if something is wrong.
h5["test_data"][0]
def test_wr_scaleoffset_fletcher32(self):
""" make sure that scaleoffset + fletcher32 is prevented
"""
data = np.linspace(0, 1, 100)
with self.assertRaises(ValueError):
self.f.create_dataset("test_data",
data=data,
fletcher32=True,
# retain 3 digits after the decimal point
scaleoffset=3,
)
@ut.skipIf('gzip' not in h5py.filters.encode, "DEFLATE is not installed")
def test_filter_ref_obj(writable_file):
gzip8 = h5py.filters.Gzip(level=8)
# **kwargs unpacking (compatible with earlier h5py versions)
assert dict(**gzip8) == {
'compression': h5py.h5z.FILTER_DEFLATE,
'compression_opts': (8,)
}
# Pass object as compression argument (new in h5py 3.0)
ds = writable_file.create_dataset(
'x', shape=(100,), dtype=np.uint32, compression=gzip8
)
assert ds.compression == 'gzip'
assert ds.compression_opts == 8
def test_filter_ref_obj_eq():
gzip8 = h5py.filters.Gzip(level=8)
assert gzip8 == h5py.filters.Gzip(level=8)
assert gzip8 != h5py.filters.Gzip(level=7)
@ut.skipIf(not os.getenv('H5PY_TEST_CHECK_FILTERS'), "H5PY_TEST_CHECK_FILTERS not set")
def test_filters_available():
assert 'gzip' in h5py.filters.decode
assert 'gzip' in h5py.filters.encode
assert 'lzf' in h5py.filters.decode
assert 'lzf' in h5py.filters.encode
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,45 @@
# 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.
from h5py import h5
from .common import TestCase
def fixnames():
cfg = h5.get_config()
cfg.complex_names = ('r','i')
class TestH5(TestCase):
def test_config(self):
cfg = h5.get_config()
self.assertIsInstance(cfg, h5.H5PYConfig)
cfg2 = h5.get_config()
self.assertIs(cfg, cfg2)
def test_cnames_get(self):
cfg = h5.get_config()
self.assertEqual(cfg.complex_names, ('r','i'))
def test_cnames_set(self):
self.addCleanup(fixnames)
cfg = h5.get_config()
cfg.complex_names = ('q','x')
self.assertEqual(cfg.complex_names, ('q','x'))
def test_cnames_set_exc(self):
self.addCleanup(fixnames)
cfg = h5.get_config()
with self.assertRaises(TypeError):
cfg.complex_names = ('q','i','v')
self.assertEqual(cfg.complex_names, ('r','i'))
def test_repr(self):
cfg = h5.get_config()
repr(cfg)
@@ -0,0 +1,184 @@
import h5py
import numpy
import numpy.testing
import pytest
from .common import ut, TestCase
class TestWriteDirectChunk(TestCase):
def test_write_direct_chunk(self):
filename = self.mktemp().encode()
with h5py.File(filename, "w") as filehandle:
dataset = filehandle.create_dataset("data", (100, 100, 100),
maxshape=(None, 100, 100),
chunks=(1, 100, 100),
dtype='float32')
# writing
array = numpy.zeros((10, 100, 100))
for index in range(10):
a = numpy.random.rand(100, 100).astype('float32')
dataset.id.write_direct_chunk((index, 0, 0), a.tobytes(), filter_mask=1)
array[index] = a
# checking
with h5py.File(filename, "r") as filehandle:
for i in range(10):
read_data = filehandle["data"][i]
numpy.testing.assert_array_equal(array[i], read_data)
@ut.skipIf('gzip' not in h5py.filters.encode, "DEFLATE is not installed")
class TestReadDirectChunk(TestCase):
def test_read_compressed_offsets(self):
filename = self.mktemp().encode()
with h5py.File(filename, "w") as filehandle:
frame = numpy.arange(16).reshape(4, 4)
frame_dataset = filehandle.create_dataset("frame",
data=frame,
compression="gzip",
compression_opts=9)
dataset = filehandle.create_dataset("compressed_chunked",
data=[frame, frame, frame],
compression="gzip",
compression_opts=9,
chunks=(1, ) + frame.shape)
filter_mask, compressed_frame = frame_dataset.id.read_direct_chunk((0, 0))
# No filter must be disabled
self.assertEqual(filter_mask, 0)
for i in range(dataset.shape[0]):
filter_mask, data = dataset.id.read_direct_chunk((i, 0, 0))
self.assertEqual(compressed_frame, data)
# No filter must be disabled
self.assertEqual(filter_mask, 0)
def test_read_uncompressed_offsets(self):
filename = self.mktemp().encode()
frame = numpy.arange(16).reshape(4, 4)
with h5py.File(filename, "w") as filehandle:
dataset = filehandle.create_dataset("frame",
maxshape=(1,) + frame.shape,
shape=(1,) + frame.shape,
compression="gzip",
compression_opts=9)
# Write uncompressed data
DISABLE_ALL_FILTERS = 0xFFFFFFFF
dataset.id.write_direct_chunk((0, 0, 0), frame.tobytes(), filter_mask=DISABLE_ALL_FILTERS)
# FIXME: Here we have to close the file and load it back else
# a runtime error occurs:
# RuntimeError: Can't get storage size of chunk (chunk storage is not allocated)
with h5py.File(filename, "r") as filehandle:
dataset = filehandle["frame"]
filter_mask, compressed_frame = dataset.id.read_direct_chunk((0, 0, 0))
# At least 1 filter is supposed to be disabled
self.assertNotEqual(filter_mask, 0)
self.assertEqual(compressed_frame, frame.tobytes())
def test_read_write_chunk(self):
filename = self.mktemp().encode()
with h5py.File(filename, "w") as filehandle:
# create a reference
frame = numpy.arange(16).reshape(4, 4)
frame_dataset = filehandle.create_dataset("source",
data=frame,
compression="gzip",
compression_opts=9)
# configure an empty dataset
filter_mask, compressed_frame = frame_dataset.id.read_direct_chunk((0, 0))
dataset = filehandle.create_dataset("created",
shape=frame_dataset.shape,
maxshape=frame_dataset.shape,
chunks=frame_dataset.chunks,
dtype=frame_dataset.dtype,
compression="gzip",
compression_opts=9)
# copy the data
dataset.id.write_direct_chunk((0, 0), compressed_frame, filter_mask=filter_mask)
# checking
with h5py.File(filename, "r") as filehandle:
dataset = filehandle["created"][...]
numpy.testing.assert_array_equal(dataset, frame)
class TestReadDirectChunkToOut:
def test_uncompressed_data(self, writable_file):
ref_data = numpy.arange(16).reshape(4, 4)
dataset = writable_file.create_dataset(
"uncompressed", data=ref_data, chunks=ref_data.shape)
out = bytearray(ref_data.nbytes)
filter_mask, chunk = dataset.id.read_direct_chunk((0, 0), out=out)
assert numpy.array_equal(
numpy.frombuffer(out, dtype=ref_data.dtype).reshape(ref_data.shape),
ref_data,
)
assert filter_mask == 0
assert len(chunk) == ref_data.nbytes
@pytest.mark.skipif(
'gzip' not in h5py.filters.encode,
reason="DEFLATE is not installed",
)
def test_compressed_data(self, writable_file):
ref_data = numpy.arange(16).reshape(4, 4)
dataset = writable_file.create_dataset(
"gzip",
data=ref_data,
chunks=ref_data.shape,
compression="gzip",
compression_opts=9,
)
chunk_info = dataset.id.get_chunk_info(0)
out = bytearray(chunk_info.size)
filter_mask, chunk = dataset.id.read_direct_chunk(
chunk_info.chunk_offset,
out=out,
)
assert filter_mask == chunk_info.filter_mask
assert len(chunk) == chunk_info.size
assert out == dataset.id.read_direct_chunk(chunk_info.chunk_offset)[1]
def test_fail_buffer_too_small(self, writable_file):
ref_data = numpy.arange(16).reshape(4, 4)
dataset = writable_file.create_dataset(
"uncompressed", data=ref_data, chunks=ref_data.shape)
out = bytearray(ref_data.nbytes // 2)
with pytest.raises(ValueError):
dataset.id.read_direct_chunk((0, 0), out=out)
def test_fail_buffer_readonly(self, writable_file):
ref_data = numpy.arange(16).reshape(4, 4)
dataset = writable_file.create_dataset(
"uncompressed", data=ref_data, chunks=ref_data.shape)
out = bytes(ref_data.nbytes)
with pytest.raises(BufferError):
dataset.id.read_direct_chunk((0, 0), out=out)
def test_fail_buffer_not_contiguous(self, writable_file):
ref_data = numpy.arange(16).reshape(4, 4)
dataset = writable_file.create_dataset(
"uncompressed", data=ref_data, chunks=ref_data.shape)
array = numpy.empty(ref_data.shape + (2,), dtype=ref_data.dtype)
out = array[:, :, ::2] # Array is not contiguous
with pytest.raises(ValueError):
dataset.id.read_direct_chunk((0, 0), out=out)
@@ -0,0 +1,108 @@
# 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.
import tempfile
import shutil
import os
import numpy as np
from h5py import File, special_dtype
from h5py._hl.files import direct_vfd
from .common import ut, TestCase
class TestFileID(TestCase):
def test_descriptor_core(self):
with File('TestFileID.test_descriptor_core', driver='core',
backing_store=False, mode='x') as f:
assert isinstance(f.id.get_vfd_handle(), int)
def test_descriptor_sec2(self):
dn_tmp = tempfile.mkdtemp('h5py.lowtest.test_h5f.TestFileID.test_descriptor_sec2')
fn_h5 = os.path.join(dn_tmp, 'test.h5')
try:
with File(fn_h5, driver='sec2', mode='x') as f:
descriptor = f.id.get_vfd_handle()
self.assertNotEqual(descriptor, 0)
os.fsync(descriptor)
finally:
shutil.rmtree(dn_tmp)
@ut.skipUnless(direct_vfd,
"DIRECT driver is supported on Linux if hdf5 is "
"built with the appriorate flags.")
def test_descriptor_direct(self):
dn_tmp = tempfile.mkdtemp('h5py.lowtest.test_h5f.TestFileID.test_descriptor_direct')
fn_h5 = os.path.join(dn_tmp, 'test.h5')
try:
with File(fn_h5, driver='direct', mode='x') as f:
descriptor = f.id.get_vfd_handle()
self.assertNotEqual(descriptor, 0)
os.fsync(descriptor)
finally:
shutil.rmtree(dn_tmp)
class TestCacheConfig(TestCase):
def test_simple_gets(self):
dn_tmp = tempfile.mkdtemp('h5py.lowtest.test_h5f.TestFileID.TestCacheConfig.test_simple_gets')
fn_h5 = os.path.join(dn_tmp, 'test.h5')
try:
with File(fn_h5, mode='x') as f:
hit_rate = f._id.get_mdc_hit_rate()
mdc_size = f._id.get_mdc_size()
finally:
shutil.rmtree(dn_tmp)
def test_hitrate_reset(self):
dn_tmp = tempfile.mkdtemp('h5py.lowtest.test_h5f.TestFileID.TestCacheConfig.test_hitrate_reset')
fn_h5 = os.path.join(dn_tmp, 'test.h5')
try:
with File(fn_h5, mode='x') as f:
hit_rate = f._id.get_mdc_hit_rate()
f._id.reset_mdc_hit_rate_stats()
hit_rate = f._id.get_mdc_hit_rate()
assert hit_rate == 0
finally:
shutil.rmtree(dn_tmp)
def test_mdc_config_get(self):
dn_tmp = tempfile.mkdtemp('h5py.lowtest.test_h5f.TestFileID.TestCacheConfig.test_mdc_config_get')
fn_h5 = os.path.join(dn_tmp, 'test.h5')
try:
with File(fn_h5, mode='x') as f:
conf = f._id.get_mdc_config()
f._id.set_mdc_config(conf)
finally:
shutil.rmtree(dn_tmp)
class TestVlenData(TestCase):
def test_vlen_strings(self):
# Create file with dataset containing vlen arrays of vlen strings
dn_tmp = tempfile.mkdtemp('h5py.lowtest.test_h5f.TestVlenStrings.test_vlen_strings')
fn_h5 = os.path.join(dn_tmp, 'test.h5')
try:
with File(fn_h5, mode='w') as h:
vlen_str = special_dtype(vlen=str)
vlen_vlen_str = special_dtype(vlen=vlen_str)
ds = h.create_dataset('/com', (2,), dtype=vlen_vlen_str)
ds[0] = (np.array(["a", "b", "c"], dtype=vlen_vlen_str))
ds[1] = (np.array(["d", "e", "f","g"], dtype=vlen_vlen_str))
with File(fn_h5, "r") as h:
ds = h["com"]
assert ds[0].tolist() == [b'a', b'b', b'c']
assert ds[1].tolist() == [b'd', b'e', b'f', b'g']
finally:
shutil.rmtree(dn_tmp)
@@ -0,0 +1,21 @@
import pytest
from .common import TestCase
from h5py import File
class SampleException(Exception):
pass
def throwing(name, obj):
print(name, obj)
raise SampleException("throwing exception")
class TestVisit(TestCase):
def test_visit(self):
fname = self.mktemp()
fid = File(fname, 'w')
fid.create_dataset('foo', (100,), dtype='uint8')
with pytest.raises(SampleException, match='throwing exception'):
fid.visititems(throwing)
fid.close()
@@ -0,0 +1,233 @@
# 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.
import unittest as ut
from h5py import h5p, h5f, version
from .common import TestCase
class TestLibver(TestCase):
"""
Feature: Setting/getting lib ver bounds
"""
def test_libver(self):
""" Test libver bounds set/get """
plist = h5p.create(h5p.FILE_ACCESS)
plist.set_libver_bounds(h5f.LIBVER_EARLIEST, h5f.LIBVER_LATEST)
self.assertEqual((h5f.LIBVER_EARLIEST, h5f.LIBVER_LATEST),
plist.get_libver_bounds())
def test_libver_v18(self):
""" Test libver bounds set/get for H5F_LIBVER_V18"""
plist = h5p.create(h5p.FILE_ACCESS)
plist.set_libver_bounds(h5f.LIBVER_EARLIEST, h5f.LIBVER_V18)
self.assertEqual((h5f.LIBVER_EARLIEST, h5f.LIBVER_V18),
plist.get_libver_bounds())
def test_libver_v110(self):
""" Test libver bounds set/get for H5F_LIBVER_V110"""
plist = h5p.create(h5p.FILE_ACCESS)
plist.set_libver_bounds(h5f.LIBVER_V18, h5f.LIBVER_V110)
self.assertEqual((h5f.LIBVER_V18, h5f.LIBVER_V110),
plist.get_libver_bounds())
@ut.skipIf(version.hdf5_version_tuple < (1, 11, 4),
'Requires HDF5 1.11.4 or later')
def test_libver_v112(self):
""" Test libver bounds set/get for H5F_LIBVER_V112"""
plist = h5p.create(h5p.FILE_ACCESS)
plist.set_libver_bounds(h5f.LIBVER_V18, h5f.LIBVER_V112)
self.assertEqual((h5f.LIBVER_V18, h5f.LIBVER_V112),
plist.get_libver_bounds())
@ut.skipIf(version.hdf5_version_tuple < (1, 14, 0),
'Requires HDF5 1.14 or later')
def test_libver_v114(self):
""" Test libver bounds set/get for H5F_LIBVER_V114"""
plist = h5p.create(h5p.FILE_ACCESS)
plist.set_libver_bounds(h5f.LIBVER_V18, h5f.LIBVER_V114)
self.assertEqual((h5f.LIBVER_V18, h5f.LIBVER_V114),
plist.get_libver_bounds())
@ut.skipIf(version.hdf5_version_tuple < (2, 0, 0),
'Requires HDF5 2.0 or later')
def test_libver_v200(self):
""" Test libver bounds set/get for H5F_LIBVER_V200"""
plist = h5p.create(h5p.FILE_ACCESS)
plist.set_libver_bounds(h5f.LIBVER_V18, h5f.LIBVER_V200)
self.assertEqual((h5f.LIBVER_V18, h5f.LIBVER_V200),
plist.get_libver_bounds())
class TestDA(TestCase):
'''
Feature: setting/getting chunk cache size on a dataset access property list
'''
def test_chunk_cache(self):
'''test get/set chunk cache '''
dalist = h5p.create(h5p.DATASET_ACCESS)
nslots = 10000 # 40kb hash table
nbytes = 1000000 # 1MB cache size
w0 = .5 # even blend of eviction strategy
dalist.set_chunk_cache(nslots, nbytes, w0)
self.assertEqual((nslots, nbytes, w0),
dalist.get_chunk_cache())
def test_efile_prefix(self):
'''test get/set efile prefix '''
dalist = h5p.create(h5p.DATASET_ACCESS)
self.assertEqual(dalist.get_efile_prefix().decode(), '')
efile_prefix = "path/to/external/dataset"
dalist.set_efile_prefix(efile_prefix.encode('utf-8'))
self.assertEqual(dalist.get_efile_prefix().decode(),
efile_prefix)
efile_prefix = "${ORIGIN}"
dalist.set_efile_prefix(efile_prefix.encode('utf-8'))
self.assertEqual(dalist.get_efile_prefix().decode(),
efile_prefix)
def test_virtual_prefix(self):
'''test get/set virtual prefix '''
dalist = h5p.create(h5p.DATASET_ACCESS)
self.assertEqual(dalist.get_virtual_prefix().decode(), '')
virtual_prefix = "path/to/virtual/dataset"
dalist.set_virtual_prefix(virtual_prefix.encode('utf-8'))
self.assertEqual(dalist.get_virtual_prefix().decode(),
virtual_prefix)
class TestFA(TestCase):
'''
Feature: setting/getting mdc config on a file access property list
'''
def test_mdc_config(self):
'''test get/set mdc config '''
falist = h5p.create(h5p.FILE_ACCESS)
config = falist.get_mdc_config()
falist.set_mdc_config(config)
def test_set_alignment(self):
'''test get/set chunk cache '''
falist = h5p.create(h5p.FILE_ACCESS)
threshold = 10 * 1024 # threshold of 10kiB
alignment = 1024 * 1024 # threshold of 1kiB
falist.set_alignment(threshold, alignment)
self.assertEqual((threshold, alignment),
falist.get_alignment())
def test_set_file_locking(self):
'''test get/set file locking'''
falist = h5p.create(h5p.FILE_ACCESS)
use_file_locking = False
ignore_when_disabled = False
falist.set_file_locking(use_file_locking, ignore_when_disabled)
self.assertEqual((use_file_locking, ignore_when_disabled),
falist.get_file_locking())
class TestPL(TestCase):
def test_obj_track_times(self):
"""
tests if the object track times set/get
"""
# test for groups
gcid = h5p.create(h5p.GROUP_CREATE)
gcid.set_obj_track_times(False)
self.assertEqual(False, gcid.get_obj_track_times())
gcid.set_obj_track_times(True)
self.assertEqual(True, gcid.get_obj_track_times())
# test for datasets
dcid = h5p.create(h5p.DATASET_CREATE)
dcid.set_obj_track_times(False)
self.assertEqual(False, dcid.get_obj_track_times())
dcid.set_obj_track_times(True)
self.assertEqual(True, dcid.get_obj_track_times())
# test for generic objects
ocid = h5p.create(h5p.OBJECT_CREATE)
ocid.set_obj_track_times(False)
self.assertEqual(False, ocid.get_obj_track_times())
ocid.set_obj_track_times(True)
self.assertEqual(True, ocid.get_obj_track_times())
def test_link_creation_tracking(self):
"""
tests the link creation order set/get
"""
gcid = h5p.create(h5p.GROUP_CREATE)
gcid.set_link_creation_order(0)
self.assertEqual(0, gcid.get_link_creation_order())
flags = h5p.CRT_ORDER_TRACKED | h5p.CRT_ORDER_INDEXED
gcid.set_link_creation_order(flags)
self.assertEqual(flags, gcid.get_link_creation_order())
# test for file creation
fcpl = h5p.create(h5p.FILE_CREATE)
fcpl.set_link_creation_order(flags)
self.assertEqual(flags, fcpl.get_link_creation_order())
def test_attr_phase_change(self):
"""
test the attribute phase change
"""
cid = h5p.create(h5p.OBJECT_CREATE)
# test default value
ret = cid.get_attr_phase_change()
self.assertEqual((8,6), ret)
# max_compact must < 65536 (64kb)
with self.assertRaises(ValueError):
cid.set_attr_phase_change(65536, 6)
# Using dense attributes storage to avoid 64kb size limitation
# for a single attribute in compact attribute storage.
cid.set_attr_phase_change(0, 0)
self.assertEqual((0,0), cid.get_attr_phase_change())
def test_proplaid():
"""Test Link Access Property List"""
lapl = h5p.create(h5p.LINK_ACCESS)
nlinks = 3
lapl.set_nlinks(nlinks)
assert lapl.get_nlinks() == nlinks
prefix = b"/prefix"
lapl.set_elink_prefix(prefix)
assert lapl.get_elink_prefix() == prefix
flags = h5f.ACC_RDWR & h5f.ACC_SWMR_WRITE
lapl.set_elink_acc_flags(flags)
assert lapl.get_elink_acc_flags() == flags
fapl = h5p.create(h5p.FILE_ACCESS)
fapl.set_file_locking(False, False)
lapl.set_elink_fapl(fapl)
assert lapl.get_elink_fapl().get_file_locking() == (False, False)
fapl.close()
lapl.close()
@@ -0,0 +1,68 @@
# This file is part of h5py, a Python interface to the HDF5 library.
#
# http://www.h5py.org
#
# Copyright 2008-2019 Andrew Collette and contributors
#
# License: Standard 3-clause BSD; see "license.txt" for full license terms
# and contributor agreement.
import pytest
from h5py import h5pl
from h5py.tests.common import insubprocess, subproc_env
@pytest.mark.mpi_skip
@insubprocess
@subproc_env({'HDF5_PLUGIN_PATH': 'h5py_plugin_test'})
def test_default(request):
assert h5pl.size() == 1
assert h5pl.get(0) == b'h5py_plugin_test'
@pytest.mark.mpi_skip
@insubprocess
@subproc_env({'HDF5_PLUGIN_PATH': 'h5py_plugin_test'})
def test_append(request):
h5pl.append(b'/opt/hdf5/vendor-plugin')
assert h5pl.size() == 2
assert h5pl.get(0) == b'h5py_plugin_test'
assert h5pl.get(1) == b'/opt/hdf5/vendor-plugin'
@pytest.mark.mpi_skip
@insubprocess
@subproc_env({'HDF5_PLUGIN_PATH': 'h5py_plugin_test'})
def test_prepend(request):
h5pl.prepend(b'/opt/hdf5/vendor-plugin')
assert h5pl.size() == 2
assert h5pl.get(0) == b'/opt/hdf5/vendor-plugin'
assert h5pl.get(1) == b'h5py_plugin_test'
@pytest.mark.mpi_skip
@insubprocess
@subproc_env({'HDF5_PLUGIN_PATH': 'h5py_plugin_test'})
def test_insert(request):
h5pl.insert(b'/opt/hdf5/vendor-plugin', 0)
assert h5pl.size() == 2
assert h5pl.get(0) == b'/opt/hdf5/vendor-plugin'
assert h5pl.get(1) == b'h5py_plugin_test'
@pytest.mark.mpi_skip
@insubprocess
@subproc_env({'HDF5_PLUGIN_PATH': 'h5py_plugin_test'})
def test_replace(request):
h5pl.replace(b'/opt/hdf5/vendor-plugin', 0)
assert h5pl.size() == 1
assert h5pl.get(0) == b'/opt/hdf5/vendor-plugin'
@pytest.mark.mpi_skip
@insubprocess
@subproc_env({'HDF5_PLUGIN_PATH': 'h5py_plugin_test'})
def test_remove(request):
h5pl.remove(0)
assert h5pl.size() == 0
@@ -0,0 +1,24 @@
from h5py import h5s
from h5py._selector import Selector
class Helper:
def __init__(self, shape: tuple):
self.shape = shape
def __getitem__(self, item) -> h5s.SpaceID:
if not isinstance(item, tuple):
item = (item,)
space = h5s.create_simple(self.shape)
sel = Selector(space)
sel.make_selection(item)
return space
def test_same_shape():
s1 = Helper((5, 6))[:3, :4]
s2 = Helper((5, 6))[2:, 2:]
assert s1.select_shape_same(s2)
s3 = Helper((5, 6))[:4, :3]
assert not s1.select_shape_same(s3)
@@ -0,0 +1,188 @@
# 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.
import numpy as np
import h5py
from h5py import h5t
from .common import TestCase, ut
class TestCompound(ut.TestCase):
"""
Feature: Compound types can be created from Python dtypes
"""
def test_ref(self):
""" Reference types are correctly stored in compound types (issue 144)
"""
dt = np.dtype([('a', h5py.ref_dtype), ('b', '<f4')])
tid = h5t.py_create(dt, logical=True)
t1, t2 = tid.get_member_type(0), tid.get_member_type(1)
self.assertEqual(t1, h5t.STD_REF_OBJ)
self.assertEqual(t2, h5t.IEEE_F32LE)
self.assertEqual(tid.get_member_offset(0), 0)
self.assertEqual(tid.get_member_offset(1), h5t.STD_REF_OBJ.get_size())
def test_out_of_order_offsets(self):
size = 20
type_dict = {
'names': ['f1', 'f2', 'f3'],
'formats': ['<f4', '<i4', '<f8'],
'offsets': [0, 16, 8]
}
expected_dtype = np.dtype(type_dict)
tid = h5t.create(h5t.COMPOUND, size)
for name, offset, dt in zip(
type_dict["names"], type_dict["offsets"], type_dict["formats"], strict=True
):
tid.insert(
name.encode("utf8") if isinstance(name, str) else name,
offset,
h5t.py_create(dt)
)
self.assertEqual(tid.dtype, expected_dtype)
self.assertEqual(tid.dtype.itemsize, size)
class TestTypeFloatID(TestCase):
"""Test TypeFloatID."""
def test_custom_float_promotion(self):
"""Custom floats are correctly promoted to standard floats on read."""
# This test uses the low-level API, so we need names as byte strings
test_filename = self.mktemp().encode()
dataset = b'DS1'
dataset2 = b'DS2'
dataset3 = b'DS3'
dataset4 = b'DS4'
dataset5 = b'DS5'
dims = (4, 7)
wdata = np.array([[-1.50066626e-09, 1.40062184e-09, 1.81216819e-10,
4.01087163e-10, 4.27917257e-10, -7.04858394e-11,
5.74800652e-10],
[-1.50066626e-09, 4.86579665e-10, 3.42879503e-10,
5.12045517e-10, 5.10226528e-10, 2.24190444e-10,
3.93356459e-10],
[-1.50066626e-09, 5.24778443e-10, 8.19454726e-10,
1.28966349e-09, 1.68483894e-10, 5.71276360e-11,
-1.08684617e-10],
[-1.50066626e-09, -1.08343556e-10, -1.58934199e-10,
8.52196536e-10, 6.18456397e-10, 6.16637408e-10,
1.31694833e-09]], dtype=np.float32)
wdata2 = np.array([[-1.50066626e-09, 5.63886715e-10, -8.74251782e-11,
1.32558853e-10, 1.59161573e-10, 2.29420039e-10,
-7.24185156e-11],
[-1.50066626e-09, 1.87810656e-10, 7.74889486e-10,
3.95630195e-10, 9.42236511e-10, 8.38554115e-10,
-8.71978045e-11],
[-1.50066626e-09, 6.20275387e-10, 7.34871719e-10,
6.64840627e-10, 2.64662958e-10, 1.05319486e-09,
1.68256520e-10],
[-1.50066626e-09, 1.67347025e-10, 5.12045517e-10,
3.36513040e-10, 1.02545528e-10, 1.28784450e-09,
4.06089384e-10]], dtype=np.float32)
# Create a new file using the default properties.
fid = h5py.h5f.create(test_filename)
# Create the dataspace. No maximum size parameter needed.
space = h5py.h5s.create_simple(dims)
# create a custom type with larger bias
mytype = h5t.IEEE_F16LE.copy()
mytype.set_fields(14, 9, 5, 0, 9)
mytype.set_size(2)
mytype.set_ebias(53)
mytype.lock()
dset = h5py.h5d.create(fid, dataset, mytype, space)
dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata)
del dset
# create a custom type with larger exponent
mytype2 = h5t.IEEE_F16LE.copy()
mytype2.set_fields(15, 9, 6, 0, 9)
mytype2.set_size(2)
mytype2.set_ebias(53)
mytype2.lock()
dset = h5py.h5d.create(fid, dataset2, mytype2, space)
dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2)
del dset
# create a custom type which reimplements 16-bit floats
mytype3 = h5t.IEEE_F16LE.copy()
mytype3.set_fields(15, 10, 5, 0, 10)
mytype3.set_size(2)
mytype3.set_ebias(15)
mytype3.lock()
dset = h5py.h5d.create(fid, dataset3, mytype3, space)
dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2)
del dset
# create a custom type with larger bias
mytype4 = h5t.IEEE_F16LE.copy()
mytype4.set_fields(15, 10, 5, 0, 10)
mytype4.set_size(2)
mytype4.set_ebias(258)
mytype4.lock()
dset = h5py.h5d.create(fid, dataset4, mytype4, space)
dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2)
del dset
# create a dataset with long doubles
dset = h5py.h5d.create(fid, dataset5, h5t.NATIVE_LDOUBLE, space)
dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2)
# Explicitly close and release resources.
del space
del dset
del fid
f = h5py.File(test_filename, 'r')
# ebias promotion to float32
values = f[dataset][:]
np.testing.assert_array_equal(values, wdata)
self.assertEqual(values.dtype, np.dtype('<f4'))
# esize promotion to float32
values = f[dataset2][:]
np.testing.assert_array_equal(values, wdata2)
self.assertEqual(values.dtype, np.dtype('<f4'))
# regular half floats
dset = f[dataset3]
try:
self.assertEqual(dset.dtype, np.dtype('<f2'))
except AttributeError:
self.assertEqual(dset.dtype, np.dtype('<f4'))
# ebias promotion to float64
dset = f[dataset4]
self.assertEqual(dset.dtype, np.dtype('<f8'))
# long double floats
dset = f[dataset5]
self.assertEqual(dset.dtype, np.longdouble)
@@ -0,0 +1,85 @@
from ctypes import (
addressof,
c_char_p,
c_int,
c_long,
c_uint,
c_void_p,
CFUNCTYPE,
POINTER,
Structure,
)
import pytest
import h5py
from h5py import h5z
from .common import insubprocess
# Type of filter callback function of H5Z_class2_t
H5ZFuncT = CFUNCTYPE(
c_long, # restype
# argtypes
c_uint, # flags
c_long, # cd_nelemts
POINTER(c_uint), # cd_values
c_long, # nbytes
POINTER(c_long), # buf_size
POINTER(c_void_p), # buf
)
class H5ZClass2T(Structure):
"""H5Z_class2_t structure defining a filter"""
_fields_ = [
("version", c_int),
("id_", c_int),
("encoder_present", c_uint),
("decoder_present", c_uint),
("name", c_char_p),
("can_apply", c_void_p),
("set_local", c_void_p),
("filter_", H5ZFuncT),
]
def test_register_filter():
filter_id = 256 # Test ID
@H5ZFuncT
def failing_filter_callback(flags, cd_nelemts, cd_values, nbytes, buf_size, buf):
return 0
dummy_filter_class = H5ZClass2T(
version=h5z.CLASS_T_VERS,
id_=filter_id,
encoder_present=1,
decoder_present=1,
name=b"dummy filter",
can_apply=None,
set_local=None,
filter_=failing_filter_callback,
)
h5z.register_filter(addressof(dummy_filter_class))
try:
assert h5z.filter_avail(filter_id)
filter_flags = h5z.get_filter_info(filter_id)
assert (
filter_flags
== h5z.FILTER_CONFIG_ENCODE_ENABLED | h5z.FILTER_CONFIG_DECODE_ENABLED
)
finally:
h5z.unregister_filter(filter_id)
assert not h5z.filter_avail(filter_id)
@pytest.mark.mpi_skip
@insubprocess
def test_unregister_filter(request):
if h5py.h5z.filter_avail(h5py.h5z.FILTER_LZF):
res = h5py.h5z.unregister_filter(h5py.h5z.FILTER_LZF)
assert res
@@ -0,0 +1,178 @@
import numpy as np
import pytest
import h5py
NUMPY_GE2 = int(np.__version__.split(".")[0]) >= 2
pytestmark = pytest.mark.skipif(not NUMPY_GE2, reason="requires numpy >=2.0")
def test_create_with_dtype_T(writable_file):
ds = writable_file.create_dataset("x", shape=(2, 2), dtype="T")
data = [["foo", "bar"], ["hello world", ""]]
ds[:] = data
a = ds.asstr()[:]
np.testing.assert_array_equal(a, data)
ds = writable_file["x"]
assert ds.dtype == object
np.testing.assert_array_equal(ds.asstr()[:], data)
ds[0, 0] = "baz"
data[0][0] = "baz"
a = ds.astype("T")[:]
assert a.dtype.kind == "T"
np.testing.assert_array_equal(a, data)
ds[0, 0] = np.asarray("123", dtype="O")
data[0][0] = "123"
np.testing.assert_array_equal(ds.asstr()[:], data)
def test_fromdata(writable_file):
data = [["foo", "bar"]]
np_data = np.asarray(data, dtype="T")
x = writable_file.create_dataset("x", data=data, dtype="T")
y = writable_file.create_dataset("y", data=data, dtype=np.dtypes.StringDType())
z = writable_file.create_dataset("z", data=np_data)
for ds in (x, y, z):
assert ds.dtype.kind == "O"
np.testing.assert_array_equal(ds.astype("T")[:], np_data)
for name in ("x", "y", "z"):
ds = writable_file[name]
assert ds.dtype == object
np.testing.assert_array_equal(ds.asstr()[:], data)
ds = ds.astype("T")
assert ds.dtype.kind == "T"
a = ds[:]
assert a.dtype.kind == "T"
np.testing.assert_array_equal(a, data)
def test_fixed_to_variable_width(writable_file):
data = ["foo", "longer than 8 bytes"]
x = writable_file.create_dataset(
"x", data=data, dtype=h5py.string_dtype(length=20)
)
assert x.dtype == "S20"
# read T <- S
y = x.astype("T")
assert y.dtype.kind == "T"
assert y[:].dtype.kind == "T"
np.testing.assert_array_equal(y[:], data)
# write T -> S
x[0] = np.asarray("1234", dtype="T")
data[0] = "1234"
np.testing.assert_array_equal(y[:], data)
def test_fixed_to_variable_width_too_short(writable_file):
# Note: this test triggers calls to H5Tconvert which are otherwise skipped.
data = ["foo", "bar"]
x = writable_file.create_dataset(
"x", data=data, dtype=h5py.string_dtype(length=3)
)
assert x.dtype == "S3"
# write T -> S
x[0] = np.asarray("1234", dtype="T")
np.testing.assert_array_equal(x[:], [b"123", b"bar"])
def test_variable_to_fixed_width(writable_file):
data = ["foo", "longer than 8 bytes"]
bdata = [b"foo", b"longer than 8 bytes"]
x = writable_file.create_dataset("x", data=data, dtype="T")
# read S <- T
y = x.astype("S20")
assert y.dtype == "S20"
assert y[:].dtype == "S20"
np.testing.assert_array_equal(y[:], bdata)
y = x.astype("S3")
assert y.dtype == "S3"
assert y[:].dtype == "S3"
np.testing.assert_array_equal(y[:], [b"foo", b"lon"])
# write S -> T
x[0] = np.asarray(b"1234", dtype="S5")
bdata[0] = b"1234"
np.testing.assert_array_equal(x[:], bdata)
def test_write_object_into_npystrings(writable_file):
x = writable_file.create_dataset("x", data=["foo"], dtype="T")
x[0] = np.asarray("1234", dtype="O")
np.testing.assert_array_equal(x[:], b"1234")
def test_write_npystrings_into_object(writable_file):
x = writable_file.create_dataset(
"x", data=["foo"], dtype=h5py.string_dtype()
)
assert x.dtype == object
x[0] = np.asarray("1234", dtype="T")
np.testing.assert_array_equal(x[:], b"1234")
# Test with HDF5 variable-length strings with ASCII character set
xa = writable_file.create_dataset(
"xa", shape=(1,), dtype=h5py.string_dtype('ascii')
)
xa[0] = np.asarray("2345", dtype="T")
np.testing.assert_array_equal(xa[:], b"2345")
def test_fillvalue(writable_file):
# Create as NpyString dtype
x = writable_file.create_dataset("x", shape=(2,), dtype="T", fillvalue="foo")
assert isinstance(x.fillvalue, bytes)
assert x.fillvalue == b"foo"
assert x[0] == b"foo"
# Create as object dtype
y = writable_file.create_dataset(
"y", shape=(2,), dtype=h5py.string_dtype(), fillvalue=b"foo"
)
assert isinstance(y.fillvalue, bytes)
assert y.fillvalue == b"foo"
assert y[0] == b"foo"
# Convert object dtype to NpyString
y = y.astype("T")
assert y[0] == "foo"
def test_empty_string(writable_file):
data = np.array(["", "a", "b"], dtype="T")
x = writable_file.create_dataset("x", data=data)
np.testing.assert_array_equal(x[:], [b"", b"a", b"b"])
np.testing.assert_array_equal(x.astype("T")[:], data)
data[:2] = ["c", ""]
x[:2] = data[:2]
np.testing.assert_array_equal(x[:], [b"c", b"", b"b"])
np.testing.assert_array_equal(x.astype("T")[:], data)
def test_astype_nonstring(writable_file):
x = writable_file.create_dataset("x", shape=(2, ), dtype="i8")
with pytest.raises(TypeError, match="HDF5 string datatype"):
x.astype("T")
def test_resized_read(writable_file):
"""Read default values created by resize(). This triggers a special case
where libhdf5 returns a char** containing NULL pointers.
"""
l = ["string1", "string2", "string3"]
data = np.array(l, dtype='T')
d = writable_file.create_dataset("dset", data=data, maxshape=(None,))
d.resize((10,))
np.testing.assert_array_equal(d[:], np.array(
[s.encode() for s in l] + [b''] * 7, dtype=object
))
np.testing.assert_array_equal(d.astype('T')[:], np.array(l + [''] * 7, dtype='T'))
@@ -0,0 +1,88 @@
# 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.
import os
import threading
from unittest import SkipTest
import time
from h5py import _objects as o
from .common import TestCase
class TestObjects(TestCase):
def test_invalid(self):
# Check for segfault on close
oid = o.ObjectID(0)
del oid
oid = o.ObjectID(1)
del oid
def test_equality(self):
# Identifier-based equality
oid1 = o.ObjectID(42)
oid2 = o.ObjectID(42)
oid3 = o.ObjectID(43)
self.assertEqual(oid1, oid2)
self.assertNotEqual(oid1, oid3)
def test_hash(self):
# Default objects are not hashable
oid = o.ObjectID(42)
with self.assertRaises(TypeError):
hash(oid)
def test_phil_fork_with_threads(self):
# Test that handling of the phil Lock after fork is correct.
# We simulate a deadlock in the forked process by explicitly
# waiting for the phil Lock to be acquired in a different thread
# before forking.
# On Windows forking (and the register_at_fork handler)
# are not available, skip this test.
if not hasattr(os, "fork"):
raise SkipTest("os.fork not available")
thread_acquired_phil_event = threading.Event()
def f():
o.phil.acquire()
try:
thread_acquired_phil_event.set()
time.sleep(1)
finally:
o.phil.release()
thread = threading.Thread(target=f)
thread.start()
try:
# wait for the thread running "f" to have acquired the phil lock
thread_acquired_phil_event.wait()
# now fork the current (main) thread while the other thread holds the lock
pid = os.fork()
if pid == 0:
# child process
# If we handle the phil lock correctly, this should not deadlock,
# and we should be able to acquire the lock here.
if o.phil.acquire(blocking=False):
o.phil.release()
os._exit(0)
else:
os._exit(1)
else:
# parent process
# wait for the child process to finish
_, status = os.waitpid(pid, 0)
assert os.WIFEXITED(status)
assert os.WEXITSTATUS(status) == 0
finally:
thread.join()
@@ -0,0 +1,112 @@
# 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.
"""
Read-only S3 virtual file driver (VFD) test module.
"""
import h5py
from h5py._hl.files import make_fapl
import pytest
pytestmark = [
pytest.mark.skipif(
not h5py.h5.get_config().ros3,
reason="ros3 driver not available")
]
@pytest.mark.network
@pytest.mark.parametrize(
"kwargs",
[
pytest.param(
{},
id="HDF5-v1",
marks=pytest.mark.skipif(
h5py.version.hdf5_version_tuple >= (2, 0, 0),
reason="Requires HDF5 < 2.0",
),
),
pytest.param(
{"aws_region": b"us-east-2"},
id="HDF5-v2",
marks=pytest.mark.skipif(
h5py.version.hdf5_version_tuple < (2, 0, 0),
reason="Requires HDF5 >= 2.0",
),
),
],
)
def test_ros3(kwargs):
""" ROS3 driver and options """
with h5py.File("https://dandiarchive.s3.amazonaws.com/ros3test.hdf5", 'r',
driver='ros3', **kwargs) as f:
assert f
assert 'mydataset' in f.keys()
assert f["mydataset"].shape == (100,)
@pytest.mark.parametrize(
"exc,match_exc",
[
pytest.param(
ValueError,
[
"AWS region required for s3:// location",
r"^foo://wrong/scheme: S3 location must begin with",
],
id="HDF5-v1",
marks=pytest.mark.skipif(
h5py.version.hdf5_version_tuple >= (2, 0, 0),
reason="Requires HDF5 < 2.0",
),
),
pytest.param(
OSError,
[None, "can't parse object key from path"],
id="HDF5-v2",
marks=pytest.mark.skipif(
h5py.version.hdf5_version_tuple < (2, 0, 0),
reason="Requires HDF5 >= 2.0",
),
),
],
)
def test_ros3_s3_fails(exc, match_exc):
"""ROS3 exceptions for s3:// location"""
with pytest.raises(exc, match=match_exc[0]):
h5py.File('s3://fakebucket/fakekey', 'r', driver='ros3')
with pytest.raises(exc, match=match_exc[1]):
h5py.File('foo://wrong/scheme', 'r', driver='ros3')
@pytest.mark.network
def test_ros3_s3uri():
"""Use S3 URI with ROS3 driver"""
with h5py.File('s3://dandiarchive/ros3test.hdf5', 'r', driver='ros3',
aws_region=b'us-east-2') as f:
assert f
assert 'mydataset' in f.keys()
assert f["mydataset"].shape == (100,)
@pytest.mark.skipif(h5py.version.hdf5_version_tuple < (1, 14, 2),
reason='AWS S3 access token support in HDF5 >= 1.14.2')
def test_ros3_temp_token():
"""Set and get S3 access token"""
token = b'#0123FakeToken4567/8/9'
fapl = make_fapl('ros3', libver=None, rdcc_nslots=None, rdcc_nbytes=None,
rdcc_w0=None, locking=None, page_buf_size=None, min_meta_keep=None,
min_raw_keep=None, alignment_threshold=1, alignment_interval=1,
meta_block_size=None, session_token=token)
assert token, fapl.get_fapl_ros3_token()
@@ -0,0 +1,142 @@
# 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.
"""
Tests for the (internal) selections module
"""
import numpy as np
import h5py
import h5py._hl.selections as sel
import h5py._hl.selections2 as sel2
from .common import TestCase
class BaseSelection(TestCase):
def setUp(self):
self.f = h5py.File(self.mktemp(), 'w')
self.dsid = self.f.create_dataset('x', ()).id
def tearDown(self):
if self.f:
self.f.close()
class TestTypeGeneration(BaseSelection):
"""
Internal feature: Determine output types from dataset dtype and fields.
"""
def test_simple(self):
""" Non-compound types are handled appropriately """
dt = np.dtype('i')
out, format = sel2.read_dtypes(dt, ())
self.assertEqual(out, format)
self.assertEqual(out, np.dtype('i'))
def test_simple_fieldexc(self):
""" Field names for non-field types raises ValueError """
dt = np.dtype('i')
with self.assertRaises(ValueError):
out, format = sel2.read_dtypes(dt, ('a',))
def test_compound_simple(self):
""" Compound types with elemental subtypes """
dt = np.dtype( [('a','i'), ('b','f'), ('c','|S10')] )
# Implicit selection of all fields -> all fields
out, format = sel2.read_dtypes(dt, ())
self.assertEqual(out, format)
self.assertEqual(out, dt)
# Explicit selection of fields -> requested fields
out, format = sel2.read_dtypes(dt, ('a','b'))
self.assertEqual(out, format)
self.assertEqual(out, np.dtype( [('a','i'), ('b','f')] ))
# Explicit selection of exactly one field -> no fields
out, format = sel2.read_dtypes(dt, ('a',))
self.assertEqual(out, np.dtype('i'))
self.assertEqual(format, np.dtype( [('a','i')] ))
# Field does not appear in named typed
with self.assertRaises(ValueError):
out, format = sel2.read_dtypes(dt, ('j', 'k'))
class TestScalarSliceRules(BaseSelection):
"""
Internal feature: selections rules for scalar datasets
"""
def test_args(self):
""" Permissible arguments for scalar slicing """
shape, selection = sel2.read_selections_scalar(self.dsid, ())
self.assertEqual(shape, None)
self.assertEqual(selection.get_select_npoints(), 1)
shape, selection = sel2.read_selections_scalar(self.dsid, (Ellipsis,))
self.assertEqual(shape, ())
self.assertEqual(selection.get_select_npoints(), 1)
with self.assertRaises(ValueError):
shape, selection = sel2.read_selections_scalar(self.dsid, (1,))
dsid = self.f.create_dataset('y', (1,)).id
with self.assertRaises(RuntimeError):
shape, selection = sel2.read_selections_scalar(dsid, (1,))
class TestSelection(BaseSelection):
""" High-level routes to generate a selection
"""
def test_selection(self):
dset = self.f.create_dataset('dset', (100,100))
regref = dset.regionref[0:100, 0:100]
# args is list, return a FancySelection
st = sel.select((10,), list([1,2,3]), dset)
self.assertIsInstance(st, sel.FancySelection)
# args[0] is tuple, return a FancySelection
st = sel.select((10,), ((1, 2, 3),), dset)
self.assertIsInstance(st, sel.FancySelection)
# args is a Boolean mask, return a PointSelection
st1 = sel.select((5,), np.array([True,False,False,False,True]), dset)
self.assertIsInstance(st1, sel.PointSelection)
# args is int, return a SimpleSelection
st2 = sel.select((10,), 1, dset)
self.assertIsInstance(st2, sel.SimpleSelection)
# args is str, should be rejected
with self.assertRaises(TypeError):
sel.select((100,), "foo", dset)
# args is RegionReference, return a Selection instance
st3 = sel.select((100,100), regref, dset)
self.assertIsInstance(st3, sel.Selection)
# args is RegionReference, but dataset is None
with self.assertRaises(TypeError):
sel.select((100,), regref, None)
# args is RegionReference, but its shape doesn't match dataset shape
with self.assertRaises(TypeError):
sel.select((100,), regref, dset)
# args is a single Selection instance, return the arg
st4 = sel.select((100,100), st3, dset)
self.assertEqual(st4,st3)
# args is a single Selection instance, but args shape doesn't match Shape
with self.assertRaises(TypeError):
sel.select((100,), st3, dset)
@@ -0,0 +1,415 @@
# 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.
"""
Dataset slicing test module.
Tests all supported slicing operations, including read/write and
broadcasting operations. Does not test type conversion except for
corner cases overlapping with slicing; for example, when selecting
specific fields of a compound type.
"""
import numpy as np
from .common import TestCase
import h5py
from h5py import File, MultiBlockSlice
class BaseSlicing(TestCase):
def setUp(self):
self.f = File(self.mktemp(), 'w')
def tearDown(self):
if self.f:
self.f.close()
class TestSingleElement(BaseSlicing):
"""
Feature: Retrieving a single element works with NumPy semantics
"""
def test_single_index(self):
""" Single-element selection with [index] yields array scalar """
dset = self.f.create_dataset('x', (1,), dtype='i1')
out = dset[0]
self.assertIsInstance(out, np.int8)
def test_single_null(self):
""" Single-element selection with [()] yields ndarray """
dset = self.f.create_dataset('x', (1,), dtype='i1')
out = dset[()]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, (1,))
def test_scalar_index(self):
""" Slicing with [...] yields scalar ndarray """
dset = self.f.create_dataset('x', shape=(), dtype='f')
out = dset[...]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, ())
def test_scalar_null(self):
""" Slicing with [()] yields array scalar """
dset = self.f.create_dataset('x', shape=(), dtype='i1')
out = dset[()]
self.assertIsInstance(out, np.int8)
def test_compound(self):
""" Compound scalar is numpy.void, not tuple (issue 135) """
dt = np.dtype([('a','i4'),('b','f8')])
v = np.ones((4,), dtype=dt)
dset = self.f.create_dataset('foo', (4,), data=v)
self.assertEqual(dset[0], v[0])
self.assertIsInstance(dset[0], np.void)
class TestObjectIndex(BaseSlicing):
"""
Feature: numpy.object_ subtypes map to real Python objects
"""
def test_reference(self):
""" Indexing a reference dataset returns a h5py.Reference instance """
dset = self.f.create_dataset('x', (1,), dtype=h5py.ref_dtype)
dset[0] = self.f.ref
self.assertEqual(type(dset[0]), h5py.Reference)
def test_regref(self):
""" Indexing a region reference dataset returns a h5py.RegionReference
"""
dset1 = self.f.create_dataset('x', (10,10))
regref = dset1.regionref[...]
dset2 = self.f.create_dataset('y', (1,), dtype=h5py.regionref_dtype)
dset2[0] = regref
self.assertEqual(type(dset2[0]), h5py.RegionReference)
def test_reference_field(self):
""" Compound types of which a reference is an element work right """
dt = np.dtype([('a', 'i'),('b', h5py.ref_dtype)])
dset = self.f.create_dataset('x', (1,), dtype=dt)
dset[0] = (42, self.f['/'].ref)
out = dset[0]
self.assertEqual(type(out[1]), h5py.Reference) # isinstance does NOT work
def test_scalar(self):
""" Indexing returns a real Python object on scalar datasets """
dset = self.f.create_dataset('x', (), dtype=h5py.ref_dtype)
dset[()] = self.f.ref
self.assertEqual(type(dset[()]), h5py.Reference)
def test_bytestr(self):
""" Indexing a byte string dataset returns a real python byte string
"""
dset = self.f.create_dataset('x', (1,), dtype=h5py.string_dtype(encoding='ascii'))
dset[0] = b"Hello there!"
self.assertEqual(type(dset[0]), bytes)
class TestSimpleSlicing(TestCase):
"""
Feature: Simple NumPy-style slices (start:stop:step) are supported.
"""
def setUp(self):
self.f = File(self.mktemp(), 'w')
self.arr = np.arange(10)
self.dset = self.f.create_dataset('x', data=self.arr)
def tearDown(self):
if self.f:
self.f.close()
def test_negative_stop(self):
""" Negative stop indexes work as they do in NumPy """
self.assertArrayEqual(self.dset[2:-2], self.arr[2:-2])
def test_write(self):
"""Assigning to a 1D slice of a 2D dataset
"""
dset = self.f.create_dataset('x2', (10, 2))
x = np.zeros((10, 1))
dset[:, 0] = x[:, 0]
with self.assertRaises(TypeError):
dset[:, 1] = x
class TestArraySlicing(BaseSlicing):
"""
Feature: Array types are handled appropriately
"""
def test_read(self):
""" Read arrays tack array dimensions onto end of shape tuple """
dt = np.dtype('(3,)f8')
dset = self.f.create_dataset('x',(10,),dtype=dt)
self.assertEqual(dset.shape, (10,))
self.assertEqual(dset.dtype, dt)
# Full read
out = dset[...]
self.assertEqual(out.dtype, np.dtype('f8'))
self.assertEqual(out.shape, (10,3))
# Single element
out = dset[0]
self.assertEqual(out.dtype, np.dtype('f8'))
self.assertEqual(out.shape, (3,))
# Range
out = dset[2:8:2]
self.assertEqual(out.dtype, np.dtype('f8'))
self.assertEqual(out.shape, (3,3))
def test_write_broadcast(self):
""" Array fill from constant is not supported (issue 211).
"""
dt = np.dtype('(3,)i')
dset = self.f.create_dataset('x', (10,), dtype=dt)
with self.assertRaises(TypeError):
dset[...] = 42
def test_write_element(self):
""" Write a single element to the array
Issue 211.
"""
dt = np.dtype('(3,)f8')
dset = self.f.create_dataset('x', (10,), dtype=dt)
data = np.array([1,2,3.0])
dset[4] = data
out = dset[4]
self.assertTrue(np.all(out == data))
def test_write_slices(self):
""" Write slices to array type """
dt = np.dtype('(3,)i')
data1 = np.ones((2,), dtype=dt)
data2 = np.ones((4,5), dtype=dt)
dset = self.f.create_dataset('x', (10,9,11), dtype=dt)
dset[0,0,2:4] = data1
self.assertArrayEqual(dset[0,0,2:4], data1)
dset[3, 1:5, 6:11] = data2
self.assertArrayEqual(dset[3, 1:5, 6:11], data2)
def test_roundtrip(self):
""" Read the contents of an array and write them back
Issue 211.
"""
dt = np.dtype('(3,)f8')
dset = self.f.create_dataset('x', (10,), dtype=dt)
out = dset[...]
dset[...] = out
self.assertTrue(np.all(dset[...] == out))
class TestZeroLengthSlicing(BaseSlicing):
"""
Slices resulting in empty arrays
"""
def test_slice_zero_length_dimension(self):
""" Slice a dataset with a zero in its shape vector
along the zero-length dimension """
for i, shape in enumerate([(0,), (0, 3), (0, 2, 1)]):
dset = self.f.create_dataset('x%d'%i, shape, dtype=int, maxshape=(None,)*len(shape))
self.assertEqual(dset.shape, shape)
out = dset[...]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, shape)
out = dset[:]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, shape)
if len(shape) > 1:
out = dset[:, :1]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape[:2], (0, 1))
def test_slice_other_dimension(self):
""" Slice a dataset with a zero in its shape vector
along a non-zero-length dimension """
for i, shape in enumerate([(3, 0), (1, 2, 0), (2, 0, 1)]):
dset = self.f.create_dataset('x%d'%i, shape, dtype=int, maxshape=(None,)*len(shape))
self.assertEqual(dset.shape, shape)
out = dset[:1]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, (1,)+shape[1:])
def test_slice_of_length_zero(self):
""" Get a slice of length zero from a non-empty dataset """
for i, shape in enumerate([(3,), (2, 2,), (2, 1, 5)]):
dset = self.f.create_dataset('x%d'%i, data=np.zeros(shape, int), maxshape=(None,)*len(shape))
self.assertEqual(dset.shape, shape)
out = dset[1:1]
self.assertIsInstance(out, np.ndarray)
self.assertEqual(out.shape, (0,)+shape[1:])
class TestFieldNames(BaseSlicing):
"""
Field names for read & write
"""
dt = np.dtype([('a', 'f'), ('b', 'i'), ('c', 'f4')])
data = np.ones((100,), dtype=dt)
def setUp(self):
BaseSlicing.setUp(self)
self.dset = self.f.create_dataset('x', (100,), dtype=self.dt)
self.dset[...] = self.data
def test_read(self):
""" Test read with field selections """
self.assertArrayEqual(self.dset['a'], self.data['a'])
def test_unicode_names(self):
""" Unicode field names for for read and write """
self.assertArrayEqual(self.dset['a'], self.data['a'])
self.dset['a'] = 42
data = self.data.copy()
data['a'] = 42
self.assertArrayEqual(self.dset['a'], data['a'])
def test_write(self):
""" Test write with field selections """
data2 = self.data.copy()
data2['a'] *= 2
self.dset['a'] = data2
self.assertTrue(np.all(self.dset[...] == data2))
data2['b'] *= 4
self.dset['b'] = data2
self.assertTrue(np.all(self.dset[...] == data2))
data2['a'] *= 3
data2['c'] *= 3
self.dset['a','c'] = data2
self.assertTrue(np.all(self.dset[...] == data2))
def test_write_noncompound(self):
""" Test write with non-compound source (single-field) """
data2 = self.data.copy()
data2['b'] = 1.0
self.dset['b'] = 1.0
self.assertTrue(np.all(self.dset[...] == data2))
class TestMultiBlockSlice(BaseSlicing):
def setUp(self):
super().setUp()
self.arr = np.arange(10)
self.dset = self.f.create_dataset('x', data=self.arr)
def test_default(self):
# Default selects entire dataset as one block
mbslice = MultiBlockSlice()
self.assertEqual(mbslice.indices(10), (0, 1, 10, 1))
np.testing.assert_array_equal(self.dset[mbslice], self.arr)
def test_default_explicit(self):
mbslice = MultiBlockSlice(start=0, count=10, stride=1, block=1)
self.assertEqual(mbslice.indices(10), (0, 1, 10, 1))
np.testing.assert_array_equal(self.dset[mbslice], self.arr)
def test_start(self):
mbslice = MultiBlockSlice(start=4)
self.assertEqual(mbslice.indices(10), (4, 1, 6, 1))
np.testing.assert_array_equal(self.dset[mbslice], np.array([4, 5, 6, 7, 8, 9]))
def test_count(self):
mbslice = MultiBlockSlice(count=7)
self.assertEqual(mbslice.indices(10), (0, 1, 7, 1))
np.testing.assert_array_equal(
self.dset[mbslice], np.array([0, 1, 2, 3, 4, 5, 6])
)
def test_count_more_than_length_error(self):
mbslice = MultiBlockSlice(count=11)
with self.assertRaises(ValueError):
mbslice.indices(10)
def test_stride(self):
mbslice = MultiBlockSlice(stride=2)
self.assertEqual(mbslice.indices(10), (0, 2, 5, 1))
np.testing.assert_array_equal(self.dset[mbslice], np.array([0, 2, 4, 6, 8]))
def test_stride_zero_error(self):
with self.assertRaises(ValueError):
# This would cause a ZeroDivisionError if not caught
MultiBlockSlice(stride=0, block=0).indices(10)
def test_stride_block_equal(self):
mbslice = MultiBlockSlice(stride=2, block=2)
self.assertEqual(mbslice.indices(10), (0, 2, 5, 2))
np.testing.assert_array_equal(self.dset[mbslice], self.arr)
def test_block_more_than_stride_error(self):
with self.assertRaises(ValueError):
MultiBlockSlice(block=3)
with self.assertRaises(ValueError):
MultiBlockSlice(stride=2, block=3)
def test_stride_more_than_block(self):
mbslice = MultiBlockSlice(stride=3, block=2)
self.assertEqual(mbslice.indices(10), (0, 3, 3, 2))
np.testing.assert_array_equal(self.dset[mbslice], np.array([0, 1, 3, 4, 6, 7]))
def test_block_overruns_extent_error(self):
# If fully described then must fit within extent
mbslice = MultiBlockSlice(start=2, count=2, stride=5, block=4)
with self.assertRaises(ValueError):
mbslice.indices(10)
def test_fully_described(self):
mbslice = MultiBlockSlice(start=1, count=2, stride=5, block=4)
self.assertEqual(mbslice.indices(10), (1, 5, 2, 4))
np.testing.assert_array_equal(
self.dset[mbslice], np.array([1, 2, 3, 4, 6, 7, 8, 9])
)
def test_count_calculated(self):
# If not given, count should be calculated to select as many full blocks as possible
mbslice = MultiBlockSlice(start=1, stride=3, block=2)
self.assertEqual(mbslice.indices(10), (1, 3, 3, 2))
np.testing.assert_array_equal(self.dset[mbslice], np.array([1, 2, 4, 5, 7, 8]))
def test_zero_count_calculated_error(self):
# In this case, there is no possible count to select even one block, so error
mbslice = MultiBlockSlice(start=8, stride=4, block=3)
with self.assertRaises(ValueError):
mbslice.indices(10)
@@ -0,0 +1,4 @@
from .test_virtual_source import *
from .test_highlevel_vds import *
from .test_lowlevel_vds import *
@@ -0,0 +1,476 @@
'''
Unit test for the high level vds interface for eiger
https://support.hdfgroup.org/HDF5/docNewFeatures/VDS/HDF5-VDS-requirements-use-cases-2014-12-10.pdf
'''
import numpy as np
from numpy.testing import assert_array_equal
import os
import os.path as osp
import shutil
import tempfile
import h5py as h5
from ..common import ut
from ..._hl.vds import vds_support
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class TestEigerHighLevel(ut.TestCase):
def setUp(self):
self.working_dir = tempfile.mkdtemp()
self.fname = ['raw_file_1.h5', 'raw_file_2.h5', 'raw_file_3.h5']
for k, outfile in enumerate(self.fname):
filename = osp.join(self.working_dir, outfile)
f = h5.File(filename, 'w')
f['data'] = np.ones((20, 200, 200)) * k
f.close()
f = h5.File(osp.join(self.working_dir, 'raw_file_4.h5'), 'w')
f['data'] = np.ones((18, 200, 200)) * 3
self.fname.append('raw_file_4.h5')
self.fname = [osp.join(self.working_dir, ix) for ix in self.fname]
f.close()
def test_eiger_high_level(self):
outfile = osp.join(self.working_dir, 'eiger.h5')
layout = h5.VirtualLayout(shape=(78, 200, 200), dtype=float)
M_minus_1 = 0
# Create the virtual dataset file
with h5.File(outfile, 'w', libver='latest') as f:
for foo in self.fname:
in_data = h5.File(foo, 'r')['data']
src_shape = in_data.shape
in_data.file.close()
M = M_minus_1 + src_shape[0]
vsource = h5.VirtualSource(foo, 'data', shape=src_shape)
layout[M_minus_1:M, :, :] = vsource
M_minus_1 = M
f.create_virtual_dataset('data', layout, fillvalue=45)
f = h5.File(outfile, 'r')['data']
self.assertEqual(f[10, 100, 10], 0.0)
self.assertEqual(f[30, 100, 100], 1.0)
self.assertEqual(f[50, 100, 100], 2.0)
self.assertEqual(f[70, 100, 100], 3.0)
f.file.close()
def tearDown(self):
shutil.rmtree(self.working_dir)
'''
Unit test for the high level vds interface for excalibur
https://support.hdfgroup.org/HDF5/docNewFeatures/VDS/HDF5-VDS-requirements-use-cases-2014-12-10.pdf
'''
class ExcaliburData:
FEM_PIXELS_PER_CHIP_X = 256
FEM_PIXELS_PER_CHIP_Y = 256
FEM_CHIPS_PER_STRIPE_X = 8
FEM_CHIPS_PER_STRIPE_Y = 1
FEM_STRIPES_PER_MODULE = 2
@property
def sensor_module_dimensions(self):
x_pixels = self.FEM_PIXELS_PER_CHIP_X * self.FEM_CHIPS_PER_STRIPE_X
y_pixels = self.FEM_PIXELS_PER_CHIP_Y * self.FEM_CHIPS_PER_STRIPE_Y * self.FEM_STRIPES_PER_MODULE
return y_pixels, x_pixels,
@property
def fem_stripe_dimensions(self):
x_pixels = self.FEM_PIXELS_PER_CHIP_X * self.FEM_CHIPS_PER_STRIPE_X
y_pixels = self.FEM_PIXELS_PER_CHIP_Y * self.FEM_CHIPS_PER_STRIPE_Y
return y_pixels, x_pixels,
def generate_sensor_module_image(self, value, dtype='uint16'):
dset = np.empty(shape=self.sensor_module_dimensions, dtype=dtype)
dset.fill(value)
return dset
def generate_fem_stripe_image(self, value, dtype='uint16'):
dset = np.empty(shape=self.fem_stripe_dimensions, dtype=dtype)
dset.fill(value)
return dset
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class TestExcaliburHighLevel(ut.TestCase):
def create_excalibur_fem_stripe_datafile(self, fname, nframes, excalibur_data,scale):
shape = (nframes,) + excalibur_data.fem_stripe_dimensions
max_shape = shape#(None,) + excalibur_data.fem_stripe_dimensions
chunk = (1,) + excalibur_data.fem_stripe_dimensions
with h5.File(fname, 'w', libver='latest') as f:
dset = f.create_dataset('data', shape=shape, maxshape=max_shape, chunks=chunk, dtype='uint16')
for data_value_index in np.arange(nframes):
dset[data_value_index] = excalibur_data.generate_fem_stripe_image(data_value_index*scale)
def setUp(self):
self.working_dir = tempfile.mkdtemp()
self.fname = ["stripe_%d.h5" % stripe for stripe in range(1,7)]
self.fname = [osp.join(self.working_dir, f) for f in self.fname]
nframes = 5
self.edata = ExcaliburData()
for k, raw_file in enumerate(self.fname):
self.create_excalibur_fem_stripe_datafile(raw_file, nframes, self.edata,k)
def test_excalibur_high_level(self):
outfile = osp.join(self.working_dir, 'excalibur.h5')
f = h5.File(outfile,'w',libver='latest') # create an output file.
in_key = 'data' # where is the data at the input?
in_sh = h5.File(self.fname[0],'r')[in_key].shape # get the input shape
dtype = h5.File(self.fname[0],'r')[in_key].dtype # get the datatype
# now generate the output shape
vertical_gap = 10 # pixels spacing in the vertical
nfiles = len(self.fname)
nframes = in_sh[0]
width = in_sh[2]
height = (in_sh[1]*nfiles) + (vertical_gap*(nfiles-1))
out_sh = (nframes, height, width)
# Virtual layout is a representation of the output dataset
layout = h5.VirtualLayout(shape=out_sh, dtype=dtype)
offset = 0 # initial offset
for i, filename in enumerate(self.fname):
# A representation of the input dataset
vsource = h5.VirtualSource(filename, in_key, shape=in_sh)
layout[:, offset:(offset + in_sh[1]), :] = vsource # map them with indexing
offset += in_sh[1] + vertical_gap # increment the offset
# pass the fill value and list of maps
f.create_virtual_dataset('data', layout, fillvalue=0x1)
f.close()
f = h5.File(outfile,'r')['data']
self.assertEqual(f[3,100,0], 0.0)
self.assertEqual(f[3,260,0], 1.0)
self.assertEqual(f[3,350,0], 3.0)
self.assertEqual(f[3,650,0], 6.0)
self.assertEqual(f[3,900,0], 9.0)
self.assertEqual(f[3,1150,0], 12.0)
self.assertEqual(f[3,1450,0], 15.0)
f.file.close()
def tearDown(self):
shutil.rmtree(self.working_dir)
'''
Unit test for the high level vds interface for percival
https://support.hdfgroup.org/HDF5/docNewFeatures/VDS/HDF5-VDS-requirements-use-cases-2014-12-10.pdf
'''
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class TestPercivalHighLevel(ut.TestCase):
def setUp(self):
self.working_dir = tempfile.mkdtemp()
self.fname = ['raw_file_1.h5','raw_file_2.h5','raw_file_3.h5']
k = 0
for outfile in self.fname:
filename = osp.join(self.working_dir, outfile)
f = h5.File(filename,'w')
f['data'] = np.ones((20,200,200))*k
k +=1
f.close()
f = h5.File(osp.join(self.working_dir, 'raw_file_4.h5'), 'w')
f['data'] = np.ones((19,200,200))*3
self.fname.append('raw_file_4.h5')
self.fname = [osp.join(self.working_dir, ix) for ix in self.fname]
f.close()
def test_percival_high_level(self):
outfile = osp.join(self.working_dir, 'percival.h5')
# Virtual layout is a representation of the output dataset
layout = h5.VirtualLayout(shape=(79, 200, 200), dtype=np.float64)
for k, filename in enumerate(self.fname):
dim1 = 19 if k == 3 else 20
vsource = h5.VirtualSource(filename, 'data',shape=(dim1, 200, 200))
layout[k:79:4, :, :] = vsource[:, :, :]
# Create the virtual dataset file
with h5.File(outfile, 'w', libver='latest') as f:
f.create_virtual_dataset('data', layout, fillvalue=-5)
foo = np.array(2 * list(range(4)))
with h5.File(outfile,'r') as f:
ds = f['data']
line = ds[:8,100,100]
self.assertEqual(ds.shape, (79,200,200),)
assert_array_equal(line, foo)
def test_percival_source_from_dataset(self):
outfile = osp.join(self.working_dir, 'percival.h5')
# Virtual layout is a representation of the output dataset
layout = h5.VirtualLayout(shape=(79, 200, 200), dtype=np.float64)
for k, filename in enumerate(self.fname):
with h5.File(filename, 'r') as f:
vsource = h5.VirtualSource(f['data'])
layout[k:79:4, :, :] = vsource
# Create the virtual dataset file
with h5.File(outfile, 'w', libver='latest') as f:
f.create_virtual_dataset('data', layout, fillvalue=-5)
foo = np.array(2 * list(range(4)))
with h5.File(outfile,'r') as f:
ds = f['data']
line = ds[:8,100,100]
self.assertEqual(ds.shape, (79,200,200),)
assert_array_equal(line, foo)
def tearDown(self):
shutil.rmtree(self.working_dir)
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class SlicingTestCase(ut.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
# Create source files (1.h5 to 4.h5)
for n in range(1, 5):
with h5.File(osp.join(self.tmpdir, '{}.h5'.format(n)), 'w') as f:
d = f.create_dataset('data', (100,), 'i4')
d[:] = np.arange(100) + n
def make_virtual_ds(self):
# Assemble virtual dataset
layout = h5.VirtualLayout((4, 100), 'i4', maxshape=(4, None))
for n in range(1, 5):
filename = osp.join(self.tmpdir, "{}.h5".format(n))
vsource = h5.VirtualSource(filename, 'data', shape=(100,))
# Fill the first half with positions 0, 2, 4... from the source
layout[n - 1, :50] = vsource[0:100:2]
# Fill the second half with places 1, 3, 5... from the source
layout[n - 1, 50:] = vsource[1:100:2]
outfile = osp.join(self.tmpdir, 'VDS.h5')
# Add virtual dataset to output file
with h5.File(outfile, 'w', libver='latest') as f:
f.create_virtual_dataset('/group/data', layout, fillvalue=-5)
return outfile
def test_slice_source(self):
outfile = self.make_virtual_ds()
with h5.File(outfile, 'r') as f:
assert_array_equal(f['/group/data'][0][:3], [1, 3, 5])
assert_array_equal(f['/group/data'][0][50:53], [2, 4, 6])
assert_array_equal(f['/group/data'][3][:3], [4, 6, 8])
assert_array_equal(f['/group/data'][3][50:53], [5, 7, 9])
def test_inspection(self):
with h5.File(osp.join(self.tmpdir, '1.h5'), 'r') as f:
assert not f['data'].is_virtual
outfile = self.make_virtual_ds()
with h5.File(outfile, 'r') as f:
ds = f['/group/data']
assert ds.is_virtual
src_files = {osp.join(self.tmpdir, '{}.h5'.format(n))
for n in range(1, 5)}
assert {s.file_name for s in ds.virtual_sources()} == src_files
def test_mismatched_selections(self):
layout = h5.VirtualLayout((4, 100), 'i4', maxshape=(4, None))
filename = osp.join(self.tmpdir, "1.h5")
vsource = h5.VirtualSource(filename, 'data', shape=(100,))
with self.assertRaisesRegex(ValueError, r'different number'):
layout[0, :49] = vsource[0:100:2]
def tearDown(self):
shutil.rmtree(self.tmpdir)
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class IndexingTestCase(ut.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
# Create source file (1.h5)
with h5.File(osp.join(self.tmpdir, '1.h5'), 'w') as f:
d = f.create_dataset('data', (10,), 'i4')
d[:] = np.arange(10)*10
def test_index_layout(self):
# Assemble virtual dataset (indexing target)
layout = h5.VirtualLayout((100,), 'i4')
inds = [3,6,20,25,33,47,70,75,96,98]
filename = osp.join(self.tmpdir, "1.h5")
vsource = h5.VirtualSource(filename, 'data', shape=(10,))
layout[inds] = vsource
outfile = osp.join(self.tmpdir, 'VDS.h5')
# Assembly virtual dataset (indexing source)
layout2 = h5.VirtualLayout((6,), 'i4')
inds2 = [0,1,4,5,8]
layout2[1:] = vsource[inds2]
# Add virtual datasets to output file and close
with h5.File(outfile, 'w', libver='latest') as f:
f.create_virtual_dataset('/data', layout, fillvalue=-5)
f.create_virtual_dataset(b'/data2', layout2, fillvalue=-3)
# Read data from virtual datasets
with h5.File(outfile, 'r') as f:
data = f['/data'][()]
data2 = f['/data2'][()]
# Verify
assert_array_equal(data[inds], np.arange(10)*10)
assert_array_equal(data2[1:], [0,10,40,50,80])
mask = np.zeros(100)
mask[inds] = 1
self.assertEqual(data[mask == 0].min(), -5)
self.assertEqual(data[mask == 0].max(), -5)
self.assertEqual(data2[0], -3)
def tearDown(self):
shutil.rmtree(self.tmpdir)
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class RelativeLinkTestCase(ut.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self.f1 = osp.join(self.tmpdir, 'testfile1.h5')
self.f2 = osp.join(self.tmpdir, 'testfile2.h5')
self.data1 = np.arange(10)
self.data2 = np.arange(10) * -1
with h5.File(self.f1, 'w') as f:
# dataset
ds = f.create_dataset('data', (10,), 'f4')
ds[:] = self.data1
with h5.File(self.f2, 'w') as f:
# dataset
ds = f.create_dataset('data', (10,), 'f4')
ds[:] = self.data2
self.make_vds(f)
def make_vds(self, f):
# virtual dataset
layout = h5.VirtualLayout((2, 10), 'f4')
vsource1 = h5.VirtualSource(self.f1, 'data', shape=(10,))
vsource2 = h5.VirtualSource(self.f2, 'data', shape=(10,))
layout[0] = vsource1
layout[1] = vsource2
f.create_virtual_dataset('virtual', layout)
def test_relative_vds(self):
with h5.File(self.f2) as f:
data = f['virtual'][:]
np.testing.assert_array_equal(data[0], self.data1)
np.testing.assert_array_equal(data[1], self.data2)
# move f2 -> f3
f3 = osp.join(self.tmpdir, 'testfile3.h5')
os.rename(self.f2, f3)
with h5.File(f3) as f:
data = f['virtual'][:]
assert data.dtype == 'f4'
np.testing.assert_array_equal(data[0], self.data1)
np.testing.assert_array_equal(data[1], self.data2)
# moving other file
f4 = osp.join(self.tmpdir, 'testfile4.h5')
os.rename(self.f1, f4)
with h5.File(f3) as f:
data = f['virtual'][:]
assert data.dtype == 'f4'
# unavailable data is silently converted to default value
np.testing.assert_array_equal(data[0], 0)
np.testing.assert_array_equal(data[1], self.data2)
def tearDown(self):
shutil.rmtree(self.tmpdir)
class RelativeLinkBuildVDSTestCase(RelativeLinkTestCase):
# Test a link to the same file with the virtual dataset created by
# File.build_virtual_dataset()
def make_vds(self, f):
with f.build_virtual_dataset('virtual', (2, 10), dtype='f4') as layout:
layout[0] = h5.VirtualSource(self.f1, 'data', shape=(10,))
layout[1] = h5.VirtualSource(self.f2, 'data', shape=(10,))
@ut.skipUnless(vds_support,
'VDS requires HDF5 >= 1.9.233')
class VDSUnlimitedTestCase(ut.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self.path = osp.join(self.tmpdir, "resize.h5")
with h5.File(self.path, "w") as f:
source_dset = f.create_dataset(
"source",
data=np.arange(20),
shape=(10, 2),
maxshape=(None, 2),
chunks=(10, 1),
fillvalue=-1
)
self.layout = h5.VirtualLayout((10, 1), int, maxshape=(None, 1))
layout_source = h5.VirtualSource(source_dset)
self.layout[:h5.UNLIMITED, 0] = layout_source[:h5.UNLIMITED, 1]
f.create_virtual_dataset("virtual", self.layout)
def test_unlimited_axis(self):
comp1 = np.arange(1, 20, 2).reshape(10, 1)
comp2 = np.vstack((
comp1,
np.full(shape=(10, 1), fill_value=-1)
))
comp3 = np.vstack((
comp1,
np.full(shape=(10, 1), fill_value=0)
))
with h5.File(self.path, "a") as f:
source_dset = f['source']
virtual_dset = f['virtual']
np.testing.assert_array_equal(comp1, virtual_dset)
source_dset.resize(20, axis=0)
np.testing.assert_array_equal(comp2, virtual_dset)
source_dset[10:, 1] = np.zeros((10,), dtype=int)
np.testing.assert_array_equal(comp3, virtual_dset)
def tearDown(self):
shutil.rmtree(self.tmpdir)
def test_no_mappings(writable_file):
with writable_file.build_virtual_dataset("foo", (10, 20), np.int32):
pass
dset = writable_file['foo']
assert dset.is_virtual
assert dset.virtual_sources() == []
np.testing.assert_array_equal(dset[()], np.zeros((10, 20), np.int32))
if __name__ == "__main__":
ut.main()
@@ -0,0 +1,298 @@
'''
Unit test for the low level vds interface for eiger
https://support.hdfgroup.org/HDF5/docNewFeatures/VDS/HDF5-VDS-requirements-use-cases-2014-12-10.pdf
'''
import os.path as osp
import tempfile
import numpy as np
import h5py as h5
from ..common import ut
class TestEigerLowLevel(ut.TestCase):
def setUp(self):
self.working_dir = tempfile.TemporaryDirectory()
self.fname = ['raw_file_1.h5', 'raw_file_2.h5', 'raw_file_3.h5']
k = 0
for outfile in self.fname:
filename = osp.join(self.working_dir.name, outfile)
with h5.File(filename, 'w') as f:
f['data'] = np.ones((20, 200, 200))*k
k += 1
with h5.File(osp.join(self.working_dir.name, 'raw_file_4.h5'), 'w') as f:
f['data'] = np.ones((18, 200, 200))*3
self.fname.append('raw_file_4.h5')
self.fname = [osp.join(self.working_dir.name, ix) for ix in self.fname]
def test_eiger_low_level(self):
outfile = osp.join(self.working_dir.name, 'eiger.h5')
with h5.File(outfile, 'w', libver='latest') as f:
vdset_shape = (78, 200, 200)
vdset_max_shape = vdset_shape
virt_dspace = h5.h5s.create_simple(vdset_shape, vdset_max_shape)
dcpl = h5.h5p.create(h5.h5p.DATASET_CREATE)
dcpl.set_fill_value(np.array([-1]))
# Create the source dataset dataspace
k = 0
for foo in self.fname:
with h5.File(foo, 'r') as in_f:
src_shape = in_f['data'].shape
src_dspace = h5.h5s.create_simple(src_shape, src_shape)
# Select the source dataset hyperslab
src_dspace.select_hyperslab(start=(0, 0, 0),
stride=(1, 1, 1),
count=(1, 1, 1),
block=src_shape)
virt_dspace.select_hyperslab(start=(k, 0, 0),
stride=(1, 1, 1),
count=(1, 1, 1),
block=src_shape)
dcpl.set_virtual(virt_dspace, foo.encode('utf-8'),
b'data', src_dspace)
k += src_shape[0]
# Create the virtual dataset
h5.h5d.create(f.id, name=b"data", tid=h5.h5t.NATIVE_INT16,
space=virt_dspace, dcpl=dcpl)
with h5.File(outfile, 'r') as f:
d = f['data']
self.assertEqual(d[10, 100, 10], 0.0)
self.assertEqual(d[30, 100, 100], 1.0)
self.assertEqual(d[50, 100, 100], 2.0)
self.assertEqual(d[70, 100, 100], 3.0)
def tearDown(self):
self.working_dir.cleanup()
if __name__ == "__main__":
ut.main()
'''
Unit test for the low level vds interface for excalibur
https://support.hdfgroup.org/HDF5/docNewFeatures/VDS/HDF5-VDS-requirements-use-cases-2014-12-10.pdf
'''
class ExcaliburData:
FEM_PIXELS_PER_CHIP_X = 256
FEM_PIXELS_PER_CHIP_Y = 256
FEM_CHIPS_PER_STRIPE_X = 8
FEM_CHIPS_PER_STRIPE_Y = 1
FEM_STRIPES_PER_MODULE = 2
@property
def sensor_module_dimensions(self):
x_pixels = self.FEM_PIXELS_PER_CHIP_X * self.FEM_CHIPS_PER_STRIPE_X
y_pixels = self.FEM_PIXELS_PER_CHIP_Y * self.FEM_CHIPS_PER_STRIPE_Y * self.FEM_STRIPES_PER_MODULE
return y_pixels, x_pixels,
@property
def fem_stripe_dimensions(self):
x_pixels = self.FEM_PIXELS_PER_CHIP_X * self.FEM_CHIPS_PER_STRIPE_X
y_pixels = self.FEM_PIXELS_PER_CHIP_Y * self.FEM_CHIPS_PER_STRIPE_Y
return y_pixels, x_pixels,
def generate_sensor_module_image(self, value, dtype='uint16'):
dset = np.empty(shape=self.sensor_module_dimensions, dtype=dtype)
dset.fill(value)
return dset
def generate_fem_stripe_image(self, value, dtype='uint16'):
dset = np.empty(shape=self.fem_stripe_dimensions, dtype=dtype)
dset.fill(value)
return dset
class TestExcaliburLowLevel(ut.TestCase):
def create_excalibur_fem_stripe_datafile(self, fname, nframes, excalibur_data,scale):
shape = (nframes,) + excalibur_data.fem_stripe_dimensions
max_shape = (nframes,) + excalibur_data.fem_stripe_dimensions
chunk = (1,) + excalibur_data.fem_stripe_dimensions
with h5.File(fname, 'w', libver='latest') as f:
dset = f.create_dataset('data', shape=shape, maxshape=max_shape, chunks=chunk, dtype='uint16')
for data_value_index in np.arange(nframes):
dset[data_value_index] = excalibur_data.generate_fem_stripe_image(data_value_index*scale)
def setUp(self):
self.working_dir = tempfile.TemporaryDirectory()
self.fname = ["stripe_%d.h5" % stripe for stripe in range(1,7)]
self.fname = [osp.join(self.working_dir.name, ix) for ix in self.fname]
nframes = 5
self.edata = ExcaliburData()
k=0
for raw_file in self.fname:
self.create_excalibur_fem_stripe_datafile(raw_file, nframes, self.edata,k)
k+=1
def test_excalibur_low_level(self):
excalibur_data = self.edata
outfile = osp.join(self.working_dir.name, 'excalibur.h5')
vdset_stripe_shape = (1,) + excalibur_data.fem_stripe_dimensions
vdset_stripe_max_shape = (5, ) + excalibur_data.fem_stripe_dimensions
vdset_shape = (5,
excalibur_data.fem_stripe_dimensions[0] * len(self.fname) + (10 * (len(self.fname)-1)),
excalibur_data.fem_stripe_dimensions[1])
vdset_max_shape = (5,
excalibur_data.fem_stripe_dimensions[0] * len(self.fname) + (10 * (len(self.fname)-1)),
excalibur_data.fem_stripe_dimensions[1])
vdset_y_offset = 0
# Create the virtual dataset file
with h5.File(outfile, 'w', libver='latest') as f:
# Create the source dataset dataspace
src_dspace = h5.h5s.create_simple(vdset_stripe_shape, vdset_stripe_max_shape)
# Create the virtual dataset dataspace
virt_dspace = h5.h5s.create_simple(vdset_shape, vdset_max_shape)
# Create the virtual dataset property list
dcpl = h5.h5p.create(h5.h5p.DATASET_CREATE)
dcpl.set_fill_value(np.array([0x01]))
# Select the source dataset hyperslab
src_dspace.select_hyperslab(start=(0, 0, 0), count=(1, 1, 1), block=vdset_stripe_max_shape)
for raw_file in self.fname:
# Select the virtual dataset hyperslab (for the source dataset)
virt_dspace.select_hyperslab(start=(0, vdset_y_offset, 0),
count=(1, 1, 1),
block=vdset_stripe_max_shape)
# Set the virtual dataset hyperslab to point to the real first dataset
dcpl.set_virtual(virt_dspace, raw_file.encode('utf-8'),
b"/data", src_dspace)
vdset_y_offset += vdset_stripe_shape[1] + 10
# Create the virtual dataset
h5.h5d.create(
f.id,
name=b"data",
tid=h5.h5t.NATIVE_INT16,
space=virt_dspace,
dcpl=dcpl,
)
assert(f['data'].fillvalue == 0x01)
with h5.File(outfile,'r') as f:
d = f['data']
self.assertEqual(d[3,100,0], 0.0)
self.assertEqual(d[3,260,0], 1.0)
self.assertEqual(d[3,350,0], 3.0)
self.assertEqual(d[3,650,0], 6.0)
self.assertEqual(d[3,900,0], 9.0)
self.assertEqual(d[3,1150,0], 12.0)
self.assertEqual(d[3,1450,0], 15.0)
def tearDown(self):
self.working_dir.cleanup()
'''
Unit test for the low level vds interface for percival
https://support.hdfgroup.org/HDF5/docNewFeatures/VDS/HDF5-VDS-requirements-use-cases-2014-12-10.pdf
'''
class TestPercivalLowLevel(ut.TestCase):
def setUp(self):
self.working_dir = tempfile.TemporaryDirectory()
self.fname = ['raw_file_1.h5','raw_file_2.h5','raw_file_3.h5']
k = 0
for outfile in self.fname:
filename = osp.join(self.working_dir.name, outfile)
with h5.File(filename,'w') as f:
f['data'] = np.ones((20,200,200))*k
k +=1
with h5.File(osp.join(self.working_dir.name, 'raw_file_4.h5'),'w') as f:
f['data'] = np.ones((19,200,200))*3
self.fname.append('raw_file_4.h5')
self.fname = [osp.join(self.working_dir.name, ix) for ix in self.fname]
def test_percival_low_level(self):
outfile = osp.join(self.working_dir.name, 'percival.h5')
with h5.File(outfile, 'w', libver='latest') as f:
vdset_shape = (1,200,200)
num = h5.h5s.UNLIMITED
vdset_max_shape = (num,)+vdset_shape[1:]
virt_dspace = h5.h5s.create_simple(vdset_shape, vdset_max_shape)
dcpl = h5.h5p.create(h5.h5p.DATASET_CREATE)
dcpl.set_fill_value(np.array([-1]))
# Create the source dataset dataspace
k = 0
for foo in self.fname:
with h5.File(foo, 'r') as in_f:
src_shape = in_f['data'].shape
max_src_shape = (num,)+src_shape[1:]
src_dspace = h5.h5s.create_simple(src_shape, max_src_shape)
# Select the source dataset hyperslab
src_dspace.select_hyperslab(start=(0, 0, 0),
stride=(1,1,1),
count=(num, 1, 1),
block=(1,)+src_shape[1:])
virt_dspace.select_hyperslab(start=(k, 0, 0),
stride=(4,1,1),
count=(num, 1, 1),
block=(1,)+src_shape[1:])
dcpl.set_virtual(virt_dspace, foo.encode('utf-8'), b'data', src_dspace)
k+=1
# Create the virtual dataset
h5.h5d.create(
f.id,
name=b"data",
tid=h5.h5t.NATIVE_INT16,
space=virt_dspace,
dcpl=dcpl,
)
with h5.File(outfile, 'r') as f:
sh = f['data'].shape
line = f['data'][:8,100,100]
foo = np.array(2*list(range(4)))
self.assertEqual(sh,(79,200,200),)
np.testing.assert_array_equal(line,foo)
def tearDown(self):
self.working_dir.cleanup()
def test_virtual_prefix(tmp_path):
a = tmp_path / 'a'
b = tmp_path / 'b'
a.mkdir()
b.mkdir()
src_file = h5.File(a / 'src.h5', 'w')
src_file['data'] = np.arange(10)
vds_file = h5.File(b / 'vds.h5', 'w')
layout = h5.VirtualLayout(shape=(10,), dtype=np.int64)
layout[:] = h5.VirtualSource('src.h5', 'data', shape=(10,))
vds_file.create_virtual_dataset('data', layout, fillvalue=-1)
# Path doesn't resolve
np.testing.assert_array_equal(vds_file['data'], np.full(10, fill_value=-1))
a_bytes = bytes(a)
dapl = h5.h5p.create(h5.h5p.DATASET_ACCESS)
dapl.set_virtual_prefix(a_bytes)
vds_id = h5.h5d.open(vds_file.id, b'data', dapl=dapl)
vds = h5.Dataset(vds_id)
# Now it should find the source file and read the data correctly
np.testing.assert_array_equal(vds[:], np.arange(10))
# Check that get_virtual_prefix gives back what we put in
assert vds.id.get_access_plist().get_virtual_prefix() == a_bytes
src_file.close()
vds_file.close()
@@ -0,0 +1,166 @@
from ..common import ut
import h5py as h5
import numpy as np
class TestVirtualSource(ut.TestCase):
def test_full_slice(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[:,:,:]
self.assertEqual(dataset.shape,sliced.shape)
# def test_full_slice_inverted(self):
# dataset = h5.VirtualSource('test','test',(20,30,30))
# sliced = dataset[:,:,::-1]
# self.assertEqual(dataset.shape,sliced.shape)
#
# def test_subsampled_slice_inverted(self):
# dataset = h5.VirtualSource('test','test',(20,30,30))
# sliced = dataset[:,:,::-2]
# self.assertEqual((20,30,15),sliced.shape)
def test_integer_indexed(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[5,:,:]
self.assertEqual((30,30),sliced.shape)
def test_integer_single_indexed(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[5]
self.assertEqual((30,30),sliced.shape)
def test_two_integer_indexed(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[5,:,10]
self.assertEqual((30,),sliced.shape)
def test_single_range(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[5:10,:,:]
self.assertEqual((5,)+dataset.shape[1:],sliced.shape)
def test_shape_calculation_positive_step(self):
dataset = h5.VirtualSource('test','test',(20,))
cmp = []
for i in range(5):
d = dataset[2:12+i:3].shape[0]
ref = np.arange(20)[2:12+i:3].size
cmp.append(ref==d)
self.assertEqual(5, sum(cmp))
# def test_shape_calculation_positive_step_switched_start_stop(self):
# dataset = h5.VirtualSource('test','test',(20,))
# cmp = []
# for i in range(5):
# d = dataset[12+i:2:3].shape[0]
# ref = np.arange(20)[12+i:2:3].size
# cmp.append(ref==d)
# self.assertEqual(5, sum(cmp))
#
#
# def test_shape_calculation_negative_step(self):
# dataset = h5.VirtualSource('test','test',(20,))
# cmp = []
# for i in range(5):
# d = dataset[12+i:2:-3].shape[0]
# ref = np.arange(20)[12+i:2:-3].size
# cmp.append(ref==d)
# self.assertEqual(5, sum(cmp))
#
# def test_shape_calculation_negative_step_switched_start_stop(self):
# dataset = h5.VirtualSource('test','test',(20,))
# cmp = []
# for i in range(5):
# d = dataset[2:12+i:-3].shape[0]
# ref = np.arange(20)[2:12+i:-3].size
# cmp.append(ref==d)
# self.assertEqual(5, sum(cmp))
def test_double_range(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[5:10,:,20:25]
self.assertEqual((5,30,5),sliced.shape)
def test_double_strided_range(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[6:12:2,:,20:26:3]
self.assertEqual((3,30,2,),sliced.shape)
# def test_double_strided_range_inverted(self):
# dataset = h5.VirtualSource('test','test',(20,30,30))
# sliced = dataset[12:6:-2,:,26:20:-3]
# self.assertEqual((3,30,2),sliced.shape)
def test_negative_start_index(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[-10:16]
self.assertEqual((6,30,30),sliced.shape)
def test_negative_stop_index(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[10:-4]
self.assertEqual((6,30,30),sliced.shape)
def test_negative_start_and_stop_index(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[-10:-4]
self.assertEqual((6,30,30),sliced.shape)
# def test_negative_start_and_stop_and_stride_index(self):
# dataset = h5.VirtualSource('test','test',(20,30,30))
# sliced = dataset[-4:-10:-2]
# self.assertEqual((3,30,30),sliced.shape)
#
def test_ellipsis(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[...]
self.assertEqual(dataset.shape,sliced.shape)
def test_ellipsis_end(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[0:1,...]
self.assertEqual((1,)+dataset.shape[1:],sliced.shape)
def test_ellipsis_start(self):
dataset = h5.VirtualSource('test','test',(20,30,30))
sliced = dataset[...,0:1]
self.assertEqual(dataset.shape[:-1]+(1,),sliced.shape)
def test_ellipsis_sandwich(self):
dataset = h5.VirtualSource('test','test',(20,30,30,40))
sliced = dataset[0:1,...,5:6]
self.assertEqual((1,)+dataset.shape[1:-1]+(1,),sliced.shape)
def test_integer_shape(self):
dataset = h5.VirtualSource('test','test', 20)
self.assertEqual(dataset.shape, (20,))
def test_integer_maxshape(self):
dataset = h5.VirtualSource('test','test', 20, maxshape=30)
self.assertEqual(dataset.maxshape, (30,))
def test_extra_args(self):
with h5.File(name='f1', driver='core',
backing_store=False, mode='w') as ftest:
ftest['a'] = [1, 2, 3]
a = ftest['a']
with self.assertRaises(TypeError):
h5.VirtualSource(a, 'b')
with self.assertRaises(TypeError):
h5.VirtualSource(a, shape=(1, ))
with self.assertRaises(TypeError):
h5.VirtualSource(a, maxshape=(None,))
with self.assertRaises(TypeError):
h5.VirtualSource(a, dtype=int)
def test_repeated_slice(self):
dataset = h5.VirtualSource('test', 'test', (20, 30, 30))
sliced = dataset[5:10, :, :]
with self.assertRaises(RuntimeError):
sliced[:, :4]
if __name__ == "__main__":
ut.main()