hydroserverpy 0.2.5__py3-none-any.whl → 0.4.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 (77) hide show
  1. hydroserverpy/__init__.py +6 -15
  2. hydroserverpy/core/endpoints/__init__.py +9 -0
  3. hydroserverpy/core/endpoints/base.py +146 -0
  4. hydroserverpy/core/endpoints/data_loaders.py +93 -0
  5. hydroserverpy/core/endpoints/data_sources.py +93 -0
  6. hydroserverpy/core/endpoints/datastreams.py +225 -0
  7. hydroserverpy/core/endpoints/observed_properties.py +111 -0
  8. hydroserverpy/core/endpoints/processing_levels.py +111 -0
  9. hydroserverpy/core/endpoints/result_qualifiers.py +111 -0
  10. hydroserverpy/core/endpoints/sensors.py +111 -0
  11. hydroserverpy/core/endpoints/things.py +261 -0
  12. hydroserverpy/core/endpoints/units.py +111 -0
  13. hydroserverpy/{components → core/schemas}/__init__.py +1 -2
  14. hydroserverpy/core/schemas/base.py +124 -0
  15. hydroserverpy/core/schemas/data_loaders.py +73 -0
  16. hydroserverpy/core/schemas/data_sources.py +223 -0
  17. hydroserverpy/core/schemas/datastreams.py +330 -0
  18. hydroserverpy/core/schemas/observed_properties.py +43 -0
  19. hydroserverpy/core/schemas/processing_levels.py +31 -0
  20. hydroserverpy/core/schemas/result_qualifiers.py +26 -0
  21. hydroserverpy/core/schemas/sensors.py +68 -0
  22. hydroserverpy/core/schemas/things.py +346 -0
  23. hydroserverpy/core/schemas/units.py +29 -0
  24. hydroserverpy/core/service.py +200 -0
  25. hydroserverpy/etl/__init__.py +21 -0
  26. hydroserverpy/etl/extractors/__init__.py +0 -0
  27. hydroserverpy/etl/extractors/base.py +13 -0
  28. hydroserverpy/etl/extractors/ftp_extractor.py +50 -0
  29. hydroserverpy/etl/extractors/http_extractor.py +84 -0
  30. hydroserverpy/etl/extractors/local_file_extractor.py +25 -0
  31. hydroserverpy/etl/hydroserver_etl.py +40 -0
  32. hydroserverpy/etl/loaders/__init__.py +0 -0
  33. hydroserverpy/etl/loaders/base.py +13 -0
  34. hydroserverpy/etl/loaders/hydroserver_loader.py +68 -0
  35. hydroserverpy/etl/transformers/__init__.py +0 -0
  36. hydroserverpy/etl/transformers/base.py +52 -0
  37. hydroserverpy/etl/transformers/csv_transformer.py +88 -0
  38. hydroserverpy/etl/transformers/json_transformer.py +62 -0
  39. hydroserverpy/etl/types.py +7 -0
  40. hydroserverpy/etl_csv/__init__.py +0 -0
  41. hydroserverpy/{etl.py → etl_csv/hydroserver_etl_csv.py} +118 -95
  42. hydroserverpy/quality/__init__.py +1 -0
  43. hydroserverpy/quality/service.py +405 -0
  44. hydroserverpy-0.4.0.dist-info/METADATA +18 -0
  45. hydroserverpy-0.4.0.dist-info/RECORD +51 -0
  46. {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/WHEEL +1 -1
  47. hydroserverpy/components/data_loaders.py +0 -67
  48. hydroserverpy/components/data_sources.py +0 -98
  49. hydroserverpy/components/datastreams.py +0 -47
  50. hydroserverpy/components/observed_properties.py +0 -48
  51. hydroserverpy/components/processing_levels.py +0 -48
  52. hydroserverpy/components/result_qualifiers.py +0 -48
  53. hydroserverpy/components/sensors.py +0 -48
  54. hydroserverpy/components/things.py +0 -48
  55. hydroserverpy/components/units.py +0 -48
  56. hydroserverpy/components/users.py +0 -28
  57. hydroserverpy/main.py +0 -62
  58. hydroserverpy/models.py +0 -218
  59. hydroserverpy/schemas/data_loaders.py +0 -27
  60. hydroserverpy/schemas/data_sources.py +0 -58
  61. hydroserverpy/schemas/datastreams.py +0 -56
  62. hydroserverpy/schemas/observed_properties.py +0 -33
  63. hydroserverpy/schemas/processing_levels.py +0 -33
  64. hydroserverpy/schemas/result_qualifiers.py +0 -32
  65. hydroserverpy/schemas/sensors.py +0 -39
  66. hydroserverpy/schemas/things.py +0 -107
  67. hydroserverpy/schemas/units.py +0 -32
  68. hydroserverpy/schemas/users.py +0 -28
  69. hydroserverpy/service.py +0 -170
  70. hydroserverpy/utils.py +0 -37
  71. hydroserverpy-0.2.5.dist-info/METADATA +0 -15
  72. hydroserverpy-0.2.5.dist-info/RECORD +0 -35
  73. /hydroserverpy/{schemas → core}/__init__.py +0 -0
  74. /hydroserverpy/{exceptions.py → etl_csv/exceptions.py} +0 -0
  75. {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/LICENSE +0 -0
  76. {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/top_level.txt +0 -0
  77. {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/zip-safe +0 -0
@@ -1,47 +0,0 @@
1
- from uuid import UUID
2
- from typing import List
3
- from hydroserverpy.schemas.datastreams import DatastreamGetResponse, DatastreamPostBody, DatastreamPatchBody
4
-
5
-
6
- class Datastream:
7
-
8
- def __init__(self, service):
9
- self._service = service
10
-
11
- def list(self):
12
-
13
- return self._service.get(
14
- 'datastreams',
15
- response_schema=List[DatastreamGetResponse]
16
- )
17
-
18
- def get(self, datastream_id: str):
19
-
20
- return self._service.get(
21
- f'datastreams/{datastream_id}',
22
- response_schema=DatastreamGetResponse
23
- )
24
-
25
- def create(self, datastream_body: DatastreamPostBody):
26
-
27
- return self._service.post(
28
- f'datastreams',
29
- headers={'Content-type': 'application/json'},
30
- data=datastream_body.json(by_alias=True),
31
- response_schema=DatastreamGetResponse
32
- )
33
-
34
- def update(self, datastream_id: UUID, datastream_body: DatastreamPatchBody):
35
-
36
- return self._service.patch(
37
- f'datastreams/{str(datastream_id)}',
38
- headers={'Content-type': 'application/json'},
39
- data=datastream_body.json(exclude_unset=True, by_alias=True),
40
- response_schema=DatastreamGetResponse
41
- )
42
-
43
- def delete(self, datastream_id: UUID):
44
-
45
- return self._service.delete(
46
- f'datastreams/{str(datastream_id)}'
47
- )
@@ -1,48 +0,0 @@
1
- from typing import List
2
- from uuid import UUID
3
- from hydroserverpy.schemas.observed_properties import ObservedPropertyGetResponse, ObservedPropertyPostBody, \
4
- ObservedPropertyPatchBody
5
-
6
-
7
- class ObservedProperty:
8
-
9
- def __init__(self, service):
10
- self._service = service
11
-
12
- def list(self):
13
-
14
- return self._service.get(
15
- 'observed-properties',
16
- response_schema=List[ObservedPropertyGetResponse]
17
- )
18
-
19
- def get(self, observed_property_id: UUID):
20
-
21
- return self._service.get(
22
- f'observed-properties/{observed_property_id}',
23
- response_schema=ObservedPropertyGetResponse
24
- )
25
-
26
- def create(self, observed_property_body: ObservedPropertyPostBody):
27
-
28
- return self._service.post(
29
- f'observed-properties',
30
- headers={'Content-type': 'application/json'},
31
- data=observed_property_body.json(by_alias=True),
32
- response_schema=ObservedPropertyGetResponse
33
- )
34
-
35
- def update(self, observed_property_id: UUID, observed_property_body: ObservedPropertyPatchBody):
36
-
37
- return self._service.patch(
38
- f'observed-properties/{str(observed_property_id)}',
39
- headers={'Content-type': 'application/json'},
40
- data=observed_property_body.json(exclude_unset=True, by_alias=True),
41
- response_schema=ObservedPropertyGetResponse
42
- )
43
-
44
- def delete(self, observed_property_id: UUID):
45
-
46
- return self._service.delete(
47
- f'observed-properties/{str(observed_property_id)}'
48
- )
@@ -1,48 +0,0 @@
1
- from typing import List
2
- from uuid import UUID
3
- from hydroserverpy.schemas.processing_levels import ProcessingLevelGetResponse, ProcessingLevelPostBody, \
4
- ProcessingLevelPatchBody
5
-
6
-
7
- class ProcessingLevel:
8
-
9
- def __init__(self, service):
10
- self._service = service
11
-
12
- def list(self):
13
-
14
- return self._service.get(
15
- 'processing-levels',
16
- response_schema=List[ProcessingLevelGetResponse]
17
- )
18
-
19
- def get(self, processing_level_id: str):
20
-
21
- return self._service.get(
22
- f'processing-levels/{processing_level_id}',
23
- response_schema=ProcessingLevelGetResponse
24
- )
25
-
26
- def create(self, processing_level_body: ProcessingLevelPostBody):
27
-
28
- return self._service.post(
29
- f'processing-levels',
30
- headers={'Content-type': 'application/json'},
31
- data=processing_level_body.json(by_alias=True),
32
- response_schema=ProcessingLevelGetResponse
33
- )
34
-
35
- def update(self, processing_level_id: UUID, processing_level_body: ProcessingLevelPatchBody):
36
-
37
- return self._service.patch(
38
- f'processing-levels/{str(processing_level_id)}',
39
- headers={'Content-type': 'application/json'},
40
- data=processing_level_body.json(exclude_unset=True, by_alias=True),
41
- response_schema=ProcessingLevelGetResponse
42
- )
43
-
44
- def delete(self, processing_level_id: UUID):
45
-
46
- return self._service.delete(
47
- f'processing-levels/{str(processing_level_id)}'
48
- )
@@ -1,48 +0,0 @@
1
- from typing import List
2
- from uuid import UUID
3
- from hydroserverpy.schemas.result_qualifiers import ResultQualifierGetResponse, ResultQualifierPostBody, \
4
- ResultQualifierPatchBody
5
-
6
-
7
- class ResultQualifier:
8
-
9
- def __init__(self, service):
10
- self._service = service
11
-
12
- def list(self):
13
-
14
- return self._service.get(
15
- 'result-qualifiers',
16
- response_schema=List[ResultQualifierGetResponse]
17
- )
18
-
19
- def get(self, result_qualifier_id: str):
20
-
21
- return self._service.get(
22
- f'result-qualifiers/{result_qualifier_id}',
23
- response_schema=ResultQualifierGetResponse
24
- )
25
-
26
- def create(self, result_qualifier_body: ResultQualifierPostBody):
27
-
28
- return self._service.post(
29
- f'result-qualifiers',
30
- headers={'Content-type': 'application/json'},
31
- data=result_qualifier_body.json(by_alias=True),
32
- response_schema=ResultQualifierGetResponse
33
- )
34
-
35
- def update(self, result_qualifier_id: UUID, result_qualifier_body: ResultQualifierPatchBody):
36
-
37
- return self._service.patch(
38
- f'result-qualifiers/{str(result_qualifier_id)}',
39
- headers={'Content-type': 'application/json'},
40
- data=result_qualifier_body.json(exclude_unset=True, by_alias=True),
41
- response_schema=ResultQualifierGetResponse
42
- )
43
-
44
- def delete(self, result_qualifier_id: UUID):
45
-
46
- return self._service.delete(
47
- f'result-qualifiers/{str(result_qualifier_id)}'
48
- )
@@ -1,48 +0,0 @@
1
- from typing import List
2
- from uuid import UUID
3
- from hydroserverpy.schemas.sensors import SensorGetResponse, SensorPostBody, \
4
- SensorPatchBody
5
-
6
-
7
- class Sensor:
8
-
9
- def __init__(self, service):
10
- self._service = service
11
-
12
- def list(self):
13
-
14
- return self._service.get(
15
- 'sensors',
16
- response_schema=List[SensorGetResponse]
17
- )
18
-
19
- def get(self, sensor_id: str):
20
-
21
- return self._service.get(
22
- f'sensors/{sensor_id}',
23
- response_schema=SensorGetResponse
24
- )
25
-
26
- def create(self, sensor_body: SensorPostBody):
27
-
28
- return self._service.post(
29
- f'sensors',
30
- headers={'Content-type': 'application/json'},
31
- data=sensor_body.json(by_alias=True),
32
- response_schema=SensorGetResponse
33
- )
34
-
35
- def update(self, sensor_id: UUID, sensor_body: SensorPatchBody):
36
-
37
- return self._service.patch(
38
- f'sensors/{str(sensor_id)}',
39
- headers={'Content-type': 'application/json'},
40
- data=sensor_body.json(exclude_unset=True, by_alias=True),
41
- response_schema=SensorGetResponse
42
- )
43
-
44
- def delete(self, sensor_id: UUID):
45
-
46
- return self._service.delete(
47
- f'sensors/{str(sensor_id)}'
48
- )
@@ -1,48 +0,0 @@
1
- from typing import List
2
- from uuid import UUID
3
- from hydroserverpy.schemas.things import ThingGetResponse, ThingPostBody, \
4
- ThingPatchBody
5
-
6
-
7
- class Thing:
8
-
9
- def __init__(self, service):
10
- self._service = service
11
-
12
- def list(self):
13
-
14
- return self._service.get(
15
- 'things',
16
- response_schema=List[ThingGetResponse]
17
- )
18
-
19
- def get(self, thing_id: str):
20
-
21
- return self._service.get(
22
- f'things/{thing_id}',
23
- response_schema=ThingGetResponse
24
- )
25
-
26
- def create(self, thing_body: ThingPostBody):
27
-
28
- return self._service.post(
29
- f'things',
30
- headers={'Content-type': 'application/json'},
31
- data=thing_body.json(by_alias=True),
32
- response_schema=ThingGetResponse
33
- )
34
-
35
- def update(self, thing_id: UUID, thing_body: ThingPatchBody):
36
-
37
- return self._service.patch(
38
- f'things/{str(thing_id)}',
39
- headers={'Content-type': 'application/json'},
40
- data=thing_body.json(exclude_unset=True, by_alias=True),
41
- response_schema=ThingGetResponse
42
- )
43
-
44
- def delete(self, thing_id: UUID):
45
-
46
- return self._service.delete(
47
- f'things/{str(thing_id)}'
48
- )
@@ -1,48 +0,0 @@
1
- from typing import List
2
- from uuid import UUID
3
- from hydroserverpy.schemas.units import UnitGetResponse, UnitPostBody, \
4
- UnitPatchBody
5
-
6
-
7
- class Unit:
8
-
9
- def __init__(self, service):
10
- self._service = service
11
-
12
- def list(self):
13
-
14
- return self._service.get(
15
- 'units',
16
- response_schema=List[UnitGetResponse]
17
- )
18
-
19
- def get(self, unit_id: str):
20
-
21
- return self._service.get(
22
- f'units/{unit_id}',
23
- response_schema=UnitGetResponse
24
- )
25
-
26
- def create(self, unit_body: UnitPostBody):
27
-
28
- return self._service.post(
29
- f'units',
30
- headers={'Content-type': 'application/json'},
31
- data=unit_body.json(by_alias=True),
32
- response_schema=UnitGetResponse
33
- )
34
-
35
- def update(self, unit_id: UUID, unit_body: UnitPatchBody):
36
-
37
- return self._service.patch(
38
- f'units/{str(unit_id)}',
39
- headers={'Content-type': 'application/json'},
40
- data=unit_body.json(exclude_unset=True, by_alias=True),
41
- response_schema=UnitGetResponse
42
- )
43
-
44
- def delete(self, unit_id: UUID):
45
-
46
- return self._service.delete(
47
- f'units/{str(unit_id)}'
48
- )
@@ -1,28 +0,0 @@
1
- from pydantic import BaseModel, Field
2
- from typing import Optional
3
-
4
-
5
- class Organization(BaseModel):
6
- code: str
7
- name: str
8
- description: Optional[str]
9
- type: str
10
- link: Optional[str]
11
-
12
-
13
- class UserResponse(BaseModel):
14
- email: str
15
- first_name: str = Field(..., alias='firstName')
16
- last_name: str = Field(..., alias='lastName')
17
- middle_name: Optional[str] = Field(None, alias='middleName')
18
- phone: Optional[str]
19
- address: Optional[str]
20
- type: str
21
- link: Optional[str]
22
- organization: Optional[Organization]
23
-
24
-
25
- class User:
26
-
27
- def __init__(self, service):
28
- self._service = service
hydroserverpy/main.py DELETED
@@ -1,62 +0,0 @@
1
- from typing import Optional, Union, Tuple
2
- from pydantic import AnyHttpUrl
3
- from hydroserverpy.service import BaseService
4
- from hydroserverpy.components import DataLoader, DataSource, Datastream, ObservedProperty, ProcessingLevel, \
5
- ResultQualifier, Sensor, Thing, Unit, User
6
-
7
-
8
- class HydroServer(BaseService):
9
-
10
- def __init__(
11
- self,
12
- host: Union[AnyHttpUrl, str],
13
- auth: Optional[Tuple[str, str]] = None,
14
- sta_path: str = 'api/sensorthings/v1.1',
15
- api_path: str = 'api/data'
16
- ):
17
- super().__init__(
18
- host=host,
19
- auth=auth,
20
- sta_path=sta_path,
21
- api_path=api_path
22
- )
23
-
24
- @property
25
- def data_loaders(self):
26
- return DataLoader(self)
27
-
28
- @property
29
- def data_sources(self):
30
- return DataSource(self)
31
-
32
- @property
33
- def datastreams(self):
34
- return Datastream(self)
35
-
36
- @property
37
- def observed_properties(self):
38
- return ObservedProperty(self)
39
-
40
- @property
41
- def processing_levels(self):
42
- return ProcessingLevel(self)
43
-
44
- @property
45
- def result_qualifiers(self):
46
- return ResultQualifier(self)
47
-
48
- @property
49
- def sensors(self):
50
- return Sensor(self)
51
-
52
- @property
53
- def things(self):
54
- return Thing(self)
55
-
56
- @property
57
- def units(self):
58
- return Unit(self)
59
-
60
- @property
61
- def users(self):
62
- return User(self)
hydroserverpy/models.py DELETED
@@ -1,218 +0,0 @@
1
- import yaml
2
- import re
3
- import simplejson as json
4
- from uuid import UUID
5
- from datetime import datetime
6
- from crontab import CronTab
7
- from pydantic import BaseModel, validator, root_validator, conint, AnyHttpUrl, Field
8
- from typing import List, Optional, Literal, Union
9
-
10
-
11
- class HydroLoaderDatastream(BaseModel):
12
- id: UUID
13
- value_count: Optional[int] = Field(None, alias='valueCount')
14
- result_time: Optional[datetime] = Field(None, alias='resultTime')
15
- phenomenon_time: Optional[datetime] = Field(None, alias='phenomenonTime')
16
- file_row_start_index: Optional[int]
17
- file_result_end_time: Optional[datetime]
18
- chunk_result_start_time: Optional[datetime]
19
- chunk_result_end_time: Optional[datetime]
20
-
21
-
22
- class HydroLoaderObservationsResponse(BaseModel):
23
- datastream_id: str
24
- request_url: str
25
- status_code: int
26
- reason: str
27
- chunk_start_time: str
28
- chunk_end_time: str
29
-
30
-
31
- class HydroLoaderConfSchedule(BaseModel):
32
- crontab: Optional[str]
33
- interval_units: Optional[Literal['minutes', 'hours', 'days', 'weeks', 'months']]
34
- interval: Optional[conint(gt=0)]
35
- start_time: Optional[datetime]
36
- end_time: Optional[datetime]
37
- paused: Optional[bool]
38
-
39
- @root_validator(pre=True)
40
- def check_crontab_or_interval(cls, values):
41
- """
42
- The check_crontab_or_interval function is a validator that ensures that the HydroLoaderConfSchedule model
43
- does not include both a crontab and an interval. It also ensures that if an interval is
44
- included, it includes both an interval and its units.
45
-
46
- :param cls: Pass the class of the model to be created
47
- :param values: Pass the values of the fields in a form to
48
- :return: The values dictionary
49
- """
50
-
51
- if values.get('crontab') and (values.get('interval_units') or values.get('interval')):
52
- raise ValueError('Schedule can include either a crontab or an interval, not both.')
53
-
54
- if (
55
- values.get('interval_units') and not values.get('interval')
56
- ) or (
57
- not values.get('interval_units') and values.get('interval')
58
- ):
59
- raise ValueError('Interval must include both an interval and interval_units.')
60
-
61
- return values
62
-
63
- @validator('crontab')
64
- def check_valid_crontab(cls, v):
65
- """
66
- The check_valid_crontab function is a validator that uses the CronTab library to check if the inputted
67
- crontab string is valid. If it's not, an exception will be raised.
68
-
69
- :param cls: Pass the class to the function
70
- :param v: Pass the value of the field to be validated
71
- :return: The crontab string
72
- """
73
-
74
- if v is not None:
75
- CronTab(v)
76
-
77
- return v
78
-
79
-
80
- class HydroLoaderConfFileAccess(BaseModel):
81
- path: Optional[str]
82
- url: Optional[AnyHttpUrl]
83
- header_row: Optional[conint(gt=0)] = None
84
- data_start_row: Optional[conint(gt=0)] = 1
85
- delimiter: Optional[str] = ','
86
- quote_char: Optional[str] = '"'
87
-
88
- @root_validator(pre=True)
89
- def check_path_or_url(cls, values):
90
- """
91
- The check_path_or_url function is a validator that takes in the values of the HydroLoaderConfFileAccess model
92
- and checks to see if there is either a path or url. If there isn't, it raises an error.
93
-
94
- :param cls: Pass the class of the object being created
95
- :param values: Pass in the values of the path and url parameters
96
- :return: The values dictionary
97
- """
98
-
99
- if bool(values.get('path')) == bool(values.get('url')):
100
- raise ValueError('File access must include either a path or a URL.')
101
-
102
- return values
103
-
104
- @root_validator(pre=True)
105
- def check_header_and_data_rows(cls, values):
106
- """
107
- The check_header_and_data_rows function is a class method that takes in the values of the header_row and
108
- data_start_row and ensures the header row is not greater than the data start row. If it is, it raises an error.
109
-
110
- :param cls: Refer to the class that is being created
111
- :param values: Get the values of the header_row and data_start_row
112
- :return: The values dictionary
113
- """
114
-
115
- if values.get('header_row') is not None and values.get('header_row') >= values.get('data_start_row'):
116
- raise ValueError('Header row cannot occur after data start row.')
117
-
118
- return values
119
-
120
- @validator('delimiter')
121
- def convert_delimiters(cls, v):
122
- """
123
- The convert_delimiters function is a validator that takes in a string and replaces all instances of '\\t' with
124
- '\t'. This function is used to convert the delimiters from the input file into tab-delimited format.
125
-
126
- :param cls: Pass the class object to the function
127
- :param v: Pass the value of the escaped delimiter into the function
128
- :return: An unescaped delimiter string
129
- """
130
-
131
- return v.replace('\\t', '\t')
132
-
133
-
134
- class HydroLoaderConfFileTimestamp(BaseModel):
135
- column: Union[conint(gt=0), str]
136
- format: Optional[str] = '%Y-%m-%dT%H:%M:%S%Z'
137
- offset: Optional[str] = '+0000'
138
-
139
- @validator('format')
140
- def check_valid_strftime(cls, v):
141
- """
142
- The check_valid_strftime function is a validator that takes in a datetime strf string and checks to see if it
143
- is valid. It uses the strftime function from the datetime module, which returns an error if the string passed
144
- to it is not valid.
145
-
146
- :param cls: Pass the class to which the validator is attached
147
- :param v: Pass the value of the argument to be checked
148
- :return: The value of the string
149
- """
150
-
151
- datetime.now().strftime(v)
152
-
153
- return v
154
-
155
- @validator('offset', always=True)
156
- def parse_tzinfo(cls, v):
157
- """
158
- The parse_tzinfo function is a validator for the offset field. It takes in a string and returns an instance
159
- of datetime.tzinfo, which is used by Python's datetime module to represent timezone information. The function
160
- first checks that the input string is a valid UTC offset formatted like "+0000". If it is not valid, then it
161
- raises an exception.
162
-
163
- :param cls: Pass in the class of the object being created
164
- :param v: Pass the timezone offset
165
- :return: A tzinfo object
166
- """
167
-
168
- tzinfo_pattern = r'^[+-](0[0-9]|1[0-4])[0-5][0-9]$'
169
- if v is not None and re.match(tzinfo_pattern, v) is None:
170
- raise ValueError('The offset must be a valid UTC timezone offset formatted such as "+0000".')
171
-
172
- return v # datetime.strptime(v, '%z').tzinfo if v is not None else None
173
-
174
-
175
- class HydroLoaderConfFileDatastream(BaseModel):
176
- column: Union[conint(gt=0), str]
177
- id: UUID
178
-
179
-
180
- class HydroLoaderConf(BaseModel):
181
- schedule: Optional[HydroLoaderConfSchedule]
182
- file_access: HydroLoaderConfFileAccess
183
- file_timestamp: HydroLoaderConfFileTimestamp
184
- datastreams: List[HydroLoaderConfFileDatastream]
185
-
186
- @root_validator()
187
- def check_header_and_fields(cls, values):
188
- """"""
189
-
190
- if not values.get('file_access') or not values['file_access'].header_row:
191
- if values.get('file_timestamp') and not isinstance(values['file_timestamp'].column, int):
192
- raise ValueError('If no header row is defined, all column identifiers must be integers.')
193
- if values.get('datastreams'):
194
- for datastream in values['datastreams']:
195
- if not isinstance(datastream.column, int):
196
- raise ValueError('If no header row is defined, all column identifiers must be integers.')
197
-
198
- return values
199
-
200
- def to_yaml(
201
- self,
202
- file_path: str
203
- ):
204
- """
205
- The to_yaml function takes a file path and writes the configuration to that file in YAML format.
206
-
207
- :param self: Refer to the current instance of the class
208
- :param file_path: str: Specify the file path to save the configuration
209
- :return: A yaml file
210
- """
211
-
212
- with open(file_path, 'w') as conf_file:
213
- yaml.dump(
214
- json.loads(self.json()),
215
- conf_file,
216
- sort_keys=False,
217
- default_flow_style=False
218
- )
@@ -1,27 +0,0 @@
1
- from pydantic import BaseModel
2
- from uuid import UUID
3
- from hydroserverpy.utils import allow_partial
4
-
5
-
6
- class DataLoaderID(BaseModel):
7
- id: UUID
8
-
9
-
10
- class DataLoaderFields(BaseModel):
11
- name: str
12
-
13
-
14
- class DataLoaderGetResponse(DataLoaderFields, DataLoaderID):
15
- pass
16
-
17
- class Config:
18
- allow_population_by_field_name = True
19
-
20
-
21
- class DataLoaderPostBody(DataLoaderFields):
22
- pass
23
-
24
-
25
- @allow_partial
26
- class DataLoaderPatchBody(DataLoaderFields):
27
- pass