Skip to content

Commit 7bf87ce

Browse files
fixup! Add option to disable core loading
1 parent 7d412f4 commit 7bf87ce

File tree

5 files changed

+61
-10
lines changed

5 files changed

+61
-10
lines changed

src/snowflake/connector/_utils.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ class _CoreLoader:
107107
def __init__(self):
108108
self._version: bytes | None = None
109109
self._error: Exception | None = None
110+
self._path: str | None = None
110111

111112
@staticmethod
112-
def _get_core_path():
113+
def _get_core_path() -> Path:
113114
# Define the file name for each platform
114115
if sys.platform.startswith("win"):
115116
lib_name = "libsf_mini_core.dll"
@@ -147,6 +148,7 @@ def _load(self) -> None:
147148
self._register_functions(core)
148149
self._version = core.sf_core_full_version()
149150
self._error = None
151+
self._path = str(path)
150152
except Exception as err:
151153
self._error = err
152154

@@ -170,5 +172,8 @@ def get_core_version(self) -> str | None:
170172
pass
171173
return None
172174

175+
def get_file_name(self) -> str:
176+
return self._path
177+
173178

174179
_core_loader = _CoreLoader()

src/snowflake/connector/connection.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@
9494
from .description import (
9595
CLIENT_NAME,
9696
CLIENT_VERSION,
97+
ISA,
98+
OPERATING_SYSTEM,
99+
OS_VERSION,
97100
PLATFORM,
98101
PYTHON_VERSION,
99102
SNOWFLAKE_CONNECTOR_VERSION,
@@ -2491,14 +2494,27 @@ def async_query_check_helper(
24912494
return not found_unfinished_query
24922495

24932496
def _log_minicore_import(self):
2497+
"""
2498+
OS - meaningful value like Windows, Linux, Darwin/MacOS etc.
2499+
OS_VERSION - meaningful version like kernel version for Linux/Darwin, etc. that your language provides
2500+
ISA - instruction set architecture, like amd64/arm64.
2501+
CORE_VERSION - result of sf_core_full_version call, if finished successfully.
2502+
CORE_FILE_NAME - a string representing binary name that driver tried to load
2503+
CORE_LOAD_ERROR - flag or error type included if there are any errors (can’t write a library to disk, can’t load it, can’t find symbols, etc).
2504+
:return:
2505+
"""
24942506
ts = get_time_millis()
24952507
self._log_telemetry(
24962508
TelemetryData.from_telemetry_data_dict(
24972509
from_dict={
24982510
TelemetryField.KEY_TYPE.value: TelemetryField.CORE_IMPORT.value,
24992511
TelemetryField.KEY_VALUE: {
2500-
"CORE_LOAD_ERROR": _core_loader.get_load_error(),
2512+
"OS": OPERATING_SYSTEM,
2513+
"OS_VERSION": OS_VERSION,
2514+
"ISA": ISA,
25012515
"CORE_VERSION": _core_loader.get_core_version(),
2516+
"CORE_FILE_NAME": _core_loader.get_file_name(),
2517+
"CORE_LOAD_ERROR": _core_loader.get_load_error(),
25022518
},
25032519
},
25042520
timestamp=ts,

src/snowflake/connector/description.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
PYTHON_VERSION = ".".join(str(v) for v in sys.version_info[:3])
1313
OPERATING_SYSTEM = platform.system()
1414
PLATFORM = platform.platform()
15+
OS_VERSION = platform.version()
16+
ISA = platform.machine()
1517
IMPLEMENTATION = platform.python_implementation()
1618
COMPILER = platform.python_compiler()
1719

test/integ/test_connection.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@
1919

2020
import snowflake.connector
2121
from snowflake.connector import DatabaseError, OperationalError, ProgrammingError
22+
from snowflake.connector._utils import _core_loader
2223
from snowflake.connector.compat import IS_WINDOWS
2324
from snowflake.connector.connection import (
2425
DEFAULT_CLIENT_PREFETCH_THREADS,
2526
SnowflakeConnection,
2627
)
27-
from snowflake.connector.description import CLIENT_NAME
28+
from snowflake.connector.description import (
29+
CLIENT_NAME,
30+
ISA,
31+
OPERATING_SYSTEM,
32+
OS_VERSION,
33+
)
2834
from snowflake.connector.errorcode import (
2935
ER_CONNECTION_IS_CLOSED,
3036
ER_FAILED_PROCESSING_PYFORMAT,
@@ -1232,7 +1238,7 @@ def check_packages(message: str, expected_packages: list[str]) -> bool:
12321238

12331239
@pytest.mark.skipolddriver
12341240
def test_minicore_import_telemetry(conn_cnx, capture_sf_telemetry):
1235-
"""Test that minicore import telemetry (CORE_LOAD_ERROR and CORE_VERSION) is logged."""
1241+
"""Test that minicore import telemetry is logged with all required fields and correct values."""
12361242
with (
12371243
conn_cnx() as conn,
12381244
capture_sf_telemetry.patch_connection(conn, False) as telemetry_test,
@@ -1248,12 +1254,14 @@ def test_minicore_import_telemetry(conn_cnx, capture_sf_telemetry):
12481254
and TelemetryField.KEY_VALUE.value in t.message
12491255
):
12501256
found_minicore_telemetry = True
1251-
# Verify that the value contains CORE_LOAD_ERROR and CORE_VERSION
1257+
# Verify that the value contains all required fields with correct values
12521258
value = t.message[TelemetryField.KEY_VALUE.value]
1253-
assert (
1254-
"CORE_LOAD_ERROR" in value
1255-
), "CORE_LOAD_ERROR not in telemetry value"
1256-
assert "CORE_VERSION" in value, "CORE_VERSION not in telemetry value"
1259+
assert value["OS"] == OPERATING_SYSTEM
1260+
assert value["OS_VERSION"] == OS_VERSION
1261+
assert value["ISA"] == ISA
1262+
assert value["CORE_VERSION"] == _core_loader.get_core_version()
1263+
assert value["CORE_FILE_NAME"] == _core_loader.get_file_name()
1264+
assert value["CORE_LOAD_ERROR"] == _core_loader.get_load_error()
12571265
break
12581266
assert (
12591267
found_minicore_telemetry

test/unit/test_util.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def test_core_loader_initialization(self):
4040
loader = _CoreLoader()
4141
assert loader._version is None
4242
assert loader._error is None
43+
assert loader._path is None
4344

4445
def test_get_core_path_windows(self):
4546
"""Test _get_core_path returns correct path for Windows."""
@@ -129,7 +130,7 @@ def test_is_core_disabled_returns_false_when_not_set(self):
129130
loader = _CoreLoader()
130131
with mock.patch.dict(os.environ, {}, clear=True):
131132
# Ensure the env var is not set
132-
os.environ.pop("SNOWFLAKE_DISABLE_CORE", None)
133+
os.environ.pop("SNOWFLAKE_DISABLE_MINICORE", None)
133134
assert loader._is_core_disabled() is False
134135

135136
def test_load_skips_loading_when_core_disabled(self):
@@ -171,6 +172,7 @@ def test_load_success(self):
171172
mock_register.assert_called_once_with(mock_core)
172173
assert loader._version == mock_version
173174
assert loader._error is None
175+
assert loader._path == str(mock_path)
174176

175177
def test_load_failure(self):
176178
"""Test that load captures exceptions."""
@@ -186,6 +188,7 @@ def test_load_failure(self):
186188
mock_get_path.assert_called_once()
187189
assert loader._version is None
188190
assert loader._error == test_error
191+
assert loader._path is None
189192

190193
def test_get_load_error_with_error(self):
191194
"""Test get_load_error returns error message when error exists."""
@@ -222,6 +225,23 @@ def test_get_core_version_no_version(self):
222225

223226
assert result is None
224227

228+
def test_get_file_name_with_path(self):
229+
"""Test get_file_name returns the path string after successful load."""
230+
loader = _CoreLoader()
231+
loader._path = "/path/to/libsf_mini_core.so"
232+
233+
result = loader.get_file_name()
234+
235+
assert result == "/path/to/libsf_mini_core.so"
236+
237+
def test_get_file_name_no_path(self):
238+
"""Test get_file_name returns None when no path exists."""
239+
loader = _CoreLoader()
240+
241+
result = loader.get_file_name()
242+
243+
assert result is None
244+
225245

226246
def test_importing_snowflake_connector_triggers_core_loader_load():
227247
"""Test that importing snowflake.connector triggers core_loader.load()."""

0 commit comments

Comments
 (0)