Add THREDDS catalog connector to the acquire stage#227
Open
Hackshaven wants to merge 4 commits into
Open
Conversation
Implements `zyra acquire thredds` to enumerate datasets from a THREDDS catalog.xml, map each dataset's urlPath to its HTTPServer (fileServer) download URL, and list, sync, or fetch matching datasets. Supports opt-in recursion into nested catalogRef entries (with a depth cap and cycle guard), pattern/date filtering, and sync replacement options that mirror the existing FTP connector vocabulary. - New backend: connectors/backends/thredds.py (hermetic; supports a fetcher/catalog_xml injection so tests need no network). Malformed, non-XML catalog responses are logged and skipped during recursion. - CLI: acquire/import `thredds` subcommand. `--output` fetches a single matched dataset (default stdout); `--output-dir` is required only for multi-file fetches. `--date-format` documents strftime tokens. - API: AcquireThreddsArgs/AcquireThreddsRun wired into POST /acquire. - Tests: backend + CLI tests using offline catalog fixtures. - Docs: ingest README THREDDS section; sample pipeline thredds_to_local.yaml. - Generated capabilities manifest and OpenAPI sha256 snapshot. Addresses NOAA-GSL/zyra#283 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vfz8KKCKV7AGZ9RSPCiRoH Signed-off-by: Claude <noreply@anthropic.com>
|
🔁 Relay created/updated upstream PR: NOAA-GSL/zyra#286 |
Deploying zyra with
|
| Latest commit: |
a3d52c6
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://1b138c32.zyra.pages.dev |
| Branch Preview URL: | https://claude-thredds-acquire-283.zyra.pages.dev |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new THREDDS “catalog.xml” acquisition connector to Zyra’s ingest/acquire layer, including CLI and API wiring, so users can enumerate and bulk-fetch datasets from THREDDS Data Server catalogs (similar to existing S3/FTP directory-style workflows).
Changes:
- Introduces
zyra acquire thredds/zyra import threddsbacked by a new THREDDS backend that parses catalogs, optionally recursescatalogRefs, and supports list/sync/fetch flows. - Wires THREDDS into the API acquire discriminated union + schemas, and updates wizard capabilities manifests/OpenAPI snapshot hash.
- Adds hermetic backend + CLI tests and a sample pipeline YAML.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/snapshots/openapi_sha256.txt | Updates OpenAPI snapshot hash to reflect new acquire tool. |
| tests/connectors/test_thredds_backend.py | Adds offline unit tests for catalog parsing, filtering, recursion, and sync behavior. |
| tests/cli/test_acquire_thredds.py | Adds hermetic CLI-level tests for zyra acquire thredds list/sync/output behaviors. |
| src/zyra/wizard/zyra_capabilities/acquire.json | Adds acquire thredds and import thredds command metadata for the wizard/capabilities system. |
| src/zyra/wizard/zyra_capabilities.json | Same capabilities updates in the consolidated wizard capabilities file. |
| src/zyra/connectors/ingest/README.md | Documents THREDDS usage patterns and options alongside other ingest connectors. |
| src/zyra/connectors/ingest/init.py | Registers the new thredds subcommand and implements the CLI handler. |
| src/zyra/connectors/backends/thredds.py | Implements THREDDS catalog parsing, dataset enumeration, and sync/fetch helpers. |
| src/zyra/api/schemas/domain_args.py | Adds AcquireThreddsArgs and header normalization for acquire thredds. |
| src/zyra/api/routers/domain_acquire.py | Extends the acquire request union to include AcquireThreddsRun. |
| src/zyra/api/models/domain_api.py | Adds AcquireThreddsRun model for the API discriminator. |
| samples/pipelines/thredds_to_local.yaml | Adds a sample pipeline demonstrating THREDDS → transform → visualize → export. |
- _build_download_url: support an absolute HTTPServer service base (with scheme/netloc) by using it as the download root directly, while relative bases continue to resolve against the catalog's host. Uses urllib.parse urljoin/urlparse instead of manual concatenation. Adds a unit test asserting an absolute-base catalog points at the declared host. - _cmd_thredds: warn (not error) when more than one of --list/--sync-dir/ --output-dir is passed, naming the mode that actually runs, keeping the existing precedence (--list > --sync-dir > fetch). - Document basename-collision behavior on sync_directory and the --output-dir help text (datasets sharing a basename overwrite, as with the s3/ftp backends). - Lift the in-function `from pathlib import Path` in _cmd_thredds to the module-level imports. Regenerate capabilities manifest for the updated --output-dir help text; OpenAPI snapshot is unchanged (internal/help-only changes). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vfz8KKCKV7AGZ9RSPCiRoH Signed-off-by: Claude <noreply@anthropic.com>
|
🔁 Relay created/updated upstream PR: NOAA-GSL/zyra#286 |
Recursion across catalogRef entries that point at a different host (absolute xlink:href) or a catalog with a different HTTPServer base can produce distinct datasets that share the same urlPath. De-duplicating on urlPath alone would drop one of them, so key the seen-set on the fully resolved download_url instead. Adds a cross-host recursion test. Pairs with the absolute fileServer base handling added in the previous commit. Addresses Copilot review feedback on NOAA-GSL/zyra#283. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vfz8KKCKV7AGZ9RSPCiRoH Signed-off-by: Claude <noreply@anthropic.com>
|
🔁 Relay created/updated upstream PR: NOAA-GSL/zyra#286 |
In _should_download, when --recheck-existing is set but the server omits or blocks Content-Length (http_backend.get_size returns None), the previous logic forced a re-download every run. Keep the local copy instead, matching the FTP backend's recheck_existing semantics (re-download only on a known size mismatch). Avoids unnecessary network/mirror load against servers that don't expose HEAD/Content-Length. Adds a regression test. Addresses Copilot review feedback on NOAA-GSL/zyra#283. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vfz8KKCKV7AGZ9RSPCiRoH Signed-off-by: Claude <noreply@anthropic.com>
|
🔁 Relay created/updated upstream PR: NOAA-GSL/zyra#286 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a dedicated
zyra acquire threddsconnector that reads a THREDDS Data Servercatalog.xml, maps each dataset'surlPathto itsHTTPServer(fileServer) download URL, and lists, syncs, or fetches matching datasets. Closes the workflow gap in NOAA-GSL/zyra#283 — previouslyacquire httponly handled individual URLs, with no bulk catalog enumeration like S3/FTP offer.What's included
src/zyra/connectors/backends/thredds.py—parse_catalog,enumerate_datasets,list_files,sync_directorysrc/zyra/connectors/ingest/__init__.py—threddssubcommand (registered foracquireandimport)AcquireThreddsArgs,AcquireThreddsRun, wired into thePOST /acquirediscriminated uniontests/connectors/test_thredds_backend.py,tests/cli/test_acquire_thredds.py(offline fixtures)README.mdTHREDDS section;samples/pipelines/thredds_to_local.yamlsha256snapshotDesign notes
acquire httpflag) — THREDDS concepts (services,catalogRefrecursion,urlPath→fileServer mapping) don't map onto the HTTP anchor-scraper; matches thes3/ftpprecedent.--recursivefollows nestedcatalogRefentries up to--max-depth(default 3), with a cycle guard. Non-XML responses (HTML error pages / auth redirects) are logged and skipped so one bad catalog doesn't abort traversal.--outputworks for single matches;--output-dirrequired only for multi-file fetches (clear error otherwise).--pattern/--since/--until/--since-period/--date-format(strftime tokens) and the sync replacement options reuse the existing connector surface.xml.etree.ElementTree+ existingrequests. Tests are hermetic via afetcher/catalog_xmlinjection.Validation
ruff format/checkclean; backend + CLI + OpenAPI snapshot tests passingzyra generate-manifestand the OpenAPI snapshotAddresses NOAA-GSL/zyra#283
🤖 Generated with Claude Code
Generated by Claude Code