peak-sdk 1.13.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.
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.13.0"
21
+ __version__: str = "1.14.0"
@@ -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/resources/alerts.py CHANGED
@@ -23,6 +23,7 @@
23
23
 
24
24
  from __future__ import annotations
25
25
 
26
+ import json
26
27
  from typing import Any, Dict, Iterator, List, Literal, Optional, overload
27
28
 
28
29
  from peak.base_client import BaseClient
@@ -126,6 +127,7 @@ class Alert(BaseClient):
126
127
  def send_email(
127
128
  self,
128
129
  body: Dict[str, Any],
130
+ attachments: Optional[list[str]] = None,
129
131
  ) -> Dict[str, Any]:
130
132
  """Send an email to the specified recipients using the specified template.
131
133
 
@@ -134,6 +136,8 @@ class Alert(BaseClient):
134
136
 
135
137
  Args:
136
138
  body (Dict[str, Any]): A dictionary containing the details of the email to send.
139
+ attachments (Optional[list[str]]): A list of file paths to attach to the email.
140
+ When a directory is provided, a zip is automatically created for the same.
137
141
 
138
142
  Returns:
139
143
  Dict[str, Any]: A dictionary containing the ID of the email sent.
@@ -161,11 +165,15 @@ class Alert(BaseClient):
161
165
  """
162
166
  method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT}/emails"
163
167
 
168
+ parsed_body = {k: json.dumps(v) if not isinstance(v, str) else v for (k, v) in body.items()}
169
+
164
170
  return self.session.create_request( # type: ignore[no-any-return]
165
171
  endpoint,
166
172
  method,
167
- body=body,
168
- content_type=ContentType.APPLICATION_JSON,
173
+ body=parsed_body,
174
+ content_type=ContentType.MULTIPART_FORM_DATA,
175
+ path=attachments,
176
+ file_key="attachments",
169
177
  )
170
178
 
171
179
  def describe_email(self, email_id: int) -> Dict[str, Any]:
@@ -19,12 +19,14 @@
19
19
  # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
20
  #
21
21
  """Artifact client module."""
22
+
22
23
  from __future__ import annotations
23
24
 
24
25
  from typing import Any, Dict, Iterator, List, Literal, Optional, overload
25
26
 
26
27
  from peak.base_client import BaseClient
27
28
  from peak.constants import ArtifactInfo, ContentType, HttpMethods
29
+ from peak.helpers import parse_body_for_multipart_request
28
30
  from peak.session import Session
29
31
 
30
32
 
@@ -104,6 +106,9 @@ class Artifact(BaseClient):
104
106
  name: str,
105
107
  artifact: ArtifactInfo,
106
108
  description: Optional[str] = None,
109
+ source: Optional[str] = None,
110
+ scan: Optional[bool] = None,
111
+ validate: Optional[bool] = None,
107
112
  ) -> Dict[str, Any]:
108
113
  """Create a new artifact.
109
114
 
@@ -115,6 +120,9 @@ class Artifact(BaseClient):
115
120
  artifact (ArtifactInfo): Mapping of artifact attributes that specifies how the artifact will be generated,
116
121
  it accepts two keys `path`, which is required and `ignore_files` which is optional, and defaults to `.dockerignore`, it is strongly advised that users use `ignore_files` when generating artifacts to avoid copying any extra files in artifact.
117
122
  description (str | None): A brief description of the artifact.
123
+ source (str | None): The source of the artifact.
124
+ scan (bool | None): Whether to scan the artifact for vulnerabilities.
125
+ validate (bool | None): Whether to validate the artifact. Source needs to be provided for the validation to work.
118
126
 
119
127
  Returns:
120
128
  Dict[str, Any]: `Id` and `Version` of the created artifact.
@@ -127,13 +135,27 @@ class Artifact(BaseClient):
127
135
  InternalServerErrorException: The server failed to process the request.
128
136
  """
129
137
  method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT}/artifacts/"
130
- body: Dict[str, Any] = {"name": name, "description": description}
138
+ body: Dict[str, Any] = {
139
+ "name": name,
140
+ "description": description,
141
+ }
142
+
143
+ if source is not None:
144
+ body["source"] = source
145
+
146
+ if scan is not None:
147
+ body["scan"] = scan
148
+
149
+ if validate is not None:
150
+ body["validate"] = validate
151
+
152
+ updated_body = parse_body_for_multipart_request(body)
131
153
 
132
154
  return self.session.create_request( # type: ignore[no-any-return]
133
155
  endpoint,
134
156
  method,
135
157
  content_type=ContentType.MULTIPART_FORM_DATA,
136
- body=body,
158
+ body=updated_body,
137
159
  path=artifact["path"],
138
160
  ignore_files=artifact.get("ignore_files"),
139
161
  )
@@ -205,6 +227,8 @@ class Artifact(BaseClient):
205
227
  self,
206
228
  artifact_id: str,
207
229
  artifact: ArtifactInfo,
230
+ scan: Optional[bool] = None,
231
+ validate: Optional[bool] = None,
208
232
  ) -> Dict[str, int]:
209
233
  """Create a new version of the artifact.
210
234
 
@@ -215,6 +239,8 @@ class Artifact(BaseClient):
215
239
  artifact_id (str): ID of the artifact for which a new version is to be created.
216
240
  artifact (ArtifactInfo): Mapping of artifact attributes that specifies how the artifact will be generated,
217
241
  it accepts two keys `path`, which is required and `ignore_files` which is optional, and defaults to `.dockerignore`, it is strongly advised that users use `ignore_files` when generating artifacts to avoid copying any extra files in artifact.
242
+ scan (bool | None): Whether to scan the artifact for vulnerabilities.
243
+ validate (bool | None): Whether to validate the artifact. Source needs to be present in the artifact for the validation to work.
218
244
 
219
245
  Returns:
220
246
  Dict[str, int]: version number.
@@ -229,11 +255,21 @@ class Artifact(BaseClient):
229
255
  """
230
256
  method, endpoint = HttpMethods.PUT, f"{self.BASE_ENDPOINT}/artifacts/{artifact_id}"
231
257
 
258
+ body = {}
259
+
260
+ if scan is not None:
261
+ body["scan"] = scan
262
+
263
+ if validate is not None:
264
+ body["validate"] = validate
265
+
266
+ updated_body = parse_body_for_multipart_request(body)
267
+
232
268
  return self.session.create_request( # type: ignore[no-any-return]
233
269
  endpoint,
234
270
  method,
235
271
  content_type=ContentType.MULTIPART_FORM_DATA,
236
- body={},
272
+ body=updated_body,
237
273
  path=artifact["path"],
238
274
  ignore_files=artifact.get("ignore_files"),
239
275
  )
@@ -2,6 +2,9 @@
2
2
 
3
3
  name: new-artifact
4
4
  description: Creating a new artifact
5
+ source: "email"
6
+ scan: True
7
+ validate: True
5
8
  artifact:
6
9
  path: "."
7
10
  ignore_files:
@@ -1,5 +1,7 @@
1
1
  # artifact_version.yaml
2
2
 
3
+ scan: True
4
+ validate: False
3
5
  artifact:
4
6
  path: "."
5
7
  ignore_files:
@@ -13,3 +13,6 @@ body:
13
13
  templateParameters:
14
14
  name: John
15
15
  company: Peak
16
+ attachments:
17
+ - model.txt
18
+ - outputs
peak/session.py CHANGED
@@ -87,9 +87,10 @@ class Session:
87
87
  *,
88
88
  params: Optional[Dict[str, Any]] = None,
89
89
  body: Optional[Dict[str, Any]] = None,
90
- path: Optional[str] = None,
90
+ path: Optional[str | list[str]] = None,
91
91
  ignore_files: Optional[list[str]] = None,
92
92
  subdomain: Optional[str] = "service",
93
+ file_key: Optional[str] = "artifact",
93
94
  ) -> Any:
94
95
  """Prepares a request to be sent over the network.
95
96
 
@@ -105,6 +106,7 @@ class Session:
105
106
  path (Optional[str] optional): path to the file or folder that will be compressed and used as artifact, required for multipart requests.
106
107
  ignore_files(Optional[list[str]]): Ignore files to be used when creating artifact, used only for multipart requests.
107
108
  subdomain (Optional[str]): Subdomain for the endpoint. Defaults to `service`.
109
+ file_key (Optional[str]): the field in which the files must be uploaded
108
110
 
109
111
  Returns:
110
112
  Any: response dict object.
@@ -124,6 +126,7 @@ class Session:
124
126
  session_meta={
125
127
  "stage": self.stage,
126
128
  },
129
+ file_key=file_key,
127
130
  ).json()
128
131
 
129
132
  def create_generator_request(
peak/telemetry.py CHANGED
@@ -103,10 +103,11 @@ def telemetry(make_request: F) -> F:
103
103
  headers: Optional[Dict[str, str]] = None,
104
104
  params: Optional[Dict[str, Any]] = None,
105
105
  body: Optional[Dict[str, Any]] = None,
106
- path: Optional[str] = None,
106
+ path: Optional[str | list[str]] = None,
107
107
  request_kwargs: Optional[Dict[str, int | bool | str | float]] = None,
108
108
  ignore_files: Optional[list[str]] = None,
109
109
  session_meta: Optional[Dict[str, Any]] = None,
110
+ file_key: Optional[str] = "artifact",
110
111
  ) -> requests.Response:
111
112
  """A decorator that wraps over the make_request function to send telemetry requests as required.
112
113
 
@@ -122,6 +123,7 @@ def telemetry(make_request: F) -> F:
122
123
  request_kwargs(Dict[str, int | bool | str | float] | None): extra arguments to be passed when making the request.
123
124
  ignore_files(Optional[list[str]]): Ignore files to be used when creating artifact
124
125
  session_meta(Dict[str, Any]): Metadata about the session object, like - stage
126
+ file_key (Optional[str]): the field in which the files must be uploaded
125
127
 
126
128
  Returns:
127
129
  requests.Response: response json
@@ -192,6 +194,7 @@ def telemetry(make_request: F) -> F:
192
194
  path=path,
193
195
  ignore_files=ignore_files,
194
196
  request_kwargs=request_kwargs,
197
+ file_key=file_key,
195
198
  )
196
199
 
197
200
  trigger_usage_collection(res=res)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: peak-sdk
3
- Version: 1.13.0
3
+ Version: 1.14.0
4
4
  Summary: Python SDK for interacting with the Peak platform
5
5
  Home-page: https://docs.peak.ai/sdk/latest/
6
6
  License: Apache-2.0
@@ -106,7 +106,7 @@ Follow these steps to create a virtual environment using Python's built-in `venv
106
106
  This should return a response of the following format
107
107
 
108
108
  ```bash
109
- peak-cli==1.13.0
109
+ peak-cli==1.14.0
110
110
  Python==3.12.3
111
111
  System==Darwin(23.6.0)
112
112
  ```
@@ -122,7 +122,7 @@ Follow these steps to create a virtual environment using Python's built-in `venv
122
122
  This should print the version of the SDK
123
123
 
124
124
  ```
125
- 1.13.0
125
+ 1.14.0
126
126
  ```
127
127
 
128
128
  ### Using the SDK and CLI
@@ -1,6 +1,6 @@
1
1
  peak/__init__.py,sha256=lxS3Xqyj9yvZdI3DVWbfn8i_Lw4t2Ujw9HbKe44-LY8,1284
2
2
  peak/_metadata.py,sha256=ongQ3I77xv-3nZSLemYk_UKYLiMAwfM60-K_vcqRMBI,30528
3
- peak/_version.py,sha256=MbZ0hqaFuTOXiQjpQLbkSZB_iRF6w2pSKGMbF2_yGFg,887
3
+ peak/_version.py,sha256=q_w6UYjTZ96mhm0Vg6AXepEKgyu-XGfEAbNB40N3tlI,887
4
4
  peak/auth.py,sha256=KcqCqovY6sFiMGNAGP9k3AtCAXrZ-tYd7QP-PFYorX0,904
5
5
  peak/base_client.py,sha256=3cS8hZApONkojwdgzt_tbwSxwpFcn3xGwzVcmxkgOJc,1808
6
6
  peak/callbacks.py,sha256=k_p2Av5_ZWD8bDzcSPhbYaAS2xHQpVI1cSkAecnmuqU,3775
@@ -21,8 +21,8 @@ peak/cli/press/deployments.py,sha256=xr46ZWwmOE9IIRb9U9zNSIfDN6_jAbQce-wvjgfm-VI
21
21
  peak/cli/press/specs.py,sha256=7XFWmgOuNBM8N482InvtQiZoQOldHqcQghLyHCmLHHI,4737
22
22
  peak/cli/resources/__init__.py,sha256=ThMYJ-QNULjTWOmAGUzhKWuqDcHq73DxzgTV2r5-uLs,883
23
23
  peak/cli/resources/alerts/__init__.py,sha256=TyeLPOGiA4qvOKORV3Ejlx8n6lGfX1G2GcU-bpYsgPE,1197
24
- peak/cli/resources/alerts/emails.py,sha256=10ledYdyD6jQgTac62xn8yDodOLwoj8wD4s3HEmEIpc,11892
25
- peak/cli/resources/artifacts.py,sha256=GiJ-yR1bvClDVO6EIHGqDyqsLGpmlUh9Bk_UPdUc-Co,12105
24
+ peak/cli/resources/alerts/emails.py,sha256=Z2qhub2eFhGLjVY_koto_SoqB1nQ3uWvdW_Zft1ukAU,12435
25
+ peak/cli/resources/artifacts.py,sha256=iYx29_FUdohxmm5zwwRtrOAedVSFgjVo8iVA7CTmtgE,12619
26
26
  peak/cli/resources/images.py,sha256=SwZC0y6pw3mq1HMiO9nPV3YzykbMuSIGt2TD47ZTZ1Y,43133
27
27
  peak/cli/resources/services.py,sha256=ZiWX4OyR9bMDglhRJNF8fY9YjGfH4ZDqxeNvCO88s4Q,25666
28
28
  peak/cli/resources/tenants.py,sha256=1vmNOwmLQdNV9RSVNaOZBRcAzHkOzIcVNz5ZH390O0c,4066
@@ -35,7 +35,7 @@ peak/compression.py,sha256=XPYjtREe93Gxlnn9YkSnBwaFKTIJSZ6MOPeuqwi3qTs,7894
35
35
  peak/config.py,sha256=FZ6aIN0gwA52noh-8HJkGnUr8HEOpyNFk6uR4QWt65o,1146
36
36
  peak/constants.py,sha256=TDMN4cXXKyR_Q8maeo8Ukvprl_Bz0YtYytD3yuHBZKs,3312
37
37
  peak/exceptions.py,sha256=xAPgn8KHsKEEiHoViGPrF3TF1Ma_lSk6tgki2Yv_yEY,7491
38
- peak/handler.py,sha256=aD_KyFTBKu_4ZpKiDXHNclQbfPfSR8FL_KdBeGZ87IA,15147
38
+ peak/handler.py,sha256=9HFbVtxJ6bEBgvpF8PmlPYa6EOHLKejWMBL3SJd26VM,17229
39
39
  peak/helpers.py,sha256=J2q1syT-2V5eD8gkgcH8mk6gNLsEvPa7qFcB390O6V0,9879
40
40
  peak/logger.py,sha256=bPq_7mdbhFoUcnV_LCi8hRDrb7INwf8PHHEx2z83bFU,1548
41
41
  peak/metrics/__init__.py,sha256=g5ufdcpozE7C6jJVbzo9XQNK3o9dNTy31wgIaRBmrHQ,1057
@@ -48,8 +48,8 @@ peak/press/deployments.py,sha256=lfWSkrJ6nEWiA8bO0d5u675mGJakRgNuQEbqXpLgbJc,848
48
48
  peak/press/specs.py,sha256=GH9-SACctAlcBZznXEmsIqneOwIJoE55mD4aHQymMrM,10915
49
49
  peak/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
50
  peak/resources/__init__.py,sha256=CkLWMygz8mr_isA8uMGQn2uut-BilCydLwx5sYniPIA,1242
51
- peak/resources/alerts.py,sha256=-RIfyCa4bkrb32poJlbKnsfLslpw49DyqvUOCTl-mUo,12370
52
- peak/resources/artifacts.py,sha256=lLVRRrznKKYVOA-pinWyqLpRd-AoFHGkFYwLT9aEGOU,14365
51
+ peak/resources/alerts.py,sha256=Ey1TUtCD7L0X5N03B5EijrGkFWxrarNi8QBv9_x6eBI,12792
52
+ peak/resources/artifacts.py,sha256=Ga6D-axCq_Gn5sq8eH7MZrWCMCwBK8xO-iaUapGdM2U,15648
53
53
  peak/resources/images.py,sha256=7UB-jNEkE3HaqGLiTkv5wf5SU_9Y-jeFoMG_aMPT-y8,46715
54
54
  peak/resources/services.py,sha256=JXZrPf3TXL-MhcjzduN6dNbMJe4PrbALUYffJviOnbY,17176
55
55
  peak/resources/tenants.py,sha256=amTs39KZ5hxDd7h3h1qo3TgYJOY1Eql0EhRgDBPlQ6Y,4380
@@ -77,10 +77,10 @@ peak/sample_yaml/press/blocks/specs/update_block_spec_metadata.yaml,sha256=WsfYG
77
77
  peak/sample_yaml/press/blocks/specs/workflow/create_block_spec.yaml,sha256=k4RePPB0wEiTwq91Lg2NY0MTTWr90zHPluxKsxAEpA4,4564
78
78
  peak/sample_yaml/press/blocks/specs/workflow/create_block_spec_release.yaml,sha256=70tGyUmrP-h_MweS7LzoYcltV8cNvBuDYxgexed7GxI,4208
79
79
  peak/sample_yaml/press/patch_parameters.yaml,sha256=8eD8X2XNVQ9_TNDFXd-XPiZ5CK2upqpv1QCEiWvDGBs,139
80
- peak/sample_yaml/resources/artifacts/create_artifact.yaml,sha256=TtUB8yI-hZqXY3t5bCYPbXncvg-GXUIq0T8Ak7tYuW4,152
81
- peak/sample_yaml/resources/artifacts/create_artifact_version.yaml,sha256=orT1FOpjxpLP3XHMB9XDfhLM1KG8Sv3PSlVUQkeNUeI,104
80
+ peak/sample_yaml/resources/artifacts/create_artifact.yaml,sha256=8sFU7VV2vv292THRsGNzTItWbhP7F4YMACM4jkVisRU,194
81
+ peak/sample_yaml/resources/artifacts/create_artifact_version.yaml,sha256=Mru6TdS0z34--r4nhx0-ZBUgR6Ylj0Gp_JRy3-Kb7pk,131
82
82
  peak/sample_yaml/resources/artifacts/update_artifact_metadata.yaml,sha256=nvV84lOBtoekXl3kWrMTIU3tbsVn-gVIx4cLRI8jevw,99
83
- peak/sample_yaml/resources/emails/send_email.yaml,sha256=aU0oUT7AppVRSnu-NJmp-Li0xKkM8XGqStpJAIGYKGg,256
83
+ peak/sample_yaml/resources/emails/send_email.yaml,sha256=YWv0PDq-4g0krsbtZdte9oV9PlluKuytEIwR8Ck6hyk,295
84
84
  peak/sample_yaml/resources/images/dockerfile/create_image.yaml,sha256=kHLlrnDJZX_sFcgxbu0wbmTjsVCqsJxe1G1__jZZeLs,384
85
85
  peak/sample_yaml/resources/images/dockerfile/create_image_version.yaml,sha256=fq51FEdHbe1kp6ozpZUkeGBguqYRroo8W2YvXf-L_Xg,353
86
86
  peak/sample_yaml/resources/images/dockerfile/update_version.yaml,sha256=XPHAp-5vD2IdDglalqnbknwJA8FEQM3GQ2_SCa0y5eA,318
@@ -110,8 +110,8 @@ peak/sample_yaml/resources/workflows/workflow_input_parameters.yaml,sha256=kM52m
110
110
  peak/sample_yaml/resources/workflows/workflow_input_parameters_inherit.yaml,sha256=6sA-CsVB0xS31G_2YE9W4vtZvupA9zDO97UCJKJlJiQ,1426
111
111
  peak/sample_yaml/resources/workflows/workflow_output_parameters.yaml,sha256=S9twG4lSB2HAt4ZL6zy5beKD-XY1Jik4asyHy4DG5Cs,913
112
112
  peak/sample_yaml/resources/workflows/workflow_skippable_steps.yaml,sha256=Ei1wGqJC-LqDPpQfqh_CmMmJ_DI5kQfuGTK4koQsiVk,1418
113
- peak/session.py,sha256=UZxo3Zai50G_ruZTTvNCUQvpQG2yl3TP5-uXz_wLWy8,10187
114
- peak/telemetry.py,sha256=vRiWm3evFRSy_V8wC2IopdDP32KbcueqNASUhlnmyHs,7086
113
+ peak/session.py,sha256=4Wi6uBmJSv6vAV0d6SweZCV59jpMr3Zkc-84aUTrn7U,10360
114
+ peak/telemetry.py,sha256=LSrqSir-2WKPDwhjs_hG-oSjSIVnojptN124hPPR5i0,7263
115
115
  peak/template.py,sha256=VezqlvPxJKW_e4lh3GqsUX1mjUJsW9WRGLC1oMK2UwE,10839
116
116
  peak/tools/__init__.py,sha256=qK30qBi0MNvob6UkyzcfhI0s8nfSwGC4167A_2URBnY,1048
117
117
  peak/tools/logging/__init__.py,sha256=tIKis2HbtFzXY9gEsjcFipHxoGbieDtV2cYKP7Z9Ibw,1513
@@ -120,8 +120,8 @@ peak/tools/logging/log_level.py,sha256=Xtv4zZnYk4QBix_MfCRGim4yJbv7w2tTbNKe_s4Qm
120
120
  peak/tools/logging/logger.py,sha256=Jow5D3hqek-n0kHWNeL2nKbC9NfpfkWFT_FmPp-skTw,15653
121
121
  peak/tools/logging/utils.py,sha256=qmjdBbCc1Y6JDbSgNXfdnLnpkx7fb9kPw9u8uO3AAII,3330
122
122
  peak/validators.py,sha256=_nVAXF_AB443voKNjyQsCTQBAVVAqn7xCbCbBguohIs,2715
123
- peak_sdk-1.13.0.dist-info/LICENSE,sha256=W0jszenKx7YdFA7BDnyg8xDKXzCP8AperJb_PHh9paQ,11340
124
- peak_sdk-1.13.0.dist-info/METADATA,sha256=HoRITd4d2gO1wDKXvENISm3Wq3Yi0y0WFF81N4_SYy8,7978
125
- peak_sdk-1.13.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
- peak_sdk-1.13.0.dist-info/entry_points.txt,sha256=zHCEjuOTjkfmqivgEZQsPGm4zFA4W3Q_vKCjPr7W6lE,47
127
- peak_sdk-1.13.0.dist-info/RECORD,,
123
+ peak_sdk-1.14.0.dist-info/LICENSE,sha256=W0jszenKx7YdFA7BDnyg8xDKXzCP8AperJb_PHh9paQ,11340
124
+ peak_sdk-1.14.0.dist-info/METADATA,sha256=7zHFOJ0bEqwu2_NEDS3jJ2ig9kJjDSw2Kv_IUHEdqv0,7978
125
+ peak_sdk-1.14.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
+ peak_sdk-1.14.0.dist-info/entry_points.txt,sha256=zHCEjuOTjkfmqivgEZQsPGm4zFA4W3Q_vKCjPr7W6lE,47
127
+ peak_sdk-1.14.0.dist-info/RECORD,,