sagemaker-core 1.0.8__tar.gz → 1.0.10__tar.gz

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 sagemaker-core might be problematic. Click here for more details.

Files changed (43) hide show
  1. {sagemaker_core-1.0.8/src/sagemaker_core.egg-info → sagemaker_core-1.0.10}/PKG-INFO +1 -1
  2. sagemaker_core-1.0.10/VERSION +1 -0
  3. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/code_injection/shape_dag.py +18 -0
  4. sagemaker_core-1.0.10/src/sagemaker_core/main/logs.py +167 -0
  5. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/resources.py +202 -51
  6. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/shapes.py +4 -0
  7. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/utils.py +9 -3
  8. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/constants.py +2 -0
  9. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/resources_codegen.py +47 -0
  10. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/templates.py +42 -6
  11. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10/src/sagemaker_core.egg-info}/PKG-INFO +1 -1
  12. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core.egg-info/SOURCES.txt +1 -0
  13. sagemaker_core-1.0.8/VERSION +0 -1
  14. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/LICENSE +0 -0
  15. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/MANIFEST.in +0 -0
  16. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/README.rst +0 -0
  17. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/pyproject.toml +0 -0
  18. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/setup.cfg +0 -0
  19. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/__init__.py +0 -0
  20. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/_version.py +0 -0
  21. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/helper/__init__.py +0 -0
  22. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/helper/session_helper.py +0 -0
  23. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/__init__.py +0 -0
  24. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/code_injection/__init__.py +0 -0
  25. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/code_injection/base.py +0 -0
  26. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/code_injection/codec.py +0 -0
  27. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/code_injection/constants.py +0 -0
  28. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/config_schema.py +0 -0
  29. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/exceptions.py +0 -0
  30. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/intelligent_defaults_helper.py +0 -0
  31. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/main/user_agent.py +0 -0
  32. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/resources/__init__.py +0 -0
  33. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/shapes/__init__.py +0 -0
  34. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/__init__.py +0 -0
  35. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/codegen.py +0 -0
  36. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/data_extractor.py +0 -0
  37. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/method.py +0 -0
  38. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/resources_extractor.py +0 -0
  39. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/shapes_codegen.py +0 -0
  40. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core/tools/shapes_extractor.py +0 -0
  41. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core.egg-info/dependency_links.txt +0 -0
  42. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core.egg-info/requires.txt +0 -0
  43. {sagemaker_core-1.0.8 → sagemaker_core-1.0.10}/src/sagemaker_core.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sagemaker-core
3
- Version: 1.0.8
3
+ Version: 1.0.10
4
4
  Summary: An python package for sagemaker core functionalities
5
5
  Author-email: AWS <sagemaker-interests@amazon.com>
6
6
  Project-URL: Repository, https://github.com/aws/sagemaker-core.git
@@ -0,0 +1 @@
1
+ 1.0.10
@@ -1380,6 +1380,11 @@ SHAPE_DAG = {
1380
1380
  "shape": "AppLifecycleManagement",
1381
1381
  "type": "structure",
1382
1382
  },
1383
+ {
1384
+ "name": "BuiltInLifecycleConfigArn",
1385
+ "shape": "StudioLifecycleConfigArn",
1386
+ "type": "string",
1387
+ },
1383
1388
  ],
1384
1389
  "type": "structure",
1385
1390
  },
@@ -1884,6 +1889,7 @@ SHAPE_DAG = {
1884
1889
  "shape": "AppSecurityGroupManagement",
1885
1890
  "type": "string",
1886
1891
  },
1892
+ {"name": "TagPropagation", "shape": "TagPropagation", "type": "string"},
1887
1893
  {"name": "DefaultSpaceSettings", "shape": "DefaultSpaceSettings", "type": "structure"},
1888
1894
  ],
1889
1895
  "type": "structure",
@@ -3792,6 +3798,11 @@ SHAPE_DAG = {
3792
3798
  {"name": "CreationTime", "shape": "Timestamp", "type": "timestamp"},
3793
3799
  {"name": "FailureReason", "shape": "FailureReason", "type": "string"},
3794
3800
  {"name": "ResourceSpec", "shape": "ResourceSpec", "type": "structure"},
3801
+ {
3802
+ "name": "BuiltInLifecycleConfigArn",
3803
+ "shape": "StudioLifecycleConfigArn",
3804
+ "type": "string",
3805
+ },
3795
3806
  ],
3796
3807
  "type": "structure",
3797
3808
  },
@@ -4125,6 +4136,7 @@ SHAPE_DAG = {
4125
4136
  "shape": "AppSecurityGroupManagement",
4126
4137
  "type": "string",
4127
4138
  },
4139
+ {"name": "TagPropagation", "shape": "TagPropagation", "type": "string"},
4128
4140
  {"name": "DefaultSpaceSettings", "shape": "DefaultSpaceSettings", "type": "structure"},
4129
4141
  ],
4130
4142
  "type": "structure",
@@ -7697,6 +7709,11 @@ SHAPE_DAG = {
7697
7709
  "type": "structure",
7698
7710
  },
7699
7711
  {"name": "EmrSettings", "shape": "EmrSettings", "type": "structure"},
7712
+ {
7713
+ "name": "BuiltInLifecycleConfigArn",
7714
+ "shape": "StudioLifecycleConfigArn",
7715
+ "type": "string",
7716
+ },
7700
7717
  ],
7701
7718
  "type": "structure",
7702
7719
  },
@@ -14082,6 +14099,7 @@ SHAPE_DAG = {
14082
14099
  {"name": "DefaultSpaceSettings", "shape": "DefaultSpaceSettings", "type": "structure"},
14083
14100
  {"name": "SubnetIds", "shape": "Subnets", "type": "list"},
14084
14101
  {"name": "AppNetworkAccessType", "shape": "AppNetworkAccessType", "type": "string"},
14102
+ {"name": "TagPropagation", "shape": "TagPropagation", "type": "string"},
14085
14103
  ],
14086
14104
  "type": "structure",
14087
14105
  },
@@ -0,0 +1,167 @@
1
+ import boto3
2
+ import botocore
3
+
4
+ from boto3.session import Session
5
+ import botocore.client
6
+ from botocore.config import Config
7
+ from typing import Generator, Tuple, List
8
+ from sagemaker_core.main.utils import SingletonMeta
9
+
10
+
11
+ class CloudWatchLogsClient(metaclass=SingletonMeta):
12
+ """
13
+ A singleton class for creating a CloudWatchLogs client.
14
+ """
15
+
16
+ client: botocore.client = None
17
+
18
+ def __init__(self):
19
+ if not self.client:
20
+ session = Session()
21
+ self.client = session.client(
22
+ "logs",
23
+ session.region_name,
24
+ config=Config(retries={"max_attempts": 10, "mode": "standard"}),
25
+ )
26
+
27
+
28
+ class LogStreamHandler:
29
+ log_group_name: str = None
30
+ log_stream_name: str = None
31
+ stream_id: int = None
32
+ next_token: str = None
33
+ cw_client = None
34
+
35
+ def __init__(self, log_group_name: str, log_stream_name: str, stream_id: int):
36
+ self.log_group_name = log_group_name
37
+ self.log_stream_name = log_stream_name
38
+ self.cw_client = CloudWatchLogsClient().client
39
+ self.stream_id = stream_id
40
+
41
+ def get_latest_log_events(self) -> Generator[Tuple[str, dict], None, None]:
42
+ """
43
+ This method gets all the latest log events for this stream that exist at this moment in time.
44
+
45
+ cw_client.get_log_events() always returns a nextForwardToken even if the current batch of events is empty.
46
+ You can keep calling cw_client.get_log_events() with the same token until a new batch of log events exist.
47
+
48
+ API Reference: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs/client/get_log_events.html
49
+
50
+ Returns:
51
+ Generator[tuple[str, dict], None, None]: Generator that yields a tuple that consists for two values
52
+ str: stream_name,
53
+ dict: event dict in format
54
+ {
55
+ "ingestionTime": number,
56
+ "message": "string",
57
+ "timestamp": number
58
+ }
59
+ """
60
+ while True:
61
+ if not self.next_token:
62
+ token_args = {}
63
+ else:
64
+ token_args = {"nextToken": self.next_token}
65
+
66
+ response = self.cw_client.get_log_events(
67
+ logGroupName=self.log_group_name,
68
+ logStreamName=self.log_stream_name,
69
+ startFromHead=True,
70
+ **token_args,
71
+ )
72
+
73
+ self.next_token = response["nextForwardToken"]
74
+ if not response["events"]:
75
+ break
76
+
77
+ for event in response["events"]:
78
+ yield self.log_stream_name, event
79
+
80
+
81
+ class MultiLogStreamHandler:
82
+ log_group_name: str = None
83
+ log_stream_name_prefix: str = None
84
+ expected_stream_count: int = None
85
+ streams: List[LogStreamHandler] = []
86
+ cw_client = None
87
+
88
+ def __init__(
89
+ self, log_group_name: str, log_stream_name_prefix: str, expected_stream_count: int
90
+ ):
91
+ self.log_group_name = log_group_name
92
+ self.log_stream_name_prefix = log_stream_name_prefix
93
+ self.expected_stream_count = expected_stream_count
94
+ self.cw_client = CloudWatchLogsClient().client
95
+
96
+ def get_latest_log_events(self) -> Generator[Tuple[str, dict], None, None]:
97
+ """
98
+ This method gets all the latest log events from each stream that exist at this moment.
99
+
100
+ Returns:
101
+ Generator[tuple[str, dict], None, None]: Generator that yields a tuple that consists for two values
102
+ str: stream_name,
103
+ dict: event dict in format -
104
+ {
105
+ "ingestionTime": number,
106
+ "message": "string",
107
+ "timestamp": number
108
+ }
109
+ """
110
+ if not self.ready():
111
+ return []
112
+
113
+ for stream in self.streams:
114
+ yield from stream.get_latest_log_events()
115
+
116
+ def ready(self) -> bool:
117
+ """
118
+ Checks whether or not MultiLogStreamHandler is ready to serve new log events at this moment.
119
+
120
+ If self.streams is already set, return True.
121
+ Otherwise, check if the current number of log streams in the log group match the exptected stream count.
122
+
123
+ Returns:
124
+ bool: Whether or not MultiLogStreamHandler is ready to serve new log events.
125
+ """
126
+
127
+ if len(self.streams) >= self.expected_stream_count:
128
+ return True
129
+
130
+ try:
131
+ response = self.cw_client.describe_log_streams(
132
+ logGroupName=self.log_group_name,
133
+ logStreamNamePrefix=self.log_stream_name_prefix + "/",
134
+ orderBy="LogStreamName",
135
+ )
136
+ stream_names = [stream["logStreamName"] for stream in response["logStreams"]]
137
+
138
+ next_token = response.get("nextToken")
139
+ while next_token:
140
+ response = self.cw_client.describe_log_streams(
141
+ logGroupName=self.log_group_name,
142
+ logStreamNamePrefix=self.log_stream_name_prefix + "/",
143
+ orderBy="LogStreamName",
144
+ nextToken=next_token,
145
+ )
146
+ stream_names.extend([stream["logStreamName"] for stream in response["logStreams"]])
147
+ next_token = response.get("nextToken", None)
148
+
149
+ if len(stream_names) >= self.expected_stream_count:
150
+ self.streams = [
151
+ LogStreamHandler(self.log_group_name, log_stream_name, index)
152
+ for index, log_stream_name in enumerate(stream_names)
153
+ ]
154
+
155
+ return True
156
+ else:
157
+ # Log streams are created whenever a container starts writing to stdout/err,
158
+ # so if the stream count is less than the expected number, return False
159
+ return False
160
+
161
+ except botocore.exceptions.ClientError as e:
162
+ # On the very first training job run on an account, there's no log group until
163
+ # the container starts logging, so ignore any errors thrown about that
164
+ if e.response["Error"]["Code"] == "ResourceNotFoundException":
165
+ return False
166
+ else:
167
+ raise