Skip to content

H5json - #293

Open
jreadey wants to merge 46 commits into
masterfrom
h5json
Open

H5json#293
jreadey wants to merge 46 commits into
masterfrom
h5json

Conversation

@jreadey

@jreadey jreadey commented Aug 25, 2026

Copy link
Copy Markdown
Member

Overview

This branch migrates h5pyd's storage/object-model layer to the shared h5json library instead of h5pyd's own bespoke
JSON-schema/selection/dtype code. h5json now owns the HDF5 object-model representation
(groups/datasets/datatypes/attributes as JSON), dtype (de)serialization, and selection logic, while h5pyd is reduced
to the high-level (h5py-compatible) API plus an HSDS-specific storage plugin. This lets h5pyd share that core logic
with other tools built on h5json (e.g. HSDS itself) rather than maintaining a parallel implementation.

Major changes

Core architecture

  • Replaced h5pyd/_hl/selections.py, most of h5pyd/_hl/h5type.py, and related object-model code with imports from
    h5json (h5json.selections, h5json.hdf5dtype, h5json.hdf5db, etc.) — removed ~1,900 lines of now-redundant local
    implementation (selections.py, h5type_test.py, requests_lambda.py deleted outright; h5type.py and base.py cut by more
    than half).
  • Introduced h5pyd/hsds_plugin.py (new, ~1,000 lines) as the storage plugin that backs h5json's Hdf5db for HSDS:
    handles object/attribute/link CRUD, chunked value reads/writes, point/fancy/hyperslab selections over HTTP, and
    flush/dirty-object tracking.
  • Reorganized connection-layer modules (httpconn.py, openid.py, serverinfo.py) up from h5pyd/_hl/ to top-level h5pyd/,
    reflecting their new role as shared infrastructure rather than internal _hl details.
  • Added h5json as a hard dependency (pyproject.toml), currently pinned to the abstract branch of HDFGroup/hdf5-json.

New/improved features

  • Consolidated-metadata support: File open/read paths can use a domain's consolidated metadata blob to avoid
    per-object round trips, when available.
  • track_order support for groups/datasets (creation-order tracking).
  • Region reference support on datasets, including scalar dataspaces, and a new _RegionProxy.query() that runs a
    pytable-style query expression and returns a region reference (point selection) over matching elements.
  • Boolean mask selections and improved fancy/point-selection handling (including field-restricted point writes).
  • Native complex-number dtype support on dataset/attribute creation and read/write, using h5py's own real/imaginary
    compound-field convention for compatibility.
  • Committed (named) datatype support, and getFilters() for inspecting dataset filter pipelines.
  • Table class gained query(), read_where(), and update_where() (pytable-style conditional read/update), with explicit
    flush-before/flush-after semantics around query-based updates so local and server state stay consistent.
  • Object reference and dimension-scale fixes for closer h5py compatibility.

Bug fixes

  • Hyperslab read/write, dataset extend/resize, visit(), Folder/dataset_like, and vlen-type handling fixes.
  • Attribute creation/read fixes across scalar, compound, and vlen attribute types.
  • CLI tool fixes: hsinfo, hsstat, hsload (including scalar-dataset domains) — including making hsinfo.py's import
    absolute so it also runs standalone, not just as an installed package.

Housekeeping

  • flake8 cleanup, removed duplicate/dead files, reverted stray test config changes, removed a stale codespace link
    from the README.

Test coverage

Extensive test suite changes alongside the migration: several existing suites were reworked to run against both real
h5py and h5pyd (test_dataset.py, test_dataset_getitem.py, test_group.py, test_vlentype.py, test_dimscale.py,
test_table.py, etc.), plus new test files (test_attribute_create.py, test_attribute_data.py, test_file_read.py) and
substantial expansions to test_dataset_pointselect.py and test_dataset_query.py.

@jreadey
jreadey requested a review from mattjala August 25, 2026 17:47
Comment thread h5pyd/hsds_plugin.py Outdated

return attr_json

def getDatasetValues(self, dset_id, sel=None, dtype=None, query=None):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't match the signature from getDatasetValues defined in hdf5-json. That has dset_id instead of obj_id. They should be the same

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread h5pyd/_hl/files.py
# domain doesn't exist - fall through and create it below
db.plugin = HsdsPlugin(domain, getobjs=getobjs, **kwargs)
new_domain = True
elif mode in ('r', 'r+', 'a'):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this grouping will result in r+ causing a new domain to be created if it didn't already exist, which isn't what the semantics imply.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this and it didn't create a new file with 'r+'. I think there' some trickery going on with the "if new_domain: db.flush()" that restricts new domain creation otherwise.

Comment thread h5pyd/hsds_plugin.py Outdated
if rsp.status_code != 200:
# file must exist
http_conn.close()
raise IOError(rsp.status_code, rsp.reason)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think FileNotFoundError would be more applicable here. This is minor, but could potentially bite us if we have except FileNotFoundError blocks elsewhere.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Comment thread h5pyd/_hl/files.py Outdated
def run_scan(self):
MAX_WAIT = 10
self._getVerboseInfo()
self._getStats(verbose=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_getStats() is defined to take no arguments, so this will result in an error

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh-oh - this wasn't plumbed through to HSDS. I've taken out the whole function.
hsstat (the only thing that used it) now just prints "rescan is not supported".

Comment thread h5pyd/hsds_plugin.py Outdated

return attr_json

def getDatasetValues(self, dset_id, sel=None, dtype=None, query=None):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HsdsPlugin doesn't override queryDataset(), so when h5pyd calls it, it will falls back to pulling down every element in the queried range rather than using the query. Not a crucial fix for the release, but we should make a note this for later.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll make an issue for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants