snowflake-connector-python 4.4.0__tar.gz → 4.5.0__tar.gz
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_python-4.4.0 → snowflake_connector_python-4.5.0}/CONTRIBUTING.md +1 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/DESCRIPTION.md +19 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/PKG-INFO +20 -2
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/_utils.py +37 -15
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_connection.py +2 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_cursor.py +3 -4
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_network.py +39 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_pandas_tools.py +1 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_wif_util.py +76 -8
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/_auth.py +2 -2
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/keypair.py +41 -11
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/okta.py +3 -3
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/compat.py +2 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/config_manager.py +9 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/connection.py +38 -14
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/cursor.py +4 -8
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/network.py +44 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/ocsp_snowflake.py +14 -40
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/pandas_tools.py +1 -1
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/platform_detection.py +17 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/token_cache.py +42 -12
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/util_text.py +90 -0
- snowflake_connector_python-4.5.0/src/snowflake/connector/version.py +3 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/wif_util.py +116 -30
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/PKG-INFO +20 -2
- snowflake_connector_python-4.4.0/src/snowflake/connector/version.py +0 -3
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/LICENSE.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/MANIFEST.in +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/NOTICE +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/README.md +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/SECURITY.md +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/pyproject.toml +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/setup.cfg +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/setup.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/_query_context_cache.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/_sql_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/README.md +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_azure_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_bind_upload_agent.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_description.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_direct_file_operation_utils.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_file_transfer_agent.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_gcs_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_ocsp_asn1crypto.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_ocsp_snowflake.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_result_batch.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_result_set.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_s3_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_session_manager.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_telemetry.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/_time_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_auth.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_by_plugin.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_default.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_idtoken.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_keypair.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_no_auth.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_oauth.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_oauth_code.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_oauth_credentials.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_okta.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_pat.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_usrpwdmfa.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_webbrowser.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/aio/auth/_workload_identity.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/arrow_context.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/_http_server.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/_oauth_base.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/by_plugin.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/default.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/idtoken.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/no_auth.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/oauth.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/oauth_code.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/oauth_credentials.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/pat.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/usrpwdmfa.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/webbrowser.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/auth/workload_identity.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/azure_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/backoff_policies.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/bind_upload_agent.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/cache.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/connection_diagnostic.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/constants.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/converter.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/converter_issue23517.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/converter_null.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/converter_snowsql.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/crl.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/crl_cache.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/dbapi.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/description.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/direct_file_operation_utils.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/encryption_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/errorcode.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/errors.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/externals_utils/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/externals_utils/externals_setup.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/feature.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/file_compression_type.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/file_lock.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/file_transfer_agent.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/file_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/gcs_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/gzip_decoder.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/interval_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/local_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/log_configuration.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/logging_utils/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/logging_utils/filters.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/minicore/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/minicore/linux_x86_64_glibc/libsf_mini_core.so +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/ocsp_asn1crypto.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/options.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/os_details.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/proxy.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/py.typed +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/result_batch.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/result_set.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/s3_storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/secret_detector.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/session_manager.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/sf_dirs.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/sfbinaryformat.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/sfdatetime.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/snow_logging.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/sqlstate.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/ssd_internal_keys.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/ssl_wrap_socket.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/storage_client.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/telemetry.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/telemetry_oob.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/test_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/time_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/tool/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/tool/dump_certs.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/tool/dump_ocsp_response.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/tool/dump_ocsp_response_cache.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/tool/probe_connection.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/url_util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/LICENSE +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/__version__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/_internal_utils.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/adapters.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/api.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/auth.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/certs.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/compat.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/cookies.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/exceptions.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/help.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/hooks.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/models.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/packages.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/sessions.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/status_codes.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/structures.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/requests/utils.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/LICENSE.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/_base_connection.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/_collections.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/_request_methods.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/_version.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/connection.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/connectionpool.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/connection.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/emscripten_fetch_worker.js +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/fetch.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/request.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/response.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/contrib/socks.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/exceptions.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/fields.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/filepost.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/http2/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/http2/connection.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/http2/probe.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/poolmanager.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/py.typed +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/response.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/__init__.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/connection.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/proxy.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/request.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/response.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/retry.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/ssl_.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/ssltransport.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/timeout.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/url.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/util.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake/connector/vendored/urllib3/util/wait.py +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/SOURCES.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/dependency_links.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/entry_points.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/not-zip-safe +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/requires.txt +0 -0
- {snowflake_connector_python-4.4.0 → snowflake_connector_python-4.5.0}/src/snowflake_connector_python.egg-info/top_level.txt +0 -0
|
@@ -27,7 +27,7 @@ We require our contributors to sign a CLA, available at https://github.com/snowf
|
|
|
27
27
|
What is a development environment? It's a [virtualenv](https://virtualenv.pypa.io) that has all of necessary
|
|
28
28
|
dependencies installed with `snowflake-connector-python` installed as an editable package.
|
|
29
29
|
|
|
30
|
-
Setting up a development environment is super easy with this [one simple tox command](https://tox.wiki/en/
|
|
30
|
+
Setting up a development environment is super easy with this [one simple tox command](https://tox.wiki/en/legacy/example/devenv.html).
|
|
31
31
|
|
|
32
32
|
```shell
|
|
33
33
|
tox --devenv venv39 -e py39
|
|
@@ -7,7 +7,22 @@ https://docs.snowflake.com/
|
|
|
7
7
|
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
|
|
8
8
|
|
|
9
9
|
# Release Notes
|
|
10
|
-
- v4.
|
|
10
|
+
- v4.5.0(May 12,2026)
|
|
11
|
+
- Fixed `write_pandas` temp stage name collisions (SNOW-3481510). The old PRNG could produce identical name sequences in forked processes (e.g. Notebook kernels), causing `CREATE TEMPORARY STAGE` to fail with "Object already exists".
|
|
12
|
+
- Fixed a security bug in Okta SAML authentication where `_is_prefix_equal()` compared `url1`'s port against itself instead of `url2`'s port, allowing an attacker to redirect credentials to a different port on the same hostname. Also fixed the default port fallback to use `int` instead of `str` for correct comparison when one URL omits the port.
|
|
13
|
+
- Fixed `executemany` with `paramstyle="pyformat"` to correctly locate the VALUES clause using a balanced-parentheses parser instead of a greedy regex. This fixes incorrect behaviour with nested function calls such as SQLAlchemy `@compiles VARIANT` patterns (e.g. `PARSE_JSON(%(col)s)`) and subquery-form INSERTs (SNOW-298756).
|
|
14
|
+
- Added ECDSA key support (ES256, ES384, ES512) for key-pair authentication.
|
|
15
|
+
- Added HTTP 307/308 redirect status codes to the retryable set as defense-in-depth, with redirect-aware logging in both sync and async paths.
|
|
16
|
+
- Consolidated keyring token cache to use a single service name with hashed account keys, reducing macOS Keychain password prompts. Legacy entries are auto-migrated on first read.
|
|
17
|
+
- Added support for AWS outbound JWT token attestation for Workload Identity Federation (WIF). This can be enabled by setting the `SNOWFLAKE_ENABLE_AWS_WIF_OUTBOUND_TOKEN` environment variable to `true`. Note: This environment variable will be removed in a future release.
|
|
18
|
+
- Removed dynamic class deserialization from the OCSP response validation cache to prevent arbitrary code execution via crafted cache files (SNOW-2439940). The `SNOWFLAKE_ENABLE_CUSTOM_REVOCATION_ERRORS` environment variable is now a no-op.
|
|
19
|
+
- Updated SPCS token injection to gate on `SNOWFLAKE_RUNNING_INSIDE_SPCS` environment variable, trim whitespace, and remove configurable token path.
|
|
20
|
+
- GCP WIF attestation now uses hostname `metadata.google.internal` instead of the IPv4 link-local address, so it works on IPv6-only GCP VMs.
|
|
21
|
+
- Fixed a bug where `write_pandas()` with `auto_create_table=False` and `overwrite=True` would execute `CREATE TABLE IF NOT EXISTS`, which required unnecessary `OWNERSHIP` privilege on the table. Now only `TRUNCATE TABLE` is executed in this case. Note: users who relied on the table being implicitly created despite `auto_create_table=False` should set `auto_create_table=True` instead.
|
|
22
|
+
- Added validation of the `account` connection parameter so malformed identifiers (for example path-like values or labels outside letters, digits, `_`, and `-`) are rejected with `ProgrammingError` before login (SNOW-1902886).
|
|
23
|
+
- Added support for Azure Workload Identity Federation impersonation, allowing a managed identity to authenticate as a service principal.
|
|
24
|
+
|
|
25
|
+
- v4.4.0(March 25,2026)
|
|
11
26
|
- Bump the lower boundary of cryptography to 46.0.5 due to CVE-2026-26007.
|
|
12
27
|
- Added support for Python 3.14.
|
|
13
28
|
- Removed pyOpenSSL upper bound dependency constraint to allow installation of pyOpenSSL 26.0.0+, which includes a fix for GHSA-vp96-hxj8-p424.
|
|
@@ -17,6 +32,8 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
|
|
|
17
32
|
- Renamed the environment variable for skipping config file permission warnings from `SF_SKIP_WARNING_FOR_READ_PERMISSIONS_ON_CONFIG_FILE` to `SF_SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION`. The old variable is still supported but emits a deprecation warning.
|
|
18
33
|
- Fixed `unsafe_skip_file_permissions_check` flag not being respected when reading `connections.toml`.
|
|
19
34
|
- Fixed JSONDecodeError in result_batch._load() when fetching large result sets
|
|
35
|
+
- Fixed validation ordering for `client_session_keep_alive_heartbeat_frequency`.
|
|
36
|
+
|
|
20
37
|
|
|
21
38
|
- v4.3.0(February 12,2026)
|
|
22
39
|
- Ensured proper list conversion - the converter runs to_snowflake on all list elements.
|
|
@@ -72,6 +89,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
|
|
|
72
89
|
|
|
73
90
|
- v3.18.0(October 03,2025)
|
|
74
91
|
- Added support for pandas conversion for Day-time and Year-Month Interval types
|
|
92
|
+
* Fixed the return type of iterating over a cursor
|
|
75
93
|
|
|
76
94
|
- v3.17.4(September 22,2025)
|
|
77
95
|
- Added support for intermediate certificates as roots when they are stored in the trust store
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-connector-python
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.0
|
|
4
4
|
Summary: Snowflake Connector for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -94,7 +94,22 @@ https://docs.snowflake.com/
|
|
|
94
94
|
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
|
|
95
95
|
|
|
96
96
|
# Release Notes
|
|
97
|
-
- v4.
|
|
97
|
+
- v4.5.0(May 12,2026)
|
|
98
|
+
- Fixed `write_pandas` temp stage name collisions (SNOW-3481510). The old PRNG could produce identical name sequences in forked processes (e.g. Notebook kernels), causing `CREATE TEMPORARY STAGE` to fail with "Object already exists".
|
|
99
|
+
- Fixed a security bug in Okta SAML authentication where `_is_prefix_equal()` compared `url1`'s port against itself instead of `url2`'s port, allowing an attacker to redirect credentials to a different port on the same hostname. Also fixed the default port fallback to use `int` instead of `str` for correct comparison when one URL omits the port.
|
|
100
|
+
- Fixed `executemany` with `paramstyle="pyformat"` to correctly locate the VALUES clause using a balanced-parentheses parser instead of a greedy regex. This fixes incorrect behaviour with nested function calls such as SQLAlchemy `@compiles VARIANT` patterns (e.g. `PARSE_JSON(%(col)s)`) and subquery-form INSERTs (SNOW-298756).
|
|
101
|
+
- Added ECDSA key support (ES256, ES384, ES512) for key-pair authentication.
|
|
102
|
+
- Added HTTP 307/308 redirect status codes to the retryable set as defense-in-depth, with redirect-aware logging in both sync and async paths.
|
|
103
|
+
- Consolidated keyring token cache to use a single service name with hashed account keys, reducing macOS Keychain password prompts. Legacy entries are auto-migrated on first read.
|
|
104
|
+
- Added support for AWS outbound JWT token attestation for Workload Identity Federation (WIF). This can be enabled by setting the `SNOWFLAKE_ENABLE_AWS_WIF_OUTBOUND_TOKEN` environment variable to `true`. Note: This environment variable will be removed in a future release.
|
|
105
|
+
- Removed dynamic class deserialization from the OCSP response validation cache to prevent arbitrary code execution via crafted cache files (SNOW-2439940). The `SNOWFLAKE_ENABLE_CUSTOM_REVOCATION_ERRORS` environment variable is now a no-op.
|
|
106
|
+
- Updated SPCS token injection to gate on `SNOWFLAKE_RUNNING_INSIDE_SPCS` environment variable, trim whitespace, and remove configurable token path.
|
|
107
|
+
- GCP WIF attestation now uses hostname `metadata.google.internal` instead of the IPv4 link-local address, so it works on IPv6-only GCP VMs.
|
|
108
|
+
- Fixed a bug where `write_pandas()` with `auto_create_table=False` and `overwrite=True` would execute `CREATE TABLE IF NOT EXISTS`, which required unnecessary `OWNERSHIP` privilege on the table. Now only `TRUNCATE TABLE` is executed in this case. Note: users who relied on the table being implicitly created despite `auto_create_table=False` should set `auto_create_table=True` instead.
|
|
109
|
+
- Added validation of the `account` connection parameter so malformed identifiers (for example path-like values or labels outside letters, digits, `_`, and `-`) are rejected with `ProgrammingError` before login (SNOW-1902886).
|
|
110
|
+
- Added support for Azure Workload Identity Federation impersonation, allowing a managed identity to authenticate as a service principal.
|
|
111
|
+
|
|
112
|
+
- v4.4.0(March 25,2026)
|
|
98
113
|
- Bump the lower boundary of cryptography to 46.0.5 due to CVE-2026-26007.
|
|
99
114
|
- Added support for Python 3.14.
|
|
100
115
|
- Removed pyOpenSSL upper bound dependency constraint to allow installation of pyOpenSSL 26.0.0+, which includes a fix for GHSA-vp96-hxj8-p424.
|
|
@@ -104,6 +119,8 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
|
|
|
104
119
|
- Renamed the environment variable for skipping config file permission warnings from `SF_SKIP_WARNING_FOR_READ_PERMISSIONS_ON_CONFIG_FILE` to `SF_SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION`. The old variable is still supported but emits a deprecation warning.
|
|
105
120
|
- Fixed `unsafe_skip_file_permissions_check` flag not being respected when reading `connections.toml`.
|
|
106
121
|
- Fixed JSONDecodeError in result_batch._load() when fetching large result sets
|
|
122
|
+
- Fixed validation ordering for `client_session_keep_alive_heartbeat_frequency`.
|
|
123
|
+
|
|
107
124
|
|
|
108
125
|
- v4.3.0(February 12,2026)
|
|
109
126
|
- Ensured proper list conversion - the converter runs to_snowflake on all list elements.
|
|
@@ -159,6 +176,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
|
|
|
159
176
|
|
|
160
177
|
- v3.18.0(October 03,2025)
|
|
161
178
|
- Added support for pandas conversion for Day-time and Year-Month Interval types
|
|
179
|
+
* Fixed the return type of iterating over a cursor
|
|
162
180
|
|
|
163
181
|
- v3.17.4(September 22,2025)
|
|
164
182
|
- Added support for intermediate certificates as roots when they are stored in the trust store
|
|
@@ -10,7 +10,7 @@ import threading
|
|
|
10
10
|
import time
|
|
11
11
|
from enum import Enum
|
|
12
12
|
from inspect import stack
|
|
13
|
-
from
|
|
13
|
+
from secrets import choice
|
|
14
14
|
from threading import Timer
|
|
15
15
|
from uuid import UUID
|
|
16
16
|
|
|
@@ -109,30 +109,29 @@ def get_application_path() -> str:
|
|
|
109
109
|
return "unknown"
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
_SPCS_ENV_VAR = "SNOWFLAKE_RUNNING_INSIDE_SPCS"
|
|
113
|
+
_SPCS_TOKEN_PATH = "/snowflake/session/spcs_token"
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
def get_spcs_token() -> str | None:
|
|
117
|
-
"""Return the SPCS token
|
|
117
|
+
"""Return the SPCS token if running inside an SPCS container, or None.
|
|
118
118
|
|
|
119
|
-
The
|
|
120
|
-
|
|
119
|
+
The token is only read when the SNOWFLAKE_RUNNING_INSIDE_SPCS environment
|
|
120
|
+
variable is set. The file at /snowflake/session/spcs_token is read as
|
|
121
|
+
UTF-8 text and leading/trailing whitespace is stripped.
|
|
121
122
|
|
|
122
|
-
Any
|
|
123
|
-
will not cause authentication to fail.
|
|
123
|
+
Any read failure is logged as a warning and None is returned.
|
|
124
124
|
"""
|
|
125
|
-
|
|
125
|
+
if not os.environ.get(_SPCS_ENV_VAR):
|
|
126
|
+
return None
|
|
126
127
|
try:
|
|
127
|
-
|
|
128
|
-
return None
|
|
129
|
-
with open(path, encoding="utf-8") as f:
|
|
128
|
+
with open(_SPCS_TOKEN_PATH, encoding="utf-8") as f:
|
|
130
129
|
token = f.read().strip()
|
|
131
130
|
if not token:
|
|
132
131
|
return None
|
|
133
132
|
return token
|
|
134
|
-
except Exception as exc:
|
|
135
|
-
logger.
|
|
133
|
+
except Exception as exc:
|
|
134
|
+
logger.warning("Failed to read SPCS token from %s: %s", _SPCS_TOKEN_PATH, exc)
|
|
136
135
|
return None
|
|
137
136
|
|
|
138
137
|
|
|
@@ -184,14 +183,35 @@ class _CoreLoader:
|
|
|
184
183
|
else:
|
|
185
184
|
return "unknown"
|
|
186
185
|
|
|
186
|
+
@staticmethod
|
|
187
|
+
def _libc_ver() -> tuple[str, str]:
|
|
188
|
+
"""Return (libc_name, libc_version) from the platform."""
|
|
189
|
+
return platform.libc_ver()
|
|
190
|
+
|
|
187
191
|
@staticmethod
|
|
188
192
|
def _detect_libc() -> str:
|
|
189
193
|
"""Detect libc type on Linux (glibc vs musl)."""
|
|
190
|
-
lib, _ =
|
|
194
|
+
lib, _ = _CoreLoader._libc_ver()
|
|
191
195
|
if lib == "glibc":
|
|
192
196
|
return "glibc"
|
|
193
197
|
return "musl"
|
|
194
198
|
|
|
199
|
+
@staticmethod
|
|
200
|
+
def get_libc_version() -> str | None:
|
|
201
|
+
"""Return libc version from :func:`platform.libc_ver`, or None if unknown."""
|
|
202
|
+
_, version = _CoreLoader._libc_ver()
|
|
203
|
+
if not version:
|
|
204
|
+
return None
|
|
205
|
+
stripped = version.strip()
|
|
206
|
+
return stripped or None
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def get_libc_family() -> str | None:
|
|
210
|
+
"""Return libc family for Linux (glibc or musl), otherwise None."""
|
|
211
|
+
if _CoreLoader._detect_os() != "linux":
|
|
212
|
+
return None
|
|
213
|
+
return _CoreLoader._detect_libc()
|
|
214
|
+
|
|
195
215
|
@staticmethod
|
|
196
216
|
def _get_platform_subdir() -> str:
|
|
197
217
|
"""Get the platform-specific subdirectory name."""
|
|
@@ -330,6 +350,8 @@ def build_minicore_usage_for_session() -> dict[str, str | None]:
|
|
|
330
350
|
"ISA": ISA,
|
|
331
351
|
"CORE_VERSION": _core_loader.get_core_version(),
|
|
332
352
|
"CORE_FILE_NAME": _core_loader.get_file_name(),
|
|
353
|
+
"LIBC_FAMILY": _CoreLoader.get_libc_family(),
|
|
354
|
+
"LIBC_VERSION": _CoreLoader.get_libc_version(),
|
|
333
355
|
}
|
|
334
356
|
|
|
335
357
|
|
|
@@ -451,6 +451,7 @@ class SnowflakeConnection(SnowflakeConnectionSync):
|
|
|
451
451
|
not in (
|
|
452
452
|
AttestationProvider.GCP,
|
|
453
453
|
AttestationProvider.AWS,
|
|
454
|
+
AttestationProvider.AZURE,
|
|
454
455
|
)
|
|
455
456
|
):
|
|
456
457
|
Error.errorhandler_wrapper(
|
|
@@ -458,7 +459,7 @@ class SnowflakeConnection(SnowflakeConnectionSync):
|
|
|
458
459
|
None,
|
|
459
460
|
ProgrammingError,
|
|
460
461
|
{
|
|
461
|
-
"msg": "workload_identity_impersonation_path is currently only supported for GCP and
|
|
462
|
+
"msg": "workload_identity_impersonation_path is currently only supported for GCP, AWS, and AZURE.",
|
|
462
463
|
"errno": ER_INVALID_WIF_SETTINGS,
|
|
463
464
|
},
|
|
464
465
|
)
|
|
@@ -57,6 +57,7 @@ from snowflake.connector.errors import BindUploadError, DatabaseError
|
|
|
57
57
|
from snowflake.connector.file_transfer_agent import SnowflakeProgressPercentage
|
|
58
58
|
from snowflake.connector.telemetry import TelemetryData, TelemetryField
|
|
59
59
|
from snowflake.connector.time_util import get_time_millis
|
|
60
|
+
from snowflake.connector.util_text import extract_values_clause
|
|
60
61
|
|
|
61
62
|
from .._utils import REQUEST_ID_STATEMENT_PARAM_NAME, is_uuid4
|
|
62
63
|
|
|
@@ -765,8 +766,8 @@ class SnowflakeCursorBase(SnowflakeCursorBaseSync, abc.ABC, typing.Generic[Fetch
|
|
|
765
766
|
# accumulate results to mock the result from a single insert statement as formatted below
|
|
766
767
|
logger.debug("rewriting INSERT query")
|
|
767
768
|
command_wo_comments = re.sub(self.COMMENT_SQL_RE, "", command)
|
|
768
|
-
|
|
769
|
-
if
|
|
769
|
+
fmt = extract_values_clause(command_wo_comments)
|
|
770
|
+
if fmt is None:
|
|
770
771
|
Error.errorhandler_wrapper(
|
|
771
772
|
self.connection,
|
|
772
773
|
self,
|
|
@@ -776,8 +777,6 @@ class SnowflakeCursorBase(SnowflakeCursorBaseSync, abc.ABC, typing.Generic[Fetch
|
|
|
776
777
|
"errno": ER_FAILED_TO_REWRITE_MULTI_ROW_INSERT,
|
|
777
778
|
},
|
|
778
779
|
)
|
|
779
|
-
|
|
780
|
-
fmt = m.group(1)
|
|
781
780
|
values = []
|
|
782
781
|
for param in seqparams:
|
|
783
782
|
logger.debug(f"parameter: {param}")
|
|
@@ -11,7 +11,16 @@ from typing import TYPE_CHECKING, Any, AsyncGenerator
|
|
|
11
11
|
|
|
12
12
|
import OpenSSL.SSL
|
|
13
13
|
|
|
14
|
-
from ..compat import
|
|
14
|
+
from ..compat import (
|
|
15
|
+
FORBIDDEN,
|
|
16
|
+
OK,
|
|
17
|
+
PERMANENT_REDIRECT,
|
|
18
|
+
TEMPORARY_REDIRECT,
|
|
19
|
+
UNAUTHORIZED,
|
|
20
|
+
urlencode,
|
|
21
|
+
urlparse,
|
|
22
|
+
urlsplit,
|
|
23
|
+
)
|
|
15
24
|
from ..constants import (
|
|
16
25
|
_CONNECTIVITY_ERR_MSG,
|
|
17
26
|
HTTP_HEADER_ACCEPT,
|
|
@@ -741,6 +750,18 @@ class SnowflakeRestful(SnowflakeRestfulSync):
|
|
|
741
750
|
data=input_data,
|
|
742
751
|
timeout=aiohttp.ClientTimeout(socket_timeout),
|
|
743
752
|
)
|
|
753
|
+
|
|
754
|
+
# Log when the HTTP library auto-followed a redirect chain before
|
|
755
|
+
# delivering this response (history is populated by aiohttp).
|
|
756
|
+
if raw_ret.history:
|
|
757
|
+
for hist_resp in raw_ret.history:
|
|
758
|
+
if hist_resp.status in (TEMPORARY_REDIRECT, PERMANENT_REDIRECT):
|
|
759
|
+
logger.debug(
|
|
760
|
+
"Request was redirected: HTTP %d to %s",
|
|
761
|
+
hist_resp.status,
|
|
762
|
+
hist_resp.headers.get("Location", "unknown"),
|
|
763
|
+
)
|
|
764
|
+
|
|
744
765
|
try:
|
|
745
766
|
if raw_ret.status == OK:
|
|
746
767
|
logger.debug("SUCCESS")
|
|
@@ -841,6 +862,23 @@ class SnowflakeRestful(SnowflakeRestfulSync):
|
|
|
841
862
|
exc_info=True,
|
|
842
863
|
)
|
|
843
864
|
raise RetryRequest(err)
|
|
865
|
+
except aiohttp.TooManyRedirects as err:
|
|
866
|
+
# aiohttp raises TooManyRedirects when max_redirects is exceeded.
|
|
867
|
+
# Unlike .NET's HttpClient (which returns the last 307/308 response),
|
|
868
|
+
# aiohttp throws here — so is_retryable_http_code(307/308) never fires.
|
|
869
|
+
# Catch explicitly and apply the same retry/login logic.
|
|
870
|
+
if is_login_request(full_url):
|
|
871
|
+
raise OperationalError(
|
|
872
|
+
msg="Login request is retryable. Will be handled by authenticator",
|
|
873
|
+
errno=ER_RETRYABLE_CODE,
|
|
874
|
+
)
|
|
875
|
+
else:
|
|
876
|
+
logger.debug(
|
|
877
|
+
"Too many redirects. Retrying... Ignore the following "
|
|
878
|
+
f"error stack: {err}",
|
|
879
|
+
exc_info=True,
|
|
880
|
+
)
|
|
881
|
+
raise RetryRequest(err)
|
|
844
882
|
except Exception as err:
|
|
845
883
|
if isinstance(err, (Error, RetryRequest, ReauthenticationRequest)):
|
|
846
884
|
raise err
|
|
@@ -443,7 +443,7 @@ async def write_pandas(
|
|
|
443
443
|
quote_identifiers,
|
|
444
444
|
)
|
|
445
445
|
|
|
446
|
-
if auto_create_table
|
|
446
|
+
if auto_create_table:
|
|
447
447
|
iceberg = "ICEBERG " if iceberg_config else ""
|
|
448
448
|
iceberg_config_statement = _iceberg_config_statement_helper(
|
|
449
449
|
iceberg_config or {}
|
|
@@ -5,6 +5,8 @@ import logging
|
|
|
5
5
|
import os
|
|
6
6
|
from base64 import b64encode
|
|
7
7
|
|
|
8
|
+
import jwt
|
|
9
|
+
|
|
8
10
|
from snowflake.connector.options import (
|
|
9
11
|
aioboto3,
|
|
10
12
|
aiobotocore,
|
|
@@ -12,9 +14,10 @@ from snowflake.connector.options import (
|
|
|
12
14
|
installed_aioboto,
|
|
13
15
|
)
|
|
14
16
|
|
|
15
|
-
from ..errorcode import ER_WIF_CREDENTIALS_NOT_FOUND
|
|
17
|
+
from ..errorcode import ER_INVALID_WIF_SETTINGS, ER_WIF_CREDENTIALS_NOT_FOUND
|
|
16
18
|
from ..errors import MissingDependencyError, ProgrammingError
|
|
17
19
|
from ..wif_util import (
|
|
20
|
+
AZURE_WIF_FEDERATION_AUDIENCE,
|
|
18
21
|
DEFAULT_ENTRA_SNOWFLAKE_RESOURCE,
|
|
19
22
|
SNOWFLAKE_AUDIENCE,
|
|
20
23
|
AttestationProvider,
|
|
@@ -27,9 +30,7 @@ from ._session_manager import SessionManager, SessionManagerFactory
|
|
|
27
30
|
|
|
28
31
|
logger = logging.getLogger(__name__)
|
|
29
32
|
|
|
30
|
-
GCP_METADATA_SERVICE_ACCOUNT_BASE_URL =
|
|
31
|
-
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default"
|
|
32
|
-
)
|
|
33
|
+
GCP_METADATA_SERVICE_ACCOUNT_BASE_URL = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default"
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
async def get_aws_region() -> str:
|
|
@@ -227,17 +228,75 @@ async def create_gcp_attestation(
|
|
|
227
228
|
)
|
|
228
229
|
|
|
229
230
|
|
|
231
|
+
async def get_azure_sp_token_via_impersonation(
|
|
232
|
+
mi_token: str,
|
|
233
|
+
sp_client_id: str,
|
|
234
|
+
snowflake_entra_resource: str,
|
|
235
|
+
session_manager: SessionManager,
|
|
236
|
+
) -> str:
|
|
237
|
+
"""Exchanges a managed identity token for a service principal token via the Entra ID token endpoint."""
|
|
238
|
+
# Azure requires the MI and the app registration to be in the same tenant, so the
|
|
239
|
+
# tid claim from the MI token is always the correct tenant for the token exchange endpoint.
|
|
240
|
+
tenant_id = jwt.decode(mi_token, options={"verify_signature": False}).get("tid")
|
|
241
|
+
if not tenant_id:
|
|
242
|
+
raise ProgrammingError(
|
|
243
|
+
msg="MI token is missing 'tid' claim; cannot determine tenant ID for impersonation.",
|
|
244
|
+
errno=ER_WIF_CREDENTIALS_NOT_FOUND,
|
|
245
|
+
)
|
|
246
|
+
response_text = None
|
|
247
|
+
try:
|
|
248
|
+
res = await session_manager.post(
|
|
249
|
+
url=f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token",
|
|
250
|
+
data={
|
|
251
|
+
"grant_type": "client_credentials",
|
|
252
|
+
"client_id": sp_client_id,
|
|
253
|
+
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
|
254
|
+
"client_assertion": mi_token,
|
|
255
|
+
"scope": f"{snowflake_entra_resource}/.default",
|
|
256
|
+
},
|
|
257
|
+
)
|
|
258
|
+
content = await res.content.read()
|
|
259
|
+
response_text = content.decode("utf-8")
|
|
260
|
+
response_data = json.loads(response_text)
|
|
261
|
+
res.raise_for_status()
|
|
262
|
+
except Exception as e:
|
|
263
|
+
raise ProgrammingError(
|
|
264
|
+
msg=f"Error fetching SP token for Azure client_id '{sp_client_id}': {e}. Response: {response_text}",
|
|
265
|
+
errno=ER_WIF_CREDENTIALS_NOT_FOUND,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
sp_token = response_data.get("access_token")
|
|
269
|
+
if not sp_token:
|
|
270
|
+
raise ProgrammingError(
|
|
271
|
+
msg=f"No access token found in Entra ID response for client_id '{sp_client_id}'.",
|
|
272
|
+
errno=ER_WIF_CREDENTIALS_NOT_FOUND,
|
|
273
|
+
)
|
|
274
|
+
return sp_token
|
|
275
|
+
|
|
276
|
+
|
|
230
277
|
async def create_azure_attestation(
|
|
231
278
|
snowflake_entra_resource: str,
|
|
232
279
|
session_manager: SessionManager | None = None,
|
|
280
|
+
impersonation_path: list[str] | None = None,
|
|
233
281
|
) -> WorkloadIdentityAttestation:
|
|
234
282
|
"""Tries to create a workload identity attestation for Azure.
|
|
235
283
|
|
|
236
284
|
If the application isn't running on Azure or no credentials were found, raises an error.
|
|
237
285
|
"""
|
|
286
|
+
if impersonation_path:
|
|
287
|
+
if len(impersonation_path) != 1:
|
|
288
|
+
raise ProgrammingError(
|
|
289
|
+
msg="Azure WIF impersonation only supports a single service principal (single-hop). impersonation_path must contain exactly one client_id.",
|
|
290
|
+
errno=ER_INVALID_WIF_SETTINGS,
|
|
291
|
+
)
|
|
292
|
+
resource = (
|
|
293
|
+
AZURE_WIF_FEDERATION_AUDIENCE
|
|
294
|
+
if impersonation_path
|
|
295
|
+
else snowflake_entra_resource
|
|
296
|
+
)
|
|
238
297
|
headers = {"Metadata": "true"}
|
|
239
298
|
url_without_query_string = "http://169.254.169.254/metadata/identity/oauth2/token"
|
|
240
|
-
query_params = f"api-version=2018-02-01&resource={
|
|
299
|
+
query_params = f"api-version=2018-02-01&resource={resource}"
|
|
241
300
|
|
|
242
301
|
# Check if running in Azure Functions environment
|
|
243
302
|
identity_endpoint = os.environ.get("IDENTITY_ENDPOINT")
|
|
@@ -254,7 +313,7 @@ async def create_azure_attestation(
|
|
|
254
313
|
# Azure Functions uses a different endpoint, headers and API version.
|
|
255
314
|
url_without_query_string = identity_endpoint
|
|
256
315
|
headers = {"X-IDENTITY-HEADER": identity_header}
|
|
257
|
-
query_params = f"api-version=2019-08-01&resource={
|
|
316
|
+
query_params = f"api-version=2019-08-01&resource={resource}"
|
|
258
317
|
|
|
259
318
|
# Allow configuring an explicit client ID, which may be used in Azure Functions,
|
|
260
319
|
# if there are user-assigned identities, or multiple managed identities available.
|
|
@@ -262,6 +321,7 @@ async def create_azure_attestation(
|
|
|
262
321
|
if managed_identity_client_id:
|
|
263
322
|
query_params += f"&client_id={managed_identity_client_id}"
|
|
264
323
|
|
|
324
|
+
response_text = None
|
|
265
325
|
try:
|
|
266
326
|
res = await session_manager.request(
|
|
267
327
|
method="GET",
|
|
@@ -272,9 +332,10 @@ async def create_azure_attestation(
|
|
|
272
332
|
content = await res.content.read()
|
|
273
333
|
response_text = content.decode("utf-8")
|
|
274
334
|
response_data = json.loads(response_text)
|
|
335
|
+
res.raise_for_status()
|
|
275
336
|
except Exception as e:
|
|
276
337
|
raise ProgrammingError(
|
|
277
|
-
msg=f"Error fetching Azure metadata: {e}. Ensure the application is running on Azure.",
|
|
338
|
+
msg=f"Error fetching Azure metadata: {e}. Response: {response_text}. Ensure the application is running on Azure.",
|
|
278
339
|
errno=ER_WIF_CREDENTIALS_NOT_FOUND,
|
|
279
340
|
)
|
|
280
341
|
|
|
@@ -285,6 +346,11 @@ async def create_azure_attestation(
|
|
|
285
346
|
errno=ER_WIF_CREDENTIALS_NOT_FOUND,
|
|
286
347
|
)
|
|
287
348
|
|
|
349
|
+
if impersonation_path:
|
|
350
|
+
jwt_str = await get_azure_sp_token_via_impersonation(
|
|
351
|
+
jwt_str, impersonation_path[0], snowflake_entra_resource, session_manager
|
|
352
|
+
)
|
|
353
|
+
|
|
288
354
|
issuer, subject = extract_iss_and_sub_without_signature_verification(jwt_str)
|
|
289
355
|
return WorkloadIdentityAttestation(
|
|
290
356
|
AttestationProvider.AZURE, jwt_str, {"iss": issuer, "sub": subject}
|
|
@@ -312,7 +378,9 @@ async def create_attestation(
|
|
|
312
378
|
if provider == AttestationProvider.AWS:
|
|
313
379
|
return await create_aws_attestation(impersonation_path)
|
|
314
380
|
elif provider == AttestationProvider.AZURE:
|
|
315
|
-
return await create_azure_attestation(
|
|
381
|
+
return await create_azure_attestation(
|
|
382
|
+
entra_resource, session_manager, impersonation_path
|
|
383
|
+
)
|
|
316
384
|
elif provider == AttestationProvider.GCP:
|
|
317
385
|
return await create_gcp_attestation(session_manager, impersonation_path)
|
|
318
386
|
elif provider == AttestationProvider.OIDC:
|
|
@@ -105,8 +105,8 @@ class Auth:
|
|
|
105
105
|
def _add_spcs_token_to_body(self, body: dict[Any, Any]) -> None:
|
|
106
106
|
"""Inject SPCS_TOKEN into the login request body when available.
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
The token is read from /snowflake/session/spcs_token when
|
|
109
|
+
SNOWFLAKE_RUNNING_INSIDE_SPCS is set.
|
|
110
110
|
"""
|
|
111
111
|
spcs_token = get_spcs_token()
|
|
112
112
|
if spcs_token is not None:
|
|
@@ -10,6 +10,12 @@ from typing import Any
|
|
|
10
10
|
|
|
11
11
|
import jwt
|
|
12
12
|
from cryptography.hazmat.backends import default_backend
|
|
13
|
+
from cryptography.hazmat.primitives.asymmetric.ec import (
|
|
14
|
+
SECP256R1,
|
|
15
|
+
SECP384R1,
|
|
16
|
+
SECP521R1,
|
|
17
|
+
EllipticCurvePrivateKey,
|
|
18
|
+
)
|
|
13
19
|
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
|
|
14
20
|
from cryptography.hazmat.primitives.serialization import (
|
|
15
21
|
Encoding,
|
|
@@ -28,7 +34,12 @@ logger = getLogger(__name__)
|
|
|
28
34
|
class AuthByKeyPair(AuthByPlugin):
|
|
29
35
|
"""Key pair based authentication."""
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
ALG_RS256 = "RS256"
|
|
38
|
+
ALG_ES256 = "ES256"
|
|
39
|
+
ALG_ES384 = "ES384"
|
|
40
|
+
ALG_ES512 = "ES512"
|
|
41
|
+
ALGORITHM = ALG_RS256 # deprecated, kept for backward compatibility
|
|
42
|
+
|
|
32
43
|
ISSUER = "iss"
|
|
33
44
|
SUBJECT = "sub"
|
|
34
45
|
EXPIRE_TIME = "exp"
|
|
@@ -39,7 +50,7 @@ class AuthByKeyPair(AuthByPlugin):
|
|
|
39
50
|
|
|
40
51
|
def __init__(
|
|
41
52
|
self,
|
|
42
|
-
private_key: bytes | str | RSAPrivateKey,
|
|
53
|
+
private_key: bytes | str | RSAPrivateKey | EllipticCurvePrivateKey,
|
|
43
54
|
private_key_passphrase: bytes | None = None,
|
|
44
55
|
lifetime_in_seconds: int = LIFETIME,
|
|
45
56
|
**kwargs,
|
|
@@ -48,7 +59,7 @@ class AuthByKeyPair(AuthByPlugin):
|
|
|
48
59
|
|
|
49
60
|
Args:
|
|
50
61
|
private_key: a byte array of der formats of private key, or an
|
|
51
|
-
object that implements the `RSAPrivateKey` interface.
|
|
62
|
+
object that implements the `RSAPrivateKey` or `EllipticCurvePrivateKey` interface.
|
|
52
63
|
lifetime_in_seconds: number of seconds the JWT token will be valid
|
|
53
64
|
"""
|
|
54
65
|
super().__init__(
|
|
@@ -72,7 +83,9 @@ class AuthByKeyPair(AuthByPlugin):
|
|
|
72
83
|
).total_seconds()
|
|
73
84
|
)
|
|
74
85
|
|
|
75
|
-
self._private_key:
|
|
86
|
+
self._private_key: (
|
|
87
|
+
bytes | str | RSAPrivateKey | EllipticCurvePrivateKey | None
|
|
88
|
+
) = private_key
|
|
76
89
|
self._private_key_passphrase: bytes | None = private_key_passphrase
|
|
77
90
|
self._jwt_token = ""
|
|
78
91
|
self._jwt_token_exp = 0
|
|
@@ -109,7 +122,7 @@ class AuthByKeyPair(AuthByPlugin):
|
|
|
109
122
|
except Exception as e:
|
|
110
123
|
raise ProgrammingError(
|
|
111
124
|
msg=f"Failed to decode private key: {e}\nPlease provide a valid "
|
|
112
|
-
"unencrypted
|
|
125
|
+
"unencrypted RSA or ECDSA private key in base64-encoded DER format as a "
|
|
113
126
|
"str object",
|
|
114
127
|
errno=ER_INVALID_PRIVATE_KEY,
|
|
115
128
|
)
|
|
@@ -124,23 +137,23 @@ class AuthByKeyPair(AuthByPlugin):
|
|
|
124
137
|
except Exception as e:
|
|
125
138
|
raise ProgrammingError(
|
|
126
139
|
msg=f"Failed to load private key: {e}\nPlease provide a valid "
|
|
127
|
-
"
|
|
140
|
+
"RSA or ECDSA private key in DER format as bytes object. If the key is "
|
|
128
141
|
"encrypted, provide the passphrase via private_key_passphrase",
|
|
129
142
|
errno=ER_INVALID_PRIVATE_KEY,
|
|
130
143
|
)
|
|
131
144
|
|
|
132
|
-
if not isinstance(private_key, RSAPrivateKey):
|
|
145
|
+
if not isinstance(private_key, (RSAPrivateKey, EllipticCurvePrivateKey)):
|
|
133
146
|
raise ProgrammingError(
|
|
134
147
|
msg=f"Private key type ({private_key.__class__.__name__}) not supported."
|
|
135
|
-
"\nPlease provide a valid
|
|
148
|
+
"\nPlease provide a valid RSA or ECDSA private key in DER format as bytes "
|
|
136
149
|
"object",
|
|
137
150
|
errno=ER_INVALID_PRIVATE_KEY,
|
|
138
151
|
)
|
|
139
|
-
elif isinstance(self._private_key, RSAPrivateKey):
|
|
152
|
+
elif isinstance(self._private_key, (RSAPrivateKey, EllipticCurvePrivateKey)):
|
|
140
153
|
private_key = self._private_key
|
|
141
154
|
else:
|
|
142
155
|
raise TypeError(
|
|
143
|
-
f"Expected bytes or
|
|
156
|
+
f"Expected bytes, RSAPrivateKey, or EllipticCurvePrivateKey, got {type(self._private_key)}"
|
|
144
157
|
)
|
|
145
158
|
|
|
146
159
|
public_key_fp = self.calculate_public_key_fingerprint(private_key)
|
|
@@ -153,7 +166,24 @@ class AuthByKeyPair(AuthByPlugin):
|
|
|
153
166
|
self.EXPIRE_TIME: self._jwt_token_exp,
|
|
154
167
|
}
|
|
155
168
|
|
|
156
|
-
|
|
169
|
+
# select algorithm based on key type and curve
|
|
170
|
+
if isinstance(private_key, EllipticCurvePrivateKey):
|
|
171
|
+
curve = private_key.curve
|
|
172
|
+
if isinstance(curve, SECP256R1):
|
|
173
|
+
algorithm = self.ALG_ES256
|
|
174
|
+
elif isinstance(curve, SECP384R1):
|
|
175
|
+
algorithm = self.ALG_ES384
|
|
176
|
+
elif isinstance(curve, SECP521R1):
|
|
177
|
+
algorithm = self.ALG_ES512
|
|
178
|
+
else:
|
|
179
|
+
raise ProgrammingError(
|
|
180
|
+
msg=f"Unsupported EC curve: {curve.name}. Supported: SECP256R1, SECP384R1, SECP521R1",
|
|
181
|
+
errno=ER_INVALID_PRIVATE_KEY,
|
|
182
|
+
)
|
|
183
|
+
else:
|
|
184
|
+
algorithm = self.ALG_RS256
|
|
185
|
+
|
|
186
|
+
_jwt_token = jwt.encode(payload, private_key, algorithm=algorithm)
|
|
157
187
|
|
|
158
188
|
# jwt.encode() returns bytes in pyjwt 1.x and a string
|
|
159
189
|
# in pyjwt 2.x
|
|
@@ -38,10 +38,10 @@ def _is_prefix_equal(url1, url2):
|
|
|
38
38
|
|
|
39
39
|
port1 = parsed_url1.port
|
|
40
40
|
if not port1 and parsed_url1.scheme == "https":
|
|
41
|
-
port1 =
|
|
42
|
-
port2 =
|
|
41
|
+
port1 = 443
|
|
42
|
+
port2 = parsed_url2.port
|
|
43
43
|
if not port2 and parsed_url2.scheme == "https":
|
|
44
|
-
port2 =
|
|
44
|
+
port2 = 443
|
|
45
45
|
|
|
46
46
|
return (
|
|
47
47
|
parsed_url1.hostname == parsed_url2.hostname
|
|
@@ -70,6 +70,8 @@ METHOD_NOT_ALLOWED = http.client.METHOD_NOT_ALLOWED
|
|
|
70
70
|
BAD_GATEWAY = http.client.BAD_GATEWAY
|
|
71
71
|
BAD_REQUEST = http.client.BAD_REQUEST
|
|
72
72
|
REQUEST_TIMEOUT = http.client.REQUEST_TIMEOUT
|
|
73
|
+
TEMPORARY_REDIRECT = http.client.TEMPORARY_REDIRECT # 307
|
|
74
|
+
PERMANENT_REDIRECT = http.client.PERMANENT_REDIRECT # type: ignore[attr-defined] # 308 — stubs lag runtime
|
|
73
75
|
TOO_MANY_REQUESTS = http.client.TOO_MANY_REQUESTS
|
|
74
76
|
SERVICE_UNAVAILABLE = http.client.SERVICE_UNAVAILABLE
|
|
75
77
|
GATEWAY_TIMEOUT = http.client.GATEWAY_TIMEOUT
|
|
@@ -29,7 +29,14 @@ LOGGER = logging.getLogger(__name__)
|
|
|
29
29
|
READABLE_BY_OTHERS = stat.S_IRGRP | stat.S_IROTH
|
|
30
30
|
WRITABLE_BY_OTHERS = stat.S_IWGRP | stat.S_IWOTH
|
|
31
31
|
|
|
32
|
+
# NOTE: For historical and compatibility reasons, three environment variables are recognized:
|
|
33
|
+
# - The skip warning mechanism was originally for internal use (only within SPCS containers).
|
|
34
|
+
# - SPCS containers set SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION.
|
|
35
|
+
# - SF_SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION is the documented/public way to disable the warning.
|
|
36
|
+
# - In the Universal driver, this warning will become unskippable and the message will clarify:
|
|
37
|
+
# "SNOWFLAKE_RUNNING_INSIDE_SPCS is detected, skipping permission checks."
|
|
32
38
|
DEPRECATED_SKIP_WARNING_ENV_VAR = "SF_SKIP_WARNING_FOR_READ_PERMISSIONS_ON_CONFIG_FILE"
|
|
39
|
+
SPCS_INJECTED_SKIP_WARNING_ENV_VAR = "SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION"
|
|
33
40
|
SKIP_WARNING_ENV_VAR = "SF_SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION"
|
|
34
41
|
|
|
35
42
|
|
|
@@ -37,6 +44,8 @@ def _should_skip_warning_for_read_permissions_on_config_file() -> bool:
|
|
|
37
44
|
"""Check if the warning should be skipped based on environment variable."""
|
|
38
45
|
if SKIP_WARNING_ENV_VAR in os.environ:
|
|
39
46
|
return os.getenv(SKIP_WARNING_ENV_VAR, "false").lower() == "true"
|
|
47
|
+
if SPCS_INJECTED_SKIP_WARNING_ENV_VAR in os.environ:
|
|
48
|
+
return os.getenv(SPCS_INJECTED_SKIP_WARNING_ENV_VAR, "false").lower() == "true"
|
|
40
49
|
# Else fallback to old value
|
|
41
50
|
if DEPRECATED_SKIP_WARNING_ENV_VAR in os.environ:
|
|
42
51
|
warn(
|