snowflake-connector-python 5.2.0__cp315-cp315-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snowflake/connector/__init__.py +148 -0
- snowflake/connector/_common/__init__.py +0 -0
- snowflake/connector/_common/extras.py +134 -0
- snowflake/connector/_common/telemetry.py +221 -0
- snowflake/connector/_common/wif_util.py +92 -0
- snowflake/connector/_core/sf_core_python.cp315-win_amd64.pyd +0 -0
- snowflake/connector/_core/sf_core_python.pyi +79 -0
- snowflake/connector/_internal/__init__.py +6 -0
- snowflake/connector/_internal/_private_key_helper.py +31 -0
- snowflake/connector/_internal/api_client/__init__.py +93 -0
- snowflake/connector/_internal/api_client/bridge.py +41 -0
- snowflake/connector/_internal/api_client/client_api.py +976 -0
- snowflake/connector/_internal/arrow.py +47 -0
- snowflake/connector/_internal/arrow_context.py +240 -0
- snowflake/connector/_internal/arrow_stream_async.py +266 -0
- snowflake/connector/_internal/arrow_stream_iterator.cp311-win_amd64.pyd +0 -0
- snowflake/connector/_internal/arrow_stream_iterator.cp312-win_amd64.pyd +0 -0
- snowflake/connector/_internal/arrow_stream_iterator.cp313-win_amd64.pyd +0 -0
- snowflake/connector/_internal/arrow_stream_iterator.cp314-win_amd64.pyd +0 -0
- snowflake/connector/_internal/arrow_stream_iterator.cp314t-win_amd64.pyd +0 -0
- snowflake/connector/_internal/arrow_stream_iterator.cp315-win_amd64.pyd +0 -0
- snowflake/connector/_internal/arrow_stream_iterator.pyi +42 -0
- snowflake/connector/_internal/arrow_stream_utils.py +171 -0
- snowflake/connector/_internal/authenticator_type.py +53 -0
- snowflake/connector/_internal/backward_compatibility.py +245 -0
- snowflake/connector/_internal/binding_converters.py +741 -0
- snowflake/connector/_internal/config_utils.py +71 -0
- snowflake/connector/_internal/connection/__init__.py +39 -0
- snowflake/connector/_internal/connection/connection.py +616 -0
- snowflake/connector/_internal/connection/connection_types.py +13 -0
- snowflake/connector/_internal/connection/constants.py +25 -0
- snowflake/connector/_internal/connection/decorators.py +31 -0
- snowflake/connector/_internal/connection/freezable_proxy.py +104 -0
- snowflake/connector/_internal/connection/queries.py +10 -0
- snowflake/connector/_internal/connection_config_mixin.py +755 -0
- snowflake/connector/_internal/cursor/__init__.py +25 -0
- snowflake/connector/_internal/cursor/base.py +732 -0
- snowflake/connector/_internal/cursor/cursor_types.py +13 -0
- snowflake/connector/_internal/cursor/decorators.py +56 -0
- snowflake/connector/_internal/cursor/query_result.py +202 -0
- snowflake/connector/_internal/cursor/query_result_waiter.py +98 -0
- snowflake/connector/_internal/cursor/result_metadata.py +255 -0
- snowflake/connector/_internal/cursor/result_set_wrapper.py +66 -0
- snowflake/connector/_internal/decorators.py +539 -0
- snowflake/connector/_internal/error_kinds.py +111 -0
- snowflake/connector/_internal/errorcode.py +35 -0
- snowflake/connector/_internal/errorhandler.py +278 -0
- snowflake/connector/_internal/fips.py +28 -0
- snowflake/connector/_internal/logging/__init__.py +52 -0
- snowflake/connector/_internal/logging/config.py +134 -0
- snowflake/connector/_internal/logging/core_logger.py +218 -0
- snowflake/connector/_internal/logging/native_extension_logger.py +144 -0
- snowflake/connector/_internal/logout_config_mapping.py +187 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +57 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrowTableConverter.cpp +943 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrowTableConverter.hpp +63 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +18 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +118 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +116 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamIterator.cpp +323 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamIterator.hpp +133 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamTableIterator.cpp +275 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamTableIterator.hpp +168 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ConverterUtil.cpp +439 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ConverterUtil.hpp +30 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +48 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +76 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +90 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +63 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +62 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +29 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +41 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +65 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +54 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +79 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +52 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +117 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +54 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +34 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +33 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +18 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +39 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +326 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +138 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/time.cpp +65 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/arrow_stream_iterator.cpp +13278 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/arrow_stream_iterator.pyx +204 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +109 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +125 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1914 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +208 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +128 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +58 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +144 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +160 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +98 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +243 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +207 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +80 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +83 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +201 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +108 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +164 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +926 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +182 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc.c +3052 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3019 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3354 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +344 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +29305 -0
- snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +381 -0
- snowflake/connector/_internal/nanoarrow_cpp/Logging/logging.cpp +108 -0
- snowflake/connector/_internal/nanoarrow_cpp/Logging/logging.hpp +47 -0
- snowflake/connector/_internal/nanoarrow_cpp/scripts/.clang-format +8 -0
- snowflake/connector/_internal/nanoarrow_cpp/scripts/format.sh +8 -0
- snowflake/connector/_internal/protobuf_gen/__init__.py +0 -0
- snowflake/connector/_internal/protobuf_gen/database_driver_v1_pb2.py +408 -0
- snowflake/connector/_internal/protobuf_gen/database_driver_v1_pb2.pyi +4487 -0
- snowflake/connector/_internal/protobuf_gen/database_driver_v1_services.py +2088 -0
- snowflake/connector/_internal/protobuf_gen/proto_exception.py +17 -0
- snowflake/connector/_internal/result_batch.py +150 -0
- snowflake/connector/_internal/snowflake_restful.py +222 -0
- snowflake/connector/_internal/snowpark_backcompat_helpers.py +31 -0
- snowflake/connector/_internal/sqlstate.py +11 -0
- snowflake/connector/_internal/statement_utils.py +207 -0
- snowflake/connector/_internal/text_utils.py +112 -0
- snowflake/connector/_internal/type_codes.py +139 -0
- snowflake/connector/_internal/utils.py +65 -0
- snowflake/connector/_internal/write_pandas_operation.py +657 -0
- snowflake/connector/aio/README.md +168 -0
- snowflake/connector/aio/__init__.py +37 -0
- snowflake/connector/aio/connection/__init__.py +17 -0
- snowflake/connector/aio/connection/_connection.py +506 -0
- snowflake/connector/aio/cursor/__init__.py +35 -0
- snowflake/connector/aio/cursor/_base.py +1034 -0
- snowflake/connector/aio/cursor/_dict_cursor.py +78 -0
- snowflake/connector/aio/cursor/_result_set_wrapper.py +35 -0
- snowflake/connector/aio/cursor/_snowflake_cursor.py +72 -0
- snowflake/connector/aio/pandas_tools.py +279 -0
- snowflake/connector/aio/result_batch.py +165 -0
- snowflake/connector/auth/__init__.py +0 -0
- snowflake/connector/auth/workload_identity.py +5 -0
- snowflake/connector/compat.py +22 -0
- snowflake/connector/config_manager.py +392 -0
- snowflake/connector/connection/__init__.py +30 -0
- snowflake/connector/connection/_connection.py +641 -0
- snowflake/connector/connection_config.py +517 -0
- snowflake/connector/constants.py +52 -0
- snowflake/connector/cursor/__init__.py +37 -0
- snowflake/connector/cursor/_base.py +1169 -0
- snowflake/connector/cursor/_chunked_download_reader.py +75 -0
- snowflake/connector/cursor/_dict_cursor.py +78 -0
- snowflake/connector/cursor/_result_set_wrapper.py +35 -0
- snowflake/connector/cursor/_snowflake_cursor.py +72 -0
- snowflake/connector/description.py +7 -0
- snowflake/connector/errors.py +492 -0
- snowflake/connector/network.py +71 -0
- snowflake/connector/pandas_tools.py +191 -0
- snowflake/connector/py.typed +0 -0
- snowflake/connector/result_batch.py +216 -0
- snowflake/connector/telemetry.py +40 -0
- snowflake/connector/time_util.py +11 -0
- snowflake/connector/types.py +134 -0
- snowflake/connector/util_text.py +3 -0
- snowflake/connector/version.py +23 -0
- snowflake_connector_python-5.2.0.dist-info/DELVEWHEEL +2 -0
- snowflake_connector_python-5.2.0.dist-info/METADATA +190 -0
- snowflake_connector_python-5.2.0.dist-info/RECORD +204 -0
- snowflake_connector_python-5.2.0.dist-info/WHEEL +4 -0
- snowflake_connector_python.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ConfigManager implementation that wraps the Rust sf_core config management API.
|
|
3
|
+
|
|
4
|
+
This module provides backward compatibility with the old Python Snowflake driver's
|
|
5
|
+
ConfigManager while using the Rust core for actual configuration management.
|
|
6
|
+
All file I/O, TOML parsing, and permission checks are performed by sf_core.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
from collections.abc import Callable, Iterable
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any, Literal, NamedTuple, TypeVar
|
|
17
|
+
|
|
18
|
+
import tomlkit
|
|
19
|
+
|
|
20
|
+
from ._internal.api_client.client_api import core_driver
|
|
21
|
+
from ._internal.logging import get_logger
|
|
22
|
+
from ._internal.protobuf_gen.proto_exception import ProtoApplicationException
|
|
23
|
+
from .errors import ConfigManagerError, ConfigSourceError, MissingConfigOptionError
|
|
24
|
+
from .errors import Error as DriverError
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
_T = TypeVar("_T")
|
|
28
|
+
|
|
29
|
+
LOGGER = get_logger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ConfigSliceOptions(NamedTuple):
|
|
33
|
+
"""Class that defines settings individual configuration files."""
|
|
34
|
+
|
|
35
|
+
check_permissions: bool = True
|
|
36
|
+
only_in_slice: bool = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ConfigSlice(NamedTuple):
|
|
40
|
+
path: Path
|
|
41
|
+
options: ConfigSliceOptions
|
|
42
|
+
section: str
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _dict_to_tomlkit_container(data: dict[str, Any]) -> Any:
|
|
46
|
+
"""Wrap a nested plain dict in tomlkit types for CLI backward compatibility."""
|
|
47
|
+
doc = tomlkit.document()
|
|
48
|
+
_populate_tomlkit(doc, data)
|
|
49
|
+
return doc
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _populate_tomlkit(target: Any, source: dict[str, Any]) -> None:
|
|
53
|
+
"""Recursively copy *source* into a tomlkit container *target*."""
|
|
54
|
+
for key, value in source.items():
|
|
55
|
+
if value is None:
|
|
56
|
+
continue
|
|
57
|
+
if isinstance(value, dict):
|
|
58
|
+
table = tomlkit.table()
|
|
59
|
+
_populate_tomlkit(table, value)
|
|
60
|
+
target.add(key, table)
|
|
61
|
+
elif isinstance(value, bytes):
|
|
62
|
+
target.add(key, value.decode("utf-8", errors="replace"))
|
|
63
|
+
else:
|
|
64
|
+
target.add(key, value)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _extract_error_msg(exc: Exception) -> str:
|
|
68
|
+
"""Extract the raw error message from a proto or PEP 249 exception."""
|
|
69
|
+
if hasattr(exc, "message"):
|
|
70
|
+
return str(exc.message)
|
|
71
|
+
if hasattr(exc, "raw_msg"):
|
|
72
|
+
return str(exc.raw_msg)
|
|
73
|
+
return str(exc)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _translate_core_error(
|
|
77
|
+
exc: Exception,
|
|
78
|
+
file_path: Path | None = None,
|
|
79
|
+
) -> DriverError:
|
|
80
|
+
"""Translate a Rust core DriverException into the appropriate Python error.
|
|
81
|
+
|
|
82
|
+
Maps sf_core error messages to backward-compatible Python exception types.
|
|
83
|
+
Accepts both raw ``ProtoApplicationException`` and PEP 249 ``Error``
|
|
84
|
+
subclasses (produced by the error_handler in the generated client).
|
|
85
|
+
"""
|
|
86
|
+
msg = _extract_error_msg(exc)
|
|
87
|
+
|
|
88
|
+
if "parse TOML" in msg or "Failed to parse" in msg or "Failed to read config file" in msg:
|
|
89
|
+
display_path = str(file_path) if file_path else "unknown"
|
|
90
|
+
return ConfigSourceError(f"An unknown error happened while loading '{display_path}'")
|
|
91
|
+
|
|
92
|
+
return ConfigManagerError(msg)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ConfigOption:
|
|
96
|
+
"""ConfigOption represents a flag/setting.
|
|
97
|
+
|
|
98
|
+
This class is backward compatible with the old Python driver's ConfigOption
|
|
99
|
+
but uses the Rust core for actual configuration retrieval.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
*,
|
|
105
|
+
name: str,
|
|
106
|
+
parse_str: Callable[[str], _T] | None = None,
|
|
107
|
+
choices: Iterable[Any] | None = None,
|
|
108
|
+
env_name: str | None | Literal[False] = None,
|
|
109
|
+
default: Any | None = None,
|
|
110
|
+
_root_manager: ConfigManager | None = None,
|
|
111
|
+
_nest_path: list[str] | None = None,
|
|
112
|
+
) -> None:
|
|
113
|
+
if _root_manager is None:
|
|
114
|
+
raise TypeError("_root_manager cannot be None")
|
|
115
|
+
if _nest_path is None:
|
|
116
|
+
raise TypeError("_nest_path cannot be None")
|
|
117
|
+
|
|
118
|
+
self.name = name
|
|
119
|
+
self.parse_str = parse_str
|
|
120
|
+
self.choices = choices
|
|
121
|
+
self._nest_path = _nest_path + [name]
|
|
122
|
+
self._root_manager: ConfigManager = _root_manager
|
|
123
|
+
self.env_name = env_name
|
|
124
|
+
self.default = default
|
|
125
|
+
|
|
126
|
+
def value(self) -> Any:
|
|
127
|
+
"""Retrieve a value of option.
|
|
128
|
+
|
|
129
|
+
Priority: Custom Environment Variable > Config File > Default
|
|
130
|
+
"""
|
|
131
|
+
source = "configuration file"
|
|
132
|
+
value = None
|
|
133
|
+
|
|
134
|
+
if self.env_name is not False:
|
|
135
|
+
env_name = self.env_name or self.default_env_name
|
|
136
|
+
if env_name:
|
|
137
|
+
env_var = os.environ.get(env_name)
|
|
138
|
+
if env_var is not None:
|
|
139
|
+
source = "environment variable"
|
|
140
|
+
value = self.parse_str(env_var) if self.parse_str else env_var
|
|
141
|
+
|
|
142
|
+
if value is None:
|
|
143
|
+
try:
|
|
144
|
+
value = self._get_config()
|
|
145
|
+
source = "configuration file"
|
|
146
|
+
except MissingConfigOptionError:
|
|
147
|
+
if self.default is not None:
|
|
148
|
+
source = "default_value"
|
|
149
|
+
value = self.default
|
|
150
|
+
else:
|
|
151
|
+
raise
|
|
152
|
+
|
|
153
|
+
if self.choices and value not in self.choices:
|
|
154
|
+
raise ConfigSourceError(f"The value of {self.option_name} read from {source} is not part of {self.choices}")
|
|
155
|
+
|
|
156
|
+
return value
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def option_name(self) -> str:
|
|
160
|
+
return ".".join(self._nest_path[1:])
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def default_env_name(self) -> str:
|
|
164
|
+
pieces = [p.upper() for p in self._nest_path[1:]]
|
|
165
|
+
return f"SNOWFLAKE_{'_'.join(pieces)}"
|
|
166
|
+
|
|
167
|
+
def _get_config(self) -> Any:
|
|
168
|
+
"""Get value from the nested cached configuration loaded by sf_core.
|
|
169
|
+
|
|
170
|
+
Dict values that contain sub-dicts are wrapped in tomlkit types so
|
|
171
|
+
that the CLI's ``isinstance(section, Container)`` / ``Table`` gates
|
|
172
|
+
work for environment-variable merging.
|
|
173
|
+
"""
|
|
174
|
+
nested_config = self._root_manager._get_cached_config()
|
|
175
|
+
|
|
176
|
+
if not nested_config:
|
|
177
|
+
raise MissingConfigOptionError(
|
|
178
|
+
f"Configuration option '{self.option_name}' is not defined anywhere, "
|
|
179
|
+
"have you forgotten to set it in a configuration file, or "
|
|
180
|
+
"environmental variable?"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
path_parts = self._nest_path[1:]
|
|
184
|
+
current = nested_config
|
|
185
|
+
for part in path_parts:
|
|
186
|
+
try:
|
|
187
|
+
current = current[part]
|
|
188
|
+
except (KeyError, TypeError) as err:
|
|
189
|
+
raise MissingConfigOptionError(
|
|
190
|
+
f"Configuration option '{self.option_name}' is not defined anywhere, "
|
|
191
|
+
"have you forgotten to set it in a configuration file, or "
|
|
192
|
+
"environmental variable?"
|
|
193
|
+
) from err
|
|
194
|
+
|
|
195
|
+
return _dict_to_tomlkit_container(current) if isinstance(current, dict) else current
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class ConfigManager:
|
|
199
|
+
"""Read a TOML configuration file with managed multi-source precedence.
|
|
200
|
+
|
|
201
|
+
This class provides backward compatibility with the old Python driver's
|
|
202
|
+
ConfigManager while using the Rust sf_core for actual file I/O,
|
|
203
|
+
TOML parsing, and permission checks.
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
def __init__(
|
|
207
|
+
self,
|
|
208
|
+
*,
|
|
209
|
+
name: str,
|
|
210
|
+
file_path: Path | None = None,
|
|
211
|
+
_slices: list[ConfigSlice] | None = None,
|
|
212
|
+
):
|
|
213
|
+
if _slices is None:
|
|
214
|
+
_slices = list()
|
|
215
|
+
|
|
216
|
+
self.name = name
|
|
217
|
+
self.file_path = file_path
|
|
218
|
+
self._slices = _slices
|
|
219
|
+
|
|
220
|
+
self._options: dict[str, ConfigOption] = dict()
|
|
221
|
+
self._sub_managers: dict[str, ConfigManager] = dict()
|
|
222
|
+
|
|
223
|
+
self.conf_file_cache: dict[str, Any] | None = None
|
|
224
|
+
|
|
225
|
+
self._root_manager: ConfigManager = self
|
|
226
|
+
self._nest_path = [name]
|
|
227
|
+
|
|
228
|
+
def read_config(
|
|
229
|
+
self,
|
|
230
|
+
skip_file_permissions_check: bool = False,
|
|
231
|
+
) -> None:
|
|
232
|
+
"""Read and cache config file contents from sf_core.
|
|
233
|
+
|
|
234
|
+
Passes file_path and slice paths to the Rust core so it reads
|
|
235
|
+
the correct files. Translates core errors to Python exceptions.
|
|
236
|
+
|
|
237
|
+
When ``skip_file_permissions_check`` is ``True``, file-permission checks
|
|
238
|
+
on ``config.toml`` and ``connections.toml`` are bypassed (mirrors the
|
|
239
|
+
``unsafe_skip_config_file_permissions_check`` connection parameter).
|
|
240
|
+
"""
|
|
241
|
+
if self.file_path is None:
|
|
242
|
+
raise ConfigManagerError("ConfigManager is trying to read config file, but it doesn't have one")
|
|
243
|
+
|
|
244
|
+
connections_file = self._get_connections_file_path()
|
|
245
|
+
|
|
246
|
+
try:
|
|
247
|
+
response = core_driver.config_load_all_sections(
|
|
248
|
+
config_file=str(self.file_path),
|
|
249
|
+
connections_file=str(connections_file) if connections_file is not None else None,
|
|
250
|
+
skip_permissions=skip_file_permissions_check,
|
|
251
|
+
)
|
|
252
|
+
except (ProtoApplicationException, DriverError) as e:
|
|
253
|
+
msg = _extract_error_msg(e)
|
|
254
|
+
if "permission denied" in msg.lower():
|
|
255
|
+
# OS-level read failure (e.g. restrictive parent-directory permissions).
|
|
256
|
+
# Silently return empty cache — the process simply can't see this file.
|
|
257
|
+
LOGGER.debug(
|
|
258
|
+
"Config file '%s' could not be read due to no permission on its parent directory",
|
|
259
|
+
self.file_path,
|
|
260
|
+
)
|
|
261
|
+
self.conf_file_cache = {}
|
|
262
|
+
return
|
|
263
|
+
raise _translate_core_error(e, self.file_path) from e
|
|
264
|
+
|
|
265
|
+
nested_config: dict[str, Any] = json.loads(response.config_json) if response.config_json else {}
|
|
266
|
+
|
|
267
|
+
for slice_info in self._slices:
|
|
268
|
+
_slice_path, slice_options, slice_section = slice_info
|
|
269
|
+
if slice_options.only_in_slice:
|
|
270
|
+
nested_config.pop(slice_section, None)
|
|
271
|
+
|
|
272
|
+
self.conf_file_cache = nested_config
|
|
273
|
+
|
|
274
|
+
def _get_connections_file_path(self) -> Path | None:
|
|
275
|
+
"""Extract connections file path from slices configuration."""
|
|
276
|
+
for slice_info in self._slices:
|
|
277
|
+
slice_path, _slice_options, slice_section = slice_info
|
|
278
|
+
if slice_section == "connections":
|
|
279
|
+
return slice_path
|
|
280
|
+
return None
|
|
281
|
+
|
|
282
|
+
def _get_cached_config(self) -> dict[str, Any]:
|
|
283
|
+
"""Get cached config, loading from sf_core if cache is empty."""
|
|
284
|
+
if self.conf_file_cache is None:
|
|
285
|
+
if self.file_path is None:
|
|
286
|
+
return {}
|
|
287
|
+
self.read_config()
|
|
288
|
+
return self.conf_file_cache or {}
|
|
289
|
+
|
|
290
|
+
def clear_cache(self) -> None:
|
|
291
|
+
self.conf_file_cache = None
|
|
292
|
+
|
|
293
|
+
def add_option(
|
|
294
|
+
self,
|
|
295
|
+
*,
|
|
296
|
+
option_cls: type[ConfigOption] = ConfigOption,
|
|
297
|
+
**kwargs: Any,
|
|
298
|
+
) -> None:
|
|
299
|
+
kwargs["_root_manager"] = self._root_manager
|
|
300
|
+
kwargs["_nest_path"] = self._nest_path
|
|
301
|
+
new_option = option_cls(**kwargs)
|
|
302
|
+
self._check_child_conflict(new_option.name)
|
|
303
|
+
self._options[new_option.name] = new_option
|
|
304
|
+
|
|
305
|
+
def _check_child_conflict(self, name: str) -> None:
|
|
306
|
+
if name in (self._options.keys() | self._sub_managers.keys()):
|
|
307
|
+
raise ConfigManagerError(f"'{name}' sub-manager, or option conflicts with a child element of '{self.name}'")
|
|
308
|
+
|
|
309
|
+
def add_submanager(self, new_child: ConfigManager) -> None:
|
|
310
|
+
self._check_child_conflict(new_child.name)
|
|
311
|
+
self._sub_managers[new_child.name] = new_child
|
|
312
|
+
|
|
313
|
+
def _root_setter_helper(node: ConfigManager) -> None:
|
|
314
|
+
node._root_manager = self._root_manager
|
|
315
|
+
node._nest_path = self._nest_path + node._nest_path
|
|
316
|
+
for sub_manager in node._sub_managers.values():
|
|
317
|
+
_root_setter_helper(sub_manager)
|
|
318
|
+
for option in node._options.values():
|
|
319
|
+
option._root_manager = self._root_manager
|
|
320
|
+
option._nest_path = self._nest_path + option._nest_path
|
|
321
|
+
|
|
322
|
+
_root_setter_helper(new_child)
|
|
323
|
+
|
|
324
|
+
def __getitem__(self, name: str) -> ConfigOption | ConfigManager | Any:
|
|
325
|
+
self._root_manager._get_cached_config()
|
|
326
|
+
if name in self._options:
|
|
327
|
+
return self._options[name].value()
|
|
328
|
+
if name in self._sub_managers:
|
|
329
|
+
return self._sub_managers[name]
|
|
330
|
+
raise ConfigSourceError(f"No ConfigManager, or ConfigOption can be found with the name '{name}'")
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _get_config_paths_from_core() -> tuple[Path, Path]:
|
|
334
|
+
"""Retrieve config file paths from sf_core via protobuf."""
|
|
335
|
+
response = core_driver.config_get_paths()
|
|
336
|
+
return Path(response.config_file), Path(response.connections_file)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
# TODO: These paths are resolved at import time via an RPC to sf_core, which
|
|
340
|
+
# introduces I/O during module import. This can fail or hang if the native
|
|
341
|
+
# transport isn't available yet. Consider lazily resolving paths on first access
|
|
342
|
+
# (e.g., via a module-level getter or descriptor) with a safe fallback.
|
|
343
|
+
CONFIG_FILE, CONNECTIONS_FILE = _get_config_paths_from_core()
|
|
344
|
+
|
|
345
|
+
CONFIG_MANAGER = ConfigManager(
|
|
346
|
+
name="CONFIG_MANAGER",
|
|
347
|
+
file_path=CONFIG_FILE,
|
|
348
|
+
_slices=[
|
|
349
|
+
ConfigSlice(
|
|
350
|
+
CONNECTIONS_FILE,
|
|
351
|
+
ConfigSliceOptions(
|
|
352
|
+
check_permissions=True,
|
|
353
|
+
),
|
|
354
|
+
"connections",
|
|
355
|
+
),
|
|
356
|
+
],
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
CONFIG_MANAGER.add_option(
|
|
360
|
+
name="connections",
|
|
361
|
+
parse_str=tomlkit.parse,
|
|
362
|
+
default=dict(),
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
CONFIG_MANAGER.add_option(
|
|
366
|
+
name="default_connection_name",
|
|
367
|
+
default="default",
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _get_default_connection_params() -> dict[str, Any]:
|
|
372
|
+
"""Get default connection parameters from configuration."""
|
|
373
|
+
from snowflake.connector.errors import Error
|
|
374
|
+
|
|
375
|
+
def_connection_name = str(CONFIG_MANAGER["default_connection_name"])
|
|
376
|
+
connections: dict[str, Any] = CONFIG_MANAGER["connections"] # type: ignore[assignment]
|
|
377
|
+
|
|
378
|
+
if def_connection_name not in connections:
|
|
379
|
+
raise Error(
|
|
380
|
+
f"Default connection with name '{def_connection_name}' "
|
|
381
|
+
"cannot be found, known ones are "
|
|
382
|
+
f"{list(connections.keys())}"
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
return dict(connections[def_connection_name])
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
__all__ = [
|
|
389
|
+
"ConfigOption",
|
|
390
|
+
"ConfigManager",
|
|
391
|
+
"CONFIG_MANAGER",
|
|
392
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PEP 249 Database API 2.0 Connection Objects
|
|
3
|
+
|
|
4
|
+
This package defines the Connection class as specified in PEP 249.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from .._internal.connection.constants import (
|
|
10
|
+
APPLICATION_NAME as _APPLICATION_NAME,
|
|
11
|
+
)
|
|
12
|
+
from .._internal.connection.constants import (
|
|
13
|
+
CLIENT_NAME,
|
|
14
|
+
DEFAULT_CONFIGURATION,
|
|
15
|
+
LOG_MAX_QUERY_LENGTH,
|
|
16
|
+
)
|
|
17
|
+
from ..connection_config import ConnectionConfig, OptionsModifier
|
|
18
|
+
from ._connection import Connection, SnowflakeConnection
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"CLIENT_NAME",
|
|
23
|
+
"Connection",
|
|
24
|
+
"ConnectionConfig",
|
|
25
|
+
"DEFAULT_CONFIGURATION",
|
|
26
|
+
"LOG_MAX_QUERY_LENGTH",
|
|
27
|
+
"OptionsModifier",
|
|
28
|
+
"SnowflakeConnection",
|
|
29
|
+
"_APPLICATION_NAME",
|
|
30
|
+
]
|