1212# language governing permissions and limitations under the License.
1313"""Tests for pydantic compatibility check."""
1414
15+ import builtins
1516import sys
1617from unittest import mock
1718
@@ -26,6 +27,18 @@ def test_check_pydantic_compatibility_passes_with_matching_versions():
2627 check_pydantic_compatibility ()
2728
2829
30+ def _make_pydantic_system_error_import (error_msg ):
31+ """Create a mock import function that raises SystemError for pydantic."""
32+ _real_import = builtins .__import__
33+
34+ def _mock_import (name , * args , ** kwargs ):
35+ if name == "pydantic" :
36+ raise SystemError (error_msg )
37+ return _real_import (name , * args , ** kwargs )
38+
39+ return _mock_import
40+
41+
2942def test_check_pydantic_compatibility_raises_on_system_error ():
3043 """Mock pydantic import to raise SystemError and verify a clear ImportError is raised."""
3144 from sagemaker .core ._pydantic_compat import check_pydantic_compatibility
@@ -35,20 +48,15 @@ def test_check_pydantic_compatibility_raises_on_system_error():
3548 "with the current pydantic version, which requires 2.41.5."
3649 )
3750
38- with mock .patch .dict (sys .modules , {"pydantic" : None }):
39- original_import = __builtins__ .__import__ if hasattr (__builtins__ , '__import__' ) else __import__
40-
41- def mock_import (name , * args , ** kwargs ):
42- if name == "pydantic" :
43- raise SystemError (error_msg )
44- return original_import (name , * args , ** kwargs )
51+ mock_import = _make_pydantic_system_error_import (error_msg )
4552
53+ with mock .patch .dict (sys .modules , {"pydantic" : None }):
4654 with mock .patch ("builtins.__import__" , side_effect = mock_import ):
4755 with pytest .raises (ImportError ) as exc_info :
4856 check_pydantic_compatibility ()
4957
50- assert "incompatibility detected" in str (exc_info .value ).lower () or \
51- "incompatible" in str ( exc_info . value ). lower ()
58+ error_str = str (exc_info .value ).lower ()
59+ assert "incompatibility detected" in error_str
5260
5361
5462def test_pydantic_import_error_message_contains_instructions ():
@@ -60,17 +68,32 @@ def test_pydantic_import_error_message_contains_instructions():
6068 "with the current pydantic version, which requires 2.41.5."
6169 )
6270
63- with mock .patch .dict (sys .modules , {"pydantic" : None }):
64- original_import = __builtins__ .__import__ if hasattr (__builtins__ , '__import__' ) else __import__
65-
66- def mock_import (name , * args , ** kwargs ):
67- if name == "pydantic" :
68- raise SystemError (error_msg )
69- return original_import (name , * args , ** kwargs )
71+ mock_import = _make_pydantic_system_error_import (error_msg )
7072
73+ with mock .patch .dict (sys .modules , {"pydantic" : None }):
7174 with mock .patch ("builtins.__import__" , side_effect = mock_import ):
7275 with pytest .raises (ImportError ) as exc_info :
7376 check_pydantic_compatibility ()
7477
7578 error_str = str (exc_info .value )
7679 assert "pip install pydantic pydantic-core --force-reinstall" in error_str
80+
81+
82+ def test_pydantic_import_error_chains_original_system_error ():
83+ """Verify the ImportError chains the original SystemError as __cause__."""
84+ from sagemaker .core ._pydantic_compat import check_pydantic_compatibility
85+
86+ error_msg = (
87+ "The installed pydantic-core version (2.42.0) is incompatible "
88+ "with the current pydantic version, which requires 2.41.5."
89+ )
90+
91+ mock_import = _make_pydantic_system_error_import (error_msg )
92+
93+ with mock .patch .dict (sys .modules , {"pydantic" : None }):
94+ with mock .patch ("builtins.__import__" , side_effect = mock_import ):
95+ with pytest .raises (ImportError ) as exc_info :
96+ check_pydantic_compatibility ()
97+
98+ assert isinstance (exc_info .value .__cause__ , SystemError )
99+ assert "incompatible" in str (exc_info .value .__cause__ ).lower ()
0 commit comments