peak-sdk 1.13.0__py3-none-any.whl → 1.15.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.
Files changed (34) hide show
  1. peak/_metadata.py +4 -1
  2. peak/_version.py +2 -2
  3. peak/cli/press/apps/specs.py +14 -1
  4. peak/cli/press/blocks/specs.py +13 -1
  5. peak/cli/press/deployments.py +58 -2
  6. peak/cli/resources/alerts/emails.py +8 -4
  7. peak/cli/resources/artifacts.py +6 -0
  8. peak/handler.py +56 -16
  9. peak/press/apps.py +39 -1
  10. peak/press/blocks.py +39 -1
  11. peak/press/deployments.py +63 -1
  12. peak/resources/alerts.py +10 -2
  13. peak/resources/artifacts.py +39 -3
  14. peak/sample_yaml/press/apps/specs/create_app_spec.yaml +31 -0
  15. peak/sample_yaml/press/apps/specs/create_app_spec_release.yaml +31 -0
  16. peak/sample_yaml/press/blocks/specs/service/api/create_block_spec.yaml +31 -0
  17. peak/sample_yaml/press/blocks/specs/service/api/create_block_spec_release.yaml +31 -0
  18. peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec.yaml +31 -0
  19. peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec_release.yaml +31 -0
  20. peak/sample_yaml/press/blocks/specs/workflow/create_block_spec.yaml +31 -0
  21. peak/sample_yaml/press/blocks/specs/workflow/create_block_spec_release.yaml +31 -0
  22. peak/sample_yaml/press/deployments/patch_app_parameters_v2.yaml +15 -0
  23. peak/sample_yaml/press/deployments/patch_block_parameters_v2.yaml +10 -0
  24. peak/sample_yaml/resources/artifacts/create_artifact.yaml +3 -0
  25. peak/sample_yaml/resources/artifacts/create_artifact_version.yaml +2 -0
  26. peak/sample_yaml/resources/emails/send_email.yaml +3 -0
  27. peak/session.py +11 -7
  28. peak/telemetry.py +4 -1
  29. peak/tools/logging/logger.py +2 -2
  30. {peak_sdk-1.13.0.dist-info → peak_sdk-1.15.0.dist-info}/METADATA +6 -6
  31. {peak_sdk-1.13.0.dist-info → peak_sdk-1.15.0.dist-info}/RECORD +34 -32
  32. {peak_sdk-1.13.0.dist-info → peak_sdk-1.15.0.dist-info}/LICENSE +0 -0
  33. {peak_sdk-1.13.0.dist-info → peak_sdk-1.15.0.dist-info}/WHEEL +0 -0
  34. {peak_sdk-1.13.0.dist-info → peak_sdk-1.15.0.dist-info}/entry_points.txt +0 -0
peak/_metadata.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -959,6 +959,9 @@ command_metadata: Dict[str, Any] = {
959
959
  "deployments>patch-parameters": {
960
960
  "request_body_yaml_path": "sample_yaml/press/patch_parameters.yaml",
961
961
  },
962
+ "deployments>patch-parameters-v2": {
963
+ "request_body_yaml_path": "sample_yaml/press/deployments/patch_app_parameters_v2.yaml",
964
+ },
962
965
  "metrics>publish": {
963
966
  "request_body_yaml_path": "sample_yaml/metrics/publish.yaml",
964
967
  },
peak/_version.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -18,4 +18,4 @@
18
18
  # # You should have received a copy of the APACHE LICENSE, VERSION 2.0
19
19
  # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
20
  #
21
- __version__: str = "1.13.0"
21
+ __version__: str = "1.15.0"
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -19,6 +19,7 @@
19
19
  # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
20
  #
21
21
  """Peak apps specs commands."""
22
+
22
23
  from typing import Dict, List, Optional
23
24
 
24
25
  import typer
@@ -86,6 +87,12 @@ def create(
86
87
  title (string | required: false): Title of the parameter.
87
88
  options (list(str) | required: false): List of options for the parameter. If provided, it must have at least one object with "title" and "value" field.
88
89
  hideValue(boolean | required: false): Can be optionally provided to parameters of type "string", to mask the parameter's value when it has been set at deployment time.
90
+ conditions(list(map) | required: false): Conditions that determine when the parameter should be enabled. Conditions on two or more parameters should be used with conditionType "AND" or "OR".
91
+ - dependsOn (string): Name of the parameter that this parameter depends on.
92
+ operator (string): Operator to be used for the condition. Should be one of "equals" or "not-equals".
93
+ value (string): Value to be compared with the parameter.
94
+ - conditionType (string): Type of the condition. Should be one of "AND" or "OR".
95
+ conditions (list(map)): Nested conditions that determine when the parameter should be enabled.
89
96
  ```
90
97
 
91
98
  \b
@@ -352,6 +359,12 @@ def create_release(
352
359
  title (string | required: false): Title of the parameter.
353
360
  options (list(str) | required: false): List of options for the parameter. If provided, it must have at least one object with "title" and "value" field.
354
361
  hideValue(boolean | required: false): Can be optionally provided to parameters of type "string", to mask the parameter's value when it has been set at deployment time.
362
+ conditions(list(map) | required: false): Conditions that determine when the parameter should be enabled. Conditions on two or more parameters should be used with conditionType "AND" or "OR".
363
+ - dependsOn (string): Name of the parameter that this parameter depends on.
364
+ operator (string): Operator to be used for the condition. Should be one of "equals" or "not-equals".
365
+ value (string): Value to be compared with the parameter.
366
+ - conditionType (string): Type of the condition. Should be one of "AND" or "OR".
367
+ conditions (list(map)): Nested conditions that determine when the parameter should be enabled.
355
368
  ```
356
369
 
357
370
  \b
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -344,6 +344,12 @@ def create(
344
344
  title (string | required: false): Title of the parameter.
345
345
  options (list(str) | required: false): List of options for the parameter. If provided, it must have at least one object with "title" and "value" field.
346
346
  hideValue(boolean | required: false): Can be optionally provided to parameters of type "string", to mask the parameter's value when it has been set at deployment time.
347
+ conditions(list(map) | required: false): Conditions that determine when the parameter should be enabled. Conditions on two or more parameters should be used with conditionType "AND" or "OR".
348
+ - dependsOn (string): Name of the parameter that this parameter depends on.
349
+ operator (string): Operator to be used for the condition. Should be one of "equals" or "not-equals".
350
+ value (string): Value to be compared with the parameter.
351
+ - conditionType (string): Type of the condition. Should be one of "AND" or "OR".
352
+ conditions (list(map)): Nested conditions that determine when the parameter should be enabled.
347
353
  artifact (map | required: false):
348
354
  path (str): Path to the artifact.
349
355
  ignore_files (list(str) | required: false) : Ignore files to use when creating artifact.
@@ -762,6 +768,12 @@ def create_release(
762
768
  defaultValue (string | required: false): Default value of the parameter.
763
769
  title (string | required: false): Title of the parameter.
764
770
  options (list(str) | required: false): List of options for the parameter. If provided, it must have at least one object with "title" and "value" field.
771
+ conditions(list(map) | required: false): Conditions that determine when the parameter should be enabled. Conditions on two or more parameters should be used with conditionType "AND" or "OR".
772
+ - dependsOn (string): Name of the parameter that this parameter depends on.
773
+ operator (string): Operator to be used for the condition. Should be one of "equals" or "not-equals".
774
+ value (string): Value to be compared with the parameter.
775
+ - conditionType (string): Type of the condition. Should be one of "AND" or "OR".
776
+ conditions (list(map)): Nested conditions that determine when the parameter should be enabled.
765
777
  artifact (map | required: false):
766
778
  path (str): Path to the artifact.
767
779
  ignore_files (list(str) | required: false) : Ignore files to use when creating artifact.
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -127,7 +127,7 @@ def execute_resources(
127
127
  writer.write(response)
128
128
 
129
129
 
130
- @app.command(short_help="Update the parameters for a deployment at run time.")
130
+ @app.command(short_help="Update the runtime parameters for a deployment.")
131
131
  def patch_parameters(
132
132
  ctx: typer.Context,
133
133
  deployment_id: str = _DEPLOYMENT_ID,
@@ -169,3 +169,59 @@ def patch_parameters(
169
169
  with writer.pager():
170
170
  response = deployments_client.patch_parameters(deployment_id, **body)
171
171
  writer.write(response)
172
+
173
+
174
+ @app.command(short_help="Update the App runtime parameters and Block runtime parameters for a deployment.")
175
+ def patch_parameters_v2(
176
+ ctx: typer.Context,
177
+ deployment_id: str = _DEPLOYMENT_ID,
178
+ file: str = args.TEMPLATE_PATH,
179
+ params_file: Optional[str] = args.TEMPLATE_PARAMS_FILE,
180
+ params: Optional[List[str]] = args.TEMPLATE_PARAMS,
181
+ dry_run: Optional[bool] = DRY_RUN, # noqa: ARG001
182
+ paging: Optional[bool] = PAGING, # noqa: ARG001
183
+ output_type: Optional[OutputTypesNoTable] = OUTPUT_TYPES, # noqa: ARG001
184
+ generate: Optional[bool] = GENERATE_YAML, # noqa: ARG001
185
+ ) -> None:
186
+ """***Update*** the parameters for a deployment at runtime.
187
+
188
+ \b
189
+ 🧩 ***Input file schema to update run parameters of an app deployment (yaml):***<br/>
190
+ ```yaml
191
+ body (map):
192
+ appParameters (map | required: false):
193
+ Dictionary of runtime app parameters. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
194
+ parameters (map | required: false):
195
+ <blockName> (map): Dictionary of parameters specific to each block, where each key represents the block name.
196
+ Dictionary of runtime block parameters. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
197
+ ```
198
+
199
+ 🧩 ***Input file schema to update run parameters of a block deployment (yaml):***<br/>
200
+ ```yaml
201
+ body (map):
202
+ parameters (map | required: false):
203
+ Dictionary of runtime block parameters. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
204
+ ```
205
+
206
+ \b
207
+ 📝 ***Example usage:***
208
+ ```bash
209
+ peak deployments patch-parameters-v2 <deployment-id> /path/to/body.yaml -v /path/to/params.yaml
210
+ ```
211
+
212
+ \b
213
+ 🆗 ***Response:***
214
+ ```
215
+ { appParameters: {...}, parameters: {...} }
216
+ ```
217
+
218
+ 🔗 [**API Documentation**](https://press.peak.ai/api-docs/index.htm#/Deployment%20Parameters/patch_v2_deployments__deploymentId__parameters_run)
219
+ """
220
+ body = helpers.template_handler(file, params_file, params)
221
+ deployments_client: Deployment = ctx.obj["client"]
222
+ body = helpers.remove_unknown_args(body, deployments_client.patch_parameters_v2)
223
+ writer: Writer = ctx.obj["writer"]
224
+
225
+ with writer.pager():
226
+ response = deployments_client.patch_parameters_v2(deployment_id, **body)
227
+ writer.write(response)
@@ -55,6 +55,7 @@ _BCC = typer.Option(None, help="The email addresses of the recipients to be BCC'
55
55
  _LIST_TEMPLATE_NAME = typer.Option(None, help="Email Template Name to search for.")
56
56
  _LIST_TEMPLATE_SCOPE = typer.Option(None, help="List of type of template to filter the templates by.")
57
57
  _DESCRIBE_TEMPLATE_NAME = typer.Argument(None, help="The name of the email template.")
58
+ _ATTACHMENTS = typer.Option(None, help="The path of files to be sent as the mail attachments.")
58
59
 
59
60
 
60
61
  @app.command("list", short_help="List all emails.")
@@ -132,6 +133,7 @@ def send_email(
132
133
  subject: Optional[str] = _SUBJECT,
133
134
  template_name: Optional[str] = _TEMPLATE_NAME,
134
135
  template_parameters: Optional[str] = _TEMPLATE_PARAMETERS,
136
+ attachments: Optional[List[str]] = _ATTACHMENTS,
135
137
  paging: Optional[bool] = PAGING, # noqa: ARG001
136
138
  output_type: Optional[OutputTypesNoTable] = OUTPUT_TYPES, # noqa: ARG001
137
139
  ) -> None:
@@ -147,9 +149,10 @@ def send_email(
147
149
  subject (str | required: true): The subject of the email.
148
150
  templateName (str | required: true): The name of the email template.
149
151
  templateParameters (map | required: false): The parameters for the email template.
152
+ attachments (list(str) | required: false): The path of files to be sent as email attachments. A maximum of 3 files can be included, with each file not exceeding 10 MB. Supported file formats are: .pdf, .docx, .doc, .csv, .txt, .xlsx, .xls, and .zip.
150
153
  ```
151
154
 
152
- \b
155
+ \b
153
156
  📝 ***Example usage:***
154
157
  ```bash
155
158
  peak alerts emails send '/path/to/email.yaml' --params-file '/path/to/values.yaml'
@@ -160,7 +163,7 @@ def send_email(
160
163
  \b
161
164
  📝 ***Example usage without yaml:***
162
165
  ```bash
163
- peak alerts emails send --recipients <recipient_email_1> --recipients <recipient_email_2> --subject <email_subject> --template-name <template_name> --template-parameters '{"key": "value"}'
166
+ peak alerts emails send --recipients <recipient_email_1> --recipients <recipient_email_2> --subject <email_subject> --template-name <template_name> --template-parameters '{"key": "value"}' --attachments model.txt --attachments outputs
164
167
  ```
165
168
 
166
169
  \b
@@ -191,6 +194,7 @@ def send_email(
191
194
  body = helpers.remove_unknown_args(body, alert_client.send_email)
192
195
 
193
196
  updated_body = combine_dictionaries(body.get("body") or {}, user_options)
197
+ final_attachments = body.get("attachments", attachments)
194
198
 
195
199
  if recipients:
196
200
  updated_body["recipients"] = parse_list_of_strings(recipients)
@@ -209,7 +213,7 @@ def send_email(
209
213
  )
210
214
 
211
215
  with writer.pager():
212
- response: Dict[str, Any] = alert_client.send_email(body=updated_body)
216
+ response: Dict[str, Any] = alert_client.send_email(body=updated_body, attachments=final_attachments)
213
217
  writer.write(response)
214
218
 
215
219
 
@@ -250,7 +254,7 @@ def describe(
250
254
  }
251
255
  ],
252
256
  "subject": "Hello, world!",
253
- "templateName": "template_name",
257
+ "templateName": "template_name"
254
258
  }
255
259
  ```
256
260
 
@@ -19,6 +19,7 @@
19
19
  # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
20
  #
21
21
  """Peak Artifacts service commands."""
22
+
22
23
  from typing import Any, Dict, List, Optional
23
24
 
24
25
  import typer
@@ -179,6 +180,9 @@ def create(
179
180
  ```yaml
180
181
  name (str): Name of the artifact.
181
182
  description (str): Description of the artifact.
183
+ source (str | required: false): Source of the artifact.
184
+ scan (bool | required: false): Whether to scan the artifact for vulnerabilities.
185
+ validate (bool | required: false): Whether to validate the artifact. Source needs to be provided for the validation to work.
182
186
  artifact (map):
183
187
  path (str): Path to the artifact.
184
188
  ignore_files (list(str) | required: false): Ignore files to use when creating artifact.
@@ -305,6 +309,8 @@ def create_version(
305
309
  \b
306
310
  🧩 ***Input file schema(yaml):***<br/>
307
311
  ```yaml
312
+ scan (bool | required: false): Whether to scan the artifact for vulnerabilities.
313
+ validate (bool | required: false): Whether to validate the artifact. Source needs to be present in the artifact for the validation to work.
308
314
  artifact (map):
309
315
  path (str): Path to the artifact.
310
316
  ignore_files (list(str) | required: false): Ignore files to use when creating artifact.
peak/handler.py CHANGED
@@ -24,7 +24,11 @@ from __future__ import annotations
24
24
 
25
25
  import contextlib
26
26
  import json
27
+ import mimetypes
27
28
  from abc import ABC, ABCMeta, abstractmethod
29
+ from io import BufferedReader
30
+ from pathlib import Path
31
+ from tempfile import SpooledTemporaryFile
28
32
  from typing import Any, Callable, ClassVar, Dict, Iterator, List, Optional, Tuple, Type, TypeVar, Union
29
33
 
30
34
  import requests
@@ -118,9 +122,10 @@ class HandlerUtils(AuthRetrySession):
118
122
  @contextlib.contextmanager
119
123
  def make_artifact(
120
124
  self,
121
- path: Optional[str],
125
+ path: Optional[str | list[str]],
122
126
  body: Dict[str, Any],
123
127
  ignore_files: Optional[list[str]],
128
+ file_key: Optional[str] = "artifact",
124
129
  ) -> Iterator[MultipartEncoderMonitor]:
125
130
  """Create a multipart/form-data encoded file with given body and path as file.
126
131
 
@@ -128,23 +133,46 @@ class HandlerUtils(AuthRetrySession):
128
133
  path (Optional[str]): path to the file or folder that will be compressed and used as artifact
129
134
  ignore_files(Optional[list[str]]): Ignore files to be used when creating artifact
130
135
  body (Dict[str, Any]): body content to be sent with artifact
136
+ file_key (Optional[str]): the field in which the files must be uploaded
131
137
 
132
138
  Yields:
133
139
  MultipartEncoderMonitor: MultipartEncoderMonitor generator object
134
140
  """
135
141
  if path:
136
- with compress(path, ignore_files) as fh:
137
- check_file_size(fh)
138
- encoder = MultipartEncoder(
139
- {
140
- **body,
141
- "artifact": (
142
+ with contextlib.ExitStack() as stack:
143
+ files: list[tuple[str, SpooledTemporaryFile[bytes] | BufferedReader, str | None]] = []
144
+ if isinstance(path, list):
145
+ for p in path:
146
+ file_path = Path(p)
147
+ if file_path.is_dir():
148
+ context = compress(p)
149
+ compressed_file = stack.enter_context(context)
150
+ file_name = f"{file_path.name}.zip"
151
+ files.append((file_name, compressed_file, "application/zip"))
152
+ else:
153
+ fh = open(p, "rb") # noqa: SIM115, PTH123
154
+ stack.push(fh)
155
+ file_name = file_path.name
156
+ files.append((file_name, fh, mimetypes.guess_type(file_name)[0]))
157
+ else:
158
+ context = compress(path, ignore_files)
159
+ file = stack.enter_context(context)
160
+ check_file_size(file)
161
+ files.append(
162
+ (
142
163
  "artifact.zip",
143
- fh,
164
+ file,
144
165
  "application/zip",
145
166
  ),
146
- },
167
+ )
168
+
169
+ files_object = [(file_key, file) for file in files]
170
+ body_array = list(body.items())
171
+
172
+ encoder = MultipartEncoder(
173
+ files_object + body_array,
147
174
  )
175
+
148
176
  callback = self._default_callback(encoder)
149
177
  monitor = MultipartEncoderMonitor(encoder, callback)
150
178
  yield monitor
@@ -226,9 +254,10 @@ class BaseHandler(ABC, HandlerUtils, metaclass=_CombinedMeta):
226
254
  headers: Dict[str, str],
227
255
  params: Optional[Dict[str, Any]],
228
256
  body: Optional[Dict[str, Any]],
229
- path: Optional[str],
257
+ path: Optional[str | list[str]],
230
258
  ignore_files: Optional[list[str]],
231
259
  request_kwargs: OptionalSerializable,
260
+ file_key: Optional[str],
232
261
  ) -> requests.Response:
233
262
  """Placeholder handle method."""
234
263
  ...
@@ -244,11 +273,12 @@ class MultipartFormDataHandler(BaseHandler):
244
273
  url: str,
245
274
  method: HttpMethods,
246
275
  *,
247
- path: Optional[str],
276
+ path: Optional[str | list[str]],
248
277
  headers: Dict[str, str],
249
278
  body: Optional[Dict[str, Any]],
250
279
  params: Optional[Dict[str, Any]] = None, # noqa: ARG002
251
280
  ignore_files: Optional[list[str]] = None,
281
+ file_key: Optional[str] = "artifact",
252
282
  request_kwargs: OptionalSerializable = None,
253
283
  ) -> requests.Response:
254
284
  """Handle multipart/form-data requests.
@@ -262,13 +292,14 @@ class MultipartFormDataHandler(BaseHandler):
262
292
  path (Optional[str]): path to the file or folder that will be compressed and used as artifact
263
293
  request_kwargs (OptionalSerializable): extra arguments to be passed when making the request, defaults to None
264
294
  ignore_files(Optional[list[str]]): Ignore files to be used when creating artifact
295
+ file_key (Optional[str]): the field in which the files must be uploaded
265
296
 
266
297
  Returns:
267
298
  requests.Response: response of the request
268
299
  """
269
300
  self._add_retries()
270
301
 
271
- with self.make_artifact(path, self.parse_args(body or {}), ignore_files) as monitor:
302
+ with self.make_artifact(path, self.parse_args(body or {}), ignore_files, file_key) as monitor:
272
303
  headers = {**headers, "Content-Type": monitor.content_type}
273
304
  response: Any = getattr(self, method.value)(url, data=monitor, headers=headers, **request_kwargs)
274
305
  return self.handle_response(response)
@@ -287,8 +318,9 @@ class ApplicationJsonHandler(BaseHandler):
287
318
  headers: Dict[str, str],
288
319
  params: Optional[Dict[str, Any]],
289
320
  body: Optional[Dict[str, Any]],
290
- path: Optional[str] = None, # noqa: ARG002
321
+ path: Optional[str | list[str]] = None, # noqa: ARG002
291
322
  ignore_files: Optional[list[str]] = None, # noqa: ARG002
323
+ file_key: Optional[str] = "artifact", # noqa: ARG002
292
324
  request_kwargs: OptionalSerializable = None,
293
325
  ) -> requests.Response:
294
326
  """Handle application/json requests.
@@ -302,6 +334,7 @@ class ApplicationJsonHandler(BaseHandler):
302
334
  path (Optional[str]): path to the file or folder that will be compressed and used as artifact, not used in application/json handler
303
335
  request_kwargs (OptionalSerializable): extra arguments to be passed when making the request, defaults to None
304
336
  ignore_files(Optional[list[str]]): Ignore files to be used when creating artifact
337
+ file_key (Optional[str]): the field in which the files must be uploaded
305
338
 
306
339
  Returns:
307
340
  requests.Response: response of the request.
@@ -328,14 +361,18 @@ class Handler:
328
361
  def _pretty_print_request(
329
362
  *_: Any,
330
363
  content_type: str,
331
- path: Optional[str] = None,
364
+ path: Optional[str | list[str]] = None,
332
365
  ignore_files: Optional[list[str]] = None,
333
366
  **kwargs: Any,
334
367
  ) -> None:
335
368
  writer.write(f"\nSample request: {json.dumps(kwargs, indent=2)}\n")
336
369
  if content_type == ContentType.MULTIPART_FORM_DATA.value and path is not None:
337
370
  writer.write("\nArtifact file tree:")
338
- print_file_tree(get_files_to_include(path, ignore_files))
371
+ if isinstance(path, list):
372
+ for p in path:
373
+ print_file_tree(get_files_to_include(p, ignore_files))
374
+ else:
375
+ print_file_tree(get_files_to_include(path, ignore_files))
339
376
 
340
377
  @telemetry
341
378
  def make_request(
@@ -346,9 +383,10 @@ class Handler:
346
383
  headers: Optional[Dict[str, str]] = None,
347
384
  params: Optional[Dict[str, Any]] = None,
348
385
  body: Optional[Dict[str, Any]] = None,
349
- path: Optional[str] = None,
386
+ path: Optional[str | list[str]] = None,
350
387
  request_kwargs: Optional[Dict[str, int | bool | str | float]] = None,
351
388
  ignore_files: Optional[list[str]] = None,
389
+ file_key: Optional[str] = "artifact",
352
390
  ) -> requests.Response:
353
391
  """Redirects the request to the appropriate strategy based on the content type.
354
392
 
@@ -362,6 +400,7 @@ class Handler:
362
400
  path (Optional[str]): path to the file or folder that will be compressed and used as artifact, defaults to None
363
401
  request_kwargs(Dict[str, int | bool | str | float] | None): extra arguments to be passed when making the request.
364
402
  ignore_files(Optional[list[str]]): Ignore files to be used when creating artifact
403
+ file_key (Optional[str]): the field in which the files must be uploaded
365
404
 
366
405
  Returns:
367
406
  requests.Response: response json
@@ -395,6 +434,7 @@ class Handler:
395
434
  path=path,
396
435
  request_kwargs=request_kwargs,
397
436
  ignore_files=ignore_files,
437
+ file_key=file_key,
398
438
  )
399
439
 
400
440
 
peak/press/apps.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -236,6 +236,25 @@ class App(BaseClient):
236
236
  "title": "string",
237
237
  "options": "list(str)",
238
238
  "hideValue": "boolean",
239
+ "conditions": [
240
+ // Basic condition
241
+ {
242
+ "dependsOn": "string",
243
+ "operator": "string",
244
+ "value": "string|number|boolean"
245
+ },
246
+ // Composite condition
247
+ {
248
+ "conditionType": "AND|OR",
249
+ "conditions": [
250
+ {
251
+ "dependsOn": "string",
252
+ "operator": "string",
253
+ "value": "string|number|boolean"
254
+ }
255
+ ]
256
+ }
257
+ ]
239
258
  }
240
259
  ]
241
260
  }
@@ -426,6 +445,25 @@ class App(BaseClient):
426
445
  "required": "boolean(required)",
427
446
  "title": "string",
428
447
  "type": "string(required)",
448
+ "conditions": [
449
+ // Basic condition
450
+ {
451
+ "dependsOn": "string",
452
+ "operator": "string",
453
+ "value": "string|number|boolean"
454
+ },
455
+ // Composite condition
456
+ {
457
+ "conditionType": "AND|OR",
458
+ "conditions": [
459
+ {
460
+ "dependsOn": "string",
461
+ "operator": "string",
462
+ "value": "string|number|boolean"
463
+ }
464
+ ]
465
+ }
466
+ ]
429
467
  }
430
468
  ]
431
469
  }
peak/press/blocks.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -574,6 +574,25 @@ class Block(BaseClient):
574
574
  "required": "boolean(required)",
575
575
  "title": "string",
576
576
  "type": "string(required)",
577
+ "conditions": [
578
+ // Basic condition
579
+ {
580
+ "dependsOn": "string",
581
+ "operator": "equals|not-equals",
582
+ "value": "string|number|boolean"
583
+ },
584
+ // Composite condition
585
+ {
586
+ "conditionType": "AND|OR",
587
+ "conditions": [
588
+ {
589
+ "dependsOn": "string",
590
+ "operator": "equals|not-equals",
591
+ "value": "string|number|boolean"
592
+ }
593
+ ]
594
+ }
595
+ ]
577
596
  }
578
597
  ]
579
598
  }
@@ -1123,6 +1142,25 @@ class Block(BaseClient):
1123
1142
  "required": "boolean(required)",
1124
1143
  "title": "string",
1125
1144
  "type": "string(required)",
1145
+ "conditions": [
1146
+ // Basic condition
1147
+ {
1148
+ "dependsOn": "string",
1149
+ "operator": "equals|not-equals",
1150
+ "value": "string|number|boolean"
1151
+ },
1152
+ // Composite condition
1153
+ {
1154
+ "conditionType": "AND|OR",
1155
+ "conditions": [
1156
+ {
1157
+ "dependsOn": "string",
1158
+ "operator": "equals|not-equals",
1159
+ "value": "string|number|boolean"
1160
+ }
1161
+ ]
1162
+ }
1163
+ ]
1126
1164
  }
1127
1165
  ]
1128
1166
  }
peak/press/deployments.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
2
+ # # Copyright © 2025 Peak AI Limited. or its affiliates. All Rights Reserved.
3
3
  # #
4
4
  # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
5
  # # may not use this file except in compliance with the License. A copy of
@@ -188,6 +188,68 @@ class Deployment(BaseClient):
188
188
  subdomain="press",
189
189
  )
190
190
 
191
+ def patch_parameters_v2(
192
+ self,
193
+ deployment_id: str,
194
+ body: Dict[str, Any],
195
+ ) -> Dict[str, Any]:
196
+ """Get the runtime parameters for a deployment.
197
+
198
+ REFERENCE:
199
+ 🔗 `API Documentation <https://press.peak.ai/api-docs/index.htm#/Deployment%20Parameters/patch_v2_deployments__deploymentId__parameters_run>`__
200
+
201
+ Args:
202
+ deployment_id (str): The ID of the deployment.
203
+ body (Dict[str, Any]): body (Dict[str, str]): Dictionary of app and block parameters.
204
+
205
+ Returns:
206
+ Dict[str, Any]: Dictionary containing app and block parameters.
207
+
208
+ SCHEMA(Block Deployment Run Parameters):
209
+ The valid types for parameters are `boolean`, `string`, `string_array`, `number`, `number_array`, `object` and `object_array`.
210
+
211
+ .. code-block:: json
212
+
213
+ {
214
+ "parameters": {
215
+ "param_name": "param_value (string | number | boolean | dict | array)"
216
+ }
217
+ }
218
+
219
+ SCHEMA(App Deployment Run Parameters):
220
+ The valid types for parameters are `boolean`, `string`, `string_array`, `number`, `number_array`, `object` and `object_array`.
221
+
222
+ .. code-block:: json
223
+
224
+ {
225
+ "appParameters": {
226
+ "param_name": "param_value (string | number | boolean | dict | array)"
227
+ },
228
+ "parameters": {
229
+ "block_name": {
230
+ "param_name": "param_value (string | number | boolean | dict | array)"
231
+ }
232
+ }
233
+ }
234
+
235
+ Raises:
236
+ BadRequestException: The given parameters are invalid.
237
+ UnauthorizedException: The credentials are invalid.
238
+ ForbiddenException: The user does not have permission to perform the operation.
239
+ NotFoundException: The given deployment does not exist.
240
+ InternalServerErrorException: The server encountered an unexpected condition that
241
+ prevented it from fulfilling the request.
242
+ """
243
+ method, endpoint = HttpMethods.PATCH, f"v2/deployments/{deployment_id}/parameters/run"
244
+
245
+ return self.session.create_request( # type: ignore[no-any-return]
246
+ endpoint,
247
+ method,
248
+ body=body,
249
+ content_type=ContentType.APPLICATION_JSON,
250
+ subdomain="press",
251
+ )
252
+
191
253
 
192
254
  def get_client(session: Optional[Session] = None) -> Deployment:
193
255
  """Returns a Deployment client.