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.
Files changed (204) hide show
  1. snowflake/connector/__init__.py +148 -0
  2. snowflake/connector/_common/__init__.py +0 -0
  3. snowflake/connector/_common/extras.py +134 -0
  4. snowflake/connector/_common/telemetry.py +221 -0
  5. snowflake/connector/_common/wif_util.py +92 -0
  6. snowflake/connector/_core/sf_core_python.cp315-win_amd64.pyd +0 -0
  7. snowflake/connector/_core/sf_core_python.pyi +79 -0
  8. snowflake/connector/_internal/__init__.py +6 -0
  9. snowflake/connector/_internal/_private_key_helper.py +31 -0
  10. snowflake/connector/_internal/api_client/__init__.py +93 -0
  11. snowflake/connector/_internal/api_client/bridge.py +41 -0
  12. snowflake/connector/_internal/api_client/client_api.py +976 -0
  13. snowflake/connector/_internal/arrow.py +47 -0
  14. snowflake/connector/_internal/arrow_context.py +240 -0
  15. snowflake/connector/_internal/arrow_stream_async.py +266 -0
  16. snowflake/connector/_internal/arrow_stream_iterator.cp311-win_amd64.pyd +0 -0
  17. snowflake/connector/_internal/arrow_stream_iterator.cp312-win_amd64.pyd +0 -0
  18. snowflake/connector/_internal/arrow_stream_iterator.cp313-win_amd64.pyd +0 -0
  19. snowflake/connector/_internal/arrow_stream_iterator.cp314-win_amd64.pyd +0 -0
  20. snowflake/connector/_internal/arrow_stream_iterator.cp314t-win_amd64.pyd +0 -0
  21. snowflake/connector/_internal/arrow_stream_iterator.cp315-win_amd64.pyd +0 -0
  22. snowflake/connector/_internal/arrow_stream_iterator.pyi +42 -0
  23. snowflake/connector/_internal/arrow_stream_utils.py +171 -0
  24. snowflake/connector/_internal/authenticator_type.py +53 -0
  25. snowflake/connector/_internal/backward_compatibility.py +245 -0
  26. snowflake/connector/_internal/binding_converters.py +741 -0
  27. snowflake/connector/_internal/config_utils.py +71 -0
  28. snowflake/connector/_internal/connection/__init__.py +39 -0
  29. snowflake/connector/_internal/connection/connection.py +616 -0
  30. snowflake/connector/_internal/connection/connection_types.py +13 -0
  31. snowflake/connector/_internal/connection/constants.py +25 -0
  32. snowflake/connector/_internal/connection/decorators.py +31 -0
  33. snowflake/connector/_internal/connection/freezable_proxy.py +104 -0
  34. snowflake/connector/_internal/connection/queries.py +10 -0
  35. snowflake/connector/_internal/connection_config_mixin.py +755 -0
  36. snowflake/connector/_internal/cursor/__init__.py +25 -0
  37. snowflake/connector/_internal/cursor/base.py +732 -0
  38. snowflake/connector/_internal/cursor/cursor_types.py +13 -0
  39. snowflake/connector/_internal/cursor/decorators.py +56 -0
  40. snowflake/connector/_internal/cursor/query_result.py +202 -0
  41. snowflake/connector/_internal/cursor/query_result_waiter.py +98 -0
  42. snowflake/connector/_internal/cursor/result_metadata.py +255 -0
  43. snowflake/connector/_internal/cursor/result_set_wrapper.py +66 -0
  44. snowflake/connector/_internal/decorators.py +539 -0
  45. snowflake/connector/_internal/error_kinds.py +111 -0
  46. snowflake/connector/_internal/errorcode.py +35 -0
  47. snowflake/connector/_internal/errorhandler.py +278 -0
  48. snowflake/connector/_internal/fips.py +28 -0
  49. snowflake/connector/_internal/logging/__init__.py +52 -0
  50. snowflake/connector/_internal/logging/config.py +134 -0
  51. snowflake/connector/_internal/logging/core_logger.py +218 -0
  52. snowflake/connector/_internal/logging/native_extension_logger.py +144 -0
  53. snowflake/connector/_internal/logout_config_mapping.py +187 -0
  54. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +57 -0
  55. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
  56. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrowTableConverter.cpp +943 -0
  57. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrowTableConverter.hpp +63 -0
  58. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +18 -0
  59. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
  60. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
  61. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
  62. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +118 -0
  63. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +116 -0
  64. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamIterator.cpp +323 -0
  65. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamIterator.hpp +133 -0
  66. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamTableIterator.cpp +275 -0
  67. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamTableIterator.hpp +168 -0
  68. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ConverterUtil.cpp +439 -0
  69. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ConverterUtil.hpp +30 -0
  70. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +48 -0
  71. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
  72. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +76 -0
  73. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
  74. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +90 -0
  75. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +63 -0
  76. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +62 -0
  77. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
  78. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +29 -0
  79. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
  80. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
  81. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
  82. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +41 -0
  83. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +65 -0
  84. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +54 -0
  85. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  86. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +79 -0
  87. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
  88. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +52 -0
  89. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
  90. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
  91. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +117 -0
  92. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +54 -0
  93. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +34 -0
  94. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +33 -0
  95. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  96. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +18 -0
  97. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
  98. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +39 -0
  99. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
  100. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +326 -0
  101. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +138 -0
  102. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
  103. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/time.cpp +65 -0
  104. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
  105. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/arrow_stream_iterator.cpp +13278 -0
  106. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/arrow_stream_iterator.pyx +204 -0
  107. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +109 -0
  108. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +125 -0
  109. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  110. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1914 -0
  111. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +208 -0
  112. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +128 -0
  113. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  114. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +58 -0
  115. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +144 -0
  116. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  117. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  118. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  119. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +160 -0
  120. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +98 -0
  121. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +243 -0
  122. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  123. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +207 -0
  124. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +80 -0
  125. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +83 -0
  126. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  127. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  128. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +201 -0
  129. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +108 -0
  130. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  131. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  132. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  133. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  134. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  135. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +164 -0
  136. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +926 -0
  137. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +182 -0
  138. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  139. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  140. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc.c +3052 -0
  141. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3019 -0
  142. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3354 -0
  143. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +344 -0
  144. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +29305 -0
  145. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +381 -0
  146. snowflake/connector/_internal/nanoarrow_cpp/Logging/logging.cpp +108 -0
  147. snowflake/connector/_internal/nanoarrow_cpp/Logging/logging.hpp +47 -0
  148. snowflake/connector/_internal/nanoarrow_cpp/scripts/.clang-format +8 -0
  149. snowflake/connector/_internal/nanoarrow_cpp/scripts/format.sh +8 -0
  150. snowflake/connector/_internal/protobuf_gen/__init__.py +0 -0
  151. snowflake/connector/_internal/protobuf_gen/database_driver_v1_pb2.py +408 -0
  152. snowflake/connector/_internal/protobuf_gen/database_driver_v1_pb2.pyi +4487 -0
  153. snowflake/connector/_internal/protobuf_gen/database_driver_v1_services.py +2088 -0
  154. snowflake/connector/_internal/protobuf_gen/proto_exception.py +17 -0
  155. snowflake/connector/_internal/result_batch.py +150 -0
  156. snowflake/connector/_internal/snowflake_restful.py +222 -0
  157. snowflake/connector/_internal/snowpark_backcompat_helpers.py +31 -0
  158. snowflake/connector/_internal/sqlstate.py +11 -0
  159. snowflake/connector/_internal/statement_utils.py +207 -0
  160. snowflake/connector/_internal/text_utils.py +112 -0
  161. snowflake/connector/_internal/type_codes.py +139 -0
  162. snowflake/connector/_internal/utils.py +65 -0
  163. snowflake/connector/_internal/write_pandas_operation.py +657 -0
  164. snowflake/connector/aio/README.md +168 -0
  165. snowflake/connector/aio/__init__.py +37 -0
  166. snowflake/connector/aio/connection/__init__.py +17 -0
  167. snowflake/connector/aio/connection/_connection.py +506 -0
  168. snowflake/connector/aio/cursor/__init__.py +35 -0
  169. snowflake/connector/aio/cursor/_base.py +1034 -0
  170. snowflake/connector/aio/cursor/_dict_cursor.py +78 -0
  171. snowflake/connector/aio/cursor/_result_set_wrapper.py +35 -0
  172. snowflake/connector/aio/cursor/_snowflake_cursor.py +72 -0
  173. snowflake/connector/aio/pandas_tools.py +279 -0
  174. snowflake/connector/aio/result_batch.py +165 -0
  175. snowflake/connector/auth/__init__.py +0 -0
  176. snowflake/connector/auth/workload_identity.py +5 -0
  177. snowflake/connector/compat.py +22 -0
  178. snowflake/connector/config_manager.py +392 -0
  179. snowflake/connector/connection/__init__.py +30 -0
  180. snowflake/connector/connection/_connection.py +641 -0
  181. snowflake/connector/connection_config.py +517 -0
  182. snowflake/connector/constants.py +52 -0
  183. snowflake/connector/cursor/__init__.py +37 -0
  184. snowflake/connector/cursor/_base.py +1169 -0
  185. snowflake/connector/cursor/_chunked_download_reader.py +75 -0
  186. snowflake/connector/cursor/_dict_cursor.py +78 -0
  187. snowflake/connector/cursor/_result_set_wrapper.py +35 -0
  188. snowflake/connector/cursor/_snowflake_cursor.py +72 -0
  189. snowflake/connector/description.py +7 -0
  190. snowflake/connector/errors.py +492 -0
  191. snowflake/connector/network.py +71 -0
  192. snowflake/connector/pandas_tools.py +191 -0
  193. snowflake/connector/py.typed +0 -0
  194. snowflake/connector/result_batch.py +216 -0
  195. snowflake/connector/telemetry.py +40 -0
  196. snowflake/connector/time_util.py +11 -0
  197. snowflake/connector/types.py +134 -0
  198. snowflake/connector/util_text.py +3 -0
  199. snowflake/connector/version.py +23 -0
  200. snowflake_connector_python-5.2.0.dist-info/DELVEWHEEL +2 -0
  201. snowflake_connector_python-5.2.0.dist-info/METADATA +190 -0
  202. snowflake_connector_python-5.2.0.dist-info/RECORD +204 -0
  203. snowflake_connector_python-5.2.0.dist-info/WHEEL +4 -0
  204. snowflake_connector_python.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,616 @@
1
+ """Shared connection mixin for sync and async connection implementations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import uuid
7
+
8
+ from typing import TYPE_CHECKING, Any, ClassVar, cast
9
+
10
+ from ..._common.extras import check_dependency
11
+ from ..._common.extras import numpy as np
12
+ from ...connection_config import ConnectionConfig
13
+ from ...constants import QueryStatus, SessionParameterName
14
+ from ...errors import Error, ErrorDetails, InterfaceError, ProgrammingError, StructuredErrorHandler
15
+ from ..api_client.client_api import core_driver
16
+ from ..binding_converters import ParamStyle
17
+ from ..decorators import api_telemetry, backward_compatibility, internal_api, pep249
18
+ from ..errorhandler import ErrorHandlerMixin
19
+ from ..logging import get_logger
20
+ from .constants import LOG_MAX_QUERY_LENGTH
21
+
22
+
23
+ if TYPE_CHECKING:
24
+ from ...aio.cursor import CursorType as AsyncCursorType
25
+ from ...cursor import CursorType as SyncCursorType
26
+ from ..protobuf_gen.database_driver_v1_pb2 import ConnectionHandle, DatabaseHandle
27
+ from ..protobuf_gen.database_driver_v1_services import ConnectionGetInfoResponse
28
+
29
+
30
+ logger = get_logger(__name__)
31
+
32
+ # Matches the legacy connector's `MAX_CLIENT_PREFETCH_THREADS` /
33
+ # `_validate_client_prefetch_threads` bounds (`connection.py`).
34
+ MIN_CLIENT_PREFETCH_THREADS = 1
35
+ MAX_CLIENT_PREFETCH_THREADS = 10
36
+
37
+
38
+ def clamp_client_prefetch_threads(value: int) -> int:
39
+ """Clamp to ``[1, 10]``, matching the legacy connector's validation."""
40
+ value = int(value)
41
+ if value <= 0:
42
+ return MIN_CLIENT_PREFETCH_THREADS
43
+ if value > MAX_CLIENT_PREFETCH_THREADS:
44
+ return MAX_CLIENT_PREFETCH_THREADS
45
+ return value
46
+
47
+
48
+ def validate_query_id(sf_qid: str) -> None:
49
+ """Raise ValueError if ``sf_qid`` is not a valid UUID, matching the legacy connector's validation."""
50
+ try:
51
+ uuid.UUID(sf_qid)
52
+ except ValueError as err:
53
+ raise ValueError(f"Invalid UUID: '{sf_qid}'") from err
54
+
55
+
56
+ def _session_param_is_true(value: bool | str | None) -> bool:
57
+ """Return True for a native ``True`` or the string ``"true"`` (case-insensitive).
58
+
59
+ A session-parameter value is a native bool once read through
60
+ ``SessionParametersProxy``, or a plain string when supplied via a
61
+ caller-side override; both spellings of ``"true"``/``"false"`` are
62
+ accepted case-insensitively.
63
+ """
64
+ if isinstance(value, bool):
65
+ return value
66
+ if isinstance(value, str):
67
+ return value.lower() == "true"
68
+ return False
69
+
70
+
71
+ class ConnectionMixin(ErrorHandlerMixin):
72
+ """Connection members shared by sync and async connection classes.
73
+
74
+ Subclasses set handle/proxy fields (``conn_handle``, ``_session_parameters``,
75
+ ``_connection_info``, etc.) and call :meth:`__init__` before performing any
76
+ I/O to establish the session.
77
+ """
78
+
79
+ _messages: list[tuple[type[Error], ErrorDetails]]
80
+ _errorhandler: StructuredErrorHandler
81
+ config: ConnectionConfig
82
+ __paramstyle: ParamStyle
83
+ _interpolate_empty_sequences: bool
84
+ _reuse_results: bool
85
+ _session_parameters: Any
86
+ _connection_info: Any
87
+ _client_param_telemetry_enabled: bool
88
+ conn_handle: ConnectionHandle | None
89
+
90
+ # Concrete subclasses set the default cursor class returned by ``cursor()``
91
+ # (the sync vs. async ``SnowflakeCursor``); kept off the shared mixin so
92
+ # ``_internal`` never imports the public cursor packages at runtime.
93
+ _default_cursor_class: ClassVar[SyncCursorType | AsyncCursorType]
94
+
95
+ def __init__(
96
+ self,
97
+ *,
98
+ connection_name: str | None = None,
99
+ connections_file_path: str | os.PathLike[str] | None = None,
100
+ config: ConnectionConfig | None = None,
101
+ **kwargs: Any,
102
+ ) -> None:
103
+ self._messages = []
104
+ self._errorhandler = Error.default_errorhandler
105
+ self._client_param_telemetry_enabled = True
106
+
107
+ if config is not None:
108
+ if kwargs:
109
+ raise ProgrammingError(
110
+ "Cannot pass both a ConnectionConfig object and keyword arguments. Use one or the other."
111
+ )
112
+ config = config._clone()
113
+ if connection_name is not None:
114
+ config.connection_name = connection_name
115
+ if connections_file_path is not None:
116
+ config.connections_file_path = os.fspath(connections_file_path)
117
+ self.config = ConnectionConfig._finalize(config)
118
+ else:
119
+ self.config = ConnectionConfig.from_connection_args(
120
+ connection_name=connection_name,
121
+ connections_file_path=connections_file_path,
122
+ **kwargs,
123
+ )
124
+
125
+ if self.config.client_prefetch_threads is not None:
126
+ self.config.client_prefetch_threads = clamp_client_prefetch_threads(self.config.client_prefetch_threads)
127
+
128
+ from snowflake.connector import paramstyle as default_paramstyle
129
+
130
+ self.paramstyle = self.config.paramstyle or default_paramstyle
131
+
132
+ if self.config.numpy:
133
+ check_dependency(np)
134
+
135
+ self._interpolate_empty_sequences = bool(self.config.interpolate_empty_sequences)
136
+ self._reuse_results = self.config.reuse_results is True
137
+
138
+ # ------------------------------------------------------------------
139
+ # Cursors
140
+ # ------------------------------------------------------------------
141
+
142
+ def _instantiate_cursor(self, cursor_class: type[Any] | None) -> Any:
143
+ # The class is chosen by the caller, so this cannot name its constructor.
144
+ factory: Any = cursor_class or self._default_cursor_class
145
+ return factory(self)
146
+
147
+ # ------------------------------------------------------------------
148
+ # Handle release
149
+ # ------------------------------------------------------------------
150
+
151
+ def _close_telemetry_client(self) -> None:
152
+ client = getattr(self, "_telemetry_client", None)
153
+ if client is not None:
154
+ client.close()
155
+
156
+ def _release_connection_handle(self, conn_handle: ConnectionHandle) -> None:
157
+ """Release the Rust-side connection handle."""
158
+ try:
159
+ core_driver.connection_release(conn_handle=conn_handle)
160
+ except Exception:
161
+ logger.warning("Failed to release connection handle", exc_info=True)
162
+
163
+ def _release_database_handle(self, db_handle: DatabaseHandle) -> None:
164
+ """Release the Rust-side database handle."""
165
+ try:
166
+ core_driver.database_release(db_handle=db_handle)
167
+ except Exception:
168
+ logger.warning("Failed to release database handle", exc_info=True)
169
+
170
+ # ------------------------------------------------------------------
171
+ # PEP 249 attributes
172
+ # ------------------------------------------------------------------
173
+
174
+ @property
175
+ @pep249
176
+ @api_telemetry
177
+ def messages(self) -> list[tuple[type[Error], ErrorDetails]]:
178
+ """List of (exception class, exception value) tuples received from the database."""
179
+ return self._messages
180
+
181
+ @messages.setter
182
+ @api_telemetry
183
+ def messages(self, value: list[tuple[type[Error], ErrorDetails]]) -> None:
184
+ self._messages = value
185
+
186
+ # ------------------------------------------------------------------
187
+ # Paramstyle
188
+ # ------------------------------------------------------------------
189
+
190
+ @property
191
+ @api_telemetry
192
+ def paramstyle(self) -> ParamStyle:
193
+ """Get the paramstyle for this connection."""
194
+ return self.__paramstyle
195
+
196
+ @paramstyle.setter
197
+ @api_telemetry
198
+ def paramstyle(self, value: str | ParamStyle) -> None:
199
+ """Set binding style from a :class:`ParamStyle` or PEP 249 string (e.g. ``"pyformat"``)."""
200
+ if isinstance(value, ParamStyle):
201
+ self.__paramstyle = value
202
+ elif isinstance(value, str):
203
+ self.__paramstyle = ParamStyle.from_string(value)
204
+ else:
205
+ raise ProgrammingError(msg=f"paramstyle must be str or ParamStyle, got {type(value).__name__}")
206
+
207
+ @property
208
+ @backward_compatibility
209
+ def _paramstyle(self) -> ParamStyle:
210
+ """Internal binding-style storage (legacy callers assign to ``_paramstyle``)."""
211
+ return self.__paramstyle
212
+
213
+ @_paramstyle.setter
214
+ @backward_compatibility
215
+ def _paramstyle(self, value: str | ParamStyle) -> None:
216
+ """Normalize assignments to ``_paramstyle`` (e.g. SnowPy ``temporary_paramstyle``)."""
217
+ self.paramstyle = value
218
+
219
+ # ------------------------------------------------------------------
220
+ # Session info
221
+ # ------------------------------------------------------------------
222
+
223
+ @property
224
+ @api_telemetry
225
+ def role(self) -> str | None:
226
+ """The current role in use for the session."""
227
+ return cast("str | None", self._connection_info["role"])
228
+
229
+ @property
230
+ @api_telemetry
231
+ def database(self) -> str | None:
232
+ """The current database in use for the session."""
233
+ return cast("str | None", self._connection_info["database"])
234
+
235
+ @property
236
+ @api_telemetry
237
+ def schema(self) -> str | None:
238
+ """The current schema in use for the session."""
239
+ return cast("str | None", self._connection_info["schema"])
240
+
241
+ @property
242
+ @api_telemetry
243
+ def account(self) -> str | None:
244
+ """The Snowflake account name used by this connection."""
245
+ return cast("str | None", self._connection_info["account"])
246
+
247
+ @property
248
+ @api_telemetry
249
+ def warehouse(self) -> str | None:
250
+ """The current warehouse in use for the session."""
251
+ return cast("str | None", self._connection_info["warehouse"])
252
+
253
+ @property
254
+ @api_telemetry
255
+ def user(self) -> str | None:
256
+ """The user name used for authentication."""
257
+ return cast("str | None", self._connection_info["user"])
258
+
259
+ @property
260
+ @api_telemetry
261
+ def host(self) -> str | None:
262
+ """The host name of the Snowflake instance."""
263
+ return cast("str | None", self._connection_info["host"])
264
+
265
+ @property
266
+ @api_telemetry
267
+ def port(self) -> int | None:
268
+ """The port number of the Snowflake instance."""
269
+ return cast("int | None", self._connection_info["port"])
270
+
271
+ @property
272
+ @api_telemetry
273
+ def session_id(self) -> int:
274
+ """The Snowflake session ID for this connection."""
275
+ value = cast("int | None", self._connection_info["session_id"])
276
+ if value is None:
277
+ raise InterfaceError(msg="Session ID is not available; connection may not be initialized")
278
+ return value
279
+
280
+ # ------------------------------------------------------------------
281
+ # Proxy info
282
+ # ------------------------------------------------------------------
283
+
284
+ @property
285
+ @api_telemetry
286
+ def proxy_host(self) -> str | None:
287
+ """The configured HTTP proxy hostname, or ``None`` when no proxy is set."""
288
+ return cast("str | None", self._connection_info["proxy_host"])
289
+
290
+ @property
291
+ @api_telemetry
292
+ def proxy_port(self) -> int | None:
293
+ """The configured HTTP proxy port, or ``None`` when no proxy is set."""
294
+ return cast("int | None", self._connection_info["proxy_port"])
295
+
296
+ @property
297
+ @api_telemetry
298
+ def proxy_user(self) -> str | None:
299
+ """The configured HTTP proxy username for Basic auth, or ``None`` when unset."""
300
+ return cast("str | None", self._connection_info["proxy_user"])
301
+
302
+ @property
303
+ @api_telemetry
304
+ def proxy_password(self) -> str | None:
305
+ """The configured HTTP proxy password for Basic auth, or ``None`` when unset."""
306
+ return cast("str | None", self._connection_info["proxy_password"])
307
+
308
+ @property
309
+ @api_telemetry
310
+ def no_proxy(self) -> str | None:
311
+ """Comma-separated list of hosts that bypass the proxy, or ``None`` when unset."""
312
+ return cast("str | None", self._connection_info["no_proxy"])
313
+
314
+ # ------------------------------------------------------------------
315
+ # Connection properties
316
+ # ------------------------------------------------------------------
317
+
318
+ @property
319
+ @api_telemetry
320
+ def login_timeout(self) -> int | None:
321
+ """The login timeout in seconds."""
322
+ return self.config.login_timeout
323
+
324
+ @property
325
+ @api_telemetry
326
+ def network_timeout(self) -> int | None:
327
+ """The network timeout in seconds for all other operations."""
328
+ return self.config.request_timeout
329
+
330
+ @property
331
+ @api_telemetry
332
+ def socket_timeout(self) -> int | None:
333
+ """The socket timeout in seconds."""
334
+ return self.config.retry_timeout
335
+
336
+ @property
337
+ @api_telemetry
338
+ def platform_detection_timeout_seconds(self) -> float | None:
339
+ """The configured value, which the driver ignores; each platform check is limited to 2 seconds."""
340
+ return self.config.platform_detection_timeout_seconds
341
+
342
+ @property
343
+ @api_telemetry
344
+ def client_session_keep_alive(self) -> bool | None:
345
+ """Whether to keep the session active with periodic heartbeat requests."""
346
+ return self.config.client_session_keep_alive
347
+
348
+ @property
349
+ @api_telemetry
350
+ def client_session_keep_alive_heartbeat_frequency(self) -> int | None:
351
+ """The frequency in seconds of heartbeat requests when session keep-alive is enabled."""
352
+ return self.config.client_session_keep_alive_heartbeat_frequency
353
+
354
+ @property
355
+ @api_telemetry
356
+ def client_prefetch_threads(self) -> int | None:
357
+ """The number of threads used to prefetch query result data."""
358
+ return self.config.client_prefetch_threads
359
+
360
+ @client_prefetch_threads.setter
361
+ @api_telemetry
362
+ def client_prefetch_threads(self, value: int) -> None:
363
+ """Update local state only; this is the base (zero-I/O) implementation.
364
+
365
+ The core's chunk-prefetch pool size is read from the server-echoed
366
+ session-parameter cache, not from this config value, so on its own
367
+ this setter has no effect on an already-open connection. The
368
+ synchronous ``Connection`` class overrides this property to also run
369
+ ``ALTER SESSION SET CLIENT_PREFETCH_THREADS`` so the change actually
370
+ takes effect on subsequent fetches, matching the old connector's
371
+ immediate, locally-effective setter. Async connections cannot do the
372
+ same through a synchronous property setter (it can't ``await``); use
373
+ ``await conn.set_client_prefetch_threads(value)`` there instead.
374
+ """
375
+ self.config.client_prefetch_threads = clamp_client_prefetch_threads(value)
376
+
377
+ @property
378
+ @api_telemetry
379
+ def application(self) -> str:
380
+ """The name of the client application connecting to Snowflake."""
381
+ return self.config.application # type: ignore[return-value]
382
+
383
+ # ------------------------------------------------------------------
384
+ # Error handling
385
+ # ------------------------------------------------------------------
386
+
387
+ @property
388
+ @pep249
389
+ @api_telemetry
390
+ def errorhandler(self) -> StructuredErrorHandler:
391
+ """PEP 249 error handler called for connection and cursor errors."""
392
+ return self._errorhandler
393
+
394
+ @errorhandler.setter
395
+ @api_telemetry
396
+ def errorhandler(self, value: StructuredErrorHandler | None) -> None:
397
+ if value is None:
398
+ raise ProgrammingError("Invalid errorhandler is specified")
399
+ self._errorhandler = value
400
+
401
+ @property
402
+ @api_telemetry
403
+ def is_pyformat(self) -> bool:
404
+ """Whether the connection uses pyformat or format paramstyle (client-side binding)."""
405
+ return self._paramstyle in (ParamStyle.PYFORMAT, ParamStyle.FORMAT)
406
+
407
+ # ------------------------------------------------------------------
408
+ # Logging & options
409
+ # ------------------------------------------------------------------
410
+
411
+ def _server_param_telemetry_enabled(self) -> bool:
412
+ try:
413
+ value = self._session_parameters[SessionParameterName.CLIENT_TELEMETRY_ENABLED]
414
+ except Exception:
415
+ logger.debug("Failed to read CLIENT_TELEMETRY_ENABLED session parameter")
416
+ return False
417
+ return _session_param_is_true(value)
418
+
419
+ @property
420
+ @api_telemetry
421
+ def telemetry_enabled(self) -> bool:
422
+ """Whether client-side telemetry collection is enabled.
423
+
424
+ True only when both halves agree: the client has not disabled it via
425
+ this property, AND the server has confirmed ``CLIENT_TELEMETRY_ENABLED``
426
+ for the session. Unlike ``sf_core``'s own (unrelated) OTEL-export gate,
427
+ an unconfirmed server parameter is treated as disabled, not enabled,
428
+ matching the old driver version. Reading this property issues an RPC.
429
+ """
430
+ return self._client_param_telemetry_enabled and self._server_param_telemetry_enabled()
431
+
432
+ @telemetry_enabled.setter
433
+ @api_telemetry
434
+ def telemetry_enabled(self, value: bool) -> None:
435
+ """Set the client-side telemetry flag.
436
+
437
+ This can only narrow, never widen, server policy: it never issues an
438
+ RPC or ``ALTER SESSION``.
439
+ """
440
+ self._client_param_telemetry_enabled = bool(value)
441
+ if self._client_param_telemetry_enabled and not self._server_param_telemetry_enabled():
442
+ logger.info(
443
+ "Telemetry has been disabled by the session parameter CLIENT_TELEMETRY_ENABLED."
444
+ " Set session parameter CLIENT_TELEMETRY_ENABLED to true to enable telemetry."
445
+ )
446
+
447
+ @property
448
+ @api_telemetry
449
+ def service_name(self) -> str | None:
450
+ """The Snowflake service name for the connection, used for service discovery."""
451
+ return cast("str | None", self._session_parameters._get_string("SERVICE_NAME"))
452
+
453
+ @service_name.setter
454
+ @api_telemetry
455
+ def service_name(self, value: str | None) -> None:
456
+ if self.conn_handle is None:
457
+ return
458
+ if value is None:
459
+ value = ""
460
+ core_driver.connection_set_session_parameters(conn_handle=self.conn_handle, parameters={"SERVICE_NAME": value})
461
+
462
+ @property
463
+ @api_telemetry
464
+ def log_max_query_length(self) -> int:
465
+ """Maximum number of characters of a query string to log."""
466
+ return (
467
+ self.config.log_max_query_length if self.config.log_max_query_length is not None else LOG_MAX_QUERY_LENGTH
468
+ )
469
+
470
+ def _format_query_for_log(self, query: str) -> str:
471
+ """Collapse whitespace and truncate a query string for gated INFO query logging."""
472
+ ret = " ".join(line.strip() for line in query.split("\n"))
473
+ if len(ret) < self.log_max_query_length:
474
+ return ret
475
+ return ret[: self.log_max_query_length] + "..."
476
+
477
+ @property
478
+ @api_telemetry
479
+ def use_openssl_only(self) -> bool:
480
+ """Deprecated. Whether to restrict TLS to OpenSSL only (always ``True``)."""
481
+ raise NotImplementedError("use_openssl_only is not yet implemented")
482
+
483
+ @property
484
+ @api_telemetry
485
+ def arrow_number_to_decimal(self) -> bool:
486
+ """Whether to convert Arrow numeric types to Python ``Decimal`` instead of ``float``."""
487
+ return bool(self.config.arrow_number_to_decimal)
488
+
489
+ @arrow_number_to_decimal.setter
490
+ @api_telemetry
491
+ def arrow_number_to_decimal(self, value: bool) -> None:
492
+ self.config.arrow_number_to_decimal = bool(value)
493
+
494
+ @arrow_number_to_decimal.setter # type: ignore[attr-defined, untyped-decorator]
495
+ @backward_compatibility
496
+ def arrow_number_to_decimal_setter(self, value: bool) -> None:
497
+ """Set arrow_number_to_decimal field. Deprecated."""
498
+ self.arrow_number_to_decimal = value
499
+
500
+ @property
501
+ @api_telemetry
502
+ def force_microsecond_precision(self) -> bool:
503
+ """Whether ``fetch_arrow_*`` and ``fetch_pandas_*`` truncate timestamps to microseconds.
504
+
505
+ Those methods use this value when the call omits ``force_microsecond_precision``.
506
+ A per-call argument overrides it.
507
+ """
508
+ return bool(self.config.force_microsecond_precision)
509
+
510
+ @force_microsecond_precision.setter
511
+ @api_telemetry
512
+ def force_microsecond_precision(self, value: bool) -> None:
513
+ self.config.force_microsecond_precision = bool(value)
514
+
515
+ @property
516
+ @api_telemetry
517
+ def validate_default_parameters(self) -> bool:
518
+ """Whether to validate default connection parameters at connect time."""
519
+ return bool(self.config.validate_default_parameters)
520
+
521
+ @property
522
+ @api_telemetry
523
+ def insecure_mode(self) -> bool:
524
+ """Whether OCSP certificate revocation checking is disabled."""
525
+ raise NotImplementedError("insecure_mode is not yet implemented")
526
+
527
+ @property
528
+ @api_telemetry
529
+ def consent_cache_id_token(self) -> bool:
530
+ """Whether to cache the IdP token for browser-based SSO authentication."""
531
+ raise NotImplementedError("consent_cache_id_token is not yet implemented")
532
+
533
+ # ------------------------------------------------------------------
534
+ # connection state (sync core_driver reads)
535
+ # ------------------------------------------------------------------
536
+
537
+ def _autocommit_enabled(self) -> bool:
538
+ value = self._session_parameters["AUTOCOMMIT"]
539
+ return _session_param_is_true(value)
540
+
541
+ @property
542
+ def _autocommit(self) -> bool:
543
+ """Whether autocommit is enabled (legacy internal name used by sync tests)."""
544
+ return self._autocommit_enabled()
545
+
546
+ @api_telemetry
547
+ def get_autocommit(self) -> bool:
548
+ """Return the current autocommit mode."""
549
+ return self._autocommit_enabled()
550
+
551
+ @api_telemetry
552
+ def get_client_prefetch_threads(self) -> int:
553
+ """Return the configured number of chunk-prefetch threads."""
554
+ return cast(int, self.config.client_prefetch_threads)
555
+
556
+ @api_telemetry
557
+ def is_expired(self) -> bool:
558
+ """Return True if the connection's master token has expired.
559
+
560
+ Once True, the session can no longer be renewed and the connection
561
+ must be replaced; full re-authentication is required.
562
+
563
+ Matches the legacy ``SnowflakeConnection.expired`` flag — intended as a
564
+ read-only signal for external pool / application code. Fails closed on
565
+ RPC errors so pools evict uncertain connections.
566
+ """
567
+ if self.conn_handle is None:
568
+ return False
569
+ try:
570
+ response = core_driver.connection_is_expired(conn_handle=self.conn_handle)
571
+ return bool(response.is_expired)
572
+ except Exception:
573
+ return True
574
+
575
+ @property
576
+ @api_telemetry
577
+ def expired(self) -> bool:
578
+ """Whether the master token has expired (sync legacy property name)."""
579
+ return self.is_expired()
580
+
581
+ @internal_api
582
+ def _get_connection_info(self, include_master_token: bool = False) -> ConnectionGetInfoResponse:
583
+ """Return connection details from Core."""
584
+ if self.conn_handle is None:
585
+ raise InterfaceError(msg="Connection handle is not available")
586
+ return core_driver.connection_get_info(
587
+ conn_handle=self.conn_handle,
588
+ include_master_token=include_master_token,
589
+ )
590
+
591
+ # ------------------------------------------------------------------
592
+ # Query status helpers
593
+ # ------------------------------------------------------------------
594
+
595
+ @staticmethod
596
+ def is_still_running(status: QueryStatus) -> bool:
597
+ """Check whether given status is currently running."""
598
+ return status in (
599
+ QueryStatus.RUNNING,
600
+ QueryStatus.QUEUED,
601
+ QueryStatus.RESUMING_WAREHOUSE,
602
+ QueryStatus.QUEUED_REPARING_WAREHOUSE,
603
+ QueryStatus.BLOCKED,
604
+ QueryStatus.NO_DATA,
605
+ )
606
+
607
+ @staticmethod
608
+ def is_an_error(status: QueryStatus) -> bool:
609
+ """Check whether given status means that there has been an error."""
610
+ return status in (
611
+ QueryStatus.ABORTING,
612
+ QueryStatus.FAILED_WITH_ERROR,
613
+ QueryStatus.ABORTED,
614
+ QueryStatus.FAILED_WITH_INCIDENT,
615
+ QueryStatus.DISCONNECTED,
616
+ )
@@ -0,0 +1,13 @@
1
+ """Connection type aliases shared by sync and async connection implementations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from typing import Any, TypeVar
7
+
8
+
9
+ SessionParameters = dict[str, Any]
10
+ ConnectionParamValue = int | str | float | bytes | bool | SessionParameters
11
+ ConnectionParameters = dict[str, ConnectionParamValue]
12
+
13
+ F = TypeVar("F", bound=Callable[..., Any])
@@ -0,0 +1,25 @@
1
+ """Connection constants shared by sync and async connection implementations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ # backward compatibility constant
9
+ # snowflake-sqlalchemy imports this symbol and calls .get(name) in
10
+ # parse_query_param_type to cast URL query-string values to the types the
11
+ # connector expects. The universal core validates parameters internally, so
12
+ # an empty dict is correct: every .get() returns None and values pass through
13
+ # uncast.
14
+ DEFAULT_CONFIGURATION: dict[str, tuple[Any, tuple[type, ...]]] = {}
15
+
16
+ APPLICATION_NAME = "PythonConnector"
17
+ # Kept as a public alias for backward compatibility — external packages
18
+ # (e.g. snowflake-sqlalchemy) may import this symbol.
19
+ CLIENT_NAME = APPLICATION_NAME
20
+
21
+ # Default upper bound for query strings included in log messages. Mirrors
22
+ # the ``log_max_query_length`` default emitted by the generated
23
+ # :class:`ConnectionConfig` (sourced from ``PARAM_DEFS``); kept here as a
24
+ # named constant so the property fallback isn't a magic number.
25
+ LOG_MAX_QUERY_LENGTH = 80
@@ -0,0 +1,31 @@
1
+ """Connection precondition decorators shared by sync and async connection implementations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from ...errors import DatabaseError
8
+ from ..decorators import wrap_method_with_sync_pre
9
+ from ..errorcode import ER_CONNECTION_IS_CLOSED
10
+ from ..sqlstate import SQLSTATE_CONNECTION_NOT_EXISTS
11
+ from .connection_types import F
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from ...aio.connection import Connection as AsyncConnection
16
+ from ...connection import Connection
17
+
18
+
19
+ def _raise_if_connection_closed(self: Connection | AsyncConnection) -> None:
20
+ # TODO: it should rather raise InterfaceError, consider to align with the cursor
21
+ if self.conn_handle is None or self.is_closed():
22
+ raise DatabaseError(
23
+ msg="Connection is closed.",
24
+ errno=ER_CONNECTION_IS_CLOSED,
25
+ sqlstate=SQLSTATE_CONNECTION_NOT_EXISTS,
26
+ )
27
+
28
+
29
+ def requires_open(func: F) -> F:
30
+ """Raise ``DatabaseError`` if the connection is closed."""
31
+ return wrap_method_with_sync_pre(func, pre=_raise_if_connection_closed)