Skip to content

New integrations with AHORN and Hypergraphx-Data - #759

Open
nwlandry wants to merge 10 commits into
devfrom
new-data-repo-integrations
Open

New integrations with AHORN and Hypergraphx-Data#759
nwlandry wants to merge 10 commits into
devfrom
new-data-repo-integrations

Conversation

@nwlandry

@nwlandry nwlandry commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

This PR does the following:

  • Generalizes request_json_from_url and request_json_from_url_cached to request_from_url and request_from_url_cached
  • Adds load_ahorn_data and load_hypergraphx_data to the XGI API.

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.56863% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.69%. Comparing base (18b70fa) to head (ac9b395).
⚠️ Report is 1 commits behind head on dev.

Files with missing lines Patch % Lines
xgi/readwrite/hypergraphx_data.py 92.78% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #759      +/-   ##
==========================================
+ Coverage   94.43%   94.69%   +0.25%     
==========================================
  Files          65       65              
  Lines        5213     5336     +123     
==========================================
+ Hits         4923     5053     +130     
+ Misses        290      283       -7     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nwlandry nwlandry mentioned this pull request Aug 24, 2026
@nwlandry

Copy link
Copy Markdown
Collaborator Author

Hey @leotrs --- (Sorry for the re-ping; I mistakenly deleted my previous comment) if you would be willing to help with unit tests and reviewing, I would really appreciate it! This seems like an ideal place for automated code generation.

@leotrs leotrs left a comment

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.

Direction is right (this is the second half of the #756 split), and generalizing request_json_from_url into request_from_url(mode=...) is a nice cleanup. A few things I'd like to see addressed before merge.

Blockers

  1. hypergraphx_data.py::_download reintroduces its own HTTP client with verify_ssl=False by default. This bypasses TLS certificate verification (ssl._create_unverified_context()), which opens the loader to man-in-the-middle attacks — every HGX download from cricca.disi.unitn.it is served over an unverified TLS channel. On top of that, the function shadows the perfectly good request_from_url(url, mode="raw") this same PR generalizes, and the verify_ssl=True branch is dead code (verify_ssl defaults to False and there's no public way to override it). Options: (a) fix the cert issue upstream or install certifi and require it; (b) if there's a specific cert-chain problem with cricca.disi that can't be solved, handle it once inside request_from_url with a clear comment naming the host. Either way, don't ship a silent MITM path. If we merge as-is, users pulling HGX datasets are trusting whatever intermediary is on their network.

  2. load_ahorn_data hits the catalog twice per call. Once at the top of the function to build index_data, and again inside _get_dataset_data. That's an extra round trip to ahorn.rwth-aachen.de for every non-listing invocation. Either fetch once and thread the catalog through _get_dataset_data, or route both through request_from_url_cached.

  3. load_hypergraphx_data has no cache parameter. load_xgi_data, load_bigg_data, and load_ahorn_data all do. Users shouldn't have to guess which loaders cache. Add it.

  4. _from_ahorn_text ignores nodetype and edgetype. It always casts node IDs to int (node = int(ids)) and never applies edgetype to the edge or nodetype to nodes/edge members. The HIF path does the right thing; the ahorn-text path silently drops the caller's contract. If AHORN datasets can come back in either format (they can, per _get_dataset_url), the two paths need to be consistent.

Should fix (not blocking but worth doing)

  1. Exception types don't match docstrings. Both load_ahorn_data and load_hypergraphx_data docstrings say "Raises XGIError" for invalid dataset names, but the code raises KeyError. Either use XGIError (matches the rest of the loaders) or fix the docstring. Same file: _parse_remote_dataset_catalog raises TypeError for parsing/validation failures, where XGIError or ValueError is more appropriate — TypeError should be reserved for actual type mismatches.

  2. The HGX catalog parser is a fragility waiting to happen. _parse_remote_dataset_catalog regex-matches window.RELATED_DATASETS = ... out of a JavaScript file. If the hypergraphx-data team refactors their static JS (renames the global, minifies it, splits it, wraps it in an IIFE, anything), we silently break. This is exactly the "maintenance contract" concern I raised on #756 — worth pinging the HGX maintainers to see if they can expose a stable JSON endpoint instead. Not blocking this PR, but file an issue so it's tracked.

Nits

  1. _get_dataset_url accepts a revision argument but there's no way to pass it from load_ahorn_data — always defaults to max. Either wire it through or drop the parameter until it has a caller.

  2. load_ahorn_data mixes print and return on the listing pathprint(*index_data, sep="\n") and then return index_data. Matches load_xgi_data's pattern, so consistent, but worth flagging as a broader-API cleanup later.

  3. Docstring for the new mode parameter in request_from_url and request_from_url_cached is duplicated verbatim. Fine, but a shared constant or a See Also on one would DRY it.

  4. nodetype in _load_hypergraph (HGX) — applied to node_id and to each element of interaction, but the edge metadata.pop("id") path uses edgetype correctly. That part looks fine, but skim it in case any metadata field carries node references.

  5. Coverage check is failing (codecov/project:FAILURE). Not blocking, but a quick look at what's uncovered would probably surface some of the above (the _download error paths aren't tested, neither is the format == "ahorn" branch in _request_from_ahorn_data).

  6. Benchmark workflow bumped to Python 3.14 without confirming the benchmark deps install cleanly on 3.14 (asv, matplotlib, scipy…). If any of them lag, benchmarks silently break.

Overall the loaders are the right shape and the utility rename is clean. Please address 1-4 and I'll re-review; 5-6 would be nice too.

leotrs and others added 2 commits August 27, 2026 10:28
The `except HTTPError` branch in `_download` re-raised a new HTTPError
with only the message argument, but HTTPError's __init__ signature is
(url, code, msg, hdrs, fp). Any real HTTP failure would therefore fall
into a TypeError inside the exception handler rather than surface the
intended message. Pass the original exception's url/code/headers through
and use the wrapped-message string as msg.

Surfaced by the new unit test for this branch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyLLuAmW2dQ7KCewxArJHd
Adds targeted mocked tests to cover the paths that the existing webtest
markers skip locally:

AHORN (test_ahorn_data.py):
- listing branch of load_ahorn_data with prints
- KeyError on invalid dataset name
- happy path through the HIF format
- cache=False routes through the uncached utility
- ahorn-text format branch of _request_from_ahorn_data
- max_order truncation
- _from_ahorn_text: metadata + nodes + edges, blank-line skipping

hypergraphx-data (test_hypergraphx_data.py):
- edge record without an explicit id
- unknown record-type is silently ignored
- _parse_remote_dataset_catalog error branches: invalid JSON, invalid
  window.RELATED_DATASETS body, non-list shape, name-less items skipped
- load_hypergraphx_data listing, invalid dataset, full dispatch,
  max_order truncation
- _download happy path, HTTPError wrapping, URLError wrapping

Uses mocked responses and gzipped fixtures throughout, so nothing hits
the network. All 35 tests in the two files pass under the current
matrix Python versions (previously most of them were webtest-skipped).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyLLuAmW2dQ7KCewxArJHd
@leotrs

leotrs commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Pushed two commits to your branch:

01a5b15 fix: construct HTTPError with the required positional args in _download
The except HTTPError branch in _download re-raised a new HTTPError with only one positional argument, but HTTPError.__init__ needs five. Any real HTTP failure would surface as a TypeError inside the exception handler rather than the intended message. Surfaced by the new unit test for that branch. Minimal fix — this doesn't preempt the broader question in my review about whether _download should exist at all.

4440a86 test: add unit tests for AHORN and hypergraphx-data loaders
+34 tests, all mocked (no network). Coverage additions:

AHORN:

  • load_ahorn_data listing branch, KeyError on invalid dataset
  • HIF-format happy path, cache=False routes through uncached utility
  • ahorn-text-format branch of _request_from_ahorn_data
  • max_order truncation
  • _from_ahorn_text metadata + nodes + edges + blank-line skipping

hypergraphx-data:

  • _load_hypergraph: edge without explicit id, unknown record-type ignored
  • _parse_remote_dataset_catalog error paths: invalid JSON, invalid window.RELATED_DATASETS body, wrong shape, name-less items skipped
  • load_hypergraphx_data: listing, invalid dataset, full dispatch, max_order truncation
  • _download: happy path, HTTPError wrapping, URLError wrapping

Full local suite: 480 passed / 7 skipped. Codecov should be a lot happier — most of the previously-untested lines are now covered without needing the network.

The review points on _download, the double-catalog-fetch, missing cache, and _from_ahorn_text ignoring nodetype/edgetype still stand — the tests here document the current behavior so it's easy to see what changes when you address those.

Applies four review comments from #759:

1. `load_ahorn_data` now fetches the AHORN catalog exactly once per call
   and threads it into `_request_from_ahorn_data` / `_get_dataset_data`.
   Previously the catalog was fetched twice (once at the top of
   `load_ahorn_data` and again inside `_get_dataset_data`). Kept the
   `catalog=None` path in `_get_dataset_data` so direct callers still work.

2. `load_hypergraphx_data` gains a `cache=True` parameter, matching
   `load_xgi_data`, `load_ahorn_data`, and `load_bigg_data`. Caching is
   implemented as `@cache _download_cached(url)` wrapping the existing
   `_download`, so the underlying network path is unchanged.

3. `_from_ahorn_text` now honors `nodetype` for node IDs (both single
   nodes and edge members). Defaults to `int`, preserving the existing
   behavior when `nodetype` is not passed. `edgetype` remains unused
   because edges get auto-assigned uids from `Hypergraph`; documented
   this in the parameter docstring.

4. `load_ahorn_data` and `load_hypergraphx_data` now raise `XGIError` for
   invalid dataset names, matching their docstrings (previously they
   raised `KeyError`). Error messages name the specific repository.

Tests updated accordingly and new coverage added:
- `test_load_ahorn_data_fetches_catalog_once` — asserts single catalog hit.
- `test_load_ahorn_data_invalid_dataset` — asserts XGIError.
- `test_from_ahorn_text_respects_nodetype` — asserts nodetype casting.
- `test_load_hypergraphx_data_invalid_dataset` — asserts XGIError.
- `test_load_hypergraphx_data_cache_false_bypasses_cache` — asserts the
  cache=False path routes around the memoized wrapper.
- `test_load_hypergraphx_data_cache_true_reuses_result` — asserts two
  calls with cache=True hit `_download` only once.

Full local suite: 484 passed / 7 skipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyLLuAmW2dQ7KCewxArJHd
@leotrs

leotrs commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

One more commit addressing the remaining low-risk review items:

933805d refactor: address review items on AHORN and hypergraphx-data loaders

  1. Single catalog fetch (review item 2). load_ahorn_data now fetches the AHORN catalog once per call and threads it into _request_from_ahorn_data / _get_dataset_data. Kept the catalog=None fallback in _get_dataset_data so direct callers still work.

  2. load_hypergraphx_data gains cache=True (review item 3). Matches load_xgi_data, load_ahorn_data, load_bigg_data. Implemented as @cache _download_cached(url) wrapping the existing _download, so the underlying network path is unchanged and your _download design decision stays yours to revisit.

  3. _from_ahorn_text honors nodetype (review item 4). Both single-node and edge-member IDs are cast; defaults to int when nodetype is not passed, preserving existing behavior. edgetype is documented as unused since edges get auto-assigned uids.

  4. KeyErrorXGIError in both loaders (review item 5, part 1). Now matches the docstrings.

Left explicitly for you:

  • The bigger _download question (review item 1: verify_ssl=False default, and whether to keep _download at all vs. routing through request_from_url(url, mode="raw")). Adding cache in a wrapper preserves that decision for you.
  • The hypergraphx catalog parser fragility (review item 6) — needs an upstream conversation with the HGX team.

Full local suite: 484 passed / 7 skipped. Adding this brings us to a total of +39 mocked tests on top of the two you had.

The pre-existing `test_load_ahorn_data` webtest asserted `KeyError` for
the invalid-dataset path. The previous commit changed `load_ahorn_data`
to raise `XGIError` to match its docstring. Local tests were updated in
that commit but the webtest was skipped locally (network-required), so
the mismatch was only caught by Ubuntu CI. Update it too.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyLLuAmW2dQ7KCewxArJHd
@leotrs

leotrs commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

CI is green (20/20). Here's the final state of the review items:

Addressed in-branch:

  • ✅ HTTPError construction bug in _download (surfaced by the new tests)
  • ✅ Single AHORN catalog fetch per call (review item 2)
  • cache=True parameter on load_hypergraphx_data (item 3)
  • _from_ahorn_text honors nodetype (item 4)
  • KeyErrorXGIError in both loaders, matching docstrings (item 5)
  • ✅ +39 mocked unit tests covering the previously network-only paths (coverage was 71.57%, should be substantially higher now)

Left for you:

  • The bigger _download question (item 1): TLS verification disabled by default, and whether to keep _download at all vs. routing through request_from_url(url, mode="raw"). I kept _download untouched and added caching as a @cache wrapper around it, so this stays your design call.
  • HGX catalog parser fragility (item 6): fix is upstream — worth pinging the HGX team about a stable JSON endpoint. Not blocking this PR.

Please give the last three commits (01a5b15, 4440a86, 933805d, ac9b395) a look and merge when you're happy.

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.

2 participants