cwms-python 0.4.4__tar.gz → 0.5.0__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.
- {cwms_python-0.4.4 → cwms_python-0.5.0}/PKG-INFO +2 -2
- {cwms_python-0.4.4 → cwms_python-0.5.0}/README.md +1 -1
- cwms_python-0.5.0/cwms/__init__.py +27 -0
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/api.py +53 -6
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/catalog/catalog.py +1 -1
- cwms_python-0.4.4/cwms/types.py → cwms_python-0.5.0/cwms/cwms_types.py +31 -11
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/forecast/forecast_instance.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/forecast/forecast_spec.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/levels/location_levels.py +2 -2
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/levels/specified_levels.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/locations/physical_locations.py +29 -5
- cwms_python-0.5.0/cwms/outlets/outlets.py +195 -0
- cwms_python-0.5.0/cwms/outlets/virtual_outlets.py +164 -0
- cwms_python-0.5.0/cwms/projects/project_lock_rights.py +151 -0
- cwms_python-0.5.0/cwms/projects/project_locks.py +239 -0
- cwms_python-0.5.0/cwms/projects/projects.py +309 -0
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/ratings/ratings.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/ratings/ratings_spec.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/ratings/ratings_template.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/standard_text/standard_text.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/timeseries/timerseries_identifier.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/timeseries/timeseries.py +138 -14
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/timeseries/timeseries_bin.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/cwms/timeseries/timeseries_txt.py +1 -1
- {cwms_python-0.4.4 → cwms_python-0.5.0}/pyproject.toml +1 -1
- cwms_python-0.4.4/cwms/__init__.py +0 -22
- {cwms_python-0.4.4 → cwms_python-0.5.0}/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cwms-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Corps water managerment systems (CWMS) REST API for Data Retrieval of USACE water data
|
|
5
5
|
License: LICENSE
|
|
6
6
|
Keywords: USACE,water data
|
|
@@ -49,7 +49,7 @@ from datetime import datetime, timedelta
|
|
|
49
49
|
|
|
50
50
|
end = datetime.now()
|
|
51
51
|
begin = end - timedelta(days = 10)
|
|
52
|
-
data = cwms.get_timeseries(
|
|
52
|
+
data = cwms.get_timeseries(ts_id='Some.Fully.Qualified.Ts.Id',office_id='OFFICE1' , begin = begin, end = end)
|
|
53
53
|
|
|
54
54
|
#a cwms data object will be provided this object containes both the JSON as well
|
|
55
55
|
#as the values converted into a dataframe
|
|
@@ -28,7 +28,7 @@ from datetime import datetime, timedelta
|
|
|
28
28
|
|
|
29
29
|
end = datetime.now()
|
|
30
30
|
begin = end - timedelta(days = 10)
|
|
31
|
-
data = cwms.get_timeseries(
|
|
31
|
+
data = cwms.get_timeseries(ts_id='Some.Fully.Qualified.Ts.Id',office_id='OFFICE1' , begin = begin, end = end)
|
|
32
32
|
|
|
33
33
|
#a cwms data object will be provided this object containes both the JSON as well
|
|
34
34
|
#as the values converted into a dataframe
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
from cwms.api import *
|
|
4
|
+
from cwms.catalog.catalog import *
|
|
5
|
+
from cwms.forecast.forecast_instance import *
|
|
6
|
+
from cwms.forecast.forecast_spec import *
|
|
7
|
+
from cwms.levels.location_levels import *
|
|
8
|
+
from cwms.levels.specified_levels import *
|
|
9
|
+
from cwms.locations.physical_locations import *
|
|
10
|
+
from cwms.outlets.outlets import *
|
|
11
|
+
from cwms.outlets.virtual_outlets import *
|
|
12
|
+
from cwms.projects.project_lock_rights import *
|
|
13
|
+
from cwms.projects.project_locks import *
|
|
14
|
+
from cwms.projects.projects import *
|
|
15
|
+
from cwms.ratings.ratings import *
|
|
16
|
+
from cwms.ratings.ratings_spec import *
|
|
17
|
+
from cwms.ratings.ratings_template import *
|
|
18
|
+
from cwms.standard_text.standard_text import *
|
|
19
|
+
from cwms.timeseries.timerseries_identifier import *
|
|
20
|
+
from cwms.timeseries.timeseries import *
|
|
21
|
+
from cwms.timeseries.timeseries_bin import *
|
|
22
|
+
from cwms.timeseries.timeseries_txt import *
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
__version__ = version("cwms-python")
|
|
26
|
+
except PackageNotFoundError:
|
|
27
|
+
__version__ = "version-unknown"
|
|
@@ -31,18 +31,20 @@ import logging
|
|
|
31
31
|
from json import JSONDecodeError
|
|
32
32
|
from typing import Any, Optional, cast
|
|
33
33
|
|
|
34
|
-
from requests import Response
|
|
34
|
+
from requests import Response, adapters
|
|
35
35
|
from requests_toolbelt import sessions # type: ignore
|
|
36
36
|
from requests_toolbelt.sessions import BaseUrlSession # type: ignore
|
|
37
37
|
|
|
38
|
-
from cwms.
|
|
38
|
+
from cwms.cwms_types import JSON, RequestParams
|
|
39
39
|
|
|
40
40
|
# Specify the default API root URL and version.
|
|
41
41
|
API_ROOT = "https://cwms-data.usace.army.mil/cwms-data/"
|
|
42
42
|
API_VERSION = 2
|
|
43
43
|
|
|
44
|
-
# Initialize a non-authenticated session with the default root URL.
|
|
44
|
+
# Initialize a non-authenticated session with the default root URL and set default pool connections.
|
|
45
45
|
SESSION = sessions.BaseUrlSession(base_url=API_ROOT)
|
|
46
|
+
adapter = adapters.HTTPAdapter(pool_connections=100, pool_maxsize=100)
|
|
47
|
+
SESSION.mount("https://", adapter)
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
class InvalidVersion(Exception):
|
|
@@ -91,7 +93,10 @@ class ApiError(Exception):
|
|
|
91
93
|
|
|
92
94
|
|
|
93
95
|
def init_session(
|
|
94
|
-
*,
|
|
96
|
+
*,
|
|
97
|
+
api_root: Optional[str] = None,
|
|
98
|
+
api_key: Optional[str] = None,
|
|
99
|
+
pool_connections: int = 100,
|
|
95
100
|
) -> BaseUrlSession:
|
|
96
101
|
"""Specify a root URL and authentication key for the CWMS Data API.
|
|
97
102
|
|
|
@@ -112,7 +117,10 @@ def init_session(
|
|
|
112
117
|
if api_root:
|
|
113
118
|
logging.debug(f"Initializing root URL: api_root={api_root}")
|
|
114
119
|
SESSION = sessions.BaseUrlSession(base_url=api_root)
|
|
115
|
-
|
|
120
|
+
adapter = adapters.HTTPAdapter(
|
|
121
|
+
pool_connections=pool_connections, pool_maxsize=pool_connections
|
|
122
|
+
)
|
|
123
|
+
SESSION.mount("https://", adapter)
|
|
116
124
|
if api_key:
|
|
117
125
|
logging.debug(f"Setting authorization key: api_key={api_key}")
|
|
118
126
|
SESSION.headers.update({"Authorization": api_key})
|
|
@@ -220,7 +228,6 @@ def get(
|
|
|
220
228
|
|
|
221
229
|
headers = {"Accept": api_version_text(api_version)}
|
|
222
230
|
response = SESSION.get(endpoint, params=params, headers=headers)
|
|
223
|
-
|
|
224
231
|
if response.status_code < 200 or response.status_code >= 300:
|
|
225
232
|
logging.error(f"CDA Error: response={response}")
|
|
226
233
|
raise ApiError(response)
|
|
@@ -232,6 +239,46 @@ def get(
|
|
|
232
239
|
return {}
|
|
233
240
|
|
|
234
241
|
|
|
242
|
+
def get_with_paging(
|
|
243
|
+
selector: str,
|
|
244
|
+
endpoint: str,
|
|
245
|
+
params: RequestParams,
|
|
246
|
+
*,
|
|
247
|
+
api_version: int = API_VERSION,
|
|
248
|
+
) -> JSON:
|
|
249
|
+
"""Make a GET request to the CWMS Data API with paging.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
endpoint: The CDA endpoint for the record(s).
|
|
253
|
+
selector: The json key that will be merged though each page call
|
|
254
|
+
params (optional): Query parameters for the request.
|
|
255
|
+
|
|
256
|
+
Keyword Args:
|
|
257
|
+
api_version (optional): The CDA version to use for the request. If not specified,
|
|
258
|
+
the default API_VERSION will be used.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
The deserialized JSON response data.
|
|
262
|
+
|
|
263
|
+
Raises:
|
|
264
|
+
ApiError: If an error response is return by the API.
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
first_pass = True
|
|
268
|
+
while (params["page"] is not None) or first_pass:
|
|
269
|
+
temp = get(endpoint, params, api_version=api_version)
|
|
270
|
+
if first_pass:
|
|
271
|
+
response = temp
|
|
272
|
+
else:
|
|
273
|
+
response[selector] = response[selector] + temp[selector]
|
|
274
|
+
if "next-page" in temp.keys():
|
|
275
|
+
params["page"] = temp["next-page"]
|
|
276
|
+
else:
|
|
277
|
+
params["page"] = None
|
|
278
|
+
first_pass = False
|
|
279
|
+
return response
|
|
280
|
+
|
|
281
|
+
|
|
235
282
|
def post(
|
|
236
283
|
endpoint: str,
|
|
237
284
|
data: Any,
|
|
@@ -51,27 +51,47 @@ class Data:
|
|
|
51
51
|
A data frame containing the data located
|
|
52
52
|
"""
|
|
53
53
|
|
|
54
|
-
data
|
|
55
|
-
|
|
56
|
-
if selector:
|
|
54
|
+
def get_df_data(data: JSON, selector: str) -> JSON:
|
|
55
|
+
# get the data that will be stored in the dataframe using the selectors
|
|
57
56
|
df_data = data
|
|
58
57
|
for key in selector.split("."):
|
|
59
58
|
if key in df_data.keys():
|
|
60
59
|
df_data = df_data[key]
|
|
60
|
+
return df_data
|
|
61
|
+
|
|
62
|
+
def rating_type(data: JSON) -> DataFrame:
|
|
63
|
+
# grab the correct point values for a rating table
|
|
64
|
+
df = DataFrame(data["point"]) if data["point"] else DataFrame()
|
|
65
|
+
return df
|
|
66
|
+
|
|
67
|
+
def timeseries_type(orig_json: JSON, value_json: JSON) -> DataFrame:
|
|
68
|
+
# if timeseries values are present then grab the values and put into
|
|
69
|
+
# dataframe else create empty dataframe
|
|
70
|
+
columns = Index([sub["name"] for sub in orig_json["value-columns"]])
|
|
71
|
+
if value_json:
|
|
72
|
+
df = DataFrame(value_json)
|
|
73
|
+
df.columns = columns
|
|
74
|
+
else:
|
|
75
|
+
df = DataFrame(columns=columns)
|
|
76
|
+
|
|
77
|
+
if "date-time" in df.columns:
|
|
78
|
+
df["date-time"] = to_datetime(df["date-time"], unit="ms", utc=True)
|
|
79
|
+
return df
|
|
80
|
+
|
|
81
|
+
data = deepcopy(json)
|
|
82
|
+
|
|
83
|
+
if selector:
|
|
84
|
+
df_data = get_df_data(data, selector)
|
|
61
85
|
|
|
62
86
|
# if the dataframe is for a rating table
|
|
63
87
|
if ("rating-points" in selector) and ("point" in df_data.keys()):
|
|
64
|
-
df =
|
|
88
|
+
df = rating_type(df_data)
|
|
65
89
|
|
|
66
90
|
elif selector == "values":
|
|
67
|
-
df =
|
|
68
|
-
# if timeseries values are present then grab the values and put into dataframe
|
|
69
|
-
df.columns = Index([sub["name"] for sub in data["value-columns"]])
|
|
91
|
+
df = timeseries_type(data, df_data)
|
|
70
92
|
|
|
71
|
-
if "date-time" in df.columns:
|
|
72
|
-
df["date-time"] = to_datetime(df["date-time"], unit="ms", utc=True)
|
|
73
93
|
else:
|
|
74
|
-
df = json_normalize(df_data)
|
|
94
|
+
df = json_normalize(df_data) if df_data else DataFrame()
|
|
75
95
|
else:
|
|
76
96
|
df = json_normalize(data)
|
|
77
97
|
|
|
@@ -81,7 +101,7 @@ class Data:
|
|
|
81
101
|
def df(self) -> DataFrame:
|
|
82
102
|
"""Return the data frame."""
|
|
83
103
|
|
|
84
|
-
if
|
|
104
|
+
if not isinstance(self._df, DataFrame):
|
|
85
105
|
self._df = Data.to_df(self.json, self.selector)
|
|
86
106
|
|
|
87
107
|
return self._df
|
|
@@ -9,7 +9,7 @@ from typing import Optional
|
|
|
9
9
|
import pandas as pd
|
|
10
10
|
|
|
11
11
|
import cwms.api as api
|
|
12
|
-
from cwms.
|
|
12
|
+
from cwms.cwms_types import JSON, Data
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def get_location_levels(
|
|
@@ -218,4 +218,4 @@ def get_level_as_timeseries(
|
|
|
218
218
|
"unit": unit,
|
|
219
219
|
}
|
|
220
220
|
response = api.get(endpoint, params)
|
|
221
|
-
return Data(response)
|
|
221
|
+
return Data(response, selector="values")
|
|
@@ -4,7 +4,7 @@ import pandas as pd
|
|
|
4
4
|
from pandas import DataFrame
|
|
5
5
|
|
|
6
6
|
import cwms.api as api
|
|
7
|
-
from cwms.
|
|
7
|
+
from cwms.cwms_types import JSON, Data
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def get_location_group(loc_group_id: str, category_id: str, office_id: str) -> Data:
|
|
@@ -46,20 +46,44 @@ def get_location(location_id: str, office_id: str, unit: str = "EN") -> Data:
|
|
|
46
46
|
|
|
47
47
|
def get_locations(
|
|
48
48
|
office_id: Optional[str] = None,
|
|
49
|
-
|
|
50
|
-
units: Optional[str] =
|
|
49
|
+
location_ids: Optional[str] = None,
|
|
50
|
+
units: Optional[str] = "EN",
|
|
51
51
|
datum: Optional[str] = None,
|
|
52
52
|
) -> Data:
|
|
53
|
+
"""
|
|
54
|
+
Get location data for a single location
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
location_id: str
|
|
59
|
+
Specifies the name(s) of the location(s) whose data is to be included in the response. This parameter is a Posix regular expression matching against the id
|
|
60
|
+
office_id : str
|
|
61
|
+
The ID of the office that the locations belongs to.
|
|
62
|
+
unit: string, optional, default is EN
|
|
63
|
+
The unit or unit system of the response. Defaults to EN. Valid values
|
|
64
|
+
for the unit field are:
|
|
65
|
+
1. EN. English unit system.
|
|
66
|
+
2. SI. SI unit system.
|
|
67
|
+
3. Other.
|
|
68
|
+
Datum: string, optional, default is None
|
|
69
|
+
Specifies the elevation datum of the response. This field affects only vertical datum. Valid values for this field are:
|
|
70
|
+
1.) NAVD88 The elevation values will in the specified or default units above the NAVD-88 datum.
|
|
71
|
+
2.) NGVD29 The elevation values will be in the specified or default units above the NGVD-29 datum.
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
cwms data type. data.json will return the JSON output and data.df will return a dataframe
|
|
75
|
+
|
|
76
|
+
"""
|
|
53
77
|
endpoint = "locations"
|
|
54
78
|
params = {
|
|
55
79
|
"office": office_id,
|
|
56
|
-
"names":
|
|
80
|
+
"names": location_ids,
|
|
57
81
|
"units": units,
|
|
58
82
|
"datum": datum,
|
|
59
83
|
}
|
|
60
84
|
|
|
61
85
|
response = api.get(endpoint, params)
|
|
62
|
-
return Data(response
|
|
86
|
+
return Data(response)
|
|
63
87
|
|
|
64
88
|
|
|
65
89
|
def ExpandLocations(df: DataFrame) -> DataFrame:
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Copyright (c) 2024
|
|
2
|
+
# United States Army Corps of Engineers - Hydrologic Engineering Center (USACE/HEC)
|
|
3
|
+
# All Rights Reserved. USACE PROPRIETARY/CONFIDENTIAL.
|
|
4
|
+
# Source may not be released without written approval from HEC
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
import cwms.api as api
|
|
8
|
+
from cwms.cwms_types import JSON, Data, DeleteMethod
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_outlet(office_id: str, name: str) -> Data:
|
|
12
|
+
"""
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
name : str
|
|
16
|
+
The ID of the outlet.
|
|
17
|
+
office_id : str
|
|
18
|
+
The ID of the office.
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
response : dict
|
|
23
|
+
the JSON response from CWMS Data API.
|
|
24
|
+
|
|
25
|
+
Raises
|
|
26
|
+
------
|
|
27
|
+
ValueError
|
|
28
|
+
If any of name or office_id is None.
|
|
29
|
+
ClientError
|
|
30
|
+
If a 400 range error code response is returned from the server.
|
|
31
|
+
NoDataFoundError
|
|
32
|
+
If a 404 range error code response is returned from the server.
|
|
33
|
+
ServerError
|
|
34
|
+
If a 500 range error code response is returned from the server.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
if name is None:
|
|
38
|
+
raise ValueError("Retrieve outlet requires a name")
|
|
39
|
+
if office_id is None:
|
|
40
|
+
raise ValueError("Retrieve outlet requires an office")
|
|
41
|
+
|
|
42
|
+
endpoint = f"projects/outlets/{name}"
|
|
43
|
+
params = {"office": office_id}
|
|
44
|
+
response = api.get(endpoint, params)
|
|
45
|
+
return Data(response)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_outlets(office_id: str, project_id: str) -> Data:
|
|
49
|
+
"""
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
project_id : str
|
|
53
|
+
The project ID of the outlets.
|
|
54
|
+
office_id : str
|
|
55
|
+
The ID of the project's office.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
response : dict
|
|
60
|
+
the JSON response from CWMS Data API.
|
|
61
|
+
|
|
62
|
+
Raises
|
|
63
|
+
------
|
|
64
|
+
ValueError
|
|
65
|
+
If any of project_id or office_id is None.
|
|
66
|
+
ClientError
|
|
67
|
+
If a 400 range error code response is returned from the server.
|
|
68
|
+
NoDataFoundError
|
|
69
|
+
If a 404 range error code response is returned from the server.
|
|
70
|
+
ServerError
|
|
71
|
+
If a 500 range error code response is returned from the server.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
if project_id is None:
|
|
75
|
+
raise ValueError("Retrieve outlets requires a project id")
|
|
76
|
+
if office_id is None:
|
|
77
|
+
raise ValueError("Retrieve outlets requires an office")
|
|
78
|
+
|
|
79
|
+
endpoint = "projects/outlets"
|
|
80
|
+
params = {"office": office_id, "project-id": project_id}
|
|
81
|
+
response = api.get(endpoint, params)
|
|
82
|
+
return Data(response)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def delete_outlet(office_id: str, name: str, delete_method: DeleteMethod) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
name : str
|
|
90
|
+
The name of the outlets.
|
|
91
|
+
office_id : str
|
|
92
|
+
The ID of the project's office.
|
|
93
|
+
delete_method: DeleteMethod
|
|
94
|
+
The method to use to delete the outlet.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
None
|
|
99
|
+
|
|
100
|
+
Raises
|
|
101
|
+
------
|
|
102
|
+
ValueError
|
|
103
|
+
If any of name, delete_method, or office_id is None.
|
|
104
|
+
ClientError
|
|
105
|
+
If a 400 range error code response is returned from the server.
|
|
106
|
+
NoDataFoundError
|
|
107
|
+
If a 404 range error code response is returned from the server.
|
|
108
|
+
ServerError
|
|
109
|
+
If a 500 range error code response is returned from the server.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
if name is None:
|
|
113
|
+
raise ValueError("Delete outlet requires an outlet name")
|
|
114
|
+
if office_id is None:
|
|
115
|
+
raise ValueError("Delete outlet requires an office")
|
|
116
|
+
if delete_method is None:
|
|
117
|
+
raise ValueError("Delete outlet requires a delete method")
|
|
118
|
+
|
|
119
|
+
endpoint = f"projects/outlets/{name}"
|
|
120
|
+
params = {"office": office_id, "method": delete_method.name}
|
|
121
|
+
api.delete(endpoint, params)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def rename_outlet(office_id: str, old_name: str, new_name: str) -> None:
|
|
125
|
+
"""
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
old_name : str
|
|
129
|
+
The name of the outlet to rename.
|
|
130
|
+
new_name : str
|
|
131
|
+
The new name of the outlet.
|
|
132
|
+
office_id : str
|
|
133
|
+
The ID of the project's office.
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
None
|
|
138
|
+
|
|
139
|
+
Raises
|
|
140
|
+
------
|
|
141
|
+
ValueError
|
|
142
|
+
If any of old_outlet_name, new_outlet_name, or office_id is None.
|
|
143
|
+
ClientError
|
|
144
|
+
If a 400 range error code response is returned from the server.
|
|
145
|
+
NoDataFoundError
|
|
146
|
+
If a 404 range error code response is returned from the server.
|
|
147
|
+
ServerError
|
|
148
|
+
If a 500 range error code response is returned from the server.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
if old_name is None:
|
|
152
|
+
raise ValueError("Rename outlet requires the original outlet name")
|
|
153
|
+
if new_name is None:
|
|
154
|
+
raise ValueError("Rename outlet requires a new outlet name")
|
|
155
|
+
if office_id is None:
|
|
156
|
+
raise ValueError("Rename outlet requires an office")
|
|
157
|
+
|
|
158
|
+
endpoint = f"projects/outlets/{old_name}"
|
|
159
|
+
params = {"office": office_id, "name": new_name}
|
|
160
|
+
api.patch(endpoint=endpoint, params=params)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def store_outlet(data: JSON, fail_if_exists: Optional[bool] = True) -> None:
|
|
164
|
+
"""
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
data : dict
|
|
168
|
+
A dictionary representing the JSON data to be stored.
|
|
169
|
+
If the `data` value is None, a `ValueError` will be raised.
|
|
170
|
+
fail_if_exists : str, optional
|
|
171
|
+
A boolean value indicating whether to fail if the outlet already exists.
|
|
172
|
+
Default is True.
|
|
173
|
+
|
|
174
|
+
Returns
|
|
175
|
+
-------
|
|
176
|
+
None
|
|
177
|
+
|
|
178
|
+
Raises
|
|
179
|
+
------
|
|
180
|
+
ValueError
|
|
181
|
+
If any of data is None.
|
|
182
|
+
ClientError
|
|
183
|
+
If a 400 range error code response is returned from the server.
|
|
184
|
+
NoDataFoundError
|
|
185
|
+
If a 404 range error code response is returned from the server.
|
|
186
|
+
ServerError
|
|
187
|
+
If a 500 range error code response is returned from the server.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
if data is None:
|
|
191
|
+
raise ValueError("Cannot store an outlet without a JSON data dictionary")
|
|
192
|
+
|
|
193
|
+
endpoint = "projects/outlets"
|
|
194
|
+
params = {"fail-if-exists": fail_if_exists}
|
|
195
|
+
api.post(endpoint, data, params)
|