peak-sdk 1.10.0__py3-none-any.whl → 1.12.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.
- peak/__init__.py +3 -2
- peak/_metadata.py +182 -1
- peak/_version.py +1 -1
- peak/callbacks.py +22 -2
- peak/cli/cli.py +2 -0
- peak/cli/helpers.py +2 -0
- peak/cli/metrics/__init__.py +21 -0
- peak/cli/metrics/metrics.py +707 -0
- peak/cli/press/blocks/specs.py +2 -0
- peak/cli/resources/services.py +20 -5
- peak/handler.py +16 -7
- peak/metrics/__init__.py +26 -0
- peak/metrics/metrics.py +553 -0
- peak/output.py +9 -1
- peak/press/blocks.py +2 -0
- peak/resources/__init__.py +10 -1
- peak/resources/services.py +5 -2
- peak/sample_yaml/metrics/create_collection.yaml +8 -0
- peak/sample_yaml/metrics/publish.yaml +6 -0
- peak/sample_yaml/metrics/query.yaml +25 -0
- peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec.yaml +1 -0
- peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec_release.yaml +1 -0
- peak/sample_yaml/resources/services/create_or_update_service.yaml +1 -0
- peak/sample_yaml/resources/services/create_service.yaml +1 -0
- peak/sample_yaml/resources/services/update_service.yaml +1 -0
- peak/sample_yaml/resources/webapps/create_or_update_webapp.yaml +1 -0
- peak/sample_yaml/resources/webapps/create_webapp.yaml +1 -0
- peak/sample_yaml/resources/webapps/update_webapp.yaml +1 -0
- {peak_sdk-1.10.0.dist-info → peak_sdk-1.12.0.dist-info}/METADATA +45 -7
- {peak_sdk-1.10.0.dist-info → peak_sdk-1.12.0.dist-info}/RECORD +33 -26
- {peak_sdk-1.10.0.dist-info → peak_sdk-1.12.0.dist-info}/LICENSE +0 -0
- {peak_sdk-1.10.0.dist-info → peak_sdk-1.12.0.dist-info}/WHEEL +0 -0
- {peak_sdk-1.10.0.dist-info → peak_sdk-1.12.0.dist-info}/entry_points.txt +0 -0
peak/metrics/metrics.py
ADDED
@@ -0,0 +1,553 @@
|
|
1
|
+
#
|
2
|
+
# # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
|
3
|
+
# #
|
4
|
+
# # Licensed under the Apache License, Version 2.0 (the "License"). You
|
5
|
+
# # may not use this file except in compliance with the License. A copy of
|
6
|
+
# # the License is located at:
|
7
|
+
# #
|
8
|
+
# # https://github.com/PeakBI/peak-sdk/blob/main/LICENSE
|
9
|
+
# #
|
10
|
+
# # or in the "license" file accompanying this file. This file is
|
11
|
+
# # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
12
|
+
# # ANY KIND, either express or implied. See the License for the specific
|
13
|
+
# # language governing permissions and limitations under the License.
|
14
|
+
# #
|
15
|
+
# # This file is part of the peak-sdk.
|
16
|
+
# # see (https://github.com/PeakBI/peak-sdk)
|
17
|
+
# #
|
18
|
+
# # You should have received a copy of the APACHE LICENSE, VERSION 2.0
|
19
|
+
# # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
|
20
|
+
#
|
21
|
+
|
22
|
+
"""Metrics client module."""
|
23
|
+
|
24
|
+
from __future__ import annotations
|
25
|
+
|
26
|
+
import json
|
27
|
+
from typing import Any, Dict, Iterator, List, Literal, Optional, overload
|
28
|
+
|
29
|
+
from peak.base_client import BaseClient
|
30
|
+
from peak.constants import ArtifactInfo, ContentType, HttpMethods
|
31
|
+
from peak.exceptions import InvalidParameterException
|
32
|
+
from peak.session import Session
|
33
|
+
|
34
|
+
|
35
|
+
class Metric(BaseClient):
|
36
|
+
"""Client class for interacting with metrics resource."""
|
37
|
+
|
38
|
+
BASE_ENDPOINT = "semantic-layer/api/v1"
|
39
|
+
|
40
|
+
def __get_artifact_details(self, artifact: ArtifactInfo) -> str | None:
|
41
|
+
path = None
|
42
|
+
|
43
|
+
if artifact:
|
44
|
+
path = artifact.get("path")
|
45
|
+
|
46
|
+
return path
|
47
|
+
|
48
|
+
def publish(
|
49
|
+
self,
|
50
|
+
artifact: Optional[ArtifactInfo] = None,
|
51
|
+
collection_id: Optional[str] = None,
|
52
|
+
body: Optional[Dict[str, Any]] = None,
|
53
|
+
) -> Dict[str, Any]:
|
54
|
+
"""Publish Metrics.
|
55
|
+
|
56
|
+
The metrics can be published either by passing artifact and namespace,
|
57
|
+
or by passing collection_id and namespace. If both artifact and collection_id
|
58
|
+
are provided, artifact takes priority. If the namespace is not provided, the 'default' namespace is used.
|
59
|
+
|
60
|
+
REFERENCE:
|
61
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Metrics/post_api_v1_metrics>`__
|
62
|
+
|
63
|
+
Args:
|
64
|
+
body (Dict[str, Any]): A dictionary containing the details to publish the metrics.
|
65
|
+
artifact (ArtifactInfo | None): Mapping of artifact attributes that specifies how the artifact will be generated,
|
66
|
+
it accepts one key `path`,
|
67
|
+
collection_id (str | None): The ID of the collection to publish the metrics.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
Dict[str, Any]: A dictionary containing details about the published metrics.
|
71
|
+
|
72
|
+
SCHEMA:
|
73
|
+
.. code-block:: json
|
74
|
+
|
75
|
+
{
|
76
|
+
"namespace": "string",
|
77
|
+
}
|
78
|
+
|
79
|
+
Raises:
|
80
|
+
InvalidParameterException: The given request parameters are invalid.
|
81
|
+
UnauthorizedException: The credentials are invalid.
|
82
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
83
|
+
NotFoundException: The given feature does not exist.
|
84
|
+
UnprocessableEntityException: The server was unable to process the request.
|
85
|
+
InternalServerErrorException: The server failed to process the request.
|
86
|
+
"""
|
87
|
+
if artifact:
|
88
|
+
method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT}/metrics"
|
89
|
+
path = self.__get_artifact_details(artifact)
|
90
|
+
|
91
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
92
|
+
endpoint,
|
93
|
+
method,
|
94
|
+
content_type=ContentType.MULTIPART_FORM_DATA,
|
95
|
+
body=body,
|
96
|
+
path=path,
|
97
|
+
)
|
98
|
+
|
99
|
+
if collection_id:
|
100
|
+
method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT}/metrics/collections/{collection_id}/publish"
|
101
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
102
|
+
endpoint,
|
103
|
+
method,
|
104
|
+
content_type=ContentType.APPLICATION_JSON,
|
105
|
+
body=body,
|
106
|
+
)
|
107
|
+
|
108
|
+
raise InvalidParameterException(
|
109
|
+
message="Either Artifact or Collection ID must be passed to publish the metrics.",
|
110
|
+
)
|
111
|
+
|
112
|
+
def query(
|
113
|
+
self,
|
114
|
+
measures: List[str],
|
115
|
+
namespace: Optional[str] = None,
|
116
|
+
generate_sql: Optional[bool] = False, # noqa: FBT002
|
117
|
+
dimensions: Optional[List[str]] = None,
|
118
|
+
filters: Optional[List[Dict[str, Any]]] = None,
|
119
|
+
time_dimensions: Optional[List[Dict[str, Any]]] = None,
|
120
|
+
segments: Optional[List[str]] = None,
|
121
|
+
order: Optional[Dict[str, Literal["asc", "desc"]]] = None,
|
122
|
+
limit: Optional[int] = None,
|
123
|
+
offset: Optional[int] = None,
|
124
|
+
) -> Dict[str, Any]:
|
125
|
+
"""Query a published metric in the semantic layer using the provided parameters.
|
126
|
+
|
127
|
+
REFERENCE:
|
128
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Query/get_api_v1_metrics_query>`__
|
129
|
+
|
130
|
+
Args:
|
131
|
+
measures (List[str]): An array of measures to include in the query. Measures represent quantitative metrics such as sums or counts.
|
132
|
+
namespace (str | None): The namespace associated with the metrics. If not provided, the default namespace is used.
|
133
|
+
generate_sql (bool | None): Indicates whether to return the SQL query instead of data. If `true`, the response will include the SQL query used to retrieve the metrics. Default is `false`.
|
134
|
+
dimensions (List[str] | None): An array of dimensions to include in the query. Dimensions represent qualitative categories such as time, location, or product names.
|
135
|
+
filters (List[Dict[str, Any]] | None): An array of filter objects to apply to the query. Filters limit the data returned based on specific conditions.
|
136
|
+
dimension (str): The dimension to filter on.
|
137
|
+
operator (str): The operator to use for the filter. Supported values are `equals`, `notEquals`, `contains`, `notContains`, `startsWith`, `notStartsWith`, `endsWith`, `notEndsWith`, `gt`, `gte`, `lt`, `lte`, `inDateRange`, `notInDateRange`, `beforeDate`, `beforeOrOnDate`, `afterDate`, `afterOrOnDate` etc.
|
138
|
+
values (List[str]): An array of values to filter on.
|
139
|
+
time_dimensions (List[Dict[str, Any]] | None): Time dimensions allow querying over specific time ranges with optional granularity (e.g., day, month, year).
|
140
|
+
dimension (str): The time dimension to include in the query.
|
141
|
+
granularity (str | None): The granularity of the time dimension. Supported values are `second`, `minute`, `hour`, `day`, `week`, `month`, `quarter`, and `year`.
|
142
|
+
dateRange (list(str) | str | None): An array of two dates that define the time range for the query. Alternatively, you can provide a single string out of the following predefined date ranges `today`, `yesterday`, `this week`, `last week`, `this month`, `last month`, `this quarter`, `last quarter`, `this year`, `last year`, `last 7 days` and `last 30 days`.
|
143
|
+
segments (List[str] | None): An array of segments to include in the query. Segments represent pre-defined filters that can be applied to metrics.
|
144
|
+
order (Dict[str, Any] | None): Defines the sort order of the results. This is an object where keys are the dimensions/measures and values are either 'asc' or 'desc' to specify ascending or descending order.
|
145
|
+
limit (int | None): Limits the number of rows returned by the query. If not provided, the default limit is applied.
|
146
|
+
offset (int | None): Specifies the number of rows to skip before starting to return data. Useful for pagination.
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
Dict[str, Any]: A dictionary containing the query metrics response.
|
150
|
+
|
151
|
+
Raises:
|
152
|
+
InvalidParameterException: The given request parameters are invalid.
|
153
|
+
UnauthorizedException: The credentials are invalid.
|
154
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
155
|
+
NotFoundException: The given feature does not exist.
|
156
|
+
UnprocessableEntityException: The server was unable to process the request.
|
157
|
+
InternalServerErrorException: The server failed to process the request.
|
158
|
+
"""
|
159
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/metrics/query"
|
160
|
+
|
161
|
+
request_params = {
|
162
|
+
"namespace": namespace,
|
163
|
+
"generateSql": str(generate_sql).lower(),
|
164
|
+
"measures": measures,
|
165
|
+
"dimensions": dimensions,
|
166
|
+
"filters": json.dumps(filters) if filters else None,
|
167
|
+
"timeDimensions": json.dumps(time_dimensions) if time_dimensions else None,
|
168
|
+
"segments": segments,
|
169
|
+
"order": json.dumps(order) if order else None,
|
170
|
+
"limit": limit,
|
171
|
+
"offset": offset,
|
172
|
+
}
|
173
|
+
|
174
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
175
|
+
endpoint,
|
176
|
+
method,
|
177
|
+
params=request_params,
|
178
|
+
content_type=ContentType.APPLICATION_JSON,
|
179
|
+
)
|
180
|
+
|
181
|
+
@overload
|
182
|
+
def list(
|
183
|
+
self,
|
184
|
+
page_size: Optional[int] = None,
|
185
|
+
page_number: Optional[int] = None,
|
186
|
+
namespace: Optional[str] = None,
|
187
|
+
type: Optional[str] = None, # noqa: A002
|
188
|
+
*,
|
189
|
+
return_iterator: Literal[False],
|
190
|
+
) -> Dict[str, Any]: ...
|
191
|
+
|
192
|
+
@overload
|
193
|
+
def list(
|
194
|
+
self,
|
195
|
+
page_size: Optional[int] = None,
|
196
|
+
page_number: Optional[int] = None,
|
197
|
+
namespace: Optional[str] = None,
|
198
|
+
type: Optional[str] = None, # noqa: A002
|
199
|
+
*,
|
200
|
+
return_iterator: Literal[True] = True,
|
201
|
+
) -> Iterator[Dict[str, Any]]: ...
|
202
|
+
|
203
|
+
def list(
|
204
|
+
self,
|
205
|
+
page_size: Optional[int] = None,
|
206
|
+
page_number: Optional[int] = None,
|
207
|
+
namespace: Optional[str] = None,
|
208
|
+
type: Optional[str] = None, # noqa: A002
|
209
|
+
*,
|
210
|
+
return_iterator: bool = True,
|
211
|
+
) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
|
212
|
+
"""Retrieve the list of metrics.
|
213
|
+
|
214
|
+
REFERENCE:
|
215
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Metrics/get_api_v1_metrics>`__
|
216
|
+
|
217
|
+
Args:
|
218
|
+
page_size (int | None): The number of images per page.
|
219
|
+
page_number (int | None): The page number to retrieve. Only used when `return_iterator` is False.
|
220
|
+
namespace (str | None): The namespace associated with the metrics. If not provided, the default namespace is used.
|
221
|
+
type (str | None): The type of metrics to retrieve. If not provided, all metrics are retrieved. Available types are `cube`, `view`, `dimension`, `measure`, `segment` and `all`.
|
222
|
+
return_iterator (bool): Whether to return an iterator object or list of metrics for a specified page number, defaults to True.
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
|
226
|
+
If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
|
227
|
+
|
228
|
+
Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
|
229
|
+
|
230
|
+
Raises:
|
231
|
+
BadRequestException: The given request parameters are invalid.
|
232
|
+
UnauthorizedException: The credentials are invalid.
|
233
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
234
|
+
InternalServerErrorException: The server failed to process the request.
|
235
|
+
"""
|
236
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/metrics"
|
237
|
+
params = {
|
238
|
+
"pageSize": page_size,
|
239
|
+
"namespace": namespace,
|
240
|
+
"type": type,
|
241
|
+
}
|
242
|
+
|
243
|
+
if return_iterator:
|
244
|
+
return self.session.create_generator_request(
|
245
|
+
endpoint,
|
246
|
+
method,
|
247
|
+
content_type=ContentType.APPLICATION_JSON,
|
248
|
+
response_key="data",
|
249
|
+
params=params,
|
250
|
+
)
|
251
|
+
|
252
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
253
|
+
endpoint,
|
254
|
+
method,
|
255
|
+
content_type=ContentType.APPLICATION_JSON,
|
256
|
+
params={**params, "pageNumber": page_number},
|
257
|
+
)
|
258
|
+
|
259
|
+
def delete(
|
260
|
+
self,
|
261
|
+
*,
|
262
|
+
namespace: Optional[str] = None,
|
263
|
+
measures: Optional[List[str]] = None,
|
264
|
+
publication_id: Optional[str] = None,
|
265
|
+
) -> Dict[str, Any]:
|
266
|
+
"""Delete one or more measures.
|
267
|
+
|
268
|
+
The measures can be deleted either by passing publication_id in which case all metrics related to the publication will be deleted.
|
269
|
+
Or by passing namespace and measures in which case only the specified measures will be deleted.
|
270
|
+
If both are passed, publication_id takes priority.
|
271
|
+
|
272
|
+
REFERENCE:
|
273
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Metrics/delete_api_v1_metrics_publications__publicationId_>`__
|
274
|
+
|
275
|
+
Args:
|
276
|
+
namespace (str): The namespace to delete the measures from. Required if measures is passed.
|
277
|
+
measures (List[str]): An array of measures to delete.
|
278
|
+
publication_id (str): The publication ID to delete. Passing this will delete all the metrics in the
|
279
|
+
publication.
|
280
|
+
|
281
|
+
Returns:
|
282
|
+
Dict[str, Any]: An empty dictionary.
|
283
|
+
|
284
|
+
Raises:
|
285
|
+
InvalidParameterException: The given request parameters are invalid.
|
286
|
+
UnauthorizedException: The credentials are invalid.
|
287
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
288
|
+
NotFoundException: The given feature does not exist.
|
289
|
+
UnprocessableEntityException: The server was unable to process the request.
|
290
|
+
InternalServerErrorException: The server failed to process the request.
|
291
|
+
"""
|
292
|
+
if publication_id:
|
293
|
+
method, endpoint = HttpMethods.DELETE, f"{self.BASE_ENDPOINT}/metrics/publications/{publication_id}"
|
294
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
295
|
+
endpoint,
|
296
|
+
method,
|
297
|
+
content_type=ContentType.APPLICATION_JSON,
|
298
|
+
)
|
299
|
+
|
300
|
+
if measures:
|
301
|
+
method, endpoint = HttpMethods.DELETE, f"{self.BASE_ENDPOINT}/metrics"
|
302
|
+
body = {"namespace": namespace, "measures": measures}
|
303
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
304
|
+
endpoint,
|
305
|
+
method,
|
306
|
+
content_type=ContentType.APPLICATION_JSON,
|
307
|
+
params=body,
|
308
|
+
)
|
309
|
+
|
310
|
+
raise InvalidParameterException(
|
311
|
+
message="Either Publication Id or Measures must be passed.",
|
312
|
+
)
|
313
|
+
|
314
|
+
def create_collection(
|
315
|
+
self,
|
316
|
+
artifact: ArtifactInfo,
|
317
|
+
body: Dict[str, Any],
|
318
|
+
) -> Dict[str, Any]:
|
319
|
+
"""Create Metric Collection.
|
320
|
+
|
321
|
+
REFERENCE:
|
322
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Collections/post_api_v1_metrics_collections>`__
|
323
|
+
|
324
|
+
Args:
|
325
|
+
body (Dict[str, Any]): A dictionary containing the details to publish the metrics.
|
326
|
+
artifact (ArtifactInfo): Mapping of artifact attributes that specifies how the artifact will be generated,
|
327
|
+
it accepts one key `path`,
|
328
|
+
|
329
|
+
Returns:
|
330
|
+
Dict[str, Any]: A dictionary containing details about the published metrics.
|
331
|
+
|
332
|
+
SCHEMA:
|
333
|
+
.. code-block:: json
|
334
|
+
|
335
|
+
{
|
336
|
+
"name": "string",
|
337
|
+
"scope": "string",
|
338
|
+
"description": "string"
|
339
|
+
}
|
340
|
+
|
341
|
+
Raises:
|
342
|
+
InvalidParameterException: The given request parameters are invalid.
|
343
|
+
UnauthorizedException: The credentials are invalid.
|
344
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
345
|
+
NotFoundException: The given feature does not exist.
|
346
|
+
UnprocessableEntityException: The server was unable to process the request.
|
347
|
+
InternalServerErrorException: The server failed to process the request.
|
348
|
+
"""
|
349
|
+
method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT}/metrics/collections"
|
350
|
+
|
351
|
+
if not artifact:
|
352
|
+
raise InvalidParameterException(
|
353
|
+
message="Artifact must be provided to create the metrics collection.",
|
354
|
+
)
|
355
|
+
|
356
|
+
path = self.__get_artifact_details(artifact)
|
357
|
+
|
358
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
359
|
+
endpoint,
|
360
|
+
method,
|
361
|
+
content_type=ContentType.MULTIPART_FORM_DATA,
|
362
|
+
body=body,
|
363
|
+
path=path,
|
364
|
+
)
|
365
|
+
|
366
|
+
def delete_collection(self, collection_id: str) -> Dict[str, Any]:
|
367
|
+
"""Delete a metric collection.
|
368
|
+
|
369
|
+
REFERENCE:
|
370
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Collections/delete_api_v1_metrics_collections__collectionId_>`__
|
371
|
+
|
372
|
+
Args:
|
373
|
+
collection_id (str): The ID of the collection to delete.
|
374
|
+
|
375
|
+
Returns:
|
376
|
+
Dict[str, Any]: A dictionary containing details about the deleted collection.
|
377
|
+
|
378
|
+
Raises:
|
379
|
+
InvalidParameterException: The given request parameters are invalid.
|
380
|
+
UnauthorizedException: The credentials are invalid.
|
381
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
382
|
+
NotFoundException: The given feature does not exist.
|
383
|
+
UnprocessableEntityException: The server was unable to process the request.
|
384
|
+
InternalServerErrorException: The server failed to process the request.
|
385
|
+
"""
|
386
|
+
method, endpoint = HttpMethods.DELETE, f"{self.BASE_ENDPOINT}/metrics/collections/{collection_id}"
|
387
|
+
|
388
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
389
|
+
endpoint,
|
390
|
+
method,
|
391
|
+
content_type=ContentType.APPLICATION_JSON,
|
392
|
+
)
|
393
|
+
|
394
|
+
@overload
|
395
|
+
def list_collections(
|
396
|
+
self,
|
397
|
+
page_size: Optional[int] = None,
|
398
|
+
page_number: Optional[int] = None,
|
399
|
+
id: Optional[List[str]] = None, # noqa: A002
|
400
|
+
scope: Optional[List[str]] = None,
|
401
|
+
*,
|
402
|
+
return_iterator: Literal[False],
|
403
|
+
) -> Dict[str, Any]: ...
|
404
|
+
|
405
|
+
@overload
|
406
|
+
def list_collections(
|
407
|
+
self,
|
408
|
+
page_size: Optional[int] = None,
|
409
|
+
page_number: Optional[int] = None,
|
410
|
+
id: Optional[List[str]] = None, # noqa: A002
|
411
|
+
scope: Optional[List[str]] = None,
|
412
|
+
*,
|
413
|
+
return_iterator: Literal[True] = True,
|
414
|
+
) -> Iterator[Dict[str, Any]]: ...
|
415
|
+
|
416
|
+
def list_collections(
|
417
|
+
self,
|
418
|
+
page_size: Optional[int] = None,
|
419
|
+
page_number: Optional[int] = None,
|
420
|
+
id: Optional[List[str]] = None, # noqa: A002
|
421
|
+
scope: Optional[List[str]] = None,
|
422
|
+
*,
|
423
|
+
return_iterator: bool = True,
|
424
|
+
) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
|
425
|
+
"""Retrieve the list of metric collections.
|
426
|
+
|
427
|
+
REFERENCE:
|
428
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Collections/get_api_v1_metrics_collections>`__
|
429
|
+
|
430
|
+
Args:
|
431
|
+
page_size (int | None): The number of images per page.
|
432
|
+
page_number (int | None): The page number to retrieve. Only used when `return_iterator` is False.
|
433
|
+
id (List[str] | None): An array of collection IDs to retrieve. If not provided, all collections are retrieved.
|
434
|
+
scope (List[str] | None): An array of scopes to filter the collections by. Available scopes are `PUBLIC` and `PRIVATE`. If not provided, all collections of the tenant along with all public collections are retrieved.
|
435
|
+
return_iterator (bool): Whether to return an iterator object or list of metrics for a specified page number, defaults to True.
|
436
|
+
|
437
|
+
Returns:
|
438
|
+
Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
|
439
|
+
If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
|
440
|
+
|
441
|
+
Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
|
442
|
+
|
443
|
+
Raises:
|
444
|
+
BadRequestException: The given request parameters are invalid.
|
445
|
+
UnauthorizedException: The credentials are invalid.
|
446
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
447
|
+
InternalServerErrorException: The server failed to process the request.
|
448
|
+
"""
|
449
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/metrics/collections"
|
450
|
+
params = {
|
451
|
+
"pageSize": page_size,
|
452
|
+
"id": id,
|
453
|
+
"scope": scope,
|
454
|
+
}
|
455
|
+
|
456
|
+
if return_iterator:
|
457
|
+
return self.session.create_generator_request(
|
458
|
+
endpoint,
|
459
|
+
method,
|
460
|
+
content_type=ContentType.APPLICATION_JSON,
|
461
|
+
response_key="collections",
|
462
|
+
params=params,
|
463
|
+
)
|
464
|
+
|
465
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
466
|
+
endpoint,
|
467
|
+
method,
|
468
|
+
content_type=ContentType.APPLICATION_JSON,
|
469
|
+
params={**params, "pageNumber": page_number},
|
470
|
+
)
|
471
|
+
|
472
|
+
@overload
|
473
|
+
def list_namespaces(
|
474
|
+
self,
|
475
|
+
page_size: Optional[int] = None,
|
476
|
+
page_number: Optional[int] = None,
|
477
|
+
*,
|
478
|
+
return_iterator: Literal[False],
|
479
|
+
) -> Dict[str, Any]: ...
|
480
|
+
|
481
|
+
@overload
|
482
|
+
def list_namespaces(
|
483
|
+
self,
|
484
|
+
page_size: Optional[int] = None,
|
485
|
+
page_number: Optional[int] = None,
|
486
|
+
*,
|
487
|
+
return_iterator: Literal[True] = True,
|
488
|
+
) -> Iterator[Dict[str, Any]]: ...
|
489
|
+
|
490
|
+
def list_namespaces(
|
491
|
+
self,
|
492
|
+
page_size: Optional[int] = None,
|
493
|
+
page_number: Optional[int] = None,
|
494
|
+
*,
|
495
|
+
return_iterator: bool = True,
|
496
|
+
) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
|
497
|
+
"""Retrieve the list of namespaces.
|
498
|
+
|
499
|
+
REFERENCE:
|
500
|
+
🔗 `API Documentation <https://service.peak.ai/semantic-layer/api-docs/index.htm#/Namespaces/get_api_v1_namespaces>`__
|
501
|
+
|
502
|
+
Args:
|
503
|
+
page_size (int | None): The number of images per page.
|
504
|
+
page_number (int | None): The page number to retrieve. Only used when `return_iterator` is False.
|
505
|
+
return_iterator (bool): Whether to return an iterator object or list of metrics for a specified page number, defaults to True.
|
506
|
+
|
507
|
+
Returns:
|
508
|
+
Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
|
509
|
+
If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
|
510
|
+
|
511
|
+
Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
|
512
|
+
|
513
|
+
Raises:
|
514
|
+
BadRequestException: The given request parameters are invalid.
|
515
|
+
UnauthorizedException: The credentials are invalid.
|
516
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
517
|
+
InternalServerErrorException: The server failed to process the request.
|
518
|
+
"""
|
519
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/namespaces"
|
520
|
+
params = {
|
521
|
+
"pageSize": page_size,
|
522
|
+
}
|
523
|
+
|
524
|
+
if return_iterator:
|
525
|
+
return self.session.create_generator_request(
|
526
|
+
endpoint,
|
527
|
+
method,
|
528
|
+
content_type=ContentType.APPLICATION_JSON,
|
529
|
+
response_key="namespaces",
|
530
|
+
params=params,
|
531
|
+
)
|
532
|
+
|
533
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
534
|
+
endpoint,
|
535
|
+
method,
|
536
|
+
content_type=ContentType.APPLICATION_JSON,
|
537
|
+
params={**params, "pageNumber": page_number},
|
538
|
+
)
|
539
|
+
|
540
|
+
|
541
|
+
def get_client(session: Optional[Session] = None) -> Metric:
|
542
|
+
"""Returns a Metrics client, If no session is provided, a default session is used.
|
543
|
+
|
544
|
+
Args:
|
545
|
+
session (Optional[Session]): A Session Object. Default is None.
|
546
|
+
|
547
|
+
Returns:
|
548
|
+
Metric: The metric client object.
|
549
|
+
"""
|
550
|
+
return Metric(session)
|
551
|
+
|
552
|
+
|
553
|
+
__all__ = ["get_client"]
|
peak/output.py
CHANGED
@@ -87,7 +87,7 @@ class Writer:
|
|
87
87
|
output_type (OutputTypes): If passed, JSON parser would be used to print output
|
88
88
|
even if the data is not a dictionary.
|
89
89
|
"""
|
90
|
-
if isinstance(data, dict) or output_type == OutputTypes.json:
|
90
|
+
if isinstance(data, (dict, list)) or output_type == OutputTypes.json:
|
91
91
|
console.print_json(data=data)
|
92
92
|
else:
|
93
93
|
console.print(data)
|
@@ -128,6 +128,11 @@ class Writer:
|
|
128
128
|
|
129
129
|
output_keys = params["output_keys"].items()
|
130
130
|
|
131
|
+
if len(output_keys) == 0:
|
132
|
+
keys = data[params["data_key"]][0].keys()
|
133
|
+
params["output_keys"] = {key: {"label": key} for key in keys}
|
134
|
+
output_keys = params["output_keys"].items()
|
135
|
+
|
131
136
|
for key_details in output_keys:
|
132
137
|
table.add_column(key_details[1]["label"])
|
133
138
|
|
@@ -176,6 +181,9 @@ class Writer:
|
|
176
181
|
if not key:
|
177
182
|
return data
|
178
183
|
|
184
|
+
if key in data:
|
185
|
+
return data[key]
|
186
|
+
|
179
187
|
key_first_part = key.split(".")[0]
|
180
188
|
key_rest = ".".join(key.split(".")[1:])
|
181
189
|
|
peak/press/blocks.py
CHANGED
@@ -542,6 +542,7 @@ class Block(BaseClient):
|
|
542
542
|
"secrets": []
|
543
543
|
},
|
544
544
|
"sessionStickiness": "boolean (only for web-app service)",
|
545
|
+
"scaleToZero": "boolean (only for web-app service)",
|
545
546
|
"entrypoint": "string",
|
546
547
|
"healthCheckURL": "string",
|
547
548
|
"minInstances": "number. Default is 1 and maximum is 2",
|
@@ -1090,6 +1091,7 @@ class Block(BaseClient):
|
|
1090
1091
|
"secrets": []
|
1091
1092
|
},
|
1092
1093
|
"sessionStickiness": "boolean (only for web-app service)",
|
1094
|
+
"scaleToZero": "boolean (only for web-app service)",
|
1093
1095
|
"entrypoint": "string",
|
1094
1096
|
"healthCheckURL": "string",
|
1095
1097
|
"minInstances": "number. Default is 1 and maximum is 2",
|
peak/resources/__init__.py
CHANGED
@@ -26,4 +26,13 @@ from typing import List
|
|
26
26
|
|
27
27
|
from peak.resources import alerts, artifacts, images, services, tenants, users, webapps, workflows
|
28
28
|
|
29
|
-
__all__: List[str] = [
|
29
|
+
__all__: List[str] = [
|
30
|
+
"alerts",
|
31
|
+
"artifacts",
|
32
|
+
"images",
|
33
|
+
"services",
|
34
|
+
"tenants",
|
35
|
+
"users",
|
36
|
+
"webapps",
|
37
|
+
"workflows",
|
38
|
+
]
|
peak/resources/services.py
CHANGED
@@ -152,6 +152,7 @@ class Service(BaseClient):
|
|
152
152
|
},
|
153
153
|
"description": "string",
|
154
154
|
"sessionStickiness": "boolean. Not required for 'api' service type.",
|
155
|
+
"scaleToZero": "boolean. Only for 'web-app' service type.",
|
155
156
|
"entrypoint": "string",
|
156
157
|
"healthCheckURL": "string",
|
157
158
|
"minInstances": "number. Default is 1 and maximum is 2",
|
@@ -180,7 +181,7 @@ class Service(BaseClient):
|
|
180
181
|
"""Updates the existing service.
|
181
182
|
|
182
183
|
When updating the service, it will trigger a redeployment only under specific conditions.
|
183
|
-
Redeployment is triggered if you make changes to any of the following parameters: imageId, versionId, instanceTypeId, parameters, healthCheckURL, entrypoint or sessionStickiness.
|
184
|
+
Redeployment is triggered if you make changes to any of the following parameters: imageId, versionId, instanceTypeId, parameters, healthCheckURL, entrypoint, scaleToZero or sessionStickiness.
|
184
185
|
However, only modifying the title or description will not trigger a redeployment.
|
185
186
|
|
186
187
|
With the help of this operation, we can just update the required fields (except name and serviceType) and keep the rest of the fields as it is.
|
@@ -215,6 +216,7 @@ class Service(BaseClient):
|
|
215
216
|
},
|
216
217
|
"description": "string",
|
217
218
|
"sessionStickiness": "boolean. Not required for 'api' service type.",
|
219
|
+
"scaleToZero": "boolean. Only for 'web-app' service type.",
|
218
220
|
"entrypoint": "string",
|
219
221
|
"healthCheckURL": "string",
|
220
222
|
"minInstances": "number. Default is 1 and maximum is 2",
|
@@ -240,7 +242,7 @@ class Service(BaseClient):
|
|
240
242
|
"""Create a new service or updates an existing service based on service name.
|
241
243
|
|
242
244
|
When updating the service, it will trigger a redeployment only under specific conditions.
|
243
|
-
Redeployment is triggered if you make changes to any of the following parameters: imageId, versionId, instanceTypeId, parameters, healthCheckURL, entrypoint or sessionStickiness.
|
245
|
+
Redeployment is triggered if you make changes to any of the following parameters: imageId, versionId, instanceTypeId, parameters, healthCheckURL, entrypoint, scaleToZero or sessionStickiness.
|
244
246
|
However, only modifying the title or description will not trigger a redeployment.
|
245
247
|
|
246
248
|
REFERENCE:
|
@@ -274,6 +276,7 @@ class Service(BaseClient):
|
|
274
276
|
},
|
275
277
|
"description": "string",
|
276
278
|
"sessionStickiness": "boolean. Not required for 'api' service type.",
|
279
|
+
"scaleToZero": "boolean. Only for 'web-app' service type.",
|
277
280
|
"entrypoint": "string",
|
278
281
|
"healthCheckURL": "string",
|
279
282
|
"minInstances": "number. Default is 1 and maximum is 2",
|