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.
- hydroserverpy/__init__.py +6 -15
- hydroserverpy/core/endpoints/__init__.py +9 -0
- hydroserverpy/core/endpoints/base.py +146 -0
- hydroserverpy/core/endpoints/data_loaders.py +93 -0
- hydroserverpy/core/endpoints/data_sources.py +93 -0
- hydroserverpy/core/endpoints/datastreams.py +225 -0
- hydroserverpy/core/endpoints/observed_properties.py +111 -0
- hydroserverpy/core/endpoints/processing_levels.py +111 -0
- hydroserverpy/core/endpoints/result_qualifiers.py +111 -0
- hydroserverpy/core/endpoints/sensors.py +111 -0
- hydroserverpy/core/endpoints/things.py +261 -0
- hydroserverpy/core/endpoints/units.py +111 -0
- hydroserverpy/{components → core/schemas}/__init__.py +1 -2
- hydroserverpy/core/schemas/base.py +124 -0
- hydroserverpy/core/schemas/data_loaders.py +73 -0
- hydroserverpy/core/schemas/data_sources.py +223 -0
- hydroserverpy/core/schemas/datastreams.py +330 -0
- hydroserverpy/core/schemas/observed_properties.py +43 -0
- hydroserverpy/core/schemas/processing_levels.py +31 -0
- hydroserverpy/core/schemas/result_qualifiers.py +26 -0
- hydroserverpy/core/schemas/sensors.py +68 -0
- hydroserverpy/core/schemas/things.py +346 -0
- hydroserverpy/core/schemas/units.py +29 -0
- hydroserverpy/core/service.py +200 -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.py → etl_csv/hydroserver_etl_csv.py} +118 -95
- hydroserverpy/quality/__init__.py +1 -0
- hydroserverpy/quality/service.py +405 -0
- hydroserverpy-0.4.0.dist-info/METADATA +18 -0
- hydroserverpy-0.4.0.dist-info/RECORD +51 -0
- {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/WHEEL +1 -1
- hydroserverpy/components/data_loaders.py +0 -67
- hydroserverpy/components/data_sources.py +0 -98
- hydroserverpy/components/datastreams.py +0 -47
- hydroserverpy/components/observed_properties.py +0 -48
- hydroserverpy/components/processing_levels.py +0 -48
- hydroserverpy/components/result_qualifiers.py +0 -48
- hydroserverpy/components/sensors.py +0 -48
- hydroserverpy/components/things.py +0 -48
- hydroserverpy/components/units.py +0 -48
- hydroserverpy/components/users.py +0 -28
- hydroserverpy/main.py +0 -62
- hydroserverpy/models.py +0 -218
- hydroserverpy/schemas/data_loaders.py +0 -27
- hydroserverpy/schemas/data_sources.py +0 -58
- hydroserverpy/schemas/datastreams.py +0 -56
- hydroserverpy/schemas/observed_properties.py +0 -33
- hydroserverpy/schemas/processing_levels.py +0 -33
- hydroserverpy/schemas/result_qualifiers.py +0 -32
- hydroserverpy/schemas/sensors.py +0 -39
- hydroserverpy/schemas/things.py +0 -107
- hydroserverpy/schemas/units.py +0 -32
- hydroserverpy/schemas/users.py +0 -28
- hydroserverpy/service.py +0 -170
- hydroserverpy/utils.py +0 -37
- hydroserverpy-0.2.5.dist-info/METADATA +0 -15
- hydroserverpy-0.2.5.dist-info/RECORD +0 -35
- /hydroserverpy/{schemas → core}/__init__.py +0 -0
- /hydroserverpy/{exceptions.py → etl_csv/exceptions.py} +0 -0
- {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/LICENSE +0 -0
- {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/top_level.txt +0 -0
- {hydroserverpy-0.2.5.dist-info → hydroserverpy-0.4.0.dist-info}/zip-safe +0 -0
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
|
-
from typing import Optional, Literal, Union
|
|
3
|
-
from pydantic import AnyHttpUrl, conint
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from uuid import UUID
|
|
6
|
-
from hydroserverpy.utils import allow_partial
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class DataSourceID(BaseModel):
|
|
10
|
-
id: UUID
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class DataSourceFields(BaseModel):
|
|
14
|
-
name: str
|
|
15
|
-
path: Optional[str]
|
|
16
|
-
url: Optional[AnyHttpUrl]
|
|
17
|
-
header_row: Optional[conint(gt=0)] = Field(None, alias='headerRow')
|
|
18
|
-
data_start_row: Optional[conint(gt=0)] = Field(1, alias='dataStartRow')
|
|
19
|
-
delimiter: Optional[str] = ','
|
|
20
|
-
quote_char: Optional[str] = Field('"', alias='quoteChar')
|
|
21
|
-
interval: Optional[conint(gt=0)]
|
|
22
|
-
interval_units: Optional[Literal['minutes', 'hours', 'days', 'weeks', 'months']] = \
|
|
23
|
-
Field(None, alias='intervalUnits')
|
|
24
|
-
crontab: Optional[str]
|
|
25
|
-
start_time: Optional[datetime] = Field(None, alias='startTime')
|
|
26
|
-
end_time: Optional[datetime] = Field(None, alias='endTime')
|
|
27
|
-
paused: Optional[bool]
|
|
28
|
-
timestamp_column: Union[conint(gt=0), str] = Field(..., alias='timestampColumn')
|
|
29
|
-
timestamp_format: Optional[str] = Field('%Y-%m-%dT%H:%M:%S%Z', alias='timestampFormat')
|
|
30
|
-
timestamp_offset: Optional[str] = Field('+0000', alias='timestampOffset')
|
|
31
|
-
data_loader_id: UUID = Field(..., alias='dataLoaderId')
|
|
32
|
-
data_source_thru: Optional[datetime] = Field(None, alias='dataSourceThru')
|
|
33
|
-
last_sync_successful: Optional[bool] = Field(None, alias='lastSyncSuccessful')
|
|
34
|
-
last_sync_message: Optional[str] = Field(None, alias='lastSyncMessage')
|
|
35
|
-
last_synced: Optional[datetime] = Field(None, alias='lastSynced')
|
|
36
|
-
next_sync: Optional[datetime] = Field(None, alias='nextSync')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class DataSourceGetResponse(DataSourceFields, DataSourceID):
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
class Config:
|
|
43
|
-
allow_population_by_field_name = True
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class DataSourcePostBody(DataSourceFields):
|
|
47
|
-
pass
|
|
48
|
-
|
|
49
|
-
class Config:
|
|
50
|
-
allow_population_by_field_name = True
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@allow_partial
|
|
54
|
-
class DataSourcePatchBody(DataSourceFields):
|
|
55
|
-
pass
|
|
56
|
-
|
|
57
|
-
class Config:
|
|
58
|
-
allow_population_by_field_name = True
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
|
-
from typing import Union, Literal, Optional
|
|
3
|
-
from uuid import UUID
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from hydroserverpy.utils import allow_partial
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class DatastreamID(BaseModel):
|
|
9
|
-
id: UUID
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class DatastreamFields(BaseModel):
|
|
13
|
-
name: Union[UUID, str]
|
|
14
|
-
description: str
|
|
15
|
-
observation_type: str = Field(..., alias='observationType')
|
|
16
|
-
sampled_medium: str = Field(..., alias='sampledMedium')
|
|
17
|
-
no_data_value: float = Field(..., alias='noDataValue')
|
|
18
|
-
aggregation_statistic: str = Field(..., alias='aggregationStatistic')
|
|
19
|
-
time_aggregation_interval: float = Field(..., alias='timeAggregationInterval')
|
|
20
|
-
status: str = None
|
|
21
|
-
result_type: str = Field(..., alias='resultType')
|
|
22
|
-
value_count: int = Field(None, alias='valueCount')
|
|
23
|
-
intended_time_spacing: float = Field(None, alias='intendedTimeSpacing')
|
|
24
|
-
phenomenon_begin_time: datetime = Field(None, alias='phenomenonBeginTime')
|
|
25
|
-
phenomenon_end_time: datetime = Field(None, alias='phenomenonEndTime')
|
|
26
|
-
result_begin_time: datetime = Field(None, alias='resultBeginTime')
|
|
27
|
-
result_end_time: datetime = Field(None, alias='resultEndTime')
|
|
28
|
-
data_source_id: UUID = Field(None, alias='dataSourceId')
|
|
29
|
-
data_source_column: str = Field(None, alias='dataSourceColumn')
|
|
30
|
-
is_visible: bool = Field(True, alias='isVisible')
|
|
31
|
-
thing_id: UUID = Field(..., alias='thingId')
|
|
32
|
-
sensor_id: UUID = Field(..., alias='sensorId')
|
|
33
|
-
observed_property_id: UUID = Field(..., alias='observedPropertyId')
|
|
34
|
-
processing_level_id: UUID = Field(..., alias='processingLevelId')
|
|
35
|
-
unit_id: UUID = Field(..., alias='unitId')
|
|
36
|
-
time_aggregation_interval_units: Literal['seconds', 'minutes', 'hours', 'days'] = \
|
|
37
|
-
Field(..., alias='timeAggregationIntervalUnits')
|
|
38
|
-
intended_time_spacing_units: Optional[Literal['seconds', 'minutes', 'hours', 'days']] = \
|
|
39
|
-
Field(None, alias='intendedTimeSpacingUnits')
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class DatastreamGetResponse(DatastreamFields, DatastreamID):
|
|
43
|
-
|
|
44
|
-
class Config:
|
|
45
|
-
allow_population_by_field_name = True
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class DatastreamPostBody(DatastreamFields):
|
|
49
|
-
|
|
50
|
-
class Config:
|
|
51
|
-
allow_population_by_field_name = True
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@allow_partial
|
|
55
|
-
class DatastreamPatchBody(DatastreamFields):
|
|
56
|
-
thing_id: UUID = Field(..., alias='thingId')
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel
|
|
2
|
-
from uuid import UUID
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from hydroserverpy.utils import allow_partial
|
|
5
|
-
from hydroserverpy.schemas.users import UserFields
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ObservedPropertyID(BaseModel):
|
|
9
|
-
id: UUID
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ObservedPropertyFields(BaseModel):
|
|
13
|
-
name: str
|
|
14
|
-
definition: str
|
|
15
|
-
description: str = None
|
|
16
|
-
type: str = None
|
|
17
|
-
code: str = None
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ObservedPropertyGetResponse(ObservedPropertyFields, ObservedPropertyID):
|
|
21
|
-
owner: Optional[str]
|
|
22
|
-
|
|
23
|
-
class Config:
|
|
24
|
-
allow_population_by_field_name = True
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class ObservedPropertyPostBody(ObservedPropertyFields):
|
|
28
|
-
pass
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@allow_partial
|
|
32
|
-
class ObservedPropertyPatchBody(ObservedPropertyFields):
|
|
33
|
-
pass
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel
|
|
2
|
-
from uuid import UUID
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from ..utils import allow_partial
|
|
5
|
-
from ..schemas.users import UserFields
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ProcessingLevelID(BaseModel):
|
|
9
|
-
id: UUID
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ProcessingLevelFields(BaseModel):
|
|
13
|
-
code: str
|
|
14
|
-
definition: str = None
|
|
15
|
-
explanation: str = None
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class ProcessingLevelGetResponse(ProcessingLevelFields, ProcessingLevelID):
|
|
19
|
-
owner: Optional[str]
|
|
20
|
-
|
|
21
|
-
class Config:
|
|
22
|
-
allow_population_by_field_name = True
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ProcessingLevelPostBody(ProcessingLevelFields):
|
|
26
|
-
|
|
27
|
-
class Config:
|
|
28
|
-
allow_population_by_field_name = True
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@allow_partial
|
|
32
|
-
class ProcessingLevelPatchBody(ProcessingLevelFields):
|
|
33
|
-
pass
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel
|
|
2
|
-
from uuid import UUID
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from ..utils import allow_partial
|
|
5
|
-
from ..schemas.users import UserFields
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ResultQualifierID(BaseModel):
|
|
9
|
-
id: UUID
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ResultQualifierFields(BaseModel):
|
|
13
|
-
code: str
|
|
14
|
-
description: str
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class ResultQualifierGetResponse(ResultQualifierFields, ResultQualifierID):
|
|
18
|
-
owner: Optional[str]
|
|
19
|
-
|
|
20
|
-
class Config:
|
|
21
|
-
allow_population_by_field_name = True
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class ResultQualifierPostBody(ResultQualifierFields):
|
|
25
|
-
|
|
26
|
-
class Config:
|
|
27
|
-
allow_population_by_field_name = True
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@allow_partial
|
|
31
|
-
class ResultQualifierPatchBody(ResultQualifierFields):
|
|
32
|
-
pass
|
hydroserverpy/schemas/sensors.py
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
|
-
from uuid import UUID
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from hydroserverpy.utils import allow_partial
|
|
5
|
-
from hydroserverpy.schemas.users import UserFields
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class SensorID(BaseModel):
|
|
9
|
-
id: UUID
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class SensorFields(BaseModel):
|
|
13
|
-
name: str
|
|
14
|
-
description: str
|
|
15
|
-
encoding_type: str = Field(alias="encodingType")
|
|
16
|
-
manufacturer: str = None
|
|
17
|
-
model: str = None
|
|
18
|
-
model_link: str = Field(None, alias='modelLink')
|
|
19
|
-
method_type: str = Field(alias='methodType')
|
|
20
|
-
method_link: str = Field(None, alias='methodLink')
|
|
21
|
-
method_code: str = Field(None, alias='methodCode')
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class SensorGetResponse(SensorFields, SensorID):
|
|
25
|
-
owner: Optional[str]
|
|
26
|
-
|
|
27
|
-
class Config:
|
|
28
|
-
allow_population_by_field_name = True
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class SensorPostBody(SensorFields):
|
|
32
|
-
|
|
33
|
-
class Config:
|
|
34
|
-
allow_population_by_field_name = True
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@allow_partial
|
|
38
|
-
class SensorPatchBody(SensorFields):
|
|
39
|
-
pass
|
hydroserverpy/schemas/things.py
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field, root_validator
|
|
2
|
-
from typing import List, Optional
|
|
3
|
-
from uuid import UUID
|
|
4
|
-
from hydroserverpy.utils import allow_partial
|
|
5
|
-
from hydroserverpy.schemas.observed_properties import ObservedPropertyGetResponse
|
|
6
|
-
from hydroserverpy.schemas.processing_levels import ProcessingLevelGetResponse
|
|
7
|
-
from hydroserverpy.schemas.units import UnitGetResponse
|
|
8
|
-
from hydroserverpy.schemas.sensors import SensorGetResponse
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class ThingID(BaseModel):
|
|
12
|
-
id: UUID
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class ThingFields(BaseModel):
|
|
16
|
-
name: str
|
|
17
|
-
description: str
|
|
18
|
-
sampling_feature_type: str = Field(alias='samplingFeatureType')
|
|
19
|
-
sampling_feature_code: str = Field(alias='samplingFeatureCode')
|
|
20
|
-
site_type: str = Field(alias='siteType')
|
|
21
|
-
data_disclaimer: str = Field(None, alias='dataDisclaimer')
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class LocationFields(BaseModel):
|
|
25
|
-
latitude: float
|
|
26
|
-
longitude: float
|
|
27
|
-
elevation_m: float = None
|
|
28
|
-
elevation_datum: str = Field(None, alias='elevationDatum')
|
|
29
|
-
state: str = None
|
|
30
|
-
county: str = None
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class OrganizationFields(BaseModel):
|
|
34
|
-
organization_name: Optional[str] = Field(None, alias='organizationName')
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class AssociationFields(BaseModel):
|
|
38
|
-
is_primary_owner: bool = Field(..., alias='isPrimaryOwner')
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class PersonFields(BaseModel):
|
|
42
|
-
first_name: str = Field(..., alias='firstName')
|
|
43
|
-
last_name: str = Field(..., alias='lastName')
|
|
44
|
-
email: str
|
|
45
|
-
|
|
46
|
-
class Config:
|
|
47
|
-
allow_population_by_field_name = True
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class OwnerFields(AssociationFields, OrganizationFields, PersonFields):
|
|
51
|
-
pass
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class ThingGetResponse(LocationFields, ThingFields, ThingID):
|
|
55
|
-
is_private: bool = Field(..., alias='isPrivate')
|
|
56
|
-
is_primary_owner: bool = Field(..., alias='isPrimaryOwner')
|
|
57
|
-
owns_thing: bool = Field(..., alias='ownsThing')
|
|
58
|
-
owners: List[OwnerFields]
|
|
59
|
-
|
|
60
|
-
class Config:
|
|
61
|
-
allow_population_by_field_name = True
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class ThingPostBody(ThingFields, LocationFields):
|
|
65
|
-
|
|
66
|
-
class Config:
|
|
67
|
-
allow_population_by_field_name = True
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@allow_partial
|
|
71
|
-
class ThingPatchBody(ThingFields, LocationFields):
|
|
72
|
-
|
|
73
|
-
class Config:
|
|
74
|
-
allow_population_by_field_name = True
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class ThingOwnershipPatchBody(BaseModel):
|
|
78
|
-
email: str
|
|
79
|
-
make_owner: Optional[bool] = Field(False, alias='makeOwner')
|
|
80
|
-
remove_owner: Optional[bool] = Field(False, alias='removeOwner')
|
|
81
|
-
transfer_primary: Optional[bool] = Field(False, alias='transferPrimary')
|
|
82
|
-
|
|
83
|
-
@root_validator()
|
|
84
|
-
def validate_only_one_method_allowed(cls, field_values):
|
|
85
|
-
|
|
86
|
-
assert [
|
|
87
|
-
field_values.get('make_owner', False),
|
|
88
|
-
field_values.get('remove_owner', False),
|
|
89
|
-
field_values.get('transfer_primary', False)
|
|
90
|
-
].count(True) == 1, \
|
|
91
|
-
'You must perform one and only one action from among "makeOwner", "removeOwner", and "transferPrimary".'
|
|
92
|
-
|
|
93
|
-
return field_values
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class ThingPrivacyPatchBody(BaseModel):
|
|
97
|
-
is_private: bool = Field(..., alias="isPrivate")
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class ThingMetadataGetResponse(BaseModel):
|
|
101
|
-
units: List[UnitGetResponse]
|
|
102
|
-
sensors: List[SensorGetResponse]
|
|
103
|
-
processing_levels: List[ProcessingLevelGetResponse] = Field(..., alias='processingLevels')
|
|
104
|
-
observed_properties: List[ObservedPropertyGetResponse] = Field(..., alias='observedProperties')
|
|
105
|
-
|
|
106
|
-
class Config:
|
|
107
|
-
allow_population_by_field_name = True
|
hydroserverpy/schemas/units.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel
|
|
2
|
-
from uuid import UUID
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from hydroserverpy.utils import allow_partial
|
|
5
|
-
from hydroserverpy.schemas.users import UserFields
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class UnitID(BaseModel):
|
|
9
|
-
id: UUID
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class UnitFields(BaseModel):
|
|
13
|
-
name: str
|
|
14
|
-
symbol: str
|
|
15
|
-
definition: str
|
|
16
|
-
type: str
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class UnitGetResponse(UnitFields, UnitID):
|
|
20
|
-
owner: Optional[str]
|
|
21
|
-
|
|
22
|
-
class Config:
|
|
23
|
-
allow_population_by_field_name = True
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class UnitPostBody(UnitFields):
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@allow_partial
|
|
31
|
-
class UnitPatchBody(UnitFields):
|
|
32
|
-
pass
|
hydroserverpy/schemas/users.py
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class OrganizationFields(BaseModel):
|
|
5
|
-
code: str
|
|
6
|
-
name: str
|
|
7
|
-
description: str = None
|
|
8
|
-
type: str
|
|
9
|
-
link: str = None
|
|
10
|
-
|
|
11
|
-
@classmethod
|
|
12
|
-
def is_empty(cls, obj):
|
|
13
|
-
return not (obj.name and obj.code and obj.type)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class UserFields(BaseModel):
|
|
17
|
-
first_name: str = Field(alias="firstName")
|
|
18
|
-
last_name: str = Field(alias="lastName")
|
|
19
|
-
email: str = None
|
|
20
|
-
middle_name: str = Field(default=None, alias="middleName")
|
|
21
|
-
phone: str = None
|
|
22
|
-
address: str = None
|
|
23
|
-
type: str = None
|
|
24
|
-
link: str = None
|
|
25
|
-
organization: OrganizationFields = None
|
|
26
|
-
|
|
27
|
-
class Config:
|
|
28
|
-
allow_population_by_field_name = True
|
hydroserverpy/service.py
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import json
|
|
3
|
-
import frost_sta_client as fsc
|
|
4
|
-
from typing import Optional, Union, Tuple
|
|
5
|
-
from pydantic import AnyHttpUrl
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class BaseService:
|
|
9
|
-
|
|
10
|
-
def __init__(
|
|
11
|
-
self,
|
|
12
|
-
host: Union[AnyHttpUrl, str],
|
|
13
|
-
sta_path: str,
|
|
14
|
-
api_path: str,
|
|
15
|
-
auth: Optional[Tuple[str, str]] = None,
|
|
16
|
-
):
|
|
17
|
-
self.host = host.strip('/')
|
|
18
|
-
self.auth = auth
|
|
19
|
-
self.sensorthings = None
|
|
20
|
-
self._sta_path = sta_path.strip('/')
|
|
21
|
-
self._api_path = api_path.strip('/')
|
|
22
|
-
self._session = None
|
|
23
|
-
self._timeout = 60
|
|
24
|
-
self._initialize_session()
|
|
25
|
-
|
|
26
|
-
def _initialize_session(self):
|
|
27
|
-
"""
|
|
28
|
-
The _initialize_session function is used to initialize the session object.
|
|
29
|
-
|
|
30
|
-
:param self
|
|
31
|
-
:return: None
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
if self._session is not None:
|
|
35
|
-
self._session.close()
|
|
36
|
-
|
|
37
|
-
self._session = requests.Session()
|
|
38
|
-
|
|
39
|
-
if self.auth and self.auth[0] == '__token__':
|
|
40
|
-
self._session.headers.update(
|
|
41
|
-
{'Authorization': f'Bearer {self.auth[1]}'}
|
|
42
|
-
)
|
|
43
|
-
elif self.auth:
|
|
44
|
-
self._session.auth = self.auth
|
|
45
|
-
|
|
46
|
-
self.sensorthings = fsc.SensorThingsService(
|
|
47
|
-
url=f'{self.host}/{self._sta_path}',
|
|
48
|
-
auth_handler=fsc.service.auth_handler.AuthHandler(
|
|
49
|
-
username=self.auth[0],
|
|
50
|
-
password=self.auth[1]
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
def _request(self, method, path, *args, **kwargs):
|
|
55
|
-
"""
|
|
56
|
-
The _request function is a helper function that makes it easier to make requests to the API.
|
|
57
|
-
It takes in a method, path, and any other arguments you want to pass into the request.
|
|
58
|
-
The method argument should be one of 'get', 'post', or 'delete'. The path argument should be
|
|
59
|
-
the endpoint you are trying to reach (e.g., '/users/me'). Any additional arguments will be passed
|
|
60
|
-
into the request as-is.
|
|
61
|
-
|
|
62
|
-
:param self
|
|
63
|
-
:param method: Specify the type of request that is being made
|
|
64
|
-
:param path: Specify the path of the request
|
|
65
|
-
:return: A response object
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
for attempt in range(2):
|
|
69
|
-
try:
|
|
70
|
-
return getattr(self._session, method)(
|
|
71
|
-
f'{self.host}/{self._api_path}/{path.strip("/")}',
|
|
72
|
-
timeout=self._timeout,
|
|
73
|
-
*args, **kwargs
|
|
74
|
-
)
|
|
75
|
-
except requests.exceptions.ConnectionError as e:
|
|
76
|
-
if attempt == 0:
|
|
77
|
-
self._initialize_session()
|
|
78
|
-
continue
|
|
79
|
-
else:
|
|
80
|
-
raise e
|
|
81
|
-
|
|
82
|
-
def get(self, path, response_schema=None, *args, **kwargs):
|
|
83
|
-
"""
|
|
84
|
-
The get function accepts a path and any other arguments that are passed to it,
|
|
85
|
-
and then calls the _request function with the 'get' method. If the request is successful,
|
|
86
|
-
the response content is parsed and added to the response object to be returned.
|
|
87
|
-
|
|
88
|
-
:param self: Represent the instance of the class
|
|
89
|
-
:param path: Specify the url of the request
|
|
90
|
-
:param response_schema: Specify the schema of the response
|
|
91
|
-
:return: A response object
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
response = self._request('get', path, *args, **kwargs)
|
|
95
|
-
|
|
96
|
-
if response.status_code == 200:
|
|
97
|
-
if not response_schema:
|
|
98
|
-
response.data = json.loads(response.content)
|
|
99
|
-
elif getattr(response_schema, '__origin__', None) == list:
|
|
100
|
-
response.data = [
|
|
101
|
-
response_schema.__args__[0](**entity)
|
|
102
|
-
for entity in json.loads(response.content)
|
|
103
|
-
]
|
|
104
|
-
else:
|
|
105
|
-
response.data = response_schema(**json.loads(response.content))
|
|
106
|
-
|
|
107
|
-
else:
|
|
108
|
-
response.data = None
|
|
109
|
-
|
|
110
|
-
return response
|
|
111
|
-
|
|
112
|
-
def post(self, path, response_schema=None, *args, **kwargs):
|
|
113
|
-
"""
|
|
114
|
-
The post function accepts a path and any other arguments that are passed to it,
|
|
115
|
-
and then calls the _request function with the 'post' method. If the request is successful,
|
|
116
|
-
the response content is parsed and added to the response object to be returned.
|
|
117
|
-
|
|
118
|
-
:param self: Represent the instance of the class
|
|
119
|
-
:param path: Specify the url of the request
|
|
120
|
-
:param response_schema: Specify the schema of the response
|
|
121
|
-
:return: A response object
|
|
122
|
-
"""
|
|
123
|
-
|
|
124
|
-
response = self._request('post', path, *args, **kwargs)
|
|
125
|
-
|
|
126
|
-
if response.status_code == 201:
|
|
127
|
-
if not response_schema:
|
|
128
|
-
response.data = json.loads(response.content)
|
|
129
|
-
else:
|
|
130
|
-
response.data = response_schema(**json.loads(response.content))
|
|
131
|
-
else:
|
|
132
|
-
response.data = None
|
|
133
|
-
|
|
134
|
-
return response
|
|
135
|
-
|
|
136
|
-
def patch(self, path, response_schema=None, *args, **kwargs):
|
|
137
|
-
"""
|
|
138
|
-
The patch function accepts a path and any other arguments that are passed to it,
|
|
139
|
-
and then calls the _request function with the 'patch' method. If the request is successful,
|
|
140
|
-
the response content is parsed and added to the response object to be returned.
|
|
141
|
-
|
|
142
|
-
:param self: Represent the instance of the class
|
|
143
|
-
:param path: Specify the url of the request
|
|
144
|
-
:param response_schema: Specify the schema of the response
|
|
145
|
-
:return: A response object
|
|
146
|
-
"""
|
|
147
|
-
|
|
148
|
-
response = self._request('patch', path, *args, **kwargs)
|
|
149
|
-
|
|
150
|
-
if response.status_code == 203:
|
|
151
|
-
if not response_schema:
|
|
152
|
-
response.data = json.loads(response.content)
|
|
153
|
-
else:
|
|
154
|
-
response.data = response_schema(**json.loads(response.content))
|
|
155
|
-
else:
|
|
156
|
-
response.data = None
|
|
157
|
-
|
|
158
|
-
return response
|
|
159
|
-
|
|
160
|
-
def delete(self, path, *args, **kwargs):
|
|
161
|
-
"""
|
|
162
|
-
The patch function accepts a path and any other arguments that are passed to it,
|
|
163
|
-
and then calls the _request function with the 'delete' method.
|
|
164
|
-
|
|
165
|
-
:param self: Represent the instance of the class
|
|
166
|
-
:param path: Specify the url of the request
|
|
167
|
-
:return: A response object
|
|
168
|
-
"""
|
|
169
|
-
|
|
170
|
-
return self._request('delete', path, *args, **kwargs)
|
hydroserverpy/utils.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
from pydantic import BaseModel
|
|
3
|
-
from typing import Callable
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def allow_partial(*fields) -> Callable:
|
|
7
|
-
"""
|
|
8
|
-
The allow_partial function is a decorator that allows you to mark fields as not required.
|
|
9
|
-
This means that the field will be allowed to be missing from the input data, and if it is missing,
|
|
10
|
-
the default value for the field will be used instead. This can also be done by setting required=False on each field.
|
|
11
|
-
|
|
12
|
-
:return: A decorator that can be applied to a class
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
def dec(_cls):
|
|
16
|
-
for field in fields:
|
|
17
|
-
_cls.__fields__[field].required = False
|
|
18
|
-
return _cls
|
|
19
|
-
|
|
20
|
-
if fields and inspect.isclass(fields[0]) and issubclass(fields[0], BaseModel):
|
|
21
|
-
cls = fields[0]
|
|
22
|
-
fields = cls.__fields__
|
|
23
|
-
return dec(cls)
|
|
24
|
-
|
|
25
|
-
return dec
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def entity_path(self, entity_id):
|
|
29
|
-
"""
|
|
30
|
-
The entity_path function returns the path to a specific entity.
|
|
31
|
-
|
|
32
|
-
:param self: Represent the instance of the class
|
|
33
|
-
:param entity_id: Specify the entity id of the entity to be retrieved
|
|
34
|
-
:return: The entity type and the id of the entity
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
return "{}({})".format(self.entitytype_plural, entity_id)
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: hydroserverpy
|
|
3
|
-
Version: 0.2.5
|
|
4
|
-
License-File: LICENSE
|
|
5
|
-
Requires-Dist: requests >=2
|
|
6
|
-
Requires-Dist: pydantic <2.0.0,>=1.6
|
|
7
|
-
Requires-Dist: pyyaml >=5
|
|
8
|
-
Requires-Dist: simplejson >=3
|
|
9
|
-
Requires-Dist: crontab >=1
|
|
10
|
-
Requires-Dist: python-dateutil >=2.8.2
|
|
11
|
-
Requires-Dist: croniter >=2.0.1
|
|
12
|
-
Requires-Dist: frost-sta-client >=1.1.44
|
|
13
|
-
Provides-Extra: docs
|
|
14
|
-
Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
|
|
15
|
-
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
hydroserverpy/__init__.py,sha256=iZcBLrXpuWr7SYUIgIT3ngDKcI63LgfRNCwCIiv_CW4,616
|
|
2
|
-
hydroserverpy/etl.py,sha256=3cczra-7m1WxdHXm3yZO3hlz-OkWUJdQkA8mdhF8bi0,13229
|
|
3
|
-
hydroserverpy/exceptions.py,sha256=0UY8YUlNepG0y6FfH36hJyR1bOhwYHSZIdUSSMTg7GA,314
|
|
4
|
-
hydroserverpy/main.py,sha256=UD8l4wFvJbLWA07r0kR5tYPW3dnD7OCQoB4PJVpHkeo,1421
|
|
5
|
-
hydroserverpy/models.py,sha256=IxQrSEHM344Bn6qtwjGFdY7bqyH_-lc8TJggVqDsvdg,8174
|
|
6
|
-
hydroserverpy/service.py,sha256=wMuOi4TwZbaB0kPgTOzdfP0HLwmlHTVREuksyxJJ1YQ,6150
|
|
7
|
-
hydroserverpy/utils.py,sha256=VWnd1ffMaiQDVNAKBCr3HhiWMe1YxAmbkb7UNcHSA6k,1173
|
|
8
|
-
hydroserverpy/components/__init__.py,sha256=raT0GabQrFf6lHRW0nm0GYbnQgpScP6FocKCFWwii3w,356
|
|
9
|
-
hydroserverpy/components/data_loaders.py,sha256=83a4oYNGxn5QkJmiOPbk0cx713RvNpyoBSz9genWu3M,2066
|
|
10
|
-
hydroserverpy/components/data_sources.py,sha256=UEdTBU2V5HWqptVk7eZWpKon0osDhq99CgHV7foan6k,3262
|
|
11
|
-
hydroserverpy/components/datastreams.py,sha256=rXdKjSH21IT6cVY3kP0GWS22CYL0I3oeZaInzqwju3w,1365
|
|
12
|
-
hydroserverpy/components/observed_properties.py,sha256=D2yvdDgJc4cNr5H73kb1QZ4Ju4IcsrBubp-4yYn8_fA,1551
|
|
13
|
-
hydroserverpy/components/processing_levels.py,sha256=0bVYp3WJv3MaBz_mqCNirHMu25W6pVg4u0THbTHElVs,1518
|
|
14
|
-
hydroserverpy/components/result_qualifiers.py,sha256=JmAF1gfSz0mPtXHptWxaZvlTonZ363-bBwXwiKAjgX4,1522
|
|
15
|
-
hydroserverpy/components/sensors.py,sha256=V6tQi4i4Amoy1o0HFYx-YdELVfQQomJV4hzdUsvj38I,1268
|
|
16
|
-
hydroserverpy/components/things.py,sha256=-XCkoQj_VdvADGOwbi6czjr6vCdaXhFEZhPvmClG4bw,1246
|
|
17
|
-
hydroserverpy/components/units.py,sha256=2nHmJgd97loHjh6jt84PQPjD7XzztECWbCr4o8VwHD8,1216
|
|
18
|
-
hydroserverpy/components/users.py,sha256=jpZ6TGOImK_j3ghwTFoAxpD9WMBG9DzIC0vcsb2G1w0,622
|
|
19
|
-
hydroserverpy/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
hydroserverpy/schemas/data_loaders.py,sha256=5YIXryh1LaVgjRetruyZHvBivsCS1XqOnT6lbcMCIMg,459
|
|
21
|
-
hydroserverpy/schemas/data_sources.py,sha256=cYnhKUaKqirhJjxo9niSgtOdokv98Fah635rOywosAE,2053
|
|
22
|
-
hydroserverpy/schemas/datastreams.py,sha256=wOY3O8UBLjfJXlVJI18rkcPNFApGDteKmFGsCbCv4s4,2266
|
|
23
|
-
hydroserverpy/schemas/observed_properties.py,sha256=-DpFuo4UYY5dx7mAxRSyN6EqjHGp9-CT5AapzSOE2RQ,698
|
|
24
|
-
hydroserverpy/schemas/processing_levels.py,sha256=MWy7fRIP-hDJtjwmSB1PK27agx9U2UFpjhl5lrYMIHA,686
|
|
25
|
-
hydroserverpy/schemas/result_qualifiers.py,sha256=m2OfJHefO1jFfRqV-Klgv6b50jOM0X1UtNCrSon3Znc,652
|
|
26
|
-
hydroserverpy/schemas/sensors.py,sha256=mUilTxc61zkrL2GULhJTO-q3P58Rkh2leHyCSZl1-Ug,918
|
|
27
|
-
hydroserverpy/schemas/things.py,sha256=79WMxbf54vgob-3JtHwC_e85W-5U__GI0ZOMnCxJDL0,3300
|
|
28
|
-
hydroserverpy/schemas/units.py,sha256=_28zmCz9TDuNfHa4Ycj1RKkxwUB_J832NSWIO3cBK9k,550
|
|
29
|
-
hydroserverpy/schemas/users.py,sha256=TauiaArJ4LVjAKq80KvjKjxex5DAwQekc_nDXHyaU3U,675
|
|
30
|
-
hydroserverpy-0.2.5.dist-info/LICENSE,sha256=xVqFxDw3QOEJukakL7gQCqIMTQ1dlSCTo6Oc1otNW80,1508
|
|
31
|
-
hydroserverpy-0.2.5.dist-info/METADATA,sha256=hKbR4GdMGSCVPlfzcYRXsj8is5ClxC5jy0OleMwh0I8,419
|
|
32
|
-
hydroserverpy-0.2.5.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
33
|
-
hydroserverpy-0.2.5.dist-info/top_level.txt,sha256=Zf37hrncXLOYvXhgCrf5mZdeq81G9fShdE2LfYbtb7w,14
|
|
34
|
-
hydroserverpy-0.2.5.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
35
|
-
hydroserverpy-0.2.5.dist-info/RECORD,,
|
|
File without changes
|