diff --git a/dataretrieval/nwis.py b/dataretrieval/nwis.py index 6a1ed472..b9784802 100644 --- a/dataretrieval/nwis.py +++ b/dataretrieval/nwis.py @@ -283,7 +283,10 @@ def get_discharge_peaks( response = query_waterdata("peaks", format="rdb", ssl_check=ssl_check, **kwargs) - df = _read_rdb(response.text) + # Parse raw (read_rdb), not _read_rdb — the latter already runs + # format_response, and the explicit format_response(service="peaks") below + # does the peaks-specific formatting, so _read_rdb here was a redundant pass. + df = read_rdb(response.text, dtypes=_NWIS_RDB_DTYPES) return format_response(df, service="peaks", **kwargs), NWIS_Metadata( response, **kwargs @@ -383,7 +386,7 @@ def query_waterdata(service: str, ssl_check: bool = True, **kwargs) -> httpx.Res request: ``httpx.Response`` The response object from the API request to the web service """ - major_params = ["site_no", "state_cd"] + major_params = ["site_no", "stateCd"] bbox_params = [ "nw_longitude_va", "nw_latitude_va", diff --git a/dataretrieval/waterdata/api.py b/dataretrieval/waterdata/api.py index 1e6d0aa0..38a73271 100644 --- a/dataretrieval/waterdata/api.py +++ b/dataretrieval/waterdata/api.py @@ -189,7 +189,7 @@ def get_daily( axis (height or depth). Coordinates are assumed to be in crs 4326. The expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax). Another way to think of it is c(Western-most longitude, Southern-most - latitude, Eastern-most longitude, Northern-most longitude). + latitude, Eastern-most longitude, Northern-most latitude). limit : numeric, optional The optional limit parameter is used to control the subset of the selected features that should be returned in each page. The maximum @@ -700,7 +700,7 @@ def get_monitoring_locations( axis (height or depth). Coordinates are assumed to be in crs 4326. The expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax). Another way to think of it is c(Western-most longitude, Southern-most - latitude, Eastern-most longitude, Northern-most longitude). + latitude, Eastern-most longitude, Northern-most latitude). limit : numeric, optional The optional limit parameter is used to control the subset of the selected features that should be returned in each page. The maximum @@ -927,7 +927,7 @@ def get_time_series_metadata( axis (height or depth). Coordinates are assumed to be in crs 4326. The expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax). Another way to think of it is c(Western-most longitude, Southern-most - latitude, Eastern-most longitude, Northern-most longitude). + latitude, Eastern-most longitude, Northern-most latitude). limit : numeric, optional The optional limit parameter is used to control the subset of the selected features that should be returned in each page. The maximum @@ -1337,7 +1337,7 @@ def get_latest_continuous( axis (height or depth). Coordinates are assumed to be in crs 4326. The expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax). Another way to think of it is c(Western-most longitude, Southern-most - latitude, Eastern-most longitude, Northern-most longitude). + latitude, Eastern-most longitude, Northern-most latitude). limit : numeric, optional The optional limit parameter is used to control the subset of the selected features that should be returned in each page. The maximum @@ -1533,7 +1533,7 @@ def get_latest_daily( axis (height or depth). Coordinates are assumed to be in crs 4326. The expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax). Another way to think of it is c(Western-most longitude, Southern-most - latitude, Eastern-most longitude, Northern-most longitude). + latitude, Eastern-most longitude, Northern-most latitude). limit : numeric, optional The optional limit parameter is used to control the subset of the selected features that should be returned in each page. The maximum @@ -1639,10 +1639,11 @@ def get_field_measurements( A short code corresponding to the observing procedure for the field measurement. properties : string or iterable of strings, optional - A vector of requested columns to be returned from the query. Available - options are: geometry, id, time_series_id, monitoring_location_id, - parameter_code, statistic_id, time, value, unit_of_measure, - approval_status, qualifier, last_modified + A vector of requested columns to be returned from the query. See the + field-measurements schema in the OpenAPI reference for the available + columns (e.g. geometry, id, monitoring_location_id, parameter_code, + value, unit_of_measure, approval_status, qualifier, last_modified): + https://api.waterdata.usgs.gov/ogcapi/v0/openapi?f=html#/field-measurements field_visit_id : string or iterable of strings, optional A universally unique identifier (UUID) for the field visit. Multiple measurements may be made during a single field visit. @@ -1720,7 +1721,7 @@ def get_field_measurements( axis (height or depth). Coordinates are assumed to be in crs 4326. The expected format is a numeric vector structured: c(xmin,ymin,xmax,ymax). Another way to think of it is c(Western-most longitude, Southern-most - latitude, Eastern-most longitude, Northern-most longitude). + latitude, Eastern-most longitude, Northern-most latitude). limit : numeric, optional The optional limit parameter is used to control the subset of the selected features that should be returned in each page. The maximum @@ -2257,7 +2258,7 @@ def get_samples( * Western-most longitude * Southern-most latitude * Eastern-most longitude - * Northern-most longitude + * Northern-most latitude Example: [-92.8,44.2,-88.9,46.0] countryFips : string or iterable of strings, optional diff --git a/dataretrieval/waterdata/utils.py b/dataretrieval/waterdata/utils.py index 0a9f1c71..b642a4ef 100644 --- a/dataretrieval/waterdata/utils.py +++ b/dataretrieval/waterdata/utils.py @@ -674,10 +674,13 @@ def _construct_api_requests( params = {k: v for k, v in kwargs.items() if k not in post_params} else: # GET with comma-separated values: join list/tuple values into one string. + # Skip empty lists/tuples so they're omitted rather than emitted as a + # filterless ``¶m=`` (which the server reads as "match empty"). post_params = {} params = { k: ",".join(str(x) for x in v) if isinstance(v, (list, tuple)) else v for k, v in kwargs.items() + if not (isinstance(v, (list, tuple)) and len(v) == 0) } _ogc_query_params( diff --git a/tests/waterdata_test.py b/tests/waterdata_test.py index d541fed3..47bc4458 100644 --- a/tests/waterdata_test.py +++ b/tests/waterdata_test.py @@ -175,6 +175,16 @@ def test_construct_api_requests_multivalue_get(): assert "parameter_code=00060%2C00065" in str(req.url) +def test_construct_api_requests_omits_empty_list(): + """An empty list value is omitted from the URL, not emitted as a filterless + ``¶meter_code=`` (which the server reads as 'match empty').""" + req = _construct_api_requests( + "daily", monitoring_location_id="USGS-05427718", parameter_code=[] + ) + assert "parameter_code" not in str(req.url) + assert "monitoring_location_id=USGS-05427718" in str(req.url) + + def test_construct_api_requests_monitoring_locations_post(): """monitoring-locations uses POST+CQL2 for multi-value params (API limitation).""" req = _construct_api_requests(