hydroserverpy 0.3.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 +3 -4
- 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/__init__.py +21 -0
- hydroserverpy/etl/extractors/__init__.py +0 -0
- hydroserverpy/etl/extractors/base.py +13 -0
- hydroserverpy/etl/extractors/ftp_extractor.py +50 -0
- hydroserverpy/etl/extractors/http_extractor.py +84 -0
- hydroserverpy/etl/extractors/local_file_extractor.py +25 -0
- hydroserverpy/etl/hydroserver_etl.py +40 -0
- hydroserverpy/etl/loaders/__init__.py +0 -0
- hydroserverpy/etl/loaders/base.py +13 -0
- hydroserverpy/etl/loaders/hydroserver_loader.py +68 -0
- hydroserverpy/etl/transformers/__init__.py +0 -0
- hydroserverpy/etl/transformers/base.py +52 -0
- hydroserverpy/etl/transformers/csv_transformer.py +88 -0
- hydroserverpy/etl/transformers/json_transformer.py +62 -0
- hydroserverpy/etl/types.py +7 -0
- hydroserverpy/etl_csv/__init__.py +0 -0
- hydroserverpy/{etl/service.py → etl_csv/hydroserver_etl_csv.py} +93 -55
- hydroserverpy/quality/service.py +84 -70
- hydroserverpy-0.5.0b1.dist-info/METADATA +19 -0
- hydroserverpy-0.5.0b1.dist-info/RECORD +59 -0
- {hydroserverpy-0.3.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 -133
- hydroserverpy/core/endpoints/data_loaders.py +0 -92
- hydroserverpy/core/endpoints/data_sources.py +0 -92
- hydroserverpy/core/endpoints/datastreams.py +0 -188
- hydroserverpy/core/endpoints/observed_properties.py +0 -93
- hydroserverpy/core/endpoints/processing_levels.py +0 -93
- hydroserverpy/core/endpoints/result_qualifiers.py +0 -93
- hydroserverpy/core/endpoints/sensors.py +0 -93
- hydroserverpy/core/endpoints/things.py +0 -240
- hydroserverpy/core/endpoints/units.py +0 -93
- hydroserverpy/core/schemas/__init__.py +0 -9
- hydroserverpy/core/schemas/base.py +0 -117
- hydroserverpy/core/schemas/data_loaders.py +0 -71
- hydroserverpy/core/schemas/data_sources.py +0 -206
- hydroserverpy/core/schemas/datastreams.py +0 -299
- hydroserverpy/core/schemas/observed_properties.py +0 -35
- hydroserverpy/core/schemas/processing_levels.py +0 -27
- hydroserverpy/core/schemas/result_qualifiers.py +0 -23
- hydroserverpy/core/schemas/sensors.py +0 -53
- hydroserverpy/core/schemas/things.py +0 -309
- hydroserverpy/core/schemas/units.py +0 -30
- hydroserverpy/core/service.py +0 -186
- hydroserverpy-0.3.0.dist-info/METADATA +0 -18
- hydroserverpy-0.3.0.dist-info/RECORD +0 -36
- /hydroserverpy/{core → api}/__init__.py +0 -0
- /hydroserverpy/{etl → etl_csv}/exceptions.py +0 -0
- {hydroserverpy-0.3.0.dist-info → hydroserverpy-0.5.0b1.dist-info/licenses}/LICENSE +0 -0
- {hydroserverpy-0.3.0.dist-info → hydroserverpy-0.5.0b1.dist-info}/top_level.txt +0 -0
- {hydroserverpy-0.3.0.dist-info → hydroserverpy-0.5.0b1.dist-info}/zip-safe +0 -0
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field, AliasPath, AliasChoices, field_validator
|
|
2
|
-
from typing import Optional, List, Literal, IO, TYPE_CHECKING
|
|
3
|
-
from uuid import UUID
|
|
4
|
-
from country_list import countries_for_language
|
|
5
|
-
from hydroserverpy.core.schemas.base import HydroServerCoreModel, HydroServerBaseModel
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from hydroserverpy.core.schemas.datastreams import Datastream
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class ThingFields(BaseModel):
|
|
12
|
-
name: str = Field(
|
|
13
|
-
..., strip_whitespace=True, max_length=200,
|
|
14
|
-
description='The name of the site/thing.'
|
|
15
|
-
)
|
|
16
|
-
description: str = Field(
|
|
17
|
-
..., strip_whitespace=True,
|
|
18
|
-
description='A description of the site/thing.'
|
|
19
|
-
)
|
|
20
|
-
sampling_feature_type: str = Field(
|
|
21
|
-
..., strip_whitespace=True, max_length=200,
|
|
22
|
-
description='The sampling feature type of the site/thing.'
|
|
23
|
-
)
|
|
24
|
-
sampling_feature_code: str = Field(
|
|
25
|
-
..., strip_whitespace=True, max_length=200,
|
|
26
|
-
description='A code representing the sampling feature of the site/thing.'
|
|
27
|
-
)
|
|
28
|
-
site_type: str = Field(
|
|
29
|
-
..., strip_whitespace=True, max_length=200,
|
|
30
|
-
description='The type of the site/thing.'
|
|
31
|
-
)
|
|
32
|
-
data_disclaimer: Optional[str] = Field(
|
|
33
|
-
None, strip_whitespace=True,
|
|
34
|
-
description='An optional data disclaimer to attach to observations collected at this site/thing.'
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# Get a list of all ISO 3166-1 alpha-2 country codes
|
|
39
|
-
valid_country_codes = [code for code, _ in countries_for_language('en')]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class LocationFields(BaseModel):
|
|
43
|
-
latitude: float = Field(
|
|
44
|
-
..., ge=-90, le=90, serialization_alias='latitude',
|
|
45
|
-
validation_alias=AliasChoices('latitude', AliasPath('location', 'latitude')),
|
|
46
|
-
description='The WGS84 latitude of the location.'
|
|
47
|
-
)
|
|
48
|
-
longitude: float = Field(
|
|
49
|
-
..., ge=-180, le=180, serialization_alias='longitude',
|
|
50
|
-
validation_alias=AliasChoices('longitude', AliasPath('location', 'longitude')),
|
|
51
|
-
description='The WGS84 longitude of the location.'
|
|
52
|
-
)
|
|
53
|
-
elevation_m: Optional[float] = Field(
|
|
54
|
-
None, ge=-99999, le=99999, serialization_alias='elevation_m',
|
|
55
|
-
validation_alias=AliasChoices('elevation_m', AliasPath('location', 'elevation_m')),
|
|
56
|
-
description='The elevation in meters of the location.'
|
|
57
|
-
)
|
|
58
|
-
elevation_datum: Optional[str] = Field(
|
|
59
|
-
None, strip_whitespace=True, max_length=255, serialization_alias='elevationDatum',
|
|
60
|
-
validation_alias=AliasChoices('elevationDatum', AliasPath('location', 'elevationDatum')),
|
|
61
|
-
description='The datum used to represent the elevation of the location.'
|
|
62
|
-
)
|
|
63
|
-
state: Optional[str] = Field(
|
|
64
|
-
None, strip_whitespace=True, max_length=200, serialization_alias='state',
|
|
65
|
-
validation_alias=AliasChoices('state', AliasPath('location', 'state')),
|
|
66
|
-
description='The state/province of the location.'
|
|
67
|
-
)
|
|
68
|
-
county: Optional[str] = Field(
|
|
69
|
-
None, strip_whitespace=True, max_length=200, serialization_alias='county',
|
|
70
|
-
validation_alias=AliasChoices('county', AliasPath('location', 'county')),
|
|
71
|
-
description='The county/district of the location.'
|
|
72
|
-
)
|
|
73
|
-
country: Optional[str] = Field(
|
|
74
|
-
None, strip_whitespace=True, max_length=2, serialization_alias='country',
|
|
75
|
-
validation_alias=AliasChoices('country', AliasPath('location', 'country')),
|
|
76
|
-
description='The ISO 3166-1 alpha-2 country code of the location.'
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
@field_validator('country', mode='after')
|
|
80
|
-
def check_country_code(cls, value: str) -> str:
|
|
81
|
-
"""
|
|
82
|
-
Validate the country code to ensure it is an ISO 3166-1 alpha-2 country code.
|
|
83
|
-
|
|
84
|
-
:param value: The country code to validate.
|
|
85
|
-
:type value: Optional[str]
|
|
86
|
-
:raises ValueError: If the country code is invalid.
|
|
87
|
-
:return: The validated country code.
|
|
88
|
-
:rtype: Optional[str]
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
if value and value.upper() not in valid_country_codes:
|
|
92
|
-
raise ValueError(f'Invalid country code: {value}. Must be an ISO 3166-1 alpha-2 country code.')
|
|
93
|
-
|
|
94
|
-
return value
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class Thing(HydroServerCoreModel, ThingFields, LocationFields):
|
|
98
|
-
"""
|
|
99
|
-
A model representing a site/thing, combining core attributes from ThingFields and LocationFields with methods for
|
|
100
|
-
interacting with related entities.
|
|
101
|
-
|
|
102
|
-
:ivar _datastreams: A private attribute to cache the list of datastreams associated with the thing.
|
|
103
|
-
:ivar _tags: A private attribute to cache the list of tags associated with the thing.
|
|
104
|
-
:ivar _photos: A private attribute to cache the list of photos associated with the thing.
|
|
105
|
-
:ivar _archive: A private attribute to cache the archive associated with the thing.
|
|
106
|
-
"""
|
|
107
|
-
|
|
108
|
-
def __init__(self, _endpoint, _uid: Optional[UUID] = None, **data):
|
|
109
|
-
"""
|
|
110
|
-
Initialize a Thing instance.
|
|
111
|
-
|
|
112
|
-
:param _endpoint: The endpoint associated with the thing.
|
|
113
|
-
:type _endpoint: str
|
|
114
|
-
:param _uid: The unique identifier for the thing.
|
|
115
|
-
:type _uid: Optional[UUID]
|
|
116
|
-
:param data: Additional attributes for the thing.
|
|
117
|
-
"""
|
|
118
|
-
|
|
119
|
-
super().__init__(_endpoint=_endpoint, _uid=_uid, **data)
|
|
120
|
-
self._datastreams = None
|
|
121
|
-
self._tags = None
|
|
122
|
-
self._photos = None
|
|
123
|
-
self._archive = None
|
|
124
|
-
|
|
125
|
-
@property
|
|
126
|
-
def datastreams(self) -> List['Datastream']:
|
|
127
|
-
"""
|
|
128
|
-
The datastreams associated with the thing. If not already cached, fetch the datastreams from the
|
|
129
|
-
server.
|
|
130
|
-
|
|
131
|
-
:return: A list of datastreams associated with the thing.
|
|
132
|
-
:rtype: List[Datastream]
|
|
133
|
-
"""
|
|
134
|
-
|
|
135
|
-
if self._datastreams is None:
|
|
136
|
-
self._datastreams = self._endpoint.list_datastreams(uid=self.uid)
|
|
137
|
-
|
|
138
|
-
return self._datastreams
|
|
139
|
-
|
|
140
|
-
@property
|
|
141
|
-
def tags(self) -> List['Tag']:
|
|
142
|
-
"""
|
|
143
|
-
The tags associated with the thing. If not already cached, fetch the tags from the server.
|
|
144
|
-
|
|
145
|
-
:return: A list of tags associated with the thing.
|
|
146
|
-
:rtype: List[Tag]
|
|
147
|
-
"""
|
|
148
|
-
|
|
149
|
-
if self._tags is None:
|
|
150
|
-
self._tags = self._endpoint.list_tags(uid=self.uid)
|
|
151
|
-
|
|
152
|
-
return self._tags
|
|
153
|
-
|
|
154
|
-
@property
|
|
155
|
-
def photos(self) -> List['Photo']:
|
|
156
|
-
"""
|
|
157
|
-
The photos associated with the thing. If not already cached, fetch the photos from the server.
|
|
158
|
-
|
|
159
|
-
:return: A list of photos associated with the thing.
|
|
160
|
-
:rtype: List[Photo]
|
|
161
|
-
"""
|
|
162
|
-
|
|
163
|
-
if self._photos is None:
|
|
164
|
-
self._photos = self._endpoint.list_photos(uid=self.uid)
|
|
165
|
-
|
|
166
|
-
return self._photos
|
|
167
|
-
|
|
168
|
-
@property
|
|
169
|
-
def archive(self) -> 'Archive':
|
|
170
|
-
"""
|
|
171
|
-
The archive associated with the thing. If not already cached, fetch the archive from the server.
|
|
172
|
-
|
|
173
|
-
:return: The archive associated with the thing.
|
|
174
|
-
:rtype: Archive
|
|
175
|
-
"""
|
|
176
|
-
|
|
177
|
-
if self._archive is None:
|
|
178
|
-
self._archive = self._endpoint.get_archive(uid=self.uid)
|
|
179
|
-
|
|
180
|
-
return self._archive
|
|
181
|
-
|
|
182
|
-
def refresh(self) -> None:
|
|
183
|
-
"""
|
|
184
|
-
Refresh the thing with the latest data from the server and update cached datastreams, tags, photos, and archive
|
|
185
|
-
if they were previously loaded.
|
|
186
|
-
"""
|
|
187
|
-
|
|
188
|
-
entity = self._endpoint.get(uid=self.uid).model_dump(exclude=['uid'])
|
|
189
|
-
self._original_data = entity
|
|
190
|
-
self.__dict__.update(entity)
|
|
191
|
-
if self._datastreams is not None:
|
|
192
|
-
self._datastreams = self._endpoint.list_datastreams(uid=self.uid)
|
|
193
|
-
if self._tags is not None:
|
|
194
|
-
self._tags = self._endpoint.list_tags(uid=self.uid)
|
|
195
|
-
if self._photos is not None:
|
|
196
|
-
self._photos = self._endpoint.list_photos(uid=self.uid)
|
|
197
|
-
if self._archive is not None:
|
|
198
|
-
self._archive = self._endpoint.get_archive(uid=self.uid)
|
|
199
|
-
|
|
200
|
-
def add_tag(self, key: str, value: str) -> None:
|
|
201
|
-
"""
|
|
202
|
-
Add a new tag to the thing.
|
|
203
|
-
|
|
204
|
-
:param key: The key of the new tag.
|
|
205
|
-
:param value: The value of the new tag.
|
|
206
|
-
"""
|
|
207
|
-
|
|
208
|
-
if self.tags is not None:
|
|
209
|
-
new_tag = self._endpoint.create_tag(uid=self.uid, key=key, value=value)
|
|
210
|
-
self._tags.append(new_tag)
|
|
211
|
-
|
|
212
|
-
def update_tag(self, key: str, value: str) -> None:
|
|
213
|
-
"""
|
|
214
|
-
Update the value of an existing tag on the thing.
|
|
215
|
-
|
|
216
|
-
:param key: The key of the tag to update.
|
|
217
|
-
:param value: The new value for the tag.
|
|
218
|
-
"""
|
|
219
|
-
|
|
220
|
-
selected_tag = next((tag for tag in self._tags if tag.key == key))
|
|
221
|
-
updated_tag = self._endpoint.update_tag(uid=self.uid, tag_uid=selected_tag.uid, value=value)
|
|
222
|
-
self._tags = [tag if tag.key != key else updated_tag for tag in self._tags]
|
|
223
|
-
|
|
224
|
-
def delete_tag(self, key: str) -> None:
|
|
225
|
-
"""
|
|
226
|
-
Delete a tag from the thing.
|
|
227
|
-
|
|
228
|
-
:param key: The key of the tag to delete.
|
|
229
|
-
"""
|
|
230
|
-
|
|
231
|
-
selected_tag = next((tag for tag in self._tags if tag.key == key))
|
|
232
|
-
self._endpoint.delete_tag(uid=self.uid, tag_uid=selected_tag.uid)
|
|
233
|
-
self._tags = [tag for tag in self._tags if tag.key != selected_tag.key]
|
|
234
|
-
|
|
235
|
-
def add_photo(self, photo: IO) -> None:
|
|
236
|
-
"""
|
|
237
|
-
Add a photo to the thing.
|
|
238
|
-
|
|
239
|
-
:param photo: The photo file to upload.
|
|
240
|
-
:type photo: IO
|
|
241
|
-
"""
|
|
242
|
-
|
|
243
|
-
if self.photos is not None:
|
|
244
|
-
photos = self._endpoint.upload_photo(uid=self.uid, file=photo)
|
|
245
|
-
self._photos.extend(photos)
|
|
246
|
-
|
|
247
|
-
def delete_photo(self, link: str) -> None:
|
|
248
|
-
"""
|
|
249
|
-
Delete a photo from the thing.
|
|
250
|
-
|
|
251
|
-
:param link: The link to the photo to delete.
|
|
252
|
-
"""
|
|
253
|
-
|
|
254
|
-
selected_photo = next((photo for photo in self._photos if photo.link == link))
|
|
255
|
-
self._endpoint.delete_photo(uid=self.uid, photo_uid=selected_photo.uid)
|
|
256
|
-
self._photos = [photo for photo in self._photos if photo.link != selected_photo.link]
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
class Archive(HydroServerBaseModel):
|
|
260
|
-
"""
|
|
261
|
-
A model representing an archive associated with a thing.
|
|
262
|
-
"""
|
|
263
|
-
|
|
264
|
-
link: Optional[str] = Field(
|
|
265
|
-
None, strip_whitespace=True, max_length=255,
|
|
266
|
-
description='A link to the HydroShare resource containing the archived site/thing.'
|
|
267
|
-
)
|
|
268
|
-
frequency: Optional[Literal['daily', 'weekly', 'monthly']] = Field(
|
|
269
|
-
...,
|
|
270
|
-
description='The frequency at which the site/thing should be archived.',
|
|
271
|
-
)
|
|
272
|
-
path: str = Field(
|
|
273
|
-
..., strip_whitespace=True, max_length=255,
|
|
274
|
-
description='The path within the HydroShare resource containing the archived data.'
|
|
275
|
-
)
|
|
276
|
-
datastream_ids: List[UUID] = Field(
|
|
277
|
-
...,
|
|
278
|
-
description='The list of datastreams that are included in the archived data.',
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
class Tag(HydroServerBaseModel):
|
|
283
|
-
"""
|
|
284
|
-
A model representing a tag associated with a thing.
|
|
285
|
-
"""
|
|
286
|
-
|
|
287
|
-
key: str = Field(
|
|
288
|
-
..., strip_whitespace=True, max_length=255,
|
|
289
|
-
description='The key of the tag.'
|
|
290
|
-
)
|
|
291
|
-
value: str = Field(
|
|
292
|
-
..., strip_whitespace=True, max_length=255,
|
|
293
|
-
description='The value of the tag.'
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
class Photo(HydroServerBaseModel):
|
|
298
|
-
"""
|
|
299
|
-
A model representing a photo associated with a thing.
|
|
300
|
-
"""
|
|
301
|
-
|
|
302
|
-
file_path: str = Field(
|
|
303
|
-
..., strip_whitespace=True,
|
|
304
|
-
description='The file path of the photo.'
|
|
305
|
-
)
|
|
306
|
-
link: str = Field(
|
|
307
|
-
..., strip_whitespace=True,
|
|
308
|
-
description='The link to the photo.'
|
|
309
|
-
)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from pydantic import Field
|
|
2
|
-
from hydroserverpy.core.schemas.base import HydroServerCoreModel
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class UnitFields:
|
|
6
|
-
name: str = Field(
|
|
7
|
-
..., strip_whitespace=True, max_length=255,
|
|
8
|
-
description='The name of the unit.'
|
|
9
|
-
)
|
|
10
|
-
symbol: str = Field(
|
|
11
|
-
..., strip_whitespace=True, max_length=255,
|
|
12
|
-
description='The symbol of the unit.'
|
|
13
|
-
)
|
|
14
|
-
definition: str = Field(
|
|
15
|
-
..., strip_whitespace=True,
|
|
16
|
-
description='The definition of the unit.'
|
|
17
|
-
)
|
|
18
|
-
type: str = Field(
|
|
19
|
-
..., strip_whitespace=True, max_length=255,
|
|
20
|
-
description='The type of the unit.'
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class Unit(HydroServerCoreModel, UnitFields):
|
|
25
|
-
"""
|
|
26
|
-
A model representing a unit, extending the core functionality of HydroServerCoreModel with additional
|
|
27
|
-
fields defined in UnitFields.
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
pass
|
hydroserverpy/core/service.py
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
from typing import Optional
|
|
3
|
-
from hydroserverpy.core.endpoints import (DataLoaderEndpoint, DataSourceEndpoint, DatastreamEndpoint, ThingEndpoint,
|
|
4
|
-
SensorEndpoint, UnitEndpoint, ProcessingLevelEndpoint,
|
|
5
|
-
ObservedPropertyEndpoint, ResultQualifierEndpoint)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class HydroServer:
|
|
9
|
-
"""
|
|
10
|
-
Connects to a HydroServer instance and used to interact with HydroServer's Data Management API endpoints.
|
|
11
|
-
|
|
12
|
-
:param host: The base URL or host of the HydroServer API.
|
|
13
|
-
:type host: str
|
|
14
|
-
:param username: The username for basic authentication, if required.
|
|
15
|
-
:type username: Optional[str]
|
|
16
|
-
:param password: The password for basic authentication, if required.
|
|
17
|
-
:type password: Optional[str]
|
|
18
|
-
:param apikey: The API key for authentication, if using API key authentication.
|
|
19
|
-
:type apikey: Optional[str]
|
|
20
|
-
:param api_route: The API route to use, default is 'api'.
|
|
21
|
-
:type api_route: str
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(
|
|
25
|
-
self,
|
|
26
|
-
host: str,
|
|
27
|
-
username: Optional[str] = None,
|
|
28
|
-
password: Optional[str] = None,
|
|
29
|
-
apikey: Optional[str] = None,
|
|
30
|
-
api_route: str = 'api'
|
|
31
|
-
):
|
|
32
|
-
self.host = host.strip('/')
|
|
33
|
-
self.auth = (username or '__key__', password or apikey,) if (username and password) or apikey else None
|
|
34
|
-
self.api_route = api_route.strip('/')
|
|
35
|
-
self._session = None
|
|
36
|
-
self._timeout = 60
|
|
37
|
-
self._initialize_session()
|
|
38
|
-
|
|
39
|
-
def _initialize_session(self) -> None:
|
|
40
|
-
"""
|
|
41
|
-
The _initialize_session function is used to initialize the session object.
|
|
42
|
-
|
|
43
|
-
:param self
|
|
44
|
-
:return: None
|
|
45
|
-
"""
|
|
46
|
-
|
|
47
|
-
if self._session is not None:
|
|
48
|
-
self._session.close()
|
|
49
|
-
|
|
50
|
-
self._session = requests.Session()
|
|
51
|
-
|
|
52
|
-
if self.auth and self.auth[0] == '__key__':
|
|
53
|
-
self._session.headers.update(
|
|
54
|
-
{'key': self.auth[1]}
|
|
55
|
-
)
|
|
56
|
-
elif self.auth:
|
|
57
|
-
self._session.auth = self.auth
|
|
58
|
-
|
|
59
|
-
def _request(self, method, path, *args, **kwargs) -> requests.Response:
|
|
60
|
-
"""
|
|
61
|
-
The _request function is a helper function that makes it easier to make requests to the API.
|
|
62
|
-
It takes in a method, path, and any other arguments you want to pass into the request.
|
|
63
|
-
The method argument should be one of 'get', 'post', or 'delete'. The path argument should be
|
|
64
|
-
the endpoint you are trying to reach (e.g., '/users/me'). Any additional arguments will be passed
|
|
65
|
-
into the request as-is.
|
|
66
|
-
|
|
67
|
-
:param self
|
|
68
|
-
:param method: Specify the type of request that is being made
|
|
69
|
-
:param path: Specify the path of the request
|
|
70
|
-
:return: A response object
|
|
71
|
-
"""
|
|
72
|
-
|
|
73
|
-
for attempt in range(2):
|
|
74
|
-
try:
|
|
75
|
-
response = getattr(self._session, method)(
|
|
76
|
-
f'{self.host}/{path.strip("/")}',
|
|
77
|
-
timeout=self._timeout,
|
|
78
|
-
*args, **kwargs
|
|
79
|
-
)
|
|
80
|
-
response.raise_for_status()
|
|
81
|
-
return response
|
|
82
|
-
except requests.exceptions.ConnectionError as e:
|
|
83
|
-
if attempt == 0:
|
|
84
|
-
self._initialize_session()
|
|
85
|
-
continue
|
|
86
|
-
else:
|
|
87
|
-
raise e
|
|
88
|
-
|
|
89
|
-
@property
|
|
90
|
-
def dataloaders(self):
|
|
91
|
-
"""
|
|
92
|
-
Data Loader Endpoint.
|
|
93
|
-
|
|
94
|
-
:return: An instance of DataLoaderEndpoint.
|
|
95
|
-
:rtype: DataLoaderEndpoint
|
|
96
|
-
"""
|
|
97
|
-
|
|
98
|
-
return DataLoaderEndpoint(self)
|
|
99
|
-
|
|
100
|
-
@property
|
|
101
|
-
def datasources(self):
|
|
102
|
-
"""
|
|
103
|
-
Data Source Endpoint.
|
|
104
|
-
|
|
105
|
-
:return: An instance of DataSourceEndpoint.
|
|
106
|
-
:rtype: DataSourceEndpoint
|
|
107
|
-
"""
|
|
108
|
-
|
|
109
|
-
return DataSourceEndpoint(self)
|
|
110
|
-
|
|
111
|
-
@property
|
|
112
|
-
def datastreams(self):
|
|
113
|
-
"""
|
|
114
|
-
Datastream Endpoint.
|
|
115
|
-
|
|
116
|
-
:return: An instance of DatastreamEndpoint.
|
|
117
|
-
:rtype: DatastreamEndpoint
|
|
118
|
-
"""
|
|
119
|
-
|
|
120
|
-
return DatastreamEndpoint(self)
|
|
121
|
-
|
|
122
|
-
@property
|
|
123
|
-
def observedproperties(self):
|
|
124
|
-
"""
|
|
125
|
-
Observed Property Endpoint.
|
|
126
|
-
|
|
127
|
-
:return: An instance of ObservedPropertyEndpoint.
|
|
128
|
-
:rtype: ObservedPropertyEndpoint
|
|
129
|
-
"""
|
|
130
|
-
|
|
131
|
-
return ObservedPropertyEndpoint(self)
|
|
132
|
-
|
|
133
|
-
@property
|
|
134
|
-
def processinglevels(self):
|
|
135
|
-
"""
|
|
136
|
-
Processing Level Endpoint.
|
|
137
|
-
|
|
138
|
-
:return: An instance of ProcessingLevelEndpoint.
|
|
139
|
-
:rtype: ProcessingLevelEndpoint
|
|
140
|
-
"""
|
|
141
|
-
|
|
142
|
-
return ProcessingLevelEndpoint(self)
|
|
143
|
-
|
|
144
|
-
@property
|
|
145
|
-
def resultqualifiers(self):
|
|
146
|
-
"""
|
|
147
|
-
Result Qualifier Endpoint.
|
|
148
|
-
|
|
149
|
-
:return: An instance of ResultQualifierEndpoint.
|
|
150
|
-
:rtype: ResultQualifierEndpoint
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
return ResultQualifierEndpoint(self)
|
|
154
|
-
|
|
155
|
-
@property
|
|
156
|
-
def sensors(self):
|
|
157
|
-
"""
|
|
158
|
-
Sensor Endpoint.
|
|
159
|
-
|
|
160
|
-
:return: An instance of SensorEndpoint.
|
|
161
|
-
:rtype: SensorEndpoint
|
|
162
|
-
"""
|
|
163
|
-
|
|
164
|
-
return SensorEndpoint(self)
|
|
165
|
-
|
|
166
|
-
@property
|
|
167
|
-
def things(self):
|
|
168
|
-
"""
|
|
169
|
-
Thing Endpoint.
|
|
170
|
-
|
|
171
|
-
:return: An instance of ThingEndpoint.
|
|
172
|
-
:rtype: ThingEndpoint
|
|
173
|
-
"""
|
|
174
|
-
|
|
175
|
-
return ThingEndpoint(self)
|
|
176
|
-
|
|
177
|
-
@property
|
|
178
|
-
def units(self):
|
|
179
|
-
"""
|
|
180
|
-
Unit Endpoint.
|
|
181
|
-
|
|
182
|
-
:return: An instance of UnitEndpoint.
|
|
183
|
-
:rtype: UnitEndpoint
|
|
184
|
-
"""
|
|
185
|
-
|
|
186
|
-
return UnitEndpoint(self)
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: hydroserverpy
|
|
3
|
-
Version: 0.3.0
|
|
4
|
-
Requires-Python: <4,>=3.9
|
|
5
|
-
License-File: LICENSE
|
|
6
|
-
Requires-Dist: requests >=2
|
|
7
|
-
Requires-Dist: pydantic >=2.6
|
|
8
|
-
Requires-Dist: pandas >=2.2
|
|
9
|
-
Requires-Dist: numpy >=2.0
|
|
10
|
-
Requires-Dist: pyyaml >=5
|
|
11
|
-
Requires-Dist: simplejson >=3
|
|
12
|
-
Requires-Dist: crontab >=1
|
|
13
|
-
Requires-Dist: python-dateutil >=2.8.2
|
|
14
|
-
Requires-Dist: croniter >=2.0.1
|
|
15
|
-
Requires-Dist: country-list >=1.1.0
|
|
16
|
-
Provides-Extra: docs
|
|
17
|
-
Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
|
|
18
|
-
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
hydroserverpy/__init__.py,sha256=oVxU_pSr5RZx4s5UHYYNCrjXQAP5lujlosB2a3qG260,223
|
|
2
|
-
hydroserverpy/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
hydroserverpy/core/service.py,sha256=ch6rwNM8oM3L-9phE474grofCR3QkTQ8AopkMyn9sjo,5339
|
|
4
|
-
hydroserverpy/core/endpoints/__init__.py,sha256=SpN1WLX0R8HOLHBv1cp3VZcIEiKD4BBbgFGQppdA_mw,404
|
|
5
|
-
hydroserverpy/core/endpoints/base.py,sha256=Ay0a8rucNo9x8h1MMMuMaISkBAgc9DK_kouLGtnHPjk,4925
|
|
6
|
-
hydroserverpy/core/endpoints/data_loaders.py,sha256=boUdmn9_9QDJS38nBXwKXYiX_We_rfK1OFjCU8ptQUE,3009
|
|
7
|
-
hydroserverpy/core/endpoints/data_sources.py,sha256=c9hwlFUUY-Ae84TrlB2boLjKIIhN_fzxHSYvPSb9PKA,3007
|
|
8
|
-
hydroserverpy/core/endpoints/datastreams.py,sha256=z8NX21L2qcj07Cotm5sTT3GrNEV2jS0-AjLQDRHeRq8,6899
|
|
9
|
-
hydroserverpy/core/endpoints/observed_properties.py,sha256=7_BtjsCyyGaQ1EMhlQXhWupTs85q7i85LdRLejVUb9o,3309
|
|
10
|
-
hydroserverpy/core/endpoints/processing_levels.py,sha256=pDolo_BqkSufs3w_ykRbsg-93xWME7vYIA6BAwzdT7A,3286
|
|
11
|
-
hydroserverpy/core/endpoints/result_qualifiers.py,sha256=977r3Vf6Y3kkoRcHQwTbQPSCxxeWsJkcDCPhFI30Tss,3301
|
|
12
|
-
hydroserverpy/core/endpoints/sensors.py,sha256=niF6eY8dFdfowqW_dLq9-7CPolWO__lFwElMDJTYtsM,3122
|
|
13
|
-
hydroserverpy/core/endpoints/things.py,sha256=n0nSq2AgJ7zFwAerkTtYlFvc1EzgUfHsu_nNTcVxqr0,8357
|
|
14
|
-
hydroserverpy/core/endpoints/units.py,sha256=UZKizV8ZLMCPZQ0ol5U8UON_MB80uhxL2PUwDbtQLXA,3084
|
|
15
|
-
hydroserverpy/core/schemas/__init__.py,sha256=gUFAim1jcUWAvj0IqpR8UKaCdXT1v11SmFnOzEmcwJM,353
|
|
16
|
-
hydroserverpy/core/schemas/base.py,sha256=k5ctiVXLm5A0TI-Nkz9l3oDGsq16B3yKcQgnZcJVDds,3683
|
|
17
|
-
hydroserverpy/core/schemas/data_loaders.py,sha256=BJv0-IUkgsNisuwyOooUAHaAv1DLCF5SVVnBjpfahYM,2470
|
|
18
|
-
hydroserverpy/core/schemas/data_sources.py,sha256=oearfow10p-JJ5d_3-S2IEJ4039d4SMQlVA0N4dNOH0,8058
|
|
19
|
-
hydroserverpy/core/schemas/datastreams.py,sha256=OEVc7xMVaFSHvLMyunt2g0u6xAfv5xg0fO6Uz8VjOSU,11413
|
|
20
|
-
hydroserverpy/core/schemas/observed_properties.py,sha256=1ibOAYbsf1DQAos68V8KEmvBUoS2WO73dd5MhSWCC90,1161
|
|
21
|
-
hydroserverpy/core/schemas/processing_levels.py,sha256=K4N5by5bfSD3iPcx6Jv1x-xOPxW3_gwhZcEfaqwSDmQ,867
|
|
22
|
-
hydroserverpy/core/schemas/result_qualifiers.py,sha256=ejUMPCDOq3cuq3a6j2uvQNRdVNEVQ1jJAacYv-o9NZI,722
|
|
23
|
-
hydroserverpy/core/schemas/sensors.py,sha256=8nXSEyD1kGAL2Wi76kHvjXNSgh2VFTfMgBkFP8ACsZw,1835
|
|
24
|
-
hydroserverpy/core/schemas/things.py,sha256=Pkr3bIo4VjLML7o53_R2lXwBmx0Z7aoGlvJKC9Diw60,11139
|
|
25
|
-
hydroserverpy/core/schemas/units.py,sha256=EB4HATC-C2RxPC0EpcVN--aQa6nl1O9Lj1jkpXlJ-8Y,826
|
|
26
|
-
hydroserverpy/etl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
-
hydroserverpy/etl/exceptions.py,sha256=0UY8YUlNepG0y6FfH36hJyR1bOhwYHSZIdUSSMTg7GA,314
|
|
28
|
-
hydroserverpy/etl/service.py,sha256=g-zp89KK4MDIdcTWQDNKbCg485ByAg0Ui01ooFldxhI,12414
|
|
29
|
-
hydroserverpy/quality/__init__.py,sha256=GGBMkFSXciJLYrbV-NraFrj_mXWCy_GTcy9KKrKXU4c,84
|
|
30
|
-
hydroserverpy/quality/service.py,sha256=3y6hjt1jcRcQSx9xRw37YLFBNCch488MHhn-p5nmR6E,13830
|
|
31
|
-
hydroserverpy-0.3.0.dist-info/LICENSE,sha256=xVqFxDw3QOEJukakL7gQCqIMTQ1dlSCTo6Oc1otNW80,1508
|
|
32
|
-
hydroserverpy-0.3.0.dist-info/METADATA,sha256=8n1ZsmvItJmbNl7EgTtOGE4zr-MqY4xE-H5CUMZ3zgU,488
|
|
33
|
-
hydroserverpy-0.3.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
34
|
-
hydroserverpy-0.3.0.dist-info/top_level.txt,sha256=Zf37hrncXLOYvXhgCrf5mZdeq81G9fShdE2LfYbtb7w,14
|
|
35
|
-
hydroserverpy-0.3.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
36
|
-
hydroserverpy-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|