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,539 @@
|
|
|
1
|
+
"""Marker, annotation, and precondition wrapper decorators for internal APIs.
|
|
2
|
+
|
|
3
|
+
The runtime machinery for ``@backward_compatibility`` (call-time wrapper,
|
|
4
|
+
module ``__getattr__`` installer, dedup state) lives in
|
|
5
|
+
:mod:`._internal.backward_compatibility`; this module is intentionally kept
|
|
6
|
+
to just the decorator façade.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
import functools
|
|
13
|
+
import inspect
|
|
14
|
+
import types
|
|
15
|
+
|
|
16
|
+
from collections.abc import AsyncGenerator, Awaitable, Callable, Coroutine, Generator
|
|
17
|
+
from contextvars import ContextVar
|
|
18
|
+
from typing import Any, Generic, ParamSpec, Protocol, TypeVar, cast, overload
|
|
19
|
+
|
|
20
|
+
from .backward_compatibility import apply_backward_compatibility
|
|
21
|
+
from .logging import get_logger
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
logger = get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
|
27
|
+
P = ParamSpec("P")
|
|
28
|
+
|
|
29
|
+
# Generic pass-through: functions, classes, and descriptors all round-trip
|
|
30
|
+
# through ``@backward_compatibility`` as the same logical type (a class stays
|
|
31
|
+
# the same class; a wrapped function preserves its signature via
|
|
32
|
+
# ``functools.wraps``). Using ``TypeVar("T")`` lets mypy preserve the input
|
|
33
|
+
# type across the decorator instead of widening it to ``Any``.
|
|
34
|
+
T = TypeVar("T")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def internal_api(func: F) -> F:
|
|
38
|
+
"""
|
|
39
|
+
Mark a method or function as internal.
|
|
40
|
+
This is an identity function that returns the function unchanged.
|
|
41
|
+
It serves as a marker for internal APIs that should not be used by external consumers.
|
|
42
|
+
Args:
|
|
43
|
+
func: The function or method to mark as internal
|
|
44
|
+
Returns:
|
|
45
|
+
The unchanged function
|
|
46
|
+
"""
|
|
47
|
+
return func
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def pep249(func: F) -> F:
|
|
51
|
+
"""Mark a method or property as defined by PEP 249 (required or optional)."""
|
|
52
|
+
return func
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def snowpark_compat(func: F) -> F:
|
|
56
|
+
"""No-op marker: method/property added only for Snowpark's private-API surface (like :func:`pep249`)."""
|
|
57
|
+
return func
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class _AsyncContextManagerLike(Protocol):
|
|
61
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Any: ...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
R = TypeVar("R", bound=_AsyncContextManagerLike)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class _AwaitableContextManager(Generic[R]):
|
|
68
|
+
"""Wrapper returned by :func:`awaitable_context_manager` decorated functions.
|
|
69
|
+
|
|
70
|
+
Supports both ``await fn(...)`` and ``async with fn(...) as result:``.
|
|
71
|
+
The ``__aexit__`` delegates to the returned object's ``__aexit__``, so
|
|
72
|
+
the wrapped coroutine must return an async context manager.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, coro: Coroutine[Any, Any, R]) -> None:
|
|
76
|
+
self._coro = coro
|
|
77
|
+
self._obj: R | None = None
|
|
78
|
+
|
|
79
|
+
def __await__(self) -> Generator[Any, None, R]:
|
|
80
|
+
return self._coro.__await__()
|
|
81
|
+
|
|
82
|
+
async def __aenter__(self) -> R:
|
|
83
|
+
self._obj = await self._coro
|
|
84
|
+
return self._obj
|
|
85
|
+
|
|
86
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Any:
|
|
87
|
+
if self._obj is not None:
|
|
88
|
+
return await self._obj.__aexit__(exc_type, exc_val, exc_tb)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def awaitable_context_manager(
|
|
92
|
+
func: Callable[P, Coroutine[Any, Any, R]],
|
|
93
|
+
) -> Callable[P, _AwaitableContextManager[R]]:
|
|
94
|
+
"""Make an ``async def`` factory support both ``await`` and ``async with``.
|
|
95
|
+
|
|
96
|
+
The decorated function must return an object that implements
|
|
97
|
+
``__aenter__`` / ``__aexit__`` (i.e. an async context manager).
|
|
98
|
+
|
|
99
|
+
Usage::
|
|
100
|
+
|
|
101
|
+
@awaitable_context_manager
|
|
102
|
+
async def connect(**kwargs):
|
|
103
|
+
conn = Connection(**kwargs)
|
|
104
|
+
await conn.open()
|
|
105
|
+
return conn
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# Both patterns work:
|
|
109
|
+
conn = await connect(...)
|
|
110
|
+
async with connect(...) as conn:
|
|
111
|
+
...
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
@functools.wraps(func)
|
|
115
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> _AwaitableContextManager[R]:
|
|
116
|
+
return _AwaitableContextManager(func(*args, **kwargs))
|
|
117
|
+
|
|
118
|
+
return wrapper
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@overload
|
|
122
|
+
def backward_compatibility(obj: T, *, recommendation: str | None = None) -> T: ...
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@overload
|
|
126
|
+
def backward_compatibility(*, recommendation: str | None = None) -> Callable[[T], T]: ...
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def backward_compatibility(obj: T | None = None, *, recommendation: str | None = None) -> T | Callable[[T], T]:
|
|
130
|
+
"""Mark an object as a backward-compatibility shim and, where applicable,
|
|
131
|
+
wrap it so that first external use emits a ``DeprecationWarning``.
|
|
132
|
+
|
|
133
|
+
The emitted message always names the symbol (``module.qualname``) and
|
|
134
|
+
explains that it is retained only for backward compatibility. Usable bare
|
|
135
|
+
(``@backward_compatibility``) or, to name a specific replacement API in the
|
|
136
|
+
warning, called with a keyword argument
|
|
137
|
+
(``@backward_compatibility(recommendation="Use `foo` instead.")``).
|
|
138
|
+
``recommendation`` only affects function/method targets — see below.
|
|
139
|
+
|
|
140
|
+
Behavior by target type:
|
|
141
|
+
|
|
142
|
+
* **Class** — registered only; the object is returned unchanged. Paired
|
|
143
|
+
with
|
|
144
|
+
:func:`~snowflake.connector._internal.backward_compatibility.install_backward_compatibility_getattr`,
|
|
145
|
+
the warning fires on first attribute access (e.g.
|
|
146
|
+
``from ...errors import HttpError`` or ``errors.HttpError``). Classes
|
|
147
|
+
are never wrapped because "use" of a class takes too many shapes
|
|
148
|
+
(``isinstance``, ``raise``, subclassing); ``recommendation`` is ignored.
|
|
149
|
+
|
|
150
|
+
* **Function / method** — wrapped so the first *external* call emits a
|
|
151
|
+
warning. Calls originating from inside ``snowflake.connector.*`` are
|
|
152
|
+
silent, so the driver's own internal uses don't consume the one-shot
|
|
153
|
+
warning slot before the customer ever sees it.
|
|
154
|
+
|
|
155
|
+
* **Descriptor (``property``, ``staticmethod``, ``classmethod``, …)** —
|
|
156
|
+
registered only; the descriptor is returned unchanged. To warn on
|
|
157
|
+
descriptor access, apply ``@backward_compatibility`` to the *raw
|
|
158
|
+
function* (i.e. *below* ``@property`` / ``@prop.setter``) so the
|
|
159
|
+
call-time wrapper is installed before the descriptor is built on top.
|
|
160
|
+
|
|
161
|
+
* **Plain value** (e.g. a module-level string constant) — registered
|
|
162
|
+
only; the value is returned unchanged. Like classes, it warns on first
|
|
163
|
+
attribute access once paired with
|
|
164
|
+
:func:`~snowflake.connector._internal.backward_compatibility.install_backward_compatibility_getattr`,
|
|
165
|
+
since there is no "call" to intercept.
|
|
166
|
+
"""
|
|
167
|
+
if obj is None:
|
|
168
|
+
return lambda target: apply_backward_compatibility(target, recommendation=recommendation)
|
|
169
|
+
return apply_backward_compatibility(obj, recommendation=recommendation)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
# ------------------------------------------------------------------
|
|
173
|
+
# Precondition wrappers (connection/cursor @requires_open, etc.)
|
|
174
|
+
# ------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def wrap_method_with_sync_pre(
|
|
178
|
+
func: F,
|
|
179
|
+
*,
|
|
180
|
+
pre: Callable[[Any], None],
|
|
181
|
+
) -> F:
|
|
182
|
+
"""Wrap *func* with a sync pre-call hook (used for both sync and async methods)."""
|
|
183
|
+
if inspect.isasyncgenfunction(func):
|
|
184
|
+
|
|
185
|
+
@functools.wraps(func)
|
|
186
|
+
async def gen_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
187
|
+
pre(self)
|
|
188
|
+
async for value in func(self, *args, **kwargs):
|
|
189
|
+
yield value
|
|
190
|
+
|
|
191
|
+
return cast(F, gen_wrapper)
|
|
192
|
+
|
|
193
|
+
if inspect.iscoroutinefunction(func):
|
|
194
|
+
|
|
195
|
+
@functools.wraps(func)
|
|
196
|
+
async def async_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
197
|
+
pre(self)
|
|
198
|
+
return await func(self, *args, **kwargs)
|
|
199
|
+
|
|
200
|
+
return cast(F, async_wrapper)
|
|
201
|
+
|
|
202
|
+
@functools.wraps(func)
|
|
203
|
+
def sync_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
204
|
+
pre(self)
|
|
205
|
+
return func(self, *args, **kwargs)
|
|
206
|
+
|
|
207
|
+
return cast(F, sync_wrapper)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def wrap_method_with_awaitable_pre(
|
|
211
|
+
func: F,
|
|
212
|
+
*,
|
|
213
|
+
sync_pre: Callable[[Any], None],
|
|
214
|
+
async_pre: Callable[[Any], Awaitable[None]],
|
|
215
|
+
) -> F:
|
|
216
|
+
"""Wrap *func* with sync/async pre-call hooks when the pre itself may await."""
|
|
217
|
+
if inspect.isasyncgenfunction(func):
|
|
218
|
+
|
|
219
|
+
@functools.wraps(func)
|
|
220
|
+
async def gen_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
221
|
+
await async_pre(self)
|
|
222
|
+
async for value in func(self, *args, **kwargs):
|
|
223
|
+
yield value
|
|
224
|
+
|
|
225
|
+
return cast(F, gen_wrapper)
|
|
226
|
+
|
|
227
|
+
if inspect.iscoroutinefunction(func):
|
|
228
|
+
|
|
229
|
+
@functools.wraps(func)
|
|
230
|
+
async def async_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
231
|
+
await async_pre(self)
|
|
232
|
+
return await func(self, *args, **kwargs)
|
|
233
|
+
|
|
234
|
+
return cast(F, async_wrapper)
|
|
235
|
+
|
|
236
|
+
@functools.wraps(func)
|
|
237
|
+
def sync_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
238
|
+
sync_pre(self)
|
|
239
|
+
return func(self, *args, **kwargs)
|
|
240
|
+
|
|
241
|
+
return cast(F, sync_wrapper)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
_TRACKING: ContextVar[bool] = ContextVar("_api_tracking", default=True)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _telemetry_client_if_enabled(self: Any) -> Any:
|
|
248
|
+
"""Return the telemetry client for *self*, or ``None`` if there is none to send to
|
|
249
|
+
or ``Connection.telemetry_enabled`` is currently ``False``.
|
|
250
|
+
|
|
251
|
+
Deliberately re-implements the ``telemetry_enabled`` AND rather than reading
|
|
252
|
+
the public property: that property is ``@api_telemetry``-decorated, and
|
|
253
|
+
calling it from here (inside telemetry dispatch) would recurse into sending
|
|
254
|
+
telemetry about itself.
|
|
255
|
+
"""
|
|
256
|
+
from snowflake.connector.aio.connection._connection import Connection as AsyncConnection
|
|
257
|
+
from snowflake.connector.aio.cursor._base import SnowflakeCursorBase as AsyncSnowflakeCursorBase
|
|
258
|
+
from snowflake.connector.connection import Connection
|
|
259
|
+
from snowflake.connector.cursor._base import SnowflakeCursorBase
|
|
260
|
+
|
|
261
|
+
if isinstance(self, (Connection, AsyncConnection)):
|
|
262
|
+
connection = self
|
|
263
|
+
elif isinstance(self, (SnowflakeCursorBase, AsyncSnowflakeCursorBase)):
|
|
264
|
+
connection = self._connection
|
|
265
|
+
else:
|
|
266
|
+
raise TypeError(f"Unexpected telemetry target: {type(self)!r}")
|
|
267
|
+
|
|
268
|
+
client = getattr(connection, "_telemetry_client", None)
|
|
269
|
+
if client is None or getattr(client, "_closed", False):
|
|
270
|
+
return None
|
|
271
|
+
if not (connection._client_param_telemetry_enabled and connection._server_param_telemetry_enabled()):
|
|
272
|
+
return None
|
|
273
|
+
return client
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _passed_argument_names(
|
|
277
|
+
sig: inspect.Signature,
|
|
278
|
+
self: Any,
|
|
279
|
+
args: tuple[Any, ...],
|
|
280
|
+
kwargs: dict[str, Any],
|
|
281
|
+
) -> list[str]:
|
|
282
|
+
"""Return the names of the arguments the caller explicitly passed.
|
|
283
|
+
|
|
284
|
+
Signature only — never argument values. Parameters the caller left at
|
|
285
|
+
their default are omitted, because :attr:`BoundArguments.arguments` only
|
|
286
|
+
contains arguments that were actually supplied (we deliberately do not
|
|
287
|
+
call ``apply_defaults()``). ``**kwargs`` entries are expanded to the
|
|
288
|
+
keyword names the caller used, since the var-keyword parameter name
|
|
289
|
+
itself (e.g. ``"kwargs"``) carries no signal. The first positional
|
|
290
|
+
(connection/cursor instance) is dropped.
|
|
291
|
+
|
|
292
|
+
Defensive by design: any binding failure yields ``[]`` so telemetry can
|
|
293
|
+
never break the wrapped call.
|
|
294
|
+
"""
|
|
295
|
+
try:
|
|
296
|
+
bound = sig.bind(self, *args, **kwargs)
|
|
297
|
+
except TypeError:
|
|
298
|
+
return []
|
|
299
|
+
names: list[str] = []
|
|
300
|
+
for index, (name, bound_arg) in enumerate(bound.arguments.items()):
|
|
301
|
+
if index == 0:
|
|
302
|
+
continue # first positional (connection/cursor), always bound first by the wrapper
|
|
303
|
+
param = sig.parameters[name]
|
|
304
|
+
if param.kind is inspect.Parameter.VAR_KEYWORD:
|
|
305
|
+
names.extend(bound_arg.keys())
|
|
306
|
+
else:
|
|
307
|
+
names.append(name)
|
|
308
|
+
return names
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _schedule_async_telemetry(coro: Any) -> None:
|
|
312
|
+
"""Fire-and-forget async telemetry when a sync decorated method runs under a loop."""
|
|
313
|
+
try:
|
|
314
|
+
asyncio.get_running_loop().create_task(coro)
|
|
315
|
+
except RuntimeError:
|
|
316
|
+
coro.close()
|
|
317
|
+
logger.debug("Skipped async telemetry with no running event loop", exc_info=True)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _api_method_name(self: Any, func: Callable[..., Any], *, async_path: bool) -> str:
|
|
321
|
+
name = f"{type(self).__name__}.{func.__name__}"
|
|
322
|
+
if async_path:
|
|
323
|
+
return f"async {name}"
|
|
324
|
+
return name
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _send_api_usage(self: Any, func: Callable[..., Any], passed_arguments: list[str]) -> None:
|
|
328
|
+
"""Send the ``{ClassName}.{method_name}`` API-usage telemetry for *self*."""
|
|
329
|
+
try:
|
|
330
|
+
from snowflake.connector._common.telemetry import AsyncTelemetryClient
|
|
331
|
+
|
|
332
|
+
api_name = _api_method_name(self, func, async_path=False)
|
|
333
|
+
client = _telemetry_client_if_enabled(self)
|
|
334
|
+
if client is None:
|
|
335
|
+
return
|
|
336
|
+
if isinstance(client, AsyncTelemetryClient):
|
|
337
|
+
_schedule_async_telemetry(client.send_api_usage(api_name, passed_arguments))
|
|
338
|
+
else:
|
|
339
|
+
client.send_api_usage(api_name, passed_arguments)
|
|
340
|
+
except Exception:
|
|
341
|
+
logger.debug("Failed to send api_usage telemetry", exc_info=True)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
async def _send_api_usage_async(self: Any, func: Callable[..., Any], passed_arguments: list[str]) -> None:
|
|
345
|
+
"""Async counterpart of :func:`_send_api_usage`.
|
|
346
|
+
|
|
347
|
+
Coroutine and async-generator methods record
|
|
348
|
+
``async {ClassName}.{method_name}`` so they are distinguishable from the
|
|
349
|
+
sync methods that share the same class and function names.
|
|
350
|
+
"""
|
|
351
|
+
try:
|
|
352
|
+
from snowflake.connector._common.telemetry import AsyncTelemetryClient
|
|
353
|
+
|
|
354
|
+
api_name = _api_method_name(self, func, async_path=True)
|
|
355
|
+
client = _telemetry_client_if_enabled(self)
|
|
356
|
+
if client is None:
|
|
357
|
+
return
|
|
358
|
+
if isinstance(client, AsyncTelemetryClient):
|
|
359
|
+
await client.send_api_usage(api_name, passed_arguments)
|
|
360
|
+
else:
|
|
361
|
+
client.send_api_usage(api_name, passed_arguments)
|
|
362
|
+
except Exception:
|
|
363
|
+
logger.debug("Failed to send api_usage telemetry", exc_info=True)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def api_telemetry(func: F) -> F:
|
|
367
|
+
"""Record API-usage telemetry for the outermost call.
|
|
368
|
+
|
|
369
|
+
Suppresses ``_TRACKING`` for the method body so nested decorated calls
|
|
370
|
+
are not recorded. Generator results are wrapped to suppress only during
|
|
371
|
+
each iteration step (see :func:`_suppress_tracking_generator`).
|
|
372
|
+
|
|
373
|
+
Supports synchronous functions, coroutine functions, and async generator
|
|
374
|
+
functions — the suppression always spans the actual execution of the
|
|
375
|
+
wrapped callable (the awaited body or each iteration step). Sync methods
|
|
376
|
+
record ``{ClassName}.{method_name}``; coroutine and async-generator
|
|
377
|
+
methods record ``async {ClassName}.{method_name}``.
|
|
378
|
+
|
|
379
|
+
Alongside the method name, the names of the arguments the caller
|
|
380
|
+
explicitly passed are recorded (see :func:`_passed_argument_names`) —
|
|
381
|
+
names only, never values, and parameters left at their default are
|
|
382
|
+
omitted.
|
|
383
|
+
|
|
384
|
+
Free functions (first parameter name is neither ``self`` nor ``cls``) are
|
|
385
|
+
wrapped with a signature-transparent ``(*args, **kwargs)`` wrapper.
|
|
386
|
+
Telemetry dispatch is skipped for free functions because there is no
|
|
387
|
+
``self`` from which to retrieve the telemetry client; ``_TRACKING``
|
|
388
|
+
suppression still applies so nested decorated calls are not double-counted.
|
|
389
|
+
"""
|
|
390
|
+
sig = inspect.signature(func)
|
|
391
|
+
params = list(sig.parameters)
|
|
392
|
+
_is_method = bool(params) and params[0] in ("self", "cls")
|
|
393
|
+
|
|
394
|
+
if inspect.iscoroutinefunction(func):
|
|
395
|
+
if _is_method:
|
|
396
|
+
|
|
397
|
+
@functools.wraps(func)
|
|
398
|
+
async def async_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
399
|
+
if _TRACKING.get():
|
|
400
|
+
await _send_api_usage_async(self, func, _passed_argument_names(sig, self, args, kwargs))
|
|
401
|
+
_TRACKING.set(False)
|
|
402
|
+
try:
|
|
403
|
+
return await func(self, *args, **kwargs)
|
|
404
|
+
finally:
|
|
405
|
+
_TRACKING.set(True)
|
|
406
|
+
return await func(self, *args, **kwargs)
|
|
407
|
+
|
|
408
|
+
return cast(F, async_wrapper)
|
|
409
|
+
|
|
410
|
+
@functools.wraps(func)
|
|
411
|
+
async def async_free_wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
412
|
+
if _TRACKING.get():
|
|
413
|
+
_TRACKING.set(False)
|
|
414
|
+
try:
|
|
415
|
+
return await func(*args, **kwargs)
|
|
416
|
+
finally:
|
|
417
|
+
_TRACKING.set(True)
|
|
418
|
+
return await func(*args, **kwargs)
|
|
419
|
+
|
|
420
|
+
return cast(F, async_free_wrapper)
|
|
421
|
+
|
|
422
|
+
if inspect.isasyncgenfunction(func):
|
|
423
|
+
if _is_method:
|
|
424
|
+
|
|
425
|
+
@functools.wraps(func)
|
|
426
|
+
async def async_gen_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
427
|
+
if _TRACKING.get():
|
|
428
|
+
await _send_api_usage_async(self, func, _passed_argument_names(sig, self, args, kwargs))
|
|
429
|
+
async for value in _suppress_tracking_async_generator(func(self, *args, **kwargs)):
|
|
430
|
+
yield value
|
|
431
|
+
else:
|
|
432
|
+
async for value in func(self, *args, **kwargs):
|
|
433
|
+
yield value
|
|
434
|
+
|
|
435
|
+
return cast(F, async_gen_wrapper)
|
|
436
|
+
|
|
437
|
+
@functools.wraps(func)
|
|
438
|
+
async def async_gen_free_wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
439
|
+
if _TRACKING.get():
|
|
440
|
+
async for value in _suppress_tracking_async_generator(func(*args, **kwargs)):
|
|
441
|
+
yield value
|
|
442
|
+
else:
|
|
443
|
+
async for value in func(*args, **kwargs):
|
|
444
|
+
yield value
|
|
445
|
+
|
|
446
|
+
return cast(F, async_gen_free_wrapper)
|
|
447
|
+
|
|
448
|
+
if _is_method:
|
|
449
|
+
|
|
450
|
+
@functools.wraps(func)
|
|
451
|
+
def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
452
|
+
if _TRACKING.get():
|
|
453
|
+
if func.__name__ == "__init__":
|
|
454
|
+
# Compute argument names before calling (kwargs are not consumed by
|
|
455
|
+
# the call), but send telemetry post-call so _telemetry_client is ready.
|
|
456
|
+
passed_args = _passed_argument_names(sig, self, args, kwargs)
|
|
457
|
+
_TRACKING.set(False)
|
|
458
|
+
try:
|
|
459
|
+
result = func(self, *args, **kwargs)
|
|
460
|
+
finally:
|
|
461
|
+
_TRACKING.set(True)
|
|
462
|
+
_send_api_usage(self, func, passed_args)
|
|
463
|
+
return result
|
|
464
|
+
|
|
465
|
+
_send_api_usage(self, func, _passed_argument_names(sig, self, args, kwargs))
|
|
466
|
+
|
|
467
|
+
_TRACKING.set(False)
|
|
468
|
+
try:
|
|
469
|
+
result = func(self, *args, **kwargs)
|
|
470
|
+
finally:
|
|
471
|
+
_TRACKING.set(True)
|
|
472
|
+
|
|
473
|
+
if isinstance(result, types.GeneratorType):
|
|
474
|
+
return _suppress_tracking_generator(result)
|
|
475
|
+
|
|
476
|
+
return result
|
|
477
|
+
return func(self, *args, **kwargs)
|
|
478
|
+
|
|
479
|
+
return cast(F, wrapper)
|
|
480
|
+
|
|
481
|
+
@functools.wraps(func)
|
|
482
|
+
def free_wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
483
|
+
if _TRACKING.get():
|
|
484
|
+
_TRACKING.set(False)
|
|
485
|
+
try:
|
|
486
|
+
result = func(*args, **kwargs)
|
|
487
|
+
finally:
|
|
488
|
+
_TRACKING.set(True)
|
|
489
|
+
|
|
490
|
+
if isinstance(result, types.GeneratorType):
|
|
491
|
+
return _suppress_tracking_generator(result)
|
|
492
|
+
|
|
493
|
+
return result
|
|
494
|
+
return func(*args, **kwargs)
|
|
495
|
+
|
|
496
|
+
return cast(F, free_wrapper)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def _suppress_tracking_generator(
|
|
500
|
+
gen: Generator[Any, Any, Any],
|
|
501
|
+
) -> Generator[Any, Any, Any]:
|
|
502
|
+
"""Suppress ``_TRACKING`` during each iteration step, restore between yields.
|
|
503
|
+
|
|
504
|
+
Safe against never-started generators: the wrapper body only runs when
|
|
505
|
+
iterated, and ``api_telemetry`` resets ``_TRACKING`` before creating it.
|
|
506
|
+
"""
|
|
507
|
+
_TRACKING.set(False)
|
|
508
|
+
try:
|
|
509
|
+
for value in gen:
|
|
510
|
+
_TRACKING.set(True)
|
|
511
|
+
try:
|
|
512
|
+
yield value
|
|
513
|
+
except GeneratorExit:
|
|
514
|
+
gen.close()
|
|
515
|
+
return
|
|
516
|
+
_TRACKING.set(False)
|
|
517
|
+
finally:
|
|
518
|
+
_TRACKING.set(True)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
async def _suppress_tracking_async_generator(
|
|
522
|
+
agen: AsyncGenerator[Any, Any],
|
|
523
|
+
) -> AsyncGenerator[Any, Any]:
|
|
524
|
+
"""Async counterpart of :func:`_suppress_tracking_generator`.
|
|
525
|
+
|
|
526
|
+
Suppress ``_TRACKING`` during each iteration step, restore between yields.
|
|
527
|
+
"""
|
|
528
|
+
_TRACKING.set(False)
|
|
529
|
+
try:
|
|
530
|
+
async for value in agen:
|
|
531
|
+
_TRACKING.set(True)
|
|
532
|
+
try:
|
|
533
|
+
yield value
|
|
534
|
+
except GeneratorExit:
|
|
535
|
+
await agen.aclose()
|
|
536
|
+
return
|
|
537
|
+
_TRACKING.set(False)
|
|
538
|
+
finally:
|
|
539
|
+
_TRACKING.set(True)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Proto ErrorKind → PEP 249 exception class / errno mappings.
|
|
3
|
+
|
|
4
|
+
ERROR_KIND_* values are imported from the generated pb2 module so they
|
|
5
|
+
stay in sync with the Rust core automatically.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from ..errors import (
|
|
11
|
+
DatabaseError,
|
|
12
|
+
Error,
|
|
13
|
+
IntegrityError,
|
|
14
|
+
InternalError,
|
|
15
|
+
NotSupportedError,
|
|
16
|
+
OperationalError,
|
|
17
|
+
ProgrammingError,
|
|
18
|
+
)
|
|
19
|
+
from .errorcode import (
|
|
20
|
+
ER_COMPRESSION_NOT_SUPPORTED,
|
|
21
|
+
ER_FAILED_TO_CONNECT_TO_DB,
|
|
22
|
+
ER_FILE_NOT_EXISTS,
|
|
23
|
+
ER_INVALID_VALUE,
|
|
24
|
+
)
|
|
25
|
+
from .protobuf_gen.database_driver_v1_pb2 import (
|
|
26
|
+
ERROR_KIND_AUTHENTICATION_ERROR,
|
|
27
|
+
ERROR_KIND_CANCELLED,
|
|
28
|
+
ERROR_KIND_INTERNAL_ERROR,
|
|
29
|
+
ERROR_KIND_INVALID_ARGUMENT,
|
|
30
|
+
ERROR_KIND_INVALID_PARAMETER_VALUE,
|
|
31
|
+
ERROR_KIND_IO,
|
|
32
|
+
ERROR_KIND_LOCAL_FILE_NOT_FOUND,
|
|
33
|
+
ERROR_KIND_LOGIN_ERROR,
|
|
34
|
+
ERROR_KIND_MISSING_PARAMETER,
|
|
35
|
+
ERROR_KIND_NOT_IMPLEMENTED,
|
|
36
|
+
ERROR_KIND_QUERY_FAILED,
|
|
37
|
+
ERROR_KIND_REMOTE_FILE_NOT_FOUND,
|
|
38
|
+
ERROR_KIND_STAGE_BINDING,
|
|
39
|
+
ERROR_KIND_TIMEOUT,
|
|
40
|
+
ERROR_KIND_UNSUPPORTED_COMPRESSION,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
ERROR_KIND_LABELS: dict[int, str] = {
|
|
45
|
+
ERROR_KIND_AUTHENTICATION_ERROR: "Authentication error",
|
|
46
|
+
ERROR_KIND_NOT_IMPLEMENTED: "Not implemented",
|
|
47
|
+
ERROR_KIND_INVALID_ARGUMENT: "Invalid argument",
|
|
48
|
+
ERROR_KIND_IO: "I/O error",
|
|
49
|
+
ERROR_KIND_CANCELLED: "Cancelled",
|
|
50
|
+
ERROR_KIND_INTERNAL_ERROR: "Internal error",
|
|
51
|
+
ERROR_KIND_MISSING_PARAMETER: "Missing parameter",
|
|
52
|
+
ERROR_KIND_INVALID_PARAMETER_VALUE: "Invalid parameter value",
|
|
53
|
+
ERROR_KIND_LOGIN_ERROR: "Login error",
|
|
54
|
+
ERROR_KIND_LOCAL_FILE_NOT_FOUND: "Local file not found",
|
|
55
|
+
ERROR_KIND_REMOTE_FILE_NOT_FOUND: "Remote file not found",
|
|
56
|
+
ERROR_KIND_UNSUPPORTED_COMPRESSION: "Unsupported compression type",
|
|
57
|
+
ERROR_KIND_QUERY_FAILED: "Query failed",
|
|
58
|
+
ERROR_KIND_TIMEOUT: "Timeout",
|
|
59
|
+
ERROR_KIND_STAGE_BINDING: "Stage binding",
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
KIND_TO_EXCEPTION: dict[int, type[Error]] = {
|
|
63
|
+
ERROR_KIND_AUTHENTICATION_ERROR: DatabaseError,
|
|
64
|
+
ERROR_KIND_NOT_IMPLEMENTED: NotSupportedError,
|
|
65
|
+
ERROR_KIND_INVALID_ARGUMENT: ProgrammingError,
|
|
66
|
+
ERROR_KIND_IO: OperationalError,
|
|
67
|
+
ERROR_KIND_CANCELLED: OperationalError,
|
|
68
|
+
# Leftover driver faults (locks, parse, spool). Query failures use QUERY_FAILED.
|
|
69
|
+
ERROR_KIND_INTERNAL_ERROR: InternalError,
|
|
70
|
+
ERROR_KIND_MISSING_PARAMETER: ProgrammingError,
|
|
71
|
+
ERROR_KIND_INVALID_PARAMETER_VALUE: ProgrammingError,
|
|
72
|
+
ERROR_KIND_LOGIN_ERROR: DatabaseError,
|
|
73
|
+
ERROR_KIND_LOCAL_FILE_NOT_FOUND: ProgrammingError,
|
|
74
|
+
ERROR_KIND_REMOTE_FILE_NOT_FOUND: OperationalError,
|
|
75
|
+
ERROR_KIND_UNSUPPORTED_COMPRESSION: ProgrammingError,
|
|
76
|
+
ERROR_KIND_QUERY_FAILED: ProgrammingError,
|
|
77
|
+
ERROR_KIND_TIMEOUT: OperationalError,
|
|
78
|
+
# CSV bind-upload to SYSTEM$BIND failed. Same class as other transfer I/O.
|
|
79
|
+
ERROR_KIND_STAGE_BINDING: OperationalError,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Snowflake vendor_code → exception overrides.
|
|
83
|
+
#
|
|
84
|
+
# KIND_TO_EXCEPTION maps the proto ErrorKind (a broad category) to a default PEP 249 class.
|
|
85
|
+
# Some Snowflake server errors share the same ErrorKind (e.g. ERROR_KIND_QUERY_FAILED)
|
|
86
|
+
# but carry a vendor_code that warrants a more specific exception.
|
|
87
|
+
# Entries here take precedence over KIND_TO_EXCEPTION when a vendor_code is present.
|
|
88
|
+
VENDOR_CODE_TO_EXCEPTION: dict[int, type[Error]] = {
|
|
89
|
+
100072: IntegrityError, # NULL result in a non-nullable column
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def is_stage_binding_disabled(exc: Exception) -> bool:
|
|
94
|
+
"""Whether *exc* came from a disabled ``SYSTEM$BIND`` stage.
|
|
95
|
+
|
|
96
|
+
``errno`` falls back to the raw ``kind`` when no vendor_code or
|
|
97
|
+
KIND_TO_ERRNO entry applies (see ``_convert_application_error``), so
|
|
98
|
+
``ERROR_KIND_STAGE_BINDING`` survives unchanged onto the exception.
|
|
99
|
+
"""
|
|
100
|
+
return isinstance(exc, OperationalError) and getattr(exc, "errno", None) == ERROR_KIND_STAGE_BINDING
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Prefer the Snowflake server vendor_code when the core driver provides it, fallback to this mapping if not present.
|
|
104
|
+
KIND_TO_ERRNO: dict[int, int] = {
|
|
105
|
+
ERROR_KIND_AUTHENTICATION_ERROR: ER_FAILED_TO_CONNECT_TO_DB,
|
|
106
|
+
ERROR_KIND_LOGIN_ERROR: ER_FAILED_TO_CONNECT_TO_DB,
|
|
107
|
+
ERROR_KIND_INVALID_PARAMETER_VALUE: ER_INVALID_VALUE,
|
|
108
|
+
ERROR_KIND_LOCAL_FILE_NOT_FOUND: ER_FILE_NOT_EXISTS,
|
|
109
|
+
ERROR_KIND_REMOTE_FILE_NOT_FOUND: ER_FILE_NOT_EXISTS,
|
|
110
|
+
ERROR_KIND_UNSUPPORTED_COMPRESSION: ER_COMPRESSION_NOT_SUPPORTED,
|
|
111
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Snowflake error codes.
|
|
3
|
+
|
|
4
|
+
These codes are intentionally aligned with the reference snowflake-connector-python
|
|
5
|
+
so that users can rely on stable, documented error numbers across driver implementations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# network
|
|
12
|
+
ER_FAILED_TO_CONNECT_TO_DB = 250001
|
|
13
|
+
ER_CONNECTION_IS_CLOSED = 250002
|
|
14
|
+
|
|
15
|
+
# connection
|
|
16
|
+
ER_NO_ACCOUNT_NAME = 251001
|
|
17
|
+
ER_NO_USER = 251005
|
|
18
|
+
ER_NO_PASSWORD = 251006
|
|
19
|
+
ER_INVALID_VALUE = 251007
|
|
20
|
+
ER_INVALID_WIF_SETTINGS = 251017
|
|
21
|
+
|
|
22
|
+
# cursor
|
|
23
|
+
ER_FAILED_TO_REWRITE_MULTI_ROW_INSERT = 252001
|
|
24
|
+
ER_FAILED_TO_CONVERT_ROW_TO_PYTHON_TYPE = 252005
|
|
25
|
+
ER_CURSOR_IS_CLOSED = 252006
|
|
26
|
+
ER_NO_DATA_FOUND = 252009
|
|
27
|
+
|
|
28
|
+
# file transfer
|
|
29
|
+
ER_FILE_NOT_EXISTS = 253006
|
|
30
|
+
ER_COMPRESSION_NOT_SUPPORTED = 253007
|
|
31
|
+
|
|
32
|
+
# converter
|
|
33
|
+
ER_NOT_SUPPORT_DATA_TYPE = 255001
|
|
34
|
+
ER_NO_PYARROW = 255002
|
|
35
|
+
ER_NO_NUMPY = 255006
|