hydroserverpy 0.4.0__py3-none-any.whl → 0.5.0b1__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 +2 -3
- hydroserverpy/api/http.py +24 -0
- hydroserverpy/api/main.py +152 -0
- hydroserverpy/api/models/__init__.py +18 -0
- hydroserverpy/api/models/base.py +74 -0
- hydroserverpy/api/models/etl/__init__.py +0 -0
- hydroserverpy/api/models/iam/__init__.py +0 -0
- hydroserverpy/api/models/iam/account.py +12 -0
- hydroserverpy/api/models/iam/collaborator.py +34 -0
- hydroserverpy/api/models/iam/role.py +10 -0
- hydroserverpy/api/models/iam/workspace.py +203 -0
- hydroserverpy/api/models/sta/__init__.py +0 -0
- hydroserverpy/api/models/sta/datastream.py +336 -0
- hydroserverpy/api/models/sta/observed_property.py +72 -0
- hydroserverpy/api/models/sta/processing_level.py +50 -0
- hydroserverpy/api/models/sta/result_qualifier.py +49 -0
- hydroserverpy/api/models/sta/sensor.py +105 -0
- hydroserverpy/api/models/sta/thing.py +217 -0
- hydroserverpy/api/models/sta/unit.py +49 -0
- hydroserverpy/api/services/__init__.py +8 -0
- hydroserverpy/api/services/base.py +92 -0
- hydroserverpy/api/services/etl/__init__.py +0 -0
- hydroserverpy/api/services/iam/__init__.py +0 -0
- hydroserverpy/api/services/iam/workspace.py +126 -0
- hydroserverpy/api/services/sta/__init__.py +0 -0
- hydroserverpy/api/services/sta/datastream.py +354 -0
- hydroserverpy/api/services/sta/observed_property.py +98 -0
- hydroserverpy/api/services/sta/processing_level.py +78 -0
- hydroserverpy/api/services/sta/result_qualifier.py +74 -0
- hydroserverpy/api/services/sta/sensor.py +116 -0
- hydroserverpy/api/services/sta/thing.py +188 -0
- hydroserverpy/api/services/sta/unit.py +82 -0
- hydroserverpy/etl/loaders/hydroserver_loader.py +1 -1
- hydroserverpy/etl_csv/hydroserver_etl_csv.py +1 -1
- {hydroserverpy-0.4.0.dist-info → hydroserverpy-0.5.0b1.dist-info}/METADATA +4 -3
- hydroserverpy-0.5.0b1.dist-info/RECORD +59 -0
- {hydroserverpy-0.4.0.dist-info → hydroserverpy-0.5.0b1.dist-info}/WHEEL +1 -1
- hydroserverpy/core/endpoints/__init__.py +0 -9
- hydroserverpy/core/endpoints/base.py +0 -146
- hydroserverpy/core/endpoints/data_loaders.py +0 -93
- hydroserverpy/core/endpoints/data_sources.py +0 -93
- hydroserverpy/core/endpoints/datastreams.py +0 -225
- hydroserverpy/core/endpoints/observed_properties.py +0 -111
- hydroserverpy/core/endpoints/processing_levels.py +0 -111
- hydroserverpy/core/endpoints/result_qualifiers.py +0 -111
- hydroserverpy/core/endpoints/sensors.py +0 -111
- hydroserverpy/core/endpoints/things.py +0 -261
- hydroserverpy/core/endpoints/units.py +0 -111
- hydroserverpy/core/schemas/__init__.py +0 -9
- hydroserverpy/core/schemas/base.py +0 -124
- hydroserverpy/core/schemas/data_loaders.py +0 -73
- hydroserverpy/core/schemas/data_sources.py +0 -223
- hydroserverpy/core/schemas/datastreams.py +0 -330
- hydroserverpy/core/schemas/observed_properties.py +0 -43
- hydroserverpy/core/schemas/processing_levels.py +0 -31
- hydroserverpy/core/schemas/result_qualifiers.py +0 -26
- hydroserverpy/core/schemas/sensors.py +0 -68
- hydroserverpy/core/schemas/things.py +0 -346
- hydroserverpy/core/schemas/units.py +0 -29
- hydroserverpy/core/service.py +0 -200
- hydroserverpy-0.4.0.dist-info/RECORD +0 -51
- /hydroserverpy/{core → api}/__init__.py +0 -0
- {hydroserverpy-0.4.0.dist-info → hydroserverpy-0.5.0b1.dist-info/licenses}/LICENSE +0 -0
- {hydroserverpy-0.4.0.dist-info → hydroserverpy-0.5.0b1.dist-info}/top_level.txt +0 -0
- {hydroserverpy-0.4.0.dist-info → hydroserverpy-0.5.0b1.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
from typing import Optional, Union, List, Dict, IO, TYPE_CHECKING
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
from pydantic import (
|
|
4
|
+
BaseModel,
|
|
5
|
+
Field,
|
|
6
|
+
AliasChoices,
|
|
7
|
+
AliasPath,
|
|
8
|
+
AnyHttpUrl,
|
|
9
|
+
field_validator,
|
|
10
|
+
)
|
|
11
|
+
from ..base import HydroServerModel
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from hydroserverpy import HydroServer
|
|
15
|
+
from hydroserverpy.api.models import Workspace, Datastream
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ThingFields(BaseModel):
|
|
19
|
+
name: str = Field(..., max_length=200)
|
|
20
|
+
description: str
|
|
21
|
+
sampling_feature_type: str = Field(
|
|
22
|
+
...,
|
|
23
|
+
max_length=200,
|
|
24
|
+
validation_alias=AliasChoices(
|
|
25
|
+
"samplingFeatureType", AliasPath("properties", "samplingFeatureType")
|
|
26
|
+
),
|
|
27
|
+
)
|
|
28
|
+
sampling_feature_code: str = Field(
|
|
29
|
+
...,
|
|
30
|
+
max_length=200,
|
|
31
|
+
validation_alias=AliasChoices(
|
|
32
|
+
"samplingFeatureCode", AliasPath("properties", "samplingFeatureCode")
|
|
33
|
+
),
|
|
34
|
+
)
|
|
35
|
+
site_type: str = Field(
|
|
36
|
+
...,
|
|
37
|
+
max_length=200,
|
|
38
|
+
validation_alias=AliasChoices("siteType", AliasPath("properties", "siteType")),
|
|
39
|
+
)
|
|
40
|
+
tags: Dict[str, str] = Field(
|
|
41
|
+
...,
|
|
42
|
+
json_schema_extra={"editable": False, "read_only": True},
|
|
43
|
+
validation_alias=AliasChoices("tags", AliasPath("properties", "tags")),
|
|
44
|
+
)
|
|
45
|
+
photos: Dict[str, AnyHttpUrl] = Field(
|
|
46
|
+
...,
|
|
47
|
+
json_schema_extra={"editable": False, "read_only": True},
|
|
48
|
+
validation_alias=AliasChoices("photos", AliasPath("properties", "photos")),
|
|
49
|
+
)
|
|
50
|
+
data_disclaimer: Optional[str] = Field(
|
|
51
|
+
None,
|
|
52
|
+
validation_alias=AliasChoices(
|
|
53
|
+
"dataDisclaimer", AliasPath("properties", "dataDisclaimer")
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
is_private: bool = Field(
|
|
57
|
+
...,
|
|
58
|
+
validation_alias=AliasChoices(
|
|
59
|
+
"isPrivate", AliasPath("properties", "isPrivate")
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
@field_validator("tags", mode="before")
|
|
64
|
+
def convert_tags(
|
|
65
|
+
cls, value: Union[List[Dict[str, str]], Dict[str, str]]
|
|
66
|
+
) -> Dict[str, str]:
|
|
67
|
+
if isinstance(value, list):
|
|
68
|
+
return {item["key"]: item["value"] for item in value}
|
|
69
|
+
return value
|
|
70
|
+
|
|
71
|
+
@field_validator("photos", mode="before")
|
|
72
|
+
def convert_photos(
|
|
73
|
+
cls, value: Union[List[Dict[str, str]], Dict[str, str]]
|
|
74
|
+
) -> Dict[str, str]:
|
|
75
|
+
if isinstance(value, list):
|
|
76
|
+
return {item["name"]: item["link"] for item in value}
|
|
77
|
+
return value
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class LocationFields(BaseModel):
|
|
81
|
+
latitude: float = Field(
|
|
82
|
+
...,
|
|
83
|
+
ge=-90,
|
|
84
|
+
le=90,
|
|
85
|
+
validation_alias=AliasChoices(
|
|
86
|
+
"latitude",
|
|
87
|
+
AliasPath("Locations", 0, "location", "geometry", "coordinates", 0),
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
longitude: float = Field(
|
|
91
|
+
...,
|
|
92
|
+
ge=-180,
|
|
93
|
+
le=180,
|
|
94
|
+
validation_alias=AliasChoices(
|
|
95
|
+
"longitude",
|
|
96
|
+
AliasPath("Locations", 0, "location", "geometry", "coordinates", 1),
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
elevation_m: Optional[float] = Field(
|
|
100
|
+
None,
|
|
101
|
+
ge=-99999,
|
|
102
|
+
le=99999,
|
|
103
|
+
validation_alias=AliasChoices(
|
|
104
|
+
"elevation_m", AliasPath("Locations", 0, "properties", "elevation_m")
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
elevation_datum: Optional[str] = Field(
|
|
108
|
+
None,
|
|
109
|
+
max_length=255,
|
|
110
|
+
validation_alias=AliasChoices(
|
|
111
|
+
"elevationDatum", AliasPath("Locations", 0, "properties", "elevationDatum")
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
state: Optional[str] = Field(
|
|
115
|
+
None,
|
|
116
|
+
max_length=200,
|
|
117
|
+
validation_alias=AliasChoices(
|
|
118
|
+
"state", AliasPath("Locations", 0, "properties", "state")
|
|
119
|
+
),
|
|
120
|
+
)
|
|
121
|
+
county: Optional[str] = Field(
|
|
122
|
+
None,
|
|
123
|
+
max_length=200,
|
|
124
|
+
validation_alias=AliasChoices(
|
|
125
|
+
"county", AliasPath("Locations", 0, "properties", "county")
|
|
126
|
+
),
|
|
127
|
+
)
|
|
128
|
+
country: Optional[str] = Field(
|
|
129
|
+
None,
|
|
130
|
+
max_length=2,
|
|
131
|
+
validation_alias=AliasChoices(
|
|
132
|
+
"country", AliasPath("Locations", 0, "properties", "country")
|
|
133
|
+
),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class Thing(HydroServerModel, ThingFields, LocationFields):
|
|
138
|
+
def __init__(self, _connection: "HydroServer", _uid: Union[UUID, str], **data):
|
|
139
|
+
super().__init__(
|
|
140
|
+
_connection=_connection, _model_ref="things", _uid=_uid, **data
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
self._workspace_id = str(
|
|
144
|
+
data.get("workspace_id")
|
|
145
|
+
or data.get("workspaceId")
|
|
146
|
+
or data["properties"]["workspace"]["id"]
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
self._workspace = None
|
|
150
|
+
self._datastreams = None
|
|
151
|
+
self._photos = None
|
|
152
|
+
self._tags = None
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def workspace(self) -> "Workspace":
|
|
156
|
+
"""The workspace this thing belongs to."""
|
|
157
|
+
|
|
158
|
+
if self._workspace is None:
|
|
159
|
+
self._workspace = self._connection.workspaces.get(uid=self._workspace_id)
|
|
160
|
+
|
|
161
|
+
return self._workspace
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def datastreams(self) -> List["Datastream"]:
|
|
165
|
+
"""The datastreams collected at this thing."""
|
|
166
|
+
|
|
167
|
+
if self._datastreams is None:
|
|
168
|
+
self._datastreams = self._connection.datastreams.list(thing=self.uid)
|
|
169
|
+
|
|
170
|
+
return self._datastreams
|
|
171
|
+
|
|
172
|
+
def refresh(self):
|
|
173
|
+
"""Refresh this thing from HydroServer."""
|
|
174
|
+
|
|
175
|
+
super()._refresh()
|
|
176
|
+
self._workspace = None
|
|
177
|
+
self._datastreams = None
|
|
178
|
+
|
|
179
|
+
def save(self):
|
|
180
|
+
"""Save changes to this thing to HydroServer."""
|
|
181
|
+
|
|
182
|
+
super()._save()
|
|
183
|
+
|
|
184
|
+
def delete(self):
|
|
185
|
+
"""Delete this thing from HydroServer."""
|
|
186
|
+
|
|
187
|
+
super()._delete()
|
|
188
|
+
|
|
189
|
+
def add_tag(self, key: str, value: str):
|
|
190
|
+
"""Add a tag to this thing."""
|
|
191
|
+
|
|
192
|
+
self._connection.things.add_tag(uid=self.uid, key=key, value=value)
|
|
193
|
+
self.tags[key] = value
|
|
194
|
+
|
|
195
|
+
def update_tag(self, key: str, value: str):
|
|
196
|
+
"""Edit a tag of this thing."""
|
|
197
|
+
|
|
198
|
+
self._connection.things.update_tag(uid=self.uid, key=key, value=value)
|
|
199
|
+
self.tags[key] = value
|
|
200
|
+
|
|
201
|
+
def delete_tag(self, key: str):
|
|
202
|
+
"""Delete a tag of this thing."""
|
|
203
|
+
|
|
204
|
+
self._connection.things.delete_tag(uid=self.uid, key=key)
|
|
205
|
+
del self.tags[key]
|
|
206
|
+
|
|
207
|
+
def add_photo(self, file: IO[bytes]):
|
|
208
|
+
"""Add a photo of this thing."""
|
|
209
|
+
|
|
210
|
+
photo = self._connection.things.add_photo(uid=self.uid, file=file)
|
|
211
|
+
self.photos[photo["name"]] = photo["link"]
|
|
212
|
+
|
|
213
|
+
def delete_photo(self, name: str):
|
|
214
|
+
"""Delete a photo of this thing."""
|
|
215
|
+
|
|
216
|
+
self._connection.things.delete_photo(uid=self.uid, name=name)
|
|
217
|
+
del self.photos[name]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from typing import Union, TYPE_CHECKING
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
from ..base import HydroServerModel
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from hydroserverpy import HydroServer
|
|
8
|
+
from hydroserverpy.api.models import Workspace
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UnitFields(BaseModel):
|
|
12
|
+
name: str = Field(..., max_length=255)
|
|
13
|
+
symbol: str = Field(..., max_length=255)
|
|
14
|
+
definition: str
|
|
15
|
+
unit_type: str = Field(..., max_length=255, alias="type")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Unit(HydroServerModel, UnitFields):
|
|
19
|
+
def __init__(self, _connection: "HydroServer", _uid: Union[UUID, str], **data):
|
|
20
|
+
super().__init__(_connection=_connection, _model_ref="units", _uid=_uid, **data)
|
|
21
|
+
|
|
22
|
+
self._workspace_id = str(data.get("workspace_id") or data["workspaceId"])
|
|
23
|
+
|
|
24
|
+
self._workspace = None
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def workspace(self) -> "Workspace":
|
|
28
|
+
"""The workspace this unit belongs to."""
|
|
29
|
+
|
|
30
|
+
if self._workspace is None and self._workspace_id:
|
|
31
|
+
self._workspace = self._connection.workspaces.get(uid=self._workspace_id)
|
|
32
|
+
|
|
33
|
+
return self._workspace
|
|
34
|
+
|
|
35
|
+
def refresh(self):
|
|
36
|
+
"""Refresh this unit from HydroServer."""
|
|
37
|
+
|
|
38
|
+
super()._refresh()
|
|
39
|
+
self._workspace = None
|
|
40
|
+
|
|
41
|
+
def save(self):
|
|
42
|
+
"""Save changes to this unit to HydroServer."""
|
|
43
|
+
|
|
44
|
+
super()._save()
|
|
45
|
+
|
|
46
|
+
def delete(self):
|
|
47
|
+
"""Delete this unit from HydroServer."""
|
|
48
|
+
|
|
49
|
+
super()._delete()
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .iam.workspace import WorkspaceService
|
|
2
|
+
from .sta.thing import ThingService
|
|
3
|
+
from .sta.observed_property import ObservedPropertyService
|
|
4
|
+
from .sta.unit import UnitService
|
|
5
|
+
from .sta.processing_level import ProcessingLevelService
|
|
6
|
+
from .sta.result_qualifier import ResultQualifierService
|
|
7
|
+
from .sta.sensor import SensorService
|
|
8
|
+
from .sta.datastream import DatastreamService
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Type, Union, Optional
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from hydroserverpy import HydroServer
|
|
6
|
+
from hydroserverpy.api.models.base import HydroServerModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EndpointService:
|
|
10
|
+
_model: Type["HydroServerModel"]
|
|
11
|
+
_api_route: str
|
|
12
|
+
_endpoint_route: str
|
|
13
|
+
|
|
14
|
+
def __init__(self, connection: "HydroServer") -> None:
|
|
15
|
+
self._connection = connection
|
|
16
|
+
|
|
17
|
+
def _list(self, params: Optional[dict] = None):
|
|
18
|
+
path = f"/{self._api_route}/{self._endpoint_route}"
|
|
19
|
+
|
|
20
|
+
response = self._connection.request("get", path, params=params).json()
|
|
21
|
+
|
|
22
|
+
return [
|
|
23
|
+
self._model(
|
|
24
|
+
_connection=self._connection, _uid=UUID(str(obj.pop("id"))), **obj
|
|
25
|
+
)
|
|
26
|
+
for obj in response
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
def _get(self, uid: Union[UUID, str]):
|
|
30
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}"
|
|
31
|
+
response = self._connection.request("get", path).json()
|
|
32
|
+
|
|
33
|
+
return self._model(
|
|
34
|
+
_connection=self._connection, _uid=UUID(str(response.pop("id"))), **response
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def _create(self, **kwargs):
|
|
38
|
+
path = f"/{self._api_route}/{self._endpoint_route}"
|
|
39
|
+
headers = {"Content-type": "application/json"}
|
|
40
|
+
response = self._connection.request(
|
|
41
|
+
"post", path, headers=headers, json=kwargs
|
|
42
|
+
).json()
|
|
43
|
+
|
|
44
|
+
return self._model(
|
|
45
|
+
_connection=self._connection, _uid=UUID(str(response.pop("id"))), **response
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def _update(self, uid: Union[UUID, str], **kwargs):
|
|
49
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}"
|
|
50
|
+
headers = {"Content-type": "application/json"}
|
|
51
|
+
response = self._connection.request(
|
|
52
|
+
"patch", path, headers=headers, json=kwargs
|
|
53
|
+
).json()
|
|
54
|
+
|
|
55
|
+
return self._model(
|
|
56
|
+
_connection=self._connection, _uid=UUID(str(response.pop("id"))), **response
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def _delete(self, uid: Union[UUID, str]):
|
|
60
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}"
|
|
61
|
+
response = self._connection.request("delete", path)
|
|
62
|
+
|
|
63
|
+
return response
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class SensorThingsService(EndpointService):
|
|
67
|
+
_sta_route: str
|
|
68
|
+
|
|
69
|
+
def __init__(self, connection) -> None:
|
|
70
|
+
super().__init__(connection)
|
|
71
|
+
|
|
72
|
+
def _list(self, path: Optional[str] = None, params: Optional[dict] = None):
|
|
73
|
+
path = path or f"/{self._sta_route}"
|
|
74
|
+
response = self._connection.request("get", path, params=params)
|
|
75
|
+
|
|
76
|
+
return [
|
|
77
|
+
self._model(_connection=self._connection, _uid=obj.pop("@iot.id"), **obj)
|
|
78
|
+
for obj in response.json()["value"]
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
def _get(
|
|
82
|
+
self,
|
|
83
|
+
uid: Union[UUID, str],
|
|
84
|
+
path: Optional[str] = None,
|
|
85
|
+
params: Optional[dict] = None,
|
|
86
|
+
):
|
|
87
|
+
path = path or f"/{self._sta_route}('{str(uid)}')"
|
|
88
|
+
response = self._connection.request("get", path, params=params).json()
|
|
89
|
+
|
|
90
|
+
return self._model(
|
|
91
|
+
_connection=self._connection, _uid=response.pop("@iot.id"), **response
|
|
92
|
+
)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Union, List
|
|
2
|
+
from pydantic import EmailStr
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
from hydroserverpy.api.models import Workspace, Role, Collaborator
|
|
5
|
+
from ..base import EndpointService
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from hydroserverpy import HydroServer
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WorkspaceService(EndpointService):
|
|
13
|
+
def __init__(self, connection: "HydroServer"):
|
|
14
|
+
self._model = Workspace
|
|
15
|
+
self._api_route = "api/auth"
|
|
16
|
+
self._endpoint_route = "workspaces"
|
|
17
|
+
|
|
18
|
+
super().__init__(connection)
|
|
19
|
+
|
|
20
|
+
def list(self, associated_only: bool = False) -> List["Workspace"]:
|
|
21
|
+
"""Fetch a collection of HydroServer resources."""
|
|
22
|
+
|
|
23
|
+
return super()._list(params={"associated_only": associated_only})
|
|
24
|
+
|
|
25
|
+
def get(self, uid: Union[UUID, str]) -> "Workspace":
|
|
26
|
+
"""Get a workspace by ID."""
|
|
27
|
+
|
|
28
|
+
return super()._get(uid=str(uid))
|
|
29
|
+
|
|
30
|
+
def create(self, name: str, is_private: bool, **_) -> "Workspace":
|
|
31
|
+
"""Create a new workspace."""
|
|
32
|
+
|
|
33
|
+
kwargs = {"name": name, "isPrivate": is_private}
|
|
34
|
+
|
|
35
|
+
return super()._create(**kwargs)
|
|
36
|
+
|
|
37
|
+
def update(
|
|
38
|
+
self, uid: Union[UUID, str], name: str = ..., is_private: bool = ..., **_
|
|
39
|
+
) -> "Workspace":
|
|
40
|
+
"""Update a workspace."""
|
|
41
|
+
|
|
42
|
+
kwargs = {"name": name, "isPrivate": is_private}
|
|
43
|
+
|
|
44
|
+
return super()._update(
|
|
45
|
+
uid=str(uid), **{k: v for k, v in kwargs.items() if v is not ...}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def delete(self, uid: Union[UUID, str]) -> None:
|
|
49
|
+
"""Delete a workspace."""
|
|
50
|
+
|
|
51
|
+
super()._delete(uid=str(uid))
|
|
52
|
+
|
|
53
|
+
def list_roles(self, uid: Union[UUID, str]) -> List["Role"]:
|
|
54
|
+
"""Get all roles that can be assigned within a workspace."""
|
|
55
|
+
|
|
56
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/roles"
|
|
57
|
+
response = self._connection.request("get", path)
|
|
58
|
+
|
|
59
|
+
return [Role(**obj) for obj in response.json()]
|
|
60
|
+
|
|
61
|
+
def list_collaborators(self, uid: Union[UUID, str]) -> List["Collaborator"]:
|
|
62
|
+
"""Get all collaborators associated with a workspace."""
|
|
63
|
+
|
|
64
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/collaborators"
|
|
65
|
+
response = self._connection.request("get", path)
|
|
66
|
+
|
|
67
|
+
return [
|
|
68
|
+
Collaborator(_connection=self._connection, workspace_id=uid, **obj)
|
|
69
|
+
for obj in response.json()
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
def add_collaborator(
|
|
73
|
+
self, uid: Union[UUID, str], email: EmailStr, role: Union["Role", UUID, str]
|
|
74
|
+
) -> "Collaborator":
|
|
75
|
+
"""Add a collaborator to a workspace."""
|
|
76
|
+
|
|
77
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/collaborators"
|
|
78
|
+
response = self._connection.request(
|
|
79
|
+
"post",
|
|
80
|
+
path,
|
|
81
|
+
json={"email": email, "roleId": str(getattr(role, "uid", role))},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return Collaborator(
|
|
85
|
+
_connection=self._connection, workspace_id=uid, **response.json()
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def edit_collaborator_role(
|
|
89
|
+
self, uid: Union[UUID, str], email: EmailStr, role: Union["Role", UUID, str]
|
|
90
|
+
) -> "Collaborator":
|
|
91
|
+
"""Edit the role of a collaborator in a workspace."""
|
|
92
|
+
|
|
93
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/collaborators"
|
|
94
|
+
response = self._connection.request(
|
|
95
|
+
"put",
|
|
96
|
+
path,
|
|
97
|
+
json={"email": email, "roleId": str(getattr(role, "uid", role))},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return Collaborator(
|
|
101
|
+
_connection=self._connection, workspace_id=uid, **response.json()
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def remove_collaborator(self, uid: Union[UUID, str], email: EmailStr) -> None:
|
|
105
|
+
"""Remove a collaborator from a workspace."""
|
|
106
|
+
|
|
107
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/collaborators"
|
|
108
|
+
self._connection.request("delete", path, json={"email": email})
|
|
109
|
+
|
|
110
|
+
def transfer_ownership(self, uid: Union[UUID, str], email: str) -> None:
|
|
111
|
+
"""Transfer ownership of a workspace to another HydroServer user."""
|
|
112
|
+
|
|
113
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/transfer"
|
|
114
|
+
self._connection.request("post", path, json={"newOwner": email})
|
|
115
|
+
|
|
116
|
+
def accept_ownership_transfer(self, uid: Union[UUID, str]) -> None:
|
|
117
|
+
"""Accept ownership transfer of a workspace."""
|
|
118
|
+
|
|
119
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/transfer"
|
|
120
|
+
self._connection.request("put", path)
|
|
121
|
+
|
|
122
|
+
def cancel_ownership_transfer(self, uid: Union[UUID, str]) -> None:
|
|
123
|
+
"""Cancel ownership transfer of a workspace."""
|
|
124
|
+
|
|
125
|
+
path = f"/{self._api_route}/{self._endpoint_route}/{str(uid)}/transfer"
|
|
126
|
+
self._connection.request("delete", path)
|
|
File without changes
|