Skip to content

Commit 18090d4

Browse files
thodson-usgsclaude
andauthored
chore: misc cleanups from the package review (#312)
Small, low-risk fixes bundled from the review (no behavior change beyond the two noted): - docs(waterdata): the `bbox` docstring labeled the 4th coordinate "Northern-most longitude"; it is the Northern-most *latitude* (xmin, ymin, xmax, ymax). Fixed across the OGC getters and get_samples (7 spots). - docs(waterdata): get_field_measurements' `properties` listed daily/continuous columns it doesn't have (time_series_id, statistic_id, time); point to the field-measurements OpenAPI schema instead. - fix(nwis): get_discharge_peaks ran format_response twice (via _read_rdb, then again with service="peaks"); parse raw with read_rdb so it formats once. - fix(nwis): query_waterdata validated a dead `state_cd` key while the docs, error message, and callers use `stateCd`; align it so a stateCd-only query is recognized as a major filter. - fix(waterdata): _construct_api_requests omitted an empty-list param as a filterless `&param=` (read by the server as "match empty"); drop it instead. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 473a07c commit 18090d4

4 files changed

Lines changed: 30 additions & 13 deletions

File tree

dataretrieval/nwis.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,10 @@ def get_discharge_peaks(
275275

276276
response = query_waterdata("peaks", format="rdb", ssl_check=ssl_check, **kwargs)
277277

278-
df = _read_rdb(response.text)
278+
# Parse raw (read_rdb), not _read_rdb — the latter already runs
279+
# format_response, and the explicit format_response(service="peaks") below
280+
# does the peaks-specific formatting, so _read_rdb here was a redundant pass.
281+
df = read_rdb(response.text, dtypes=_NWIS_RDB_DTYPES)
279282

280283
return format_response(df, service="peaks", **kwargs), NWIS_Metadata(
281284
response, **kwargs
@@ -375,7 +378,7 @@ def query_waterdata(service: str, ssl_check: bool = True, **kwargs) -> httpx.Res
375378
request: ``httpx.Response``
376379
The response object from the API request to the web service
377380
"""
378-
major_params = ["site_no", "state_cd"]
381+
major_params = ["site_no", "stateCd"]
379382
bbox_params = [
380383
"nw_longitude_va",
381384
"nw_latitude_va",

dataretrieval/waterdata/api.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def get_daily(
189189
axis (height or depth). Coordinates are assumed to be in crs 4326. The
190190
expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax).
191191
Another way to think of it is c(Western-most longitude, Southern-most
192-
latitude, Eastern-most longitude, Northern-most longitude).
192+
latitude, Eastern-most longitude, Northern-most latitude).
193193
limit : numeric, optional
194194
The optional limit parameter is used to control the subset of the
195195
selected features that should be returned in each page. The maximum
@@ -700,7 +700,7 @@ def get_monitoring_locations(
700700
axis (height or depth). Coordinates are assumed to be in crs 4326. The
701701
expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax).
702702
Another way to think of it is c(Western-most longitude, Southern-most
703-
latitude, Eastern-most longitude, Northern-most longitude).
703+
latitude, Eastern-most longitude, Northern-most latitude).
704704
limit : numeric, optional
705705
The optional limit parameter is used to control the subset of the
706706
selected features that should be returned in each page. The maximum
@@ -927,7 +927,7 @@ def get_time_series_metadata(
927927
axis (height or depth). Coordinates are assumed to be in crs 4326. The
928928
expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax).
929929
Another way to think of it is c(Western-most longitude, Southern-most
930-
latitude, Eastern-most longitude, Northern-most longitude).
930+
latitude, Eastern-most longitude, Northern-most latitude).
931931
limit : numeric, optional
932932
The optional limit parameter is used to control the subset of the
933933
selected features that should be returned in each page. The maximum
@@ -1337,7 +1337,7 @@ def get_latest_continuous(
13371337
axis (height or depth). Coordinates are assumed to be in crs 4326. The
13381338
expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax).
13391339
Another way to think of it is c(Western-most longitude, Southern-most
1340-
latitude, Eastern-most longitude, Northern-most longitude).
1340+
latitude, Eastern-most longitude, Northern-most latitude).
13411341
limit : numeric, optional
13421342
The optional limit parameter is used to control the subset of the
13431343
selected features that should be returned in each page. The maximum
@@ -1533,7 +1533,7 @@ def get_latest_daily(
15331533
axis (height or depth). Coordinates are assumed to be in crs 4326. The
15341534
expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax).
15351535
Another way to think of it is c(Western-most longitude, Southern-most
1536-
latitude, Eastern-most longitude, Northern-most longitude).
1536+
latitude, Eastern-most longitude, Northern-most latitude).
15371537
limit : numeric, optional
15381538
The optional limit parameter is used to control the subset of the
15391539
selected features that should be returned in each page. The maximum
@@ -1639,10 +1639,11 @@ def get_field_measurements(
16391639
A short code corresponding to the observing procedure for the field
16401640
measurement.
16411641
properties : string or iterable of strings, optional
1642-
A vector of requested columns to be returned from the query. Available
1643-
options are: geometry, id, time_series_id, monitoring_location_id,
1644-
parameter_code, statistic_id, time, value, unit_of_measure,
1645-
approval_status, qualifier, last_modified
1642+
A vector of requested columns to be returned from the query. See the
1643+
field-measurements schema in the OpenAPI reference for the available
1644+
columns (e.g. geometry, id, monitoring_location_id, parameter_code,
1645+
value, unit_of_measure, approval_status, qualifier, last_modified):
1646+
https://api.waterdata.usgs.gov/ogcapi/v0/openapi?f=html#/field-measurements
16461647
field_visit_id : string or iterable of strings, optional
16471648
A universally unique identifier (UUID) for the field visit.
16481649
Multiple measurements may be made during a single field visit.
@@ -1720,7 +1721,7 @@ def get_field_measurements(
17201721
axis (height or depth). Coordinates are assumed to be in crs 4326. The
17211722
expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax).
17221723
Another way to think of it is c(Western-most longitude, Southern-most
1723-
latitude, Eastern-most longitude, Northern-most longitude).
1724+
latitude, Eastern-most longitude, Northern-most latitude).
17241725
limit : numeric, optional
17251726
The optional limit parameter is used to control the subset of the
17261727
selected features that should be returned in each page. The maximum
@@ -2255,7 +2256,7 @@ def get_samples(
22552256
* Western-most longitude
22562257
* Southern-most latitude
22572258
* Eastern-most longitude
2258-
* Northern-most longitude
2259+
* Northern-most latitude
22592260
22602261
Example: [-92.8,44.2,-88.9,46.0]
22612262
countryFips : string or iterable of strings, optional

dataretrieval/waterdata/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,13 @@ def _construct_api_requests(
674674
params = {k: v for k, v in kwargs.items() if k not in post_params}
675675
else:
676676
# GET with comma-separated values: join list/tuple values into one string.
677+
# Skip empty lists/tuples so they're omitted rather than emitted as a
678+
# filterless ``&param=`` (which the server reads as "match empty").
677679
post_params = {}
678680
params = {
679681
k: ",".join(str(x) for x in v) if isinstance(v, (list, tuple)) else v
680682
for k, v in kwargs.items()
683+
if not (isinstance(v, (list, tuple)) and len(v) == 0)
681684
}
682685

683686
_ogc_query_params(

tests/waterdata_test.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ def test_construct_api_requests_multivalue_get():
175175
assert "parameter_code=00060%2C00065" in str(req.url)
176176

177177

178+
def test_construct_api_requests_omits_empty_list():
179+
"""An empty list value is omitted from the URL, not emitted as a filterless
180+
``&parameter_code=`` (which the server reads as 'match empty')."""
181+
req = _construct_api_requests(
182+
"daily", monitoring_location_id="USGS-05427718", parameter_code=[]
183+
)
184+
assert "parameter_code" not in str(req.url)
185+
assert "monitoring_location_id=USGS-05427718" in str(req.url)
186+
187+
178188
def test_construct_api_requests_monitoring_locations_post():
179189
"""monitoring-locations uses POST+CQL2 for multi-value params (API limitation)."""
180190
req = _construct_api_requests(

0 commit comments

Comments
 (0)