hydroserverpy 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl
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.
Potentially problematic release.
This version of hydroserverpy might be problematic. Click here for more details.
- hydroserverpy/__init__.py +1 -1
- hydroserverpy/api/{main.py → client.py} +52 -22
- hydroserverpy/api/models/__init__.py +1 -2
- hydroserverpy/api/models/base.py +180 -47
- hydroserverpy/api/models/etl/data_archive.py +31 -59
- hydroserverpy/api/models/etl/data_source.py +34 -76
- hydroserverpy/api/models/etl/orchestration_system.py +23 -38
- hydroserverpy/api/models/iam/apikey.py +57 -38
- hydroserverpy/api/models/iam/collaborator.py +55 -19
- hydroserverpy/api/models/iam/role.py +32 -4
- hydroserverpy/api/models/iam/workspace.py +58 -86
- hydroserverpy/api/models/sta/datastream.py +122 -214
- hydroserverpy/api/models/sta/observation.py +101 -0
- hydroserverpy/api/models/sta/observed_property.py +18 -53
- hydroserverpy/api/models/sta/processing_level.py +16 -31
- hydroserverpy/api/models/sta/result_qualifier.py +16 -31
- hydroserverpy/api/models/sta/sensor.py +27 -88
- hydroserverpy/api/models/sta/thing.py +48 -152
- hydroserverpy/api/models/sta/unit.py +16 -29
- hydroserverpy/api/services/__init__.py +1 -0
- hydroserverpy/api/services/base.py +92 -76
- hydroserverpy/api/services/etl/data_archive.py +42 -72
- hydroserverpy/api/services/etl/data_source.py +42 -72
- hydroserverpy/api/services/etl/orchestration_system.py +25 -33
- hydroserverpy/api/services/iam/role.py +38 -0
- hydroserverpy/api/services/iam/workspace.py +96 -99
- hydroserverpy/api/services/sta/datastream.py +150 -211
- hydroserverpy/api/services/sta/observed_property.py +31 -49
- hydroserverpy/api/services/sta/processing_level.py +30 -36
- hydroserverpy/api/services/sta/result_qualifier.py +24 -34
- hydroserverpy/api/services/sta/sensor.py +34 -48
- hydroserverpy/api/services/sta/thing.py +96 -89
- hydroserverpy/api/services/sta/unit.py +30 -34
- hydroserverpy/api/utils.py +22 -0
- hydroserverpy/etl/extractors/base.py +3 -5
- hydroserverpy/etl/loaders/hydroserver_loader.py +1 -0
- hydroserverpy/etl/timestamp_parser.py +82 -48
- hydroserverpy/etl/transformers/base.py +6 -10
- hydroserverpy/etl_csv/hydroserver_etl_csv.py +18 -24
- {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/METADATA +1 -1
- hydroserverpy-1.3.0.dist-info/RECORD +70 -0
- hydroserverpy/api/http.py +0 -22
- hydroserverpy-1.2.0.dist-info/RECORD +0 -68
- {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/WHEEL +0 -0
- {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/top_level.txt +0 -0
- {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/zip-safe +0 -0
hydroserverpy/__init__.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import requests
|
|
2
|
+
import json
|
|
2
3
|
from typing import Optional, Tuple
|
|
3
|
-
from hydroserverpy.api.http import raise_for_hs_status
|
|
4
4
|
from hydroserverpy.api.services import (
|
|
5
5
|
WorkspaceService,
|
|
6
|
+
RoleService,
|
|
6
7
|
ThingService,
|
|
7
8
|
ObservedPropertyService,
|
|
8
9
|
UnitService,
|
|
@@ -20,11 +21,14 @@ class HydroServer:
|
|
|
20
21
|
def __init__(
|
|
21
22
|
self,
|
|
22
23
|
host: str,
|
|
24
|
+
auth_route: str = "/api/auth",
|
|
25
|
+
base_route: str = "/api/data",
|
|
23
26
|
email: Optional[str] = None,
|
|
24
27
|
password: Optional[str] = None,
|
|
25
28
|
apikey: Optional[str] = None,
|
|
26
29
|
):
|
|
27
30
|
self.host = host.strip("/")
|
|
31
|
+
self.base_route = base_route
|
|
28
32
|
self.auth = (
|
|
29
33
|
(
|
|
30
34
|
email or "__key__",
|
|
@@ -34,7 +38,7 @@ class HydroServer:
|
|
|
34
38
|
else None
|
|
35
39
|
)
|
|
36
40
|
|
|
37
|
-
self._auth_url = f"{self.host}/
|
|
41
|
+
self._auth_url = f"{self.host}{auth_route}/app/session"
|
|
38
42
|
|
|
39
43
|
self._session = None
|
|
40
44
|
self._timeout = 60
|
|
@@ -52,6 +56,30 @@ class HydroServer:
|
|
|
52
56
|
|
|
53
57
|
self._session.delete(self._auth_url, timeout=self._timeout)
|
|
54
58
|
|
|
59
|
+
def request(self, method, path, *args, **kwargs) -> requests.Response:
|
|
60
|
+
"""Sends a request to HydroServer's API."""
|
|
61
|
+
|
|
62
|
+
for attempt in range(2):
|
|
63
|
+
try:
|
|
64
|
+
response = getattr(self._session, method)(
|
|
65
|
+
f"{self.host}/{path.strip('/')}",
|
|
66
|
+
timeout=self._timeout,
|
|
67
|
+
*args,
|
|
68
|
+
**kwargs,
|
|
69
|
+
)
|
|
70
|
+
self._raise_for_hs_status(response)
|
|
71
|
+
except (
|
|
72
|
+
requests.exceptions.HTTPError,
|
|
73
|
+
requests.exceptions.ConnectionError,
|
|
74
|
+
) as e:
|
|
75
|
+
if attempt == 0:
|
|
76
|
+
self._init_session()
|
|
77
|
+
continue
|
|
78
|
+
else:
|
|
79
|
+
raise e
|
|
80
|
+
|
|
81
|
+
return response
|
|
82
|
+
|
|
55
83
|
def _init_session(self, auth: Optional[Tuple[str, str]] = None) -> None:
|
|
56
84
|
if self._session is not None:
|
|
57
85
|
self.logout()
|
|
@@ -82,29 +110,25 @@ class HydroServer:
|
|
|
82
110
|
|
|
83
111
|
return session_token
|
|
84
112
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
113
|
+
@staticmethod
|
|
114
|
+
def _raise_for_hs_status(response):
|
|
115
|
+
try:
|
|
116
|
+
response.raise_for_status()
|
|
117
|
+
except requests.HTTPError as e:
|
|
89
118
|
try:
|
|
90
|
-
|
|
91
|
-
f"{
|
|
92
|
-
|
|
93
|
-
*args,
|
|
94
|
-
**kwargs,
|
|
119
|
+
http_error_msg = (
|
|
120
|
+
f"{response.status_code} Client Error: "
|
|
121
|
+
f"{str(json.loads(response.content).get('detail'))}"
|
|
95
122
|
)
|
|
96
|
-
raise_for_hs_status(response)
|
|
97
123
|
except (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return response
|
|
124
|
+
ValueError,
|
|
125
|
+
TypeError,
|
|
126
|
+
):
|
|
127
|
+
http_error_msg = e
|
|
128
|
+
if 400 <= response.status_code < 500:
|
|
129
|
+
raise requests.HTTPError(http_error_msg, response=response)
|
|
130
|
+
else:
|
|
131
|
+
raise requests.HTTPError(str(e), response=response)
|
|
108
132
|
|
|
109
133
|
@property
|
|
110
134
|
def workspaces(self):
|
|
@@ -112,6 +136,12 @@ class HydroServer:
|
|
|
112
136
|
|
|
113
137
|
return WorkspaceService(self)
|
|
114
138
|
|
|
139
|
+
@property
|
|
140
|
+
def roles(self):
|
|
141
|
+
"""Utilities for managing HydroServer workspaces."""
|
|
142
|
+
|
|
143
|
+
return RoleService(self)
|
|
144
|
+
|
|
115
145
|
@property
|
|
116
146
|
def things(self):
|
|
117
147
|
"""Utilities for managing HydroServer things."""
|
|
@@ -5,6 +5,7 @@ from .iam.collaborator import Collaborator
|
|
|
5
5
|
from .iam.apikey import APIKey
|
|
6
6
|
from .iam.account import Account
|
|
7
7
|
from .sta.datastream import Datastream
|
|
8
|
+
from .sta.observation import ObservationCollection
|
|
8
9
|
from .sta.observed_property import ObservedProperty
|
|
9
10
|
from .sta.processing_level import ProcessingLevel
|
|
10
11
|
from .sta.result_qualifier import ResultQualifier
|
|
@@ -19,5 +20,3 @@ Workspace.model_rebuild()
|
|
|
19
20
|
Role.model_rebuild()
|
|
20
21
|
Collaborator.model_rebuild()
|
|
21
22
|
APIKey.model_rebuild()
|
|
22
|
-
|
|
23
|
-
Unit.model_rebuild()
|
hydroserverpy/api/models/base.py
CHANGED
|
@@ -1,22 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
3
|
-
from
|
|
1
|
+
import uuid
|
|
2
|
+
from typing import Type, List, Dict, Any, Optional, ClassVar, TYPE_CHECKING
|
|
3
|
+
from requests import Response
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, PrivateAttr, Field
|
|
4
6
|
from pydantic.alias_generators import to_camel
|
|
5
7
|
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from hydroserverpy import HydroServer
|
|
10
|
+
from hydroserverpy.api.services.base import HydroServerBaseService
|
|
11
|
+
|
|
6
12
|
|
|
7
13
|
class HydroServerBaseModel(BaseModel):
|
|
8
|
-
|
|
14
|
+
uid: Optional[uuid.UUID] = Field(..., alias="id")
|
|
15
|
+
|
|
16
|
+
_client: "HydroServer" = PrivateAttr()
|
|
17
|
+
_service: "HydroServerBaseService" = PrivateAttr()
|
|
18
|
+
_server_data: Dict[str, Any] = PrivateAttr()
|
|
19
|
+
_editable_fields: ClassVar[set[str]] = set()
|
|
9
20
|
|
|
10
|
-
def __init__(self,
|
|
21
|
+
def __init__(self, *, client: "HydroServer", service: Optional["HydroServerBaseService"] = None, **data):
|
|
11
22
|
super().__init__(**data)
|
|
12
|
-
self._uid = _uid
|
|
13
23
|
|
|
14
|
-
|
|
24
|
+
self._client = client
|
|
25
|
+
self._service = service
|
|
26
|
+
self._server_data = self.dict(by_alias=False).copy()
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def get_route(cls):
|
|
30
|
+
raise NotImplementedError("Route not defined")
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def client(self) -> "HydroServer":
|
|
34
|
+
return self._client
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def service(self) -> "HydroServerBaseService":
|
|
38
|
+
return self._service
|
|
39
|
+
|
|
15
40
|
@property
|
|
16
|
-
def
|
|
17
|
-
|
|
41
|
+
def unsaved_changes(self) -> dict:
|
|
42
|
+
return {
|
|
43
|
+
k: v for k, v in self.__dict__.items()
|
|
44
|
+
if k in self._editable_fields and k in self._server_data and v != self._server_data[k]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
def save(self):
|
|
48
|
+
"""Saves changes to this resource to HydroServer."""
|
|
49
|
+
|
|
50
|
+
if not self.service:
|
|
51
|
+
raise NotImplementedError("Saving not enabled for this object.")
|
|
52
|
+
|
|
53
|
+
if not self.uid:
|
|
54
|
+
raise AttributeError("Data cannot be saved: UID is not set.")
|
|
55
|
+
|
|
56
|
+
if self.unsaved_changes:
|
|
57
|
+
saved_resource = self.service.update(
|
|
58
|
+
self.uid, **self.unsaved_changes
|
|
59
|
+
)
|
|
60
|
+
self._server_data = saved_resource.dict(by_alias=False).copy()
|
|
61
|
+
self.__dict__.update(saved_resource.__dict__)
|
|
62
|
+
|
|
63
|
+
def refresh(self):
|
|
64
|
+
"""Refreshes this resource from HydroServer."""
|
|
18
65
|
|
|
19
|
-
|
|
66
|
+
if not self.service:
|
|
67
|
+
raise NotImplementedError("Refreshing not enabled for this object.")
|
|
68
|
+
|
|
69
|
+
if self.uid is None:
|
|
70
|
+
raise ValueError("Cannot refresh data without a valid ID.")
|
|
71
|
+
|
|
72
|
+
refreshed_resource = self.service.get(self.uid)
|
|
73
|
+
self._server_data = refreshed_resource.dict(by_alias=False).copy()
|
|
74
|
+
self.__dict__.update(refreshed_resource.__dict__)
|
|
75
|
+
|
|
76
|
+
def delete(self):
|
|
77
|
+
"""Deletes this resource from HydroServer."""
|
|
78
|
+
|
|
79
|
+
if not self.service:
|
|
80
|
+
raise NotImplementedError("Deleting not enabled for this object.")
|
|
81
|
+
|
|
82
|
+
if self.uid is None:
|
|
83
|
+
raise AttributeError("Cannot delete data without a valid ID.")
|
|
84
|
+
|
|
85
|
+
self.service.delete(self.uid)
|
|
86
|
+
self.uid = None
|
|
20
87
|
|
|
21
88
|
model_config = ConfigDict(
|
|
22
89
|
validate_assignment=True,
|
|
@@ -26,49 +93,115 @@ class HydroServerBaseModel(BaseModel):
|
|
|
26
93
|
)
|
|
27
94
|
|
|
28
95
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
96
|
+
@dataclass
|
|
97
|
+
class HydroServerCollection:
|
|
98
|
+
items: List["HydroServerBaseModel"]
|
|
99
|
+
filters: Optional[dict[str, Any]] = None
|
|
100
|
+
order_by: Optional[List[str]] = None
|
|
101
|
+
page: Optional[int] = None
|
|
102
|
+
page_size: Optional[int] = None
|
|
103
|
+
total_pages: Optional[int] = None
|
|
104
|
+
total_count: Optional[int] = None
|
|
105
|
+
|
|
106
|
+
_service: Optional["HydroServerBaseService"] = field(init=False, repr=False)
|
|
107
|
+
|
|
108
|
+
def __init__(
|
|
109
|
+
self,
|
|
110
|
+
model: Type["HydroServerBaseModel"],
|
|
111
|
+
client: "HydroServer",
|
|
112
|
+
service: Optional["HydroServerBaseService"] = None,
|
|
113
|
+
response: Optional[Response] = None,
|
|
114
|
+
**data
|
|
115
|
+
):
|
|
116
|
+
self._service = service
|
|
117
|
+
|
|
118
|
+
self.filters = data.get("filters")
|
|
119
|
+
self.order_by = data.get("order_by")
|
|
120
|
+
self.page = data.get("page") or (int(response.headers.get("X-Page")) if response else None)
|
|
121
|
+
self.page_size = data.get("page_size") or (int(response.headers.get("X-Page-Size")) if response else None)
|
|
122
|
+
self.total_pages = data.get("total_pages") or (int(response.headers.get("X-Total-Pages")) if response else None)
|
|
123
|
+
self.total_count = data.get("total_count") or (int(response.headers.get("X-Total-Count")) if response else None)
|
|
124
|
+
|
|
125
|
+
if "items" in data:
|
|
126
|
+
self.items = data["items"]
|
|
127
|
+
elif response is not None:
|
|
128
|
+
self.items = [model(client=client, **entity) for entity in response.json()]
|
|
129
|
+
else:
|
|
130
|
+
self.items = []
|
|
32
131
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
132
|
+
@property
|
|
133
|
+
def service(self) -> "HydroServerBaseService":
|
|
134
|
+
return self._service
|
|
36
135
|
|
|
37
|
-
|
|
136
|
+
def next_page(self):
|
|
137
|
+
"""Fetches the next page of data from HydroServer."""
|
|
38
138
|
|
|
39
|
-
self.
|
|
40
|
-
|
|
41
|
-
self._original_data = self.dict(by_alias=False).copy()
|
|
139
|
+
if not self._service:
|
|
140
|
+
raise NotImplementedError("Pagination not enabled for this collection.")
|
|
42
141
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
142
|
+
return self._service.list(
|
|
143
|
+
**(self.filters or {}),
|
|
144
|
+
page=(self.page or 0) + 1,
|
|
145
|
+
page_size=self.page_size or 100,
|
|
146
|
+
order_by=self.order_by or ...
|
|
147
|
+
)
|
|
50
148
|
|
|
51
|
-
def
|
|
52
|
-
"""
|
|
149
|
+
def previous_page(self):
|
|
150
|
+
"""Fetches the previous page of data from HydroServer."""
|
|
53
151
|
|
|
54
|
-
self.
|
|
55
|
-
|
|
56
|
-
.get(uid=self.uid)
|
|
57
|
-
.model_dump(exclude=["uid"])
|
|
58
|
-
)
|
|
59
|
-
self.__dict__.update(self._original_data)
|
|
152
|
+
if not self._service:
|
|
153
|
+
raise NotImplementedError("Pagination not enabled for this collection.")
|
|
60
154
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
entity = getattr(self._connection, self._model_ref).update(
|
|
64
|
-
uid=self.uid, **self._patch_data
|
|
65
|
-
)
|
|
66
|
-
self._original_data = entity.dict(by_alias=False, exclude=["uid"])
|
|
67
|
-
self.__dict__.update(self._original_data)
|
|
155
|
+
if not self.page or self.page <= 1:
|
|
156
|
+
return None
|
|
68
157
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
158
|
+
return self._service.list(
|
|
159
|
+
**(self.filters or {}),
|
|
160
|
+
page=self.page - 1,
|
|
161
|
+
page_size=self.page_size or 100,
|
|
162
|
+
order_by=self.order_by or ...
|
|
163
|
+
)
|
|
72
164
|
|
|
73
|
-
|
|
74
|
-
|
|
165
|
+
def fetch_all(self) -> "HydroServerCollection":
|
|
166
|
+
"""Fetches all pages of data from HydroServer for this collection."""
|
|
167
|
+
|
|
168
|
+
if not self._service:
|
|
169
|
+
raise NotImplementedError("Pagination not enabled for this collection.")
|
|
170
|
+
|
|
171
|
+
all_items = []
|
|
172
|
+
current_page = self.page or 1
|
|
173
|
+
page_size = self.page_size or 100
|
|
174
|
+
total_pages = self.total_pages
|
|
175
|
+
|
|
176
|
+
page_num = 1
|
|
177
|
+
while total_pages is None or page_num <= total_pages:
|
|
178
|
+
if page_num == current_page:
|
|
179
|
+
all_items.extend(self.items)
|
|
180
|
+
else:
|
|
181
|
+
page = self._service.list(
|
|
182
|
+
**(self.filters or {}),
|
|
183
|
+
page=page_num,
|
|
184
|
+
page_size=page_size,
|
|
185
|
+
order_by=self.order_by or ...
|
|
186
|
+
)
|
|
187
|
+
if not page.items:
|
|
188
|
+
break
|
|
189
|
+
all_items.extend(page.items)
|
|
190
|
+
|
|
191
|
+
if page.total_pages is not None:
|
|
192
|
+
total_pages = page.total_pages
|
|
193
|
+
|
|
194
|
+
page_num += 1
|
|
195
|
+
|
|
196
|
+
return self.__class__(
|
|
197
|
+
model=type(self.items[0]) if self.items else None,
|
|
198
|
+
client=self.items[0].client if self.items else None,
|
|
199
|
+
service=self._service,
|
|
200
|
+
items=all_items,
|
|
201
|
+
filters=self.filters,
|
|
202
|
+
order_by=self.order_by,
|
|
203
|
+
page=1,
|
|
204
|
+
page_size=len(all_items),
|
|
205
|
+
total_pages=1,
|
|
206
|
+
total_count=len(all_items)
|
|
207
|
+
)
|
|
@@ -1,59 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
3
|
-
from pydantic import
|
|
1
|
+
import uuid
|
|
2
|
+
from typing import Union, ClassVar, Optional, TYPE_CHECKING, List
|
|
3
|
+
from pydantic import Field
|
|
4
4
|
from .orchestration_system import OrchestrationSystem
|
|
5
5
|
from .orchestration_configuration import OrchestrationConfigurationFields
|
|
6
6
|
from ..sta.datastream import Datastream
|
|
7
|
-
from ..base import
|
|
7
|
+
from ..base import HydroServerBaseModel
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from hydroserverpy import HydroServer
|
|
11
11
|
from hydroserverpy.api.models import Workspace
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class
|
|
14
|
+
class DataArchive(
|
|
15
|
+
HydroServerBaseModel, OrchestrationConfigurationFields
|
|
16
|
+
):
|
|
15
17
|
name: str = Field(..., max_length=255)
|
|
16
18
|
settings: Optional[dict] = None
|
|
19
|
+
orchestration_system_id: uuid.UUID
|
|
20
|
+
workspace_id: uuid.UUID
|
|
17
21
|
|
|
22
|
+
_editable_fields: ClassVar[set[str]] = {
|
|
23
|
+
"name", "settings", "interval", "interval_units", "crontab", "start_time", "end_time", "last_run_successful",
|
|
24
|
+
"last_run_message", "last_run", "next_run", "paused"
|
|
25
|
+
}
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
):
|
|
22
|
-
def __init__(self, _connection: "HydroServer", _uid: Union[UUID, str], **data):
|
|
23
|
-
super().__init__(
|
|
24
|
-
_connection=_connection, _model_ref="dataarchives", _uid=_uid, **data
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
self._workspace_id = str(data.get("workspace_id") or data["workspaceId"])
|
|
28
|
-
self._orchestration_system_id = str(
|
|
29
|
-
data.get("orchestration_system_id") or data["orchestrationSystem"]["id"]
|
|
30
|
-
)
|
|
27
|
+
def __init__(self, client: "HydroServer", **data):
|
|
28
|
+
super().__init__(client=client, service=client.dataarchives, **data)
|
|
31
29
|
|
|
32
30
|
self._workspace = None
|
|
31
|
+
self._orchestration_system = None
|
|
32
|
+
self._datastreams = None
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
_uid=self._orchestration_system_id,
|
|
38
|
-
**data["orchestrationSystem"]
|
|
39
|
-
)
|
|
40
|
-
else:
|
|
41
|
-
self._orchestration_system = None
|
|
42
|
-
|
|
43
|
-
if data.get("datastreams"):
|
|
44
|
-
self._datastreams = [
|
|
45
|
-
Datastream(_connection=_connection, _uid=datastream["id"], **datastream)
|
|
46
|
-
for datastream in data["datastreams"]
|
|
47
|
-
]
|
|
48
|
-
else:
|
|
49
|
-
self._datastreams = []
|
|
34
|
+
@classmethod
|
|
35
|
+
def get_route(cls):
|
|
36
|
+
return "data-archives"
|
|
50
37
|
|
|
51
38
|
@property
|
|
52
39
|
def workspace(self) -> "Workspace":
|
|
53
40
|
"""The workspace this data archive belongs to."""
|
|
54
41
|
|
|
55
|
-
if self._workspace is None
|
|
56
|
-
self._workspace = self.
|
|
42
|
+
if self._workspace is None:
|
|
43
|
+
self._workspace = self.client.workspaces.get(uid=self.workspace_id)
|
|
57
44
|
|
|
58
45
|
return self._workspace
|
|
59
46
|
|
|
@@ -61,10 +48,8 @@ class DataArchive(
|
|
|
61
48
|
def orchestration_system(self) -> "OrchestrationSystem":
|
|
62
49
|
"""The orchestration system that manages this data archive."""
|
|
63
50
|
|
|
64
|
-
if self._orchestration_system is None
|
|
65
|
-
self._orchestration_system = self.
|
|
66
|
-
uid=self._orchestration_system_id
|
|
67
|
-
)
|
|
51
|
+
if self._orchestration_system is None:
|
|
52
|
+
self._orchestration_system = self.client.orchestrationsystems.get(uid=self.orchestration_system_id)
|
|
68
53
|
|
|
69
54
|
return self._orchestration_system
|
|
70
55
|
|
|
@@ -72,34 +57,21 @@ class DataArchive(
|
|
|
72
57
|
def datastreams(self) -> List["Datastream"]:
|
|
73
58
|
"""The datastreams this data archive provides data for."""
|
|
74
59
|
|
|
75
|
-
|
|
60
|
+
if self._datastreams is None:
|
|
61
|
+
self._datastreams = self.client.datastreams.list(data_archive=self.uid, fetch_all=True).items
|
|
76
62
|
|
|
77
|
-
|
|
78
|
-
"""Refresh this data archive from HydroServer."""
|
|
79
|
-
|
|
80
|
-
super()._refresh()
|
|
81
|
-
self._workspace = None
|
|
82
|
-
|
|
83
|
-
def save(self):
|
|
84
|
-
"""Save changes to this data archive to HydroServer."""
|
|
85
|
-
|
|
86
|
-
super()._save()
|
|
87
|
-
|
|
88
|
-
def delete(self):
|
|
89
|
-
"""Delete this data archive from HydroServer."""
|
|
90
|
-
|
|
91
|
-
super()._delete()
|
|
63
|
+
return self._datastreams
|
|
92
64
|
|
|
93
|
-
def add_datastream(self, datastream: Union["Datastream", UUID, str]):
|
|
65
|
+
def add_datastream(self, datastream: Union["Datastream", uuid.UUID, str]):
|
|
94
66
|
"""Add a datastream to this data archive."""
|
|
95
67
|
|
|
96
|
-
self.
|
|
68
|
+
self.client.dataarchives.add_datastream(
|
|
97
69
|
uid=self.uid, datastream=datastream
|
|
98
70
|
)
|
|
99
71
|
|
|
100
|
-
def remove_datastream(self, datastream: Union["Datastream", UUID, str]):
|
|
72
|
+
def remove_datastream(self, datastream: Union["Datastream", uuid.UUID, str]):
|
|
101
73
|
"""Remove a datastream from this data archive."""
|
|
102
74
|
|
|
103
|
-
self.
|
|
75
|
+
self.client.dataarchives.remove_datastream(
|
|
104
76
|
uid=self.uid, datastream=datastream
|
|
105
77
|
)
|