sagemaker-core 1.0.62__py3-none-any.whl → 2.1.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.
Files changed (362) hide show
  1. sagemaker/core/__init__.py +16 -0
  2. sagemaker/core/_studio.py +116 -0
  3. sagemaker/core/_version.py +11 -0
  4. sagemaker/core/accept_types.py +131 -0
  5. sagemaker/core/analytics.py +744 -0
  6. sagemaker/core/apiutils/__init__.py +13 -0
  7. sagemaker/core/apiutils/_base_types.py +228 -0
  8. sagemaker/core/apiutils/_boto_functions.py +130 -0
  9. sagemaker/core/apiutils/_utils.py +34 -0
  10. sagemaker/core/base_deserializers.py +35 -0
  11. sagemaker/core/base_serializers.py +35 -0
  12. sagemaker/core/clarify/__init__.py +2898 -0
  13. sagemaker/core/collection.py +467 -0
  14. sagemaker/core/common_utils.py +2281 -0
  15. sagemaker/core/compute_resource_requirements/__init__.py +18 -0
  16. sagemaker/core/compute_resource_requirements/resource_requirements.py +94 -0
  17. sagemaker/core/config/__init__.py +181 -0
  18. sagemaker/core/config/config.py +238 -0
  19. sagemaker/core/config/config_manager.py +595 -0
  20. sagemaker/core/config/config_schema.py +1220 -0
  21. sagemaker/core/config/config_utils.py +297 -0
  22. {sagemaker_core/main → sagemaker/core}/config_schema.py +408 -3
  23. sagemaker/core/constants.py +73 -0
  24. sagemaker/core/content_types.py +137 -0
  25. sagemaker/core/debugger/__init__.py +39 -0
  26. sagemaker/core/debugger/debugger.py +945 -0
  27. sagemaker/core/debugger/framework_profile.py +292 -0
  28. sagemaker/core/debugger/metrics_config.py +468 -0
  29. sagemaker/core/debugger/profiler.py +42 -0
  30. sagemaker/core/debugger/profiler_config.py +190 -0
  31. sagemaker/core/debugger/profiler_constants.py +40 -0
  32. sagemaker/core/debugger/utils.py +148 -0
  33. sagemaker/core/deprecations.py +254 -0
  34. sagemaker/core/deserializers/__init__.py +10 -0
  35. sagemaker/core/deserializers/base.py +424 -0
  36. sagemaker/core/deserializers/implementations.py +157 -0
  37. sagemaker/core/drift_check_baselines.py +106 -0
  38. sagemaker/core/enums.py +51 -0
  39. sagemaker/core/environment_variables.py +101 -0
  40. sagemaker/core/exceptions.py +108 -0
  41. sagemaker/core/experiments/__init__.py +53 -0
  42. sagemaker/core/experiments/_api_types.py +251 -0
  43. sagemaker/core/experiments/_environment.py +124 -0
  44. sagemaker/core/experiments/_helper.py +294 -0
  45. sagemaker/core/experiments/_metrics.py +333 -0
  46. sagemaker/core/experiments/_run_context.py +58 -0
  47. sagemaker/core/experiments/_utils.py +216 -0
  48. sagemaker/core/experiments/experiment.py +244 -0
  49. sagemaker/core/experiments/run.py +970 -0
  50. sagemaker/core/experiments/trial.py +296 -0
  51. sagemaker/core/experiments/trial_component.py +387 -0
  52. sagemaker/core/explainer/__init__.py +24 -0
  53. sagemaker/core/explainer/clarify_explainer_config.py +298 -0
  54. sagemaker/core/explainer/explainer_config.py +44 -0
  55. sagemaker/core/fw_utils.py +1176 -0
  56. sagemaker/core/git_utils.py +349 -0
  57. sagemaker/core/helper/pipeline_variable.py +82 -0
  58. sagemaker/core/helper/session_helper.py +2965 -0
  59. sagemaker/core/huggingface/__init__.py +29 -0
  60. sagemaker/core/huggingface/llm_utils.py +150 -0
  61. sagemaker/core/huggingface/processing.py +139 -0
  62. sagemaker/core/huggingface/training_compiler/config.py +167 -0
  63. sagemaker/core/hyperparameters.py +172 -0
  64. sagemaker/core/image_retriever/__init__.py +3 -0
  65. sagemaker/core/image_retriever/image_retriever.py +640 -0
  66. sagemaker/core/image_retriever/image_retriever_utils.py +511 -0
  67. sagemaker/core/image_retriever/test.py +7 -0
  68. sagemaker/core/image_uri_config/__init__.py +13 -0
  69. sagemaker/core/image_uri_config/autogluon.json +1335 -0
  70. sagemaker/core/image_uri_config/blazingtext.json +50 -0
  71. sagemaker/core/image_uri_config/chainer.json +104 -0
  72. sagemaker/core/image_uri_config/clarify.json +39 -0
  73. sagemaker/core/image_uri_config/coach-mxnet.json +70 -0
  74. sagemaker/core/image_uri_config/coach-tensorflow.json +186 -0
  75. sagemaker/core/image_uri_config/data-wrangler.json +91 -0
  76. sagemaker/core/image_uri_config/debugger.json +34 -0
  77. sagemaker/core/image_uri_config/detailed-profiler.json +18 -0
  78. sagemaker/core/image_uri_config/djl-deepspeed.json +385 -0
  79. sagemaker/core/image_uri_config/djl-fastertransformer.json +167 -0
  80. sagemaker/core/image_uri_config/djl-lmi.json +136 -0
  81. sagemaker/core/image_uri_config/djl-neuronx.json +258 -0
  82. sagemaker/core/image_uri_config/djl-tensorrtllm.json +262 -0
  83. sagemaker/core/image_uri_config/factorization-machines.json +50 -0
  84. sagemaker/core/image_uri_config/forecasting-deepar.json +50 -0
  85. sagemaker/core/image_uri_config/huggingface-llm-neuronx.json +660 -0
  86. sagemaker/core/image_uri_config/huggingface-llm.json +1158 -0
  87. sagemaker/core/image_uri_config/huggingface-neuron.json +52 -0
  88. sagemaker/core/image_uri_config/huggingface-neuronx.json +510 -0
  89. sagemaker/core/image_uri_config/huggingface-tei-cpu.json +298 -0
  90. sagemaker/core/image_uri_config/huggingface-tei.json +298 -0
  91. sagemaker/core/image_uri_config/huggingface-training-compiler.json +195 -0
  92. sagemaker/core/image_uri_config/huggingface.json +2138 -0
  93. sagemaker/core/image_uri_config/hyperpod-recipes-neuron.json +52 -0
  94. sagemaker/core/image_uri_config/image-classification-neo.json +43 -0
  95. sagemaker/core/image_uri_config/image-classification.json +50 -0
  96. sagemaker/core/image_uri_config/inferentia-mxnet.json +88 -0
  97. sagemaker/core/image_uri_config/inferentia-pytorch.json +127 -0
  98. sagemaker/core/image_uri_config/inferentia-tensorflow.json +88 -0
  99. sagemaker/core/image_uri_config/instance_gpu_info.json +782 -0
  100. sagemaker/core/image_uri_config/ipinsights.json +50 -0
  101. sagemaker/core/image_uri_config/kmeans.json +50 -0
  102. sagemaker/core/image_uri_config/knn.json +50 -0
  103. sagemaker/core/image_uri_config/lda.json +26 -0
  104. sagemaker/core/image_uri_config/linear-learner.json +50 -0
  105. sagemaker/core/image_uri_config/model-monitor.json +42 -0
  106. sagemaker/core/image_uri_config/mxnet.json +1154 -0
  107. sagemaker/core/image_uri_config/neo-mxnet.json +64 -0
  108. sagemaker/core/image_uri_config/neo-pytorch.json +341 -0
  109. sagemaker/core/image_uri_config/neo-tensorflow.json +109 -0
  110. sagemaker/core/image_uri_config/ntm.json +50 -0
  111. sagemaker/core/image_uri_config/object-detection.json +50 -0
  112. sagemaker/core/image_uri_config/object2vec.json +50 -0
  113. sagemaker/core/image_uri_config/pca.json +50 -0
  114. sagemaker/core/image_uri_config/pytorch-neuron.json +43 -0
  115. sagemaker/core/image_uri_config/pytorch-smp.json +218 -0
  116. sagemaker/core/image_uri_config/pytorch-training-compiler.json +80 -0
  117. sagemaker/core/image_uri_config/pytorch.json +3101 -0
  118. sagemaker/core/image_uri_config/randomcutforest.json +50 -0
  119. sagemaker/core/image_uri_config/ray-pytorch.json +46 -0
  120. sagemaker/core/image_uri_config/ray-tensorflow.json +194 -0
  121. sagemaker/core/image_uri_config/sagemaker-base-python.json +46 -0
  122. sagemaker/core/image_uri_config/sagemaker-distribution.json +37 -0
  123. sagemaker/core/image_uri_config/sagemaker-geospatial.json +13 -0
  124. sagemaker/core/image_uri_config/sagemaker-tritonserver.json +212 -0
  125. sagemaker/core/image_uri_config/semantic-segmentation.json +50 -0
  126. sagemaker/core/image_uri_config/seq2seq.json +50 -0
  127. sagemaker/core/image_uri_config/sklearn.json +446 -0
  128. sagemaker/core/image_uri_config/spark.json +280 -0
  129. sagemaker/core/image_uri_config/sparkml-serving.json +97 -0
  130. sagemaker/core/image_uri_config/stabilityai.json +53 -0
  131. sagemaker/core/image_uri_config/tensorflow.json +5086 -0
  132. sagemaker/core/image_uri_config/vw.json +25 -0
  133. sagemaker/core/image_uri_config/xgboost-neo.json +43 -0
  134. sagemaker/core/image_uri_config/xgboost.json +888 -0
  135. sagemaker/core/image_uris.py +810 -0
  136. sagemaker/core/inference_config.py +144 -0
  137. sagemaker/core/inference_recommender/__init__.py +18 -0
  138. sagemaker/core/inference_recommender/inference_recommender_mixin.py +622 -0
  139. sagemaker/core/inputs.py +366 -0
  140. sagemaker/core/instance_group.py +61 -0
  141. sagemaker/core/instance_types.py +164 -0
  142. sagemaker/core/instance_types_gpu_info.py +43 -0
  143. sagemaker/core/interactive_apps/__init__.py +41 -0
  144. sagemaker/core/interactive_apps/base_interactive_app.py +204 -0
  145. sagemaker/core/interactive_apps/detail_profiler_app.py +139 -0
  146. sagemaker/core/interactive_apps/tensorboard.py +149 -0
  147. sagemaker/core/iterators.py +186 -0
  148. sagemaker/core/job.py +380 -0
  149. sagemaker/core/jumpstart/__init__.py +156 -0
  150. sagemaker/core/jumpstart/accessors.py +390 -0
  151. sagemaker/core/jumpstart/artifacts/__init__.py +69 -0
  152. sagemaker/core/jumpstart/artifacts/environment_variables.py +252 -0
  153. sagemaker/core/jumpstart/artifacts/hyperparameters.py +120 -0
  154. sagemaker/core/jumpstart/artifacts/image_uris.py +139 -0
  155. sagemaker/core/jumpstart/artifacts/incremental_training.py +87 -0
  156. sagemaker/core/jumpstart/artifacts/instance_types.py +223 -0
  157. sagemaker/core/jumpstart/artifacts/kwargs.py +289 -0
  158. sagemaker/core/jumpstart/artifacts/metric_definitions.py +117 -0
  159. sagemaker/core/jumpstart/artifacts/model_packages.py +202 -0
  160. sagemaker/core/jumpstart/artifacts/model_uris.py +252 -0
  161. sagemaker/core/jumpstart/artifacts/payloads.py +96 -0
  162. sagemaker/core/jumpstart/artifacts/predictors.py +540 -0
  163. sagemaker/core/jumpstart/artifacts/resource_names.py +86 -0
  164. sagemaker/core/jumpstart/artifacts/resource_requirements.py +162 -0
  165. sagemaker/core/jumpstart/artifacts/script_uris.py +172 -0
  166. sagemaker/core/jumpstart/cache.py +663 -0
  167. sagemaker/core/jumpstart/configs.py +50 -0
  168. sagemaker/core/jumpstart/constants.py +198 -0
  169. sagemaker/core/jumpstart/deserializers.py +81 -0
  170. sagemaker/core/jumpstart/document.py +76 -0
  171. sagemaker/core/jumpstart/enums.py +168 -0
  172. sagemaker/core/jumpstart/exceptions.py +236 -0
  173. sagemaker/core/jumpstart/factory/utils.py +833 -0
  174. sagemaker/core/jumpstart/filters.py +597 -0
  175. sagemaker/core/jumpstart/hub/constants.py +16 -0
  176. sagemaker/core/jumpstart/hub/hub.py +291 -0
  177. sagemaker/core/jumpstart/hub/interfaces.py +936 -0
  178. sagemaker/core/jumpstart/hub/parser_utils.py +70 -0
  179. sagemaker/core/jumpstart/hub/parsers.py +288 -0
  180. sagemaker/core/jumpstart/hub/types.py +35 -0
  181. sagemaker/core/jumpstart/hub/utils.py +260 -0
  182. sagemaker/core/jumpstart/models.py +499 -0
  183. sagemaker/core/jumpstart/notebook_utils.py +575 -0
  184. sagemaker/core/jumpstart/parameters.py +20 -0
  185. sagemaker/core/jumpstart/payload_utils.py +239 -0
  186. sagemaker/core/jumpstart/region_config.json +163 -0
  187. sagemaker/core/jumpstart/search.py +171 -0
  188. sagemaker/core/jumpstart/serializers.py +81 -0
  189. sagemaker/core/jumpstart/session_utils.py +234 -0
  190. sagemaker/core/jumpstart/types.py +3044 -0
  191. sagemaker/core/jumpstart/utils.py +1731 -0
  192. sagemaker/core/jumpstart/validators.py +257 -0
  193. sagemaker/core/lambda_helper.py +312 -0
  194. sagemaker/core/lineage/__init__.py +42 -0
  195. sagemaker/core/lineage/_api_types.py +239 -0
  196. sagemaker/core/lineage/_utils.py +49 -0
  197. sagemaker/core/lineage/action.py +345 -0
  198. sagemaker/core/lineage/artifact.py +646 -0
  199. sagemaker/core/lineage/association.py +190 -0
  200. sagemaker/core/lineage/context.py +505 -0
  201. sagemaker/core/lineage/lineage_trial_component.py +191 -0
  202. sagemaker/core/lineage/query.py +732 -0
  203. sagemaker/core/lineage/visualizer.py +346 -0
  204. sagemaker/core/local/__init__.py +18 -0
  205. sagemaker/core/local/data.py +413 -0
  206. sagemaker/core/local/entities.py +678 -0
  207. sagemaker/core/local/exceptions.py +17 -0
  208. sagemaker/core/local/image.py +1243 -0
  209. sagemaker/core/local/local_session.py +739 -0
  210. sagemaker/core/local/utils.py +245 -0
  211. sagemaker/core/logs.py +181 -0
  212. sagemaker/core/metadata_properties.py +56 -0
  213. sagemaker/core/metric_definitions.py +91 -0
  214. sagemaker/core/mlflow/__init__.py +38 -0
  215. sagemaker/core/mlflow/forward_sagemaker_metrics.py +44 -0
  216. sagemaker/core/model_card/__init__.py +26 -0
  217. sagemaker/core/model_life_cycle.py +51 -0
  218. sagemaker/core/model_metrics.py +160 -0
  219. sagemaker/core/model_monitor/__init__.py +66 -0
  220. sagemaker/core/model_monitor/clarify_model_monitoring.py +1495 -0
  221. sagemaker/core/model_monitor/cron_expression_generator.py +82 -0
  222. sagemaker/core/model_monitor/data_capture_config.py +115 -0
  223. sagemaker/core/model_monitor/data_quality_monitoring_config.py +66 -0
  224. sagemaker/core/model_monitor/dataset_format.py +102 -0
  225. sagemaker/core/model_monitor/model_monitoring.py +4266 -0
  226. sagemaker/core/model_monitor/monitoring_alert.py +76 -0
  227. sagemaker/core/model_monitor/monitoring_files.py +506 -0
  228. sagemaker/core/model_monitor/utils.py +793 -0
  229. sagemaker/core/model_registry.py +480 -0
  230. sagemaker/core/model_uris.py +97 -0
  231. sagemaker/core/modules/__init__.py +19 -0
  232. sagemaker/core/modules/configs.py +226 -0
  233. sagemaker/core/modules/constants.py +37 -0
  234. sagemaker/core/modules/distributed.py +182 -0
  235. sagemaker/core/modules/local_core/__init__.py +0 -0
  236. sagemaker/core/modules/local_core/local_container.py +605 -0
  237. sagemaker/core/modules/templates.py +83 -0
  238. sagemaker/core/modules/train/__init__.py +14 -0
  239. sagemaker/core/modules/train/container_drivers/__init__.py +14 -0
  240. sagemaker/core/modules/train/container_drivers/common/__init__.py +14 -0
  241. sagemaker/core/modules/train/container_drivers/common/utils.py +213 -0
  242. sagemaker/core/modules/train/container_drivers/distributed_drivers/__init__.py +14 -0
  243. sagemaker/core/modules/train/container_drivers/distributed_drivers/basic_script_driver.py +81 -0
  244. sagemaker/core/modules/train/container_drivers/distributed_drivers/mpi_driver.py +123 -0
  245. sagemaker/core/modules/train/container_drivers/distributed_drivers/mpi_utils.py +302 -0
  246. sagemaker/core/modules/train/container_drivers/distributed_drivers/torchrun_driver.py +129 -0
  247. sagemaker/core/modules/train/container_drivers/scripts/__init__.py +14 -0
  248. sagemaker/core/modules/train/container_drivers/scripts/environment.py +305 -0
  249. sagemaker/core/modules/train/sm_recipes/__init__.py +0 -0
  250. sagemaker/core/modules/train/sm_recipes/utils.py +330 -0
  251. sagemaker/core/modules/types.py +19 -0
  252. sagemaker/core/modules/utils.py +194 -0
  253. sagemaker/core/network.py +185 -0
  254. sagemaker/core/parameter.py +173 -0
  255. sagemaker/core/payloads.py +185 -0
  256. sagemaker/core/processing.py +1597 -0
  257. sagemaker/core/remote_function/__init__.py +19 -0
  258. sagemaker/core/remote_function/checkpoint_location.py +47 -0
  259. sagemaker/core/remote_function/client.py +1285 -0
  260. sagemaker/core/remote_function/core/__init__.py +0 -0
  261. sagemaker/core/remote_function/core/_custom_dispatch_table.py +72 -0
  262. sagemaker/core/remote_function/core/pipeline_variables.py +353 -0
  263. sagemaker/core/remote_function/core/serialization.py +422 -0
  264. sagemaker/core/remote_function/core/stored_function.py +226 -0
  265. sagemaker/core/remote_function/custom_file_filter.py +128 -0
  266. sagemaker/core/remote_function/errors.py +104 -0
  267. sagemaker/core/remote_function/invoke_function.py +172 -0
  268. sagemaker/core/remote_function/job.py +2140 -0
  269. sagemaker/core/remote_function/logging_config.py +38 -0
  270. sagemaker/core/remote_function/runtime_environment/__init__.py +14 -0
  271. sagemaker/core/remote_function/runtime_environment/bootstrap_runtime_environment.py +605 -0
  272. sagemaker/core/remote_function/runtime_environment/mpi_utils_remote.py +252 -0
  273. sagemaker/core/remote_function/runtime_environment/runtime_environment_manager.py +554 -0
  274. sagemaker/core/remote_function/runtime_environment/spark_app.py +18 -0
  275. sagemaker/core/remote_function/spark_config.py +149 -0
  276. sagemaker/core/resource_requirements.py +168 -0
  277. {sagemaker_core/main → sagemaker/core}/resources.py +19098 -10895
  278. sagemaker/core/s3/__init__.py +41 -0
  279. sagemaker/core/s3/client.py +367 -0
  280. sagemaker/core/s3/utils.py +175 -0
  281. sagemaker/core/script_uris.py +93 -0
  282. sagemaker/core/serializers/__init__.py +11 -0
  283. sagemaker/core/serializers/base.py +510 -0
  284. sagemaker/core/serializers/implementations.py +159 -0
  285. sagemaker/core/serializers/utils.py +223 -0
  286. sagemaker/core/serverless_inference_config.py +63 -0
  287. sagemaker/core/session_settings.py +55 -0
  288. sagemaker/core/shapes/__init__.py +3 -0
  289. sagemaker/core/shapes/model_card_shapes.py +159 -0
  290. {sagemaker_core/main → sagemaker/core/shapes}/shapes.py +5810 -1806
  291. sagemaker/core/spark/__init__.py +16 -0
  292. sagemaker/core/spark/defaults.py +16 -0
  293. sagemaker/core/spark/processing.py +1380 -0
  294. sagemaker/core/telemetry/__init__.py +23 -0
  295. sagemaker/core/telemetry/constants.py +84 -0
  296. sagemaker/core/telemetry/telemetry_logging.py +284 -0
  297. sagemaker/core/tools/__init__.py +1 -0
  298. {sagemaker_core → sagemaker/core}/tools/codegen.py +4 -4
  299. {sagemaker_core → sagemaker/core}/tools/constants.py +23 -15
  300. {sagemaker_core → sagemaker/core}/tools/data_extractor.py +1 -1
  301. {sagemaker_core → sagemaker/core}/tools/method.py +1 -1
  302. sagemaker/core/tools/model_card/generate_model_card_from_schema.py +562 -0
  303. {sagemaker_core → sagemaker/core}/tools/resources_codegen.py +165 -98
  304. {sagemaker_core → sagemaker/core}/tools/resources_extractor.py +5 -13
  305. {sagemaker_core → sagemaker/core}/tools/shapes_codegen.py +16 -17
  306. {sagemaker_core → sagemaker/core}/tools/shapes_extractor.py +29 -67
  307. {sagemaker_core → sagemaker/core}/tools/templates.py +39 -17
  308. sagemaker/core/training/__init__.py +14 -0
  309. sagemaker/core/training/configs.py +333 -0
  310. sagemaker/core/training/constants.py +37 -0
  311. sagemaker/core/training/utils.py +77 -0
  312. sagemaker/core/training_compiler/__init__.py +16 -0
  313. sagemaker/core/training_compiler/config.py +197 -0
  314. sagemaker/core/training_compiler_config.py +197 -0
  315. sagemaker/core/transformer.py +793 -0
  316. sagemaker/core/user_agent.py +76 -0
  317. sagemaker/core/utilities/__init__.py +24 -0
  318. sagemaker/core/utilities/cache.py +169 -0
  319. sagemaker/core/utilities/search_expression.py +133 -0
  320. sagemaker/core/utils/__init__.py +48 -0
  321. sagemaker/core/utils/code_injection/__init__.py +0 -0
  322. {sagemaker_core/main → sagemaker/core/utils}/code_injection/codec.py +2 -2
  323. {sagemaker_core/main → sagemaker/core/utils}/code_injection/shape_dag.py +5979 -176
  324. {sagemaker_core/main → sagemaker/core/utils}/exceptions.py +8 -8
  325. sagemaker_core/main/default_configs_helper.py → sagemaker/core/utils/intelligent_defaults_helper.py +5 -6
  326. {sagemaker_core/main → sagemaker/core/utils}/logs.py +1 -2
  327. {sagemaker_core/main → sagemaker/core/utils}/utils.py +27 -22
  328. sagemaker/core/workflow/__init__.py +152 -0
  329. sagemaker/core/workflow/conditions.py +313 -0
  330. sagemaker/core/workflow/entities.py +58 -0
  331. sagemaker/core/workflow/execution_variables.py +89 -0
  332. sagemaker/core/workflow/functions.py +193 -0
  333. sagemaker/core/workflow/parameters.py +222 -0
  334. sagemaker/core/workflow/pipeline_context.py +394 -0
  335. sagemaker/core/workflow/pipeline_definition_config.py +31 -0
  336. sagemaker/core/workflow/properties.py +285 -0
  337. sagemaker/core/workflow/step_outputs.py +65 -0
  338. sagemaker/core/workflow/utilities.py +507 -0
  339. sagemaker/lineage/__init__.py +33 -0
  340. sagemaker/lineage/action.py +28 -0
  341. sagemaker/lineage/artifact.py +28 -0
  342. sagemaker/lineage/context.py +28 -0
  343. sagemaker/lineage/lineage_trial_component.py +28 -0
  344. {sagemaker_core-1.0.62.dist-info → sagemaker_core-2.1.1.dist-info}/METADATA +28 -9
  345. sagemaker_core-2.1.1.dist-info/RECORD +355 -0
  346. sagemaker_core-2.1.1.dist-info/top_level.txt +1 -0
  347. sagemaker_core/_version.py +0 -3
  348. sagemaker_core/helper/session_helper.py +0 -769
  349. sagemaker_core/resources/__init__.py +0 -1
  350. sagemaker_core/shapes/__init__.py +0 -1
  351. sagemaker_core/tools/__init__.py +0 -1
  352. sagemaker_core-1.0.62.dist-info/RECORD +0 -35
  353. sagemaker_core-1.0.62.dist-info/top_level.txt +0 -1
  354. {sagemaker_core → sagemaker/core/helper}/__init__.py +0 -0
  355. {sagemaker_core/helper → sagemaker/core/huggingface/training_compiler}/__init__.py +0 -0
  356. {sagemaker_core/main → sagemaker/core/jumpstart/factory}/__init__.py +0 -0
  357. {sagemaker_core/main/code_injection → sagemaker/core/jumpstart/hub}/__init__.py +0 -0
  358. {sagemaker_core/main → sagemaker/core/utils}/code_injection/base.py +0 -0
  359. {sagemaker_core/main → sagemaker/core/utils}/code_injection/constants.py +0 -0
  360. {sagemaker_core/main → sagemaker/core/utils}/user_agent.py +0 -0
  361. {sagemaker_core-1.0.62.dist-info → sagemaker_core-2.1.1.dist-info}/WHEEL +0 -0
  362. {sagemaker_core-1.0.62.dist-info → sagemaker_core-2.1.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,204 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+ """A base class for starting/accessing apps hosted on Amazon SageMaker Studio"""
14
+
15
+ from __future__ import absolute_import
16
+
17
+ import abc
18
+ import base64
19
+ import json
20
+ import logging
21
+ import os
22
+ import re
23
+ import webbrowser
24
+
25
+ from typing import Optional
26
+ import boto3
27
+ from sagemaker.core.helper.session_helper import Session, NOTEBOOK_METADATA_FILE
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class BaseInteractiveApp(abc.ABC):
33
+ """BaseInteractiveApp is a base class for creating/accessing apps hosted on SageMaker."""
34
+
35
+ def __init__(
36
+ self,
37
+ region: Optional[str] = None,
38
+ ):
39
+ """Initialize a BaseInteractiveApp object.
40
+
41
+ Args:
42
+ region (str): Optional. The AWS Region, e.g. us-east-1. If not specified,
43
+ one is created using the default AWS configuration chain.
44
+ Default: ``None``
45
+ """
46
+ if isinstance(region, str):
47
+ self.region = region
48
+ else:
49
+ try:
50
+ self.region = Session().boto_region_name
51
+ except ValueError:
52
+ raise ValueError(
53
+ "Failed to get the Region information from the default config. Please either "
54
+ "pass your Region manually as an input argument or set up the local AWS"
55
+ " configuration."
56
+ )
57
+
58
+ self._sagemaker_client = boto3.client("sagemaker", region_name=self.region)
59
+ # Used to store domain and user profile info retrieved from Studio environment.
60
+ self._domain_id = None
61
+ self._user_profile_name = None
62
+ self._in_studio_env = False
63
+ self._get_domain_and_user()
64
+
65
+ def __str__(self):
66
+ """Return str(self)."""
67
+ return f"{type(self).__name__}(region={self.region})"
68
+
69
+ def __repr__(self):
70
+ """Return repr(self)."""
71
+ return self.__str__()
72
+
73
+ def _get_domain_and_user(self):
74
+ """Get domain id and user profile from Studio environment.
75
+
76
+ To verify Studio environment, we check if NOTEBOOK_METADATA_FILE exists
77
+ and domain id and user profile name are present in the file.
78
+ """
79
+ if not os.path.isfile(NOTEBOOK_METADATA_FILE):
80
+ return
81
+
82
+ try:
83
+ with open(NOTEBOOK_METADATA_FILE, "rb") as metadata_file:
84
+ metadata = json.loads(metadata_file.read())
85
+ except OSError as err:
86
+ logger.warning("Could not load metadata due to unexpected error. %s", err)
87
+ return
88
+
89
+ if "DomainId" in metadata and "UserProfileName" in metadata:
90
+ self._in_studio_env = True
91
+ self._domain_id = metadata.get("DomainId")
92
+ self._user_profile_name = metadata.get("UserProfileName")
93
+
94
+ def _get_presigned_url(
95
+ self,
96
+ create_presigned_url_kwargs: dict,
97
+ redirect: Optional[str] = None,
98
+ state: Optional[str] = None,
99
+ ):
100
+ """Generate a presigned URL to access a user's domain / user profile.
101
+
102
+ Optional state and redirect parameters can be used to to have presigned URL automatically
103
+ redirect to a specific app and provide modifying data.
104
+
105
+ Args:
106
+ create_presigned_url_kwargs (dict): Required. This dictionary should include the
107
+ parameters that will be used when calling create_presigned_domain_url via the boto3
108
+ client. At a minimum, this should include the "DomainId" and "UserProfileName"
109
+ parameters as defined by create_presigned_domain_url's documentation.
110
+ Default: ``None``
111
+ redirect (str): Optional. This value will be appended to the resulting presigned URL
112
+ in the format "&redirect=<redirect parameter>". This is used to automatically
113
+ redirect the user into a specific Studio app.
114
+ Default: ``None``
115
+ state (str): Optional. This value will be appended to the resulting presigned URL
116
+ in the format "&state=<state parameter base64 encoded>". This is used to
117
+ automatically apply a state to the given app. Should be used in conjuction with
118
+ the redirect parameter.
119
+ Default: ``None``
120
+
121
+ Returns:
122
+ str: A presigned URL.
123
+ """
124
+ response = self._sagemaker_client.create_presigned_domain_url(**create_presigned_url_kwargs)
125
+ if response["ResponseMetadata"]["HTTPStatusCode"] == 200:
126
+ url = response["AuthorizedUrl"]
127
+ else:
128
+ raise ValueError(
129
+ "An invalid status code was returned when creating a presigned URL."
130
+ f" See response for more: {response}"
131
+ )
132
+
133
+ if redirect:
134
+ url += f"&redirect={redirect}"
135
+
136
+ if state:
137
+ url += f"&state={base64.b64encode(bytes(state, 'utf-8')).decode('utf-8')}"
138
+
139
+ logger.warning(
140
+ "A presigned domain URL was generated. This is sensitive and should not be shared with"
141
+ " others."
142
+ )
143
+
144
+ return url
145
+
146
+ def _open_url_in_web_browser(self, url: str):
147
+ """Open a URL in the default web browser.
148
+
149
+ Args:
150
+ url (str): The URL to open.
151
+ """
152
+ webbrowser.open(url)
153
+
154
+ def _validate_job_name(self, job_name: str):
155
+ """Validate training job name format.
156
+
157
+ Args:
158
+ job_name (str): The job name to validate.
159
+
160
+ Returns:
161
+ bool: Whether the supplied job name is valid.
162
+ """
163
+ job_name_regex = "^[a-zA-Z0-9](-*[a-zA-Z0-9]){0,62}"
164
+ if not re.fullmatch(job_name_regex, job_name):
165
+ raise ValueError(
166
+ f"Invalid job name. Job name must match regular expression {job_name_regex}"
167
+ )
168
+
169
+ def _validate_domain_id(self, domain_id: str):
170
+ """Validate domain id format.
171
+
172
+ Args:
173
+ domain_id (str): Required. The domain ID to validate.
174
+
175
+ Returns:
176
+ bool: Whether the supplied domain ID is valid.
177
+ """
178
+ if domain_id is None or len(domain_id) > 63:
179
+ return False
180
+ return True
181
+
182
+ def _validate_user_profile_name(self, user_profile_name: str):
183
+ """Validate user profile name format.
184
+
185
+ Args:
186
+ user_profile_name (str): Required. The user profile name to validate.
187
+
188
+ Returns:
189
+ bool: Whether the supplied user profile name is valid.
190
+ """
191
+ user_profile_name_regex = "^[a-zA-Z0-9](-*[a-zA-Z0-9]){0,62}"
192
+ if user_profile_name is None or not re.fullmatch(
193
+ user_profile_name_regex, user_profile_name
194
+ ):
195
+ return False
196
+ return True
197
+
198
+ @abc.abstractmethod
199
+ def get_app_url(self):
200
+ """Abstract method to generate a URL to help access the application in Studio.
201
+
202
+ Classes that inherit from BaseInteractiveApp should implement and override with what
203
+ parameters are needed for its specific use case.
204
+ """
@@ -0,0 +1,139 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+ """Methods for starting up and accessing DetailProfiler apps
14
+
15
+ This module contains methods for starting up and accessing
16
+ DetailProfiler apps hosted on SageMaker
17
+ """
18
+ from __future__ import absolute_import
19
+
20
+ import json
21
+ import logging
22
+ import os
23
+ import re
24
+
25
+ from typing import Optional
26
+ from sagemaker.core.helper.session_helper import Session, NOTEBOOK_METADATA_FILE
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class DetailProfilerApp(object):
32
+ """Class for creating/accessing a DetailProfiler app hosted on SageMaker."""
33
+
34
+ def __init__(self, region: Optional[str] = None):
35
+ """Initialize a DetailProfilerApp object.
36
+
37
+ Args:
38
+ region (str): The name of the region e.g. us-east-1. If not specified,
39
+ one is created using the default AWS configuration chain.
40
+ """
41
+ if region:
42
+ self.region = region
43
+ else:
44
+ try:
45
+ self.region = Session().boto_region_name
46
+ except ValueError:
47
+ raise ValueError(
48
+ "Failed to get region from default config. Please eihter pass region "
49
+ "as an input argument or setup the local AWS config."
50
+ )
51
+
52
+ self._domain_id = None
53
+ self._user_profile_name = None
54
+ self._valid_domain_and_user = False
55
+ self._get_domain_and_user()
56
+
57
+ def __str__(self):
58
+ """Return str(self)."""
59
+ return f"DetailProfilerApp(region={self.region})"
60
+
61
+ def __repr__(self):
62
+ """Return repr(self)."""
63
+ return self.__str__()
64
+
65
+ def get_app_url(self, training_job_name: Optional[str] = None):
66
+ """Get an unsigned URL for DetailProfiler app hosted on SageMaker.
67
+
68
+ For users that are already in SM Studio notebook instance, the method tries to
69
+ get domain id and user profile from the Studio environment. If succeeded, the
70
+ generated URL will direct to SM DetailProfiler app. Otherwise it will direct to
71
+ DetailProfiler landing page on SageMaker console. For non Studio users, the
72
+ URL will direct to the DetailProfiler landing page on SageMaker console.
73
+
74
+ Args:
75
+ training_job_name (str): Optional. The name of the training job to pre-load in
76
+ DetailProfiler.
77
+ If not provided, no job will be automatically loaded when the URL is opened.
78
+
79
+ Returns:
80
+ str: An unsigned URL for DetailProfiler hosted on SageMaker.
81
+ """
82
+ if self._valid_domain_and_user:
83
+ url = f"https://{self._domain_id}.studio.{self.region}.sagemaker.aws/profiler/default"
84
+ if training_job_name is not None:
85
+ self._validate_job_name(training_job_name)
86
+ url += f"/#!/welcome?profile={training_job_name}"
87
+ else:
88
+ dp = "profiler-landing"
89
+ url = "https://{region}.console.aws.amazon.com/sagemaker/home?region={region}#/{dp}".format(
90
+ region=self.region, dp=dp
91
+ )
92
+
93
+ return url
94
+
95
+ def _get_domain_and_user(self):
96
+ """Validate studio domain id and user profile
97
+
98
+ Get and validate studio domain id and user profile
99
+ from NOTEBOOK_METADATA_FILE in studio environment.
100
+
101
+ Set _valid_domain_and_user to True if validation succeeded.
102
+ """
103
+ if not os.path.isfile(NOTEBOOK_METADATA_FILE):
104
+ return
105
+
106
+ with open(NOTEBOOK_METADATA_FILE, "rb") as f:
107
+ metadata = json.loads(f.read())
108
+ self._domain_id = metadata.get("DomainId")
109
+ self._user_profile_name = metadata.get("UserProfileName")
110
+ if self._validate_domain_id() is True and self._validate_user_profile_name() is True:
111
+ self._valid_domain_and_user = True
112
+ else:
113
+ logger.warning(
114
+ "NOTEBOOK_METADATA_FILE detected but failed to get"
115
+ "valid domain and user from it."
116
+ )
117
+
118
+ def _validate_job_name(self, job_name: str):
119
+ """Validate training job name format."""
120
+ job_name_regex = "^[a-zA-Z0-9](-*[a-zA-Z0-9]){0,62}"
121
+ if not re.fullmatch(job_name_regex, job_name):
122
+ raise ValueError(
123
+ f"Invalid job name. " f"Job name must match regular expression {job_name_regex}"
124
+ )
125
+
126
+ def _validate_domain_id(self):
127
+ """Validate domain id format."""
128
+ if self._domain_id is None or len(self._domain_id) > 63:
129
+ return False
130
+ return True
131
+
132
+ def _validate_user_profile_name(self):
133
+ """Validate user profile name format."""
134
+ user_profile_name_regex = "^[a-zA-Z0-9](-*[a-zA-Z0-9]){0,62}"
135
+ if self._user_profile_name is None or not re.fullmatch(
136
+ user_profile_name_regex, self._user_profile_name
137
+ ):
138
+ return False
139
+ return True
@@ -0,0 +1,149 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+ """Methods for TensorBoard apps hosted on SageMaker.
14
+
15
+ This module contains methods for starting up and accessing
16
+ TensorBoard apps hosted on SageMaker
17
+ """
18
+ from __future__ import absolute_import
19
+
20
+ import logging
21
+
22
+ from typing import Optional
23
+
24
+ from sagemaker.core.interactive_apps.base_interactive_app import BaseInteractiveApp
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class TensorBoardApp(BaseInteractiveApp):
30
+ """TensorBoardApp is a class for creating/accessing a TensorBoard app hosted on Studio."""
31
+
32
+ def get_app_url(
33
+ self,
34
+ training_job_name: Optional[str] = None,
35
+ open_in_default_web_browser: Optional[bool] = True,
36
+ create_presigned_domain_url: Optional[bool] = False,
37
+ domain_id: Optional[str] = None,
38
+ user_profile_name: Optional[str] = None,
39
+ optional_create_presigned_url_kwargs: Optional[dict] = None,
40
+ ):
41
+ """Generate a URL to help access the TensorBoard application hosted in Studio.
42
+
43
+ For users that are already in SageMaker Studio, this method tries to get the
44
+ domain id and the user profile from the Studio environment. If successful, the generated
45
+ URL will direct to the TensorBoard application in SageMaker. Otherwise, it will direct
46
+ to the TensorBoard landing page in the SageMaker console. If a user outside of SageMaker
47
+ Studio passes in a valid domain ID and user profile name, the generated URL will be
48
+ presigned - authenticating the user and redirecting to the TensorBoard app once used.
49
+ Otherwise, the URL will direct to the TensorBoard landing page in the SageMaker console.
50
+ By default, the generated URL will attempt to open in the environment's default web
51
+ browser.
52
+
53
+ Args:
54
+ training_job_name (str): Optional. The name of the training job to pre-load in
55
+ TensorBoard. If nothing provided, the method just returns the TensorBoard
56
+ application URL. You can add training jobs later by using the SageMaker Data
57
+ Manager UI.
58
+ Default: ``None``
59
+ open_in_default_web_browser (bool): Optional. When True, the URL will attempt to be
60
+ opened in the environment's default web browser. Otherwise, the resulting URL will
61
+ be returned by this function.
62
+ Default: ``True``
63
+ create_presigned_domain_url (bool): Optional. Determines whether a presigned domain URL
64
+ should be generated instead of an unsigned URL. This only applies when called from
65
+ outside of a SageMaker Studio environment. If this is set to True inside of a
66
+ SageMaker Studio environment, it will be ignored.
67
+ Default: ``False``
68
+ domain_id (str): Optional. This parameter should be passed when a user outside of
69
+ Studio wants a presigned URL to the TensorBoard application. This value will map to
70
+ 'DomainId' in the resulting create_presigned_domain_url call. Must be passed with
71
+ user_profile_name and create_presigned_domain_url set to True.
72
+ Default: ``None``
73
+ user_profile_name (str): Optional. This parameter should be passed when a user outside
74
+ of Studio wants a presigned URL to the TensorBoard application. This value will
75
+ map to 'UserProfileName' in the resulting create_presigned_domain_url call. Must be
76
+ passed with domain_id and create_presigned_domain_url set to True.
77
+ Default: ``None``
78
+ optional_create_presigned_url_kwargs (dict): Optional. This parameter
79
+ should be passed when a user outside of Studio wants a presigned URL to the
80
+ TensorBoard application and wants to modify the optional parameters of the
81
+ create_presigned_domain_url call.
82
+ Default: ``None``
83
+
84
+ Returns:
85
+ str: A URL for TensorBoard hosted on SageMaker.
86
+ """
87
+ if training_job_name is not None:
88
+ self._validate_job_name(training_job_name)
89
+
90
+ if (
91
+ self._in_studio_env
92
+ and self._validate_domain_id(self._domain_id)
93
+ and self._validate_user_profile_name(self._user_profile_name)
94
+ ):
95
+ if domain_id or user_profile_name:
96
+ logger.warning(
97
+ "Ignoring passed in domain_id and user_profile_name for Studio set values."
98
+ )
99
+ url = (
100
+ f"https://{self._domain_id}.studio.{self.region}."
101
+ + "sagemaker.aws/tensorboard/default"
102
+ )
103
+ if training_job_name is not None:
104
+ url += (
105
+ "/data/plugin/sagemaker_data_manager/"
106
+ + f"add_folder_or_job?Redirect=True&Name={training_job_name}"
107
+ )
108
+ else:
109
+ url += "/#sagemaker_data_manager"
110
+
111
+ elif (
112
+ not self._in_studio_env
113
+ and create_presigned_domain_url
114
+ and self._validate_domain_id(domain_id)
115
+ and self._validate_user_profile_name(user_profile_name)
116
+ ):
117
+ if optional_create_presigned_url_kwargs is None:
118
+ optional_create_presigned_url_kwargs = {}
119
+ optional_create_presigned_url_kwargs["DomainId"] = domain_id
120
+ optional_create_presigned_url_kwargs["UserProfileName"] = user_profile_name
121
+
122
+ redirect = "TensorBoard"
123
+ state_to_encode = None
124
+ if training_job_name is not None:
125
+ state_to_encode = (
126
+ "/tensorboard/default/data/plugin/sagemaker_data_manager/"
127
+ + f"add_folder_or_job?Redirect=True&Name={training_job_name}"
128
+ )
129
+
130
+ url = self._get_presigned_url(
131
+ optional_create_presigned_url_kwargs, redirect, state_to_encode
132
+ )
133
+ else:
134
+ if not self._in_studio_env and create_presigned_domain_url:
135
+ logger.warning(
136
+ "A valid domain ID and user profile name were not provided. "
137
+ "Providing default landing page URL as a result."
138
+ )
139
+ url = (
140
+ f"https://{self.region}.console.aws.amazon.com/sagemaker/home"
141
+ + f"?region={self.region}#/tensor-board-landing"
142
+ )
143
+ if training_job_name is not None:
144
+ url += f"/{training_job_name}"
145
+
146
+ if open_in_default_web_browser:
147
+ self._open_url_in_web_browser(url)
148
+ url = ""
149
+ return url
@@ -0,0 +1,186 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+ """Implements iterators for deserializing data returned from an inference streaming endpoint."""
14
+ from __future__ import absolute_import
15
+
16
+ from abc import ABC, abstractmethod
17
+ import io
18
+
19
+ from sagemaker.core.exceptions import ModelStreamError, InternalStreamFailure
20
+
21
+
22
+ def handle_stream_errors(chunk):
23
+ """Handle API Response errors within `invoke_endpoint_with_response_stream` API if any.
24
+
25
+ Args:
26
+ chunk (dict): A chunk of response received as part of `botocore.eventstream.EventStream`
27
+ response object.
28
+
29
+ Raises:
30
+ ModelStreamError: If `ModelStreamError` error is detected in a chunk of
31
+ `botocore.eventstream.EventStream` response object.
32
+ InternalStreamFailure: If `InternalStreamFailure` error is detected in a chunk of
33
+ `botocore.eventstream.EventStream` response object.
34
+ """
35
+ if "ModelStreamError" in chunk:
36
+ raise ModelStreamError(
37
+ chunk["ModelStreamError"]["Message"], code=chunk["ModelStreamError"]["ErrorCode"]
38
+ )
39
+ if "InternalStreamFailure" in chunk:
40
+ raise InternalStreamFailure(chunk["InternalStreamFailure"]["Message"])
41
+
42
+
43
+ class BaseIterator(ABC):
44
+ """Abstract base class for Inference Streaming iterators.
45
+
46
+ Provides a skeleton for customization requiring the overriding of iterator methods
47
+ __iter__ and __next__.
48
+
49
+ Tenets of iterator class for Streaming Inference API Response
50
+ (https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/
51
+ sagemaker-runtime/client/invoke_endpoint_with_response_stream.html):
52
+ 1. Needs to accept an botocore.eventstream.EventStream response.
53
+ 2. Needs to implement logic in __next__ to:
54
+ 2.1. Concatenate and provide next chunk of response from botocore.eventstream.EventStream.
55
+ While doing so parse the response_chunk["PayloadPart"]["Bytes"].
56
+ 2.2. If PayloadPart not in EventStream response, handle Errors
57
+ [Recommended to use `iterators.handle_stream_errors` method].
58
+ """
59
+
60
+ def __init__(self, event_stream):
61
+ """Initialises a Iterator object to help parse the byte event stream input.
62
+
63
+ Args:
64
+ event_stream: (botocore.eventstream.EventStream): Event Stream object to be iterated.
65
+ """
66
+ self.event_stream = event_stream
67
+
68
+ @abstractmethod
69
+ def __iter__(self):
70
+ """Abstract method, returns an iterator object itself"""
71
+ return self
72
+
73
+ @abstractmethod
74
+ def __next__(self):
75
+ """Abstract method, is responsible for returning the next element in the iteration"""
76
+
77
+
78
+ class ByteIterator(BaseIterator):
79
+ """A helper class for parsing the byte Event Stream input to provide Byte iteration."""
80
+
81
+ def __init__(self, event_stream):
82
+ """Initialises a BytesIterator Iterator object
83
+
84
+ Args:
85
+ event_stream: (botocore.eventstream.EventStream): Event Stream object to be iterated.
86
+ """
87
+ super().__init__(event_stream)
88
+ self.byte_iterator = iter(event_stream)
89
+
90
+ def __iter__(self):
91
+ """Returns an iterator object itself, which allows the object to be iterated.
92
+
93
+ Returns:
94
+ iter : object
95
+ An iterator object representing the iterable.
96
+ """
97
+ return self
98
+
99
+ def __next__(self):
100
+ """Returns the next chunk of Byte directly."""
101
+ # Even with "while True" loop the function still behaves like a generator
102
+ # and sends the next new byte chunk.
103
+ while True:
104
+ chunk = next(self.byte_iterator)
105
+ if "PayloadPart" not in chunk:
106
+ # handle API response errors and force terminate.
107
+ handle_stream_errors(chunk)
108
+ # print and move on to next response byte
109
+ print("Unknown event type:" + chunk)
110
+ continue
111
+ return chunk["PayloadPart"]["Bytes"]
112
+
113
+
114
+ class LineIterator(BaseIterator):
115
+ """A helper class for parsing the byte Event Stream input to provide Line iteration."""
116
+
117
+ def __init__(self, event_stream):
118
+ """Initialises a LineIterator Iterator object
119
+
120
+ Args:
121
+ event_stream: (botocore.eventstream.EventStream): Event Stream object to be iterated.
122
+ """
123
+ super().__init__(event_stream)
124
+ self.byte_iterator = iter(self.event_stream)
125
+ self.buffer = io.BytesIO()
126
+ self.read_pos = 0
127
+
128
+ def __iter__(self):
129
+ """Returns an iterator object itself, which allows the object to be iterated.
130
+
131
+ Returns:
132
+ iter : object
133
+ An iterator object representing the iterable.
134
+ """
135
+ return self
136
+
137
+ def __next__(self):
138
+ r"""Returns the next Line for an Line iterable.
139
+
140
+ The output of the event stream will be in the following format:
141
+
142
+ ```
143
+ b'{"outputs": [" a"]}\n'
144
+ b'{"outputs": [" challenging"]}\n'
145
+ b'{"outputs": [" problem"]}\n'
146
+ ...
147
+ ```
148
+
149
+ While usually each PayloadPart event from the event stream will contain a byte array
150
+ with a full json, this is not guaranteed and some of the json objects may be split across
151
+ PayloadPart events. For example:
152
+ ```
153
+ {'PayloadPart': {'Bytes': b'{"outputs": '}}
154
+ {'PayloadPart': {'Bytes': b'[" problem"]}\n'}}
155
+ ```
156
+
157
+ This class accounts for this by concatenating bytes written via the 'write' function
158
+ and then exposing a method which will return lines (ending with a '\n' character) within
159
+ the buffer via the 'scan_lines' function. It maintains the position of the last read
160
+ position to ensure that previous bytes are not exposed again.
161
+
162
+ Returns:
163
+ str: Read and return one line from the event stream.
164
+ """
165
+ # Even with "while True" loop the function still behaves like a generator
166
+ # and sends the next new concatenated line
167
+ while True:
168
+ self.buffer.seek(self.read_pos)
169
+ line = self.buffer.readline()
170
+ if line and line[-1] == ord("\n"):
171
+ self.read_pos += len(line)
172
+ return line[:-1]
173
+ try:
174
+ chunk = next(self.byte_iterator)
175
+ except StopIteration:
176
+ if self.read_pos < self.buffer.getbuffer().nbytes:
177
+ continue
178
+ raise
179
+ if "PayloadPart" not in chunk:
180
+ # handle API response errors and force terminate.
181
+ handle_stream_errors(chunk)
182
+ # print and move on to next response byte
183
+ print("Unknown event type:" + chunk)
184
+ continue
185
+ self.buffer.seek(0, io.SEEK_END)
186
+ self.buffer.write(chunk["PayloadPart"]["Bytes"])