peak-sdk 1.12.0__py3-none-any.whl → 1.14.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 (35) hide show
  1. peak/_metadata.py +3 -0
  2. peak/_version.py +1 -1
  3. peak/cli/press/apps/deployments.py +12 -6
  4. peak/cli/press/apps/specs.py +20 -0
  5. peak/cli/press/blocks/deployments.py +5 -6
  6. peak/cli/press/deployments.py +49 -3
  7. peak/cli/resources/alerts/emails.py +8 -4
  8. peak/cli/resources/artifacts.py +6 -0
  9. peak/handler.py +56 -16
  10. peak/metrics/metrics.py +1 -1
  11. peak/press/apps.py +100 -5
  12. peak/press/deployments.py +35 -0
  13. peak/resources/alerts.py +10 -2
  14. peak/resources/artifacts.py +39 -3
  15. peak/sample_yaml/press/apps/deployments/create_app_deployment.yaml +12 -0
  16. peak/sample_yaml/press/apps/deployments/create_app_deployment_revision.yaml +12 -0
  17. peak/sample_yaml/press/apps/specs/create_app_spec.yaml +63 -0
  18. peak/sample_yaml/press/apps/specs/create_app_spec_release.yaml +63 -0
  19. peak/sample_yaml/press/blocks/specs/service/api/create_block_spec.yaml +28 -28
  20. peak/sample_yaml/press/blocks/specs/service/api/create_block_spec_release.yaml +28 -28
  21. peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec.yaml +28 -28
  22. peak/sample_yaml/press/blocks/specs/service/webapp/create_block_spec_release.yaml +28 -28
  23. peak/sample_yaml/press/blocks/specs/workflow/create_block_spec.yaml +32 -32
  24. peak/sample_yaml/press/blocks/specs/workflow/create_block_spec_release.yaml +32 -32
  25. peak/sample_yaml/press/patch_parameters.yaml +9 -0
  26. peak/sample_yaml/resources/artifacts/create_artifact.yaml +3 -0
  27. peak/sample_yaml/resources/artifacts/create_artifact_version.yaml +2 -0
  28. peak/sample_yaml/resources/emails/send_email.yaml +3 -0
  29. peak/session.py +4 -1
  30. peak/telemetry.py +4 -1
  31. {peak_sdk-1.12.0.dist-info → peak_sdk-1.14.0.dist-info}/METADATA +3 -3
  32. {peak_sdk-1.12.0.dist-info → peak_sdk-1.14.0.dist-info}/RECORD +35 -34
  33. {peak_sdk-1.12.0.dist-info → peak_sdk-1.14.0.dist-info}/LICENSE +0 -0
  34. {peak_sdk-1.12.0.dist-info → peak_sdk-1.14.0.dist-info}/WHEEL +0 -0
  35. {peak_sdk-1.12.0.dist-info → peak_sdk-1.14.0.dist-info}/entry_points.txt +0 -0
peak/_metadata.py CHANGED
@@ -956,6 +956,9 @@ command_metadata: Dict[str, Any] = {
956
956
  "blocks>deployments>patch-parameters": {
957
957
  "request_body_yaml_path": "sample_yaml/press/blocks/deployments/patch_block_parameters.yaml",
958
958
  },
959
+ "deployments>patch-parameters": {
960
+ "request_body_yaml_path": "sample_yaml/press/patch_parameters.yaml",
961
+ },
959
962
  "metrics>publish": {
960
963
  "request_body_yaml_path": "sample_yaml/metrics/publish.yaml",
961
964
  },
peak/_version.py CHANGED
@@ -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.12.0"
21
+ __version__: str = "1.14.0"
@@ -66,10 +66,13 @@ def create(
66
66
  imageUrl (string | required: false): URL of the image to be associated with the app deployment.
67
67
  tags (list(map) | required: false):
68
68
  - name (string): Name of the tag.
69
+ appParameters (map | required: false):
70
+ build (map | required: false): Dictionary of parameters specific to the 'build' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
71
+ run (map | required: false): Dictionary of parameters specific to the 'run' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
69
72
  parameters (map | required: false):
70
- <blockName> (map): Dictionary of parameters for the block. Here the key is the name of the block.
71
- <parameterType> (map): Dictionary of parameters. Here the key is the type of the parameter. Accepted values are "build" or "run".
72
- <parameterName> (string | boolean | number | list(string)): Value of the parameter. Here the key is the name of the parameter.
73
+ <blockName> (map): Dictionary of parameters specific to each block, where each key represents the block name.
74
+ build (map | required: false): Dictionary of parameters for the block's 'build' phase. Keys are parameter names, and values can be of type string, boolean, number, dictionary or list (string, number, dictionary).
75
+ run (map | required: false): Dictionary of parameters for the block's 'run' phase. Keys are parameter names, and values can be of type string, boolean, number, dictionary or list (string, number, dictionary).
73
76
  revision (map | required: false):
74
77
  notes (string | required: false): Notes for the deployment revision.
75
78
  spec (map):
@@ -348,10 +351,13 @@ def create_revision(
348
351
  🧩 ***Input file schema (yaml):***<br/>
349
352
  ```yaml
350
353
  body (map):
354
+ appParameters (map | required: false):
355
+ build (map | required: false): Dictionary of parameters specific to the 'build' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
356
+ run (map | required: false): Dictionary of parameters specific to the 'run' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
351
357
  parameters (map | required: false):
352
- <blockName> (map): Dictionary of blocks within the app, for which to provide parameters. Must be a valid block name.
353
- <parameterType> (map): Dictionary of parameters. Here the key is the type of the parameter. Accepted values are "build" or "run".
354
- <parameterName> (string | boolean | number | list(string)): Value of the parameter. Here the key is the name of the parameter.
358
+ <blockName> (map): Dictionary of parameters specific to each block, where each key represents the block name.
359
+ build (map | required: false): Dictionary of parameters for the block's 'build' phase. Keys are parameter names, and values can be of type string, boolean, number, dictionary or list (string, number, dictionary).
360
+ run (map | required: false): Dictionary of parameters for the block's 'run' phase. Keys are parameter names, and values can be of type string, boolean, number, dictionary or list (string, number, dictionary).
355
361
  release (map):
356
362
  version (string): A valid semantic release version of the app spec.
357
363
  revision (map | required: false):
@@ -76,6 +76,16 @@ def create(
76
76
  release (map):
77
77
  version (string): A valid semantic release version of the block spec.
78
78
  autoRunOnDeploy (bool | required: false): Whether to execute the resource after the app is deployed. By default it is False.
79
+ parameters (map | required: false):
80
+ <parameterType> (list(map)): List containing the parameter objects. Here the key is the type of the parameter. Accepted values are "build" or "run".
81
+ name (string): Name of the parameter.
82
+ type (string): Type of the parameter. Should be one of "boolean", "string", "string_array", "number", "number_array", "object" and "object_array".
83
+ required (boolean): Whether the parameter is required.
84
+ description (string | required: false): Description of the parameter.
85
+ defaultValue (string | required: false): Default value of the parameter.
86
+ title (string | required: false): Title of the parameter.
87
+ 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
+ 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.
79
89
  ```
80
90
 
81
91
  \b
@@ -332,6 +342,16 @@ def create_release(
332
342
  release (map):
333
343
  version (string): A valid semantic release version of the block spec.
334
344
  autoRunOnDeploy (bool | required: false): Whether to execute the resource after the app is deployed. By default it is False.
345
+ parameters (map | required: false):
346
+ <parameterType> (list(map)): List containing the parameter objects. Here the key is the type of the parameter. Accepted values are "build" or "run".
347
+ name (string): Name of the parameter.
348
+ type (string): Type of the parameter. Should be one of "boolean", "string", "string_array", "number", "number_array", "object" and "object_array".
349
+ required (boolean): Whether the parameter is required.
350
+ description (string | required: false): Description of the parameter.
351
+ defaultValue (string | required: false): Default value of the parameter.
352
+ title (string | required: false): Title of the parameter.
353
+ 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
+ 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.
335
355
  ```
336
356
 
337
357
  \b
@@ -75,8 +75,8 @@ def create(
75
75
  tags (list(map) | required: false):
76
76
  - name (string): Name of the tag.
77
77
  parameters (map | required: false):
78
- <parameterType> (map): Dictionary of parameters. Here the key is the type of the parameter. Accepted values are "build" or "run".
79
- <parameterName> (string | boolean | number | list(string)): Value of the parameter. Here the key is the name of the parameter.
78
+ build (map | required: false): Dictionary of parameters specific to the 'build' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
79
+ run (map | required: false): Dictionary of parameters specific to the 'run' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
80
80
  revision (map | required: false):
81
81
  notes (string | required: false): Notes for the deployment revision.
82
82
  spec (map):
@@ -362,8 +362,8 @@ def create_revision(
362
362
  ```yaml
363
363
  body (map):
364
364
  parameters (map | required: false):
365
- <parameterType> (map): Dictionary of parameters. Here the key is the type of the parameter. Accepted values are "build" or "run".
366
- <parameterName> (string | boolean | number | list(string)): Value of the parameter. Here the key is the name of the parameter.
365
+ build (map | required: false): Dictionary of parameters specific to the 'build' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
366
+ run (map | required: false): Dictionary of parameters specific to the 'run' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
367
367
  release (map):
368
368
  version (string): A valid semantic release version of the block spec.
369
369
  revision (map | required: false):
@@ -550,8 +550,7 @@ def patch_parameters(
550
550
  \b
551
551
  🧩 ***Input file schema (yaml):***<br/>
552
552
  ```yaml
553
- body (map):
554
- <key> (string | boolean | number | list(string)): Value of the parameter. Here the key is the name of the parameter.
553
+ body (map): Dictionary of parameters specific to the 'run' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
555
554
  ```
556
555
 
557
556
  \b
@@ -23,9 +23,9 @@
23
23
  from typing import List, Optional
24
24
 
25
25
  import typer
26
- from peak.cli import args
27
- from peak.cli.args import OUTPUT_TYPES, PAGING
28
- from peak.constants import OutputTypes
26
+ from peak.cli import args, helpers
27
+ from peak.cli.args import DRY_RUN, GENERATE_YAML, OUTPUT_TYPES, PAGING
28
+ from peak.constants import OutputTypes, OutputTypesNoTable
29
29
  from peak.output import Writer
30
30
  from peak.press.deployments import Deployment
31
31
  from rich.console import Console
@@ -36,6 +36,8 @@ app = typer.Typer(
36
36
  )
37
37
  console = Console()
38
38
 
39
+ _DEPLOYMENT_ID = typer.Argument(..., help="ID of the Block deployment to be used in this operation")
40
+
39
41
 
40
42
  @app.command("list", short_help="List App and Block deployments.")
41
43
  def list_deployments(
@@ -123,3 +125,47 @@ def execute_resources(
123
125
  with writer.pager():
124
126
  response = deployment_client.execute_resources(deployment_id)
125
127
  writer.write(response)
128
+
129
+
130
+ @app.command(short_help="Update the parameters for a deployment at run time.")
131
+ def patch_parameters(
132
+ ctx: typer.Context,
133
+ deployment_id: str = _DEPLOYMENT_ID,
134
+ file: str = args.TEMPLATE_PATH,
135
+ params_file: Optional[str] = args.TEMPLATE_PARAMS_FILE,
136
+ params: Optional[List[str]] = args.TEMPLATE_PARAMS,
137
+ dry_run: Optional[bool] = DRY_RUN, # noqa: ARG001
138
+ paging: Optional[bool] = PAGING, # noqa: ARG001
139
+ output_type: Optional[OutputTypesNoTable] = OUTPUT_TYPES, # noqa: ARG001
140
+ generate: Optional[bool] = GENERATE_YAML, # noqa: ARG001
141
+ ) -> None:
142
+ """***Update*** the parameters for a deployment at run time.
143
+
144
+ \b
145
+ 🧩 ***Input file schema (yaml):***<br/>
146
+ ```yaml
147
+ body (map): Dictionary of parameters specific to the 'run' phase. Keys are parameter names, and values are the parameter values, which can be of type string, boolean, number, dictionary or list (string, number, dictionary).
148
+ ```
149
+
150
+ \b
151
+ 📝 ***Example usage:***
152
+ ```bash
153
+ peak deployments patch-parameters <deployment-id> /path/to/body.yaml -v /path/to/params.yaml
154
+ ```
155
+
156
+ \b
157
+ 🆗 ***Response:***
158
+ ```
159
+ {...}
160
+ ```
161
+
162
+ 🔗 [**API Documentation**](https://press.peak.ai/api-docs/index.htm#/Deployment%20Parameters/patch_v1_deployments__deploymentId__parameters_run)
163
+ """
164
+ body = helpers.template_handler(file, params_file, params)
165
+ deployments_client: Deployment = ctx.obj["client"]
166
+ body = helpers.remove_unknown_args(body, deployments_client.patch_parameters)
167
+ writer: Writer = ctx.obj["writer"]
168
+
169
+ with writer.pager():
170
+ response = deployments_client.patch_parameters(deployment_id, **body)
171
+ 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/metrics/metrics.py CHANGED
@@ -550,4 +550,4 @@ def get_client(session: Optional[Session] = None) -> Metric:
550
550
  return Metric(session)
551
551
 
552
552
 
553
- __all__ = ["get_client"]
553
+ __all__: List[str] = ["get_client"]