Skip to content

Commit 009ca84

Browse files
NO-SNOW: Add core library import
1 parent 465e2c3 commit 009ca84

File tree

6 files changed

+360
-2
lines changed

6 files changed

+360
-2
lines changed

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ repair-wheel-command = ""
2323

2424
[tool.cibuildwheel.windows]
2525
archs = ["AMD64"]
26+
27+
[tool.check-manifest]
28+
ignore = ["src/snowflake/connector/minicore/*"]

setup.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ where = src
7272
exclude = snowflake.connector.cpp*
7373
include = snowflake.*
7474

75+
[options.package_data]
76+
snowflake.connector.minicore =
77+
*.so
78+
*.dll
79+
*.dylib
80+
7581
[options.entry_points]
7682
console_scripts =
7783
snowflake-dump-ocsp-response = snowflake.connector.tool.dump_ocsp_response:main

src/snowflake/connector/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from functools import wraps
77

8+
from ._utils import core_loader
9+
810
apilevel = "2.0"
911
threadsafety = 2
1012
paramstyle = "pyformat"
@@ -48,6 +50,14 @@
4850
logging.getLogger(__name__).addHandler(NullHandler())
4951
setup_external_libraries()
5052

53+
# Load the core library - failures are captured in core_loader and don't prevent module loading
54+
try:
55+
core_loader.load()
56+
except Exception:
57+
# Silently continue if core loading fails - the error is already captured in core_loader
58+
# This ensures the connector module loads even if the minicore library is unavailable
59+
pass
60+
5161

5262
@wraps(SnowflakeConnection.__init__)
5363
def Connect(**kwargs) -> SnowflakeConnection:

src/snowflake/connector/_utils.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from __future__ import annotations
22

3+
import ctypes
4+
import importlib
35
import string
6+
import sys
47
from enum import Enum
58
from inspect import stack
69
from random import choice
@@ -96,3 +99,55 @@ def get_application_path() -> str:
9699
return outermost_frame.filename
97100
except Exception:
98101
return "unknown"
102+
103+
104+
class _CoreLoader:
105+
def __init__(self):
106+
self._version: bytes | None = None
107+
self._error: Exception | None = None
108+
109+
@staticmethod
110+
def _get_core_path():
111+
# Define the file name for each platform
112+
if sys.platform.startswith("win"):
113+
lib_name = "libsf_mini_core.dll"
114+
elif sys.platform.startswith("darwin"):
115+
lib_name = "libsf_mini_core.dyldib"
116+
else:
117+
lib_name = "libsf_mini_core.so"
118+
119+
files = importlib.resources.files("snowflake.connector.minicore")
120+
return files.joinpath(lib_name)
121+
122+
@staticmethod
123+
def _register_functions(core: ctypes.CDLL):
124+
core.sf_core_full_version.argtypes = []
125+
core.sf_core_full_version.restype = ctypes.c_char_p
126+
127+
@staticmethod
128+
def _load_minicore(path: str) -> ctypes.CDLL:
129+
# This context manager is the safe way to get a
130+
# file path from importlib.resources. It handles cases
131+
# where the file is inside a zip and needs to be extracted
132+
# to a temporary location.
133+
with importlib.resources.as_file(path) as lib_path:
134+
core = ctypes.CDLL(str(lib_path))
135+
return core
136+
137+
def load(self) -> None:
138+
try:
139+
path = self._get_core_path()
140+
core = self._load_minicore(path)
141+
self._register_functions(core)
142+
self._version = core.sf_core_full_version()
143+
except Exception as err:
144+
self._error = err
145+
146+
def get_load_error(self) -> str:
147+
return str(self._error)
148+
149+
def get_core_version(self) -> str:
150+
return self._version.decode("utf-8") if self._version else self._version
151+
152+
153+
core_loader = _CoreLoader()

src/snowflake/connector/auth/_auth.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
load_pem_private_key,
1818
)
1919

20-
from .._utils import get_application_path
20+
from .._utils import core_loader, get_application_path
2121
from ..compat import urlencode
2222
from ..constants import (
2323
DAY_IN_SECONDS,
@@ -144,6 +144,8 @@ def base_auth_data(
144144
platform_detection_timeout_seconds=platform_detection_timeout_seconds,
145145
session_manager=session_manager.clone(max_retries=0),
146146
),
147+
"CORE_LOAD_ERROR": core_loader.get_load_error(),
148+
"CORE_VERSION": core_loader.get_core_version(),
147149
},
148150
},
149151
}

0 commit comments

Comments
 (0)