11import ctypes
2+ import os
23import sys
34from importlib import reload
45from unittest import mock
@@ -62,9 +63,7 @@ def test_get_core_path_darwin(self):
6263 _CoreLoader ._get_core_path ()
6364
6465 mock_files .assert_called_once_with ("snowflake.connector.minicore" )
65- mock_files_obj .joinpath .assert_called_once_with (
66- "libsf_mini_core.dyldib"
67- )
66+ mock_files_obj .joinpath .assert_called_once_with ("libsf_mini_core.dylib" )
6867
6968 def test_get_core_path_linux (self ):
7069 """Test _get_core_path returns correct path for Linux."""
@@ -111,6 +110,42 @@ def test_load_minicore(self):
111110 mock_cdll .assert_called_once_with (str (mock_lib_path ))
112111 assert result == mock_core
113112
113+ @pytest .mark .parametrize ("env_value" , ["1" , "true" , "True" , "TRUE" ])
114+ def test_is_core_disabled_returns_true (self , env_value ):
115+ """Test that _is_core_disabled returns True when env var is '1' or 'true' (case-insensitive)."""
116+ loader = _CoreLoader ()
117+ with mock .patch .dict (os .environ , {"SNOWFLAKE_DISABLE_MINICORE" : env_value }):
118+ assert loader ._is_core_disabled () is True
119+
120+ @pytest .mark .parametrize ("env_value" , ["0" , "false" , "False" , "no" , "other" , "" ])
121+ def test_is_core_disabled_returns_false (self , env_value ):
122+ """Test that _is_core_disabled returns False for other values."""
123+ loader = _CoreLoader ()
124+ with mock .patch .dict (os .environ , {"SNOWFLAKE_DISABLE_MINICORE" : env_value }):
125+ assert loader ._is_core_disabled () is False
126+
127+ def test_is_core_disabled_returns_false_when_not_set (self ):
128+ """Test that _is_core_disabled returns False when env var is not set."""
129+ loader = _CoreLoader ()
130+ with mock .patch .dict (os .environ , {}, clear = True ):
131+ # Ensure the env var is not set
132+ os .environ .pop ("SNOWFLAKE_DISABLE_CORE" , None )
133+ assert loader ._is_core_disabled () is False
134+
135+ def test_load_skips_loading_when_core_disabled (self ):
136+ """Test that load() returns early when core is disabled."""
137+ loader = _CoreLoader ()
138+
139+ with mock .patch .dict (os .environ , {"SNOWFLAKE_DISABLE_MINICORE" : "1" }):
140+ with mock .patch .object (loader , "_get_core_path" ) as mock_get_path :
141+ loader .load ()
142+
143+ # Verify that _get_core_path was never called (loading was skipped)
144+ mock_get_path .assert_not_called ()
145+ # Verify the error message is set correctly
146+ assert loader ._error == "mini-core-disabled"
147+ assert loader ._version is None
148+
114149 def test_load_success (self ):
115150 """Test successful load of the core library."""
116151 loader = _CoreLoader ()
@@ -119,34 +154,38 @@ def test_load_success(self):
119154 mock_version = b"1.2.3"
120155 mock_core .sf_core_full_version = mock .MagicMock (return_value = mock_version )
121156
122- with mock .patch .object (
123- loader , "_get_core_path" , return_value = mock_path
124- ) as mock_get_path :
157+ with mock .patch .object (loader , "_is_core_disabled" , return_value = False ):
125158 with mock .patch .object (
126- loader , "_load_minicore" , return_value = mock_core
127- ) as mock_load :
128- with mock .patch .object (loader , "_register_functions" ) as mock_register :
129- loader .load ()
130-
131- mock_get_path .assert_called_once ()
132- mock_load .assert_called_once_with (mock_path )
133- mock_register .assert_called_once_with (mock_core )
134- assert loader ._version == mock_version
135- assert loader ._error is None
159+ loader , "_get_core_path" , return_value = mock_path
160+ ) as mock_get_path :
161+ with mock .patch .object (
162+ loader , "_load_minicore" , return_value = mock_core
163+ ) as mock_load :
164+ with mock .patch .object (
165+ loader , "_register_functions"
166+ ) as mock_register :
167+ loader .load ()
168+
169+ mock_get_path .assert_called_once ()
170+ mock_load .assert_called_once_with (mock_path )
171+ mock_register .assert_called_once_with (mock_core )
172+ assert loader ._version == mock_version
173+ assert loader ._error is None
136174
137175 def test_load_failure (self ):
138176 """Test that load captures exceptions."""
139177 loader = _CoreLoader ()
140178 test_error = Exception ("Test error loading core" )
141179
142- with mock .patch .object (
143- loader , "_get_core_path" , side_effect = test_error
144- ) as mock_get_path :
145- loader .load ()
180+ with mock .patch .object (loader , "_is_core_disabled" , return_value = False ):
181+ with mock .patch .object (
182+ loader , "_get_core_path" , side_effect = test_error
183+ ) as mock_get_path :
184+ loader .load ()
146185
147- mock_get_path .assert_called_once ()
148- assert loader ._version is None
149- assert loader ._error == test_error
186+ mock_get_path .assert_called_once ()
187+ assert loader ._version is None
188+ assert loader ._error == test_error
150189
151190 def test_get_load_error_with_error (self ):
152191 """Test get_load_error returns error message when error exists."""
@@ -190,7 +229,7 @@ def test_importing_snowflake_connector_triggers_core_loader_load():
190229 # core_loader.load() is called. Since snowflake.connector is already imported,
191230 # we need to reload it and mock the load method.
192231
193- with mock .patch ("snowflake.connector._utils.core_loader .load" ) as mock_load :
232+ with mock .patch ("snowflake.connector._utils._core_loader .load" ) as mock_load :
194233 # Reload the connector module to trigger the __init__.py code again
195234 import snowflake .connector
196235
@@ -204,7 +243,7 @@ def test_snowflake_connector_loads_when_core_loader_fails():
204243 """Test that snowflake.connector loads successfully even if core_loader.load() fails."""
205244 # Mock core_loader.load() to raise an exception
206245 with mock .patch (
207- "snowflake.connector._utils.core_loader .load" ,
246+ "snowflake.connector._utils._core_loader .load" ,
208247 side_effect = Exception ("Simulated core loading failure" ),
209248 ):
210249 import snowflake .connector
@@ -229,7 +268,7 @@ def test_snowflake_connector_usable_when_core_loader_fails():
229268 """Test that snowflake.connector remains usable even if core_loader.load() fails."""
230269 # Mock core_loader.load() to raise an exception
231270 with mock .patch (
232- "snowflake.connector._utils.core_loader .load" ,
271+ "snowflake.connector._utils._core_loader .load" ,
233272 side_effect = RuntimeError ("Core library not found" ),
234273 ):
235274 import snowflake .connector
@@ -259,32 +298,34 @@ def test_core_loader_error_captured_when_load_fails():
259298 test_exception = FileNotFoundError ("Library file not found" )
260299
261300 # Mock _get_core_path to raise an exception
262- with mock .patch .object (loader , "_get_core_path" , side_effect = test_exception ):
263- # Call load - it should NOT raise an exception
264- loader .load ()
301+ with mock .patch .object (loader , "_is_core_disabled" , return_value = False ):
302+ with mock .patch .object (loader , "_get_core_path" , side_effect = test_exception ):
303+ # Call load - it should NOT raise an exception
304+ loader .load ()
265305
266- # Verify the error was captured
267- assert loader ._error is test_exception
268- assert loader ._version is None
269- assert loader .get_load_error () == "Library file not found"
270- assert loader .get_core_version () is None
306+ # Verify the error was captured
307+ assert loader ._error is test_exception
308+ assert loader ._version is None
309+ assert loader .get_load_error () == "Library file not found"
310+ assert loader .get_core_version () is None
271311
272312
273313def test_core_loader_fails_gracefully_on_missing_library ():
274314 """Test that core_loader handles missing library files gracefully."""
275315 loader = _CoreLoader ()
276316
277317 # Mock importlib.resources.files to simulate missing library
278- with mock .patch ("importlib.resources.files" ) as mock_files :
279- mock_files .side_effect = FileNotFoundError ("minicore module not found" )
318+ with mock .patch .object (loader , "_is_core_disabled" , return_value = False ):
319+ with mock .patch ("importlib.resources.files" ) as mock_files :
320+ mock_files .side_effect = FileNotFoundError ("minicore module not found" )
280321
281- # Call load - it should NOT raise an exception
282- loader .load ()
322+ # Call load - it should NOT raise an exception
323+ loader .load ()
283324
284- # Verify the error was captured
285- assert loader ._error is not None
286- assert loader ._version is None
287- assert "minicore module not found" in loader .get_load_error ()
325+ # Verify the error was captured
326+ assert loader ._error is not None
327+ assert loader ._version is None
328+ assert "minicore module not found" in loader .get_load_error ()
288329
289330
290331def test_core_loader_fails_gracefully_on_incompatible_library ():
@@ -293,16 +334,17 @@ def test_core_loader_fails_gracefully_on_incompatible_library():
293334 mock_path = mock .MagicMock ()
294335
295336 # Mock the loading to simulate incompatible library (OSError is common for this)
296- with mock .patch .object (loader , "_get_core_path" , return_value = mock_path ):
297- with mock .patch .object (
298- loader ,
299- "_load_minicore" ,
300- side_effect = OSError ("incompatible library version" ),
301- ):
302- # Call load - it should NOT raise an exception
303- loader .load ()
304-
305- # Verify the error was captured
306- assert loader ._error is not None
307- assert loader ._version is None
308- assert "incompatible library version" in loader .get_load_error ()
337+ with mock .patch .object (loader , "_is_core_disabled" , return_value = False ):
338+ with mock .patch .object (loader , "_get_core_path" , return_value = mock_path ):
339+ with mock .patch .object (
340+ loader ,
341+ "_load_minicore" ,
342+ side_effect = OSError ("incompatible library version" ),
343+ ):
344+ # Call load - it should NOT raise an exception
345+ loader .load ()
346+
347+ # Verify the error was captured
348+ assert loader ._error is not None
349+ assert loader ._version is None
350+ assert "incompatible library version" in loader .get_load_error ()
0 commit comments