peak-sdk 1.5.0__py3-none-any.whl → 1.7.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/_metadata.py +80 -5
- peak/_version.py +1 -1
- peak/cli/args.py +1 -0
- peak/cli/cli.py +3 -2
- peak/cli/helpers.py +1 -0
- peak/cli/press/apps/specs.py +2 -0
- peak/cli/press/blocks/specs.py +68 -24
- peak/cli/press/deployments.py +41 -0
- peak/cli/press/specs.py +4 -2
- peak/cli/resources/alerts/__init__.py +35 -0
- peak/cli/resources/alerts/emails.py +360 -0
- peak/cli/resources/images.py +19 -7
- peak/cli/resources/services.py +23 -0
- peak/cli/resources/tenants.py +4 -1
- peak/cli/resources/workflows.py +81 -19
- peak/cli/ruff.toml +5 -3
- peak/compression.py +2 -2
- peak/exceptions.py +4 -6
- peak/handler.py +3 -5
- peak/helpers.py +8 -9
- peak/output.py +2 -2
- peak/press/apps.py +18 -19
- peak/press/blocks.py +396 -155
- peak/press/deployments.py +30 -4
- peak/press/specs.py +12 -14
- peak/resources/__init__.py +3 -2
- peak/resources/alerts.py +309 -0
- peak/resources/artifacts.py +2 -4
- peak/resources/images.py +317 -100
- peak/resources/services.py +7 -6
- peak/resources/webapps.py +3 -5
- peak/resources/workflows.py +103 -13
- peak/sample_yaml/press/apps/specs/create_app_spec.yaml +2 -0
- peak/sample_yaml/press/apps/specs/create_app_spec_release.yaml +2 -0
- peak/sample_yaml/press/blocks/specs/service/api/create_block_spec.yaml +102 -0
- peak/sample_yaml/press/blocks/specs/service/api/create_block_spec_release.yaml +88 -0
- peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec.yaml +103 -0
- peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec_release.yaml +89 -0
- peak/sample_yaml/press/blocks/specs/{create_block_spec.yaml → workflow/create_block_spec.yaml} +20 -1
- peak/sample_yaml/press/blocks/specs/{create_block_spec_release.yaml → workflow/create_block_spec_release.yaml} +20 -1
- peak/sample_yaml/resources/emails/send_email.yaml +15 -0
- peak/sample_yaml/resources/images/dockerfile/create_image.yaml +3 -0
- peak/sample_yaml/resources/images/dockerfile/create_image_version.yaml +3 -0
- peak/sample_yaml/resources/images/dockerfile/update_version.yaml +3 -0
- peak/sample_yaml/resources/images/github/create_image.yaml +3 -0
- peak/sample_yaml/resources/images/github/create_image_version.yaml +3 -0
- peak/sample_yaml/resources/images/github/update_version.yaml +3 -0
- peak/sample_yaml/resources/images/upload/create_image.yaml +3 -0
- peak/sample_yaml/resources/images/upload/create_image_version.yaml +3 -0
- peak/sample_yaml/resources/images/upload/create_or_update_image.yaml +3 -0
- peak/sample_yaml/resources/images/upload/update_version.yaml +3 -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/workflows/create_or_update_workflow.yaml +36 -0
- peak/sample_yaml/resources/workflows/create_workflow.yaml +19 -1
- peak/sample_yaml/resources/workflows/patch_workflow.yaml +36 -0
- peak/sample_yaml/resources/workflows/update_workflow.yaml +36 -0
- peak/session.py +1 -1
- peak/telemetry.py +1 -1
- peak/template.py +6 -4
- peak/tools/logging/__init__.py +26 -268
- peak/tools/logging/log_level.py +35 -3
- peak/tools/logging/logger.py +389 -0
- {peak_sdk-1.5.0.dist-info → peak_sdk-1.7.0.dist-info}/METADATA +19 -20
- {peak_sdk-1.5.0.dist-info → peak_sdk-1.7.0.dist-info}/RECORD +69 -60
- {peak_sdk-1.5.0.dist-info → peak_sdk-1.7.0.dist-info}/WHEEL +1 -1
- {peak_sdk-1.5.0.dist-info → peak_sdk-1.7.0.dist-info}/LICENSE +0 -0
- {peak_sdk-1.5.0.dist-info → peak_sdk-1.7.0.dist-info}/entry_points.txt +0 -0
peak/cli/resources/workflows.py
CHANGED
@@ -82,6 +82,16 @@ _CLEAR_IMAGE_CACHE = typer.Option(None, help="Whether to clear image cache on wo
|
|
82
82
|
|
83
83
|
_STEP_NAMES = typer.Option(None, help="List of step names to be updated.")
|
84
84
|
|
85
|
+
_EXECUTION_STATUS = typer.Option(
|
86
|
+
None,
|
87
|
+
help="List of workflow execution statuses. Valid values are `Success`, `Running`, `Stopped`, `Stopping` and `Failed`.",
|
88
|
+
)
|
89
|
+
|
90
|
+
_COUNT = typer.Option(
|
91
|
+
None,
|
92
|
+
help="Number of workflow executions required in the provided time range or 90 days. If not provided, all executions are returned.",
|
93
|
+
)
|
94
|
+
|
85
95
|
|
86
96
|
@app.command(short_help="Create a new workflow.", options_metavar="create_workflow")
|
87
97
|
def create(
|
@@ -109,13 +119,25 @@ def create(
|
|
109
119
|
watchers (list(map) | required: false):
|
110
120
|
- events (map):
|
111
121
|
success (boolean | required: false): Whether to call event on success.
|
112
|
-
fail (boolean | required: false): Whether to call event on
|
113
|
-
runtimeExceeded (int | required: false): The runtime after which event is called.
|
114
|
-
user (string
|
115
|
-
|
122
|
+
fail (boolean | required: false): Whether to call event on failure.
|
123
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
124
|
+
user (string): User to be notified.
|
125
|
+
- events (map):
|
126
|
+
success (boolean | required: false): Whether to call event on success.
|
127
|
+
fail (boolean | required: false): Whether to call event on failure.
|
128
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
129
|
+
webhook (map):
|
116
130
|
name (string): Name of the webhook.
|
117
131
|
url (string): URL of the webhook.
|
118
132
|
payload (string): Webhook payload.
|
133
|
+
- events (map):
|
134
|
+
success (boolean | required: false): Whether to call event on success.
|
135
|
+
fail (boolean | required: false): Whether to call event on failure.
|
136
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
137
|
+
email (map):
|
138
|
+
name (string): Name of the email watcher.
|
139
|
+
recipients (map):
|
140
|
+
to (list(str)): List of email addresses to send the email to. Email can be sent only to the users who are added in the tenant.
|
119
141
|
retryOptions (map | required: false): # Workflow level retry options which will be applied to all steps.
|
120
142
|
duration (int | required: false): Duration in seconds after which the step is retried if it fails. Default is 5 seconds and maximum is 120 seconds.
|
121
143
|
exitCodes (list(int) | required: false): List of exit codes for which the step is retried. If not provided, the step is retried for all exit codes.
|
@@ -221,13 +243,25 @@ def update(
|
|
221
243
|
watchers (list(map) | required: false):
|
222
244
|
- events (map):
|
223
245
|
success (boolean | required: false): Whether to call event on success.
|
224
|
-
fail (boolean | required: false): Whether to call event on
|
225
|
-
runtimeExceeded (int | required: false): The runtime after which event is called.
|
226
|
-
user (string
|
227
|
-
|
246
|
+
fail (boolean | required: false): Whether to call event on failure.
|
247
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
248
|
+
user (string): User to be notified.
|
249
|
+
- events (map):
|
250
|
+
success (boolean | required: false): Whether to call event on success.
|
251
|
+
fail (boolean | required: false): Whether to call event on failure.
|
252
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
253
|
+
webhook (map):
|
228
254
|
name (string): Name of the webhook.
|
229
255
|
url (string): URL of the webhook.
|
230
256
|
payload (string): Webhook payload.
|
257
|
+
- events (map):
|
258
|
+
success (boolean | required: false): Whether to call event on success.
|
259
|
+
fail (boolean | required: false): Whether to call event on failure.
|
260
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
261
|
+
email (map):
|
262
|
+
name (string): Name of the email watcher.
|
263
|
+
recipients (map):
|
264
|
+
to (list(str)): List of email addresses to send the email to. Email can be sent only to the users who are added in the tenant.
|
231
265
|
retryOptions (map | required: false): # Workflow level retry options which will be applied to all steps.
|
232
266
|
duration (int | required: false): Duration in seconds after which the step is retried if it fails. Default is 5 seconds and maximum is 120 seconds.
|
233
267
|
exitCodes (list(int) | required: false): List of exit codes for which the step is retried. If not provided, the step is retried for all exit codes.
|
@@ -333,13 +367,25 @@ def create_or_update(
|
|
333
367
|
watchers (list(map) | required: false):
|
334
368
|
- events (map):
|
335
369
|
success (boolean | required: false): Whether to call event on success.
|
336
|
-
fail (boolean | required: false): Whether to call event on
|
337
|
-
runtimeExceeded (int | required: false): The runtime after which event is called.
|
338
|
-
user (string
|
339
|
-
|
370
|
+
fail (boolean | required: false): Whether to call event on failure.
|
371
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
372
|
+
user (string): User to be notified.
|
373
|
+
- events (map):
|
374
|
+
success (boolean | required: false): Whether to call event on success.
|
375
|
+
fail (boolean | required: false): Whether to call event on failure.
|
376
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
377
|
+
webhook (map):
|
340
378
|
name (string): Name of the webhook.
|
341
379
|
url (string): URL of the webhook.
|
342
380
|
payload (string): Webhook payload.
|
381
|
+
- events (map):
|
382
|
+
success (boolean | required: false): Whether to call event on success.
|
383
|
+
fail (boolean | required: false): Whether to call event on failure.
|
384
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
385
|
+
email (map):
|
386
|
+
name (string): Name of the email watcher.
|
387
|
+
recipients (map):
|
388
|
+
to (list(str)): List of email addresses to send the email to. Email can be sent only to the users who are added in the tenant.
|
343
389
|
retryOptions (map | required: false): # Workflow level retry options which will be applied to all steps.
|
344
390
|
duration (int | required: false): Duration in seconds after which the step is retried if it fails. Default is 5 seconds and maximum is 120 seconds.
|
345
391
|
exitCodes (list(int) | required: false): List of exit codes for which the step is retried. If not provided, the step is retried for all exit codes.
|
@@ -475,13 +521,25 @@ def patch(
|
|
475
521
|
watchers (list(map) | required: false):
|
476
522
|
- events (map):
|
477
523
|
success (boolean | required: false): Whether to call event on success.
|
478
|
-
fail (boolean | required: false): Whether to call event on
|
479
|
-
runtimeExceeded (int | required: false): The runtime after which event is called.
|
480
|
-
user (string
|
481
|
-
|
524
|
+
fail (boolean | required: false): Whether to call event on failure.
|
525
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
526
|
+
user (string): User to be notified.
|
527
|
+
- events (map):
|
528
|
+
success (boolean | required: false): Whether to call event on success.
|
529
|
+
fail (boolean | required: false): Whether to call event on failure.
|
530
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
531
|
+
webhook (map):
|
482
532
|
name (string): Name of the webhook.
|
483
533
|
url (string): URL of the webhook.
|
484
534
|
payload (string): Webhook payload.
|
535
|
+
- events (map):
|
536
|
+
success (boolean | required: false): Whether to call event on success.
|
537
|
+
fail (boolean | required: false): Whether to call event on failure.
|
538
|
+
runtimeExceeded (int | required: false): The runtime in minutes after which event is called.
|
539
|
+
email (map):
|
540
|
+
name (string): Name of the email watcher.
|
541
|
+
recipients (map):
|
542
|
+
to (list(str)): List of email addresses to send the email to. Email can be sent only to the users who are added in the tenant.
|
485
543
|
retryOptions (map | required: false): # Workflow level retry options which will be applied to all steps.
|
486
544
|
duration (int | required: false): Duration in seconds after which the step is retried if it fails. Default is 5 seconds and maximum is 120 seconds.
|
487
545
|
exitCodes (list(int) | required: false): List of exit codes for which the step is retried. If not provided, the step is retried for all exit codes.
|
@@ -599,7 +657,7 @@ def list_workflows(
|
|
599
657
|
\b
|
600
658
|
📝 ***Example usage:***<br/>
|
601
659
|
```bash
|
602
|
-
peak workflows list --page-size 10 --page-number 1 --
|
660
|
+
peak workflows list --page-size 10 --page-number 1 --workflow-status "Draft" --last-execution-status "Success" --last-modified-by "abc@peak.ai" --name "test"
|
603
661
|
```
|
604
662
|
|
605
663
|
\b
|
@@ -847,6 +905,8 @@ def list_executions(
|
|
847
905
|
workflow_id: int = _WORKFLOW_ID,
|
848
906
|
date_from: Optional[str] = args.DATE_FROM,
|
849
907
|
date_to: Optional[str] = args.DATE_TO,
|
908
|
+
status: Optional[List[str]] = _EXECUTION_STATUS,
|
909
|
+
count: Optional[int] = _COUNT,
|
850
910
|
page_size: Optional[int] = args.PAGE_SIZE,
|
851
911
|
page_number: Optional[int] = args.PAGE_NUMBER,
|
852
912
|
paging: Optional[bool] = PAGING, # noqa: ARG001
|
@@ -857,7 +917,7 @@ def list_executions(
|
|
857
917
|
\b
|
858
918
|
📝 ***Example usage:***<br/>
|
859
919
|
```bash
|
860
|
-
peak workflows list-executions 9999 --page-size 10 --page-number 1
|
920
|
+
peak workflows list-executions 9999 --page-size 10 --page-number 1 --status "Running" --status "Failed"
|
861
921
|
```
|
862
922
|
|
863
923
|
\b
|
@@ -882,6 +942,8 @@ def list_executions(
|
|
882
942
|
workflow_id=workflow_id,
|
883
943
|
date_from=date_from,
|
884
944
|
date_to=date_to,
|
945
|
+
status=parse_list_of_strings(status),
|
946
|
+
count=count,
|
885
947
|
page_size=page_size,
|
886
948
|
page_number=page_number,
|
887
949
|
return_iterator=False,
|
@@ -974,7 +1036,7 @@ def get_execution_logs(
|
|
974
1036
|
writer.write(response)
|
975
1037
|
break
|
976
1038
|
|
977
|
-
next_token = response
|
1039
|
+
next_token = response.get("nextToken", None)
|
978
1040
|
|
979
1041
|
|
980
1042
|
@app.command(short_help="Get workflow execution details.", options_metavar="get_execution_details")
|
peak/cli/ruff.toml
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
extend = '../../pyproject.toml'
|
2
2
|
src = ["."]
|
3
|
-
ignore = [
|
3
|
+
lint.ignore = [
|
4
4
|
"UP007", # typer is not PEP-585 and PEP-604 compliant
|
5
5
|
"D208",
|
6
6
|
"FBT001",
|
7
7
|
"FBT002",
|
8
8
|
"FBT003",
|
9
|
-
"RSE102"
|
9
|
+
"RSE102",
|
10
|
+
"FA100"
|
11
|
+
# TODO: remove this once we are supporting > 3.10 properly
|
10
12
|
]
|
11
|
-
unfixable = []
|
13
|
+
lint.unfixable = []
|
peak/compression.py
CHANGED
@@ -65,7 +65,7 @@ def compress(path: str, ignore_files: Optional[list[str]] = None) -> Iterator[te
|
|
65
65
|
raise exceptions.FileLimitExceededException(constants.MAX_ARTIFACT_SIZE_MB)
|
66
66
|
|
67
67
|
# include directories as API backend need directories explicitly included
|
68
|
-
relative_root_path = Path(
|
68
|
+
relative_root_path = Path()
|
69
69
|
if relative_root_path in parent_directories:
|
70
70
|
parent_directories.remove(relative_root_path)
|
71
71
|
for directory in parent_directories:
|
@@ -192,7 +192,7 @@ def _build_files_dict(files: Iterable[str]) -> dict[str, dict]: # type: ignore[
|
|
192
192
|
"""
|
193
193
|
files_dict: dict[str, dict] = {} # type: ignore[type-arg]
|
194
194
|
for f in files:
|
195
|
-
components = os.path.normpath(f).
|
195
|
+
components = Path(os.path.normpath(f)).parts
|
196
196
|
current_dir = files_dict
|
197
197
|
for directory in components[:-1]:
|
198
198
|
if directory not in current_dir:
|
peak/exceptions.py
CHANGED
@@ -29,13 +29,11 @@ from typing import Any, ClassVar, Dict, List, Optional, Tuple, Type
|
|
29
29
|
class PeakBaseException(Exception):
|
30
30
|
"""Base exception class for the Peak SDK."""
|
31
31
|
|
32
|
-
...
|
33
|
-
|
34
32
|
|
35
33
|
class HttpExceptionsRegistryMeta(type):
|
36
34
|
"""Registry metaclass."""
|
37
35
|
|
38
|
-
REGISTRY: Dict[int, Any] = defaultdict(lambda: Exception)
|
36
|
+
REGISTRY: ClassVar[Dict[int, Any]] = defaultdict(lambda: Exception)
|
39
37
|
|
40
38
|
def __new__(
|
41
39
|
cls: "Type[HttpExceptionsRegistryMeta]",
|
@@ -58,7 +56,7 @@ class HttpExceptionsRegistryMeta(type):
|
|
58
56
|
HttpExceptionsRegistryMeta: the child class itself, forward annotated for type checking
|
59
57
|
"""
|
60
58
|
new_cls: "HttpExceptionsRegistryMeta" = type.__new__(cls, name, bases, attrs)
|
61
|
-
status_code: Optional[int] = attrs.get("STATUS_CODE"
|
59
|
+
status_code: Optional[int] = attrs.get("STATUS_CODE")
|
62
60
|
if status_code:
|
63
61
|
cls.REGISTRY[status_code] = new_cls
|
64
62
|
return new_cls
|
@@ -148,11 +146,11 @@ class MissingEnvironmentVariableException(PeakBaseException):
|
|
148
146
|
class FileLimitExceededException(PeakBaseException):
|
149
147
|
"""Limits on the file are exceeded."""
|
150
148
|
|
151
|
-
def __init__(self, max_size:
|
149
|
+
def __init__(self, max_size: float, *, message: str = "", units: str = "MB") -> None:
|
152
150
|
"""Throw exception with custom message.
|
153
151
|
|
154
152
|
Args:
|
155
|
-
max_size (
|
153
|
+
max_size (float): Maximum size of the file.
|
156
154
|
message (str): Additional message to add to exception.
|
157
155
|
units (str): Units of the maximum size.
|
158
156
|
"""
|
peak/handler.py
CHANGED
@@ -51,7 +51,7 @@ writer = Writer(ignore_debug_mode=True)
|
|
51
51
|
class HandlerRegistryMeta(type):
|
52
52
|
"""Metaclass for registering all types of Handler classes."""
|
53
53
|
|
54
|
-
REGISTRY: Dict[ContentType, BaseHandler] = {}
|
54
|
+
REGISTRY: ClassVar[Dict[ContentType, BaseHandler]] = {}
|
55
55
|
|
56
56
|
def __new__(
|
57
57
|
cls: "Type[HandlerRegistryMeta]",
|
@@ -79,7 +79,7 @@ class HandlerRegistryMeta(type):
|
|
79
79
|
error_invalid_content_type: str = f"Invalid content type for {name} handler"
|
80
80
|
new_cls: "HandlerRegistryMeta" = type.__new__(cls, name, bases, attrs)
|
81
81
|
|
82
|
-
content_type: Optional[ContentType] = attrs.get("CONTENT_TYPE"
|
82
|
+
content_type: Optional[ContentType] = attrs.get("CONTENT_TYPE")
|
83
83
|
try:
|
84
84
|
if content_type and ContentType(content_type):
|
85
85
|
cls.REGISTRY[content_type] = new_cls()
|
@@ -92,14 +92,12 @@ class HandlerRegistryMeta(type):
|
|
92
92
|
class _CombinedMeta(HandlerRegistryMeta, ABCMeta):
|
93
93
|
"""Utility class for combining multiple meta-classes."""
|
94
94
|
|
95
|
-
...
|
96
|
-
|
97
95
|
|
98
96
|
class AuthRetrySession(requests.Session):
|
99
97
|
"""Session with extra sugar attached."""
|
100
98
|
|
101
99
|
# used in testing, so we can modify the backoff_factor etc. to speed up the tests
|
102
|
-
_DEFAULT_RETRY_CONFIG: Dict[str, Any] = {
|
100
|
+
_DEFAULT_RETRY_CONFIG: ClassVar[Dict[str, Any]] = {
|
103
101
|
"backoff_factor": 2,
|
104
102
|
"total": 5,
|
105
103
|
"status_forcelist": [500, 502, 503, 504],
|
peak/helpers.py
CHANGED
@@ -44,7 +44,7 @@ def parse_body_for_multipart_request(body: Dict[str, Any]) -> Dict[str, str]:
|
|
44
44
|
Returns:
|
45
45
|
Dict[str, str]: the parsed object
|
46
46
|
"""
|
47
|
-
return {key: (value if
|
47
|
+
return {key: (value if isinstance(value, str) else json.dumps(value)) for (key, value) in body.items()}
|
48
48
|
|
49
49
|
|
50
50
|
def remove_keys(body: Dict[str, Any], keys: List[str]) -> Dict[str, Any]:
|
@@ -76,8 +76,7 @@ def get_base_domain(stage: str, subdomain: Optional[str] = "service") -> str:
|
|
76
76
|
stage = "dev"
|
77
77
|
|
78
78
|
domain: str = f"https://{subdomain}.{stage}.peak.ai"
|
79
|
-
|
80
|
-
return domain
|
79
|
+
return domain.replace("..", ".") # for prod domain
|
81
80
|
|
82
81
|
|
83
82
|
def parse_list_of_strings(param: List[str] | None) -> List[str] | None:
|
@@ -113,7 +112,7 @@ def snake_case_to_lower_camel_case(snake_case_string: str) -> str:
|
|
113
112
|
|
114
113
|
|
115
114
|
def variables_to_dict(*args: Any, frame: FrameType | None = None) -> Dict[str, str]:
|
116
|
-
"""Converts
|
115
|
+
"""Converts arbitrary variables to a dictionary.
|
117
116
|
|
118
117
|
Args:
|
119
118
|
args (str|int): tuple of string|int variables
|
@@ -143,11 +142,11 @@ def combine_dictionaries(
|
|
143
142
|
dict2: Dict[str, Any],
|
144
143
|
nested_keys_to_skip: Optional[List[str]] = [], # noqa: B006
|
145
144
|
) -> Dict[str, Any]:
|
146
|
-
"""Combines two
|
145
|
+
"""Combines two dictionaries. Values for second dictionary have higher precedence.
|
147
146
|
|
148
147
|
Args:
|
149
148
|
dict1 (Dict[str, Any]): dictionary 1
|
150
|
-
dict2 (Dict[str, Any]):
|
149
|
+
dict2 (Dict[str, Any]): dictionary 2
|
151
150
|
nested_keys_to_skip (List[str] | None): Keys for which nested combining is not required.
|
152
151
|
|
153
152
|
Returns:
|
@@ -158,7 +157,7 @@ def combine_dictionaries(
|
|
158
157
|
|
159
158
|
combined_dict = dict(dict1)
|
160
159
|
for key in dict2:
|
161
|
-
if key in combined_dict and
|
160
|
+
if key in combined_dict and isinstance(combined_dict[key], dict) and key not in (nested_keys_to_skip or []):
|
162
161
|
combined_dict[key] = combine_dictionaries(combined_dict[key], dict2[key])
|
163
162
|
else:
|
164
163
|
combined_dict[key] = dict2[key]
|
@@ -178,12 +177,12 @@ def map_user_options(
|
|
178
177
|
dict_type_keys (List[str]): List of keys which have json type values
|
179
178
|
|
180
179
|
Returns:
|
181
|
-
Dict[str, str]:
|
180
|
+
Dict[str, str]: Mapped dictionary
|
182
181
|
"""
|
183
182
|
result: Dict[str, Any] = {}
|
184
183
|
for key in user_options:
|
185
184
|
if key in mapping:
|
186
|
-
nested_dict = result
|
185
|
+
nested_dict = result.get(mapping[key], {})
|
187
186
|
nested_dict[key] = json.loads(user_options[key]) if key in dict_type_keys else user_options[key]
|
188
187
|
result[mapping[key]] = nested_dict
|
189
188
|
else:
|
peak/output.py
CHANGED
@@ -105,7 +105,7 @@ class Writer:
|
|
105
105
|
title = params["title"]
|
106
106
|
|
107
107
|
if "subheader_key" in params and params["subheader_key"] in data:
|
108
|
-
subheader_title = "
|
108
|
+
subheader_title = params.get("subheader_title", "Total")
|
109
109
|
title = f'{title} ({subheader_title} = {data[params["subheader_key"]]})'
|
110
110
|
|
111
111
|
table = Table(
|
@@ -135,7 +135,7 @@ class Writer:
|
|
135
135
|
elif "parser" in key_details[1]:
|
136
136
|
v = key_details[1]["parser"](v)
|
137
137
|
|
138
|
-
if isinstance(v, (dict, list)):
|
138
|
+
if isinstance(v, (dict, list)):
|
139
139
|
parsed_value = json_highlighter(Text(json.dumps(v, indent=2), overflow="fold"))
|
140
140
|
else:
|
141
141
|
parsed_value = Text(str(v), overflow="fold")
|
peak/press/apps.py
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
# # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
|
20
20
|
#
|
21
21
|
"""Apps client module."""
|
22
|
+
|
22
23
|
from __future__ import annotations
|
23
24
|
|
24
25
|
import json
|
@@ -48,8 +49,7 @@ class App(BaseClient):
|
|
48
49
|
page_number: Optional[int] = None,
|
49
50
|
*,
|
50
51
|
return_iterator: Literal[False],
|
51
|
-
) -> Dict[str, Any]:
|
52
|
-
...
|
52
|
+
) -> Dict[str, Any]: ...
|
53
53
|
|
54
54
|
@overload
|
55
55
|
def list_specs(
|
@@ -64,8 +64,7 @@ class App(BaseClient):
|
|
64
64
|
page_number: Optional[int] = None,
|
65
65
|
*,
|
66
66
|
return_iterator: Literal[True] = True,
|
67
|
-
) -> Iterator[Dict[str, Any]]:
|
68
|
-
...
|
67
|
+
) -> Iterator[Dict[str, Any]]: ...
|
69
68
|
|
70
69
|
def list_specs(
|
71
70
|
self,
|
@@ -153,7 +152,8 @@ class App(BaseClient):
|
|
153
152
|
|
154
153
|
All App Specs must have unique names within a tenant.
|
155
154
|
An App Spec must now be made up of already existing block specs.
|
156
|
-
Spec details (
|
155
|
+
Spec details (Block spec ID and Release version) needs to be added to the `config` key.
|
156
|
+
`config` also contains a `autoRunOnDeploy` key which is a boolean value to specify if the resource should be executed on successful deployment of the app. By default, it is False.
|
157
157
|
|
158
158
|
REFERENCE:
|
159
159
|
🔗 `API Documentation <https://press.peak.ai/api-docs/index.htm#/App%20Specs/post_v1_apps_specs_>`__
|
@@ -198,7 +198,8 @@ class App(BaseClient):
|
|
198
198
|
"id": "string(required)",
|
199
199
|
"release": {
|
200
200
|
"version": "string(required)",
|
201
|
-
}
|
201
|
+
},
|
202
|
+
"autoRunOnDeploy": "boolean (By default it is False)",
|
202
203
|
}
|
203
204
|
]
|
204
205
|
}
|
@@ -321,6 +322,9 @@ class App(BaseClient):
|
|
321
322
|
def create_spec_release(self, spec_id: str, body: Dict[str, Any]) -> Dict[str, str]:
|
322
323
|
"""Publish a new release to an existing App spec.
|
323
324
|
|
325
|
+
Spec details (Block spec ID and Release version) needs to be added to the `config` key.
|
326
|
+
`config` also contains a `autoRunOnDeploy` key which is a boolean value to specify if the resource should be executed on successful deployment of the app. By default, it is False.
|
327
|
+
|
324
328
|
REFERENCE:
|
325
329
|
🔗 `API Documentation <https://press.peak.ai/api-docs/index.htm#/App%20Specs/post_v1_apps_specs__specId__releases>`__
|
326
330
|
|
@@ -340,7 +344,8 @@ class App(BaseClient):
|
|
340
344
|
"id": "string(required)",
|
341
345
|
"release": {
|
342
346
|
"version": "string(required)",
|
343
|
-
}
|
347
|
+
},
|
348
|
+
"autoRunOnDeploy": "boolean (By default it is False)",
|
344
349
|
}
|
345
350
|
],
|
346
351
|
"release": {
|
@@ -440,8 +445,7 @@ class App(BaseClient):
|
|
440
445
|
page_number: Optional[int] = None,
|
441
446
|
*,
|
442
447
|
return_iterator: Literal[False],
|
443
|
-
) -> Dict[str, Any]:
|
444
|
-
...
|
448
|
+
) -> Dict[str, Any]: ...
|
445
449
|
|
446
450
|
@overload
|
447
451
|
def list_spec_releases(
|
@@ -452,8 +456,7 @@ class App(BaseClient):
|
|
452
456
|
page_number: Optional[int] = None,
|
453
457
|
*,
|
454
458
|
return_iterator: Literal[True] = True,
|
455
|
-
) -> Iterator[Dict[str, Any]]:
|
456
|
-
...
|
459
|
+
) -> Iterator[Dict[str, Any]]: ...
|
457
460
|
|
458
461
|
def list_spec_releases(
|
459
462
|
self,
|
@@ -595,8 +598,7 @@ class App(BaseClient):
|
|
595
598
|
page_number: Optional[int] = None,
|
596
599
|
*,
|
597
600
|
return_iterator: Literal[False],
|
598
|
-
) -> Dict[str, Any]:
|
599
|
-
...
|
601
|
+
) -> Dict[str, Any]: ...
|
600
602
|
|
601
603
|
@overload
|
602
604
|
def list_deployments(
|
@@ -608,8 +610,7 @@ class App(BaseClient):
|
|
608
610
|
page_number: Optional[int] = None,
|
609
611
|
*,
|
610
612
|
return_iterator: Literal[True] = True,
|
611
|
-
) -> Iterator[Dict[str, Any]]:
|
612
|
-
...
|
613
|
+
) -> Iterator[Dict[str, Any]]: ...
|
613
614
|
|
614
615
|
def list_deployments(
|
615
616
|
self,
|
@@ -844,8 +845,7 @@ class App(BaseClient):
|
|
844
845
|
page_number: Optional[int] = None,
|
845
846
|
*,
|
846
847
|
return_iterator: Literal[False],
|
847
|
-
) -> Dict[str, Any]:
|
848
|
-
...
|
848
|
+
) -> Dict[str, Any]: ...
|
849
849
|
|
850
850
|
@overload
|
851
851
|
def list_deployment_revisions(
|
@@ -857,8 +857,7 @@ class App(BaseClient):
|
|
857
857
|
page_number: Optional[int] = None,
|
858
858
|
*,
|
859
859
|
return_iterator: Literal[True] = True,
|
860
|
-
) -> Iterator[Dict[str, Any]]:
|
861
|
-
...
|
860
|
+
) -> Iterator[Dict[str, Any]]: ...
|
862
861
|
|
863
862
|
def list_deployment_revisions(
|
864
863
|
self,
|