diff --git a/python/nwis_client/setup.cfg b/python/nwis_client/setup.cfg index 82af7682..2ee804c5 100644 --- a/python/nwis_client/setup.cfg +++ b/python/nwis_client/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = hydrotools.nwis_client -version = 3.0.4 +version = 3.0.5 author = Austin Raney author_email = aaraney@protonmail.com description = A convenient interface to the USGS NWIS Instantaneous Values (IV) REST Service API. diff --git a/python/nwis_client/src/hydrotools/nwis_client/iv.py b/python/nwis_client/src/hydrotools/nwis_client/iv.py index 4794488a..cf5c69d0 100644 --- a/python/nwis_client/src/hydrotools/nwis_client/iv.py +++ b/python/nwis_client/src/hydrotools/nwis_client/iv.py @@ -247,17 +247,25 @@ def list_to_df_helper(item: dict): return df + def empty_df_warning_helper(): + warning_message = "No data was returned by the request." + warnings.warn(warning_message) + list_of_frames = list(map(list_to_df_helper, raw_data)) # Empty list. No data was returned in the request if not list_of_frames: - warning_message = "No data was returned by the request." - warnings.warn(warning_message) - return pd.DataFrame(None) + empty_df_warning_helper() + return _create_empty_canonical_df() # Concatenate list in single pd.DataFrame dfs = pd.concat(list_of_frames, ignore_index=True) + # skip data processing steps if no data was retrieved and return empty canonical df + if dfs.empty: + empty_df_warning_helper() + return _create_empty_canonical_df() + # Convert values to numbers dfs.loc[:, "value"] = pd.to_numeric(dfs["value"], downcast="float") @@ -809,3 +817,17 @@ def flatten_and_stringify(v): value_groups = np.array_split(values, n_groups) return list(map(lambda i: ",".join(i), value_groups)) + + +def _create_empty_canonical_df() -> pd.DataFrame: + """Returns an empty hydrotools canonical dataframe with correct field datatypes.""" + cols = { + "value_time": pd.Series(dtype="datetime64[ns]"), + "variable_name": pd.Series(dtype="category"), + "usgs_site_code": pd.Series(dtype="category"), + "measurement_unit": pd.Series(dtype="category"), + "value": pd.Series(dtype="float32"), + "qualifiers": pd.Series(dtype="category"), + "series": pd.Series(dtype="category"), + } + return pd.DataFrame(cols, index=[]) diff --git a/python/nwis_client/tests/test_nwis.py b/python/nwis_client/tests/test_nwis.py index 9da45eb4..fef48d8f 100644 --- a/python/nwis_client/tests/test_nwis.py +++ b/python/nwis_client/tests/test_nwis.py @@ -423,3 +423,17 @@ def test_get_raw_countyCd(setup_iv): def test_splitting_bbox(test, validation): v = iv._bbox_split(test) assert v == validation + + +def test_get_returns_empty_canonical_dataframe(setup_iv, monkeypatch): + """Verify that `get` can returns an empty canonical dataframe.""" + + def get_raw_mock(*args, **kwargs): + return [{"values": []}] + + monkeypatch.setattr(iv.IVDataService, "get_raw", get_raw_mock) + df = setup_iv.get( + sites=["01189000"], startDt="2015-12-01T00:00", endDt="2015-12-31T23:45" + ) + canonical_df = iv._create_empty_canonical_df() + assert df.equals(canonical_df)