snowflake-connector-python 4.4.0__cp314-cp314-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 +118 -0
- snowflake/connector/_query_context_cache.py +276 -0
- snowflake/connector/_sql_util.py +48 -0
- snowflake/connector/_utils.py +353 -0
- snowflake/connector/aio/README.md +88 -0
- snowflake/connector/aio/__init__.py +163 -0
- snowflake/connector/aio/_azure_storage_client.py +227 -0
- snowflake/connector/aio/_bind_upload_agent.py +69 -0
- snowflake/connector/aio/_connection.py +1216 -0
- snowflake/connector/aio/_cursor.py +1402 -0
- snowflake/connector/aio/_description.py +5 -0
- snowflake/connector/aio/_direct_file_operation_utils.py +88 -0
- snowflake/connector/aio/_file_transfer_agent.py +316 -0
- snowflake/connector/aio/_gcs_storage_client.py +360 -0
- snowflake/connector/aio/_network.py +860 -0
- snowflake/connector/aio/_ocsp_asn1crypto.py +51 -0
- snowflake/connector/aio/_ocsp_snowflake.py +608 -0
- snowflake/connector/aio/_pandas_tools.py +561 -0
- snowflake/connector/aio/_result_batch.py +442 -0
- snowflake/connector/aio/_result_set.py +309 -0
- snowflake/connector/aio/_s3_storage_client.py +460 -0
- snowflake/connector/aio/_session_manager.py +588 -0
- snowflake/connector/aio/_storage_client.py +331 -0
- snowflake/connector/aio/_telemetry.py +97 -0
- snowflake/connector/aio/_time_util.py +57 -0
- snowflake/connector/aio/_wif_util.py +324 -0
- snowflake/connector/aio/auth/__init__.py +52 -0
- snowflake/connector/aio/auth/_auth.py +406 -0
- snowflake/connector/aio/auth/_by_plugin.py +131 -0
- snowflake/connector/aio/auth/_default.py +28 -0
- snowflake/connector/aio/auth/_idtoken.py +54 -0
- snowflake/connector/aio/auth/_keypair.py +60 -0
- snowflake/connector/aio/auth/_no_auth.py +31 -0
- snowflake/connector/aio/auth/_oauth.py +27 -0
- snowflake/connector/aio/auth/_oauth_code.py +117 -0
- snowflake/connector/aio/auth/_oauth_credentials.py +100 -0
- snowflake/connector/aio/auth/_okta.py +247 -0
- snowflake/connector/aio/auth/_pat.py +27 -0
- snowflake/connector/aio/auth/_usrpwdmfa.py +30 -0
- snowflake/connector/aio/auth/_webbrowser.py +405 -0
- snowflake/connector/aio/auth/_workload_identity.py +60 -0
- snowflake/connector/arrow_context.py +211 -0
- snowflake/connector/auth/__init__.py +53 -0
- snowflake/connector/auth/_auth.py +669 -0
- snowflake/connector/auth/_http_server.py +257 -0
- snowflake/connector/auth/_oauth_base.py +472 -0
- snowflake/connector/auth/by_plugin.py +219 -0
- snowflake/connector/auth/default.py +36 -0
- snowflake/connector/auth/idtoken.py +72 -0
- snowflake/connector/auth/keypair.py +225 -0
- snowflake/connector/auth/no_auth.py +39 -0
- snowflake/connector/auth/oauth.py +49 -0
- snowflake/connector/auth/oauth_code.py +490 -0
- snowflake/connector/auth/oauth_credentials.py +71 -0
- snowflake/connector/auth/okta.py +339 -0
- snowflake/connector/auth/pat.py +40 -0
- snowflake/connector/auth/usrpwdmfa.py +69 -0
- snowflake/connector/auth/webbrowser.py +514 -0
- snowflake/connector/auth/workload_identity.py +110 -0
- snowflake/connector/azure_storage_client.py +278 -0
- snowflake/connector/backoff_policies.py +141 -0
- snowflake/connector/bind_upload_agent.py +89 -0
- snowflake/connector/cache.py +696 -0
- snowflake/connector/compat.py +127 -0
- snowflake/connector/config_manager.py +553 -0
- snowflake/connector/connection.py +2671 -0
- snowflake/connector/connection_diagnostic.py +793 -0
- snowflake/connector/constants.py +460 -0
- snowflake/connector/converter.py +809 -0
- snowflake/connector/converter_issue23517.py +87 -0
- snowflake/connector/converter_null.py +14 -0
- snowflake/connector/converter_snowsql.py +205 -0
- snowflake/connector/crl.py +919 -0
- snowflake/connector/crl_cache.py +734 -0
- snowflake/connector/cursor.py +2099 -0
- snowflake/connector/dbapi.py +53 -0
- snowflake/connector/description.py +21 -0
- snowflake/connector/direct_file_operation_utils.py +88 -0
- snowflake/connector/encryption_util.py +220 -0
- snowflake/connector/errorcode.py +94 -0
- snowflake/connector/errors.py +666 -0
- snowflake/connector/externals_utils/__init__.py +0 -0
- snowflake/connector/externals_utils/externals_setup.py +30 -0
- snowflake/connector/feature.py +4 -0
- snowflake/connector/file_compression_type.py +118 -0
- snowflake/connector/file_lock.py +72 -0
- snowflake/connector/file_transfer_agent.py +1244 -0
- snowflake/connector/file_util.py +153 -0
- snowflake/connector/gcs_storage_client.py +476 -0
- snowflake/connector/gzip_decoder.py +85 -0
- snowflake/connector/interval_util.py +26 -0
- snowflake/connector/local_storage_client.py +90 -0
- snowflake/connector/log_configuration.py +62 -0
- snowflake/connector/logging_utils/__init__.py +0 -0
- snowflake/connector/logging_utils/filters.py +72 -0
- snowflake/connector/minicore/__init__.py +0 -0
- snowflake/connector/minicore/aix_ppc64/libsf_mini_core.a +0 -0
- snowflake/connector/minicore/aix_ppc64/libsf_mini_core_static.a +0 -0
- snowflake/connector/minicore/linux_aarch64_glibc/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/linux_aarch64_musl/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/linux_x86_64_glibc/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/linux_x86_64_musl/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/macos_aarch64/libsf_mini_core.dylib +0 -0
- snowflake/connector/minicore/macos_x86_64/libsf_mini_core.dylib +0 -0
- snowflake/connector/minicore/windows_x86_64/sf_mini_core.dll +0 -0
- snowflake/connector/minicore/windows_x86_64/sf_mini_core_static.lib +0 -0
- snowflake/connector/nanoarrow_arrow_iterator.cp314-win_amd64.pyd +0 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +60 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +19 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +570 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +98 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +125 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +115 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +1140 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +138 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +47 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +83 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +97 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +72 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +73 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +30 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +45 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +75 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +57 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +75 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +46 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +95 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +57 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +36 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +19 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +36 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +346 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +145 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +67 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +262 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33273 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
- snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +100 -0
- snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +49 -0
- snowflake/connector/network.py +1227 -0
- snowflake/connector/ocsp_asn1crypto.py +447 -0
- snowflake/connector/ocsp_snowflake.py +1939 -0
- snowflake/connector/options.py +179 -0
- snowflake/connector/os_details.py +88 -0
- snowflake/connector/pandas_tools.py +734 -0
- snowflake/connector/platform_detection.py +555 -0
- snowflake/connector/proxy.py +28 -0
- snowflake/connector/py.typed +0 -0
- snowflake/connector/result_batch.py +917 -0
- snowflake/connector/result_set.py +340 -0
- snowflake/connector/s3_storage_client.py +614 -0
- snowflake/connector/secret_detector.py +181 -0
- snowflake/connector/session_manager.py +650 -0
- snowflake/connector/sf_dirs.py +64 -0
- snowflake/connector/sfbinaryformat.py +35 -0
- snowflake/connector/sfdatetime.py +345 -0
- snowflake/connector/snow_logging.py +144 -0
- snowflake/connector/sqlstate.py +9 -0
- snowflake/connector/ssd_internal_keys.py +30 -0
- snowflake/connector/ssl_wrap_socket.py +281 -0
- snowflake/connector/storage_client.py +486 -0
- snowflake/connector/telemetry.py +254 -0
- snowflake/connector/telemetry_oob.py +544 -0
- snowflake/connector/test_util.py +30 -0
- snowflake/connector/time_util.py +159 -0
- snowflake/connector/token_cache.py +457 -0
- snowflake/connector/tool/__init__.py +0 -0
- snowflake/connector/tool/dump_certs.py +57 -0
- snowflake/connector/tool/dump_ocsp_response.py +139 -0
- snowflake/connector/tool/dump_ocsp_response_cache.py +194 -0
- snowflake/connector/tool/probe_connection.py +69 -0
- snowflake/connector/url_util.py +55 -0
- snowflake/connector/util_text.py +320 -0
- snowflake/connector/vendored/__init__.py +3 -0
- snowflake/connector/vendored/requests/LICENSE +175 -0
- snowflake/connector/vendored/requests/__init__.py +184 -0
- snowflake/connector/vendored/requests/__version__.py +14 -0
- snowflake/connector/vendored/requests/_internal_utils.py +50 -0
- snowflake/connector/vendored/requests/adapters.py +696 -0
- snowflake/connector/vendored/requests/api.py +157 -0
- snowflake/connector/vendored/requests/auth.py +314 -0
- snowflake/connector/vendored/requests/certs.py +17 -0
- snowflake/connector/vendored/requests/compat.py +106 -0
- snowflake/connector/vendored/requests/cookies.py +561 -0
- snowflake/connector/vendored/requests/exceptions.py +151 -0
- snowflake/connector/vendored/requests/help.py +134 -0
- snowflake/connector/vendored/requests/hooks.py +33 -0
- snowflake/connector/vendored/requests/models.py +1039 -0
- snowflake/connector/vendored/requests/packages.py +23 -0
- snowflake/connector/vendored/requests/sessions.py +831 -0
- snowflake/connector/vendored/requests/status_codes.py +128 -0
- snowflake/connector/vendored/requests/structures.py +99 -0
- snowflake/connector/vendored/requests/utils.py +1086 -0
- snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
- snowflake/connector/vendored/urllib3/__init__.py +211 -0
- snowflake/connector/vendored/urllib3/_base_connection.py +165 -0
- snowflake/connector/vendored/urllib3/_collections.py +487 -0
- snowflake/connector/vendored/urllib3/_request_methods.py +278 -0
- snowflake/connector/vendored/urllib3/_version.py +34 -0
- snowflake/connector/vendored/urllib3/connection.py +1108 -0
- snowflake/connector/vendored/urllib3/connectionpool.py +1178 -0
- snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/__init__.py +17 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/connection.py +260 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/emscripten_fetch_worker.js +110 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/fetch.py +726 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/request.py +22 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/response.py +277 -0
- snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +564 -0
- snowflake/connector/vendored/urllib3/contrib/socks.py +228 -0
- snowflake/connector/vendored/urllib3/exceptions.py +335 -0
- snowflake/connector/vendored/urllib3/fields.py +341 -0
- snowflake/connector/vendored/urllib3/filepost.py +89 -0
- snowflake/connector/vendored/urllib3/http2/__init__.py +53 -0
- snowflake/connector/vendored/urllib3/http2/connection.py +356 -0
- snowflake/connector/vendored/urllib3/http2/probe.py +87 -0
- snowflake/connector/vendored/urllib3/poolmanager.py +651 -0
- snowflake/connector/vendored/urllib3/py.typed +2 -0
- snowflake/connector/vendored/urllib3/response.py +1480 -0
- snowflake/connector/vendored/urllib3/util/__init__.py +42 -0
- snowflake/connector/vendored/urllib3/util/connection.py +137 -0
- snowflake/connector/vendored/urllib3/util/proxy.py +43 -0
- snowflake/connector/vendored/urllib3/util/request.py +263 -0
- snowflake/connector/vendored/urllib3/util/response.py +101 -0
- snowflake/connector/vendored/urllib3/util/retry.py +549 -0
- snowflake/connector/vendored/urllib3/util/ssl_.py +527 -0
- snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
- snowflake/connector/vendored/urllib3/util/ssltransport.py +271 -0
- snowflake/connector/vendored/urllib3/util/timeout.py +275 -0
- snowflake/connector/vendored/urllib3/util/url.py +469 -0
- snowflake/connector/vendored/urllib3/util/util.py +42 -0
- snowflake/connector/vendored/urllib3/util/wait.py +124 -0
- snowflake/connector/version.py +3 -0
- snowflake/connector/wif_util.py +434 -0
- snowflake_connector_python-4.4.0.dist-info/DELVEWHEEL +2 -0
- snowflake_connector_python-4.4.0.dist-info/METADATA +1591 -0
- snowflake_connector_python-4.4.0.dist-info/RECORD +302 -0
- snowflake_connector_python-4.4.0.dist-info/WHEEL +5 -0
- snowflake_connector_python-4.4.0.dist-info/entry_points.txt +4 -0
- snowflake_connector_python-4.4.0.dist-info/licenses/LICENSE.txt +202 -0
- snowflake_connector_python-4.4.0.dist-info/licenses/NOTICE +8 -0
- snowflake_connector_python-4.4.0.dist-info/top_level.txt +1 -0
- snowflake_connector_python.libs/msvcp140-0f885b509a685d2bbfa652fed26b5fb3.dll +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import json
|
|
5
|
+
import xml.etree.ElementTree as ET
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from logging import getLogger
|
|
8
|
+
from random import choice
|
|
9
|
+
from string import hexdigits
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
11
|
+
|
|
12
|
+
import aiohttp
|
|
13
|
+
|
|
14
|
+
from ..azure_storage_client import (
|
|
15
|
+
SnowflakeAzureRestClient as SnowflakeAzureRestClientSync,
|
|
16
|
+
)
|
|
17
|
+
from ..compat import quote
|
|
18
|
+
from ..constants import FileHeader, ResultStatus
|
|
19
|
+
from ..encryption_util import EncryptionMetadata
|
|
20
|
+
from ..util_text import get_md5_for_integrity
|
|
21
|
+
from ._storage_client import SnowflakeStorageClient as SnowflakeStorageClientAsync
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
24
|
+
from ..file_transfer_agent import SnowflakeFileMeta, StorageCredential
|
|
25
|
+
|
|
26
|
+
from ..azure_storage_client import (
|
|
27
|
+
ENCRYPTION_DATA,
|
|
28
|
+
MATDESC,
|
|
29
|
+
SFCDIGEST,
|
|
30
|
+
TOKEN_EXPIRATION_ERR_MESSAGE,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
logger = getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SnowflakeAzureRestClient(
|
|
37
|
+
SnowflakeStorageClientAsync, SnowflakeAzureRestClientSync
|
|
38
|
+
):
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
meta: SnowflakeFileMeta,
|
|
42
|
+
credentials: StorageCredential | None,
|
|
43
|
+
chunk_size: int,
|
|
44
|
+
stage_info: dict[str, Any],
|
|
45
|
+
unsafe_file_write: bool = False,
|
|
46
|
+
) -> None:
|
|
47
|
+
SnowflakeAzureRestClientSync.__init__(
|
|
48
|
+
self,
|
|
49
|
+
meta=meta,
|
|
50
|
+
stage_info=stage_info,
|
|
51
|
+
chunk_size=chunk_size,
|
|
52
|
+
credentials=credentials,
|
|
53
|
+
unsafe_file_write=unsafe_file_write,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
async def _has_expired_token(self, response: aiohttp.ClientResponse) -> bool:
|
|
57
|
+
return response.status == 403 and any(
|
|
58
|
+
message in response.reason for message in TOKEN_EXPIRATION_ERR_MESSAGE
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
async def _send_request_with_authentication_and_retry(
|
|
62
|
+
self,
|
|
63
|
+
verb: str,
|
|
64
|
+
url: str,
|
|
65
|
+
retry_id: int | str,
|
|
66
|
+
headers: dict[str, Any] = None,
|
|
67
|
+
data: bytes = None,
|
|
68
|
+
) -> aiohttp.ClientResponse:
|
|
69
|
+
if not headers:
|
|
70
|
+
headers = {}
|
|
71
|
+
|
|
72
|
+
def generate_authenticated_url_and_rest_args() -> tuple[str, dict[str, Any]]:
|
|
73
|
+
curtime = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
74
|
+
timestamp = curtime.strftime("YYYY-MM-DD")
|
|
75
|
+
sas_token = self.credentials.creds["AZURE_SAS_TOKEN"]
|
|
76
|
+
if sas_token and sas_token.startswith("?"):
|
|
77
|
+
sas_token = sas_token[1:]
|
|
78
|
+
if "?" in url:
|
|
79
|
+
_url = url + "&" + sas_token
|
|
80
|
+
else:
|
|
81
|
+
_url = url + "?" + sas_token
|
|
82
|
+
headers["Date"] = timestamp
|
|
83
|
+
rest_args = {"headers": headers}
|
|
84
|
+
if data:
|
|
85
|
+
rest_args["data"] = data
|
|
86
|
+
return _url, rest_args
|
|
87
|
+
|
|
88
|
+
return await self._send_request_with_retry(
|
|
89
|
+
verb, generate_authenticated_url_and_rest_args, retry_id
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async def get_file_header(self, filename: str) -> FileHeader | None:
|
|
93
|
+
"""Gets Azure file properties."""
|
|
94
|
+
container_name = quote(self.azure_location.container_name)
|
|
95
|
+
path = quote(self.azure_location.path) + quote(filename)
|
|
96
|
+
meta = self.meta
|
|
97
|
+
# HTTP HEAD request
|
|
98
|
+
url = f"https://{self.storage_account}.blob.{self.endpoint}/{container_name}/{path}"
|
|
99
|
+
retry_id = "HEAD"
|
|
100
|
+
self.retry_count[retry_id] = 0
|
|
101
|
+
r = await self._send_request_with_authentication_and_retry(
|
|
102
|
+
"HEAD", url, retry_id
|
|
103
|
+
)
|
|
104
|
+
if r.status == 200:
|
|
105
|
+
meta.result_status = ResultStatus.UPLOADED
|
|
106
|
+
enc_data_str = r.headers.get(ENCRYPTION_DATA)
|
|
107
|
+
encryption_data = None if enc_data_str is None else json.loads(enc_data_str)
|
|
108
|
+
encryption_metadata = (
|
|
109
|
+
None
|
|
110
|
+
if not encryption_data
|
|
111
|
+
else EncryptionMetadata(
|
|
112
|
+
key=encryption_data["WrappedContentKey"]["EncryptedKey"],
|
|
113
|
+
iv=encryption_data["ContentEncryptionIV"],
|
|
114
|
+
matdesc=r.headers.get(MATDESC),
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
return FileHeader(
|
|
118
|
+
digest=r.headers.get(SFCDIGEST),
|
|
119
|
+
content_length=int(r.headers.get("Content-Length")),
|
|
120
|
+
encryption_metadata=encryption_metadata,
|
|
121
|
+
)
|
|
122
|
+
elif r.status == 404:
|
|
123
|
+
meta.result_status = ResultStatus.NOT_FOUND_FILE
|
|
124
|
+
return FileHeader(
|
|
125
|
+
digest=None, content_length=None, encryption_metadata=None
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
r.raise_for_status()
|
|
129
|
+
|
|
130
|
+
async def _initiate_multipart_upload(self) -> None:
|
|
131
|
+
self.block_ids = [
|
|
132
|
+
"".join(choice(hexdigits) for _ in range(20))
|
|
133
|
+
for _ in range(self.num_of_chunks)
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
async def _upload_chunk(self, chunk_id: int, chunk: bytes) -> None:
|
|
137
|
+
container_name = quote(self.azure_location.container_name)
|
|
138
|
+
path = quote(self.azure_location.path + self.meta.dst_file_name.lstrip("/"))
|
|
139
|
+
|
|
140
|
+
if self.num_of_chunks > 1:
|
|
141
|
+
block_id = self.block_ids[chunk_id]
|
|
142
|
+
url = (
|
|
143
|
+
f"https://{self.storage_account}.blob.{self.endpoint}/{container_name}/{path}?comp=block"
|
|
144
|
+
f"&blockid={block_id}"
|
|
145
|
+
)
|
|
146
|
+
headers = {"Content-Length": str(len(chunk))}
|
|
147
|
+
r = await self._send_request_with_authentication_and_retry(
|
|
148
|
+
"PUT", url, chunk_id, headers=headers, data=chunk
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
# single request
|
|
152
|
+
azure_metadata = self._prepare_file_metadata()
|
|
153
|
+
url = f"https://{self.storage_account}.blob.{self.endpoint}/{container_name}/{path}"
|
|
154
|
+
headers = {
|
|
155
|
+
"x-ms-blob-type": "BlockBlob",
|
|
156
|
+
"Content-Encoding": "utf-8",
|
|
157
|
+
}
|
|
158
|
+
headers.update(azure_metadata)
|
|
159
|
+
r = await self._send_request_with_authentication_and_retry(
|
|
160
|
+
"PUT", url, chunk_id, headers=headers, data=chunk
|
|
161
|
+
)
|
|
162
|
+
r.raise_for_status() # expect status code 201
|
|
163
|
+
|
|
164
|
+
async def _complete_multipart_upload(self) -> None:
|
|
165
|
+
container_name = quote(self.azure_location.container_name)
|
|
166
|
+
path = quote(self.azure_location.path + self.meta.dst_file_name.lstrip("/"))
|
|
167
|
+
url = (
|
|
168
|
+
f"https://{self.storage_account}.blob.{self.endpoint}/{container_name}/{path}?comp"
|
|
169
|
+
f"=blocklist"
|
|
170
|
+
)
|
|
171
|
+
root = ET.Element("BlockList")
|
|
172
|
+
for block_id in self.block_ids:
|
|
173
|
+
part = ET.Element("Latest")
|
|
174
|
+
part.text = block_id
|
|
175
|
+
root.append(part)
|
|
176
|
+
# SNOW-1778088: We need to calculate the MD5 sum of this file for Azure Blob storage
|
|
177
|
+
new_stream = not bool(self.meta.src_stream or self.meta.intermediate_stream)
|
|
178
|
+
fd = (
|
|
179
|
+
self.meta.src_stream
|
|
180
|
+
or self.meta.intermediate_stream
|
|
181
|
+
or open(self.meta.real_src_file_name, "rb")
|
|
182
|
+
)
|
|
183
|
+
try:
|
|
184
|
+
if not new_stream:
|
|
185
|
+
# Reset position in file
|
|
186
|
+
fd.seek(0)
|
|
187
|
+
file_content = fd.read()
|
|
188
|
+
finally:
|
|
189
|
+
if new_stream:
|
|
190
|
+
fd.close()
|
|
191
|
+
headers = {
|
|
192
|
+
"x-ms-blob-content-encoding": "utf-8",
|
|
193
|
+
"x-ms-blob-content-md5": base64.b64encode(
|
|
194
|
+
get_md5_for_integrity(file_content)
|
|
195
|
+
).decode("utf-8"),
|
|
196
|
+
}
|
|
197
|
+
azure_metadata = self._prepare_file_metadata()
|
|
198
|
+
headers.update(azure_metadata)
|
|
199
|
+
retry_id = "COMPLETE"
|
|
200
|
+
self.retry_count[retry_id] = 0
|
|
201
|
+
r = await self._send_request_with_authentication_and_retry(
|
|
202
|
+
"PUT", url, "COMPLETE", headers=headers, data=ET.tostring(root)
|
|
203
|
+
)
|
|
204
|
+
r.raise_for_status() # expects status code 201
|
|
205
|
+
|
|
206
|
+
async def download_chunk(self, chunk_id: int) -> None:
|
|
207
|
+
container_name = quote(self.azure_location.container_name)
|
|
208
|
+
path = quote(self.azure_location.path + self.meta.src_file_name.lstrip("/"))
|
|
209
|
+
url = f"https://{self.storage_account}.blob.{self.endpoint}/{container_name}/{path}"
|
|
210
|
+
if self.num_of_chunks > 1:
|
|
211
|
+
chunk_size = self.chunk_size
|
|
212
|
+
if chunk_id < self.num_of_chunks - 1:
|
|
213
|
+
_range = f"{chunk_id * chunk_size}-{(chunk_id + 1) * chunk_size - 1}"
|
|
214
|
+
else:
|
|
215
|
+
_range = f"{chunk_id * chunk_size}-"
|
|
216
|
+
headers = {"Range": f"bytes={_range}"}
|
|
217
|
+
r = await self._send_request_with_authentication_and_retry(
|
|
218
|
+
"GET", url, chunk_id, headers=headers
|
|
219
|
+
) # expect 206
|
|
220
|
+
else:
|
|
221
|
+
# single request
|
|
222
|
+
r = await self._send_request_with_authentication_and_retry(
|
|
223
|
+
"GET", url, chunk_id
|
|
224
|
+
)
|
|
225
|
+
if r.status in (200, 206):
|
|
226
|
+
self.write_downloaded_chunk(chunk_id, await r.read())
|
|
227
|
+
r.raise_for_status()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
from io import BytesIO
|
|
8
|
+
from logging import getLogger
|
|
9
|
+
from typing import TYPE_CHECKING, cast
|
|
10
|
+
|
|
11
|
+
from snowflake.connector import Error
|
|
12
|
+
from snowflake.connector._utils import get_temp_type_for_object
|
|
13
|
+
from snowflake.connector.bind_upload_agent import BindUploadAgent as BindUploadAgentSync
|
|
14
|
+
from snowflake.connector.errors import BindUploadError
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from snowflake.connector.aio import SnowflakeCursor
|
|
18
|
+
|
|
19
|
+
logger = getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BindUploadAgent(BindUploadAgentSync):
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
cursor: SnowflakeCursor,
|
|
26
|
+
rows: list[bytes],
|
|
27
|
+
stream_buffer_size: int = 1024 * 1024 * 10,
|
|
28
|
+
) -> None:
|
|
29
|
+
super().__init__(cursor, rows, stream_buffer_size)
|
|
30
|
+
self.cursor = cast("SnowflakeCursor", cursor)
|
|
31
|
+
|
|
32
|
+
async def _create_stage(self) -> None:
|
|
33
|
+
create_stage_sql = (
|
|
34
|
+
f"create or replace {get_temp_type_for_object(self._use_scoped_temp_object)} stage {self._STAGE_NAME} "
|
|
35
|
+
"file_format=(type=csv field_optionally_enclosed_by='\"')"
|
|
36
|
+
)
|
|
37
|
+
await self.cursor.execute(create_stage_sql)
|
|
38
|
+
|
|
39
|
+
async def upload(self) -> None:
|
|
40
|
+
try:
|
|
41
|
+
await self._create_stage()
|
|
42
|
+
except Error as err:
|
|
43
|
+
self.cursor.connection._session_parameters[
|
|
44
|
+
"CLIENT_STAGE_ARRAY_BINDING_THRESHOLD"
|
|
45
|
+
] = 0
|
|
46
|
+
logger.debug("Failed to create stage for binding.")
|
|
47
|
+
raise BindUploadError from err
|
|
48
|
+
|
|
49
|
+
row_idx = 0
|
|
50
|
+
while row_idx < len(self.rows):
|
|
51
|
+
f = BytesIO()
|
|
52
|
+
size = 0
|
|
53
|
+
while True:
|
|
54
|
+
f.write(self.rows[row_idx])
|
|
55
|
+
size += len(self.rows[row_idx])
|
|
56
|
+
row_idx += 1
|
|
57
|
+
if row_idx >= len(self.rows) or size >= self._stream_buffer_size:
|
|
58
|
+
break
|
|
59
|
+
try:
|
|
60
|
+
f.seek(0)
|
|
61
|
+
await self.cursor._upload_stream(
|
|
62
|
+
input_stream=f,
|
|
63
|
+
stage_location=os.path.join(self.stage_path, f"{row_idx}.csv"),
|
|
64
|
+
options={"source_compression": "auto_detect"},
|
|
65
|
+
)
|
|
66
|
+
except Error as err:
|
|
67
|
+
logger.debug("Failed to upload the bindings file to stage.")
|
|
68
|
+
raise BindUploadError from err
|
|
69
|
+
f.close()
|