From 31b1bfafe5a866a3452724baebd6a4de77d2f610 Mon Sep 17 00:00:00 2001 From: Akshay Shah Date: Fri, 9 Oct 2026 12:55:35 -0500 Subject: [PATCH] fix(core): read container image from the Model resource in Transformer Transformer._retrieve_image_uri called getattr() on model.__dict__, a plain dict, so it always got the default and returned None. Auto-generated transform job names therefore always fell back to the model name instead of the image's algorithm name. Read primary_container/containers from the Model resource itself. The unit tests used a dict subclass with attribute access as __dict__, which hid the bug; they now use real Model/ContainerDefinition objects. --- .../src/sagemaker/core/transformer.py | 6 +-- sagemaker-core/tests/unit/test_transformer.py | 42 +++++-------------- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/sagemaker-core/src/sagemaker/core/transformer.py b/sagemaker-core/src/sagemaker/core/transformer.py index d6b18c30ed..8cf77c7c9e 100644 --- a/sagemaker-core/src/sagemaker/core/transformer.py +++ b/sagemaker-core/src/sagemaker/core/transformer.py @@ -442,13 +442,11 @@ def _retrieve_image_uri(self): ) if not model: return None - model_desc = model.__dict__ - - primary_container = getattr(model_desc, "primary_container", None) + primary_container = getattr(model, "primary_container", None) if primary_container: return getattr(primary_container, "image", None) - containers = getattr(model_desc, "containers", None) + containers = getattr(model, "containers", None) if containers: return getattr(containers[0], "image", None) diff --git a/sagemaker-core/tests/unit/test_transformer.py b/sagemaker-core/tests/unit/test_transformer.py index e8c954ec71..8edb3e9ea5 100644 --- a/sagemaker-core/tests/unit/test_transformer.py +++ b/sagemaker-core/tests/unit/test_transformer.py @@ -14,6 +14,8 @@ import pytest from unittest.mock import Mock, patch from sagemaker.core.transformer import Transformer +from sagemaker.core.resources import Model +from sagemaker.core.shapes import ContainerDefinition @pytest.fixture @@ -271,22 +273,10 @@ def test_prepare_data_processing_partial(self, mock_session): @patch("sagemaker.core.transformer.Model") def test_retrieve_image_uri_success(self, mock_model_class, mock_session): """Test _retrieve_image_uri with successful model retrieval""" - mock_primary_container = Mock() - mock_primary_container.image = "test-image:latest" - - class DictWithAttrs(dict): - """A dict that also supports attribute access""" - - def __getattr__(self, name): - return self.get(name) - - class MockModel: - def __init__(self): - self.__dict__ = DictWithAttrs() - self.__dict__["primary_container"] = mock_primary_container - self.__dict__["containers"] = None - - mock_model = MockModel() + mock_model = Model( + model_name="test-model", + primary_container=ContainerDefinition(image="test-image:latest"), + ) mock_model_class.get.return_value = mock_model transformer = Transformer( @@ -302,22 +292,10 @@ def __init__(self): @patch("sagemaker.core.transformer.Model") def test_retrieve_image_uri_with_containers(self, mock_model_class, mock_session): """Test _retrieve_image_uri with containers instead of primary_container""" - mock_container = Mock() - mock_container.image = "container-image:latest" - - class DictWithAttrs(dict): - """A dict that also supports attribute access""" - - def __getattr__(self, name): - return self.get(name) - - class MockModel: - def __init__(self): - self.__dict__ = DictWithAttrs() - self.__dict__["primary_container"] = None - self.__dict__["containers"] = [mock_container] - - mock_model = MockModel() + mock_model = Model( + model_name="test-model", + containers=[ContainerDefinition(image="container-image:latest")], + ) mock_model_class.get.return_value = mock_model transformer = Transformer(