maleo-metadata-client 0.1.50__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.
@@ -0,0 +1,313 @@
1
+ import json
2
+ from copy import deepcopy
3
+ from datetime import datetime, timezone
4
+ from typing import Literal, overload
5
+ from uuid import UUID
6
+ from maleo.client.maleo.config import MaleoMetadataClientConfig
7
+ from maleo.client.maleo.service import MaleoClientService
8
+ from maleo.database.enums import Connection
9
+ from maleo.database.utils import build_cache_key
10
+ from maleo.enums.cardinality import Cardinality
11
+ from maleo.enums.connection import Header
12
+ from maleo.logging.enums import Level
13
+ from maleo.metadata.constants.medical_service import MEDICAL_SERVICE_RESOURCE
14
+ from maleo.metadata.enums.medical_service import Granularity
15
+ from maleo.metadata.mixins.medical_service import is_id_identifier
16
+ from maleo.metadata.schemas.medical_service import (
17
+ ReadMultipleParameter,
18
+ ReadSingleParameter,
19
+ StandardMedicalServiceSchema,
20
+ FullMedicalServiceSchema,
21
+ )
22
+ from maleo.metadata.utils.medical_service import get_schema_model
23
+ from maleo.schemas.connection import ConnectionContext
24
+ from maleo.schemas.exception.factory import MaleoExceptionFactory
25
+ from maleo.schemas.operation.action.resource import ReadResourceOperationAction
26
+ from maleo.schemas.operation.enums import OperationType, Target
27
+ from maleo.schemas.operation.mixins import Timestamp
28
+ from maleo.schemas.operation.resource import (
29
+ ReadMultipleResourceOperation,
30
+ ReadSingleResourceOperation,
31
+ )
32
+ from maleo.schemas.pagination import StrictPagination
33
+ from maleo.schemas.resource import AggregateField
34
+ from maleo.schemas.response import (
35
+ MultipleDataResponse,
36
+ ReadMultipleDataResponse,
37
+ SingleDataResponse,
38
+ ReadSingleDataResponse,
39
+ )
40
+ from maleo.schemas.security.authorization import (
41
+ OptAnyAuthorization,
42
+ AnyAuthorization,
43
+ AuthorizationFactory,
44
+ )
45
+ from maleo.schemas.security.impersonation import OptImpersonation
46
+ from maleo.types.dict import OptStrToStrDict
47
+ from maleo.utils.merger import merge_dicts
48
+
49
+
50
+ class MedicalServiceClientService(MaleoClientService[MaleoMetadataClientConfig]):
51
+ resource = MEDICAL_SERVICE_RESOURCE
52
+
53
+ @overload
54
+ async def read(
55
+ self,
56
+ cardinality: Literal[Cardinality.MULTIPLE],
57
+ granularity: Literal[Granularity.STANDARD],
58
+ *,
59
+ operation_id: UUID,
60
+ connection_context: ConnectionContext,
61
+ authorization: AnyAuthorization,
62
+ impersonation: OptImpersonation = None,
63
+ parameters: ReadMultipleParameter,
64
+ headers: OptStrToStrDict = None,
65
+ ) -> ReadMultipleDataResponse[
66
+ StandardMedicalServiceSchema, StrictPagination, None
67
+ ]: ...
68
+ @overload
69
+ async def read(
70
+ self,
71
+ cardinality: Literal[Cardinality.MULTIPLE],
72
+ granularity: Literal[Granularity.FULL],
73
+ *,
74
+ operation_id: UUID,
75
+ connection_context: ConnectionContext,
76
+ authorization: AnyAuthorization,
77
+ impersonation: OptImpersonation = None,
78
+ parameters: ReadMultipleParameter,
79
+ headers: OptStrToStrDict = None,
80
+ ) -> ReadMultipleDataResponse[FullMedicalServiceSchema, StrictPagination, None]: ...
81
+ @overload
82
+ async def read(
83
+ self,
84
+ cardinality: Literal[Cardinality.SINGLE],
85
+ granularity: Literal[Granularity.STANDARD],
86
+ *,
87
+ operation_id: UUID,
88
+ connection_context: ConnectionContext,
89
+ authorization: AnyAuthorization,
90
+ impersonation: OptImpersonation = None,
91
+ parameters: ReadSingleParameter,
92
+ headers: OptStrToStrDict = None,
93
+ ) -> ReadSingleDataResponse[StandardMedicalServiceSchema, None]: ...
94
+ @overload
95
+ async def read(
96
+ self,
97
+ cardinality: Literal[Cardinality.SINGLE],
98
+ granularity: Literal[Granularity.FULL],
99
+ *,
100
+ operation_id: UUID,
101
+ connection_context: ConnectionContext,
102
+ authorization: AnyAuthorization,
103
+ impersonation: OptImpersonation = None,
104
+ parameters: ReadSingleParameter,
105
+ headers: OptStrToStrDict = None,
106
+ ) -> ReadSingleDataResponse[FullMedicalServiceSchema, None]: ...
107
+ async def read(
108
+ self,
109
+ cardinality: Cardinality,
110
+ granularity: Granularity,
111
+ *,
112
+ operation_id: UUID,
113
+ connection_context: ConnectionContext,
114
+ authorization: OptAnyAuthorization = None,
115
+ impersonation: OptImpersonation = None,
116
+ parameters: ReadMultipleParameter | ReadSingleParameter,
117
+ headers: OptStrToStrDict = None,
118
+ ) -> (
119
+ ReadMultipleDataResponse[StandardMedicalServiceSchema, StrictPagination, None]
120
+ | ReadMultipleDataResponse[FullMedicalServiceSchema, StrictPagination, None]
121
+ | ReadSingleDataResponse[StandardMedicalServiceSchema, None]
122
+ | ReadSingleDataResponse[FullMedicalServiceSchema, None]
123
+ ):
124
+ redis_client = self._redis.manager.client.get(Connection.ASYNC)
125
+ data_model_cls = get_schema_model(granularity)
126
+
127
+ executed_at = datetime.now(tz=timezone.utc)
128
+
129
+ # Define arguments being used in this function
130
+ positional_arguments = [cardinality, granularity]
131
+ keyword_arguments = {
132
+ "authorization": (
133
+ authorization.model_dump(mode="json")
134
+ if authorization is not None
135
+ else None
136
+ ),
137
+ "parameters": parameters.model_dump(mode="json"),
138
+ }
139
+
140
+ # Define full function string
141
+ ext = f"({json.dumps(positional_arguments)}|{json.dumps(keyword_arguments)})"
142
+
143
+ # Define full cache_key
144
+ cache_key = build_cache_key(ext, namespace=self._namespace)
145
+
146
+ if parameters.use_cache:
147
+ # Initialize cache operation context
148
+ operation_context = deepcopy(self._operation_context)
149
+ operation_context.target.type = Target.CACHE
150
+
151
+ redis_response_str = await redis_client.get(cache_key)
152
+
153
+ if redis_response_str is not None:
154
+ operation_timestamp = Timestamp.completed_now(executed_at)
155
+ if cardinality is Cardinality.MULTIPLE:
156
+ response = ReadMultipleDataResponse[
157
+ data_model_cls, StrictPagination, None
158
+ ].model_validate_json(redis_response_str)
159
+ operation = ReadMultipleResourceOperation[
160
+ data_model_cls, StrictPagination, None
161
+ ](
162
+ application_context=self._application_context,
163
+ id=operation_id,
164
+ context=operation_context,
165
+ resource=self.resource,
166
+ timestamp=operation_timestamp,
167
+ summary=f"Successfully read multiple {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from cache",
168
+ connection_context=connection_context,
169
+ authentication=None,
170
+ authorization=authorization,
171
+ impersonation=impersonation,
172
+ response=response,
173
+ )
174
+ operation.log(self._logger, Level.INFO)
175
+ operation.publish(self._logger, self._publishers)
176
+ elif cardinality is Cardinality.SINGLE:
177
+ response = ReadSingleDataResponse[
178
+ data_model_cls, None
179
+ ].model_validate_json(redis_response_str)
180
+ operation = ReadSingleResourceOperation[data_model_cls, None](
181
+ application_context=self._application_context,
182
+ id=operation_id,
183
+ context=operation_context,
184
+ resource=self.resource,
185
+ timestamp=operation_timestamp,
186
+ summary=f"Successfully read single {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from cache",
187
+ connection_context=connection_context,
188
+ authentication=None,
189
+ authorization=authorization,
190
+ impersonation=impersonation,
191
+ response=response,
192
+ )
193
+ operation.log(self._logger, Level.INFO)
194
+ operation.publish(self._logger, self._publishers)
195
+
196
+ return response # type: ignore
197
+
198
+ operation_context = deepcopy(self._operation_context)
199
+ operation_context.target.type = Target.MICROSERVICE
200
+
201
+ async with self._http_client_manager.get() as http_client:
202
+ base_headers = {
203
+ Header.CONTENT_TYPE.value: "application/json",
204
+ Header.X_OPERATION_ID.value: str(operation_id),
205
+ }
206
+ if impersonation is not None:
207
+ base_headers[Header.X_USER_ID.value] = str(impersonation.user_id)
208
+ if impersonation.organization_id is not None:
209
+ base_headers[Header.X_ORGANIZATION_ID.value] = str(
210
+ impersonation.organization_id
211
+ )
212
+
213
+ if headers is not None:
214
+ headers = merge_dicts(base_headers, headers)
215
+ else:
216
+ headers = base_headers
217
+
218
+ if authorization is not None:
219
+ auth = AuthorizationFactory.httpx_auth(
220
+ scheme=authorization.scheme, authorization=authorization.credentials
221
+ )
222
+ else:
223
+ auth = None
224
+
225
+ base_url = f"{self._config.url}/v1/{self.resource.identifiers[-1].slug}/"
226
+ if isinstance(parameters, ReadMultipleParameter):
227
+ url = base_url
228
+ elif isinstance(parameters, ReadSingleParameter):
229
+ if is_id_identifier(parameters.identifier):
230
+ url = base_url + str(parameters.identifier.value)
231
+ else:
232
+ url = (
233
+ base_url
234
+ + f"{parameters.identifier.type}/{parameters.identifier.value}"
235
+ )
236
+
237
+ params = parameters.to_query_params()
238
+
239
+ response = await http_client.get(
240
+ url, params=params, headers=headers, auth=auth
241
+ )
242
+
243
+ operation_timestamp = Timestamp.completed_now(executed_at)
244
+
245
+ if response.is_error:
246
+ exc = MaleoExceptionFactory.from_httpx(
247
+ response,
248
+ operation_type=OperationType.REQUEST,
249
+ application_context=self._application_context,
250
+ operation_id=operation_id,
251
+ operation_context=operation_context,
252
+ operation_action=ReadResourceOperationAction(),
253
+ operation_timestamp=operation_timestamp,
254
+ connection_context=connection_context,
255
+ authentication=None,
256
+ authorization=authorization,
257
+ impersonation=impersonation,
258
+ logger=self._logger,
259
+ )
260
+ exc.log_and_publish_operation(self._logger, self._publishers)
261
+ raise exc
262
+
263
+ if isinstance(parameters, ReadMultipleParameter):
264
+ validated_response = MultipleDataResponse[
265
+ data_model_cls, StrictPagination, None
266
+ ].model_validate(response.json())
267
+ service_response = ReadMultipleDataResponse[
268
+ data_model_cls, StrictPagination, None
269
+ ].new(
270
+ data=validated_response.data,
271
+ pagination=validated_response.pagination,
272
+ )
273
+ operation = ReadMultipleResourceOperation[
274
+ data_model_cls, StrictPagination, None
275
+ ](
276
+ application_context=self._application_context,
277
+ id=operation_id,
278
+ context=operation_context,
279
+ resource=self.resource,
280
+ timestamp=operation_timestamp,
281
+ summary=f"Successfully read multiple {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from microservice",
282
+ connection_context=connection_context,
283
+ authentication=None,
284
+ authorization=authorization,
285
+ impersonation=impersonation,
286
+ response=service_response,
287
+ )
288
+ operation.log(self._logger, Level.INFO)
289
+ operation.publish(self._logger, self._publishers)
290
+ elif isinstance(parameters, ReadSingleParameter):
291
+ validated_response = SingleDataResponse[
292
+ data_model_cls, None
293
+ ].model_validate(response.json())
294
+ service_response = ReadSingleDataResponse[data_model_cls, None].new(
295
+ data=validated_response.data,
296
+ )
297
+ operation = ReadSingleResourceOperation[data_model_cls, None](
298
+ application_context=self._application_context,
299
+ id=operation_id,
300
+ context=operation_context,
301
+ resource=self.resource,
302
+ timestamp=operation_timestamp,
303
+ summary=f"Successfully read single {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from microservice",
304
+ connection_context=connection_context,
305
+ authentication=None,
306
+ authorization=authorization,
307
+ impersonation=impersonation,
308
+ response=service_response,
309
+ )
310
+ operation.log(self._logger, Level.INFO)
311
+ operation.publish(self._logger, self._publishers)
312
+
313
+ return service_response # type: ignore
@@ -0,0 +1,315 @@
1
+ import json
2
+ from copy import deepcopy
3
+ from datetime import datetime, timezone
4
+ from typing import Literal, overload
5
+ from uuid import UUID
6
+ from maleo.client.maleo.config import MaleoMetadataClientConfig
7
+ from maleo.client.maleo.service import MaleoClientService
8
+ from maleo.database.enums import Connection
9
+ from maleo.database.utils import build_cache_key
10
+ from maleo.enums.cardinality import Cardinality
11
+ from maleo.enums.connection import Header
12
+ from maleo.logging.enums import Level
13
+ from maleo.metadata.constants.organization_role import ORGANIZATION_ROLE_RESOURCE
14
+ from maleo.metadata.enums.organization_role import Granularity
15
+ from maleo.metadata.mixins.organization_role import is_id_identifier
16
+ from maleo.metadata.schemas.organization_role import (
17
+ ReadMultipleParameter,
18
+ ReadSingleParameter,
19
+ StandardOrganizationRoleSchema,
20
+ FullOrganizationRoleSchema,
21
+ )
22
+ from maleo.metadata.utils.organization_role import get_schema_model
23
+ from maleo.schemas.connection import ConnectionContext
24
+ from maleo.schemas.exception.factory import MaleoExceptionFactory
25
+ from maleo.schemas.operation.action.resource import ReadResourceOperationAction
26
+ from maleo.schemas.operation.enums import OperationType, Target
27
+ from maleo.schemas.operation.mixins import Timestamp
28
+ from maleo.schemas.operation.resource import (
29
+ ReadMultipleResourceOperation,
30
+ ReadSingleResourceOperation,
31
+ )
32
+ from maleo.schemas.pagination import StrictPagination
33
+ from maleo.schemas.resource import AggregateField
34
+ from maleo.schemas.response import (
35
+ MultipleDataResponse,
36
+ ReadMultipleDataResponse,
37
+ SingleDataResponse,
38
+ ReadSingleDataResponse,
39
+ )
40
+ from maleo.schemas.security.authorization import (
41
+ OptAnyAuthorization,
42
+ AnyAuthorization,
43
+ AuthorizationFactory,
44
+ )
45
+ from maleo.schemas.security.impersonation import OptImpersonation
46
+ from maleo.types.dict import OptStrToStrDict
47
+ from maleo.utils.merger import merge_dicts
48
+
49
+
50
+ class OrganizationRoleClientService(MaleoClientService[MaleoMetadataClientConfig]):
51
+ resource = ORGANIZATION_ROLE_RESOURCE
52
+
53
+ @overload
54
+ async def read(
55
+ self,
56
+ cardinality: Literal[Cardinality.MULTIPLE],
57
+ granularity: Literal[Granularity.STANDARD],
58
+ *,
59
+ operation_id: UUID,
60
+ connection_context: ConnectionContext,
61
+ authorization: AnyAuthorization,
62
+ impersonation: OptImpersonation = None,
63
+ parameters: ReadMultipleParameter,
64
+ headers: OptStrToStrDict = None,
65
+ ) -> ReadMultipleDataResponse[
66
+ StandardOrganizationRoleSchema, StrictPagination, None
67
+ ]: ...
68
+ @overload
69
+ async def read(
70
+ self,
71
+ cardinality: Literal[Cardinality.MULTIPLE],
72
+ granularity: Literal[Granularity.FULL],
73
+ *,
74
+ operation_id: UUID,
75
+ connection_context: ConnectionContext,
76
+ authorization: AnyAuthorization,
77
+ impersonation: OptImpersonation = None,
78
+ parameters: ReadMultipleParameter,
79
+ headers: OptStrToStrDict = None,
80
+ ) -> ReadMultipleDataResponse[
81
+ FullOrganizationRoleSchema, StrictPagination, None
82
+ ]: ...
83
+ @overload
84
+ async def read(
85
+ self,
86
+ cardinality: Literal[Cardinality.SINGLE],
87
+ granularity: Literal[Granularity.STANDARD],
88
+ *,
89
+ operation_id: UUID,
90
+ connection_context: ConnectionContext,
91
+ authorization: AnyAuthorization,
92
+ impersonation: OptImpersonation = None,
93
+ parameters: ReadSingleParameter,
94
+ headers: OptStrToStrDict = None,
95
+ ) -> ReadSingleDataResponse[StandardOrganizationRoleSchema, None]: ...
96
+ @overload
97
+ async def read(
98
+ self,
99
+ cardinality: Literal[Cardinality.SINGLE],
100
+ granularity: Literal[Granularity.FULL],
101
+ *,
102
+ operation_id: UUID,
103
+ connection_context: ConnectionContext,
104
+ authorization: AnyAuthorization,
105
+ impersonation: OptImpersonation = None,
106
+ parameters: ReadSingleParameter,
107
+ headers: OptStrToStrDict = None,
108
+ ) -> ReadSingleDataResponse[FullOrganizationRoleSchema, None]: ...
109
+ async def read(
110
+ self,
111
+ cardinality: Cardinality,
112
+ granularity: Granularity,
113
+ *,
114
+ operation_id: UUID,
115
+ connection_context: ConnectionContext,
116
+ authorization: OptAnyAuthorization = None,
117
+ impersonation: OptImpersonation = None,
118
+ parameters: ReadMultipleParameter | ReadSingleParameter,
119
+ headers: OptStrToStrDict = None,
120
+ ) -> (
121
+ ReadMultipleDataResponse[StandardOrganizationRoleSchema, StrictPagination, None]
122
+ | ReadMultipleDataResponse[FullOrganizationRoleSchema, StrictPagination, None]
123
+ | ReadSingleDataResponse[StandardOrganizationRoleSchema, None]
124
+ | ReadSingleDataResponse[FullOrganizationRoleSchema, None]
125
+ ):
126
+ redis_client = self._redis.manager.client.get(Connection.ASYNC)
127
+ data_model_cls = get_schema_model(granularity)
128
+
129
+ executed_at = datetime.now(tz=timezone.utc)
130
+
131
+ # Define arguments being used in this function
132
+ positional_arguments = [cardinality, granularity]
133
+ keyword_arguments = {
134
+ "authorization": (
135
+ authorization.model_dump(mode="json")
136
+ if authorization is not None
137
+ else None
138
+ ),
139
+ "parameters": parameters.model_dump(mode="json"),
140
+ }
141
+
142
+ # Define full function string
143
+ ext = f"({json.dumps(positional_arguments)}|{json.dumps(keyword_arguments)})"
144
+
145
+ # Define full cache_key
146
+ cache_key = build_cache_key(ext, namespace=self._namespace)
147
+
148
+ if parameters.use_cache:
149
+ # Initialize cache operation context
150
+ operation_context = deepcopy(self._operation_context)
151
+ operation_context.target.type = Target.CACHE
152
+
153
+ redis_response_str = await redis_client.get(cache_key)
154
+
155
+ if redis_response_str is not None:
156
+ operation_timestamp = Timestamp.completed_now(executed_at)
157
+ if cardinality is Cardinality.MULTIPLE:
158
+ response = ReadMultipleDataResponse[
159
+ data_model_cls, StrictPagination, None
160
+ ].model_validate_json(redis_response_str)
161
+ operation = ReadMultipleResourceOperation[
162
+ data_model_cls, StrictPagination, None
163
+ ](
164
+ application_context=self._application_context,
165
+ id=operation_id,
166
+ context=operation_context,
167
+ resource=self.resource,
168
+ timestamp=operation_timestamp,
169
+ summary=f"Successfully read multiple {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from cache",
170
+ connection_context=connection_context,
171
+ authentication=None,
172
+ authorization=authorization,
173
+ impersonation=impersonation,
174
+ response=response,
175
+ )
176
+ operation.log(self._logger, Level.INFO)
177
+ operation.publish(self._logger, self._publishers)
178
+ elif cardinality is Cardinality.SINGLE:
179
+ response = ReadSingleDataResponse[
180
+ data_model_cls, None
181
+ ].model_validate_json(redis_response_str)
182
+ operation = ReadSingleResourceOperation[data_model_cls, None](
183
+ application_context=self._application_context,
184
+ id=operation_id,
185
+ context=operation_context,
186
+ resource=self.resource,
187
+ timestamp=operation_timestamp,
188
+ summary=f"Successfully read single {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from cache",
189
+ connection_context=connection_context,
190
+ authentication=None,
191
+ authorization=authorization,
192
+ impersonation=impersonation,
193
+ response=response,
194
+ )
195
+ operation.log(self._logger, Level.INFO)
196
+ operation.publish(self._logger, self._publishers)
197
+
198
+ return response # type: ignore
199
+
200
+ operation_context = deepcopy(self._operation_context)
201
+ operation_context.target.type = Target.MICROSERVICE
202
+
203
+ async with self._http_client_manager.get() as http_client:
204
+ base_headers = {
205
+ Header.CONTENT_TYPE.value: "application/json",
206
+ Header.X_OPERATION_ID.value: str(operation_id),
207
+ }
208
+ if impersonation is not None:
209
+ base_headers[Header.X_USER_ID.value] = str(impersonation.user_id)
210
+ if impersonation.organization_id is not None:
211
+ base_headers[Header.X_ORGANIZATION_ID.value] = str(
212
+ impersonation.organization_id
213
+ )
214
+
215
+ if headers is not None:
216
+ headers = merge_dicts(base_headers, headers)
217
+ else:
218
+ headers = base_headers
219
+
220
+ if authorization is not None:
221
+ auth = AuthorizationFactory.httpx_auth(
222
+ scheme=authorization.scheme, authorization=authorization.credentials
223
+ )
224
+ else:
225
+ auth = None
226
+
227
+ base_url = f"{self._config.url}/v1/{self.resource.identifiers[-1].slug}/"
228
+ if isinstance(parameters, ReadMultipleParameter):
229
+ url = base_url
230
+ elif isinstance(parameters, ReadSingleParameter):
231
+ if is_id_identifier(parameters.identifier):
232
+ url = base_url + str(parameters.identifier.value)
233
+ else:
234
+ url = (
235
+ base_url
236
+ + f"{parameters.identifier.type}/{parameters.identifier.value}"
237
+ )
238
+
239
+ params = parameters.to_query_params()
240
+
241
+ response = await http_client.get(
242
+ url, params=params, headers=headers, auth=auth
243
+ )
244
+
245
+ operation_timestamp = Timestamp.completed_now(executed_at)
246
+
247
+ if response.is_error:
248
+ exc = MaleoExceptionFactory.from_httpx(
249
+ response,
250
+ operation_type=OperationType.REQUEST,
251
+ application_context=self._application_context,
252
+ operation_id=operation_id,
253
+ operation_context=operation_context,
254
+ operation_action=ReadResourceOperationAction(),
255
+ operation_timestamp=operation_timestamp,
256
+ connection_context=connection_context,
257
+ authentication=None,
258
+ authorization=authorization,
259
+ impersonation=impersonation,
260
+ logger=self._logger,
261
+ )
262
+ exc.log_and_publish_operation(self._logger, self._publishers)
263
+ raise exc
264
+
265
+ if isinstance(parameters, ReadMultipleParameter):
266
+ validated_response = MultipleDataResponse[
267
+ data_model_cls, StrictPagination, None
268
+ ].model_validate(response.json())
269
+ service_response = ReadMultipleDataResponse[
270
+ data_model_cls, StrictPagination, None
271
+ ].new(
272
+ data=validated_response.data,
273
+ pagination=validated_response.pagination,
274
+ )
275
+ operation = ReadMultipleResourceOperation[
276
+ data_model_cls, StrictPagination, None
277
+ ](
278
+ application_context=self._application_context,
279
+ id=operation_id,
280
+ context=operation_context,
281
+ resource=self.resource,
282
+ timestamp=operation_timestamp,
283
+ summary=f"Successfully read multiple {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from microservice",
284
+ connection_context=connection_context,
285
+ authentication=None,
286
+ authorization=authorization,
287
+ impersonation=impersonation,
288
+ response=service_response,
289
+ )
290
+ operation.log(self._logger, Level.INFO)
291
+ operation.publish(self._logger, self._publishers)
292
+ elif isinstance(parameters, ReadSingleParameter):
293
+ validated_response = SingleDataResponse[
294
+ data_model_cls, None
295
+ ].model_validate(response.json())
296
+ service_response = ReadSingleDataResponse[data_model_cls, None].new(
297
+ data=validated_response.data,
298
+ )
299
+ operation = ReadSingleResourceOperation[data_model_cls, None](
300
+ application_context=self._application_context,
301
+ id=operation_id,
302
+ context=operation_context,
303
+ resource=self.resource,
304
+ timestamp=operation_timestamp,
305
+ summary=f"Successfully read single {granularity} {self.resource.aggregate(AggregateField.NAME, sep=" ").lower()} from microservice",
306
+ connection_context=connection_context,
307
+ authentication=None,
308
+ authorization=authorization,
309
+ impersonation=impersonation,
310
+ response=service_response,
311
+ )
312
+ operation.log(self._logger, Level.INFO)
313
+ operation.publish(self._logger, self._publishers)
314
+
315
+ return service_response # type: ignore