cwms-python 0.1.0__tar.gz → 0.4.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. cwms_python-0.4.4/LICENSE +21 -0
  2. cwms_python-0.4.4/PKG-INFO +95 -0
  3. cwms_python-0.4.4/README.md +73 -0
  4. cwms_python-0.4.4/cwms/__init__.py +22 -0
  5. cwms_python-0.4.4/cwms/api.py +336 -0
  6. cwms_python-0.4.4/cwms/catalog/catalog.py +128 -0
  7. cwms_python-0.4.4/cwms/forecast/forecast_instance.py +208 -0
  8. cwms_python-0.4.4/cwms/forecast/forecast_spec.py +181 -0
  9. cwms_python-0.4.4/cwms/levels/location_levels.py +221 -0
  10. cwms_python-0.4.4/cwms/levels/specified_levels.py +126 -0
  11. cwms_python-0.4.4/cwms/locations/physical_locations.py +157 -0
  12. cwms_python-0.4.4/cwms/ratings/ratings.py +378 -0
  13. cwms_python-0.4.4/cwms/ratings/ratings_spec.py +154 -0
  14. cwms_python-0.4.4/cwms/ratings/ratings_template.py +148 -0
  15. cwms_python-0.4.4/cwms/standard_text/standard_text.py +201 -0
  16. cwms_python-0.4.4/cwms/timeseries/timerseries_identifier.py +135 -0
  17. cwms_python-0.4.4/cwms/timeseries/timeseries.py +273 -0
  18. cwms_python-0.4.4/cwms/timeseries/timeseries_bin.py +212 -0
  19. cwms_python-0.4.4/cwms/timeseries/timeseries_txt.py +206 -0
  20. cwms_python-0.4.4/cwms/types.py +87 -0
  21. cwms_python-0.4.4/pyproject.toml +43 -0
  22. cwms-python-0.1.0/.github/workflows/publish-to-test-pypi.yml +0 -117
  23. cwms-python-0.1.0/CWMS/.ipynb_checkpoints/__init__-checkpoint.py +0 -11
  24. cwms-python-0.1.0/CWMS/.ipynb_checkpoints/core-checkpoint.py +0 -0
  25. cwms-python-0.1.0/CWMS/.ipynb_checkpoints/cwms_loc-checkpoint.py +0 -38
  26. cwms-python-0.1.0/CWMS/.ipynb_checkpoints/cwms_ts-checkpoint.py +0 -47
  27. cwms-python-0.1.0/CWMS/.ipynb_checkpoints/utils-checkpoint.py +0 -52
  28. cwms-python-0.1.0/CWMS/__init__.py +0 -11
  29. cwms-python-0.1.0/CWMS/__pycache__/__init__.cpython-39.pyc +0 -0
  30. cwms-python-0.1.0/CWMS/__pycache__/core.cpython-39.pyc +0 -0
  31. cwms-python-0.1.0/CWMS/__pycache__/cwms_loc.cpython-39.pyc +0 -0
  32. cwms-python-0.1.0/CWMS/__pycache__/cwms_ts.cpython-39.pyc +0 -0
  33. cwms-python-0.1.0/CWMS/__pycache__/utils.cpython-39.pyc +0 -0
  34. cwms-python-0.1.0/CWMS/core.py +0 -21
  35. cwms-python-0.1.0/CWMS/cwms_loc.py +0 -58
  36. cwms-python-0.1.0/CWMS/cwms_ts.py +0 -182
  37. cwms-python-0.1.0/CWMS/utils.py +0 -79
  38. cwms-python-0.1.0/LICENSE +0 -24
  39. cwms-python-0.1.0/PKG-INFO +0 -72
  40. cwms-python-0.1.0/README.md +0 -49
  41. cwms-python-0.1.0/cwms_python.egg-info/PKG-INFO +0 -72
  42. cwms-python-0.1.0/cwms_python.egg-info/SOURCES.txt +0 -26
  43. cwms-python-0.1.0/cwms_python.egg-info/dependency_links.txt +0 -1
  44. cwms-python-0.1.0/cwms_python.egg-info/requires.txt +0 -10
  45. cwms-python-0.1.0/cwms_python.egg-info/top_level.txt +0 -1
  46. cwms-python-0.1.0/pyproject.toml +0 -48
  47. cwms-python-0.1.0/setup.cfg +0 -4
  48. cwms-python-0.1.0/setup.py +0 -24
  49. cwms-python-0.1.0/tests/__init__.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Hydrologic Engineering Center
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.1
2
+ Name: cwms-python
3
+ Version: 0.4.4
4
+ Summary: Corps water managerment systems (CWMS) REST API for Data Retrieval of USACE water data
5
+ License: LICENSE
6
+ Keywords: USACE,water data
7
+ Author: Eric Novotny
8
+ Author-email: eric.v.novotny@usace.army.mil
9
+ Requires-Python: >=3.9,<4.0
10
+ Classifier: License :: Other/Proprietary License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Dist: numpy (>=1.26.4,<2.0.0)
17
+ Requires-Dist: pandas (>=2.1.3,<3.0.0)
18
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
19
+ Requires-Dist: requests-toolbelt (>=1.0.0,<2.0.0)
20
+ Description-Content-Type: text/markdown
21
+
22
+ # CWMSpy
23
+
24
+ CWMS REST API for Data Retrieval
25
+
26
+ ## Requirements.
27
+
28
+ Python 3.9+
29
+
30
+ ## Installation & Usage
31
+
32
+ ### pip install
33
+
34
+ ```sh
35
+ pip install cwms-python
36
+ ```
37
+
38
+ Then import the package:
39
+
40
+ ```python
41
+ import cwms
42
+ ```
43
+
44
+ ## Getting Started
45
+
46
+ ```python
47
+ import cwms
48
+ from datetime import datetime, timedelta
49
+
50
+ end = datetime.now()
51
+ begin = end - timedelta(days = 10)
52
+ data = cwms.get_timeseries(ts_id_='Some.Fully.Qualified.Ts.Id',office_id='OFFICE1' , begin = begin, end = end)
53
+
54
+ #a cwms data object will be provided this object containes both the JSON as well
55
+ #as the values converted into a dataframe
56
+
57
+ #display the dataframe
58
+
59
+ df = data.df
60
+ print(df)
61
+ ```
62
+
63
+ ```
64
+ date-time value quality-code
65
+ 0 2024-04-23 08:15:00 86.57 3
66
+ 1 2024-04-23 08:30:00 86.57 3
67
+ 2 2024-04-23 08:45:00 86.58 3
68
+ 3 2024-04-23 09:00:00 86.58 3
69
+ 4 2024-04-23 09:15:00 86.58 3
70
+ 5 2024-04-23 09:30:00 86.58 3
71
+ 6 2024-04-23 09:45:00 86.59 3
72
+ 7 2024-04-23 10:00:00 86.58 3
73
+ ```
74
+
75
+ ```python
76
+ #display JSON
77
+ json = data.JSON
78
+ print(json)
79
+ ```
80
+
81
+ ```
82
+ {'name': 'Some.Fully.Qualified.Ts.Id',
83
+ 'office-id': 'MVP',
84
+ 'units': 'ft',
85
+ 'values': [['2024-04-23T08:15:00', 86.57, 3],
86
+ ['2024-04-23T08:30:00', 86.57, 3],
87
+ ['2024-04-23T08:45:00', 86.57999999999997, 3],
88
+ ['2024-04-23T09:00:00', 86.57999999999997, 3],
89
+ ['2024-04-23T09:15:00', 86.57999999999997, 3],
90
+ ['2024-04-23T09:30:00', 86.57999999999997, 3],
91
+ ['2024-04-23T09:45:00', 86.59, 3],
92
+ ['2024-04-23T10:00:00', 86.57999999999997, 3]],
93
+ 'version-date': None}
94
+ ```
95
+
@@ -0,0 +1,73 @@
1
+ # CWMSpy
2
+
3
+ CWMS REST API for Data Retrieval
4
+
5
+ ## Requirements.
6
+
7
+ Python 3.9+
8
+
9
+ ## Installation & Usage
10
+
11
+ ### pip install
12
+
13
+ ```sh
14
+ pip install cwms-python
15
+ ```
16
+
17
+ Then import the package:
18
+
19
+ ```python
20
+ import cwms
21
+ ```
22
+
23
+ ## Getting Started
24
+
25
+ ```python
26
+ import cwms
27
+ from datetime import datetime, timedelta
28
+
29
+ end = datetime.now()
30
+ begin = end - timedelta(days = 10)
31
+ data = cwms.get_timeseries(ts_id_='Some.Fully.Qualified.Ts.Id',office_id='OFFICE1' , begin = begin, end = end)
32
+
33
+ #a cwms data object will be provided this object containes both the JSON as well
34
+ #as the values converted into a dataframe
35
+
36
+ #display the dataframe
37
+
38
+ df = data.df
39
+ print(df)
40
+ ```
41
+
42
+ ```
43
+ date-time value quality-code
44
+ 0 2024-04-23 08:15:00 86.57 3
45
+ 1 2024-04-23 08:30:00 86.57 3
46
+ 2 2024-04-23 08:45:00 86.58 3
47
+ 3 2024-04-23 09:00:00 86.58 3
48
+ 4 2024-04-23 09:15:00 86.58 3
49
+ 5 2024-04-23 09:30:00 86.58 3
50
+ 6 2024-04-23 09:45:00 86.59 3
51
+ 7 2024-04-23 10:00:00 86.58 3
52
+ ```
53
+
54
+ ```python
55
+ #display JSON
56
+ json = data.JSON
57
+ print(json)
58
+ ```
59
+
60
+ ```
61
+ {'name': 'Some.Fully.Qualified.Ts.Id',
62
+ 'office-id': 'MVP',
63
+ 'units': 'ft',
64
+ 'values': [['2024-04-23T08:15:00', 86.57, 3],
65
+ ['2024-04-23T08:30:00', 86.57, 3],
66
+ ['2024-04-23T08:45:00', 86.57999999999997, 3],
67
+ ['2024-04-23T09:00:00', 86.57999999999997, 3],
68
+ ['2024-04-23T09:15:00', 86.57999999999997, 3],
69
+ ['2024-04-23T09:30:00', 86.57999999999997, 3],
70
+ ['2024-04-23T09:45:00', 86.59, 3],
71
+ ['2024-04-23T10:00:00', 86.57999999999997, 3]],
72
+ 'version-date': None}
73
+ ```
@@ -0,0 +1,22 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ from .api import *
4
+ from .catalog.catalog import *
5
+ from .forecast.forecast_instance import *
6
+ from .forecast.forecast_spec import *
7
+ from .levels.location_levels import *
8
+ from .levels.specified_levels import *
9
+ from .locations.physical_locations import *
10
+ from .ratings.ratings import *
11
+ from .ratings.ratings_spec import *
12
+ from .ratings.ratings_template import *
13
+ from .standard_text.standard_text import *
14
+ from .timeseries.timerseries_identifier import *
15
+ from .timeseries.timeseries import *
16
+ from .timeseries.timeseries_bin import *
17
+ from .timeseries.timeseries_txt import *
18
+
19
+ try:
20
+ __version__ = version("cwms-python")
21
+ except PackageNotFoundError:
22
+ __version__ = "version-unknown"
@@ -0,0 +1,336 @@
1
+ """ Session management and REST functions for CWMS Data API.
2
+
3
+ This module provides functions for making REST calls to the CWMS Data API (CDA). These
4
+ functions should be used internally to interact with the API. The user should not have to
5
+ interact with these directly.
6
+
7
+ The `init_session()` function can be used to specify an alternative root URL, and to
8
+ provide an authentication key (if required). If `init_session()` is not called, the
9
+ default root URL (see `API_ROOT` below) will be used, and no authentication keys will be
10
+ included when making API calls.
11
+
12
+ Example: Initializing a session
13
+
14
+ # Specify an alternate URL
15
+ init_session(api_root="https://example.com/cwms-data")
16
+
17
+ # Specify an alternate URL and an auth key
18
+ init_session(api_root="https://example.com/cwms-data", api_key="API_KEY")
19
+
20
+ Functions which make API calls that _may_ return a JSON response will return a `dict`
21
+ containing the deserialized data. If the API response does not include data, an empty
22
+ `dict` will be returned.
23
+
24
+ In the event the API returns an error response, the function will raise an `APIError`
25
+ which includes the response object and provides some hints to the user on how to address
26
+ the error.
27
+ """
28
+
29
+ import json
30
+ import logging
31
+ from json import JSONDecodeError
32
+ from typing import Any, Optional, cast
33
+
34
+ from requests import Response
35
+ from requests_toolbelt import sessions # type: ignore
36
+ from requests_toolbelt.sessions import BaseUrlSession # type: ignore
37
+
38
+ from cwms.types import JSON, RequestParams
39
+
40
+ # Specify the default API root URL and version.
41
+ API_ROOT = "https://cwms-data.usace.army.mil/cwms-data/"
42
+ API_VERSION = 2
43
+
44
+ # Initialize a non-authenticated session with the default root URL.
45
+ SESSION = sessions.BaseUrlSession(base_url=API_ROOT)
46
+
47
+
48
+ class InvalidVersion(Exception):
49
+ pass
50
+
51
+
52
+ class ApiError(Exception):
53
+ """CWMS Data Api Error.
54
+
55
+ This class is a light wrapper around a `requests.Response` object. Its primary purpose
56
+ is to generate an error message that includes the request URL and provide additional
57
+ information to the user to help them resolve the error.
58
+ """
59
+
60
+ def __init__(self, response: Response):
61
+ self.response = response
62
+
63
+ def __str__(self) -> str:
64
+ # Include the request URL in the error message.
65
+ message = f"CWMS API Error ({self.response.url})"
66
+
67
+ # If a reason is provided in the response, add it to the message.
68
+ if reason := self.response.reason:
69
+ message += f" {reason}"
70
+
71
+ message += "."
72
+
73
+ # Add additional context to help the user resolve the issue.
74
+ if hint := self.hint():
75
+ message += f" {hint}"
76
+
77
+ if content := self.response.content:
78
+ message += f" {content.decode('utf8')}"
79
+
80
+ return message
81
+
82
+ def hint(self) -> str:
83
+ """Return a message with additional information on how to resolve the error."""
84
+
85
+ if self.response.status_code == 400:
86
+ return "Check that your parameters are correct."
87
+ elif self.response.status_code == 404:
88
+ return "May be the result of an empty query."
89
+ else:
90
+ return ""
91
+
92
+
93
+ def init_session(
94
+ *, api_root: Optional[str] = None, api_key: Optional[str] = None
95
+ ) -> BaseUrlSession:
96
+ """Specify a root URL and authentication key for the CWMS Data API.
97
+
98
+ This function can be used to change the root URL used when interacting with the CDA.
99
+ All API calls made after this function is called will use the specified URL. If an
100
+ authentication key is given it will be included in all future request headers.
101
+
102
+ Keyword Args:
103
+ api_root (optional): The root URL for the CWMS Data API.
104
+ api_key (optional): An authentication key.
105
+
106
+ Returns:
107
+ Returns the updated session object.
108
+ """
109
+
110
+ global SESSION
111
+
112
+ if api_root:
113
+ logging.debug(f"Initializing root URL: api_root={api_root}")
114
+ SESSION = sessions.BaseUrlSession(base_url=api_root)
115
+
116
+ if api_key:
117
+ logging.debug(f"Setting authorization key: api_key={api_key}")
118
+ SESSION.headers.update({"Authorization": api_key})
119
+
120
+ return SESSION
121
+
122
+
123
+ def return_base_url() -> str:
124
+ """returns the base URL for the CDA instance that is connected to.
125
+
126
+ Returns:
127
+ str: base URL
128
+ """
129
+
130
+ return str(SESSION.base_url)
131
+
132
+
133
+ def api_version_text(api_version: int) -> str:
134
+ """Initialize CDA request headers.
135
+
136
+ The CDA supports multiple versions. To request a specific version, the version number
137
+ must be included in the request headers.
138
+
139
+ Args:
140
+ api_version: The CDA version to use for the request.
141
+
142
+ Returns:
143
+ A dict containing the request headers.
144
+
145
+ Raises:
146
+ InvalidVersion: If an unsupported API version is specified.
147
+ """
148
+
149
+ if api_version == 1:
150
+ version = "application/json"
151
+ elif api_version == 2:
152
+ version = "application/json;version=2"
153
+ elif api_version == 102:
154
+ version = "application/xml;version=2"
155
+ else:
156
+ raise InvalidVersion(f"API version {api_version} is not supported.")
157
+
158
+ return version
159
+
160
+
161
+ def get_xml(
162
+ endpoint: str,
163
+ params: Optional[RequestParams] = None,
164
+ *,
165
+ api_version: int = API_VERSION,
166
+ ) -> Any:
167
+ """Make a GET request to the CWMS Data API.
168
+
169
+ Args:
170
+ endpoint: The CDA endpoint for the record(s).
171
+ params (optional): Query parameters for the request.
172
+
173
+ Keyword Args:
174
+ api_version (optional): The CDA version to use for the request. If not specified,
175
+ the default API_VERSION will be used.
176
+
177
+ Returns:
178
+ The deserialized JSON response data.
179
+
180
+ Raises:
181
+ ApiError: If an error response is return by the API.
182
+ """
183
+
184
+ headers = {"Accept": api_version_text(api_version)}
185
+ response = SESSION.get(endpoint, params=params, headers=headers)
186
+
187
+ if response.status_code < 200 or response.status_code >= 300:
188
+ logging.error(f"CDA Error: response={response}")
189
+ raise ApiError(response)
190
+
191
+ try:
192
+ return response.content.decode("utf-8")
193
+ except JSONDecodeError as error:
194
+ logging.error(f"Error decoding CDA response as xml: {error}")
195
+ return {}
196
+
197
+
198
+ def get(
199
+ endpoint: str,
200
+ params: Optional[RequestParams] = None,
201
+ *,
202
+ api_version: int = API_VERSION,
203
+ ) -> JSON:
204
+ """Make a GET request to the CWMS Data API.
205
+
206
+ Args:
207
+ endpoint: The CDA endpoint for the record(s).
208
+ params (optional): Query parameters for the request.
209
+
210
+ Keyword Args:
211
+ api_version (optional): The CDA version to use for the request. If not specified,
212
+ the default API_VERSION will be used.
213
+
214
+ Returns:
215
+ The deserialized JSON response data.
216
+
217
+ Raises:
218
+ ApiError: If an error response is return by the API.
219
+ """
220
+
221
+ headers = {"Accept": api_version_text(api_version)}
222
+ response = SESSION.get(endpoint, params=params, headers=headers)
223
+
224
+ if response.status_code < 200 or response.status_code >= 300:
225
+ logging.error(f"CDA Error: response={response}")
226
+ raise ApiError(response)
227
+
228
+ try:
229
+ return cast(JSON, response.json())
230
+ except JSONDecodeError as error:
231
+ logging.error(f"Error decoding CDA response as json: {error}")
232
+ return {}
233
+
234
+
235
+ def post(
236
+ endpoint: str,
237
+ data: Any,
238
+ params: Optional[RequestParams] = None,
239
+ *,
240
+ api_version: int = API_VERSION,
241
+ ) -> None:
242
+ """Make a POST request to the CWMS Data API.
243
+
244
+ Args:
245
+ endpoint: The CDA endpoint for the record type.
246
+ data: A dict containing the new record data. Must be JSON-serializable.
247
+ params (optional): Query parameters for the request.
248
+
249
+ Keyword Args:
250
+ api_version (optional): The CDA version to use for the request. If not specified,
251
+ the default API_VERSION will be used.
252
+
253
+ Returns:
254
+ The deserialized JSON response data.
255
+
256
+ Raises:
257
+ ApiError: If an error response is return by the API.
258
+ """
259
+
260
+ # post requires different headers than get for
261
+ headers = {"accept": "*/*", "Content-Type": api_version_text(api_version)}
262
+
263
+ if isinstance(data, dict):
264
+ data = json.dumps(data)
265
+
266
+ response = SESSION.post(endpoint, params=params, headers=headers, data=data)
267
+
268
+ if response.status_code < 200 or response.status_code >= 300:
269
+ logging.error(f"CDA Error: response={response}")
270
+ raise ApiError(response)
271
+
272
+
273
+ def patch(
274
+ endpoint: str,
275
+ data: Optional[Any] = None,
276
+ params: Optional[RequestParams] = None,
277
+ *,
278
+ api_version: int = API_VERSION,
279
+ ) -> None:
280
+ """Make a PATCH request to the CWMS Data API.
281
+
282
+ Args:
283
+ endpoint: The CDA endpoint for the record.
284
+ data: A dict containing the updated record data. Must be JSON-serializable.
285
+ params (optional): Query parameters for the request.
286
+
287
+ Keyword Args:
288
+ api_version (optional): The CDA version to use for the request. If not specified,
289
+ the default API_VERSION will be used.
290
+
291
+ Returns:
292
+ The deserialized JSON response data.
293
+
294
+ Raises:
295
+ ApiError: If an error response is return by the API.
296
+ """
297
+
298
+ headers = {"accept": "*/*", "Content-Type": api_version_text(api_version)}
299
+ if data is None:
300
+ response = SESSION.patch(endpoint, params=params, headers=headers)
301
+ else:
302
+ if isinstance(data, dict):
303
+ data = json.dumps(data)
304
+ response = SESSION.patch(endpoint, params=params, headers=headers, data=data)
305
+
306
+ if response.status_code < 200 or response.status_code >= 300:
307
+ logging.error(f"CDA Error: response={response}")
308
+ raise ApiError(response)
309
+
310
+
311
+ def delete(
312
+ endpoint: str,
313
+ params: Optional[RequestParams] = None,
314
+ *,
315
+ api_version: int = API_VERSION,
316
+ ) -> None:
317
+ """Make a DELETE request to the CWMS Data API.
318
+
319
+ Args:
320
+ endpoint: The CDA endpoint for the record.
321
+ params (optional): Query parameters for the request.
322
+
323
+ Keyword Args:
324
+ api_version (optional): The CDA version to use for the request. If not specified,
325
+ the default API_VERSION will be used.
326
+
327
+ Raises:
328
+ ApiError: If an error response is return by the API.
329
+ """
330
+
331
+ headers = {"Accept": api_version_text(api_version)}
332
+ response = SESSION.delete(endpoint, params=params, headers=headers)
333
+
334
+ if response.status_code < 200 or response.status_code >= 300:
335
+ logging.error(f"CDA Error: response={response}")
336
+ raise ApiError(response)
@@ -0,0 +1,128 @@
1
+ from typing import Optional
2
+
3
+ import cwms.api as api
4
+ from cwms.types import Data
5
+
6
+
7
+ def get_locations_catalog(
8
+ office_id: str,
9
+ page: Optional[str] = None,
10
+ page_size: Optional[int] = 5000,
11
+ unit_system: Optional[str] = None,
12
+ like: Optional[str] = None,
13
+ location_category_like: Optional[str] = None,
14
+ location_group_like: Optional[str] = None,
15
+ bounding_office_like: Optional[str] = None,
16
+ location_kind_like: Optional[str] = None,
17
+ ) -> Data:
18
+ """Retrieves filters for a locations catalog
19
+
20
+ Parameters
21
+ ----------
22
+ page: string
23
+ The endpoint used to identify where the request is located.
24
+ page_size: integer
25
+ The entries per page returned. The default value is 5000.
26
+ unit_system: string
27
+ The unit system desired in response. Valid values for this
28
+ field are:
29
+ 1. SI
30
+ 2. EN
31
+ office_id: string
32
+ The owning office of the timeseries group.
33
+ like: string
34
+ The regex for matching against the id
35
+ location_category_like: string
36
+ The regex for matching against the location category id
37
+ location_group_like: string
38
+ The regex for matching against the location group id
39
+ bounding_office_like: string
40
+ The regex for matching against the location bounding office
41
+ location_kind_like: string
42
+ Posix regular expression matching against the location kind. The location-kind is typically unset or one of the following: {"SITE", "EMBANKMENT", "OVERFLOW", "TURBINE", "STREAM", "PROJECT", "STREAMGAGE", "BASIN", "OUTLET", "LOCK", "GATE"}. Multiple kinds can be matched by using Regular Expression OR clauses. For example: "(SITE|STREAM)"
43
+
44
+ Returns
45
+ -------
46
+ cwms data type
47
+ """
48
+
49
+ # CHECKS
50
+ if office_id is None:
51
+ raise ValueError("Retrieve locations catalog requires an office")
52
+
53
+ dataset = "LOCATIONS"
54
+ endpoint = f"catalog/{dataset}"
55
+ params = {
56
+ "page": page,
57
+ "page-size": page_size,
58
+ "units": unit_system,
59
+ "office": office_id,
60
+ "like": like,
61
+ "location-category-like": location_category_like,
62
+ "location-group-like": location_group_like,
63
+ "bounding-office-like": bounding_office_like,
64
+ "location-kind-like": location_kind_like,
65
+ }
66
+
67
+ response = api.get(endpoint=endpoint, params=params, api_version=2)
68
+ return Data(response, selector="entries")
69
+
70
+
71
+ def get_timeseries_catalog(
72
+ office_id: str,
73
+ page: Optional[str] = None,
74
+ page_size: Optional[int] = 5000,
75
+ unit_system: Optional[str] = None,
76
+ like: Optional[str] = None,
77
+ timeseries_category_like: Optional[str] = None,
78
+ timeseries_group_like: Optional[str] = "DMZ Include List",
79
+ bounding_office_like: Optional[str] = None,
80
+ ) -> Data:
81
+ """Retrieves filters for the timeseries catalog
82
+
83
+ Parameters
84
+ ----------
85
+ page: string
86
+ The endpoint used to identify where the request is located.
87
+ page_size: integer
88
+ The entries per page returned. The default value is 500.
89
+ unit_system: string
90
+ The unit system desired in response. Valid values for this
91
+ field are:
92
+ 1. SI
93
+ 2. EN
94
+ office_id: string
95
+ The owning office of the timeseries group.
96
+ like: string
97
+ The regex for matching against the id
98
+ timeseries_category_like: string
99
+ The regex for matching against the category id
100
+ timeseries_group_like: string
101
+ The regex for matching against the timeseries group id. This will default to pull only public datasets
102
+ bounding_office_like: string
103
+ The regex for matching against the location bounding office
104
+
105
+ Returns
106
+ -------
107
+ cwms data type
108
+ """
109
+
110
+ # CHECKS
111
+ if office_id is None:
112
+ raise ValueError("Retrieve timeseries catalog requires an office")
113
+
114
+ dataset = "TIMESERIES"
115
+ endpoint = f"catalog/{dataset}"
116
+ params = {
117
+ "page": page,
118
+ "page-size": page_size,
119
+ "unit-system": unit_system,
120
+ "office": office_id,
121
+ "like": like,
122
+ "timeseries-category-like": timeseries_category_like,
123
+ "timeseries-group-like": timeseries_group_like,
124
+ "bounding-office-like": bounding_office_like,
125
+ }
126
+
127
+ response = api.get(endpoint=endpoint, params=params, api_version=2)
128
+ return Data(response, selector="entries")