Ingestion: live tests, cookbook recipe, re-verified docs (#17, PR B) - #69
Merged
Merged
Conversation
PR B of #17: the verification and documentation that need real data. - tests/integration/test_ingestion_client_integration.py: unary, stream (with a server-rejected request), and bidi ingest, each confirmed through await_request_statuses(); an unknown providerId and a duplicate re-ingest both acked and then ERROR; a chunked frame reading back whole; non-scalar columns reaching SUCCESS; the oversized-request hint. - test_query_client_integration.py: the closed-loop round trip, no longer skipped: exact values, half-open bounds, dense alignment, paging. - The datasets and #40/#41 integration tests ingest through the client (tests/integration/ingest_support.py) and wait for SUCCESS instead of polling; sample status gains a live filtered-query test. - doc/cookbook/ingestion.md, run end to end against a live stack. - query.md and sample-status.md re-verified against real data, correcting three claims: a config-only query is rejected by the server, sample query results carry no column metadata, and include() needs status_codes with dense labeling. - iter_ingest_data_bidi_stream() is typed Generator, so the documented contextlib.closing() pattern type-checks. Closes #17 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QkZu3MPfUopTisahmvhakD
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes consistently implement PR B’s testing and documentation scope without unresolved correctness issues.
Review effort: Balanced
Findings: None
What changed in this PR
Completes issue #17’s live verification and documentation for ingestion workflows.
Changes:
- Adds shared confirmed-ingestion helpers and comprehensive live integration coverage.
- Adds the ingestion cookbook and corrects query/sample-status documentation.
- Exposes bidi streams as
Generatorfor typedcontextlib.closing()support.
| File | Description |
|---|---|
src/dp_python_lib/client/ingestion_client.py |
Corrects bidi stream return typing. |
tests/integration/ingest_support.py |
Adds shared confirmed-ingestion helpers. |
tests/integration/test_ingestion_client_integration.py |
Adds end-to-end ingestion scenarios. |
tests/integration/test_query_client_integration.py |
Adds closed-loop query verification. |
tests/integration/test_sample_status_client_integration.py |
Tests live sample-status filtering. |
tests/integration/test_query_helper_relaxations_integration.py |
Migrates setup to confirmed ingestion. |
tests/integration/test_datasets_annotations_integration.py |
Replaces raw-stub ingestion. |
doc/cookbook/ingestion.md |
Adds the ingestion recipe. |
doc/cookbook/query.md |
Corrects and verifies query behavior. |
doc/cookbook/sample-status.md |
Corrects filtering guidance. |
doc/cookbook/datasets-and-annotations.md |
Updates column-builder guidance. |
doc/cookbook/README.md |
Adds ingestion to the cookbook index. |
.dev/tools/check-cookbook-snippets.py |
Supports ingestion snippets. |
README.md |
Links ingestion documentation. |
doc/release-notes/NEXT.md |
Records user-visible changes. |
plan/tickets/17/plan.md |
Records implementation findings. |
CLAUDE.md |
Documents verified behavior and tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
QueryParams accepted config_criteria alone, but QuerySpec.pvSelector is
required by the proto and dp-service rejects every query without one
("querySpec.pvSelector must be specified"). Found re-verifying the query
cookbook against real data. QueryParams now raises ValueError for a
missing selector or an empty PvSelector, pointing at PvQuery.pattern(".*")
for "every PV under a configuration", and the signature makes pv_selector
required so type checkers catch it too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkZu3MPfUopTisahmvhakD
Omitting QueryParams' pv_selector raises TypeError (it has no default), not the ValueError the docs claimed; only None or an empty PvSelector reaches the ValueError. Correct query.md, NEXT.md and CLAUDE.md, mark the NEXT.md entry as an upgrade item, and pin the omitted case with a unit test. Also: correct the cookbook README's worked-example bullet, point the provenance link at the provenance section and note metadata= in the ingestion recipe, fix a misleading test comment, and share one require_services() helper across the integration classes this PR added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QkZu3MPfUopTisahmvhakD
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.
PR B of #17 (
plan/tickets/17/plan.md, "PR B — live tests and docs that need real data"). PR A was #67.Live tests
test_ingestion_client_integration.py(rewritten): every ingest confirmed throughawait_request_statuses().providerIdand a duplicate PV/first-timestamp re-ingest: both acked, then ERROR.ingest_data_stream()with one server-rejected request (a frame over the one-day span cap):rejected_request_ids, the others SUCCESS, the reject's status REJECTED.split_data_frame()-chunked frame (3+ requests) reading back whole.RESOURCE_EXHAUSTEDwith thesplit_data_frame()hint, unary and streamed.test_query_client_integration.py:test_closed_loop_round_tripis no longer skipped;TestQueryClosedLoopasserts exact values/timestamps, half-open trimming at both bounds, dense alignment across two clocks (gaps are unset values, not zeros), and in-order paging atlimit=7.test_sample_status_client_integration.py: newTestSampleStatusQueryFilteringlabels ingested samples and assertsexclude()/include()return exactly the right rows.test_datasets_annotations_integration.py,test_query_helper_relaxations_integration.py: the hand-written stub ingests and probe loops are gone; both use the newtests/integration/ingest_support.pyand wait for SUCCESS.Docs
doc/cookbook/ingestion.md, in the worked example's PVs. It was run end to end as one continuous script against the live stack, and the snippet checker's preamble was extended for it.query.mdandsample-status.mdre-verified against real data. Three claims were wrong; I confirmed each in dp-service or dp-grpc:QueryParamsnow rejects it as well (see Code changes).QuerySpec.pvSelectoris required, andQueryV2Resolverrejects a query without one.df.attrs["column_metadata"]example was fiction.include()withoutstatus_codeskeeps every densely labeled sample. A model that scores every sample gives each one a status, including its "normal" code 0.datasets-and-annotations.mdare replaced;CLAUDE.md,README.mdandNEXT.mdare updated.Code changes
QueryParamsnow requirespv_selector, which is a behavior change. It used to acceptconfig_criteriaalone, a query the server always rejects. The parameter no longer has a default, so leaving it out raisesTypeErrorat the call, and type checkers flag it too. PassingNoneor an emptyPvSelector()raisesValueError, whose message points atPvQuery.pattern(".*"). NEXT.md lists it as an upgrade item._build_query_spec()now copies the selector unconditionally.iter_ingest_data_bidi_stream()is annotatedGeneratorinstead ofIterator. The snippet checker caught that the documentedcontextlib.closing(...)pattern failed mypy for callers. Runtime behavior is unchanged.Verification
ruff format --check,mypy src/, the cookbook snippet checker and the release-notes checker are all clean.Closes #17
🤖 Generated with Claude Code
https://claude.ai/code/session_01QkZu3MPfUopTisahmvhakD