Skip to content

Commit 943ce0a

Browse files
authored
Fix/v3 tests (#5996)
* test: make sudo install resilient in integ test Docker image The dummy_container_with_user_and_workdir fixture failed to build because the standalone `RUN apt install -y sudo` step ran several layers after the initial apt-get update, using a stale package index and failing to connect to deb.debian.org when fetching the sudo .deb. Install sudo in the same layer as the initial apt-get update against a fresh index, switch from `apt` to `apt-get`, and add Acquire::Retries so transient network failures are retried automatically. * test(train): resolve LLMAJ base model against SageMakerPublicHub in integ test * test: xfail when InsufficientInstanceCapacity * test: add test level rerun logic to reduce flackyness * fix(train): Replace EOL Claude judge model in LLM-as-Judge eval The judge model anthropic.claude-3-5-haiku-20241022-v1:0 has reached end-of-life in Bedrock, causing integ test evaluation pipelines to fail with a ValidationException. Switch to the active successor anthropic.claude-haiku-4-5-20251001-v1:0 and add it to the allowed evaluator models list. * test(serve): tolerate IAM SimulatePrincipalPolicy throttling in integ tests Add tests/integ/conftest.py with an autouse session fixture that gives boto3's default session adaptive retries (absorbed by the SDK's internal IAM role-validation client), plus a makereport hook that xfails residual SimulatePrincipalPolicy throttling under concurrent test load. * test(train): validate LLMAJ pipeline via step status, make show_results best-effort * test(serve): use canonical HF repo id openai-community/gpt2 in integ test * test(train): fix integ test region/hub/marker issues for v3 - Route Nova evaluator/recipe tests to us-east-1 via us_east_1 marker and us-east-1 session (InspectAI, sft max_steps below minimum) - Pin LLMAsJudge full-flow evaluator to us-west-2 region - Provide explicit session to no-recipe SFTTrainer test to avoid region resolution failure under xdist - Correct extract_evaluator_arn integ test: Lambda ARN is rejected by _extract_evaluator_arn (dispatched upstream), expect ValueError * test(train): Resolve Nova model from public hub in InspectAI integ tests test_inspect_ai_evaluator's two tests constructed InspectAIEvaluator with the public-hub model 'nova-textgeneration-lite' while the session-scoped use_private_hub fixture pinned SAGEMAKER_HUB_NAME to the private 'sdktest' hub, causing DescribeHubContent ResourceNotFound and a pydantic ValidationError at construction time. Override SAGEMAKER_HUB_NAME to SageMakerPublicHub in both tests, matching test_llmaj_custom_model. * test(mlops): use unique S3 prefixes to fix concurrent build races The HPO, Clarify, and pipeline train-registry integ tests used hardcoded S3 prefixes and deleted the entire prefix in their finally blocks. When two mlops integ builds ran concurrently against the same default bucket, one build's cleanup wiped the input data the other build was actively reading, causing spurious "No S3 objects found" / "matched no files on s3" failures. Append a uuid suffix to each test's S3 prefix so concurrent builds no longer share paths and cleanup only removes each run's own data. * test(train): fix hub resolution, region isolation, and stale error matches in recipe integ tests Fix three independent failure classes in the sagemaker-train recipe override / evaluator integ tests, all surfaced under xdist (-n auto). Evaluator hub resolution: TestBenchMarkEvaluatorRecipeOverrideInteg constructs BenchMarkEvaluator with the public-hub model 'meta-textgeneration-llama-3-2-1b-instruct' while the session-scoped use_private_hub fixture pins SAGEMAKER_HUB_NAME to the private 'sdktest' hub. Unlike the SFTTrainer path, the evaluator's JumpStart model resolution (_resolve_jumpstart_model) does not fall back to SageMakerPublicHub, so DescribeHubContent returned ResourceNotFound and construction failed with a pydantic ValidationError. Override SAGEMAKER_HUB_NAME to SageMakerPublicHub in both tests, matching the existing InspectAI tests. Region isolation: tests that construct SFTTrainer without an explicit sagemaker_session build a default Session() that reads the region from the environment. AWS_DEFAULT_REGION was only set as a side effect of the module-scoped sagemaker_session fixture, so a worker running only such tests had no region set and Session() raised "Must setup local AWS configuration with a region supported by SageMaker.". Add a session-scoped autouse ensure_default_region fixture that pins AWS_DEFAULT_REGION up front (without clobbering an externally provided value) so region resolution no longer depends on test order. Stale error matches: two get_resolved_recipe no-recipe tests matched "requires a 'recipe' or 'overrides'", but the raised message is now "requires a 'recipe', 'overrides', or direct hyperparameter assignments...". Update both regexes to the current wording. * test(train): align SFT recipe override assertions with real recipe structure The SFTTrainer recipe-override integ tests were written against a synthetic recipe shape (flat training_config.<hyperparameter>) that matches the unit-test mocks but not the real Hub recipe. The private "sdktest" hub does not contain meta-textgeneration-llama-3-2-1b-instruct, so resolution falls back to SageMakerPublicHub, whose SFT LoRA recipe nests hyperparameters under training_config.training_args and uses different field names. As a result overrides were correctly placed (or intentionally dropped when the key does not exist) while the assertions read the wrong paths, producing KeyErrors. Fix the tests to match the real recipe: - Read hyperparameters under training_config.training_args (learning_rate, seed, max_len, etc.) instead of directly under training_config. - Use real recipe field names: max_epochs (not num_epochs), train_batch_size (not batch_size), max_len (not max_length), and the non-spec fields micro_train_batch_size / max_norm (not the invented max_length / save_top_k). - Write recipe-file values at their real nested path, since user recipe files are not field-name remapped the way the overrides dict is. This also makes test_sft_recipe_file_with_invalid_value_raises actually reach validation and raise "above maximum". - Skip test_sft_save_steps_equal_to_max_steps_passes: save_steps/max_steps are not part of the llama SFT recipe (it trains by epochs, not steps), so the boundary cannot be exercised against this model. No production code changes: the resolver's field-name remapping and unknown-key dropping are working as designed and covered by unit tests. * fix(train): fall back to public hub for base model resolution The evaluator's JumpStart model resolution (_resolve_jumpstart_model) only queried the hub named by SAGEMAKER_HUB_NAME. When that points at a private recipe hub, base models (which live in SageMakerPublicHub) could not be resolved and construction failed. Fall back to SageMakerPublicHub when the base model isn't found in the configured hub, mirroring the behavior already in recipe_utils. This lets the integ tests drop the monkeypatch(SAGEMAKER_HUB_NAME= SageMakerPublicHub) workarounds and run the real customer flow, keeping the private hub pinned by the use_private_hub fixture. Also deduplicate _ALLOWED_EVALUATOR_MODELS: a master merge reintroduced stale entries (with conflicting region lists) that #5987 had removed. Keep the refreshed allowlist and drop the EOL claude-3-5-haiku-20241022 entry from the matching unit test. * test: trim verbose comments in v3 integ tests Condense the lengthy explanatory comments and docstrings added across the test files in this PR down to a line or two each, keeping the essential "why" and any TODOs. No logic changes. * test: de-flake recipe override and lake formation integ tests Pass explicit sagemaker_session to two SFTTrainer recipe-override tests so they no longer depend on a global AWS_DEFAULT_REGION that can be torn down by another fixture under xdist. Rewrite test_enable_lake_formation_fails_for_non_created_status to pin a non-'Created' status deterministically (mock refresh) instead of racing the creation window, avoiding a fall-through to the real RegisterResource call. * test: fix pydantic-unsafe mock.patch on FeatureGroupManager instance test_enable_lake_formation_fails_for_non_created_status patched refresh() on the FeatureGroupManager instance, but the manager is a pydantic model whose validate_assignment rejects assigning a MagicMock to a method, raising "Object has no attribute 'refresh'" before the assertion ran. Patch refresh() on the class (type(fg)) instead to stay pydantic-safe. * test: stop sagemaker_session fixture from deleting global AWS region The module-scoped sagemaker_session fixture deleted AWS_DEFAULT_REGION on teardown, clobbering the value set by the session-scoped autouse ensure_default_region fixture. Under xdist a worker runs multiple modules, so a later test that builds a trainer without an explicit session (SDK falls back to Session()) intermittently failed with "Must setup local AWS configuration with a region supported by SageMaker". Reuse the region guaranteed by ensure_default_region and no longer mutate the global env var on teardown.
1 parent 7e7b6f1 commit 943ce0a

20 files changed

Lines changed: 326 additions & 105 deletions

‎requirements/extras/test_requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pytest
22
pytest-cov
33
pytest-xdist
4+
pytest-rerunfailures
45
mock
56
pydantic==2.11.9
67
pydantic_core==2.33.2

‎sagemaker-mlops/tests/integ/test_clarify.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import joblib
66
import time
77
import os
8+
import uuid
89
from sklearn.datasets import make_classification
910
from sklearn.ensemble import RandomForestClassifier
1011
from sklearn.model_selection import train_test_split
@@ -59,7 +60,7 @@ def trained_model(test_data):
5960
def test_clarify_e2e(sagemaker_session, role, test_data, trained_model):
6061
model, X_test, y_test = trained_model
6162
bucket = sagemaker_session.default_bucket()
62-
prefix = 'clarify-test'
63+
prefix = f'clarify-test-{uuid.uuid4().hex[:8]}'
6364
data_filename = 'clarify_bias_test_data.csv'
6465
model_filename = 'clarify_test_model.joblib'
6566

‎sagemaker-mlops/tests/integ/test_feature_store_lakeformation.py‎

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import logging
1313
import uuid
14+
from unittest import mock
1415
import boto3
1516
import pytest
1617
from botocore.exceptions import ClientError
@@ -179,6 +180,8 @@ def test_create_feature_group_and_enable_lake_formation(s3_uri, role, region):
179180
cleanup_feature_group(fg)
180181

181182

183+
# Rerun to absorb transient Lake Formation ConcurrentModificationException.
184+
@pytest.mark.flaky(reruns=1, reruns_delay=15)
182185
@pytest.mark.serial
183186
@pytest.mark.slow_test
184187
def test_create_feature_group_with_lake_formation_enabled(s3_uri, role, region):
@@ -350,21 +353,34 @@ def test_enable_lake_formation_fails_for_non_created_status(s3_uri, role, region
350353
Expected behavior: ValueError should be raised indicating the Feature Group
351354
must be in 'Created' status.
352355
353-
Note: This test creates its own FeatureGroupManager because it needs to test
354-
behavior during the 'Creating' status, which requires a fresh resource.
356+
Note: This test creates its own FeatureGroupManager and forces a non-'Created'
357+
status. We do not rely on catching the transient 'Creating' window, because a
358+
small Feature Group can reach 'Created' before enable_lake_formation() refreshes
359+
its status, which would make the test race and fall through to the real
360+
RegisterResource call (flaky). Instead we pin the status deterministically so
361+
only the status guard is exercised.
355362
"""
356363
fg_name = generate_feature_group_name()
357364
fg = None
358365

359366
try:
360-
# Create the FeatureGroupManager
367+
# Create the FeatureGroupManager and let it reach 'Created' so cleanup is safe.
361368
fg = create_test_feature_group(fg_name, s3_uri, role, region)
362369
assert fg is not None
370+
fg.wait_for_status(target_status="Created", poll=30, timeout=300)
363371

364-
# Immediately try to enable Lake Formation without waiting for Created status
365-
# The Feature Group will be in 'Creating' status
366-
with pytest.raises(ValueError) as exc_info:
367-
fg.enable_lake_formation(hybrid_access_mode_enabled=False, acknowledge_risk=True, wait_for_active=False)
372+
# Force a non-'Created' status deterministically. refresh() is patched to a
373+
# no-op so it does not overwrite the pinned status, and enable_lake_formation()
374+
# should reject before ever calling RegisterResource.
375+
# NOTE: FeatureGroupManager is a pydantic model, so patching the method on the
376+
# instance (mock.patch.object(fg, "refresh")) is rejected by pydantic's
377+
# validate_assignment. Patch on the class instead to stay pydantic-safe.
378+
fg.feature_group_status = "Creating"
379+
with mock.patch.object(type(fg), "refresh", return_value=None):
380+
with pytest.raises(ValueError) as exc_info:
381+
fg.enable_lake_formation(
382+
hybrid_access_mode_enabled=False, acknowledge_risk=True, wait_for_active=False
383+
)
368384

369385
# Verify error message mentions status requirement
370386
error_msg = str(exc_info.value)
@@ -373,7 +389,6 @@ def test_enable_lake_formation_fails_for_non_created_status(s3_uri, role, region
373389
finally:
374390
# Cleanup
375391
if fg:
376-
fg.wait_for_status(target_status="Created", poll=30, timeout=300)
377392
cleanup_feature_group(fg)
378393

379394

‎sagemaker-mlops/tests/integ/test_hyperparameter_tuning.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import time
33
import boto3
44
import os
5+
import uuid
56
from sagemaker.core.helper.session_helper import Session, get_execution_role
67
from sagemaker.train import ModelTrainer
78
from sagemaker.train.configs import Compute, SourceCode, InputData, StoppingCondition
@@ -27,7 +28,7 @@ def mnist_data_dir():
2728
def test_hyperparameter_tuning_e2e(sagemaker_session, role, mnist_data_dir):
2829
region = sagemaker_session.boto_region_name
2930
bucket = sagemaker_session.default_bucket()
30-
prefix = "v3-tunning-integ-test"
31+
prefix = f"v3-tunning-integ-test-{uuid.uuid4().hex[:8]}"
3132

3233
try:
3334
# Upload pre-downloaded MNIST data to S3

‎sagemaker-mlops/tests/integ/workflow/test_pipeline_train_registry.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def role():
4040
def test_pipeline_with_train_and_registry(sagemaker_session, pipeline_session, role, sklearn_latest_version):
4141
region = sagemaker_session.boto_region_name
4242
bucket = sagemaker_session.default_bucket()
43-
prefix = "integ-test-v3-pipeline"
43+
prefix = f"integ-test-v3-pipeline-{uuid.uuid4().hex[:8]}"
4444
base_job_prefix = "train-registry-job"
4545

4646
# Upload abalone data to S3
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"). You
3+
# may not use this file except in compliance with the License. A copy of
4+
# the License is located at
5+
#
6+
# http://aws.amazon.com/apache2.0/
7+
#
8+
# or in the "license" file accompanying this file. This file is
9+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10+
# ANY KIND, either express or implied. See the License for the specific
11+
# language governing permissions and limitations under the License.
12+
"""Shared pytest configuration for sagemaker-serve integration tests.
13+
14+
These tests run under ``pytest -n auto`` (dozens of xdist workers). Several of
15+
them resolve/validate an IAM execution role during ``ModelBuilder.build()`` /
16+
``.deploy()``, which internally calls the low-TPS ``iam:SimulatePrincipalPolicy``
17+
API. With many workers hitting it at once IAM throttles the request, surfacing as
18+
``ClientError: (Throttling) ... Rate exceeded`` and failing the build.
19+
20+
This is purely a test-harness concurrency problem, so the mitigation lives here in
21+
the test layer rather than in SDK source:
22+
23+
* ``_configure_default_boto_retries`` (autouse) — approach "A": set an adaptive
24+
retry policy on boto3's *default* session. The role resolver, when no explicit
25+
session is passed, falls back to ``sagemaker.core...Session()`` whose boto
26+
session is ``boto3.DEFAULT_SESSION`` (see session_helper._initialize). Clients
27+
created from it therefore inherit these retries, letting the internal IAM calls
28+
ride out transient throttling without any source change.
29+
30+
* ``pytest_runtest_makereport`` — approach "C": a belt-and-suspenders fallback. If
31+
a residual ``SimulatePrincipalPolicy`` throttling error still escapes after the
32+
adaptive retries, convert the failure into an xfail so a transient rate limit
33+
never reds the build. Genuine failures are untouched.
34+
"""
35+
from __future__ import absolute_import
36+
37+
import boto3
38+
import pytest
39+
from botocore.config import Config
40+
41+
# Adaptive retry budget for throttling-prone IAM validation calls.
42+
_ADAPTIVE_RETRY_CONFIG = Config(retries={"max_attempts": 10, "mode": "adaptive"})
43+
44+
# Only tolerate throttling on the IAM permission simulation used during role
45+
# validation, so unrelated throttling still fails loudly.
46+
_THROTTLE_ERROR_CODES = ("Throttling", "ThrottlingException", "RequestLimitExceeded")
47+
_SIMULATE_OP = "SimulatePrincipalPolicy"
48+
49+
50+
@pytest.fixture(autouse=True, scope="session")
51+
def _configure_default_boto_retries():
52+
"""Give boto3's default session adaptive retries so IAM clients built by the
53+
role resolver absorb transient SimulatePrincipalPolicy throttling."""
54+
boto3.setup_default_session()
55+
boto3.DEFAULT_SESSION._session.set_default_client_config(_ADAPTIVE_RETRY_CONFIG)
56+
yield
57+
58+
59+
def _is_simulate_policy_throttle(exc):
60+
"""Return True if ``exc`` is a SimulatePrincipalPolicy throttling ClientError."""
61+
from botocore.exceptions import ClientError
62+
63+
if not isinstance(exc, ClientError):
64+
return False
65+
error_code = exc.response.get("Error", {}).get("Code", "")
66+
operation = getattr(exc, "operation_name", "") or ""
67+
return error_code in _THROTTLE_ERROR_CODES and operation == _SIMULATE_OP
68+
69+
70+
@pytest.hookimpl(hookwrapper=True)
71+
def pytest_runtest_makereport(item, call):
72+
"""Skip (rather than fail) on residual SimulatePrincipalPolicy throttling that
73+
survives the adaptive retries under heavy concurrency."""
74+
outcome = yield
75+
report = outcome.get_result()
76+
77+
if report.when != "call" or not report.failed:
78+
return
79+
80+
exc = call.excinfo.value if call.excinfo else None
81+
# Walk the exception chain so a wrapped ClientError is still detected.
82+
while exc is not None:
83+
if _is_simulate_policy_throttle(exc):
84+
report.outcome = "skipped"
85+
report.wasxfail = (
86+
"iam:SimulatePrincipalPolicy throttled under concurrent test load"
87+
)
88+
break
89+
exc = exc.__cause__ or exc.__context__

‎sagemaker-serve/tests/integ/test_huggingface_integration.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
logger = logging.getLogger(__name__)
2626

2727
# Configuration - easily customizable
28-
MODEL_ID = "gpt2" # Small causal language model compatible with DJL 0.36.0 vLLM
28+
MODEL_ID = "openai-community/gpt2" # canonical HF repo id ("gpt2" no longer accepted)
2929
MODEL_NAME_PREFIX = "hf-test-model"
3030
ENDPOINT_NAME_PREFIX = "hf-test-endpoint"
3131

‎sagemaker-serve/tests/integ/test_model_customization_deployment.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import random
2222
import logging
2323
from botocore.config import Config
24+
from botocore.exceptions import ClientError
2425
from datetime import datetime, timezone, timedelta
2526

2627

@@ -130,14 +131,13 @@ def test_deploy_from_training_job(self, training_job_name, endpoint_name, cleanu
130131
endpoint_name=endpoint_name,
131132
inference_component_name=adapter_name if peft_type == "LORA" else None,
132133
)
133-
except FailedStatusError as e:
134-
# Endpoint provisioning can fail when the region is temporarily out of
135-
# capacity for the requested instance type. This is an environmental
136-
# condition unrelated to the SDK, so xfail rather than fail the build.
137-
if "InsufficientInstanceCapacity" in str(e):
134+
except (FailedStatusError, ClientError) as e:
135+
# xfail on environmental capacity/quota limits rather than fail the build.
136+
msg = str(e)
137+
if "InsufficientInstanceCapacity" in msg or "ResourceLimitExceeded" in msg:
138138
cleanup_endpoints.append(endpoint_name)
139139
pytest.xfail(
140-
f"InsufficientInstanceCapacity for ml.g5.4xlarge in {AWS_REGION}: {e}"
140+
f"Environmental capacity/quota limit for ml.g5.4xlarge in {AWS_REGION}: {e}"
141141
)
142142
raise
143143

‎sagemaker-train/src/sagemaker/train/common_utils/model_resolution.py‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,28 @@ def _resolve_jumpstart_model(self, model_id: str, hub_name: str) -> _ModelInfo:
262262
session = self._get_session()
263263

264264
try:
265-
hub_content = HubContent.get(
266-
hub_name=hub_name,
267-
hub_content_type="Model",
268-
hub_content_name=model_id,
269-
session=session.boto_session,
270-
region=session.boto_session.region_name
271-
)
265+
try:
266+
hub_content = HubContent.get(
267+
hub_name=hub_name,
268+
hub_content_type="Model",
269+
hub_content_name=model_id,
270+
session=session.boto_session,
271+
region=session.boto_session.region_name
272+
)
273+
except Exception:
274+
# The base model may not exist in a custom/private hub (e.g. a
275+
# recipe hub pinned via SAGEMAKER_HUB_NAME). Base models are
276+
# published to the public hub, so fall back to it before giving
277+
# up, mirroring the resolution behavior in recipe_utils.
278+
if hub_name == "SageMakerPublicHub":
279+
raise
280+
hub_content = HubContent.get(
281+
hub_name="SageMakerPublicHub",
282+
hub_content_type="Model",
283+
hub_content_name=model_id,
284+
session=session.boto_session,
285+
region=session.boto_session.region_name
286+
)
272287

273288
# Parse additional metadata from hub content document
274289
additional_metadata = {}

‎sagemaker-train/tests/integ/train/conftest.py‎

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ def _ensure_lambda_function(region, function_name, source_file):
147147
return function_arn
148148

149149

150+
@pytest.fixture(autouse=True, scope="session")
151+
def ensure_default_region():
152+
"""Pin AWS_DEFAULT_REGION for the session so trainers/evaluators built
153+
without an explicit session can resolve a region under xdist, regardless
154+
of test execution order. Doesn't clobber an externally provided value."""
155+
if not os.environ.get("AWS_DEFAULT_REGION"):
156+
os.environ["AWS_DEFAULT_REGION"] = DEFAULT_REGION
157+
yield
158+
159+
150160
@pytest.fixture(autouse=True, scope="session")
151161
def use_private_hub():
152162
os.environ["SAGEMAKER_HUB_NAME"] = "sdktest"
@@ -156,20 +166,15 @@ def use_private_hub():
156166

157167
@pytest.fixture(scope="module")
158168
def sagemaker_session():
159-
region = os.environ.get("AWS_DEFAULT_REGION")
160-
if not region:
161-
os.environ["AWS_DEFAULT_REGION"] = DEFAULT_REGION
162-
region_manual_set = True
163-
else:
164-
region_manual_set = True
165-
166-
boto_session = boto3.Session(region_name=os.environ["AWS_DEFAULT_REGION"])
167-
sagemaker_session = Session(boto_session=boto_session)
168-
169-
yield sagemaker_session
170-
171-
if region_manual_set and "AWS_DEFAULT_REGION" in os.environ:
172-
del os.environ["AWS_DEFAULT_REGION"]
169+
# ensure_default_region (session-scoped, autouse) already guarantees
170+
# AWS_DEFAULT_REGION is set. Do NOT delete it on teardown: under xdist a
171+
# worker runs multiple modules, and clobbering the global region here made
172+
# later tests that build a trainer/evaluator without an explicit session
173+
# (SDK falls back to Session()) fail with "Must setup local AWS
174+
# configuration with a region supported by SageMaker".
175+
region = os.environ.get("AWS_DEFAULT_REGION", DEFAULT_REGION)
176+
boto_session = boto3.Session(region_name=region)
177+
return Session(boto_session=boto_session)
173178

174179

175180
@pytest.fixture(scope="module")

0 commit comments

Comments
 (0)