snowflake-connector-python 3.15.0__tar.gz → 3.17.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-3.15.0 → snowflake_connector_python-3.17.0}/DESCRIPTION.md +34 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/MANIFEST.in +1 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/PKG-INFO +37 -3
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/setup.cfg +2 -2
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/setup.py +1 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/_utils.py +28 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/arrow_context.py +43 -1
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/_auth.py +15 -1
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/_oauth_base.py +76 -6
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/by_plugin.py +2 -1
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/oauth_code.py +93 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/oauth_credentials.py +4 -5
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/okta.py +3 -2
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/pat.py +1 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/webbrowser.py +5 -3
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/workload_identity.py +10 -2
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/bind_upload_agent.py +6 -2
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/config_manager.py +5 -1
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/connection.py +143 -100
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/connection_diagnostic.py +35 -22
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/constants.py +14 -3
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/converter.py +23 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/cursor.py +23 -2
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/direct_file_operation_utils.py +31 -3
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/errorcode.py +3 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/errors.py +48 -17
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/file_transfer_agent.py +51 -10
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/gcs_storage_client.py +3 -1
- snowflake_connector_python-3.17.0/src/snowflake/connector/interval_util.py +17 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/log_configuration.py +6 -4
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +31 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +86 -46
- snowflake_connector_python-3.17.0/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +75 -0
- snowflake_connector_python-3.17.0/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +56 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +2 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +2 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/network.py +97 -140
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/ocsp_snowflake.py +21 -6
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/pandas_tools.py +64 -54
- snowflake_connector_python-3.17.0/src/snowflake/connector/platform_detection.py +451 -0
- snowflake_connector_python-3.17.0/src/snowflake/connector/proxy.py +28 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/result_batch.py +93 -12
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/result_set.py +40 -8
- snowflake_connector_python-3.17.0/src/snowflake/connector/session_manager.py +539 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/ssl_wrap_socket.py +50 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/storage_client.py +13 -7
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/telemetry.py +2 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/telemetry_oob.py +1 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/token_cache.py +43 -25
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/version.py +1 -1
- snowflake_connector_python-3.17.0/src/snowflake/connector/wif_util.py +321 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/PKG-INFO +37 -3
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/SOURCES.txt +5 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/requires.txt +2 -2
- snowflake_connector_python-3.15.0/src/snowflake/connector/proxy.py +0 -43
- snowflake_connector_python-3.15.0/src/snowflake/connector/wif_util.py +0 -327
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/CONTRIBUTING.md +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/LICENSE.txt +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/NOTICE +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/README.md +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/SECURITY.md +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/pyproject.toml +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/_query_context_cache.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/_sql_util.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/_http_server.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/default.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/idtoken.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/keypair.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/no_auth.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/oauth.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/auth/usrpwdmfa.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/azure_storage_client.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/backoff_policies.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/cache.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/compat.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/converter_issue23517.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/converter_null.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/converter_snowsql.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/dbapi.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/description.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/encryption_util.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/externals_utils/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/externals_utils/externals_setup.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/feature.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/file_compression_type.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/file_lock.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/file_util.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/gzip_decoder.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/local_storage_client.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/logging_utils/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/logging_utils/filters.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/ocsp_asn1crypto.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/options.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/py.typed +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/s3_storage_client.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/secret_detector.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/sf_dirs.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/sfbinaryformat.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/sfdatetime.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/snow_logging.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/sqlstate.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/ssd_internal_keys.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/test_util.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/time_util.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/tool/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/tool/dump_certs.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/tool/dump_ocsp_response.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/tool/dump_ocsp_response_cache.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/tool/probe_connection.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/url_util.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/util_text.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/LICENSE +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/__version__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/_internal_utils.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/adapters.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/api.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/auth.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/certs.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/compat.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/cookies.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/exceptions.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/help.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/hooks.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/models.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/sessions.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/status_codes.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/structures.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/requests/utils.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/LICENSE.txt +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/_collections.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/_version.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/connection.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/connectionpool.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/_appengine_environ.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/_securetransport/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/_securetransport/bindings.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/_securetransport/low_level.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/appengine.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/ntlmpool.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/securetransport.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/contrib/socks.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/exceptions.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/fields.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/filepost.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/packages/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/packages/backports/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/packages/backports/makefile.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/packages/backports/weakref_finalize.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/packages/six.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/poolmanager.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/request.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/response.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/__init__.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/connection.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/proxy.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/queue.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/request.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/response.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/retry.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/ssl_.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/ssltransport.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/timeout.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/url.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake/connector/vendored/urllib3/util/wait.py +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/dependency_links.txt +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/entry_points.txt +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/not-zip-safe +0 -0
- {snowflake_connector_python-3.15.0 → snowflake_connector_python-3.17.0}/src/snowflake_connector_python.egg-info/top_level.txt +0 -0
|
@@ -7,6 +7,40 @@ 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
|
+
- v3.17.0(August 16,2025)
|
|
11
|
+
- Added in-band HTTP exception telemetry.
|
|
12
|
+
- Added an `unsafe_skip_file_permissions_check` flag to skip file permission checks on the cache and configuration.
|
|
13
|
+
- Added `APPLICATION_PATH` within `CLIENT_ENVIRONMENT` to distinguish between multiple scripts using the Python Connector in the same environment.
|
|
14
|
+
- Added basic JSON support for Interval types.
|
|
15
|
+
- Added in-band OCSP exception telemetry.
|
|
16
|
+
- Added support for new authentication methods with Workload Identity Federation (WIF).
|
|
17
|
+
- Added the `WORKLOAD_IDENTITY` value for the authenticator type.
|
|
18
|
+
- Added the `workload_identity_provider` and `workload_identity_entra_resource` parameters.
|
|
19
|
+
- Added support for the `use_vectorized_scanner` parameter in the write_pandas function.
|
|
20
|
+
- Added support of proxy setup using connection parameters without emitting environment variables.
|
|
21
|
+
- Added populating of `type_code` in `ResultMetadata` for interval types.
|
|
22
|
+
- Introduced the `snowflake_version` property to the connection.
|
|
23
|
+
- Moved `OAUTH_TYPE` to `CLIENT_ENVIROMENT`.
|
|
24
|
+
- Relaxed the `pyarrow` version constrain; versions >= 19 can now be used.
|
|
25
|
+
- Disabled token caching for OAuth Client Credentials authentication.
|
|
26
|
+
- Fixed OAuth authenticator values.
|
|
27
|
+
- Fixed a bug where a PAT with an external session authenticator was used while `external_session_id` was not provided in `SnowflakeRestful.fetch`.
|
|
28
|
+
- Fixed the case-sensitivity of `Oauth` and `programmatic_access_token` authenticator values.
|
|
29
|
+
- Fixed unclear error messages for incorrect `authenticator` values.
|
|
30
|
+
- Fixed GCS staging by ensuring the endpoint has a scheme.
|
|
31
|
+
- Fixed a bug where time-zoned timestamps fetched as a `pandas.DataFrame` or `pyarrow.Table` would overflow due to unnecessary precision. A clear error will now be raised if an overflow cannot be prevented.
|
|
32
|
+
|
|
33
|
+
- v3.16.0(July 04,2025)
|
|
34
|
+
- Bumped numpy dependency from <2.1.0 to <=2.2.4.
|
|
35
|
+
- Added Windows support for Python 3.13.
|
|
36
|
+
- Added `bulk_upload_chunks` parameter to `write_pandas` function. Setting this parameter to True changes the behaviour of write_pandas function to first write all the data chunks to the local disk and then perform the wildcard upload of the chunks folder to the stage. In default behaviour the chunks are being saved, uploaded and deleted one by one.
|
|
37
|
+
- Added support for new authentication mechanism PAT with external session ID.
|
|
38
|
+
- Added `client_fetch_use_mp` parameter that enables multiprocessed fetching of result batches.
|
|
39
|
+
- Added basic arrow support for Interval types.
|
|
40
|
+
- Fixed `write_pandas` special characters usage in the location name.
|
|
41
|
+
- Fixed usage of `use_virtual_url` when building the location for gcs storage client.
|
|
42
|
+
- Added support for Snowflake OAuth for local applications.
|
|
43
|
+
|
|
10
44
|
- v3.15.0(Apr 29,2025)
|
|
11
45
|
- Bumped up min boto and botocore version to 1.24.
|
|
12
46
|
- OCSP: terminate certificates chain traversal if a trusted certificate already reached.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-connector-python
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.17.0
|
|
4
4
|
Summary: Snowflake Connector for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -61,7 +61,7 @@ Provides-Extra: development
|
|
|
61
61
|
Requires-Dist: Cython; extra == "development"
|
|
62
62
|
Requires-Dist: coverage; extra == "development"
|
|
63
63
|
Requires-Dist: more-itertools; extra == "development"
|
|
64
|
-
Requires-Dist: numpy
|
|
64
|
+
Requires-Dist: numpy<=2.2.4; extra == "development"
|
|
65
65
|
Requires-Dist: pendulum!=2.1.1; extra == "development"
|
|
66
66
|
Requires-Dist: pexpect; extra == "development"
|
|
67
67
|
Requires-Dist: pytest<7.5.0; extra == "development"
|
|
@@ -72,7 +72,7 @@ Requires-Dist: pytest-xdist; extra == "development"
|
|
|
72
72
|
Requires-Dist: pytzdata; extra == "development"
|
|
73
73
|
Provides-Extra: pandas
|
|
74
74
|
Requires-Dist: pandas<3.0.0,>=2.1.2; extra == "pandas"
|
|
75
|
-
Requires-Dist: pyarrow
|
|
75
|
+
Requires-Dist: pyarrow; extra == "pandas"
|
|
76
76
|
Provides-Extra: secure-local-storage
|
|
77
77
|
Requires-Dist: keyring<26.0.0,>=23.1.0; extra == "secure-local-storage"
|
|
78
78
|
Dynamic: license-file
|
|
@@ -86,6 +86,40 @@ https://docs.snowflake.com/
|
|
|
86
86
|
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
|
|
87
87
|
|
|
88
88
|
# Release Notes
|
|
89
|
+
- v3.17.0(August 16,2025)
|
|
90
|
+
- Added in-band HTTP exception telemetry.
|
|
91
|
+
- Added an `unsafe_skip_file_permissions_check` flag to skip file permission checks on the cache and configuration.
|
|
92
|
+
- Added `APPLICATION_PATH` within `CLIENT_ENVIRONMENT` to distinguish between multiple scripts using the Python Connector in the same environment.
|
|
93
|
+
- Added basic JSON support for Interval types.
|
|
94
|
+
- Added in-band OCSP exception telemetry.
|
|
95
|
+
- Added support for new authentication methods with Workload Identity Federation (WIF).
|
|
96
|
+
- Added the `WORKLOAD_IDENTITY` value for the authenticator type.
|
|
97
|
+
- Added the `workload_identity_provider` and `workload_identity_entra_resource` parameters.
|
|
98
|
+
- Added support for the `use_vectorized_scanner` parameter in the write_pandas function.
|
|
99
|
+
- Added support of proxy setup using connection parameters without emitting environment variables.
|
|
100
|
+
- Added populating of `type_code` in `ResultMetadata` for interval types.
|
|
101
|
+
- Introduced the `snowflake_version` property to the connection.
|
|
102
|
+
- Moved `OAUTH_TYPE` to `CLIENT_ENVIROMENT`.
|
|
103
|
+
- Relaxed the `pyarrow` version constrain; versions >= 19 can now be used.
|
|
104
|
+
- Disabled token caching for OAuth Client Credentials authentication.
|
|
105
|
+
- Fixed OAuth authenticator values.
|
|
106
|
+
- Fixed a bug where a PAT with an external session authenticator was used while `external_session_id` was not provided in `SnowflakeRestful.fetch`.
|
|
107
|
+
- Fixed the case-sensitivity of `Oauth` and `programmatic_access_token` authenticator values.
|
|
108
|
+
- Fixed unclear error messages for incorrect `authenticator` values.
|
|
109
|
+
- Fixed GCS staging by ensuring the endpoint has a scheme.
|
|
110
|
+
- Fixed a bug where time-zoned timestamps fetched as a `pandas.DataFrame` or `pyarrow.Table` would overflow due to unnecessary precision. A clear error will now be raised if an overflow cannot be prevented.
|
|
111
|
+
|
|
112
|
+
- v3.16.0(July 04,2025)
|
|
113
|
+
- Bumped numpy dependency from <2.1.0 to <=2.2.4.
|
|
114
|
+
- Added Windows support for Python 3.13.
|
|
115
|
+
- Added `bulk_upload_chunks` parameter to `write_pandas` function. Setting this parameter to True changes the behaviour of write_pandas function to first write all the data chunks to the local disk and then perform the wildcard upload of the chunks folder to the stage. In default behaviour the chunks are being saved, uploaded and deleted one by one.
|
|
116
|
+
- Added support for new authentication mechanism PAT with external session ID.
|
|
117
|
+
- Added `client_fetch_use_mp` parameter that enables multiprocessed fetching of result batches.
|
|
118
|
+
- Added basic arrow support for Interval types.
|
|
119
|
+
- Fixed `write_pandas` special characters usage in the location name.
|
|
120
|
+
- Fixed usage of `use_virtual_url` when building the location for gcs storage client.
|
|
121
|
+
- Added support for Snowflake OAuth for local applications.
|
|
122
|
+
|
|
89
123
|
- v3.15.0(Apr 29,2025)
|
|
90
124
|
- Bumped up min boto and botocore version to 1.24.
|
|
91
125
|
- OCSP: terminate certificates chain traversal if a trusted certificate already reached.
|
|
@@ -83,7 +83,7 @@ development =
|
|
|
83
83
|
Cython
|
|
84
84
|
coverage
|
|
85
85
|
more-itertools
|
|
86
|
-
numpy
|
|
86
|
+
numpy<=2.2.4
|
|
87
87
|
pendulum!=2.1.1
|
|
88
88
|
pexpect
|
|
89
89
|
pytest<7.5.0
|
|
@@ -94,7 +94,7 @@ development =
|
|
|
94
94
|
pytzdata
|
|
95
95
|
pandas =
|
|
96
96
|
pandas>=2.1.2,<3.0.0
|
|
97
|
-
pyarrow
|
|
97
|
+
pyarrow
|
|
98
98
|
secure-local-storage =
|
|
99
99
|
keyring>=23.1.0,<26.0.0
|
|
100
100
|
|
|
@@ -103,6 +103,7 @@ if _ABLE_TO_COMPILE_EXTENSIONS and not SNOWFLAKE_DISABLE_COMPILE_ARROW_EXTENSION
|
|
|
103
103
|
"FixedSizeListConverter.cpp",
|
|
104
104
|
"FloatConverter.cpp",
|
|
105
105
|
"IntConverter.cpp",
|
|
106
|
+
"IntervalConverter.cpp",
|
|
106
107
|
"MapConverter.cpp",
|
|
107
108
|
"ObjectConverter.cpp",
|
|
108
109
|
"SnowflakeType.cpp",
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import string
|
|
4
4
|
from enum import Enum
|
|
5
|
+
from inspect import stack
|
|
5
6
|
from random import choice
|
|
6
7
|
from threading import Timer
|
|
7
8
|
from uuid import UUID
|
|
@@ -32,6 +33,15 @@ _PYTHON_SNOWPARK_USE_SCOPED_TEMP_OBJECTS_STRING = (
|
|
|
32
33
|
|
|
33
34
|
REQUEST_ID_STATEMENT_PARAM_NAME = "requestId"
|
|
34
35
|
|
|
36
|
+
# Default server side cap on Degree of Parallelism for file transfer
|
|
37
|
+
# This default value is set to 2^30 (~ 10^9), such that it will not
|
|
38
|
+
# throttle regular sessions.
|
|
39
|
+
_DEFAULT_VALUE_SERVER_DOP_CAP_FOR_FILE_TRANSFER = 1 << 30
|
|
40
|
+
# Variable name of server DoP cap for file transfer
|
|
41
|
+
_VARIABLE_NAME_SERVER_DOP_CAP_FOR_FILE_TRANSFER = (
|
|
42
|
+
"snowflake_server_dop_cap_for_file_transfer"
|
|
43
|
+
)
|
|
44
|
+
|
|
35
45
|
|
|
36
46
|
def generate_random_alphanumeric(length: int = 10) -> str:
|
|
37
47
|
return "".join(choice(ALPHANUMERIC) for _ in range(length))
|
|
@@ -60,6 +70,15 @@ def is_uuid4(str_or_uuid: str | UUID) -> bool:
|
|
|
60
70
|
return uuid_str == str_or_uuid
|
|
61
71
|
|
|
62
72
|
|
|
73
|
+
def _snowflake_max_parallelism_for_file_transfer(connection):
|
|
74
|
+
"""Returns the server side cap on max parallelism for file transfer for the given connection."""
|
|
75
|
+
return getattr(
|
|
76
|
+
connection,
|
|
77
|
+
f"_{_VARIABLE_NAME_SERVER_DOP_CAP_FOR_FILE_TRANSFER}",
|
|
78
|
+
_DEFAULT_VALUE_SERVER_DOP_CAP_FOR_FILE_TRANSFER,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
63
82
|
class _TrackedQueryCancellationTimer(Timer):
|
|
64
83
|
def __init__(self, interval, function, args=None, kwargs=None):
|
|
65
84
|
super().__init__(interval, function, args, kwargs)
|
|
@@ -68,3 +87,12 @@ class _TrackedQueryCancellationTimer(Timer):
|
|
|
68
87
|
def run(self):
|
|
69
88
|
super().run()
|
|
70
89
|
self.executed = True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_application_path() -> str:
|
|
93
|
+
"""Get the path of the application script using the connector."""
|
|
94
|
+
try:
|
|
95
|
+
outermost_frame = stack()[-1]
|
|
96
|
+
return outermost_frame.filename
|
|
97
|
+
except Exception:
|
|
98
|
+
return "unknown"
|
|
@@ -13,9 +13,10 @@ from pytz import UTC
|
|
|
13
13
|
|
|
14
14
|
from .constants import PARAMETER_TIMEZONE
|
|
15
15
|
from .converter import _generate_tzinfo_from_tzoffset
|
|
16
|
+
from .interval_util import interval_year_month_to_string
|
|
16
17
|
|
|
17
18
|
if TYPE_CHECKING:
|
|
18
|
-
from numpy import datetime64, float64, int64
|
|
19
|
+
from numpy import datetime64, float64, int64, timedelta64
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
try:
|
|
@@ -163,3 +164,44 @@ class ArrowConverterContext:
|
|
|
163
164
|
|
|
164
165
|
def DECFLOAT_to_numpy_float64(self, exponent: int, significand: bytes) -> float64:
|
|
165
166
|
return numpy.float64(self.DECFLOAT_to_decimal(exponent, significand))
|
|
167
|
+
|
|
168
|
+
def INTERVAL_YEAR_MONTH_to_str(self, months: int) -> str:
|
|
169
|
+
return interval_year_month_to_string(months)
|
|
170
|
+
|
|
171
|
+
def INTERVAL_YEAR_MONTH_to_numpy_timedelta(self, months: int) -> timedelta64:
|
|
172
|
+
return numpy.timedelta64(months, "M")
|
|
173
|
+
|
|
174
|
+
def INTERVAL_DAY_TIME_int_to_numpy_timedelta(self, nanos: int) -> timedelta64:
|
|
175
|
+
return numpy.timedelta64(nanos, "ns")
|
|
176
|
+
|
|
177
|
+
def INTERVAL_DAY_TIME_int_to_timedelta(self, nanos: int) -> timedelta:
|
|
178
|
+
# Python timedelta only supports microsecond precision. We receive value in
|
|
179
|
+
# nanoseconds.
|
|
180
|
+
return timedelta(microseconds=nanos // 1000)
|
|
181
|
+
|
|
182
|
+
def INTERVAL_DAY_TIME_decimal_to_numpy_timedelta(self, value: bytes) -> timedelta64:
|
|
183
|
+
# Snowflake supports up to 9 digits leading field precision for the day-time
|
|
184
|
+
# interval. That when represented in nanoseconds can not be stored in a 64-bit
|
|
185
|
+
# integer. So we send these as Decimal128 from server to client.
|
|
186
|
+
# Arrow uses little-endian by default.
|
|
187
|
+
# https://arrow.apache.org/docs/format/Columnar.html#byte-order-endianness
|
|
188
|
+
nanos = int.from_bytes(value, byteorder="little", signed=True)
|
|
189
|
+
# Numpy timedelta only supports up to 64-bit integers, so we need to change the
|
|
190
|
+
# unit to milliseconds to avoid overflow.
|
|
191
|
+
# Max value received from server
|
|
192
|
+
# = 10**9 * NANOS_PER_DAY - 1
|
|
193
|
+
# = 86399999999999999999999 nanoseconds
|
|
194
|
+
# = 86399999999999999 milliseconds
|
|
195
|
+
# math.log2(86399999999999999) = 56.3 < 64
|
|
196
|
+
return numpy.timedelta64(nanos // 1_000_000, "ms")
|
|
197
|
+
|
|
198
|
+
def INTERVAL_DAY_TIME_decimal_to_timedelta(self, value: bytes) -> timedelta:
|
|
199
|
+
# Snowflake supports up to 9 digits leading field precision for the day-time
|
|
200
|
+
# interval. That when represented in nanoseconds can not be stored in a 64-bit
|
|
201
|
+
# integer. So we send these as Decimal128 from server to client.
|
|
202
|
+
# Arrow uses little-endian by default.
|
|
203
|
+
# https://arrow.apache.org/docs/format/Columnar.html#byte-order-endianness
|
|
204
|
+
nanos = int.from_bytes(value, byteorder="little", signed=True)
|
|
205
|
+
# Python timedelta only supports microsecond precision. We receive value in
|
|
206
|
+
# nanoseconds.
|
|
207
|
+
return timedelta(microseconds=nanos // 1000)
|
|
@@ -17,6 +17,7 @@ from cryptography.hazmat.primitives.serialization import (
|
|
|
17
17
|
load_pem_private_key,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
+
from .._utils import get_application_path
|
|
20
21
|
from ..compat import urlencode
|
|
21
22
|
from ..constants import (
|
|
22
23
|
DAY_IN_SECONDS,
|
|
@@ -51,6 +52,8 @@ from ..network import (
|
|
|
51
52
|
PYTHON_CONNECTOR_USER_AGENT,
|
|
52
53
|
ReauthenticationRequest,
|
|
53
54
|
)
|
|
55
|
+
from ..platform_detection import detect_platforms
|
|
56
|
+
from ..session_manager import SessionManager
|
|
54
57
|
from ..sqlstate import SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED
|
|
55
58
|
from ..token_cache import TokenCache, TokenKey, TokenType
|
|
56
59
|
from ..version import VERSION
|
|
@@ -100,6 +103,8 @@ class Auth:
|
|
|
100
103
|
login_timeout: int | None = None,
|
|
101
104
|
network_timeout: int | None = None,
|
|
102
105
|
socket_timeout: int | None = None,
|
|
106
|
+
platform_detection_timeout_seconds: float | None = None,
|
|
107
|
+
session_manager: SessionManager | None = None,
|
|
103
108
|
):
|
|
104
109
|
return {
|
|
105
110
|
"data": {
|
|
@@ -110,6 +115,7 @@ class Auth:
|
|
|
110
115
|
"LOGIN_NAME": user,
|
|
111
116
|
"CLIENT_ENVIRONMENT": {
|
|
112
117
|
"APPLICATION": application,
|
|
118
|
+
"APPLICATION_PATH": get_application_path(),
|
|
113
119
|
"OS": OPERATING_SYSTEM,
|
|
114
120
|
"OS_VERSION": PLATFORM,
|
|
115
121
|
"PYTHON_VERSION": PYTHON_VERSION,
|
|
@@ -120,6 +126,10 @@ class Auth:
|
|
|
120
126
|
"LOGIN_TIMEOUT": login_timeout,
|
|
121
127
|
"NETWORK_TIMEOUT": network_timeout,
|
|
122
128
|
"SOCKET_TIMEOUT": socket_timeout,
|
|
129
|
+
"PLATFORM": detect_platforms(
|
|
130
|
+
platform_detection_timeout_seconds=platform_detection_timeout_seconds,
|
|
131
|
+
session_manager=session_manager,
|
|
132
|
+
),
|
|
123
133
|
},
|
|
124
134
|
},
|
|
125
135
|
}
|
|
@@ -175,6 +185,8 @@ class Auth:
|
|
|
175
185
|
self._rest._connection.login_timeout,
|
|
176
186
|
self._rest._connection._network_timeout,
|
|
177
187
|
self._rest._connection._socket_timeout,
|
|
188
|
+
self._rest._connection._platform_detection_timeout_seconds,
|
|
189
|
+
session_manager=self._rest.session_manager.clone(use_pooling=False),
|
|
178
190
|
)
|
|
179
191
|
|
|
180
192
|
body = copy.deepcopy(body_template)
|
|
@@ -540,7 +552,9 @@ class Auth:
|
|
|
540
552
|
|
|
541
553
|
def get_token_cache(self) -> TokenCache:
|
|
542
554
|
if self._token_cache is None:
|
|
543
|
-
self._token_cache = TokenCache.make(
|
|
555
|
+
self._token_cache = TokenCache.make(
|
|
556
|
+
skip_file_permissions_check=self._rest._connection._unsafe_skip_file_permissions_check
|
|
557
|
+
)
|
|
544
558
|
return self._token_cache
|
|
545
559
|
|
|
546
560
|
|
|
@@ -12,11 +12,20 @@ from abc import ABC, abstractmethod
|
|
|
12
12
|
from typing import TYPE_CHECKING, Any
|
|
13
13
|
from urllib.error import HTTPError, URLError
|
|
14
14
|
|
|
15
|
-
from ..errorcode import
|
|
15
|
+
from ..errorcode import (
|
|
16
|
+
ER_FAILED_TO_REQUEST,
|
|
17
|
+
ER_IDP_CONNECTION_ERROR,
|
|
18
|
+
ER_NO_CLIENT_ID,
|
|
19
|
+
ER_NO_CLIENT_SECRET,
|
|
20
|
+
)
|
|
21
|
+
from ..errors import Error, ProgrammingError
|
|
16
22
|
from ..network import OAUTH_AUTHENTICATOR
|
|
23
|
+
from ..proxy import get_proxy_url
|
|
17
24
|
from ..secret_detector import SecretDetector
|
|
18
25
|
from ..token_cache import TokenCache, TokenKey, TokenType
|
|
19
26
|
from ..vendored import urllib3
|
|
27
|
+
from ..vendored.requests.utils import get_environ_proxies, select_proxy
|
|
28
|
+
from ..vendored.urllib3.poolmanager import ProxyManager
|
|
20
29
|
from .by_plugin import AuthByPlugin, AuthType
|
|
21
30
|
|
|
22
31
|
if TYPE_CHECKING:
|
|
@@ -185,6 +194,33 @@ class AuthByOAuthBase(AuthByPlugin, _OAuthTokensMixin, ABC):
|
|
|
185
194
|
"""Returns the token."""
|
|
186
195
|
return self._access_token or ""
|
|
187
196
|
|
|
197
|
+
@staticmethod
|
|
198
|
+
def _validate_client_credentials_present(
|
|
199
|
+
client_id: str, client_secret: str, connection: SnowflakeConnection
|
|
200
|
+
) -> tuple[str, str]:
|
|
201
|
+
if client_id is None or client_id == "":
|
|
202
|
+
Error.errorhandler_wrapper(
|
|
203
|
+
connection,
|
|
204
|
+
None,
|
|
205
|
+
ProgrammingError,
|
|
206
|
+
{
|
|
207
|
+
"msg": "Oauth code flow requirement 'client_id' is empty",
|
|
208
|
+
"errno": ER_NO_CLIENT_ID,
|
|
209
|
+
},
|
|
210
|
+
)
|
|
211
|
+
if client_secret is None or client_secret == "":
|
|
212
|
+
Error.errorhandler_wrapper(
|
|
213
|
+
connection,
|
|
214
|
+
None,
|
|
215
|
+
ProgrammingError,
|
|
216
|
+
{
|
|
217
|
+
"msg": "Oauth code flow requirement 'client_secret' is empty",
|
|
218
|
+
"errno": ER_NO_CLIENT_SECRET,
|
|
219
|
+
},
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
return client_id, client_secret
|
|
223
|
+
|
|
188
224
|
def reauthenticate(
|
|
189
225
|
self,
|
|
190
226
|
*,
|
|
@@ -237,7 +273,9 @@ class AuthByOAuthBase(AuthByPlugin, _OAuthTokensMixin, ABC):
|
|
|
237
273
|
"""
|
|
238
274
|
body["data"]["AUTHENTICATOR"] = OAUTH_AUTHENTICATOR
|
|
239
275
|
body["data"]["TOKEN"] = self._access_token
|
|
240
|
-
body["data"]
|
|
276
|
+
if "CLIENT_ENVIRONMENT" not in body["data"]:
|
|
277
|
+
body["data"]["CLIENT_ENVIRONMENT"] = {}
|
|
278
|
+
body["data"]["CLIENT_ENVIRONMENT"]["OAUTH_TYPE"] = self._get_oauth_type_id()
|
|
241
279
|
|
|
242
280
|
def _do_refresh_token(self, conn: SnowflakeConnection) -> None:
|
|
243
281
|
"""If a refresh token is available exchanges it with a new access token.
|
|
@@ -283,8 +321,14 @@ class AuthByOAuthBase(AuthByPlugin, _OAuthTokensMixin, ABC):
|
|
|
283
321
|
if self._scope:
|
|
284
322
|
fields["scope"] = self._scope
|
|
285
323
|
try:
|
|
286
|
-
|
|
287
|
-
|
|
324
|
+
# TODO(SNOW-2229411) Session manager should be used here. It may require additional security validation (since we would transition from PoolManager to requests.Session) and some parameters would be passed implicitly. OAuth token exchange must NOT reuse pooled HTTP sessions. We should create a fresh SessionManager with use_pooling=False for each call.
|
|
325
|
+
proxy_url = self._resolve_proxy_url(conn, self._token_request_url)
|
|
326
|
+
http_client = (
|
|
327
|
+
ProxyManager(proxy_url=proxy_url)
|
|
328
|
+
if proxy_url
|
|
329
|
+
else urllib3.PoolManager()
|
|
330
|
+
)
|
|
331
|
+
return http_client.request_encode_body(
|
|
288
332
|
"POST",
|
|
289
333
|
self._token_request_url,
|
|
290
334
|
encode_multipart=False,
|
|
@@ -323,8 +367,12 @@ class AuthByOAuthBase(AuthByPlugin, _OAuthTokensMixin, ABC):
|
|
|
323
367
|
connection: SnowflakeConnection,
|
|
324
368
|
fields: dict[str, str],
|
|
325
369
|
) -> (str | None, str | None):
|
|
326
|
-
|
|
327
|
-
|
|
370
|
+
# TODO(SNOW-2229411) Session manager should be used here. It may require additional security validation (since we would transition from PoolManager to requests.Session) and some parameters would be passed implicitly. Token request must bypass HTTP connection pools.
|
|
371
|
+
proxy_url = self._resolve_proxy_url(connection, self._token_request_url)
|
|
372
|
+
http_client = (
|
|
373
|
+
ProxyManager(proxy_url=proxy_url) if proxy_url else urllib3.PoolManager()
|
|
374
|
+
)
|
|
375
|
+
resp = http_client.request_encode_body(
|
|
328
376
|
"POST",
|
|
329
377
|
self._token_request_url,
|
|
330
378
|
headers=self._create_token_request_headers(),
|
|
@@ -365,3 +413,25 @@ class AuthByOAuthBase(AuthByPlugin, _OAuthTokensMixin, ABC):
|
|
|
365
413
|
"Accept": "application/json",
|
|
366
414
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
|
367
415
|
}
|
|
416
|
+
|
|
417
|
+
@staticmethod
|
|
418
|
+
def _resolve_proxy_url(
|
|
419
|
+
connection: SnowflakeConnection, request_url: str
|
|
420
|
+
) -> str | None:
|
|
421
|
+
# TODO(SNOW-2229411) Session manager should be used instead. It may require additional security validation.
|
|
422
|
+
"""Resolve proxy URL from explicit config first, then environment variables."""
|
|
423
|
+
# First try explicit proxy configuration from connection parameters
|
|
424
|
+
proxy_url = get_proxy_url(
|
|
425
|
+
connection.proxy_host,
|
|
426
|
+
connection.proxy_port,
|
|
427
|
+
connection.proxy_user,
|
|
428
|
+
connection.proxy_password,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
if proxy_url:
|
|
432
|
+
return proxy_url
|
|
433
|
+
|
|
434
|
+
# Fall back to environment variables (HTTP_PROXY, HTTPS_PROXY)
|
|
435
|
+
# Use proper proxy selection that considers the URL scheme
|
|
436
|
+
proxies = get_environ_proxies(request_url)
|
|
437
|
+
return select_proxy(request_url, proxies)
|
|
@@ -50,9 +50,10 @@ class AuthType(Enum):
|
|
|
50
50
|
ID_TOKEN = "ID_TOKEN"
|
|
51
51
|
USR_PWD_MFA = "USERNAME_PASSWORD_MFA"
|
|
52
52
|
OKTA = "OKTA"
|
|
53
|
-
PAT = "PROGRAMMATIC_ACCESS_TOKEN
|
|
53
|
+
PAT = "PROGRAMMATIC_ACCESS_TOKEN"
|
|
54
54
|
NO_AUTH = "NO_AUTH"
|
|
55
55
|
WORKLOAD_IDENTITY = "WORKLOAD_IDENTITY"
|
|
56
|
+
PAT_WITH_EXTERNAL_SESSION = "PAT_WITH_EXTERNAL_SESSION"
|
|
56
57
|
|
|
57
58
|
|
|
58
59
|
class AuthByPlugin(ABC):
|
|
@@ -18,11 +18,13 @@ from typing import TYPE_CHECKING, Any
|
|
|
18
18
|
from ..compat import parse_qs, urlparse, urlsplit
|
|
19
19
|
from ..constants import OAUTH_TYPE_AUTHORIZATION_CODE
|
|
20
20
|
from ..errorcode import (
|
|
21
|
+
ER_INVALID_VALUE,
|
|
21
22
|
ER_OAUTH_CALLBACK_ERROR,
|
|
22
23
|
ER_OAUTH_SERVER_TIMEOUT,
|
|
23
24
|
ER_OAUTH_STATE_CHANGED,
|
|
24
25
|
ER_UNABLE_TO_OPEN_BROWSER,
|
|
25
26
|
)
|
|
27
|
+
from ..errors import Error, ProgrammingError
|
|
26
28
|
from ..token_cache import TokenCache
|
|
27
29
|
from ._http_server import AuthHttpServer
|
|
28
30
|
from ._oauth_base import AuthByOAuthBase
|
|
@@ -45,6 +47,8 @@ def _get_query_params(
|
|
|
45
47
|
class AuthByOauthCode(AuthByOAuthBase):
|
|
46
48
|
"""Authenticates user by OAuth code flow."""
|
|
47
49
|
|
|
50
|
+
_LOCAL_APPLICATION_CLIENT_CREDENTIALS = "LOCAL_APPLICATION"
|
|
51
|
+
|
|
48
52
|
def __init__(
|
|
49
53
|
self,
|
|
50
54
|
application: str,
|
|
@@ -54,13 +58,27 @@ class AuthByOauthCode(AuthByOAuthBase):
|
|
|
54
58
|
token_request_url: str,
|
|
55
59
|
redirect_uri: str,
|
|
56
60
|
scope: str,
|
|
61
|
+
host: str,
|
|
57
62
|
pkce_enabled: bool = True,
|
|
58
63
|
token_cache: TokenCache | None = None,
|
|
59
64
|
refresh_token_enabled: bool = False,
|
|
60
65
|
external_browser_timeout: int | None = None,
|
|
61
66
|
enable_single_use_refresh_tokens: bool = False,
|
|
67
|
+
connection: SnowflakeConnection | None = None,
|
|
62
68
|
**kwargs,
|
|
63
69
|
) -> None:
|
|
70
|
+
authentication_url, redirect_uri = self._validate_oauth_code_uris(
|
|
71
|
+
authentication_url, redirect_uri, connection
|
|
72
|
+
)
|
|
73
|
+
client_id, client_secret = self._validate_client_credentials_with_defaults(
|
|
74
|
+
client_id,
|
|
75
|
+
client_secret,
|
|
76
|
+
authentication_url,
|
|
77
|
+
token_request_url,
|
|
78
|
+
host,
|
|
79
|
+
connection,
|
|
80
|
+
)
|
|
81
|
+
|
|
64
82
|
super().__init__(
|
|
65
83
|
client_id=client_id,
|
|
66
84
|
client_secret=client_secret,
|
|
@@ -251,6 +269,7 @@ You can close this window now and go back where you started from.
|
|
|
251
269
|
"login. If you can't see it, check existing browser windows, "
|
|
252
270
|
"or your OS settings. Press CTRL+C to abort and try again..."
|
|
253
271
|
)
|
|
272
|
+
# TODO(SNOW-2229411) Investigate if Session manager / Http Config should be used here.
|
|
254
273
|
code, state = (
|
|
255
274
|
self._receive_authorization_callback(callback_server, connection)
|
|
256
275
|
if webbrowser.open(authorization_request)
|
|
@@ -385,3 +404,77 @@ You can close this window now and go back where you started from.
|
|
|
385
404
|
},
|
|
386
405
|
)
|
|
387
406
|
return parsed.get("code", [None])[0], parsed.get("state", [None])[0]
|
|
407
|
+
|
|
408
|
+
@staticmethod
|
|
409
|
+
def _is_snowflake_as_idp(
|
|
410
|
+
authentication_url: str, token_request_url: str, host: str
|
|
411
|
+
) -> bool:
|
|
412
|
+
return (authentication_url == "" or host in authentication_url) and (
|
|
413
|
+
token_request_url == "" or host in token_request_url
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
def _eligible_for_default_client_credentials(
|
|
417
|
+
self,
|
|
418
|
+
client_id: str,
|
|
419
|
+
client_secret: str,
|
|
420
|
+
authorization_url: str,
|
|
421
|
+
token_request_url: str,
|
|
422
|
+
host: str,
|
|
423
|
+
) -> bool:
|
|
424
|
+
return (
|
|
425
|
+
(client_id == "" or client_secret is None)
|
|
426
|
+
and (client_secret == "" or client_secret is None)
|
|
427
|
+
and self.__class__._is_snowflake_as_idp(
|
|
428
|
+
authorization_url, token_request_url, host
|
|
429
|
+
)
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
def _validate_client_credentials_with_defaults(
|
|
433
|
+
self,
|
|
434
|
+
client_id: str,
|
|
435
|
+
client_secret: str,
|
|
436
|
+
authorization_url: str,
|
|
437
|
+
token_request_url: str,
|
|
438
|
+
host: str,
|
|
439
|
+
connection: SnowflakeConnection,
|
|
440
|
+
) -> tuple[str, str] | None:
|
|
441
|
+
if self._eligible_for_default_client_credentials(
|
|
442
|
+
client_id, client_secret, authorization_url, token_request_url, host
|
|
443
|
+
):
|
|
444
|
+
return (
|
|
445
|
+
self.__class__._LOCAL_APPLICATION_CLIENT_CREDENTIALS,
|
|
446
|
+
self.__class__._LOCAL_APPLICATION_CLIENT_CREDENTIALS,
|
|
447
|
+
)
|
|
448
|
+
else:
|
|
449
|
+
self._validate_client_credentials_present(
|
|
450
|
+
client_id, client_secret, connection
|
|
451
|
+
)
|
|
452
|
+
return client_id, client_secret
|
|
453
|
+
|
|
454
|
+
@staticmethod
|
|
455
|
+
def _validate_oauth_code_uris(
|
|
456
|
+
authorization_url: str, redirect_uri: str, connection: SnowflakeConnection
|
|
457
|
+
) -> tuple[str, str]:
|
|
458
|
+
if authorization_url and not authorization_url.startswith("https://"):
|
|
459
|
+
Error.errorhandler_wrapper(
|
|
460
|
+
connection,
|
|
461
|
+
None,
|
|
462
|
+
ProgrammingError,
|
|
463
|
+
{
|
|
464
|
+
"msg": "OAuth supports only authorization urls that use 'https' scheme",
|
|
465
|
+
"errno": ER_INVALID_VALUE,
|
|
466
|
+
},
|
|
467
|
+
)
|
|
468
|
+
if redirect_uri and not (
|
|
469
|
+
redirect_uri.startswith("http://") or redirect_uri.startswith("https://")
|
|
470
|
+
):
|
|
471
|
+
Error.errorhandler_wrapper(
|
|
472
|
+
connection,
|
|
473
|
+
None,
|
|
474
|
+
ProgrammingError,
|
|
475
|
+
{
|
|
476
|
+
"msg": "OAuth supports only authorization urls that use 'http(s)' scheme",
|
|
477
|
+
"errno": ER_INVALID_VALUE,
|
|
478
|
+
},
|
|
479
|
+
)
|
|
480
|
+
return authorization_url, redirect_uri
|
|
@@ -8,7 +8,6 @@ import logging
|
|
|
8
8
|
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
10
10
|
from ..constants import OAUTH_TYPE_CLIENT_CREDENTIALS
|
|
11
|
-
from ..token_cache import TokenCache
|
|
12
11
|
from ._oauth_base import AuthByOAuthBase
|
|
13
12
|
|
|
14
13
|
if TYPE_CHECKING:
|
|
@@ -27,17 +26,17 @@ class AuthByOauthCredentials(AuthByOAuthBase):
|
|
|
27
26
|
client_secret: str,
|
|
28
27
|
token_request_url: str,
|
|
29
28
|
scope: str,
|
|
30
|
-
|
|
31
|
-
refresh_token_enabled: bool = False,
|
|
29
|
+
connection: SnowflakeConnection | None = None,
|
|
32
30
|
**kwargs,
|
|
33
31
|
) -> None:
|
|
32
|
+
self._validate_client_credentials_present(client_id, client_secret, connection)
|
|
34
33
|
super().__init__(
|
|
35
34
|
client_id=client_id,
|
|
36
35
|
client_secret=client_secret,
|
|
37
36
|
token_request_url=token_request_url,
|
|
38
37
|
scope=scope,
|
|
39
|
-
token_cache=
|
|
40
|
-
refresh_token_enabled=
|
|
38
|
+
token_cache=None,
|
|
39
|
+
refresh_token_enabled=False,
|
|
41
40
|
**kwargs,
|
|
42
41
|
)
|
|
43
42
|
self._application = application
|
|
@@ -168,6 +168,7 @@ class AuthByOkta(AuthByPlugin):
|
|
|
168
168
|
conn._ocsp_mode(),
|
|
169
169
|
conn.login_timeout,
|
|
170
170
|
conn._network_timeout,
|
|
171
|
+
session_manager=conn._session_manager.clone(use_pooling=False),
|
|
171
172
|
)
|
|
172
173
|
|
|
173
174
|
body["data"]["AUTHENTICATOR"] = authenticator
|
|
@@ -235,7 +236,7 @@ class AuthByOkta(AuthByPlugin):
|
|
|
235
236
|
"username": user,
|
|
236
237
|
"password": password,
|
|
237
238
|
}
|
|
238
|
-
ret = conn.
|
|
239
|
+
ret = conn.rest.fetch(
|
|
239
240
|
"post",
|
|
240
241
|
token_url,
|
|
241
242
|
headers,
|
|
@@ -285,7 +286,7 @@ class AuthByOkta(AuthByPlugin):
|
|
|
285
286
|
HTTP_HEADER_ACCEPT: "*/*",
|
|
286
287
|
}
|
|
287
288
|
remaining_timeout = timeout_time - time.time() if timeout_time else None
|
|
288
|
-
response_html = conn.
|
|
289
|
+
response_html = conn.rest.fetch(
|
|
289
290
|
"get",
|
|
290
291
|
sso_url,
|
|
291
292
|
headers,
|