kas-scoped-transfer-cli#645
Conversation
Add a new `oco scoped-transfer` command and the supporting scoped transfer service for running legacy transfers by PointID. This adds scoped planning and execution, dependency expansion, family-level summary output, scoped well handling, scoped water-level idempotency, and contact-collision fallback reuse. It also suppresses legacy transfer warnings that are misleading in scoped CLI runs.
…coped transfer CLI and services Add focused tests for scoped transfer CLI output and planning behavior. This covers water-level contact collision reuse, scoped duplicate filtering and scoped log suppression for the targeted transfer workflow.
There was a problem hiding this comment.
Pull request overview
Adds a new oco scoped-transfer CLI workflow and supporting service layer to run targeted legacy transfers by specific PointID(s), including scoped filtering/behavior fixes for wells and water-level imports and regression tests to preserve the new scoped behavior.
Changes:
- Added
scoped-transferCLI command with--pointid,--only/--skip,--dry-run, and human/JSON output modes. - Introduced
services/scoped_transfer.pyimplementing family planning/execution, dependency expansion, scoped filtering helpers, and scoped transferer wrappers/fixes. - Added regression tests covering CLI output, dry-run planning, chemistry planning, scoped duplicate filtering, water-level contact collision reuse, and log suppression.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
cli/cli.py |
Adds the scoped-transfer command and output formatting/exit-code behavior. |
services/scoped_transfer.py |
Implements scoped transfer runtime, family registry, planners/executors, scoped transferer variants, and logging noise suppression. |
tests/test_scoped_transfer_cli.py |
Adds unit/regression tests for scoped CLI/service behaviors. |
| else: | ||
| matched_pointids.update(runtime.options.pointids) | ||
|
|
||
| missing = sorted(set(runtime.options.pointids) - matched_pointids) | ||
| if missing: |
There was a problem hiding this comment.
The preflight PointID validation can miss partially-matching scopes: when any non-well/non-site-type family has applicable rows, the else branch marks all requested PointIDs as matched (matched_pointids.update(runtime.options.pointids)), so a run like --pointid A --pointid B --only waterlevels will not report B as missing if only A has rows. Track matched PointIDs from the filtered source data for each family (e.g., by returning/deriving a matched set from each planner) instead of assuming all requested PointIDs matched when any row exists.
There was a problem hiding this comment.
This only affects preflight validation, not the actual scoped filtering during execution, so it should not transfer the wrong records. I agree the right fix is to track matched PointIDs per planner, but I’m going to leave that as a follow-up to keep this PR focused on the scoped-transfer work.
| re.compile(r"^\d+ PointIDs have duplicates; will skip\.$"), | ||
| re.compile(r"^Duplicate PointIDs: "), |
There was a problem hiding this comment.
The scoped log filter currently suppresses the duplicate-PointID messages ("PointIDs have duplicates; will skip." / "Duplicate PointIDs:"). After scoping ScopedWellTransferer’s duplicate check to the requested PointIDs, these messages become actionable (they explain why a requested PointID produced a no-op). Consider not filtering these patterns in scoped mode, or emitting a scoped-specific message (or ScopedFamilyResult.detail) that remains visible.
| re.compile(r"^\d+ PointIDs have duplicates; will skip\.$"), | |
| re.compile(r"^Duplicate PointIDs: "), |
There was a problem hiding this comment.
I think this is fine to leave as follow-up work for now. If it becomes an issue in real use, I'd prefer to show it in the scoped summary/detail output instead of re-enabling the raw legacy log messages.
Introduce a comprehensive guide for the `oco scoped-transfer` CLI command, including examples, common scenarios, troubleshooting tips, and JSON output details. Also, link the guide in `README.md`.
Summary
This PR adds a new
oco scoped-transfercommand for running targeted legacy imports by PointID. It also adds the scoped transfer service behind that command, fixes scoped behavior in the well and water-level paths, reduces misleading log noise during scoped runs, and adds regression tests for the main scoped behaviors.Why
This PR addresses the following problem / context:
The existing transfer workflow was built for broad or full-dataset runs, which made it hard to safely run and validate an import for one site or a small set of PointIDs. While building the scoped CLI, a few issues showed up in the well and water-level paths where the legacy behavior did not map cleanly to targeted runs. The output was also noisy enough that it could be hard to tell what mattered during a scoped transfer.
This PR creates a dedicated scoped-transfer workflow so targeted imports can be run more safely, more predictably, and with clearer operator feedback.
How
Implementation summary - the following was changed / added / removed:
Added a new
oco scoped-transferCLI command with:--pointidsupport for targeted runs--only/--skipfamily selectionAdded the scoped transfer service in
services/scoped_transfer.pywith:Added scoped wrappers / behavior fixes for key transfer paths:
Reduced misleading log output in scoped CLI mode by suppressing known legacy warnings that are expected or irrelevant in targeted runs, including:
Added regression coverage in tests/test_scoped_transfer_cli.py for:
Notes
Any special considerations, workarounds, or follow-up work to note?