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.

Files changed (47) hide show
  1. hydroserverpy/__init__.py +1 -1
  2. hydroserverpy/api/{main.py → client.py} +52 -22
  3. hydroserverpy/api/models/__init__.py +1 -2
  4. hydroserverpy/api/models/base.py +180 -47
  5. hydroserverpy/api/models/etl/data_archive.py +31 -59
  6. hydroserverpy/api/models/etl/data_source.py +34 -76
  7. hydroserverpy/api/models/etl/orchestration_system.py +23 -38
  8. hydroserverpy/api/models/iam/apikey.py +57 -38
  9. hydroserverpy/api/models/iam/collaborator.py +55 -19
  10. hydroserverpy/api/models/iam/role.py +32 -4
  11. hydroserverpy/api/models/iam/workspace.py +58 -86
  12. hydroserverpy/api/models/sta/datastream.py +122 -214
  13. hydroserverpy/api/models/sta/observation.py +101 -0
  14. hydroserverpy/api/models/sta/observed_property.py +18 -53
  15. hydroserverpy/api/models/sta/processing_level.py +16 -31
  16. hydroserverpy/api/models/sta/result_qualifier.py +16 -31
  17. hydroserverpy/api/models/sta/sensor.py +27 -88
  18. hydroserverpy/api/models/sta/thing.py +48 -152
  19. hydroserverpy/api/models/sta/unit.py +16 -29
  20. hydroserverpy/api/services/__init__.py +1 -0
  21. hydroserverpy/api/services/base.py +92 -76
  22. hydroserverpy/api/services/etl/data_archive.py +42 -72
  23. hydroserverpy/api/services/etl/data_source.py +42 -72
  24. hydroserverpy/api/services/etl/orchestration_system.py +25 -33
  25. hydroserverpy/api/services/iam/role.py +38 -0
  26. hydroserverpy/api/services/iam/workspace.py +96 -99
  27. hydroserverpy/api/services/sta/datastream.py +150 -211
  28. hydroserverpy/api/services/sta/observed_property.py +31 -49
  29. hydroserverpy/api/services/sta/processing_level.py +30 -36
  30. hydroserverpy/api/services/sta/result_qualifier.py +24 -34
  31. hydroserverpy/api/services/sta/sensor.py +34 -48
  32. hydroserverpy/api/services/sta/thing.py +96 -89
  33. hydroserverpy/api/services/sta/unit.py +30 -34
  34. hydroserverpy/api/utils.py +22 -0
  35. hydroserverpy/etl/extractors/base.py +3 -5
  36. hydroserverpy/etl/loaders/hydroserver_loader.py +1 -0
  37. hydroserverpy/etl/timestamp_parser.py +82 -48
  38. hydroserverpy/etl/transformers/base.py +6 -10
  39. hydroserverpy/etl_csv/hydroserver_etl_csv.py +18 -24
  40. {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/METADATA +1 -1
  41. hydroserverpy-1.3.0.dist-info/RECORD +70 -0
  42. hydroserverpy/api/http.py +0 -22
  43. hydroserverpy-1.2.0.dist-info/RECORD +0 -68
  44. {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/WHEEL +0 -0
  45. {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/licenses/LICENSE +0 -0
  46. {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/top_level.txt +0 -0
  47. {hydroserverpy-1.2.0.dist-info → hydroserverpy-1.3.0.dist-info}/zip-safe +0 -0
@@ -1,48 +1,80 @@
1
+ from functools import cached_property
1
2
  import logging
2
3
  from datetime import datetime, timedelta, timezone
3
- from typing import Union
4
+ import re
5
+ from typing import Literal, Optional, Union, get_args
6
+ from zoneinfo import ZoneInfo
4
7
  import pandas as pd
8
+ from pydantic import BaseModel, Field
9
+
10
+ TimestampFormat = Literal["ISO8601", "naive", "custom"]
11
+ ALLOWED_TIMESTAMP_FORMATS = {m.lower() for m in get_args(TimestampFormat)}
12
+ TimezoneMode = Literal["utc", "daylightSavings", "fixedOffset", "embeddedOffset"]
13
+ ALLOWED_TIMEZONE_MODES = {m.lower() for m in get_args(TimezoneMode)}
14
+
15
+
16
+ class Timestamp(BaseModel):
17
+ format: TimestampFormat
18
+ timezone_mode: TimezoneMode = Field("embeddedOffset", alias="timezoneMode")
19
+ custom_format: Optional[str] = Field(None, alias="customFormat")
20
+ timezone: Optional[str] = None
21
+ key: Optional[str] = None
5
22
 
6
23
 
7
24
  class TimestampParser:
8
- def __init__(
9
- self, timestamp_format: str = "ISO8601", timestamp_offset: str = "+0000"
10
- ):
11
- VALID_KEYS = {"utc", "iso8601", "constant"}
12
- self.timestamp_offset = timestamp_offset
13
- self.timestamp_format = timestamp_format
14
-
15
- if (
16
- self.timestamp_format.lower() not in VALID_KEYS
17
- and "%" not in self.timestamp_format
18
- ):
25
+ def __init__(self, raw: Union[Timestamp, dict]):
26
+ if isinstance(raw, dict):
27
+ self.timestamp = Timestamp.model_validate(raw)
28
+ else:
29
+ self.timestamp = raw
30
+
31
+ if self.timestamp.format.lower() not in ALLOWED_TIMESTAMP_FORMATS:
19
32
  raise ValueError(
20
- f"timestamp_format must be one of {', '.join(VALID_KEYS)} "
21
- "or a valid strftime pattern."
33
+ f"timestamp format {self.timestamp.format!r} must be one of {ALLOWED_TIMESTAMP_FORMATS}"
22
34
  )
23
35
 
24
- def parse_series(self, raw_series: pd.Series) -> pd.Series:
25
- s = raw_series.str.strip()
26
- if self.timestamp_format.lower() == "utc":
27
- parsed = pd.to_datetime(s, utc=True, errors="coerce")
28
-
29
- elif self.timestamp_format.lower() == "iso8601":
30
- parsed = pd.to_datetime(s, errors="coerce").dt.tz_convert("UTC")
31
-
32
- elif self.timestamp_format.lower() == "constant":
33
- off = self.timestamp_offset.strip()
34
- if not (len(off) == 5 and off[0] in "+-"):
35
- raise ValueError(f"Invalid timestamp_offset: {off}")
36
- sign = 1 if off[0] == "+" else -1
37
- hrs, mins = int(off[1:3]), int(off[3:5])
38
- tz = timezone(timedelta(minutes=sign * (hrs * 60 + mins)))
39
- naive = pd.to_datetime(s, errors="coerce")
40
- parsed = naive.dt.tz_localize(tz).dt.tz_convert("UTC")
36
+ self.tz_mode = self.timestamp.timezone_mode.lower()
37
+ if self.tz_mode not in ALLOWED_TIMEZONE_MODES and "%" not in self.tz_mode:
38
+ raise ValueError(
39
+ f"timezone mode {self.tz_mode} must be one of {', '.join(ALLOWED_TIMEZONE_MODES)} "
40
+ )
41
+
42
+ @cached_property
43
+ def tz(self):
44
+ if self.tz_mode == "fixedoffset":
45
+ offset = self.timestamp.timezone.strip()
46
+ if len(offset) != 5 or offset[0] not in "+-":
47
+ raise ValueError(f"Invalid timezone: {offset}")
48
+ sign = 1 if offset[0] == "+" else -1
49
+ hrs, mins = int(offset[1:3]), int(offset[3:5])
50
+ return timezone(timedelta(minutes=sign * (hrs * 60 + mins)))
51
+ if self.tz_mode == "daylightsavings":
52
+ return ZoneInfo(self.timestamp.timezone)
53
+ if self.tz_mode == "utc":
54
+ return timezone.utc
55
+
56
+ def _convert_series_to_UTC(self, s: pd.Series):
57
+ timestamp_fmt = self.timestamp.format.lower()
41
58
 
59
+ if timestamp_fmt == "iso8601":
60
+ return pd.to_datetime(s, utc=True, errors="coerce")
61
+
62
+ if timestamp_fmt == "custom":
63
+ pattern = self.timestamp.custom_format or ""
64
+ naive = pd.to_datetime(s, format=pattern, errors="coerce")
42
65
  else:
43
- parsed = pd.to_datetime(
44
- s, format=self.timestamp_format, errors="coerce"
45
- ).dt.tz_localize("UTC")
66
+ naive = pd.to_datetime(s, errors="coerce")
67
+
68
+ tz_mode = self.timestamp.timezone_mode.lower()
69
+ if tz_mode == "utc":
70
+ return pd.to_datetime(naive, utc=True, errors="coerce")
71
+
72
+ localized = naive.dt.tz_localize(self.tz)
73
+ return localized.dt.tz_convert(timezone.utc)
74
+
75
+ def parse_series(self, raw_series: pd.Series) -> pd.Series:
76
+ s = raw_series.str.strip()
77
+ parsed = self._convert_series_to_UTC(s)
46
78
 
47
79
  if parsed.isna().any():
48
80
  bad_rows = s[parsed.isna()].head(5).tolist()
@@ -53,23 +85,25 @@ class TimestampParser:
53
85
 
54
86
  return parsed
55
87
 
56
- def format(self, dt: Union[datetime, pd.Timestamp]) -> str:
88
+ def utc_to_string(self, dt: Union[datetime, pd.Timestamp]) -> str:
89
+ """
90
+ Convert a UTC datetime or pd.Timestamp to a custom string format.
91
+
92
+ Some external APIs are picky about their timestamp formats, so we need the ability to pull a
93
+ UTC timestamp from HydroServer and format it into a custom string.
94
+ """
57
95
  if isinstance(dt, pd.Timestamp):
58
96
  dt = dt.to_pydatetime()
59
97
 
60
- fmt = self.timestamp_format.lower()
61
- if fmt == "utc":
62
- return dt.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
63
-
64
- if fmt == "iso8601":
98
+ tz_format = self.timestamp.format.lower()
99
+ if tz_format == "iso8601":
65
100
  return dt.astimezone(timezone.utc).isoformat()
66
101
 
67
- if fmt == "constant":
68
- off = self.timestamp_offset.strip()
69
- sign = 1 if off[0] == "+" else -1
70
- hrs, mins = int(off[1:3]), int(off[3:5])
71
- tz = timezone(timedelta(minutes=sign * (hrs * 60 + mins)))
72
- return dt.astimezone(tz).strftime("%Y-%m-%dT%H:%M:%S")
102
+ if tz_format == "naive":
103
+ return dt.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
104
+
105
+ if tz_format == "custom":
106
+ logging.info(f"custom timestamp: ... {self.timestamp}")
107
+ return dt.astimezone(self.tz).strftime(self.timestamp.custom_format)
73
108
 
74
- # custom strftime
75
- return dt.strftime(self.timestamp_format)
109
+ raise ValueError(f"Unknown timestamp.format: {self.timestamp.format!r}")
@@ -1,24 +1,20 @@
1
1
  from abc import ABC, abstractmethod
2
2
  import logging
3
3
  from typing import Union
4
- from src.hydroserverpy.etl.timestamp_parser import TimestampParser
4
+ from hydroserverpy.etl.timestamp_parser import TimestampParser
5
+ import pandas as pd
5
6
 
6
7
 
7
8
  class Transformer(ABC):
8
9
  def __init__(self, settings: object):
9
- # timestampFormat will be the strs: 'utc', 'ISO8601', 'constant', or some custom openStrftime.
10
- # If 'constant', then the system will append the timestamp_offset to the end of it.
11
- self.timestamp_format = settings.get("timestampFormat", "ISO8601")
12
- self.timestamp_offset: str = settings.get("timestampOffset", "+0000")
13
- self.timestamp_key: Union[str, int] = settings["timestampKey"]
10
+ self.timestamp = settings["timestamp"]
11
+ self.timestamp_key: Union[str, int] = self.timestamp["key"]
14
12
 
15
13
  if isinstance(self.timestamp_key, int):
16
14
  # Users will always interact in 1-based, so if the key is a column index, convert to 0-based
17
15
  self.timestamp_key = self.timestamp_key - 1
18
16
 
19
- self.timestamp_parser = TimestampParser(
20
- self.timestamp_format, self.timestamp_offset
21
- )
17
+ self.timestamp_parser = TimestampParser(self.timestamp)
22
18
 
23
19
  @abstractmethod
24
20
  def transform(self, *args, **kwargs) -> None:
@@ -28,7 +24,7 @@ class Transformer(ABC):
28
24
  def needs_datastreams(self) -> bool:
29
25
  return False
30
26
 
31
- def standardize_dataframe(self, df, payload_mappings):
27
+ def standardize_dataframe(self, df: pd.DataFrame, payload_mappings):
32
28
  rename_map = {
33
29
  mapping["sourceIdentifier"]: mapping["targetIdentifier"]
34
30
  for mapping in payload_mappings
@@ -179,12 +179,12 @@ class HydroServerETLCSV:
179
179
  """
180
180
 
181
181
  try:
182
+ timestamp_key = (self._data_source.settings["transformer"].get("timestampKey") or
183
+ self._data_source.settings["transformer"]["timestamp"]["key"])
182
184
  self._timestamp_column_index = (
183
- row.index(self._data_source.settings["transformer"]["timestampKey"])
184
- if isinstance(
185
- self._data_source.settings["transformer"]["timestampKey"], str
186
- )
187
- else int(self._data_source.settings["transformer"]["timestampKey"]) - 1
185
+ row.index(timestamp_key)
186
+ if isinstance(timestamp_key, str)
187
+ else int(timestamp_key) - 1
188
188
  )
189
189
  if self._timestamp_column_index > len(row):
190
190
  raise ValueError
@@ -216,26 +216,24 @@ class HydroServerETLCSV:
216
216
  """
217
217
 
218
218
  try:
219
- if (
220
- self._data_source.settings["transformer"].get("timestampFormat") in ["utc", "constant", "ISO8601"]
221
- or self._data_source.settings["transformer"].get("timestampFormat")
222
- is None
223
- ):
224
- timestamp = isoparse(row[self._timestamp_column_index])
225
- else:
219
+ timestamp_format = (self._data_source.settings["transformer"].get("timestampFormat") or
220
+ self._data_source.settings["transformer"].get("timestamp", {}).get("format"))
221
+ if timestamp_format == "custom":
226
222
  timestamp = datetime.strptime(
227
- row[self._timestamp_column_index],
228
- self._data_source.settings["transformer"].get("timestampFormat"),
223
+ row[self._timestamp_column_index], timestamp_format,
229
224
  )
225
+ else:
226
+ timestamp = isoparse(row[self._timestamp_column_index])
230
227
  except ValueError as e:
231
228
  raise TimestampParsingError(str(e)) from e
232
229
 
233
230
  if timestamp.tzinfo is None:
234
- if not self._data_source.settings["transformer"].get(
231
+ timestamp_offset = self._data_source.settings["transformer"].get(
235
232
  "timestampOffset"
236
233
  ) or self._data_source.settings["transformer"].get(
237
- "timestampOffset"
238
- ).endswith(
234
+ "timestamp", {}
235
+ ).get("offset")
236
+ if not timestamp_offset or timestamp_offset.endswith(
239
237
  "0000"
240
238
  ):
241
239
  timestamp = timestamp.replace(tzinfo=timezone.utc)
@@ -243,13 +241,9 @@ class HydroServerETLCSV:
243
241
  try:
244
242
  timestamp = timestamp.replace(
245
243
  tzinfo=datetime.strptime(
246
- self._data_source.settings["transformer"].get(
247
- "timestampOffset"
248
- )[:-2]
244
+ timestamp_offset[:-2]
249
245
  + ":"
250
- + self._data_source.settings["transformer"].get(
251
- "timestampOffset"
252
- )[3:],
246
+ + timestamp_offset[3:],
253
247
  "%z",
254
248
  ).tzinfo
255
249
  )
@@ -291,7 +285,7 @@ class HydroServerETLCSV:
291
285
  [observation["phenomenon_time"], observation["result"]]
292
286
  for observation in observations
293
287
  ],
294
- columns=["timestamp", "value"],
288
+ columns=["phenomenon_time", "result"],
295
289
  )
296
290
 
297
291
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydroserverpy
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Requires-Python: <4,>=3.9
5
5
  License-File: LICENSE
6
6
  Requires-Dist: requests>=2
@@ -0,0 +1,70 @@
1
+ hydroserverpy/__init__.py,sha256=gn3x_C6Pe1Dn90uXn7yIwEhaQm5DE76MhamdMOqF2yM,220
2
+ hydroserverpy/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ hydroserverpy/api/client.py,sha256=jduKZV2cOkPVRjIjAiVYnTncMfEtW6IaCb895Y_PfiI,5697
4
+ hydroserverpy/api/utils.py,sha256=1RUglpvegBZOcu9BEExxsAzaGOyu4tdUk2JyiBEbzxI,496
5
+ hydroserverpy/api/models/__init__.py,sha256=NLq95t1oC2co5aqVYSw9Pq0RAsLHnLjNq1tsgbMepTg,773
6
+ hydroserverpy/api/models/base.py,sha256=mQZbanDg9t2GN9mOR_XOOtAfYF7AkY0fBZ6fHat6NRs,6944
7
+ hydroserverpy/api/models/etl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ hydroserverpy/api/models/etl/data_archive.py,sha256=rnmD_FQ1yjJ0KPBigylAQ3uQ6QBppJtBopJK4oCPLSo,2613
9
+ hydroserverpy/api/models/etl/data_source.py,sha256=4s5JfpF00Heir9T1oc_KAUdI3z5Jj8ce8R56KqQqm5A,3959
10
+ hydroserverpy/api/models/etl/orchestration_configuration.py,sha256=ElSrgi7ioFZJFJg6aGogW5ZZk7fA17y4p--yWwiOhZ0,1367
11
+ hydroserverpy/api/models/etl/orchestration_system.py,sha256=5wdGsXCMqHfE3--zG-3WAPAVPNMPIx99y-7UUhdCink,2060
12
+ hydroserverpy/api/models/iam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ hydroserverpy/api/models/iam/account.py,sha256=7COk_CPYFlthg1uFWTBlJESfnuqMW90TSjZoIcBb-_8,439
14
+ hydroserverpy/api/models/iam/apikey.py,sha256=Z4iXg_K056naT3ogwc5wzyNnRpxHkOCz0lk-Gim4eL8,3146
15
+ hydroserverpy/api/models/iam/collaborator.py,sha256=w1D72PsiwmdgFVNlkNV3TPjMR6lxNCHhGZMzPcPPxbA,2316
16
+ hydroserverpy/api/models/iam/role.py,sha256=zYTzMwnnpelZHP0uPg3vZqWqcpSROqrJ58bVkpFeTEQ,1092
17
+ hydroserverpy/api/models/iam/workspace.py,sha256=hB4W8b_cC9WhBmwGHX_VfDjqriniQgvc2BKz_j9Gh0U,8884
18
+ hydroserverpy/api/models/sta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ hydroserverpy/api/models/sta/datastream.py,sha256=1JILQUZAipxGLHY8zVPRQzXZTq5ktTVWK7dPcvTjjZY,8736
20
+ hydroserverpy/api/models/sta/observation.py,sha256=oIqm4I98rnN7cAVL6tcWBXluC6qIfO1h4WhwP7R9LXs,3641
21
+ hydroserverpy/api/models/sta/observed_property.py,sha256=KpeU8mn0U-e6iBQh34YewSBEC4fY88sJr30B8O6kiXQ,1204
22
+ hydroserverpy/api/models/sta/processing_level.py,sha256=OQKc3pxi6ST36O7qEmLPA6ALXpuUXW2ADhR7XX-CaBk,1080
23
+ hydroserverpy/api/models/sta/result_qualifier.py,sha256=kenPF1B11Q5aa3c7mnHcmMmSQMziWNyiYxGK1Il4Df8,1012
24
+ hydroserverpy/api/models/sta/sensor.py,sha256=rOuMZAcqgSYr-ZHm66EbnoXx_6-UZLeeQXZv59AHIAY,1559
25
+ hydroserverpy/api/models/sta/thing.py,sha256=c7nOvMcnNZ18pr9oOgArnUK4Ei8UgZjXORaaoeemTW8,4108
26
+ hydroserverpy/api/models/sta/unit.py,sha256=H_0HyE5-ni1lglaORSaaxF0c6ZreroeQgN4JcMynkTQ,1094
27
+ hydroserverpy/api/services/__init__.py,sha256=Nb7rc1Zt8kpRElgFdWPdcyUDrtm7XdJDgzes90EzNKQ,566
28
+ hydroserverpy/api/services/base.py,sha256=f7CoQ1m-pdgVwqJsdvE7vcannw-3i7yJgBMI4eHZxAQ,3725
29
+ hydroserverpy/api/services/etl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ hydroserverpy/api/services/etl/data_archive.py,sha256=-Pmv9EqNJncVX3gPDIeNM4TsR6fHgOIjmMGt9fGOeYg,5842
31
+ hydroserverpy/api/services/etl/data_source.py,sha256=xR_GQA7IRi-2bMrF6m_kWSmx2xi3knH-GWbGTA3LoQs,5831
32
+ hydroserverpy/api/services/etl/orchestration_system.py,sha256=Otj_DiFpFBQzSc4Ei7LxneBf3VPnodI0pqoQM2BldcM,1935
33
+ hydroserverpy/api/services/iam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ hydroserverpy/api/services/iam/role.py,sha256=PV0odC_lL9kV3ggrTjAUEMTo0WNUzv4AeMHNAXlkbN8,1137
35
+ hydroserverpy/api/services/iam/workspace.py,sha256=V4ter_XJQocdXB-11IRdL5jzVmXdtOHlbAuqw42bEks,7995
36
+ hydroserverpy/api/services/sta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ hydroserverpy/api/services/sta/datastream.py,sha256=Cnse8etWeWmRF3g5NG4Wmok0_11ZVq46p269QX2yhJ4,11450
38
+ hydroserverpy/api/services/sta/observed_property.py,sha256=hKoTXRhoJSveR7S9KuokUowadhS3b1VFE-VqCnMRbvU,2516
39
+ hydroserverpy/api/services/sta/processing_level.py,sha256=d5ReGxX193NsYW18k1RWPPIBoEsDPc6LVerDAD_UBvs,2175
40
+ hydroserverpy/api/services/sta/result_qualifier.py,sha256=gkgofUqzGXgdkyAvK9RW_dyTn1MPxpd99jdcn7zpWHM,1783
41
+ hydroserverpy/api/services/sta/sensor.py,sha256=SmrIFNHD_vrlnbZvzsv0Wf0Pexk2oDWQ28LtWdj2kao,3274
42
+ hydroserverpy/api/services/sta/thing.py,sha256=Hyo3zTghSs7IIdsOGRu35i9w-aGOYlK9bl2AnmU4bBs,6666
43
+ hydroserverpy/api/services/sta/unit.py,sha256=NFToSAIGTwDfwYWe8Q-I_f5xsw_GYzFEkMnhSJ-ChvE,2178
44
+ hydroserverpy/etl/__init__.py,sha256=qK2m4LZl8czR3VE8SxrlipSy5tLGLNB60lxD7dD0GjU,659
45
+ hydroserverpy/etl/hydroserver_etl.py,sha256=FSdvM3T7QHEWWulWRT8t-FMHSxAGB4GvleUXtSk5IWc,1507
46
+ hydroserverpy/etl/timestamp_parser.py,sha256=MA_a0qPExbIQGt-ju7w6WflVDMzigW1LKUFCJ_jhkp4,4218
47
+ hydroserverpy/etl/types.py,sha256=4PY3CM-uoXIsf2lhcqtLC6HaRGXe7HKGDU22R8-H35c,135
48
+ hydroserverpy/etl/extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ hydroserverpy/etl/extractors/base.py,sha256=mK8WotEcG-4cHIW3ExS03wxyKtXPzcDhmo8S_5CGnek,1989
50
+ hydroserverpy/etl/extractors/ftp_extractor.py,sha256=5LwvHuvLk6LwRSVyE9EkV3DPgVlAvRrOBpl1a8B7dLg,1387
51
+ hydroserverpy/etl/extractors/http_extractor.py,sha256=WxWyg-GLyr6Rb-2uCFniWe6Nmk71x-frmxgEYTr9juU,814
52
+ hydroserverpy/etl/extractors/local_file_extractor.py,sha256=WZ4xIg5FiJ5GbVuR71Uj9tw_vVyzGYeweWctKscUSW0,563
53
+ hydroserverpy/etl/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ hydroserverpy/etl/loaders/base.py,sha256=q3pTp8NqZUYF1IxwKp7TOA5b4HuJkhz3FD9tIqpL7iM,273
55
+ hydroserverpy/etl/loaders/hydroserver_loader.py,sha256=N4zu_PefOwMr-NoFvq0g57VumYpNtD6o76oqhmF35ts,2545
56
+ hydroserverpy/etl/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ hydroserverpy/etl/transformers/base.py,sha256=BtRNQItt6VY9r1TBMHByOTzOB1rY1QdY8ijqCgl0riI,2259
58
+ hydroserverpy/etl/transformers/csv_transformer.py,sha256=0kWfRKPwiGxCNZ87Q4SiBlfM3PuKL6upc1ljphBY89o,2891
59
+ hydroserverpy/etl/transformers/json_transformer.py,sha256=R7tSyDB4Wn1snP75ctbEDMaMCdjyhPnMzN_W2VV3Mv4,1506
60
+ hydroserverpy/etl_csv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ hydroserverpy/etl_csv/exceptions.py,sha256=0UY8YUlNepG0y6FfH36hJyR1bOhwYHSZIdUSSMTg7GA,314
62
+ hydroserverpy/etl_csv/hydroserver_etl_csv.py,sha256=uco-FFOPk8oA4R4iWLEtcdKUT6EWa7r5h1_BWPjANjo,14359
63
+ hydroserverpy/quality/__init__.py,sha256=GGBMkFSXciJLYrbV-NraFrj_mXWCy_GTcy9KKrKXU4c,84
64
+ hydroserverpy/quality/service.py,sha256=U02UfLKVmFvr5ySiH0n0JYzUIabq5uprrHIiwcqBlqY,13879
65
+ hydroserverpy-1.3.0.dist-info/licenses/LICENSE,sha256=xVqFxDw3QOEJukakL7gQCqIMTQ1dlSCTo6Oc1otNW80,1508
66
+ hydroserverpy-1.3.0.dist-info/METADATA,sha256=YgQl306tp2koj5QbOhyyvjlcov5o7snr8IVkv_OFcdk,530
67
+ hydroserverpy-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
+ hydroserverpy-1.3.0.dist-info/top_level.txt,sha256=Zf37hrncXLOYvXhgCrf5mZdeq81G9fShdE2LfYbtb7w,14
69
+ hydroserverpy-1.3.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
70
+ hydroserverpy-1.3.0.dist-info/RECORD,,
hydroserverpy/api/http.py DELETED
@@ -1,22 +0,0 @@
1
- import json
2
- from requests import HTTPError
3
-
4
-
5
- def raise_for_hs_status(response):
6
- try:
7
- response.raise_for_status()
8
- except HTTPError as e:
9
- try:
10
- http_error_msg = (
11
- f"{response.status_code} Client Error: "
12
- f"{str(json.loads(response.content).get('detail'))}"
13
- )
14
- except (
15
- ValueError,
16
- TypeError,
17
- ):
18
- http_error_msg = e
19
- if 400 <= response.status_code < 500:
20
- raise HTTPError(http_error_msg, response=response)
21
- else:
22
- raise HTTPError(str(e), response=response)
@@ -1,68 +0,0 @@
1
- hydroserverpy/__init__.py,sha256=FgaGFyhCjwmpJYEKNzOZxvfRx2neWMaOybj1z02_VSE,218
2
- hydroserverpy/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- hydroserverpy/api/http.py,sha256=C5DgvEeiu54RaL-9oouFPSKosC8Uy5Qdwm5hYh2Ps-s,620
4
- hydroserverpy/api/main.py,sha256=r-KD1Xyufzyt4YvRRhZbAngrj5h9yWLXiznx1Yda_8E,4766
5
- hydroserverpy/api/models/__init__.py,sha256=buOhJ2Bf9yI0GftSyulpR74A5IhyyKJrXY1xANicohw,744
6
- hydroserverpy/api/models/base.py,sha256=dc2tfMSgizymxAAOVURfy7Jzeh6xIiiq7hfWZI7l1_Q,2280
7
- hydroserverpy/api/models/etl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- hydroserverpy/api/models/etl/data_archive.py,sha256=u-gpvUsaWaw0kyF3bPMm2e55Jx2yhvSV9ufXXaNtrTc,3429
9
- hydroserverpy/api/models/etl/data_source.py,sha256=th0DzyuFA5JM4nq_DtkI8GsPHMyy9zr3t6t5QWJXIao,5541
10
- hydroserverpy/api/models/etl/orchestration_configuration.py,sha256=ElSrgi7ioFZJFJg6aGogW5ZZk7fA17y4p--yWwiOhZ0,1367
11
- hydroserverpy/api/models/etl/orchestration_system.py,sha256=25En2G0z1gQzN-RW3UlrEGgkC952QDW21oYnawCX8hY,2357
12
- hydroserverpy/api/models/iam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- hydroserverpy/api/models/iam/account.py,sha256=7COk_CPYFlthg1uFWTBlJESfnuqMW90TSjZoIcBb-_8,439
14
- hydroserverpy/api/models/iam/apikey.py,sha256=FLppIWqoBlFYqumecF1cKVm4R2-ZacyKrpObMW1g50s,2465
15
- hydroserverpy/api/models/iam/collaborator.py,sha256=jp661DKDCwk8c8HFPAV-YVhEc80F5eGDKaSHmH62Q8Q,1007
16
- hydroserverpy/api/models/iam/role.py,sha256=8FVTj_1QwtPF9tk7baliMVg000kjc5N8oP6eYo8vTDY,275
17
- hydroserverpy/api/models/iam/workspace.py,sha256=rlRL52fAQrCZqmqMnCUNvBIWrlUGoYtQd16zCg-esWU,9630
18
- hydroserverpy/api/models/sta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- hydroserverpy/api/models/sta/datastream.py,sha256=vRjgwAKaoBJEtgUXrZjIS-VuIZsCilm7FRwbvLS8Y8o,11186
20
- hydroserverpy/api/models/sta/observed_property.py,sha256=ThTg8aPMHPxbk9Hzpxw3AwM16gE1xvYpRK8UkiOdGeA,2180
21
- hydroserverpy/api/models/sta/processing_level.py,sha256=y5_0wX7QGXgswvukXJtbpOiTCZ9pI8E08DXaTSUHakg,1470
22
- hydroserverpy/api/models/sta/result_qualifier.py,sha256=IJcY04KjP9e2D-jPzUJjH2PC-JvDNCjbi5LKkTVSwgw,1416
23
- hydroserverpy/api/models/sta/sensor.py,sha256=TD9R1Uwcu1t9tRQBfk0crsSJmV5UN_9kH9Ye9b7lDJc,3055
24
- hydroserverpy/api/models/sta/thing.py,sha256=o4Xn_Luy2IEOCBjXTbek7GvPoXZyKA0dhfzoFM6nfTs,6357
25
- hydroserverpy/api/models/sta/unit.py,sha256=Pbxxp9hZErsrYImIb8-1HVnZAsJopE3US_AplSQWOJQ,1398
26
- hydroserverpy/api/services/__init__.py,sha256=B0kGyn8_HlIBf9deU6qLocQTbxe59qestUZtLU9CeXk,532
27
- hydroserverpy/api/services/base.py,sha256=zLhRDlf4h4zBXHpicKMI7xgQrXN_wHvvthvQzYNyj2E,3415
28
- hydroserverpy/api/services/etl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- hydroserverpy/api/services/etl/data_archive.py,sha256=hlNJOHJSZ1kV2n2xivWIBtT1Eovj65PDbwpAyXnlZsM,6506
30
- hydroserverpy/api/services/etl/data_source.py,sha256=DCgTyh8lF2iwh4uszePFg9UupXxJCN7Ww9Ut1MQKHis,6491
31
- hydroserverpy/api/services/etl/orchestration_system.py,sha256=JFuSJJUq4JJUt8KlZ-Ga0ktyQIe2U0Sa7ogd4oLjex4,2166
32
- hydroserverpy/api/services/iam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- hydroserverpy/api/services/iam/workspace.py,sha256=Y6IituULcr1jrXMJvLOb4czS2U_AmF-132jEUDN4_4Y,8401
34
- hydroserverpy/api/services/sta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- hydroserverpy/api/services/sta/datastream.py,sha256=i5JtjkktEjkdvuWif7gNY7aNqIQwskUD1vSkybfilfs,12458
36
- hydroserverpy/api/services/sta/observed_property.py,sha256=nRlqBldJpXlj8VOZ4EwNOs4ZgmBw5w-EqAChfM3Z0Z0,2908
37
- hydroserverpy/api/services/sta/processing_level.py,sha256=Oupfeww2XgT83AwR5Spt91VjZK6MG0XIl11Et9fRjA0,2255
38
- hydroserverpy/api/services/sta/result_qualifier.py,sha256=XG5Ng3xdFT-l3Ktkuq23Cty1RfmepBO7EQ9gPzidZuA,2069
39
- hydroserverpy/api/services/sta/sensor.py,sha256=SbDhLjlOaM2ypLDfXmQVinj7eHHJ_fHxjTD68dM2pQI,3473
40
- hydroserverpy/api/services/sta/thing.py,sha256=QL7IBwHHIgDFBpXnQF-LOUpxiRlm_HFWB1qqe7Iqq9s,5972
41
- hydroserverpy/api/services/sta/unit.py,sha256=ksO-3g___9pPNBNbgM0jyDf1NeBqX79fjeJjCshrftY,2138
42
- hydroserverpy/etl/__init__.py,sha256=qK2m4LZl8czR3VE8SxrlipSy5tLGLNB60lxD7dD0GjU,659
43
- hydroserverpy/etl/hydroserver_etl.py,sha256=FSdvM3T7QHEWWulWRT8t-FMHSxAGB4GvleUXtSk5IWc,1507
44
- hydroserverpy/etl/timestamp_parser.py,sha256=WYI8ARCSqE-TmYsOWk-iV-O0OBiIaA04v0DttCnskc4,2767
45
- hydroserverpy/etl/types.py,sha256=4PY3CM-uoXIsf2lhcqtLC6HaRGXe7HKGDU22R8-H35c,135
46
- hydroserverpy/etl/extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- hydroserverpy/etl/extractors/base.py,sha256=Y53NhCktI00z7XIU9ZAyyCmNt1WKHdQhag5sPN6-XV4,2102
48
- hydroserverpy/etl/extractors/ftp_extractor.py,sha256=5LwvHuvLk6LwRSVyE9EkV3DPgVlAvRrOBpl1a8B7dLg,1387
49
- hydroserverpy/etl/extractors/http_extractor.py,sha256=WxWyg-GLyr6Rb-2uCFniWe6Nmk71x-frmxgEYTr9juU,814
50
- hydroserverpy/etl/extractors/local_file_extractor.py,sha256=WZ4xIg5FiJ5GbVuR71Uj9tw_vVyzGYeweWctKscUSW0,563
51
- hydroserverpy/etl/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- hydroserverpy/etl/loaders/base.py,sha256=q3pTp8NqZUYF1IxwKp7TOA5b4HuJkhz3FD9tIqpL7iM,273
53
- hydroserverpy/etl/loaders/hydroserver_loader.py,sha256=asqG_atwnj22xJI5CWbr1SnEHBZm0Kt0PlJ3hk8EJrM,2457
54
- hydroserverpy/etl/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- hydroserverpy/etl/transformers/base.py,sha256=a2_R6Bb6A9JI48B06x-0LB2YJB4qvZE6ChuAR3wjcwY,2585
56
- hydroserverpy/etl/transformers/csv_transformer.py,sha256=0kWfRKPwiGxCNZ87Q4SiBlfM3PuKL6upc1ljphBY89o,2891
57
- hydroserverpy/etl/transformers/json_transformer.py,sha256=R7tSyDB4Wn1snP75ctbEDMaMCdjyhPnMzN_W2VV3Mv4,1506
58
- hydroserverpy/etl_csv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- hydroserverpy/etl_csv/exceptions.py,sha256=0UY8YUlNepG0y6FfH36hJyR1bOhwYHSZIdUSSMTg7GA,314
60
- hydroserverpy/etl_csv/hydroserver_etl_csv.py,sha256=0ueBphEaAAlsb0cn71Ihgd5zOD8Zdu4Ts_yGwvXW53M,14544
61
- hydroserverpy/quality/__init__.py,sha256=GGBMkFSXciJLYrbV-NraFrj_mXWCy_GTcy9KKrKXU4c,84
62
- hydroserverpy/quality/service.py,sha256=U02UfLKVmFvr5ySiH0n0JYzUIabq5uprrHIiwcqBlqY,13879
63
- hydroserverpy-1.2.0.dist-info/licenses/LICENSE,sha256=xVqFxDw3QOEJukakL7gQCqIMTQ1dlSCTo6Oc1otNW80,1508
64
- hydroserverpy-1.2.0.dist-info/METADATA,sha256=vMQFDFTg04VH7-UNWxbrGPFwp-ATawsyzBEjHHc3GbY,530
65
- hydroserverpy-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
66
- hydroserverpy-1.2.0.dist-info/top_level.txt,sha256=Zf37hrncXLOYvXhgCrf5mZdeq81G9fShdE2LfYbtb7w,14
67
- hydroserverpy-1.2.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
68
- hydroserverpy-1.2.0.dist-info/RECORD,,