Fix WQP_Metadata.site_info: bind as a real property and forward kwargs#249
Fix WQP_Metadata.site_info: bind as a real property and forward kwargs#249thodson-usgs wants to merge 7 commits intoDOI-USGS:mainfrom
Conversation
`site_info` was defined inside `WQP_Metadata.__init__` as a nested
`@property`-decorated function that was never bound to the class. The
decorator returned a property descriptor that was immediately discarded
when `__init__` returned, so `md.site_info` always fell through to
`BaseMetadata.site_info` and raised `NotImplementedError`. The closure
also used `parameters[...]` (the captured `**parameters` kwargs) for the
lookup but `self._parameters` for the `in` check — inconsistent.
Compounding the issue, every helper called `WQP_Metadata(response)` with
no kwargs, so `self._parameters` was always `{}` even after fixing the
closure.
Move `site_info` to a real property on the class, look up `siteid` first
(WQP-native; the previous `sites`/`site`/`site_no` keys reflected an NWIS
copy-paste and never matched a WQP query), and thread `**kwargs` through
`WQP_Metadata(response, **kwargs)` from all nine call sites so the
property has the parameters it needs.
Also corrected the docstring: the attribute is `comment` (not `comments`,
inherited from `BaseMetadata`), and the `query_time` type is
`datetime.timedelta` (not `datetme.timedelta`).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Folds the special-cased `siteid` branch into the loop over candidate keys; semantics are unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
Fixes WQP_Metadata.site_info so it’s a real, class-bound property and ensures request parameters are carried into the metadata object, enabling md.site_info to resolve station metadata instead of falling through to BaseMetadata.site_info.
Changes:
- Convert
WQP_Metadata.site_infofrom an unbound__init__-local closure into a proper@propertyon the class and make parameter lookup consistent. - Forward
**kwargsintoWQP_Metadata(response, **kwargs)fromget_results()and all WQP “what_*” helper call sites so metadata can reference the original query parameters. - Add regression tests ensuring
md.site_inforesolves whensiteidis provided and returnsNonewhen no site filter exists.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
dataretrieval/wqp.py |
Passes query kwargs into WQP_Metadata and redefines site_info as a real property to enable station lookups. |
tests/wqp_test.py |
Adds regression coverage for WQP_Metadata.site_info resolution and the no-site-filter case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @property | ||
| def site_info(self): | ||
| for key in ("siteid", "sites", "site", "site_no"): | ||
| if key in self._parameters: | ||
| return what_sites(siteid=self._parameters[key]) | ||
| return None |
| def test_wqp_metadata_site_info_property_resolves(requests_mock): | ||
| """`site_info` must be a real property bound to the class. | ||
|
|
||
| Regression: previously `site_info` was defined as a closure inside | ||
| `__init__`, so `md.site_info` fell through to `BaseMetadata.site_info` | ||
| and raised `NotImplementedError`. Also verify the parameters are | ||
| threaded through from `get_results`. | ||
| """ |
Per copilot review on PR DOI-USGS#249. The site_info property previously called what_sites() with default legacy=True/ssl_check=True, so a WQX3.0 get_results(legacy=False, ...) call produced a legacy Station lookup. WQP_Metadata now persists the originating legacy/ssl_check on the instance and forwards them when site_info is accessed. All nine WQP_Metadata call sites now thread these through. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…-info # Conflicts: # tests/wqp_test.py
Per /simplify review on PR DOI-USGS#249: - Switch `site_info` from `@property` to `functools.cached_property`. Repeated access of `md.site_info` (common in notebooks) now reuses the resolved tuple instead of issuing a fresh `what_sites` HTTP call on every read. - Add a one-line comment explaining the legacy-alias -> `siteid` coercion: whichever of `siteid`/`sites`/`site`/`site_no` matched, the value is passed as `siteid` (what_sites' native WQP arg). Also confirmed the docstring's `comments` -> `comment` rename matches `BaseMetadata.comment` (singular) defined at `dataretrieval/utils.py:130`. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
WQP_Metadata is not strictly a snapshot — a long-lived `md` reference (paginated workflow, long-running script) would see stale site metadata if `site_info` cached its result. Plain `@property` matches user expectation that an attribute named `site_info` reflects the current state, and the cost of one extra HTTP call on re-read is acceptable. Drop the now-unused `from functools import cached_property`. The coercion comment is retained. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
WQP_Metadata.site_infowas defined inside__init__as a nested@property-decorated function that was never bound to the class. The decorator returned a property descriptor that was immediately discarded when__init__returned, somd.site_infoalways fell through toBaseMetadata.site_infoand raisedNotImplementedError. The closure also usedparameters[...](the captured**parameterskwargs) for the lookup butself._parametersfor theincheck — an internal inconsistency.Compounding the issue, every helper called
WQP_Metadata(response)with no kwargs, soself._parameterswas always{}even after fixing the closure.This PR:
site_infoto a real@propertyon the class.siteidfirst (WQP-native; the previoussites/site/site_nokeys reflected an NWIS copy-paste and never matched a WQP query) while keeping the legacy aliases as a fallback.**kwargsthroughWQP_Metadata(response, **kwargs)from all nine call sites so the property has the parameters it needs.comment(singular, inherited fromBaseMetadata) andquery_timeis adatetime.timedelta(wasdatetme.timedelta).Minimal reproducible example
Pre-fix bug
The pre-fix shape that causes this:
So
md.site_infoalways resolves toBaseMetadata.site_info, which raises.Post-fix, live API
Test plan
tests/wqp_test.py:site_inforesolves and returns a(DataFrame, WQP_Metadata)tuple whensiteidwas provided; returnsNonewhen no site filter was supplied.tests/wqp_test.py(15 tests) pass.md.site_infonow returns the expected tuple.Related PRs
Other open PRs in this bug-review series that touch
dataretrieval/wqp.py(different functions, no functional conflicts):dataProfileinget_results.