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
@@ -0,0 +1,111 @@
1
+ from typing import Union, List, TYPE_CHECKING
2
+ from uuid import UUID
3
+ from hydroserverpy.core.endpoints.base import HydroServerEndpoint, expand_docstring
4
+ from hydroserverpy.core.schemas import ObservedProperty
5
+
6
+ if TYPE_CHECKING:
7
+ from hydroserverpy.core.service import HydroServer
8
+
9
+
10
+ class ObservedPropertyEndpoint(HydroServerEndpoint):
11
+ """
12
+ An endpoint for interacting with observed property entities in the HydroServer service.
13
+
14
+ :ivar _model: The model class associated with this endpoint, set to `ObservedProperty`.
15
+ :ivar _api_route: The base route of the API, derived from the service.
16
+ :ivar _endpoint_route: The specific route of the endpoint, set to `'observed-properties'`.
17
+ """
18
+
19
+ def __init__(self, service):
20
+ """
21
+ Initialize the ObservedPropertyEndpoint.
22
+
23
+ :param service: The HydroServer service instance to use for requests.
24
+ :type service: HydroServer
25
+ """
26
+
27
+ super().__init__(service)
28
+ self._model = ObservedProperty
29
+ self._api_route = self._service.api_route
30
+ self._endpoint_route = "observed-properties"
31
+
32
+ def list(
33
+ self,
34
+ include_owned: bool = True,
35
+ include_unowned: bool = True,
36
+ include_templates: bool = True,
37
+ ) -> List[ObservedProperty]:
38
+ """
39
+ Retrieve a collection of observed properties.
40
+
41
+ :param include_owned: Whether to include owned observed properties.
42
+ :param include_unowned: Whether to include unowned observed properties.
43
+ :param include_templates: Whether to include template observed properties.
44
+ """
45
+
46
+ if (
47
+ include_owned is True
48
+ and include_unowned is True
49
+ and include_templates is True
50
+ ):
51
+ owner = "anyUserOrNoUser"
52
+ elif (
53
+ include_owned is True
54
+ and include_unowned is True
55
+ and include_templates is False
56
+ ):
57
+ owner = "anyUser"
58
+ elif (
59
+ include_owned is True
60
+ and include_unowned is False
61
+ and include_templates is True
62
+ ):
63
+ owner = "currentUserOrNoUser"
64
+ elif (
65
+ include_owned is True
66
+ and include_unowned is False
67
+ and include_templates is False
68
+ ):
69
+ owner = "currentUser"
70
+ elif (
71
+ include_owned is False
72
+ and include_unowned is False
73
+ and include_templates is True
74
+ ):
75
+ owner = "noUser"
76
+ else:
77
+ return []
78
+
79
+ return super()._get(params={"owner": owner})
80
+
81
+ @expand_docstring(include_uid=True)
82
+ def get(self, uid: Union[UUID, str]) -> ObservedProperty:
83
+ """
84
+ Retrieve an observed property owned by the logged-in user.
85
+ """
86
+
87
+ return super()._get(uid)
88
+
89
+ @expand_docstring(model=ObservedProperty)
90
+ def create(self, **kwargs) -> ObservedProperty:
91
+ """
92
+ Create a new observed property in HydroServer.
93
+ """
94
+
95
+ return super()._post(**kwargs)
96
+
97
+ @expand_docstring(model=ObservedProperty, include_uid=True)
98
+ def update(self, uid: Union[UUID, str], **kwargs) -> ObservedProperty:
99
+ """
100
+ Update an existing observed property in HydroServer.
101
+ """
102
+
103
+ return super()._patch(uid=uid, **kwargs)
104
+
105
+ @expand_docstring(include_uid=True)
106
+ def delete(self, uid: Union[UUID, str]) -> None:
107
+ """
108
+ Delete an existing observed property in HydroServer.
109
+ """
110
+
111
+ super()._delete(uid=uid)
@@ -0,0 +1,111 @@
1
+ from typing import List, Union, TYPE_CHECKING
2
+ from uuid import UUID
3
+ from hydroserverpy.core.endpoints.base import HydroServerEndpoint, expand_docstring
4
+ from hydroserverpy.core.schemas import ProcessingLevel
5
+
6
+ if TYPE_CHECKING:
7
+ from hydroserverpy.core.service import HydroServer
8
+
9
+
10
+ class ProcessingLevelEndpoint(HydroServerEndpoint):
11
+ """
12
+ An endpoint for interacting with processing level entities in the HydroServer service.
13
+
14
+ :ivar _model: The model class associated with this endpoint, set to `ProcessingLevel`.
15
+ :ivar _api_route: The base route of the API, derived from the service.
16
+ :ivar _endpoint_route: The specific route of the endpoint, set to `'processing-levels'`.
17
+ """
18
+
19
+ def __init__(self, service):
20
+ """
21
+ Initialize the ProcessingLevelEndpoint.
22
+
23
+ :param service: The HydroServer service instance to use for requests.
24
+ :type service: HydroServer
25
+ """
26
+
27
+ super().__init__(service)
28
+ self._model = ProcessingLevel
29
+ self._api_route = self._service.api_route
30
+ self._endpoint_route = "processing-levels"
31
+
32
+ def list(
33
+ self,
34
+ include_owned: bool = True,
35
+ include_unowned: bool = True,
36
+ include_templates: bool = True,
37
+ ) -> List[ProcessingLevel]:
38
+ """
39
+ Retrieve a collection of processing levels.
40
+
41
+ :param include_owned: Whether to include owned observed properties.
42
+ :param include_unowned: Whether to include unowned observed properties.
43
+ :param include_templates: Whether to include template observed properties.
44
+ """
45
+
46
+ if (
47
+ include_owned is True
48
+ and include_unowned is True
49
+ and include_templates is True
50
+ ):
51
+ owner = "anyUserOrNoUser"
52
+ elif (
53
+ include_owned is True
54
+ and include_unowned is True
55
+ and include_templates is False
56
+ ):
57
+ owner = "anyUser"
58
+ elif (
59
+ include_owned is True
60
+ and include_unowned is False
61
+ and include_templates is True
62
+ ):
63
+ owner = "currentUserOrNoUser"
64
+ elif (
65
+ include_owned is True
66
+ and include_unowned is False
67
+ and include_templates is False
68
+ ):
69
+ owner = "currentUser"
70
+ elif (
71
+ include_owned is False
72
+ and include_unowned is False
73
+ and include_templates is True
74
+ ):
75
+ owner = "noUser"
76
+ else:
77
+ return []
78
+
79
+ return super()._get(params={"owner": owner})
80
+
81
+ @expand_docstring(include_uid=True)
82
+ def get(self, uid: Union[UUID, str]) -> ProcessingLevel:
83
+ """
84
+ Retrieve a processing level owned by the logged-in user.
85
+ """
86
+
87
+ return super()._get(uid)
88
+
89
+ @expand_docstring(model=ProcessingLevel)
90
+ def create(self, **kwargs) -> ProcessingLevel:
91
+ """
92
+ Create a new processing level in HydroServer.
93
+ """
94
+
95
+ return super()._post(**kwargs)
96
+
97
+ @expand_docstring(model=ProcessingLevel, include_uid=True)
98
+ def update(self, uid: Union[UUID, str], **kwargs) -> ProcessingLevel:
99
+ """
100
+ Update an existing processing level in HydroServer.
101
+ """
102
+
103
+ return super()._patch(uid=uid, **kwargs)
104
+
105
+ @expand_docstring(include_uid=True)
106
+ def delete(self, uid: Union[UUID, str]) -> None:
107
+ """
108
+ Delete an existing processing level in HydroServer.
109
+ """
110
+
111
+ super()._delete(uid=uid)
@@ -0,0 +1,111 @@
1
+ from typing import List, Union, TYPE_CHECKING
2
+ from uuid import UUID
3
+ from hydroserverpy.core.endpoints.base import HydroServerEndpoint, expand_docstring
4
+ from hydroserverpy.core.schemas import ResultQualifier
5
+
6
+ if TYPE_CHECKING:
7
+ from hydroserverpy.core.service import HydroServer
8
+
9
+
10
+ class ResultQualifierEndpoint(HydroServerEndpoint):
11
+ """
12
+ An endpoint for interacting with result qualifier entities in the HydroServer service.
13
+
14
+ :ivar _model: The model class associated with this endpoint, set to `ResultQualifier`.
15
+ :ivar _api_route: The base route of the API, derived from the service.
16
+ :ivar _endpoint_route: The specific route of the endpoint, set to `'result-qualifiers'`.
17
+ """
18
+
19
+ def __init__(self, service: "HydroServer"):
20
+ """
21
+ Initialize the ResultQualifierEndpoint.
22
+
23
+ :param service: The HydroServer service instance to use for requests.
24
+ :type service: HydroServer
25
+ """
26
+
27
+ super().__init__(service)
28
+ self._model = ResultQualifier
29
+ self._api_route = self._service.api_route
30
+ self._endpoint_route = "result-qualifiers"
31
+
32
+ def list(
33
+ self,
34
+ include_owned: bool = True,
35
+ include_unowned: bool = True,
36
+ include_templates: bool = True,
37
+ ) -> List[ResultQualifier]:
38
+ """
39
+ Retrieve a collection of result qualifiers.
40
+
41
+ :param include_owned: Whether to include owned observed properties.
42
+ :param include_unowned: Whether to include unowned observed properties.
43
+ :param include_templates: Whether to include template observed properties.
44
+ """
45
+
46
+ if (
47
+ include_owned is True
48
+ and include_unowned is True
49
+ and include_templates is True
50
+ ):
51
+ owner = "anyUserOrNoUser"
52
+ elif (
53
+ include_owned is True
54
+ and include_unowned is True
55
+ and include_templates is False
56
+ ):
57
+ owner = "anyUser"
58
+ elif (
59
+ include_owned is True
60
+ and include_unowned is False
61
+ and include_templates is True
62
+ ):
63
+ owner = "currentUserOrNoUser"
64
+ elif (
65
+ include_owned is True
66
+ and include_unowned is False
67
+ and include_templates is False
68
+ ):
69
+ owner = "currentUser"
70
+ elif (
71
+ include_owned is False
72
+ and include_unowned is False
73
+ and include_templates is True
74
+ ):
75
+ owner = "noUser"
76
+ else:
77
+ return []
78
+
79
+ return super()._get(params={"owner": owner})
80
+
81
+ @expand_docstring(include_uid=True)
82
+ def get(self, uid: Union[UUID, str]) -> ResultQualifier:
83
+ """
84
+ Retrieve a result qualifier owned by the logged-in user.
85
+ """
86
+
87
+ return super()._get(uid)
88
+
89
+ @expand_docstring(model=ResultQualifier)
90
+ def create(self, **kwargs) -> ResultQualifier:
91
+ """
92
+ Create a new result qualifier in HydroServer.
93
+ """
94
+
95
+ return super()._post(**kwargs)
96
+
97
+ @expand_docstring(model=ResultQualifier, include_uid=True)
98
+ def update(self, uid: Union[UUID, str], **kwargs) -> ResultQualifier:
99
+ """
100
+ Update an existing result qualifier in HydroServer.
101
+ """
102
+
103
+ return super()._patch(uid=uid, **kwargs)
104
+
105
+ @expand_docstring(include_uid=True)
106
+ def delete(self, uid: Union[UUID, str]) -> None:
107
+ """
108
+ Delete an existing result qualifier in HydroServer.
109
+ """
110
+
111
+ super()._delete(uid=uid)
@@ -0,0 +1,111 @@
1
+ from typing import List, Union, TYPE_CHECKING
2
+ from uuid import UUID
3
+ from hydroserverpy.core.endpoints.base import HydroServerEndpoint, expand_docstring
4
+ from hydroserverpy.core.schemas import Sensor
5
+
6
+ if TYPE_CHECKING:
7
+ from hydroserverpy.core.service import HydroServer
8
+
9
+
10
+ class SensorEndpoint(HydroServerEndpoint):
11
+ """
12
+ An endpoint for interacting with sensor entities in the HydroServer service.
13
+
14
+ :ivar _model: The model class associated with this endpoint, set to `Sensor`.
15
+ :ivar _api_route: The base route of the API, derived from the service.
16
+ :ivar _endpoint_route: The specific route of the endpoint, set to `'sensors'`.
17
+ """
18
+
19
+ def __init__(self, service: "HydroServer"):
20
+ """
21
+ Initialize the SensorEndpoint.
22
+
23
+ :param service: The HydroServer service instance to use for requests.
24
+ :type service: HydroServer
25
+ """
26
+
27
+ super().__init__(service)
28
+ self._model = Sensor
29
+ self._api_route = self._service.api_route
30
+ self._endpoint_route = "sensors"
31
+
32
+ def list(
33
+ self,
34
+ include_owned: bool = True,
35
+ include_unowned: bool = True,
36
+ include_templates: bool = True,
37
+ ) -> List[Sensor]:
38
+ """
39
+ Retrieve a collection of sensors.
40
+
41
+ :param include_owned: Whether to include owned observed properties.
42
+ :param include_unowned: Whether to include unowned observed properties.
43
+ :param include_templates: Whether to include template observed properties.
44
+ """
45
+
46
+ if (
47
+ include_owned is True
48
+ and include_unowned is True
49
+ and include_templates is True
50
+ ):
51
+ owner = "anyUserOrNoUser"
52
+ elif (
53
+ include_owned is True
54
+ and include_unowned is True
55
+ and include_templates is False
56
+ ):
57
+ owner = "anyUser"
58
+ elif (
59
+ include_owned is True
60
+ and include_unowned is False
61
+ and include_templates is True
62
+ ):
63
+ owner = "currentUserOrNoUser"
64
+ elif (
65
+ include_owned is True
66
+ and include_unowned is False
67
+ and include_templates is False
68
+ ):
69
+ owner = "currentUser"
70
+ elif (
71
+ include_owned is False
72
+ and include_unowned is False
73
+ and include_templates is True
74
+ ):
75
+ owner = "noUser"
76
+ else:
77
+ return []
78
+
79
+ return super()._get(params={"owner": owner})
80
+
81
+ @expand_docstring(include_uid=True)
82
+ def get(self, uid: Union[UUID, str]) -> Sensor:
83
+ """
84
+ Retrieve a sensor owned by the logged-in user.
85
+ """
86
+
87
+ return super()._get(uid)
88
+
89
+ @expand_docstring(model=Sensor)
90
+ def create(self, **kwargs) -> Sensor:
91
+ """
92
+ Create a new sensor in HydroServer.
93
+ """
94
+
95
+ return super()._post(**kwargs)
96
+
97
+ @expand_docstring(model=Sensor, include_uid=True)
98
+ def update(self, uid: Union[UUID, str], **kwargs) -> Sensor:
99
+ """
100
+ Update an existing sensor in HydroServer.
101
+ """
102
+
103
+ return super()._patch(uid=uid, **kwargs)
104
+
105
+ @expand_docstring(include_uid=True)
106
+ def delete(self, uid: Union[UUID, str]) -> None:
107
+ """
108
+ Delete an existing sensor in HydroServer.
109
+ """
110
+
111
+ super()._delete(uid=uid)
@@ -0,0 +1,261 @@
1
+ import json
2
+ from typing import Union, List, IO, TYPE_CHECKING
3
+ from uuid import UUID
4
+ from hydroserverpy.core.endpoints.base import HydroServerEndpoint, expand_docstring
5
+ from hydroserverpy.core.endpoints.datastreams import DatastreamEndpoint
6
+ from hydroserverpy.core.schemas import Thing, Datastream, Tag, Photo, Archive
7
+
8
+ if TYPE_CHECKING:
9
+ from hydroserverpy.core.service import HydroServer
10
+
11
+
12
+ class ThingEndpoint(HydroServerEndpoint):
13
+ """
14
+ An endpoint for interacting with thing entities in the HydroServer service.
15
+
16
+ :ivar _model: The model class associated with this endpoint, set to `Thing`.
17
+ :ivar _api_route: The base route of the API, derived from the service.
18
+ :ivar _endpoint_route: The specific route of the endpoint, set to `'things'`.
19
+ """
20
+
21
+ def __init__(self, service: "HydroServer"):
22
+ """
23
+ Initialize the ThingEndpoint.
24
+
25
+ :param service: The HydroServer service instance to use for requests.
26
+ :type service: HydroServer
27
+ """
28
+
29
+ super().__init__(service)
30
+ self._model = Thing
31
+ self._api_route = self._service.api_route
32
+ self._endpoint_route = "things"
33
+
34
+ def list(
35
+ self, owned_only: bool = False, primary_owned_only: bool = False
36
+ ) -> List[Thing]:
37
+ """
38
+ Retrieve a collection of things owned by the logged-in user.
39
+
40
+ :param owned_only: Only list things owned by the logged-in user.
41
+ :param primary_owned_only: Only list things primary owned by the logged-in user.
42
+ """
43
+
44
+ return super()._get(
45
+ params={
46
+ "owned_only": owned_only,
47
+ "primary_owned_only": primary_owned_only,
48
+ }
49
+ )
50
+
51
+ @expand_docstring(include_uid=True)
52
+ def get(self, uid: Union[UUID, str]) -> Thing:
53
+ """
54
+ Retrieve a thing owned by the logged-in user.
55
+ """
56
+
57
+ return super()._get(uid)
58
+
59
+ @expand_docstring(model=Thing)
60
+ def create(self, **kwargs) -> Thing:
61
+ """
62
+ Create a new thing in HydroServer.
63
+ """
64
+
65
+ return super()._post(**kwargs)
66
+
67
+ @expand_docstring(model=Thing, include_uid=True)
68
+ def update(self, uid: Union[UUID, str], **kwargs) -> Thing:
69
+ """
70
+ Update an existing thing in HydroServer.
71
+ """
72
+
73
+ return super()._patch(uid=uid, **kwargs)
74
+
75
+ @expand_docstring(include_uid=True)
76
+ def delete(self, uid: Union[UUID, str]) -> None:
77
+ """
78
+ Delete an existing thing in HydroServer.
79
+ """
80
+
81
+ super()._delete(uid=uid)
82
+
83
+ def list_datastreams(self, uid: Union[UUID, str]) -> List[Datastream]:
84
+ """
85
+ List all datastreams associated with a specific thing.
86
+
87
+ :param uid: The unique identifier of the thing.
88
+ :type uid: UUID or str
89
+ :returns: A list of datastream instances.
90
+ :rtype: List[Datastream]
91
+ """
92
+
93
+ response = getattr(self._service, "_request")(
94
+ "get",
95
+ f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/datastreams",
96
+ )
97
+
98
+ endpoint = DatastreamEndpoint(self._service)
99
+
100
+ return [
101
+ Datastream(_endpoint=endpoint, _uid=UUID(str(entity.pop("id"))), **entity)
102
+ for entity in json.loads(response.content)
103
+ ]
104
+
105
+ def list_tags(self, uid: Union[UUID, str]) -> List[Tag]:
106
+ """
107
+ List all tags associated with a specific thing.
108
+
109
+ :param uid: The unique identifier of the thing.
110
+ :type uid: UUID or str
111
+ :returns: A list of tag instances.
112
+ :rtype: List[Tag]
113
+ """
114
+
115
+ response = getattr(self._service, "_request")(
116
+ "get", f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/tags"
117
+ )
118
+
119
+ return [
120
+ Tag(_uid=UUID(str(entity.pop("id"))), **entity)
121
+ for entity in json.loads(response.content)
122
+ ]
123
+
124
+ def create_tag(self, uid: Union[UUID, str], key: str, value: str) -> Tag:
125
+ """
126
+ Create a new tag for a specific thing.
127
+
128
+ :param uid: The unique identifier of the thing.
129
+ :type uid: UUID or str
130
+ :param key: The key of the tag.
131
+ :type key: str
132
+ :param value: The value of the tag.
133
+ :type value: str
134
+ :returns: The created tag instance.
135
+ :rtype: Tag
136
+ """
137
+
138
+ response = getattr(self._service, "_request")(
139
+ "post",
140
+ f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/tags",
141
+ headers={"Content-type": "application/json"},
142
+ data=Tag(key=key, value=value).json(exclude_unset=True, by_alias=True),
143
+ )
144
+ entity = json.loads(response.content)
145
+
146
+ return Tag(_uid=UUID(str(entity.pop("id"))), **entity)
147
+
148
+ def update_tag(
149
+ self, uid: Union[UUID, str], tag_uid: Union[UUID, str], value: str
150
+ ) -> Tag:
151
+ """
152
+ Update an existing tag for a specific thing.
153
+
154
+ :param uid: The unique identifier of the thing.
155
+ :type uid: UUID or str
156
+ :param tag_uid: The unique identifier of the tag.
157
+ :type tag_uid: UUID or str
158
+ :param value: The new value for the tag.
159
+ :type value: str
160
+ :returns: The updated tag instance.
161
+ :rtype: Tag
162
+ """
163
+
164
+ response = getattr(self._service, "_request")(
165
+ "patch",
166
+ f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/tags/{str(tag_uid)}",
167
+ headers={"Content-type": "application/json"},
168
+ data=json.dumps({"value": str(value)}),
169
+ )
170
+ entity = json.loads(response.content)
171
+
172
+ return Tag(_uid=UUID(str(entity.pop("id"))), **entity)
173
+
174
+ def delete_tag(self, uid: Union[UUID, str], tag_uid: Union[UUID, str]) -> None:
175
+ """
176
+ Delete a tag from a specific thing.
177
+
178
+ :param uid: The unique identifier of the thing.
179
+ :type uid: UUID or str
180
+ :param tag_uid: The unique identifier of the tag.
181
+ :type tag_uid: UUID or str
182
+ """
183
+
184
+ getattr(self._service, "_request")(
185
+ "delete",
186
+ f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/tags/{str(tag_uid)}",
187
+ )
188
+
189
+ def list_photos(self, uid: Union[UUID, str]) -> List[Photo]:
190
+ """
191
+ List all photos associated with a specific thing.
192
+
193
+ :param uid: The unique identifier of the thing.
194
+ :type uid: UUID or str
195
+ :returns: A list of photo instances.
196
+ :rtype: List[Photo]
197
+ """
198
+
199
+ response = getattr(self._service, "_request")(
200
+ "get", f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/photos"
201
+ )
202
+
203
+ return [
204
+ Photo(_uid=UUID(str(entity.pop("id"))), **entity)
205
+ for entity in json.loads(response.content)
206
+ ]
207
+
208
+ def upload_photo(self, uid: Union[UUID, str], file: IO) -> List[Photo]:
209
+ """
210
+ Upload a new photo to a specific thing.
211
+
212
+ :param uid: The unique identifier of the thing.
213
+ :type uid: UUID or str
214
+ :param file: The file-like object representing the photo to upload.
215
+ :type file: IO
216
+ :returns: A list of photo instances created by the upload.
217
+ :rtype: List[Photo]
218
+ """
219
+
220
+ response = getattr(self._service, "_request")(
221
+ "post",
222
+ f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/photos",
223
+ files={"files": file},
224
+ )
225
+
226
+ return [
227
+ Photo(_uid=UUID(str(entity.pop("id"))), **entity)
228
+ for entity in json.loads(response.content)
229
+ ]
230
+
231
+ def delete_photo(self, uid: Union[UUID, str], photo_uid: Union[UUID, str]) -> None:
232
+ """
233
+ Delete a photo from a specific thing.
234
+
235
+ :param uid: The unique identifier of the thing.
236
+ :type uid: UUID or str
237
+ :param photo_uid: The unique identifier of the photo.
238
+ :type photo_uid: UUID or str
239
+ """
240
+
241
+ getattr(self._service, "_request")(
242
+ "delete",
243
+ f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/photos/{str(photo_uid)}",
244
+ )
245
+
246
+ def get_archive(self, uid: Union[UUID, str]) -> Archive:
247
+ """
248
+ Retrieve the archive associated with a specific thing.
249
+
250
+ :param uid: The unique identifier of the thing.
251
+ :type uid: UUID or str
252
+ :returns: The archive instance associated with the thing.
253
+ :rtype: Archive
254
+ """
255
+
256
+ response = getattr(self._service, "_request")(
257
+ "get", f"{self._api_route}/data/{self._endpoint_route}/{str(uid)}/archive"
258
+ )
259
+ entity = json.loads(response.content)
260
+
261
+ return Archive(_uid=UUID(str(entity.pop("id"))), **entity)