sagemaker-core 0.1.3__py3-none-any.whl → 1.0.1__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 sagemaker-core might be problematic. Click here for more details.
- sagemaker_core/__init__.py +4 -0
- sagemaker_core/helper/session_helper.py +769 -0
- sagemaker_core/{code_injection → main/code_injection}/codec.py +2 -2
- sagemaker_core/{code_injection → main/code_injection}/constants.py +10 -0
- sagemaker_core/{code_injection → main/code_injection}/shape_dag.py +48 -0
- sagemaker_core/{generated → main}/config_schema.py +47 -0
- sagemaker_core/{generated → main}/intelligent_defaults_helper.py +8 -8
- sagemaker_core/{generated → main}/resources.py +2716 -1284
- sagemaker_core/main/shapes.py +11650 -0
- sagemaker_core/main/user_agent.py +77 -0
- sagemaker_core/{generated → main}/utils.py +246 -10
- sagemaker_core/resources/__init__.py +1 -0
- sagemaker_core/shapes/__init__.py +1 -0
- sagemaker_core/tools/__init__.py +1 -1
- sagemaker_core/tools/codegen.py +1 -2
- sagemaker_core/tools/constants.py +3 -8
- sagemaker_core/tools/method.py +1 -1
- sagemaker_core/tools/resources_codegen.py +30 -28
- sagemaker_core/tools/resources_extractor.py +4 -8
- sagemaker_core/tools/shapes_codegen.py +16 -10
- sagemaker_core/tools/shapes_extractor.py +1 -1
- sagemaker_core/tools/templates.py +109 -122
- sagemaker_core-1.0.1.dist-info/METADATA +81 -0
- sagemaker_core-1.0.1.dist-info/RECORD +34 -0
- {sagemaker_core-0.1.3.dist-info → sagemaker_core-1.0.1.dist-info}/WHEEL +1 -1
- sagemaker_core/generated/shapes.py +0 -11584
- sagemaker_core/util/util.py +0 -81
- sagemaker_core-0.1.3.dist-info/METADATA +0 -28
- sagemaker_core-0.1.3.dist-info/RECORD +0 -31
- /sagemaker_core/{code_injection → helper}/__init__.py +0 -0
- /sagemaker_core/{generated → main}/__init__.py +0 -0
- /sagemaker_core/{util → main/code_injection}/__init__.py +0 -0
- /sagemaker_core/{code_injection → main/code_injection}/base.py +0 -0
- /sagemaker_core/{generated → main}/exceptions.py +0 -0
- {sagemaker_core-0.1.3.dist-info → sagemaker_core-1.0.1.dist-info}/LICENSE +0 -0
- {sagemaker_core-0.1.3.dist-info → sagemaker_core-1.0.1.dist-info}/top_level.txt +0 -0
|
@@ -17,14 +17,19 @@ export PYTHONPATH=<sagemaker-code-gen repo directory>:$PYTHONPATH
|
|
|
17
17
|
"""
|
|
18
18
|
import os
|
|
19
19
|
|
|
20
|
-
from sagemaker_core.code_injection.codec import pascal_to_snake
|
|
20
|
+
from sagemaker_core.main.code_injection.codec import pascal_to_snake
|
|
21
21
|
from sagemaker_core.tools.constants import (
|
|
22
22
|
LICENCES_STRING,
|
|
23
23
|
GENERATED_CLASSES_LOCATION,
|
|
24
24
|
SHAPES_CODEGEN_FILE_NAME,
|
|
25
25
|
)
|
|
26
26
|
from sagemaker_core.tools.shapes_extractor import ShapesExtractor
|
|
27
|
-
from sagemaker_core.
|
|
27
|
+
from sagemaker_core.main.utils import (
|
|
28
|
+
add_indent,
|
|
29
|
+
convert_to_snake_case,
|
|
30
|
+
remove_html_tags,
|
|
31
|
+
escape_special_rst_characters,
|
|
32
|
+
)
|
|
28
33
|
from sagemaker_core.tools.templates import SHAPE_CLASS_TEMPLATE, SHAPE_BASE_CLASS_TEMPLATE
|
|
29
34
|
from sagemaker_core.tools.data_extractor import (
|
|
30
35
|
load_combined_shapes_data,
|
|
@@ -166,20 +171,21 @@ class ShapesCodeGen:
|
|
|
166
171
|
"""
|
|
167
172
|
shape_dict = self.combined_shapes[shape]
|
|
168
173
|
|
|
169
|
-
docstring = f"
|
|
174
|
+
docstring = f"{shape}"
|
|
170
175
|
if "documentation" in shape_dict:
|
|
171
|
-
docstring += f"\n
|
|
176
|
+
docstring += f"\n {shape_dict['documentation']}"
|
|
172
177
|
|
|
173
|
-
docstring += "\n\
|
|
174
|
-
docstring += "\n
|
|
178
|
+
docstring += "\n\nAttributes"
|
|
179
|
+
docstring += "\n----------------------"
|
|
175
180
|
|
|
176
181
|
if "members" in shape_dict:
|
|
177
182
|
for member, member_attributes in shape_dict["members"].items():
|
|
178
|
-
docstring += f"\n
|
|
183
|
+
docstring += f"\n{convert_to_snake_case(member)}"
|
|
179
184
|
if "documentation" in member_attributes:
|
|
180
|
-
docstring += f":
|
|
185
|
+
docstring += f": {member_attributes['documentation']}"
|
|
181
186
|
|
|
182
|
-
|
|
187
|
+
docstring = remove_html_tags(docstring)
|
|
188
|
+
return escape_special_rst_characters(docstring)
|
|
183
189
|
|
|
184
190
|
def generate_license(self):
|
|
185
191
|
"""
|
|
@@ -200,7 +206,7 @@ class ShapesCodeGen:
|
|
|
200
206
|
imports += "\n"
|
|
201
207
|
imports += "from pydantic import BaseModel, ConfigDict\n"
|
|
202
208
|
imports += "from typing import List, Dict, Optional, Any, Union\n"
|
|
203
|
-
imports += "from sagemaker_core.
|
|
209
|
+
imports += "from sagemaker_core.main.utils import Unassigned"
|
|
204
210
|
imports += "\n"
|
|
205
211
|
return imports
|
|
206
212
|
|
|
@@ -17,7 +17,7 @@ from functools import lru_cache
|
|
|
17
17
|
from typing import Optional, Any
|
|
18
18
|
|
|
19
19
|
from sagemaker_core.tools.constants import BASIC_JSON_TYPES_TO_PYTHON_TYPES, SHAPE_DAG_FILE_PATH
|
|
20
|
-
from sagemaker_core.
|
|
20
|
+
from sagemaker_core.main.utils import (
|
|
21
21
|
reformat_file_with_black,
|
|
22
22
|
convert_to_snake_case,
|
|
23
23
|
snake_to_pascal,
|
|
@@ -35,6 +35,7 @@ Raises:
|
|
|
35
35
|
CREATE_METHOD_TEMPLATE = """
|
|
36
36
|
@classmethod
|
|
37
37
|
@populate_inputs_decorator
|
|
38
|
+
@Base.add_validate_call
|
|
38
39
|
def create(
|
|
39
40
|
cls,
|
|
40
41
|
{create_args}
|
|
@@ -42,7 +43,7 @@ def create(
|
|
|
42
43
|
region: Optional[str] = None,
|
|
43
44
|
) -> Optional["{resource_name}"]:
|
|
44
45
|
{docstring}
|
|
45
|
-
logger.
|
|
46
|
+
logger.info("Creating {resource_lower} resource.")
|
|
46
47
|
client = Base.get_sagemaker_client(session=session, region_name=region, service_name='{service_name}')
|
|
47
48
|
|
|
48
49
|
operation_input_args = {{
|
|
@@ -53,7 +54,7 @@ def create(
|
|
|
53
54
|
|
|
54
55
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
55
56
|
# serialize the input request
|
|
56
|
-
operation_input_args =
|
|
57
|
+
operation_input_args = serialize(operation_input_args)
|
|
57
58
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
58
59
|
|
|
59
60
|
# create the resource
|
|
@@ -65,6 +66,7 @@ def create(
|
|
|
65
66
|
|
|
66
67
|
CREATE_METHOD_TEMPLATE_WITHOUT_DEFAULTS = """
|
|
67
68
|
@classmethod
|
|
69
|
+
@Base.add_validate_call
|
|
68
70
|
def create(
|
|
69
71
|
cls,
|
|
70
72
|
{create_args}
|
|
@@ -72,7 +74,7 @@ def create(
|
|
|
72
74
|
region: Optional[str] = None,
|
|
73
75
|
) -> Optional["{resource_name}"]:
|
|
74
76
|
{docstring}
|
|
75
|
-
logger.
|
|
77
|
+
logger.info("Creating {resource_lower} resource.")
|
|
76
78
|
client =Base.get_sagemaker_client(session=session, region_name=region, service_name='{service_name}')
|
|
77
79
|
|
|
78
80
|
operation_input_args = {{
|
|
@@ -83,7 +85,7 @@ def create(
|
|
|
83
85
|
|
|
84
86
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
85
87
|
# serialize the input request
|
|
86
|
-
operation_input_args =
|
|
88
|
+
operation_input_args = serialize(operation_input_args)
|
|
87
89
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
88
90
|
|
|
89
91
|
# create the resource
|
|
@@ -95,6 +97,7 @@ def create(
|
|
|
95
97
|
|
|
96
98
|
IMPORT_METHOD_TEMPLATE = """
|
|
97
99
|
@classmethod
|
|
100
|
+
@Base.add_validate_call
|
|
98
101
|
def load(
|
|
99
102
|
cls,
|
|
100
103
|
{import_args}
|
|
@@ -102,7 +105,7 @@ def load(
|
|
|
102
105
|
region: Optional[str] = None,
|
|
103
106
|
) -> Optional["{resource_name}"]:
|
|
104
107
|
{docstring}
|
|
105
|
-
logger.
|
|
108
|
+
logger.info(f"Importing {resource_lower} resource.")
|
|
106
109
|
client = SageMakerClient(session=session, region_name=region, service_name='{service_name}').client
|
|
107
110
|
|
|
108
111
|
operation_input_args = {{
|
|
@@ -111,7 +114,7 @@ def load(
|
|
|
111
114
|
|
|
112
115
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
113
116
|
# serialize the input request
|
|
114
|
-
operation_input_args =
|
|
117
|
+
operation_input_args = serialize(operation_input_args)
|
|
115
118
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
116
119
|
|
|
117
120
|
# import the resource
|
|
@@ -142,12 +145,13 @@ def get_name(self) -> str:
|
|
|
142
145
|
|
|
143
146
|
UPDATE_METHOD_TEMPLATE = """
|
|
144
147
|
@populate_inputs_decorator
|
|
148
|
+
@Base.add_validate_call
|
|
145
149
|
def update(
|
|
146
150
|
self,
|
|
147
151
|
{update_args}
|
|
148
152
|
) -> Optional["{resource_name}"]:
|
|
149
153
|
{docstring}
|
|
150
|
-
logger.
|
|
154
|
+
logger.info("Updating {resource_lower} resource.")
|
|
151
155
|
client = Base.get_sagemaker_client()
|
|
152
156
|
|
|
153
157
|
operation_input_args = {{
|
|
@@ -155,7 +159,7 @@ def update(
|
|
|
155
159
|
}}
|
|
156
160
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
157
161
|
# serialize the input request
|
|
158
|
-
operation_input_args =
|
|
162
|
+
operation_input_args = serialize(operation_input_args)
|
|
159
163
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
160
164
|
|
|
161
165
|
# create the resource
|
|
@@ -168,12 +172,13 @@ def update(
|
|
|
168
172
|
|
|
169
173
|
|
|
170
174
|
UPDATE_METHOD_TEMPLATE_WITHOUT_DECORATOR = """
|
|
175
|
+
@Base.add_validate_call
|
|
171
176
|
def update(
|
|
172
177
|
self,
|
|
173
178
|
{update_args}
|
|
174
179
|
) -> Optional["{resource_name}"]:
|
|
175
180
|
{docstring}
|
|
176
|
-
logger.
|
|
181
|
+
logger.info("Updating {resource_lower} resource.")
|
|
177
182
|
client = Base.get_sagemaker_client()
|
|
178
183
|
|
|
179
184
|
operation_input_args = {{
|
|
@@ -181,7 +186,7 @@ def update(
|
|
|
181
186
|
}}
|
|
182
187
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
183
188
|
# serialize the input request
|
|
184
|
-
operation_input_args =
|
|
189
|
+
operation_input_args = serialize(operation_input_args)
|
|
185
190
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
186
191
|
|
|
187
192
|
# create the resource
|
|
@@ -193,18 +198,19 @@ def update(
|
|
|
193
198
|
"""
|
|
194
199
|
|
|
195
200
|
INVOKE_METHOD_TEMPLATE = """
|
|
201
|
+
@Base.add_validate_call
|
|
196
202
|
def invoke(self,
|
|
197
203
|
{invoke_args}
|
|
198
204
|
) -> Optional[object]:
|
|
199
205
|
{docstring}
|
|
200
|
-
logger.
|
|
206
|
+
logger.info(f"Invoking {resource_lower} resource.")
|
|
201
207
|
client = SageMakerRuntimeClient(service_name="{service_name}").client
|
|
202
208
|
operation_input_args = {{
|
|
203
209
|
{operation_input_args}
|
|
204
210
|
}}
|
|
205
211
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
206
212
|
# serialize the input request
|
|
207
|
-
operation_input_args =
|
|
213
|
+
operation_input_args = serialize(operation_input_args)
|
|
208
214
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
209
215
|
|
|
210
216
|
# create the resource
|
|
@@ -215,11 +221,12 @@ def invoke(self,
|
|
|
215
221
|
"""
|
|
216
222
|
|
|
217
223
|
INVOKE_ASYNC_METHOD_TEMPLATE = """
|
|
224
|
+
@Base.add_validate_call
|
|
218
225
|
def invoke_async(self,
|
|
219
226
|
{create_args}
|
|
220
227
|
) -> Optional[object]:
|
|
221
228
|
{docstring}
|
|
222
|
-
logger.
|
|
229
|
+
logger.info(f"Invoking {resource_lower} resource Async.")
|
|
223
230
|
client = SageMakerRuntimeClient(service_name="{service_name}").client
|
|
224
231
|
|
|
225
232
|
operation_input_args = {{
|
|
@@ -227,7 +234,7 @@ def invoke_async(self,
|
|
|
227
234
|
}}
|
|
228
235
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
229
236
|
# serialize the input request
|
|
230
|
-
operation_input_args =
|
|
237
|
+
operation_input_args = serialize(operation_input_args)
|
|
231
238
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
232
239
|
|
|
233
240
|
# create the resource
|
|
@@ -238,11 +245,12 @@ def invoke_async(self,
|
|
|
238
245
|
"""
|
|
239
246
|
|
|
240
247
|
INVOKE_WITH_RESPONSE_STREAM_METHOD_TEMPLATE = """
|
|
248
|
+
@Base.add_validate_call
|
|
241
249
|
def invoke_with_response_stream(self,
|
|
242
250
|
{create_args}
|
|
243
251
|
) -> Optional[object]:
|
|
244
252
|
{docstring}
|
|
245
|
-
logger.
|
|
253
|
+
logger.info(f"Invoking {resource_lower} resource with Response Stream.")
|
|
246
254
|
client = SageMakerRuntimeClient(service_name="{service_name}").client
|
|
247
255
|
|
|
248
256
|
operation_input_args = {{
|
|
@@ -250,7 +258,7 @@ def invoke_with_response_stream(self,
|
|
|
250
258
|
}}
|
|
251
259
|
logger.debug(f"Input request: {{operation_input_args}}")
|
|
252
260
|
# serialize the input request
|
|
253
|
-
operation_input_args =
|
|
261
|
+
operation_input_args = serialize(operation_input_args)
|
|
254
262
|
logger.debug(f"Serialized input request: {{operation_input_args}}")
|
|
255
263
|
|
|
256
264
|
# create the resource
|
|
@@ -260,7 +268,6 @@ def invoke_with_response_stream(self,
|
|
|
260
268
|
return response
|
|
261
269
|
"""
|
|
262
270
|
|
|
263
|
-
|
|
264
271
|
POPULATE_DEFAULTS_DECORATOR_TEMPLATE = """
|
|
265
272
|
def populate_inputs_decorator(create_func):
|
|
266
273
|
@functools.wraps(create_func)
|
|
@@ -273,6 +280,7 @@ def populate_inputs_decorator(create_func):
|
|
|
273
280
|
|
|
274
281
|
GET_METHOD_TEMPLATE = """
|
|
275
282
|
@classmethod
|
|
283
|
+
@Base.add_validate_call
|
|
276
284
|
def get(
|
|
277
285
|
cls,
|
|
278
286
|
{describe_args}
|
|
@@ -286,7 +294,7 @@ def get(
|
|
|
286
294
|
client = Base.get_sagemaker_client(session=session, region_name=region, service_name='{service_name}')
|
|
287
295
|
response = client.{operation}(**operation_input_args)
|
|
288
296
|
|
|
289
|
-
|
|
297
|
+
logger.debug(response)
|
|
290
298
|
|
|
291
299
|
# deserialize the response
|
|
292
300
|
transformed_response = transform(response, '{describe_operation_output_shape}')
|
|
@@ -295,6 +303,7 @@ def get(
|
|
|
295
303
|
"""
|
|
296
304
|
|
|
297
305
|
REFRESH_METHOD_TEMPLATE = """
|
|
306
|
+
@Base.add_validate_call
|
|
298
307
|
def refresh(
|
|
299
308
|
self,
|
|
300
309
|
{refresh_args}
|
|
@@ -317,6 +326,7 @@ if "failed" in current_status.lower():
|
|
|
317
326
|
"""
|
|
318
327
|
|
|
319
328
|
WAIT_METHOD_TEMPLATE = '''
|
|
329
|
+
@Base.add_validate_call
|
|
320
330
|
def wait(
|
|
321
331
|
self,
|
|
322
332
|
poll: int = 5,
|
|
@@ -338,25 +348,34 @@ def wait(
|
|
|
338
348
|
terminal_states = {terminal_resource_states}
|
|
339
349
|
start_time = time.time()
|
|
340
350
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
351
|
+
progress = Progress(SpinnerColumn("bouncingBar"),
|
|
352
|
+
TextColumn("{{task.description}}"),
|
|
353
|
+
TimeElapsedColumn(),
|
|
354
|
+
)
|
|
355
|
+
progress.add_task("Waiting for {resource_name}...")
|
|
356
|
+
status = Status("Current status:")
|
|
357
|
+
|
|
358
|
+
with Live(Panel(Group(progress, status), title="Wait Log Panel", border_style=Style(color=Color.BLUE.value))):
|
|
359
|
+
while True:
|
|
360
|
+
self.refresh()
|
|
361
|
+
current_status = self{status_key_path}
|
|
362
|
+
status.update(f"Current status: [bold]{{current_status}}")
|
|
344
363
|
|
|
345
|
-
|
|
346
|
-
|
|
364
|
+
if current_status in terminal_states:
|
|
365
|
+
logger.info(f"Final Resource Status: [bold]{{current_status}}")
|
|
347
366
|
{failed_error_block}
|
|
348
|
-
|
|
367
|
+
return
|
|
349
368
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
time.sleep(poll)
|
|
369
|
+
if timeout is not None and time.time() - start_time >= timeout:
|
|
370
|
+
raise TimeoutExceededError(resouce_type="{resource_name}", status=current_status)
|
|
371
|
+
time.sleep(poll)
|
|
354
372
|
'''
|
|
355
373
|
|
|
356
374
|
WAIT_FOR_STATUS_METHOD_TEMPLATE = '''
|
|
375
|
+
@Base.add_validate_call
|
|
357
376
|
def wait_for_status(
|
|
358
377
|
self,
|
|
359
|
-
|
|
378
|
+
target_status: Literal{resource_states},
|
|
360
379
|
poll: int = 5,
|
|
361
380
|
timeout: Optional[int] = None
|
|
362
381
|
) -> None:
|
|
@@ -364,7 +383,7 @@ def wait_for_status(
|
|
|
364
383
|
Wait for a {resource_name} resource to reach certain status.
|
|
365
384
|
|
|
366
385
|
Parameters:
|
|
367
|
-
|
|
386
|
+
target_status: The status to wait for.
|
|
368
387
|
poll: The number of seconds to wait between each poll.
|
|
369
388
|
timeout: The maximum number of seconds to wait before timing out.
|
|
370
389
|
|
|
@@ -375,21 +394,30 @@ def wait_for_status(
|
|
|
375
394
|
"""
|
|
376
395
|
start_time = time.time()
|
|
377
396
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
397
|
+
progress = Progress(SpinnerColumn("bouncingBar"),
|
|
398
|
+
TextColumn("{{task.description}}"),
|
|
399
|
+
TimeElapsedColumn(),
|
|
400
|
+
)
|
|
401
|
+
progress.add_task(f"Waiting for {resource_name} to reach [bold]{{target_status}} status...")
|
|
402
|
+
status = Status("Current status:")
|
|
403
|
+
|
|
404
|
+
with Live(Panel(Group(progress, status), title="Wait Log Panel", border_style=Style(color=Color.BLUE.value))):
|
|
405
|
+
while True:
|
|
406
|
+
self.refresh()
|
|
407
|
+
current_status = self{status_key_path}
|
|
408
|
+
status.update(f"Current status: [bold]{{current_status}}")
|
|
381
409
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
410
|
+
if target_status == current_status:
|
|
411
|
+
logger.info(f"Final Resource Status: [bold]{{current_status}}")
|
|
412
|
+
return
|
|
385
413
|
{failed_error_block}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
time.sleep(poll)
|
|
414
|
+
if timeout is not None and time.time() - start_time >= timeout:
|
|
415
|
+
raise TimeoutExceededError(resouce_type="{resource_name}", status=current_status)
|
|
416
|
+
time.sleep(poll)
|
|
390
417
|
'''
|
|
391
418
|
|
|
392
419
|
WAIT_FOR_DELETE_METHOD_TEMPLATE = '''
|
|
420
|
+
@Base.add_validate_call
|
|
393
421
|
def wait_for_delete(
|
|
394
422
|
self,
|
|
395
423
|
poll: int = 5,
|
|
@@ -418,25 +446,32 @@ def wait_for_delete(
|
|
|
418
446
|
"""
|
|
419
447
|
start_time = time.time()
|
|
420
448
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
449
|
+
progress = Progress(SpinnerColumn("bouncingBar"),
|
|
450
|
+
TextColumn("{{task.description}}"),
|
|
451
|
+
TimeElapsedColumn(),
|
|
452
|
+
)
|
|
453
|
+
progress.add_task("Waiting for {resource_name} to be deleted...")
|
|
454
|
+
status = Status("Current status:")
|
|
455
|
+
|
|
456
|
+
with Live(Panel(Group(progress, status), title="Wait Log Panel", border_style=Style(color=Color.BLUE.value))):
|
|
457
|
+
while True:
|
|
458
|
+
try:
|
|
459
|
+
self.refresh()
|
|
460
|
+
current_status = self{status_key_path}
|
|
461
|
+
status.update(f"Current status: [bold]{{current_status}}")
|
|
425
462
|
{delete_failed_error_block}
|
|
426
463
|
{deleted_status_check}
|
|
427
464
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
print("-", end="")
|
|
439
|
-
time.sleep(poll)
|
|
465
|
+
if timeout is not None and time.time() - start_time >= timeout:
|
|
466
|
+
raise TimeoutExceededError(resouce_type="{resource_name}", status=current_status)
|
|
467
|
+
except botocore.exceptions.ClientError as e:
|
|
468
|
+
error_code = e.response["Error"]["Code"]
|
|
469
|
+
|
|
470
|
+
if "ResourceNotFound" in error_code or "ValidationException" in error_code:
|
|
471
|
+
logger.info("Resource was not found. It may have been deleted.")
|
|
472
|
+
return
|
|
473
|
+
raise e
|
|
474
|
+
time.sleep(poll)
|
|
440
475
|
'''
|
|
441
476
|
|
|
442
477
|
DELETE_FAILED_STATUS_CHECK = """
|
|
@@ -451,6 +486,7 @@ if current_status.lower() == "deleted":
|
|
|
451
486
|
"""
|
|
452
487
|
|
|
453
488
|
DELETE_METHOD_TEMPLATE = """
|
|
489
|
+
@Base.add_validate_call
|
|
454
490
|
def delete(
|
|
455
491
|
self,
|
|
456
492
|
{delete_args}
|
|
@@ -467,6 +503,7 @@ def delete(
|
|
|
467
503
|
"""
|
|
468
504
|
|
|
469
505
|
STOP_METHOD_TEMPLATE = """
|
|
506
|
+
@Base.add_validate_call
|
|
470
507
|
def stop(self) -> None:
|
|
471
508
|
{docstring}
|
|
472
509
|
client = SageMakerClient().client
|
|
@@ -475,10 +512,13 @@ def stop(self) -> None:
|
|
|
475
512
|
{operation_input_args}
|
|
476
513
|
}}
|
|
477
514
|
client.{operation}(**operation_input_args)
|
|
515
|
+
|
|
516
|
+
logger.info(f"Stopping {{self.__class__.__name__}} - {{self.get_name()}}")
|
|
478
517
|
"""
|
|
479
518
|
|
|
480
519
|
GET_ALL_METHOD_WITH_ARGS_TEMPLATE = """
|
|
481
520
|
@classmethod
|
|
521
|
+
@Base.add_validate_call
|
|
482
522
|
def get_all(
|
|
483
523
|
cls,
|
|
484
524
|
{get_all_args}
|
|
@@ -501,6 +541,7 @@ def get_all(
|
|
|
501
541
|
|
|
502
542
|
GET_ALL_METHOD_NO_ARGS_TEMPLATE = '''
|
|
503
543
|
@classmethod
|
|
544
|
+
@Base.add_validate_call
|
|
504
545
|
def get_all(
|
|
505
546
|
cls,
|
|
506
547
|
session: Optional[Session] = None,
|
|
@@ -526,6 +567,7 @@ def get_all(
|
|
|
526
567
|
|
|
527
568
|
GENERIC_METHOD_TEMPLATE = """
|
|
528
569
|
{decorator}
|
|
570
|
+
@Base.add_validate_call
|
|
529
571
|
def {method_name}(
|
|
530
572
|
{method_args}
|
|
531
573
|
) -> {return_type}:
|
|
@@ -586,44 +628,6 @@ class Base(BaseModel):
|
|
|
586
628
|
def get_sagemaker_client(cls, session = None, region_name = None, service_name = 'sagemaker'):
|
|
587
629
|
return SageMakerClient(session=session, region_name=region_name, service_name=service_name).client
|
|
588
630
|
|
|
589
|
-
@classmethod
|
|
590
|
-
def _serialize_args(cls, value: dict) -> dict:
|
|
591
|
-
serialized_dict = {}
|
|
592
|
-
for k, v in value.items():
|
|
593
|
-
if serialize_result := cls._serialize(v):
|
|
594
|
-
serialized_dict.update({k: serialize_result})
|
|
595
|
-
return serialized_dict
|
|
596
|
-
|
|
597
|
-
@classmethod
|
|
598
|
-
def _serialize(cls, value: any) -> any:
|
|
599
|
-
if isinstance(value, Unassigned):
|
|
600
|
-
return None
|
|
601
|
-
elif isinstance(value, List):
|
|
602
|
-
return cls._serialize_list(value)
|
|
603
|
-
elif is_not_primitive(value) and not isinstance(value, dict):
|
|
604
|
-
return cls._serialize_object(value)
|
|
605
|
-
elif hasattr(value, "serialize"):
|
|
606
|
-
return value.serialize()
|
|
607
|
-
else:
|
|
608
|
-
return value
|
|
609
|
-
|
|
610
|
-
@classmethod
|
|
611
|
-
def _serialize_list(cls, value: List):
|
|
612
|
-
serialized_list = []
|
|
613
|
-
for v in value:
|
|
614
|
-
if serialize_result := cls._serialize(v):
|
|
615
|
-
serialized_list.append(serialize_result)
|
|
616
|
-
return serialized_list
|
|
617
|
-
|
|
618
|
-
@classmethod
|
|
619
|
-
def _serialize_object(cls, value: any):
|
|
620
|
-
serialized_dict = {}
|
|
621
|
-
for k, v in vars(value).items():
|
|
622
|
-
if serialize_result := cls._serialize(v):
|
|
623
|
-
key = snake_to_pascal(k) if is_snake_case(k) else k
|
|
624
|
-
serialized_dict.update({key[0].upper() + key[1:]: serialize_result})
|
|
625
|
-
return serialized_dict
|
|
626
|
-
|
|
627
631
|
@staticmethod
|
|
628
632
|
def get_updated_kwargs_with_configured_attributes(
|
|
629
633
|
config_schema_for_resource: dict, resource_name: str, **kwargs
|
|
@@ -644,7 +648,7 @@ class Base(BaseModel):
|
|
|
644
648
|
class_object = globals()[resource_name]
|
|
645
649
|
kwargs[configurable_attribute] = class_object(**config_value)
|
|
646
650
|
except BaseException as e:
|
|
647
|
-
logger.
|
|
651
|
+
logger.debug("Could not load Default Configs. Continuing.", exc_info=True)
|
|
648
652
|
# Continue with existing kwargs if no default configs found
|
|
649
653
|
return kwargs
|
|
650
654
|
|
|
@@ -685,7 +689,7 @@ class Base(BaseModel):
|
|
|
685
689
|
return updated_args
|
|
686
690
|
|
|
687
691
|
@staticmethod
|
|
688
|
-
def _get_chained_attribute(item_value:
|
|
692
|
+
def _get_chained_attribute(item_value: Any):
|
|
689
693
|
resource_name = type(item_value).__name__
|
|
690
694
|
class_object = globals()[resource_name]
|
|
691
695
|
return class_object(**Base.populate_chained_attributes(
|
|
@@ -693,42 +697,25 @@ class Base(BaseModel):
|
|
|
693
697
|
operation_input_args=vars(item_value)
|
|
694
698
|
))
|
|
695
699
|
|
|
696
|
-
|
|
700
|
+
@staticmethod
|
|
701
|
+
def add_validate_call(func):
|
|
702
|
+
@functools.wraps(func)
|
|
703
|
+
def wrapper(*args, **kwargs):
|
|
704
|
+
config = dict(arbitrary_types_allowed=True)
|
|
705
|
+
return validate_call(config=config)(func)(*args, **kwargs)
|
|
706
|
+
return wrapper
|
|
707
|
+
|
|
697
708
|
"""
|
|
698
709
|
|
|
699
710
|
SHAPE_BASE_CLASS_TEMPLATE = """
|
|
700
711
|
class {class_name}:
|
|
701
712
|
model_config = ConfigDict(protected_namespaces=(), validate_assignment=True)
|
|
702
|
-
|
|
703
|
-
def serialize(self):
|
|
704
|
-
result = {{}}
|
|
705
|
-
for attr, value in self.__dict__.items():
|
|
706
|
-
if isinstance(value, Unassigned):
|
|
707
|
-
continue
|
|
708
|
-
|
|
709
|
-
components = attr.split('_')
|
|
710
|
-
pascal_attr = ''.join(x.title() for x in components[0:])
|
|
711
|
-
if isinstance(value, List):
|
|
712
|
-
result[pascal_attr] = self._serialize_list(value)
|
|
713
|
-
elif isinstance(value, Dict):
|
|
714
|
-
result[pascal_attr] = self._serialize_dict(value)
|
|
715
|
-
elif hasattr(value, 'serialize'):
|
|
716
|
-
result[pascal_attr] = value.serialize()
|
|
717
|
-
else:
|
|
718
|
-
result[pascal_attr] = value
|
|
719
|
-
return result
|
|
720
|
-
|
|
721
|
-
def _serialize_list(self, value: List):
|
|
722
|
-
return [v.serialize() if hasattr(v, 'serialize') else v for v in value]
|
|
723
|
-
|
|
724
|
-
def _serialize_dict(self, value: Dict):
|
|
725
|
-
return {{k: v.serialize() if hasattr(v, 'serialize') else v for k, v in value.items()}}
|
|
726
713
|
"""
|
|
727
714
|
|
|
728
715
|
SHAPE_CLASS_TEMPLATE = '''
|
|
729
716
|
class {class_name}:
|
|
730
717
|
"""
|
|
731
|
-
|
|
718
|
+
{docstring}
|
|
732
719
|
"""
|
|
733
720
|
{data_class_members}
|
|
734
721
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sagemaker-core
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: An python package for sagemaker core functionalities
|
|
5
|
+
Author-email: AWS <sagemaker-interests@amazon.com>
|
|
6
|
+
Project-URL: Repository, https://github.com/aws/sagemaker-core.git
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/x-rst
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: boto3 <2.0.0,>=1.34.0
|
|
19
|
+
Requires-Dist: pydantic <3.0.0,>=1.7.0
|
|
20
|
+
Requires-Dist: PyYAML <7.0,>=6.0
|
|
21
|
+
Requires-Dist: jsonschema <5.0.0
|
|
22
|
+
Requires-Dist: platformdirs <5.0.0,>=4.0.0
|
|
23
|
+
Requires-Dist: rich <14.0.0,>=13.0.0
|
|
24
|
+
Requires-Dist: mock <5.0,>4.0
|
|
25
|
+
Requires-Dist: importlib-metadata <7.0,>=1.4.0
|
|
26
|
+
Provides-Extra: codegen
|
|
27
|
+
Requires-Dist: black <25.0.0,>=24.3.0 ; extra == 'codegen'
|
|
28
|
+
Requires-Dist: pandas <3.0.0,>=2.0.0 ; extra == 'codegen'
|
|
29
|
+
Requires-Dist: pytest <9.0.0,>=8.0.0 ; extra == 'codegen'
|
|
30
|
+
Requires-Dist: pylint <4.0.0,>=3.0.0 ; extra == 'codegen'
|
|
31
|
+
|
|
32
|
+
.. image:: https://github.com/aws/sagemaker-python-sdk/raw/master/branding/icon/sagemaker-banner.png
|
|
33
|
+
:height: 100px
|
|
34
|
+
:alt: SageMaker
|
|
35
|
+
|
|
36
|
+
====================
|
|
37
|
+
SageMaker Core
|
|
38
|
+
====================
|
|
39
|
+
|
|
40
|
+
.. image:: https://img.shields.io/pypi/v/sagemaker-core.svg
|
|
41
|
+
:target: https://pypi.python.org/pypi/sagemaker-core
|
|
42
|
+
:alt: Latest Version
|
|
43
|
+
|
|
44
|
+
.. image:: https://img.shields.io/pypi/pyversions/sagemaker-core.svg
|
|
45
|
+
:target: https://pypi.python.org/pypi/sagemaker-core
|
|
46
|
+
:alt: Supported Python Versions
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Introduction
|
|
51
|
+
------------
|
|
52
|
+
|
|
53
|
+
Welcome to the sagemaker-core Python SDK, an SDK designed to provide an object-oriented interface for interacting with Amazon SageMaker resources. It offers full parity with SageMaker APIs, allowing developers to leverage all SageMaker capabilities directly through the SDK. sagemaker-core introduces features such as dedicated resource classes, resource chaining, auto code completion, comprehensive documentation and type hints to enhance the developer experience as well as productivity.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
Key Features
|
|
57
|
+
------------
|
|
58
|
+
|
|
59
|
+
* **Object-Oriented Interface**: Provides a structured way to interact with SageMaker resources, making it easier to manage them using familiar object-oriented programming techniques.
|
|
60
|
+
* **Resource Chaining**: Allows seamless connection of SageMaker resources by passing outputs as inputs between them, simplifying workflows and reducing the complexity of parameter management.
|
|
61
|
+
* **Full Parity with SageMaker APIs**: Ensures access to all SageMaker capabilities through the SDK, providing a comprehensive toolset for building and deploying machine learning models.
|
|
62
|
+
* **Abstraction of Low-Level Details**: Automatically handles resource state transitions and polling logic, freeing developers from managing these intricacies and allowing them to focus on higher-level tasks.
|
|
63
|
+
* **Auto Code Completion**: Enhances the developer experience by offering real-time suggestions and completions in popular IDEs, reducing syntax errors and speeding up the coding process.
|
|
64
|
+
* **Comprehensive Documentation and Type Hints**: Provides detailed guidance and type hints to help developers understand functionalities, write code faster, and reduce errors without complex API navigation.
|
|
65
|
+
* **Incorporation of Intelligent Defaults**: Integrates the previous SageMaker SDK feature of intelligent defaults, allowing developers to set default values for parameters like IAM roles and VPC configurations. This streamlines the setup process, enabling developers to focus on customizations specific to their use case.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Benefits
|
|
69
|
+
--------
|
|
70
|
+
|
|
71
|
+
* **Simplified Development**: By abstracting low-level details and providing intelligent defaults, developers can focus on building and deploying machine learning models without getting bogged down by repetitive tasks.
|
|
72
|
+
* **Increased Productivity**: The SDK's features, such as auto code completion and type hints, help developers write code faster and with fewer errors.
|
|
73
|
+
* **Enhanced Readability**: Resource chaining and dedicated resource classes result in more readable and maintainable code.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
Docs and Examples
|
|
77
|
+
-----------------
|
|
78
|
+
|
|
79
|
+
For examples and walkthroughs, see the `SageMaker Core Examples <https://github.com/aws/amazon-sagemaker-examples/tree/default/sagemaker-core>`_.
|
|
80
|
+
|
|
81
|
+
For detailed documentation, including the API reference, see `Read the Docs <https://sagemaker-core.readthedocs.io>`_.
|