mercuto-client 0.3.0__py3-none-any.whl → 0.3.4a3__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.
- mercuto_client/_tests/test_ingester/test_file_processor.py +171 -13
- mercuto_client/acl.py +20 -0
- mercuto_client/client.py +41 -8
- mercuto_client/ingester/__main__.py +11 -8
- mercuto_client/ingester/processor.py +57 -37
- mercuto_client/mocks/__init__.py +76 -2
- mercuto_client/mocks/_utility.py +6 -0
- mercuto_client/mocks/mock_core.py +44 -0
- mercuto_client/mocks/mock_media.py +117 -0
- mercuto_client/mocks/mock_notifications.py +65 -0
- mercuto_client/modules/__init__.py +8 -4
- mercuto_client/modules/core.py +117 -287
- mercuto_client/modules/data.py +39 -41
- mercuto_client/modules/fatigue.py +19 -19
- mercuto_client/modules/identity.py +31 -31
- mercuto_client/modules/media.py +324 -0
- mercuto_client/modules/notifications.py +88 -0
- mercuto_client/modules/reports.py +222 -0
- mercuto_client/util.py +1 -1
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.4a3.dist-info}/METADATA +1 -1
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.4a3.dist-info}/RECORD +24 -18
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.4a3.dist-info}/WHEEL +0 -0
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.4a3.dist-info}/licenses/LICENSE +0 -0
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.4a3.dist-info}/top_level.txt +0 -0
mercuto_client/modules/data.py
CHANGED
|
@@ -10,7 +10,7 @@ from pydantic import TypeAdapter
|
|
|
10
10
|
|
|
11
11
|
from ..exceptions import MercutoClientException, MercutoHTTPException
|
|
12
12
|
from ..util import batched
|
|
13
|
-
from . import
|
|
13
|
+
from . import PayloadType, raise_for_response
|
|
14
14
|
from ._util import BaseModel, serialise_timedelta
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
@@ -145,14 +145,14 @@ class MercutoDataService:
|
|
|
145
145
|
self._path = path
|
|
146
146
|
|
|
147
147
|
def healthcheck(self) -> Healthcheck:
|
|
148
|
-
r = self._client.
|
|
148
|
+
r = self._client.request(f"{self._path}/healthcheck", "GET")
|
|
149
149
|
return Healthcheck.model_validate_json(r.text)
|
|
150
150
|
|
|
151
151
|
def refresh_continuous_aggregates(self) -> None:
|
|
152
152
|
"""
|
|
153
153
|
Request a refresh of continuous aggregates on all tables
|
|
154
154
|
"""
|
|
155
|
-
self._client.
|
|
155
|
+
self._client.request(f"{self._path}/meta/refresh-aggregates", "POST")
|
|
156
156
|
|
|
157
157
|
"""
|
|
158
158
|
Channels
|
|
@@ -174,9 +174,9 @@ class MercutoDataService:
|
|
|
174
174
|
if metric:
|
|
175
175
|
params['metric'] = metric
|
|
176
176
|
|
|
177
|
-
all_channels = []
|
|
177
|
+
all_channels: list[Channel] = []
|
|
178
178
|
while True:
|
|
179
|
-
r = self._client.
|
|
179
|
+
r = self._client.request(f'{self._path}/channels', 'GET', params=params)
|
|
180
180
|
|
|
181
181
|
channels = _ChannellistAdapter.validate_json(r.text)
|
|
182
182
|
all_channels.extend(channels)
|
|
@@ -186,16 +186,16 @@ class MercutoDataService:
|
|
|
186
186
|
return all_channels
|
|
187
187
|
|
|
188
188
|
def get_channel(self, code: str) -> Optional[Channel]:
|
|
189
|
-
r = self._client.
|
|
189
|
+
r = self._client.request(f'{self._path}/channels/{code}', 'GET', raise_for_status=False)
|
|
190
190
|
if r.status_code == 404:
|
|
191
191
|
return None
|
|
192
|
-
|
|
192
|
+
raise_for_response(r)
|
|
193
193
|
return Channel.model_validate_json(r.text)
|
|
194
194
|
|
|
195
195
|
def update_channel(self, code: str, label: Optional[str] = None, units: Optional[str] = None,
|
|
196
196
|
metric: Optional[str] = None, multiplier: Optional[float] = None,
|
|
197
197
|
offset: Optional[float] = None) -> Channel:
|
|
198
|
-
payload:
|
|
198
|
+
payload: PayloadType = {}
|
|
199
199
|
if label is not None:
|
|
200
200
|
payload['label'] = label
|
|
201
201
|
if units is not None:
|
|
@@ -207,11 +207,11 @@ class MercutoDataService:
|
|
|
207
207
|
if offset is not None:
|
|
208
208
|
payload['offset'] = offset
|
|
209
209
|
|
|
210
|
-
r = self._client.
|
|
210
|
+
r = self._client.request(f'{self._path}/channels/{code}', 'PATCH', json=payload)
|
|
211
211
|
return Channel.model_validate_json(r.text)
|
|
212
212
|
|
|
213
213
|
def delete_channel(self, code: str) -> bool:
|
|
214
|
-
r = self._client.
|
|
214
|
+
r = self._client.request(f'{self._path}/channels/{code}', 'DELETE')
|
|
215
215
|
return r.status_code == 204
|
|
216
216
|
|
|
217
217
|
def create_channel(self, project: str,
|
|
@@ -225,7 +225,7 @@ class MercutoDataService:
|
|
|
225
225
|
aggregate: Optional[str] = None,
|
|
226
226
|
source: Optional[str] = None,
|
|
227
227
|
metric: Optional[str] = None) -> Channel:
|
|
228
|
-
payload:
|
|
228
|
+
payload: PayloadType = {
|
|
229
229
|
'project': project,
|
|
230
230
|
'label': label,
|
|
231
231
|
'classification': classification.value,
|
|
@@ -249,7 +249,7 @@ class MercutoDataService:
|
|
|
249
249
|
if metric is not None:
|
|
250
250
|
payload['metric'] = metric
|
|
251
251
|
|
|
252
|
-
r = self._client.
|
|
252
|
+
r = self._client.request(f'{self._path}/channels', 'PUT', json=payload)
|
|
253
253
|
return Channel.model_validate_json(r.text)
|
|
254
254
|
|
|
255
255
|
"""
|
|
@@ -265,7 +265,7 @@ class MercutoDataService:
|
|
|
265
265
|
aggregate: Optional[str] = None,
|
|
266
266
|
metric: Optional[str] = None
|
|
267
267
|
) -> Expression:
|
|
268
|
-
payload:
|
|
268
|
+
payload: PayloadType = {
|
|
269
269
|
"project": project,
|
|
270
270
|
"label": label,
|
|
271
271
|
"expression": expression,
|
|
@@ -277,11 +277,11 @@ class MercutoDataService:
|
|
|
277
277
|
if metric is not None:
|
|
278
278
|
payload["metric"] = metric
|
|
279
279
|
|
|
280
|
-
r = self._client.
|
|
280
|
+
r = self._client.request(f'{self._path}/expressions', 'PUT', json=payload)
|
|
281
281
|
return Expression.model_validate_json(r.text)
|
|
282
282
|
|
|
283
283
|
def delete_expression(self, code: str) -> bool:
|
|
284
|
-
r = self._client.
|
|
284
|
+
r = self._client.request(f'{self._path}/expressions/{code}', 'DELETE')
|
|
285
285
|
return r.status_code == 202
|
|
286
286
|
|
|
287
287
|
"""
|
|
@@ -289,24 +289,24 @@ class MercutoDataService:
|
|
|
289
289
|
"""
|
|
290
290
|
|
|
291
291
|
def create_datatable(self, project: str, name: str, sampling_period: timedelta, column_labels: Collection[str]) -> Datatable:
|
|
292
|
-
payload:
|
|
292
|
+
payload: PayloadType = {
|
|
293
293
|
"project": project,
|
|
294
294
|
"name": name,
|
|
295
295
|
"sampling_period": serialise_timedelta(sampling_period),
|
|
296
296
|
"column_labels": list(column_labels),
|
|
297
297
|
}
|
|
298
|
-
r = self._client.
|
|
298
|
+
r = self._client.request(f'{self._path}/datatables', 'PUT', json=payload)
|
|
299
299
|
return Datatable.model_validate_json(r.text)
|
|
300
300
|
|
|
301
301
|
def list_datatables(self, project: str) -> list[Datatable]:
|
|
302
|
-
datatables = []
|
|
302
|
+
datatables: list[Datatable] = []
|
|
303
303
|
params: dict[str, Any] = {
|
|
304
304
|
"project": project,
|
|
305
305
|
"limit": 100,
|
|
306
306
|
"offset": 0,
|
|
307
307
|
}
|
|
308
308
|
while True:
|
|
309
|
-
r = self._client.
|
|
309
|
+
r = self._client.request(f'{self._path}/datatables', 'GET', params=params)
|
|
310
310
|
|
|
311
311
|
batch = _DatatablelistAdapter.validate_json(r.text)
|
|
312
312
|
datatables.extend(batch)
|
|
@@ -320,15 +320,15 @@ class MercutoDataService:
|
|
|
320
320
|
"""
|
|
321
321
|
|
|
322
322
|
def list_units(self) -> list[Units]:
|
|
323
|
-
r = self._client.
|
|
323
|
+
r = self._client.request(f'{self._path}/units', 'GET')
|
|
324
324
|
return _UnitslistAdapter.validate_json(r.text)
|
|
325
325
|
|
|
326
326
|
def create_unit(self, name: str, unit: str) -> Units:
|
|
327
|
-
payload:
|
|
327
|
+
payload: PayloadType = {
|
|
328
328
|
"name": name,
|
|
329
329
|
"unit": unit,
|
|
330
330
|
}
|
|
331
|
-
r = self._client.
|
|
331
|
+
r = self._client.request(f'{self._path}/units', 'PUT', json=payload)
|
|
332
332
|
return Units.model_validate_json(r.text)
|
|
333
333
|
|
|
334
334
|
"""
|
|
@@ -354,7 +354,7 @@ class MercutoDataService:
|
|
|
354
354
|
if channels is None and classification is None:
|
|
355
355
|
raise ValueError("Must supply either channels or classification.")
|
|
356
356
|
|
|
357
|
-
payload:
|
|
357
|
+
payload: PayloadType = {
|
|
358
358
|
"start_time": start_time.isoformat(),
|
|
359
359
|
"end_time": end_time.isoformat(),
|
|
360
360
|
"frame_format": frame_format.value,
|
|
@@ -374,7 +374,7 @@ class MercutoDataService:
|
|
|
374
374
|
if aggregation is not None:
|
|
375
375
|
payload["aggregation"] = aggregation.model_dump(mode='json')
|
|
376
376
|
|
|
377
|
-
r = self._client.
|
|
377
|
+
r = self._client.request(
|
|
378
378
|
f'{self._path}/requests', 'POST',
|
|
379
379
|
json=payload,
|
|
380
380
|
params={"timeout": timeout}
|
|
@@ -382,7 +382,7 @@ class MercutoDataService:
|
|
|
382
382
|
return GetStatusRequestResponse.model_validate_json(r.text)
|
|
383
383
|
|
|
384
384
|
def get_request(self, request_id: str) -> GetStatusRequestResponse:
|
|
385
|
-
r = self._client.
|
|
385
|
+
r = self._client.request(f'{self._path}/requests/{request_id}', 'GET')
|
|
386
386
|
return GetStatusRequestResponse.model_validate_json(r.text)
|
|
387
387
|
|
|
388
388
|
"""
|
|
@@ -425,8 +425,6 @@ class MercutoDataService:
|
|
|
425
425
|
poll_interval=poll_interval,
|
|
426
426
|
timeout=timeout
|
|
427
427
|
)
|
|
428
|
-
if result.result_url is None:
|
|
429
|
-
raise MercutoClientException("Failed to obtain presigned URL.")
|
|
430
428
|
return result.result_url
|
|
431
429
|
|
|
432
430
|
def load_data_request(
|
|
@@ -499,7 +497,7 @@ class MercutoDataService:
|
|
|
499
497
|
"""
|
|
500
498
|
for batch in batched(samples, 5000):
|
|
501
499
|
payload = _SecondarySamplelistAdapter.dump_python(list(batch), mode='json')
|
|
502
|
-
self._client.
|
|
500
|
+
self._client.request(
|
|
503
501
|
f'{self._path}/samples/secondary', 'PUT', json=payload, params={"project": project}
|
|
504
502
|
)
|
|
505
503
|
|
|
@@ -515,7 +513,7 @@ class MercutoDataService:
|
|
|
515
513
|
"""
|
|
516
514
|
for batch in batched(samples, 5000):
|
|
517
515
|
payload = _MetricSamplelistAdapter.dump_python(list(batch), mode='json')
|
|
518
|
-
self._client.
|
|
516
|
+
self._client.request(
|
|
519
517
|
f'{self._path}/samples/metric', 'PUT', json=payload, params={"project": project}
|
|
520
518
|
)
|
|
521
519
|
|
|
@@ -531,13 +529,13 @@ class MercutoDataService:
|
|
|
531
529
|
"""
|
|
532
530
|
Load up to 100 secondary samples.
|
|
533
531
|
"""
|
|
534
|
-
params:
|
|
532
|
+
params: PayloadType = {
|
|
535
533
|
"channels": list(channels),
|
|
536
534
|
"start_time": start_time.isoformat(),
|
|
537
535
|
"end_time": end_time.isoformat(),
|
|
538
536
|
"limit": limit
|
|
539
537
|
}
|
|
540
|
-
r = self._client.
|
|
538
|
+
r = self._client.request(
|
|
541
539
|
f'{self._path}/samples/secondary', 'GET', params=params
|
|
542
540
|
)
|
|
543
541
|
|
|
@@ -555,7 +553,7 @@ class MercutoDataService:
|
|
|
555
553
|
"""
|
|
556
554
|
Load up to 100 metric samples.
|
|
557
555
|
"""
|
|
558
|
-
params:
|
|
556
|
+
params: PayloadType = {
|
|
559
557
|
"limit": limit
|
|
560
558
|
}
|
|
561
559
|
if project is not None:
|
|
@@ -568,7 +566,7 @@ class MercutoDataService:
|
|
|
568
566
|
params["end_time"] = end_time.isoformat()
|
|
569
567
|
if events is not None:
|
|
570
568
|
params["event"] = list(events)
|
|
571
|
-
r = self._client.
|
|
569
|
+
r = self._client.request(
|
|
572
570
|
f'{self._path}/samples/metric', 'GET', params=params
|
|
573
571
|
)
|
|
574
572
|
|
|
@@ -582,10 +580,10 @@ class MercutoDataService:
|
|
|
582
580
|
return samples[0].value if samples else None
|
|
583
581
|
|
|
584
582
|
def delete_metric_samples(self, project: str, event: str, channels: Optional[Collection[str]] = None) -> None:
|
|
585
|
-
params:
|
|
583
|
+
params: PayloadType = {"project": project, "event": event}
|
|
586
584
|
if channels is not None:
|
|
587
585
|
params["channels"] = list(channels)
|
|
588
|
-
self._client.
|
|
586
|
+
self._client.request(
|
|
589
587
|
f'{self._path}/samples/metric', 'DELETE', params=params
|
|
590
588
|
)
|
|
591
589
|
|
|
@@ -599,7 +597,7 @@ class MercutoDataService:
|
|
|
599
597
|
ctx = nullcontext(file) # type: ignore
|
|
600
598
|
filename = filename or 'file.dat'
|
|
601
599
|
|
|
602
|
-
params:
|
|
600
|
+
params: PayloadType = {
|
|
603
601
|
"project": project,
|
|
604
602
|
"datatable": datatable,
|
|
605
603
|
}
|
|
@@ -607,16 +605,16 @@ class MercutoDataService:
|
|
|
607
605
|
params["timezone"] = timezone
|
|
608
606
|
|
|
609
607
|
with ctx as f:
|
|
610
|
-
self._client.
|
|
611
|
-
|
|
612
|
-
|
|
608
|
+
self._client.request(f'{self._path}/files/upload/small', 'POST',
|
|
609
|
+
params=params,
|
|
610
|
+
files={'file': (filename, f, 'text/csv')})
|
|
613
611
|
|
|
614
612
|
def get_latest_samples(self, project: str, include_primary: bool = True) -> list[LatestDataSample]:
|
|
615
|
-
params:
|
|
613
|
+
params: PayloadType = {
|
|
616
614
|
"project": project,
|
|
617
615
|
"include_primary": include_primary
|
|
618
616
|
}
|
|
619
|
-
r = self._client.
|
|
617
|
+
r = self._client.request(
|
|
620
618
|
f'{self._path}/statistics/latest-samples', 'GET', params=params
|
|
621
619
|
)
|
|
622
620
|
|
|
@@ -6,7 +6,7 @@ from pydantic import Field, TypeAdapter
|
|
|
6
6
|
if TYPE_CHECKING:
|
|
7
7
|
from ..client import MercutoClient
|
|
8
8
|
|
|
9
|
-
from . import
|
|
9
|
+
from . import PayloadType
|
|
10
10
|
from ._util import BaseModel
|
|
11
11
|
|
|
12
12
|
|
|
@@ -55,14 +55,14 @@ class MercutoFatigueService:
|
|
|
55
55
|
self._path = path
|
|
56
56
|
|
|
57
57
|
def healthcheck(self) -> Healthcheck:
|
|
58
|
-
r = self._client.
|
|
58
|
+
r = self._client.request(f"{self._path}/healthcheck", "GET")
|
|
59
59
|
return Healthcheck.model_validate_json(r.text)
|
|
60
60
|
|
|
61
61
|
# --- Rainflow routes ---
|
|
62
62
|
|
|
63
63
|
def list_rainflow_config(self, project: str) -> list[RainflowConfiguration]:
|
|
64
|
-
params:
|
|
65
|
-
r = self._client.
|
|
64
|
+
params: PayloadType = {"project": project}
|
|
65
|
+
r = self._client.request(f"{self._path}/rainflow/setup", "GET", params=params)
|
|
66
66
|
return _RainflowConfigurationlistAdapter.validate_json(r.text)
|
|
67
67
|
|
|
68
68
|
def setup_rainflow(
|
|
@@ -74,7 +74,7 @@ class MercutoFatigueService:
|
|
|
74
74
|
reservoir_adjustment: bool,
|
|
75
75
|
sources: list[str]
|
|
76
76
|
) -> RainflowConfiguration:
|
|
77
|
-
payload:
|
|
77
|
+
payload: PayloadType = {
|
|
78
78
|
"project": project,
|
|
79
79
|
"max_bins": max_bins,
|
|
80
80
|
"bin_size": bin_size,
|
|
@@ -82,18 +82,18 @@ class MercutoFatigueService:
|
|
|
82
82
|
"reservoir_adjustment": reservoir_adjustment,
|
|
83
83
|
"sources": sources,
|
|
84
84
|
}
|
|
85
|
-
r = self._client.
|
|
85
|
+
r = self._client.request(f"{self._path}/rainflow/setup", "PUT", json=payload)
|
|
86
86
|
return RainflowConfiguration.model_validate_json(r.text)
|
|
87
87
|
|
|
88
88
|
def get_cycle_counts(
|
|
89
89
|
self, project: str, start_time: datetime, end_time: datetime
|
|
90
90
|
) -> bytes:
|
|
91
|
-
params:
|
|
91
|
+
params: PayloadType = {
|
|
92
92
|
"project": project,
|
|
93
93
|
"start_time": start_time.isoformat(),
|
|
94
94
|
"end_time": end_time.isoformat(),
|
|
95
95
|
}
|
|
96
|
-
r = self._client.
|
|
96
|
+
r = self._client.request(
|
|
97
97
|
f"{self._path}/rainflow/cycle_counts", "GET", params=params, stream=True
|
|
98
98
|
)
|
|
99
99
|
return r.content
|
|
@@ -101,13 +101,13 @@ class MercutoFatigueService:
|
|
|
101
101
|
def delete_cycle_counts(
|
|
102
102
|
self, project: str, start_time: datetime, end_time: datetime, ignore_if_not_configured: bool = False
|
|
103
103
|
) -> None:
|
|
104
|
-
params:
|
|
104
|
+
params: PayloadType = {
|
|
105
105
|
"project": project,
|
|
106
106
|
"start_time": start_time.isoformat(),
|
|
107
107
|
"end_time": end_time.isoformat(),
|
|
108
108
|
"ignore_if_not_configured": ignore_if_not_configured,
|
|
109
109
|
}
|
|
110
|
-
self._client.
|
|
110
|
+
self._client.request(
|
|
111
111
|
f"{self._path}/rainflow/cycle_counts", "DELETE", params=params
|
|
112
112
|
)
|
|
113
113
|
|
|
@@ -120,7 +120,7 @@ class MercutoFatigueService:
|
|
|
120
120
|
url_expiry: Optional[datetime] = None,
|
|
121
121
|
ignore_if_not_configured: bool = False
|
|
122
122
|
) -> None:
|
|
123
|
-
payload:
|
|
123
|
+
payload: PayloadType = {
|
|
124
124
|
"project": project,
|
|
125
125
|
"event": event,
|
|
126
126
|
"presigned_url": presigned_url,
|
|
@@ -129,15 +129,15 @@ class MercutoFatigueService:
|
|
|
129
129
|
if url_expiry is not None:
|
|
130
130
|
payload["url_expiry"] = url_expiry.isoformat()
|
|
131
131
|
params = {"ignore_if_not_configured": ignore_if_not_configured}
|
|
132
|
-
self._client.
|
|
132
|
+
self._client.request(
|
|
133
133
|
f"{self._path}/rainflow/cycle_counts/calculate", "PUT", json=payload, params=params
|
|
134
134
|
)
|
|
135
135
|
|
|
136
136
|
# --- Fatigue Connections routes ---
|
|
137
137
|
|
|
138
138
|
def get_connections(self, project: str) -> list[FatigueConnection]:
|
|
139
|
-
params:
|
|
140
|
-
r = self._client.
|
|
139
|
+
params: PayloadType = {"project": project}
|
|
140
|
+
r = self._client.request(f"{self._path}/connections", "GET", params=params)
|
|
141
141
|
return _FatigueConnectionlistAdapter.validate_json(r.text)
|
|
142
142
|
|
|
143
143
|
def add_connection(
|
|
@@ -154,7 +154,7 @@ class MercutoFatigueService:
|
|
|
154
154
|
initial_damage: float,
|
|
155
155
|
sources: list[str]
|
|
156
156
|
) -> FatigueConnection:
|
|
157
|
-
payload:
|
|
157
|
+
payload: PayloadType = {
|
|
158
158
|
"project": project,
|
|
159
159
|
"label": label,
|
|
160
160
|
"multiplier": multiplier,
|
|
@@ -167,23 +167,23 @@ class MercutoFatigueService:
|
|
|
167
167
|
"initial_damage": initial_damage,
|
|
168
168
|
"sources": sources,
|
|
169
169
|
}
|
|
170
|
-
r = self._client.
|
|
170
|
+
r = self._client.request(f"{self._path}/connections", "PUT", json=payload)
|
|
171
171
|
return FatigueConnection.model_validate_json(r.text)
|
|
172
172
|
|
|
173
173
|
def delete_connection(self, connection_code: str) -> None:
|
|
174
|
-
self._client.
|
|
174
|
+
self._client.request(f"{self._path}/connections/{connection_code}", "DELETE")
|
|
175
175
|
|
|
176
176
|
# --- Connection Data routes ---
|
|
177
177
|
|
|
178
178
|
def get_connection_remnant_capacity(
|
|
179
179
|
self, project: str, start_time: datetime, end_time: datetime
|
|
180
180
|
) -> list[ConnectionRemnantCapacity]:
|
|
181
|
-
params:
|
|
181
|
+
params: PayloadType = {
|
|
182
182
|
"project": project,
|
|
183
183
|
"start_time": start_time.isoformat(),
|
|
184
184
|
"end_time": end_time.isoformat(),
|
|
185
185
|
}
|
|
186
|
-
r = self._client.
|
|
186
|
+
r = self._client.request(
|
|
187
187
|
f"{self._path}/connection_data/remnant-capacity", "GET", params=params
|
|
188
188
|
)
|
|
189
189
|
return _ConnectionRemnantCapacitylistAdapter.validate_json(r.text)
|
|
@@ -5,7 +5,7 @@ from pydantic import TypeAdapter
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from ..client import MercutoClient
|
|
7
7
|
|
|
8
|
-
from . import
|
|
8
|
+
from . import PayloadType
|
|
9
9
|
from ._util import BaseModel
|
|
10
10
|
|
|
11
11
|
|
|
@@ -86,22 +86,22 @@ class MercutoIdentityService:
|
|
|
86
86
|
self._path = path
|
|
87
87
|
|
|
88
88
|
def healthcheck(self) -> Healthcheck:
|
|
89
|
-
r = self._client.
|
|
89
|
+
r = self._client.request(f"{self._path}/healthcheck", "GET")
|
|
90
90
|
return Healthcheck.model_validate_json(r.text)
|
|
91
91
|
|
|
92
92
|
# --- Verify routes ---
|
|
93
93
|
|
|
94
94
|
def get_my_permissions(self) -> VerifyMyPermissions:
|
|
95
|
-
r = self._client.
|
|
95
|
+
r = self._client.request(f"{self._path}/verify/me", "GET")
|
|
96
96
|
return VerifyMyPermissions.model_validate_json(r.text)
|
|
97
97
|
|
|
98
98
|
# --- User routes ---
|
|
99
99
|
|
|
100
100
|
def list_users(self, tenant: Optional[str] = None) -> list[User]:
|
|
101
|
-
params:
|
|
101
|
+
params: PayloadType = {}
|
|
102
102
|
if tenant is not None:
|
|
103
103
|
params["tenant"] = tenant
|
|
104
|
-
r = self._client.
|
|
104
|
+
r = self._client.request(f"{self._path}/users", "GET", params=params)
|
|
105
105
|
return _UserlistAdapter.validate_json(r.text)
|
|
106
106
|
|
|
107
107
|
def create_user(
|
|
@@ -112,26 +112,26 @@ class MercutoIdentityService:
|
|
|
112
112
|
group: str,
|
|
113
113
|
default_password: Optional[str] = None
|
|
114
114
|
) -> User:
|
|
115
|
-
payload:
|
|
115
|
+
payload: PayloadType = {
|
|
116
116
|
"username": username,
|
|
117
117
|
"tenant_code": tenant,
|
|
118
118
|
"description": description,
|
|
119
119
|
"group_code": group,
|
|
120
120
|
"default_password": default_password,
|
|
121
121
|
}
|
|
122
|
-
r = self._client.
|
|
122
|
+
r = self._client.request(f"{self._path}/users", "PUT", json=payload)
|
|
123
123
|
return User.model_validate_json(r.text)
|
|
124
124
|
|
|
125
125
|
def get_current_user(self) -> CurrentUser:
|
|
126
|
-
r = self._client.
|
|
126
|
+
r = self._client.request(f"{self._path}/users/me", "GET")
|
|
127
127
|
return CurrentUser.model_validate_json(r.text)
|
|
128
128
|
|
|
129
129
|
def get_user(self, code: str) -> User:
|
|
130
|
-
r = self._client.
|
|
130
|
+
r = self._client.request(f"{self._path}/users/{code}", "GET")
|
|
131
131
|
return User.model_validate_json(r.text)
|
|
132
132
|
|
|
133
133
|
def delete_user(self, code: str) -> None:
|
|
134
|
-
self._client.
|
|
134
|
+
self._client.request(f"{self._path}/users/{code}", "DELETE")
|
|
135
135
|
|
|
136
136
|
def edit_user(
|
|
137
137
|
self,
|
|
@@ -139,15 +139,15 @@ class MercutoIdentityService:
|
|
|
139
139
|
description: str,
|
|
140
140
|
group: str
|
|
141
141
|
) -> User:
|
|
142
|
-
payload:
|
|
142
|
+
payload: PayloadType = {
|
|
143
143
|
"description": description,
|
|
144
144
|
"group_code": group,
|
|
145
145
|
}
|
|
146
|
-
r = self._client.
|
|
146
|
+
r = self._client.request(f"{self._path}/users/{code}", "PATCH", json=payload)
|
|
147
147
|
return User.model_validate_json(r.text)
|
|
148
148
|
|
|
149
149
|
def get_user_details(self, code: str) -> UserDetails:
|
|
150
|
-
r = self._client.
|
|
150
|
+
r = self._client.request(f"{self._path}/users/{code}/details", "GET")
|
|
151
151
|
return UserDetails.model_validate_json(r.text)
|
|
152
152
|
|
|
153
153
|
def set_user_details(
|
|
@@ -158,17 +158,17 @@ class MercutoIdentityService:
|
|
|
158
158
|
first_name: Optional[str] = None,
|
|
159
159
|
last_name: Optional[str] = None
|
|
160
160
|
) -> UserDetails:
|
|
161
|
-
payload:
|
|
161
|
+
payload: PayloadType = {
|
|
162
162
|
"email_address": email_address,
|
|
163
163
|
"mobile_number": mobile_number,
|
|
164
164
|
"first_name": first_name,
|
|
165
165
|
"last_name": last_name,
|
|
166
166
|
}
|
|
167
|
-
r = self._client.
|
|
167
|
+
r = self._client.request(f"{self._path}/users/{code}/details", "PATCH", json=payload)
|
|
168
168
|
return UserDetails.model_validate_json(r.text)
|
|
169
169
|
|
|
170
170
|
def get_user_api_keys(self, user: str) -> list[HiddenUserAPIKey]:
|
|
171
|
-
r = self._client.
|
|
171
|
+
r = self._client.request(f"{self._path}/users/{user}/api_keys", "GET")
|
|
172
172
|
return _HiddenUserAPIKeylistAdapter.validate_json(r.text)
|
|
173
173
|
|
|
174
174
|
def generate_api_key_for_user(
|
|
@@ -177,24 +177,24 @@ class MercutoIdentityService:
|
|
|
177
177
|
description: str,
|
|
178
178
|
custom_policy: Optional[str] = None
|
|
179
179
|
) -> VisibleUserAPIKey:
|
|
180
|
-
payload:
|
|
180
|
+
payload: PayloadType = {
|
|
181
181
|
"description": description,
|
|
182
182
|
"custom_policy": custom_policy,
|
|
183
183
|
}
|
|
184
|
-
r = self._client.
|
|
184
|
+
r = self._client.request(f"{self._path}/users/{user}/api_keys", "POST", json=payload)
|
|
185
185
|
return VisibleUserAPIKey.model_validate_json(r.text)
|
|
186
186
|
|
|
187
187
|
def delete_api_key(self, user: str, key_code: str) -> None:
|
|
188
|
-
self._client.
|
|
188
|
+
self._client.request(f"{self._path}/users/{user}/api_keys/{key_code}", "DELETE")
|
|
189
189
|
|
|
190
190
|
# --- Tenants routes ---
|
|
191
191
|
|
|
192
192
|
def list_tenants(self) -> list[Tenant]:
|
|
193
|
-
r = self._client.
|
|
193
|
+
r = self._client.request(f"{self._path}/tenants", "GET")
|
|
194
194
|
return _TenantlistAdapter.validate_json(r.text)
|
|
195
195
|
|
|
196
196
|
def get_tenant(self, code: str) -> Tenant:
|
|
197
|
-
r = self._client.
|
|
197
|
+
r = self._client.request(f"{self._path}/tenants/{code}", "GET")
|
|
198
198
|
return Tenant.model_validate_json(r.text)
|
|
199
199
|
|
|
200
200
|
def create_tenant(
|
|
@@ -203,21 +203,21 @@ class MercutoIdentityService:
|
|
|
203
203
|
description: str,
|
|
204
204
|
logo_url: Optional[str] = None
|
|
205
205
|
) -> Tenant:
|
|
206
|
-
payload:
|
|
206
|
+
payload: PayloadType = {
|
|
207
207
|
"name": name,
|
|
208
208
|
"description": description,
|
|
209
209
|
"logo_url": logo_url,
|
|
210
210
|
}
|
|
211
|
-
r = self._client.
|
|
211
|
+
r = self._client.request(f"{self._path}/tenants", "PUT", json=payload)
|
|
212
212
|
return Tenant.model_validate_json(r.text)
|
|
213
213
|
|
|
214
214
|
# --- Permission Groups routes ---
|
|
215
215
|
|
|
216
216
|
def get_permission_groups(self, tenant: Optional[str] = None) -> list[PermissionGroup]:
|
|
217
|
-
params = {}
|
|
217
|
+
params: PayloadType = {}
|
|
218
218
|
if tenant is not None:
|
|
219
219
|
params["tenant"] = tenant
|
|
220
|
-
r = self._client.
|
|
220
|
+
r = self._client.request(f"{self._path}/permissions", "GET", params=params)
|
|
221
221
|
return _PermissionGrouplistAdapter.validate_json(r.text)
|
|
222
222
|
|
|
223
223
|
def create_permission_group(
|
|
@@ -226,20 +226,20 @@ class MercutoIdentityService:
|
|
|
226
226
|
label: str,
|
|
227
227
|
acl_policy: str
|
|
228
228
|
) -> PermissionGroup:
|
|
229
|
-
payload:
|
|
229
|
+
payload: PayloadType = {
|
|
230
230
|
"tenant": tenant,
|
|
231
231
|
"label": label,
|
|
232
232
|
"acl_policy": acl_policy,
|
|
233
233
|
}
|
|
234
|
-
r = self._client.
|
|
234
|
+
r = self._client.request(f"{self._path}/permissions", "PUT", json=payload)
|
|
235
235
|
return PermissionGroup.model_validate_json(r.text)
|
|
236
236
|
|
|
237
237
|
def get_permission_group(self, group: str) -> PermissionGroup:
|
|
238
|
-
r = self._client.
|
|
238
|
+
r = self._client.request(f"{self._path}/permissions/{group}", "GET")
|
|
239
239
|
return PermissionGroup.model_validate_json(r.text)
|
|
240
240
|
|
|
241
241
|
def delete_permission_group(self, group: str) -> None:
|
|
242
|
-
self._client.
|
|
242
|
+
self._client.request(f"{self._path}/permissions/{group}", "DELETE")
|
|
243
243
|
|
|
244
244
|
def modify_permission_group(
|
|
245
245
|
self,
|
|
@@ -247,8 +247,8 @@ class MercutoIdentityService:
|
|
|
247
247
|
label: str,
|
|
248
248
|
acl_policy: str
|
|
249
249
|
) -> None:
|
|
250
|
-
payload:
|
|
250
|
+
payload: PayloadType = {
|
|
251
251
|
"label": label,
|
|
252
252
|
"acl_policy": acl_policy,
|
|
253
253
|
}
|
|
254
|
-
self._client.
|
|
254
|
+
self._client.request(f"{self._path}/permissions/{group}", "PATCH", json=payload)
|