craft-ai-sdk 0.50.1rc1__py3-none-any.whl → 0.51.0rc1__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.
Potentially problematic release.
This version of craft-ai-sdk might be problematic. Click here for more details.
- craft_ai_sdk/__init__.py +1 -1
- craft_ai_sdk/core/pipeline_metrics.py +1 -22
- craft_ai_sdk/core/pipelines.py +46 -1
- craft_ai_sdk/core/steps.py +70 -21
- craft_ai_sdk/sdk.py +3 -1
- craft_ai_sdk/utils.py +33 -1
- {craft_ai_sdk-0.50.1rc1.dist-info → craft_ai_sdk-0.51.0rc1.dist-info}/METADATA +1 -1
- {craft_ai_sdk-0.50.1rc1.dist-info → craft_ai_sdk-0.51.0rc1.dist-info}/RECORD +12 -12
- documentation.pdf +0 -0
- {craft_ai_sdk-0.50.1rc1.dist-info → craft_ai_sdk-0.51.0rc1.dist-info}/LICENSE +0 -0
- {craft_ai_sdk-0.50.1rc1.dist-info → craft_ai_sdk-0.51.0rc1.dist-info}/WHEEL +0 -0
- {craft_ai_sdk-0.50.1rc1.dist-info → craft_ai_sdk-0.51.0rc1.dist-info}/entry_points.txt +0 -0
craft_ai_sdk/__init__.py
CHANGED
|
@@ -1,29 +1,8 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import warnings
|
|
3
2
|
|
|
4
|
-
from ..utils import log_func_result, remove_none_values
|
|
3
|
+
from ..utils import log_func_result, remove_none_values, get_execution_id
|
|
5
4
|
from ..sdk import BaseCraftAiSdk
|
|
6
5
|
|
|
7
|
-
_execution_context = None
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def get_execution_id():
|
|
11
|
-
global _execution_context
|
|
12
|
-
if _execution_context is None:
|
|
13
|
-
try:
|
|
14
|
-
# File injected in steps
|
|
15
|
-
import __craft_internal_execution_context # type: ignore
|
|
16
|
-
|
|
17
|
-
_execution_context = __craft_internal_execution_context
|
|
18
|
-
except ImportError:
|
|
19
|
-
_execution_context = False
|
|
20
|
-
if _execution_context:
|
|
21
|
-
try:
|
|
22
|
-
return _execution_context.current_execution_id.get()
|
|
23
|
-
except LookupError:
|
|
24
|
-
pass
|
|
25
|
-
return os.environ.get("CRAFT_AI_EXECUTION_ID")
|
|
26
|
-
|
|
27
6
|
|
|
28
7
|
@log_func_result("Pipeline metrics definition", get_execution_id)
|
|
29
8
|
def record_metric_value(sdk: BaseCraftAiSdk, name, value):
|
craft_ai_sdk/core/pipelines.py
CHANGED
|
@@ -10,6 +10,7 @@ from ..utils import (
|
|
|
10
10
|
multipartify,
|
|
11
11
|
handle_data_store_response,
|
|
12
12
|
remove_keys_from_dict,
|
|
13
|
+
_datetime_to_timestamp_in_ms,
|
|
13
14
|
)
|
|
14
15
|
from .steps import (
|
|
15
16
|
_add_inputs_outputs_in_message,
|
|
@@ -219,7 +220,7 @@ def create_pipeline(
|
|
|
219
220
|
outputs,
|
|
220
221
|
pipeline_name=pipeline_name,
|
|
221
222
|
)
|
|
222
|
-
files = _prepare_create_step_files(container_config, data, function_path)
|
|
223
|
+
files = _prepare_create_step_files(sdk, container_config, data, function_path)
|
|
223
224
|
|
|
224
225
|
log_action(
|
|
225
226
|
sdk,
|
|
@@ -414,3 +415,47 @@ def download_pipeline_local_folder(sdk: BaseCraftAiSdk, pipeline_name, folder):
|
|
|
414
415
|
f.write(object_content)
|
|
415
416
|
else:
|
|
416
417
|
raise ValueError("'folder' must be a string")
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
@log_func_result("Pipeline logs")
|
|
421
|
+
def get_pipeline_logs(
|
|
422
|
+
sdk: BaseCraftAiSdk,
|
|
423
|
+
pipeline_name,
|
|
424
|
+
from_datetime=None,
|
|
425
|
+
to_datetime=None,
|
|
426
|
+
limit=None,
|
|
427
|
+
):
|
|
428
|
+
"""Get the logs of a pipeline.
|
|
429
|
+
|
|
430
|
+
Args:
|
|
431
|
+
pipeline_name (:obj:`str`): Name of the pipeline.
|
|
432
|
+
from_datetime (:obj:`datetime.time`, optional): Datetime from which the logs
|
|
433
|
+
are collected.
|
|
434
|
+
to_datetime (:obj:`datetime.time`, optional): Datetime until which the logs
|
|
435
|
+
are collected.
|
|
436
|
+
limit (:obj:`int`, optional): Maximum number of logs that are collected.
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
:obj:`list` of :obj:`dict`: List of collected logs represented as dict with
|
|
440
|
+
the following keys:
|
|
441
|
+
|
|
442
|
+
* ``"timestamp"`` (:obj:`str`): Timestamp of the log.
|
|
443
|
+
* ``"message"`` (:obj:`str`): Log message.
|
|
444
|
+
"""
|
|
445
|
+
url = f"{sdk.base_environment_api_url}/pipelines/{pipeline_name}/logs"
|
|
446
|
+
|
|
447
|
+
data = {}
|
|
448
|
+
if from_datetime is not None:
|
|
449
|
+
data["from"] = _datetime_to_timestamp_in_ms(from_datetime)
|
|
450
|
+
if to_datetime is not None:
|
|
451
|
+
data["to"] = _datetime_to_timestamp_in_ms(to_datetime)
|
|
452
|
+
if limit is not None:
|
|
453
|
+
data["limit"] = limit
|
|
454
|
+
|
|
455
|
+
log_action(
|
|
456
|
+
sdk,
|
|
457
|
+
"Please wait while logs are being fetched. This may take a while...",
|
|
458
|
+
)
|
|
459
|
+
logs = sdk._post(url, json=data)
|
|
460
|
+
|
|
461
|
+
return logs
|
craft_ai_sdk/core/steps.py
CHANGED
|
@@ -14,6 +14,7 @@ from ..utils import (
|
|
|
14
14
|
multipartify,
|
|
15
15
|
remove_none_values,
|
|
16
16
|
handle_data_store_response,
|
|
17
|
+
_datetime_to_timestamp_in_ms,
|
|
17
18
|
)
|
|
18
19
|
from ..constants import CREATION_REQUESTS_RETRY_INTERVAL
|
|
19
20
|
|
|
@@ -73,17 +74,30 @@ def _prepare_create_step_data(
|
|
|
73
74
|
return data
|
|
74
75
|
|
|
75
76
|
|
|
76
|
-
def _prepare_create_step_files(container_config, data, function_path):
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
def _prepare_create_step_files(sdk, container_config, data, function_path):
|
|
78
|
+
if "local_folder" not in container_config:
|
|
79
|
+
return {}
|
|
80
|
+
|
|
81
|
+
url = f"{sdk.base_environment_api_url}/project-information"
|
|
82
|
+
project_information = sdk._get(url)
|
|
83
|
+
|
|
84
|
+
included = [
|
|
85
|
+
*(
|
|
86
|
+
data.get("container_config", {}).get(
|
|
87
|
+
"included_folders", project_information.get("included_folders")
|
|
88
|
+
)
|
|
89
|
+
or []
|
|
90
|
+
),
|
|
91
|
+
data.get("container_config", {}).get(
|
|
92
|
+
"requirements_path", project_information.get("requirements_path")
|
|
93
|
+
),
|
|
94
|
+
function_path,
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
tar_data = _compress_folder_to_memory(
|
|
98
|
+
container_config["local_folder"], include=list(filter(None, included))
|
|
99
|
+
)
|
|
100
|
+
return {"step_file": tar_data}
|
|
87
101
|
|
|
88
102
|
|
|
89
103
|
def _add_inputs_outputs_in_message(message, inputs, outputs):
|
|
@@ -286,7 +300,7 @@ def create_step(
|
|
|
286
300
|
outputs,
|
|
287
301
|
step_name=step_name,
|
|
288
302
|
)
|
|
289
|
-
files = _prepare_create_step_files(container_config, data, function_path)
|
|
303
|
+
files = _prepare_create_step_files(sdk, container_config, data, function_path)
|
|
290
304
|
|
|
291
305
|
log_action(
|
|
292
306
|
sdk,
|
|
@@ -403,15 +417,6 @@ def list_steps(sdk: BaseCraftAiSdk):
|
|
|
403
417
|
* ``"step_name"`` (:obj:`str`): Name of the step.
|
|
404
418
|
* ``"status"`` (:obj:`str`): either ``"creation_pending"`` or ``"ready"``.
|
|
405
419
|
* ``"created_at"`` (:obj:`str`): The creation date in ISO format.
|
|
406
|
-
* ``"updated_at"`` (:obj:`str`): The last update date in ISO format.
|
|
407
|
-
* ``"repository_branch"`` (:obj:`str`): The branch of the
|
|
408
|
-
repository where the step was built.
|
|
409
|
-
* ``"repository_url"`` (:obj:`str`): The url of the repository
|
|
410
|
-
where the step was built.
|
|
411
|
-
* ``"commit_id"`` (:obj:`str`): The commit id on which the step was
|
|
412
|
-
built.
|
|
413
|
-
* ``"origin"`` (:obj:`str`): The origin of the step, can be
|
|
414
|
-
``"git_repository"`` or ``"local"``.
|
|
415
420
|
"""
|
|
416
421
|
url = f"{sdk.base_environment_api_url}/steps"
|
|
417
422
|
|
|
@@ -474,3 +479,47 @@ def download_step_local_folder(sdk: BaseCraftAiSdk, step_name, folder):
|
|
|
474
479
|
f.write(object_content)
|
|
475
480
|
else:
|
|
476
481
|
raise ValueError("'folder' must be a string")
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
@log_func_result("Step logs")
|
|
485
|
+
def get_step_logs(
|
|
486
|
+
sdk: BaseCraftAiSdk,
|
|
487
|
+
step_name,
|
|
488
|
+
from_datetime=None,
|
|
489
|
+
to_datetime=None,
|
|
490
|
+
limit=None,
|
|
491
|
+
):
|
|
492
|
+
"""Get the logs of a step.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
step_name (:obj:`str`): Name of the step.
|
|
496
|
+
from_datetime (:obj:`datetime.time`, optional): Datetime from which the logs
|
|
497
|
+
are collected.
|
|
498
|
+
to_datetime (:obj:`datetime.time`, optional): Datetime until which the logs
|
|
499
|
+
are collected.
|
|
500
|
+
limit (:obj:`int`, optional): Maximum number of logs that are collected.
|
|
501
|
+
|
|
502
|
+
Returns:
|
|
503
|
+
:obj:`list` of :obj:`dict`: List of collected logs represented as dict with
|
|
504
|
+
the following keys:
|
|
505
|
+
|
|
506
|
+
* ``"timestamp"`` (:obj:`str`): Timestamp of the log.
|
|
507
|
+
* ``"message"`` (:obj:`str`): Log message.
|
|
508
|
+
"""
|
|
509
|
+
url = f"{sdk.base_environment_api_url}/steps/{step_name}/logs"
|
|
510
|
+
|
|
511
|
+
data = {}
|
|
512
|
+
if from_datetime is not None:
|
|
513
|
+
data["from"] = _datetime_to_timestamp_in_ms(from_datetime)
|
|
514
|
+
if to_datetime is not None:
|
|
515
|
+
data["to"] = _datetime_to_timestamp_in_ms(to_datetime)
|
|
516
|
+
if limit is not None:
|
|
517
|
+
data["limit"] = limit
|
|
518
|
+
|
|
519
|
+
log_action(
|
|
520
|
+
sdk,
|
|
521
|
+
"Please wait while logs are being fetched. This may take a while...",
|
|
522
|
+
)
|
|
523
|
+
logs = sdk._post(url, json=data)
|
|
524
|
+
|
|
525
|
+
return logs
|
craft_ai_sdk/sdk.py
CHANGED
|
@@ -59,6 +59,7 @@ class CraftAiSdk(BaseCraftAiSdk):
|
|
|
59
59
|
list_steps,
|
|
60
60
|
delete_step,
|
|
61
61
|
download_step_local_folder,
|
|
62
|
+
get_step_logs,
|
|
62
63
|
)
|
|
63
64
|
from .core.pipelines import (
|
|
64
65
|
create_pipeline,
|
|
@@ -66,6 +67,7 @@ class CraftAiSdk(BaseCraftAiSdk):
|
|
|
66
67
|
list_pipelines,
|
|
67
68
|
delete_pipeline,
|
|
68
69
|
download_pipeline_local_folder,
|
|
70
|
+
get_pipeline_logs,
|
|
69
71
|
)
|
|
70
72
|
from .core.pipeline_executions import (
|
|
71
73
|
run_pipeline,
|
|
@@ -128,7 +130,7 @@ class CraftAiSdk(BaseCraftAiSdk):
|
|
|
128
130
|
os.environ.get("CRAFT_AI__MULTIPART_PART_SIZE__B", str(38 * 256 * 1024))
|
|
129
131
|
)
|
|
130
132
|
_access_token_margin = timedelta(seconds=30)
|
|
131
|
-
_version = "0.
|
|
133
|
+
_version = "0.51.0rc1" # Would be better to share it somewhere
|
|
132
134
|
|
|
133
135
|
def __init__(
|
|
134
136
|
self,
|
craft_ai_sdk/utils.py
CHANGED
|
@@ -8,9 +8,30 @@ from typing import Callable, Iterable, Union
|
|
|
8
8
|
import xml.etree.ElementTree as ET
|
|
9
9
|
from requests import RequestException, Response
|
|
10
10
|
from json import JSONDecodeError
|
|
11
|
+
import os
|
|
11
12
|
|
|
12
13
|
from .exceptions import SdkException
|
|
13
14
|
|
|
15
|
+
_execution_context = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_execution_id():
|
|
19
|
+
global _execution_context
|
|
20
|
+
if _execution_context is None:
|
|
21
|
+
try:
|
|
22
|
+
# File injected in steps
|
|
23
|
+
import __craft_internal_execution_context # type: ignore
|
|
24
|
+
|
|
25
|
+
_execution_context = __craft_internal_execution_context
|
|
26
|
+
except ImportError:
|
|
27
|
+
_execution_context = False
|
|
28
|
+
if _execution_context:
|
|
29
|
+
try:
|
|
30
|
+
return _execution_context.current_execution_id.get()
|
|
31
|
+
except LookupError:
|
|
32
|
+
pass
|
|
33
|
+
return os.environ.get("CRAFT_AI_EXECUTION_ID")
|
|
34
|
+
|
|
14
35
|
|
|
15
36
|
def handle_data_store_response(response):
|
|
16
37
|
"""Return the content of a response received from the datastore
|
|
@@ -64,8 +85,19 @@ def _parse_json_response(response):
|
|
|
64
85
|
def _raise_craft_ai_error_from_response(response: Response):
|
|
65
86
|
try:
|
|
66
87
|
error_content = response.json()
|
|
88
|
+
error_message = error_content.get("message", "The server returned an error")
|
|
89
|
+
|
|
90
|
+
# Permission denied inside a running execution
|
|
91
|
+
if response.status_code == 403 and get_execution_id() is not None:
|
|
92
|
+
error_message = (
|
|
93
|
+
"Insufficient permissions. This is probably because "
|
|
94
|
+
"you called an SDK function that is not permitted from "
|
|
95
|
+
"inside a running deployment or execution, even if it "
|
|
96
|
+
"works from your computer. Original error: " + error_message
|
|
97
|
+
)
|
|
98
|
+
|
|
67
99
|
raise SdkException(
|
|
68
|
-
message=
|
|
100
|
+
message=error_message,
|
|
69
101
|
status_code=response.status_code,
|
|
70
102
|
name=error_content.get("name"),
|
|
71
103
|
request_id=error_content.get("request_id"),
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
craft_ai_sdk/__init__.py,sha256=
|
|
1
|
+
craft_ai_sdk/__init__.py,sha256=AVeK65o7Y_UXm34XdKOD9VZBtPHTqVI5foTWQweq7qY,407
|
|
2
2
|
craft_ai_sdk/constants.py,sha256=KHRaIHA9tHxjwluo7zBF2UZpePQaDI57SrBs4Ob1g7Q,607
|
|
3
3
|
craft_ai_sdk/core/data_store.py,sha256=kI0nUIXfkz-9ENVEeFW70_PGhBNB_S-nntJJkKhGRoQ,8464
|
|
4
4
|
craft_ai_sdk/core/deployments.py,sha256=p717fy73OoynUuDKO6XYLfLu5stBHH73xQw6HLm8jUY,25804
|
|
5
5
|
craft_ai_sdk/core/endpoints.py,sha256=ElVcjnrjWD4_Wo5fOwRh1apUuL5IB7DM-FMH-1poP9w,4563
|
|
6
6
|
craft_ai_sdk/core/environment_variables.py,sha256=wy0U7y0C7tRXOXOiWGz0vX5ajHSmOb_7J1fXlSahGpI,2045
|
|
7
7
|
craft_ai_sdk/core/pipeline_executions.py,sha256=7RRKQUxXUCI871mmFCO4N4RG0RvX5MZ3Fss3doCb8mQ,18314
|
|
8
|
-
craft_ai_sdk/core/pipeline_metrics.py,sha256=
|
|
9
|
-
craft_ai_sdk/core/pipelines.py,sha256
|
|
8
|
+
craft_ai_sdk/core/pipeline_metrics.py,sha256=Tt5p6guHAf7nhq1wvJG3t7WqsYKqrNQ7sZcFKqXYmdM,6465
|
|
9
|
+
craft_ai_sdk/core/pipelines.py,sha256=-eU_vKoxFQiDXWZgvetI577ZOeJWR5jpVgqMBohDNUw,19756
|
|
10
10
|
craft_ai_sdk/core/resource_metrics.py,sha256=yaco_AZ4Wu5sxLRKsA3qt2R3-PMs2e32EGO0gsHtq2Y,2336
|
|
11
|
-
craft_ai_sdk/core/steps.py,sha256=
|
|
11
|
+
craft_ai_sdk/core/steps.py,sha256=pvC2bEPF-9XGugdYAQ2LhdlnKZvC3giRm9ZrX3ZDMLs,21406
|
|
12
12
|
craft_ai_sdk/core/users.py,sha256=Qi3xg7Vzk_0MepccNIZbFzjI0bBqouqkFStTuejUY6s,509
|
|
13
13
|
craft_ai_sdk/exceptions.py,sha256=IC-JfZmmmaTsbMCgirOEByRmWnatQLjKe8BErRkuwM0,1075
|
|
14
14
|
craft_ai_sdk/io.py,sha256=y9lg5unGIwQICAPuKUdUPDAJCsxe2lbseIlmiWka2Ec,11865
|
|
15
|
-
craft_ai_sdk/sdk.py,sha256=
|
|
16
|
-
craft_ai_sdk/utils.py,sha256=
|
|
15
|
+
craft_ai_sdk/sdk.py,sha256=8loHhKiH7Y5090Oxa2933Pejnunrv5CARjU8C5SEXE8,10071
|
|
16
|
+
craft_ai_sdk/utils.py,sha256=zo4fdexMeRspFHG-abmH858-eKzqZzSJ5tdxNBPzgpU,10551
|
|
17
17
|
craft_ai_sdk/warnings.py,sha256=xJXbUR66SVbG_ZO7rxpAZ2hkGxdUtM5JAx6JoWg77Qs,6678
|
|
18
|
-
documentation.pdf,sha256=
|
|
19
|
-
craft_ai_sdk-0.
|
|
20
|
-
craft_ai_sdk-0.
|
|
21
|
-
craft_ai_sdk-0.
|
|
22
|
-
craft_ai_sdk-0.
|
|
23
|
-
craft_ai_sdk-0.
|
|
18
|
+
documentation.pdf,sha256=4TF_tqHOz0cNtGGszD3oibl7tKz2ZwU6pa9yjewuFoM,327994
|
|
19
|
+
craft_ai_sdk-0.51.0rc1.dist-info/LICENSE,sha256=_2oYRJic9lZK05LceuJ9aZZw5mPHYc1WQhJiVS-oGFU,10754
|
|
20
|
+
craft_ai_sdk-0.51.0rc1.dist-info/METADATA,sha256=aDht_ffT46mGJxjMvRu5jdZ_ySd8s5fzx3tTE1fMVI4,1566
|
|
21
|
+
craft_ai_sdk-0.51.0rc1.dist-info/entry_points.txt,sha256=eV9YD0zCAb88_wNMDV99sRxVKVC-WOQF3b1Pepaytcg,385
|
|
22
|
+
craft_ai_sdk-0.51.0rc1.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
|
23
|
+
craft_ai_sdk-0.51.0rc1.dist-info/RECORD,,
|
documentation.pdf
CHANGED
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|