snowflake-connector-python 3.18.0__tar.gz → 4.1.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.18.0 → snowflake_connector_python-4.1.0}/DESCRIPTION.md +29 -2
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/PKG-INFO +45 -14
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/setup.cfg +12 -11
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/setup.py +26 -4
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/_auth.py +39 -3
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/_http_server.py +44 -7
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/_oauth_base.py +16 -2
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/oauth_code.py +8 -3
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/oauth_credentials.py +5 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/okta.py +1 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/webbrowser.py +17 -8
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/workload_identity.py +6 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/azure_storage_client.py +4 -4
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/config_manager.py +13 -1
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/connection.py +276 -9
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/connection_diagnostic.py +2 -2
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/constants.py +6 -0
- snowflake_connector_python-4.1.0/src/snowflake/connector/crl.py +794 -0
- snowflake_connector_python-4.1.0/src/snowflake/connector/crl_cache.py +643 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/cursor.py +88 -43
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +2 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/network.py +34 -6
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ocsp_snowflake.py +78 -62
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/options.py +23 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/pandas_tools.py +1 -1
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/platform_detection.py +169 -68
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/result_batch.py +11 -5
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/s3_storage_client.py +12 -3
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/session_manager.py +120 -49
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ssl_wrap_socket.py +64 -9
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/storage_client.py +5 -3
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/telemetry.py +4 -4
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/telemetry_oob.py +1 -1
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/token_cache.py +37 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/util_text.py +4 -2
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/version.py +1 -1
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/wif_util.py +133 -22
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/PKG-INFO +45 -14
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/SOURCES.txt +2 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/requires.txt +15 -11
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/CONTRIBUTING.md +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/LICENSE.txt +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/MANIFEST.in +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/NOTICE +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/README.md +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/SECURITY.md +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/pyproject.toml +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/_query_context_cache.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/_sql_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/_utils.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/arrow_context.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/by_plugin.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/default.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/idtoken.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/keypair.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/no_auth.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/oauth.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/pat.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/usrpwdmfa.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/backoff_policies.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/bind_upload_agent.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/cache.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/compat.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter_issue23517.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter_null.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter_snowsql.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/dbapi.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/description.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/direct_file_operation_utils.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/encryption_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/errorcode.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/errors.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/externals_utils/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/externals_utils/externals_setup.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/feature.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_compression_type.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_lock.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_transfer_agent.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/gcs_storage_client.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/gzip_decoder.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/interval_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/local_storage_client.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/log_configuration.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/logging_utils/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/logging_utils/filters.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ocsp_asn1crypto.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/proxy.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/py.typed +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/result_set.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/secret_detector.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sf_dirs.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sfbinaryformat.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sfdatetime.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/snow_logging.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sqlstate.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ssd_internal_keys.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/test_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/time_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/dump_certs.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/dump_ocsp_response.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/dump_ocsp_response_cache.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/probe_connection.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/url_util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/LICENSE +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/__version__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/_internal_utils.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/adapters.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/api.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/auth.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/certs.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/compat.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/cookies.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/exceptions.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/help.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/hooks.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/models.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/packages.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/sessions.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/status_codes.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/structures.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/utils.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/LICENSE.txt +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_base_connection.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_collections.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_request_methods.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_version.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/connection.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/connectionpool.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/connection.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/emscripten_fetch_worker.js +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/fetch.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/request.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/response.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/socks.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/exceptions.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/fields.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/filepost.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/http2/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/http2/connection.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/http2/probe.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/poolmanager.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/py.typed +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/response.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/__init__.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/connection.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/proxy.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/request.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/response.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/retry.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/ssl_.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/ssltransport.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/timeout.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/url.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/util.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/wait.py +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/dependency_links.txt +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/entry_points.txt +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/not-zip-safe +0 -0
- {snowflake_connector_python-3.18.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/top_level.txt +0 -0
|
@@ -7,8 +7,34 @@ 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
|
-
-
|
|
11
|
-
-
|
|
10
|
+
- v4.1.0(November 18,2025)
|
|
11
|
+
- Added the `SNOWFLAKE_AUTH_FORCE_SERVER` environment variable to force the use of the local-listening server when using the `externalbrowser` auth method.
|
|
12
|
+
- This allows headless environments (like Docker or Airflow) running locally to auth via a browser URL.
|
|
13
|
+
- Fix compilation error when building from sources with libc++.
|
|
14
|
+
- Pin lower versions of dependencies to oldest version without vulnerabilities.
|
|
15
|
+
- Added no_proxy parameter for proxy configuration without using environmental variables.
|
|
16
|
+
- Added OAUTH_AUTHORIZATION_CODE and OAUTH_CLIENT_CREDENTIALS to list of authenticators that don't require user to be set
|
|
17
|
+
- Added `oauth_socket_uri` connection parameter allowing to separate server and redirect URIs for local OAuth server.
|
|
18
|
+
- Made platform_detection logs silent and improved its timeout handling. Added support for ENV_VAR_DISABLE_PLATFORM_DETECTION environment variable.
|
|
19
|
+
- Fixed FIPS environments md5 hash issues with multipart upload on Azure.
|
|
20
|
+
|
|
21
|
+
- v4.0.0(October 09,2025)
|
|
22
|
+
- Added support for checking certificates revocation using revocation lists (CRLs)
|
|
23
|
+
- Added `CERT_REVOCATION_CHECK_MODE` to `CLIENT_ENVIRONMENT`
|
|
24
|
+
- Added the `workload_identity_impersonation_path` parameter to support service account impersonation for Workload Identity Federation on GCP and AWS workloads only
|
|
25
|
+
- Fixed `get_results_from_sfqid` when using `DictCursor` and executing multiple statements at once
|
|
26
|
+
- Added the `oauth_credentials_in_body` parameter supporting an option to send the oauth client credentials in the request body
|
|
27
|
+
- Fix retry behavior for `ECONNRESET` error
|
|
28
|
+
- Added an option to exclude `botocore` and `boto3` dependencies by setting `SNOWFLAKE_NO_BOTO` environment variable during installation
|
|
29
|
+
- Revert changing exception type in case of token expired scenario for `Oauth` authenticator back to `DatabaseError`
|
|
30
|
+
- Enhanced configuration file security checks with stricter permission validation.
|
|
31
|
+
- Configuration files writable by group or others now raise a `ConfigSourceError` with detailed permission information, preventing potential credential tampering.
|
|
32
|
+
- Fixed the return type of `SnowflakeConnection.cursor(cursor_class)` to match the type of `cursor_class`
|
|
33
|
+
- Constrained the types of `fetchone`, `fetchmany`, `fetchall`
|
|
34
|
+
- As part of this fix, `DictCursor` is no longer a subclass of `SnowflakeCursor`; use `SnowflakeCursorBase` as a superclass of both.
|
|
35
|
+
- Fix "No AWS region was found" error if AWS region was set in `AWS_DEFAULT_REGION` variable instead of `AWS_REGION` for `WORKLOAD_IDENTITY` authenticator
|
|
36
|
+
- Add `ocsp_root_certs_dict_lock_timeout` connection parameter to set the timeout (in seconds) for acquiring the lock on the OCSP root certs dictionary. Default value for this parameter is -1 which indicates no timeout.
|
|
37
|
+
- Fixed behaviour of trying S3 Transfer Accelerate endpoint by default for internal stages, and always getting HTTP403 due to permissions missing on purpose. Now /accelerate is not attempted.
|
|
12
38
|
|
|
13
39
|
- v3.18.0(October 03,2025)
|
|
14
40
|
- Added support for pandas conversion for Day-time and Year-Month Interval types
|
|
@@ -16,6 +42,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
|
|
|
16
42
|
- v3.17.4(September 22,2025)
|
|
17
43
|
- Added support for intermediate certificates as roots when they are stored in the trust store
|
|
18
44
|
- Bumped up vendored `urllib3` to `2.5.0` and `requests` to `v2.32.5`
|
|
45
|
+
- Dropped support for OpenSSL versions older than 1.1.1
|
|
19
46
|
|
|
20
47
|
- v3.17.3(September 02,2025)
|
|
21
48
|
- Enhanced configuration file permission warning messages.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-connector-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: Snowflake Connector for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -39,24 +39,26 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
License-File: LICENSE.txt
|
|
40
40
|
License-File: NOTICE
|
|
41
41
|
Requires-Dist: asn1crypto<2.0.0,>0.24.0
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist: cryptography>=3.1.0
|
|
46
|
-
Requires-Dist: pyOpenSSL<26.0.0,>=22.0.0
|
|
47
|
-
Requires-Dist: pyjwt<3.0.0
|
|
42
|
+
Requires-Dist: cryptography>=44.0.1
|
|
43
|
+
Requires-Dist: pyOpenSSL<26.0.0,>=24.0.0
|
|
44
|
+
Requires-Dist: pyjwt<3.0.0,>=2.10.1
|
|
48
45
|
Requires-Dist: pytz
|
|
49
|
-
Requires-Dist: requests<3.0.0
|
|
46
|
+
Requires-Dist: requests<3.0.0,>=2.32.4
|
|
50
47
|
Requires-Dist: packaging
|
|
51
48
|
Requires-Dist: charset_normalizer<4,>=2
|
|
52
|
-
Requires-Dist: idna<4,>=
|
|
53
|
-
Requires-Dist: urllib3<2.0.0,>=1.
|
|
54
|
-
Requires-Dist: certifi>=
|
|
49
|
+
Requires-Dist: idna<4,>=3.7
|
|
50
|
+
Requires-Dist: urllib3<2.0.0,>=1.26.5; python_version < "3.10"
|
|
51
|
+
Requires-Dist: certifi>=2024.7.4
|
|
55
52
|
Requires-Dist: typing_extensions<5,>=4.3
|
|
56
53
|
Requires-Dist: filelock<4,>=3.5
|
|
57
54
|
Requires-Dist: sortedcontainers>=2.4.0
|
|
58
55
|
Requires-Dist: platformdirs<5.0.0,>=2.6.0
|
|
59
56
|
Requires-Dist: tomlkit
|
|
57
|
+
Requires-Dist: boto3>=1.24
|
|
58
|
+
Requires-Dist: botocore>=1.24
|
|
59
|
+
Provides-Extra: boto
|
|
60
|
+
Requires-Dist: boto3>=1.24; extra == "boto"
|
|
61
|
+
Requires-Dist: botocore>=1.24; extra == "boto"
|
|
60
62
|
Provides-Extra: development
|
|
61
63
|
Requires-Dist: Cython; extra == "development"
|
|
62
64
|
Requires-Dist: coverage; extra == "development"
|
|
@@ -70,12 +72,14 @@ Requires-Dist: pytest-rerunfailures<16.0; extra == "development"
|
|
|
70
72
|
Requires-Dist: pytest-timeout; extra == "development"
|
|
71
73
|
Requires-Dist: pytest-xdist; extra == "development"
|
|
72
74
|
Requires-Dist: pytzdata; extra == "development"
|
|
75
|
+
Requires-Dist: responses; extra == "development"
|
|
73
76
|
Provides-Extra: pandas
|
|
74
77
|
Requires-Dist: pandas<3.0.0,>=2.1.2; extra == "pandas"
|
|
75
|
-
Requires-Dist: pyarrow; extra == "pandas"
|
|
78
|
+
Requires-Dist: pyarrow>=14.0.1; extra == "pandas"
|
|
76
79
|
Provides-Extra: secure-local-storage
|
|
77
80
|
Requires-Dist: keyring<26.0.0,>=23.1.0; extra == "secure-local-storage"
|
|
78
81
|
Dynamic: license-file
|
|
82
|
+
Dynamic: requires-dist
|
|
79
83
|
|
|
80
84
|
This package includes the Snowflake Connector for Python, which conforms to the Python DB API 2.0 specification:
|
|
81
85
|
https://www.python.org/dev/peps/pep-0249/
|
|
@@ -86,8 +90,34 @@ https://docs.snowflake.com/
|
|
|
86
90
|
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
|
|
87
91
|
|
|
88
92
|
# Release Notes
|
|
89
|
-
-
|
|
90
|
-
-
|
|
93
|
+
- v4.1.0(November 18,2025)
|
|
94
|
+
- Added the `SNOWFLAKE_AUTH_FORCE_SERVER` environment variable to force the use of the local-listening server when using the `externalbrowser` auth method.
|
|
95
|
+
- This allows headless environments (like Docker or Airflow) running locally to auth via a browser URL.
|
|
96
|
+
- Fix compilation error when building from sources with libc++.
|
|
97
|
+
- Pin lower versions of dependencies to oldest version without vulnerabilities.
|
|
98
|
+
- Added no_proxy parameter for proxy configuration without using environmental variables.
|
|
99
|
+
- Added OAUTH_AUTHORIZATION_CODE and OAUTH_CLIENT_CREDENTIALS to list of authenticators that don't require user to be set
|
|
100
|
+
- Added `oauth_socket_uri` connection parameter allowing to separate server and redirect URIs for local OAuth server.
|
|
101
|
+
- Made platform_detection logs silent and improved its timeout handling. Added support for ENV_VAR_DISABLE_PLATFORM_DETECTION environment variable.
|
|
102
|
+
- Fixed FIPS environments md5 hash issues with multipart upload on Azure.
|
|
103
|
+
|
|
104
|
+
- v4.0.0(October 09,2025)
|
|
105
|
+
- Added support for checking certificates revocation using revocation lists (CRLs)
|
|
106
|
+
- Added `CERT_REVOCATION_CHECK_MODE` to `CLIENT_ENVIRONMENT`
|
|
107
|
+
- Added the `workload_identity_impersonation_path` parameter to support service account impersonation for Workload Identity Federation on GCP and AWS workloads only
|
|
108
|
+
- Fixed `get_results_from_sfqid` when using `DictCursor` and executing multiple statements at once
|
|
109
|
+
- Added the `oauth_credentials_in_body` parameter supporting an option to send the oauth client credentials in the request body
|
|
110
|
+
- Fix retry behavior for `ECONNRESET` error
|
|
111
|
+
- Added an option to exclude `botocore` and `boto3` dependencies by setting `SNOWFLAKE_NO_BOTO` environment variable during installation
|
|
112
|
+
- Revert changing exception type in case of token expired scenario for `Oauth` authenticator back to `DatabaseError`
|
|
113
|
+
- Enhanced configuration file security checks with stricter permission validation.
|
|
114
|
+
- Configuration files writable by group or others now raise a `ConfigSourceError` with detailed permission information, preventing potential credential tampering.
|
|
115
|
+
- Fixed the return type of `SnowflakeConnection.cursor(cursor_class)` to match the type of `cursor_class`
|
|
116
|
+
- Constrained the types of `fetchone`, `fetchmany`, `fetchall`
|
|
117
|
+
- As part of this fix, `DictCursor` is no longer a subclass of `SnowflakeCursor`; use `SnowflakeCursorBase` as a superclass of both.
|
|
118
|
+
- Fix "No AWS region was found" error if AWS region was set in `AWS_DEFAULT_REGION` variable instead of `AWS_REGION` for `WORKLOAD_IDENTITY` authenticator
|
|
119
|
+
- Add `ocsp_root_certs_dict_lock_timeout` connection parameter to set the timeout (in seconds) for acquiring the lock on the OCSP root certs dictionary. Default value for this parameter is -1 which indicates no timeout.
|
|
120
|
+
- Fixed behaviour of trying S3 Transfer Accelerate endpoint by default for internal stages, and always getting HTTP403 due to permissions missing on purpose. Now /accelerate is not attempted.
|
|
91
121
|
|
|
92
122
|
- v3.18.0(October 03,2025)
|
|
93
123
|
- Added support for pandas conversion for Day-time and Year-Month Interval types
|
|
@@ -95,6 +125,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
|
|
|
95
125
|
- v3.17.4(September 22,2025)
|
|
96
126
|
- Added support for intermediate certificates as roots when they are stored in the trust store
|
|
97
127
|
- Bumped up vendored `urllib3` to `2.5.0` and `requests` to `v2.32.5`
|
|
128
|
+
- Dropped support for OpenSSL versions older than 1.1.1
|
|
98
129
|
|
|
99
130
|
- v3.17.3(September 02,2025)
|
|
100
131
|
- Enhanced configuration file permission warning messages.
|
|
@@ -44,19 +44,16 @@ python_requires = >=3.9
|
|
|
44
44
|
packages = find_namespace:
|
|
45
45
|
install_requires =
|
|
46
46
|
asn1crypto>0.24.0,<2.0.0
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
cryptography>=3.1.0
|
|
51
|
-
pyOpenSSL>=22.0.0,<26.0.0
|
|
52
|
-
pyjwt<3.0.0
|
|
47
|
+
cryptography>=44.0.1
|
|
48
|
+
pyOpenSSL>=24.0.0,<26.0.0
|
|
49
|
+
pyjwt>=2.10.1,<3.0.0
|
|
53
50
|
pytz
|
|
54
|
-
requests
|
|
51
|
+
requests>=2.32.4,<3.0.0
|
|
55
52
|
packaging
|
|
56
53
|
charset_normalizer>=2,<4
|
|
57
|
-
idna>=
|
|
58
|
-
urllib3>=1.
|
|
59
|
-
certifi>=
|
|
54
|
+
idna>=3.7,<4
|
|
55
|
+
urllib3>=1.26.5,<2.0.0; python_version < '3.10'
|
|
56
|
+
certifi>=2024.7.4
|
|
60
57
|
typing_extensions>=4.3,<5
|
|
61
58
|
filelock>=3.5,<4
|
|
62
59
|
sortedcontainers>=2.4.0
|
|
@@ -79,6 +76,9 @@ console_scripts =
|
|
|
79
76
|
snowflake-dump-certs = snowflake.connector.tool.dump_certs:main
|
|
80
77
|
|
|
81
78
|
[options.extras_require]
|
|
79
|
+
boto =
|
|
80
|
+
boto3>=1.24
|
|
81
|
+
botocore>=1.24
|
|
82
82
|
development =
|
|
83
83
|
Cython
|
|
84
84
|
coverage
|
|
@@ -92,9 +92,10 @@ development =
|
|
|
92
92
|
pytest-timeout
|
|
93
93
|
pytest-xdist
|
|
94
94
|
pytzdata
|
|
95
|
+
responses
|
|
95
96
|
pandas =
|
|
96
97
|
pandas>=2.1.2,<3.0.0
|
|
97
|
-
pyarrow
|
|
98
|
+
pyarrow>=14.0.1
|
|
98
99
|
secure-local-storage =
|
|
99
100
|
keyring>=23.1.0,<26.0.0
|
|
100
101
|
|
|
@@ -5,6 +5,7 @@ import sys
|
|
|
5
5
|
import warnings
|
|
6
6
|
|
|
7
7
|
from setuptools import Extension, setup
|
|
8
|
+
from setuptools.command.egg_info import egg_info
|
|
8
9
|
|
|
9
10
|
CONNECTOR_SRC_DIR = os.path.join("src", "snowflake", "connector")
|
|
10
11
|
NANOARROW_SRC_DIR = os.path.join(CONNECTOR_SRC_DIR, "nanoarrow_cpp", "ArrowIterator")
|
|
@@ -38,9 +39,14 @@ for flag in options_def:
|
|
|
38
39
|
extensions = None
|
|
39
40
|
cmd_class = {}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
_POSITIVE_VALUES = ("y", "yes", "t", "true", "1", "on")
|
|
43
|
+
SNOWFLAKE_DISABLE_COMPILE_ARROW_EXTENSIONS = (
|
|
44
|
+
os.environ.get("SNOWFLAKE_DISABLE_COMPILE_ARROW_EXTENSIONS", "false").lower()
|
|
45
|
+
in _POSITIVE_VALUES
|
|
46
|
+
)
|
|
47
|
+
SNOWFLAKE_NO_BOTO = (
|
|
48
|
+
os.environ.get("SNOWFLAKE_NO_BOTO", "false").lower() in _POSITIVE_VALUES
|
|
49
|
+
)
|
|
44
50
|
|
|
45
51
|
try:
|
|
46
52
|
from Cython.Build import cythonize
|
|
@@ -88,7 +94,7 @@ if _ABLE_TO_COMPILE_EXTENSIONS and not SNOWFLAKE_DISABLE_COMPILE_ARROW_EXTENSION
|
|
|
88
94
|
ext.sources += [
|
|
89
95
|
os.path.join(
|
|
90
96
|
NANOARROW_ARROW_ITERATOR_SRC_DIR,
|
|
91
|
-
*((file,) if isinstance(file, str) else file)
|
|
97
|
+
*((file,) if isinstance(file, str) else file),
|
|
92
98
|
)
|
|
93
99
|
for file in {
|
|
94
100
|
"ArrayConverter.cpp",
|
|
@@ -174,6 +180,22 @@ if _ABLE_TO_COMPILE_EXTENSIONS and not SNOWFLAKE_DISABLE_COMPILE_ARROW_EXTENSION
|
|
|
174
180
|
|
|
175
181
|
cmd_class = {"build_ext": MyBuildExt}
|
|
176
182
|
|
|
183
|
+
|
|
184
|
+
class SetDefaultInstallationExtras(egg_info):
|
|
185
|
+
"""Adds AWS extra unless SNOWFLAKE_NO_BOTO is specified."""
|
|
186
|
+
|
|
187
|
+
def finalize_options(self):
|
|
188
|
+
super().finalize_options()
|
|
189
|
+
|
|
190
|
+
# if not explicitly excluded, add boto dependencies to install_requires
|
|
191
|
+
if not SNOWFLAKE_NO_BOTO:
|
|
192
|
+
boto_extras = self.distribution.extras_require.get("boto", [])
|
|
193
|
+
self.distribution.install_requires += boto_extras
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# Update command classes
|
|
197
|
+
cmd_class["egg_info"] = SetDefaultInstallationExtras
|
|
198
|
+
|
|
177
199
|
setup(
|
|
178
200
|
version=version,
|
|
179
201
|
ext_modules=extensions,
|
|
@@ -53,11 +53,14 @@ from ..network import (
|
|
|
53
53
|
ReauthenticationRequest,
|
|
54
54
|
)
|
|
55
55
|
from ..platform_detection import detect_platforms
|
|
56
|
-
from ..session_manager import
|
|
56
|
+
from ..session_manager import BaseHttpConfig, HttpConfig
|
|
57
|
+
from ..session_manager import SessionManager as SyncSessionManager
|
|
58
|
+
from ..session_manager import SessionManagerFactory
|
|
57
59
|
from ..sqlstate import SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED
|
|
58
60
|
from ..token_cache import TokenCache, TokenKey, TokenType
|
|
59
61
|
from ..version import VERSION
|
|
60
62
|
from .no_auth import AuthNoAuth
|
|
63
|
+
from .oauth import AuthByOAuth
|
|
61
64
|
|
|
62
65
|
if TYPE_CHECKING:
|
|
63
66
|
from . import AuthByPlugin
|
|
@@ -100,12 +103,22 @@ class Auth:
|
|
|
100
103
|
internal_application_name,
|
|
101
104
|
internal_application_version,
|
|
102
105
|
ocsp_mode,
|
|
106
|
+
cert_revocation_check_mode,
|
|
103
107
|
login_timeout: int | None = None,
|
|
104
108
|
network_timeout: int | None = None,
|
|
105
109
|
socket_timeout: int | None = None,
|
|
106
110
|
platform_detection_timeout_seconds: float | None = None,
|
|
107
|
-
session_manager:
|
|
111
|
+
session_manager: SyncSessionManager | None = None,
|
|
112
|
+
http_config: BaseHttpConfig | None = None,
|
|
108
113
|
):
|
|
114
|
+
# Create sync SessionManager for platform detection if config is provided
|
|
115
|
+
# Platform detection runs in threads and uses sync SessionManager
|
|
116
|
+
if http_config is not None and session_manager is None:
|
|
117
|
+
# Extract base fields (automatically excludes subclass-specific fields)
|
|
118
|
+
# Note: It won't be possible to pass adapter_factory from outer async-code to this part of code
|
|
119
|
+
sync_config = HttpConfig(**http_config.to_base_dict())
|
|
120
|
+
session_manager = SessionManagerFactory.get_manager(config=sync_config)
|
|
121
|
+
|
|
109
122
|
return {
|
|
110
123
|
"data": {
|
|
111
124
|
"CLIENT_APP_ID": internal_application_name,
|
|
@@ -122,6 +135,7 @@ class Auth:
|
|
|
122
135
|
"PYTHON_RUNTIME": IMPLEMENTATION,
|
|
123
136
|
"PYTHON_COMPILER": COMPILER,
|
|
124
137
|
"OCSP_MODE": ocsp_mode.name,
|
|
138
|
+
"CERT_REVOCATION_CHECK_MODE": cert_revocation_check_mode,
|
|
125
139
|
"TRACING": logger.getEffectiveLevel(),
|
|
126
140
|
"LOGIN_TIMEOUT": login_timeout,
|
|
127
141
|
"NETWORK_TIMEOUT": network_timeout,
|
|
@@ -182,6 +196,7 @@ class Auth:
|
|
|
182
196
|
self._rest._connection._internal_application_name,
|
|
183
197
|
self._rest._connection._internal_application_version,
|
|
184
198
|
self._rest._connection._ocsp_mode(),
|
|
199
|
+
self._rest._connection.cert_revocation_check_mode,
|
|
185
200
|
self._rest._connection.login_timeout,
|
|
186
201
|
self._rest._connection._network_timeout,
|
|
187
202
|
self._rest._connection._socket_timeout,
|
|
@@ -373,7 +388,11 @@ class Auth:
|
|
|
373
388
|
sqlstate=SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
|
|
374
389
|
)
|
|
375
390
|
)
|
|
376
|
-
elif errno == OAUTH_ACCESS_TOKEN_EXPIRED_GS_CODE
|
|
391
|
+
elif (errno == OAUTH_ACCESS_TOKEN_EXPIRED_GS_CODE) and (
|
|
392
|
+
# SNOW-2329031: OAuth v1.0 does not support token renewal,
|
|
393
|
+
# for backward compatibility, we do not raise an exception here
|
|
394
|
+
not isinstance(auth_instance, AuthByOAuth)
|
|
395
|
+
):
|
|
377
396
|
raise ReauthenticationRequest(
|
|
378
397
|
ProgrammingError(
|
|
379
398
|
msg=ret["message"],
|
|
@@ -495,6 +514,16 @@ class Auth:
|
|
|
495
514
|
user: str,
|
|
496
515
|
session_parameters: dict[str, Any],
|
|
497
516
|
) -> None:
|
|
517
|
+
"""Attempt to load cached credentials to skip interactive authentication.
|
|
518
|
+
|
|
519
|
+
SSO (ID_TOKEN): If present, avoids opening browser for external authentication.
|
|
520
|
+
Controlled by client_store_temporary_credential parameter.
|
|
521
|
+
|
|
522
|
+
MFA (MFA_TOKEN): If present, skips MFA prompt on next connection.
|
|
523
|
+
Controlled by client_request_mfa_token parameter.
|
|
524
|
+
|
|
525
|
+
If cached tokens are expired/invalid, they're deleted and normal auth proceeds.
|
|
526
|
+
"""
|
|
498
527
|
if session_parameters.get(PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL, False):
|
|
499
528
|
self._rest.id_token = self._read_temporary_credential(
|
|
500
529
|
host,
|
|
@@ -530,6 +559,13 @@ class Auth:
|
|
|
530
559
|
session_parameters: dict[str, Any],
|
|
531
560
|
response: dict[str, Any],
|
|
532
561
|
) -> None:
|
|
562
|
+
"""Cache credentials received from successful authentication for future use.
|
|
563
|
+
|
|
564
|
+
Tokens are only cached if:
|
|
565
|
+
1. Server returned the token in response (server-side caching must be enabled)
|
|
566
|
+
2. Client has caching enabled via session parameters
|
|
567
|
+
3. User consented to caching (consent_cache_id_token for ID tokens)
|
|
568
|
+
"""
|
|
533
569
|
if (
|
|
534
570
|
self._rest._connection.auth_class.consent_cache_id_token
|
|
535
571
|
and session_parameters.get(
|
|
@@ -70,8 +70,10 @@ class AuthHttpServer:
|
|
|
70
70
|
self,
|
|
71
71
|
uri: str,
|
|
72
72
|
buf_size: int = 16384,
|
|
73
|
+
redirect_uri: str | None = None,
|
|
73
74
|
) -> None:
|
|
74
75
|
parsed_uri = urllib.parse.urlparse(uri)
|
|
76
|
+
parsed_redirect = urllib.parse.urlparse(redirect_uri) if redirect_uri else None
|
|
75
77
|
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
76
78
|
self.buf_size = buf_size
|
|
77
79
|
if os.getenv("SNOWFLAKE_AUTH_SOCKET_REUSE_PORT", "False").lower() == "true":
|
|
@@ -82,30 +84,34 @@ class AuthHttpServer:
|
|
|
82
84
|
else:
|
|
83
85
|
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
if parsed_redirect and self._is_local_uri(parsed_redirect):
|
|
88
|
+
server_port = parsed_redirect.port or 0
|
|
89
|
+
else:
|
|
90
|
+
server_port = parsed_uri.port or 0
|
|
91
|
+
|
|
86
92
|
for attempt in range(1, self.DEFAULT_MAX_ATTEMPTS + 1):
|
|
87
93
|
try:
|
|
88
94
|
self._socket.bind(
|
|
89
95
|
(
|
|
90
96
|
parsed_uri.hostname,
|
|
91
|
-
|
|
97
|
+
server_port,
|
|
92
98
|
)
|
|
93
99
|
)
|
|
94
100
|
break
|
|
95
101
|
except socket.gaierror as ex:
|
|
96
102
|
logger.error(
|
|
97
|
-
f"Failed to bind authorization callback server to port {
|
|
103
|
+
f"Failed to bind authorization callback server to port {server_port}: {ex}"
|
|
98
104
|
)
|
|
99
105
|
raise
|
|
100
106
|
except OSError as ex:
|
|
101
107
|
if attempt == self.DEFAULT_MAX_ATTEMPTS:
|
|
102
108
|
logger.error(
|
|
103
|
-
f"Failed to bind authorization callback server to port {
|
|
109
|
+
f"Failed to bind authorization callback server to port {server_port}: {ex}"
|
|
104
110
|
)
|
|
105
111
|
raise
|
|
106
112
|
logger.warning(
|
|
107
113
|
f"Attempt {attempt}/{self.DEFAULT_MAX_ATTEMPTS}. "
|
|
108
|
-
f"Failed to bind authorization callback server to port {
|
|
114
|
+
f"Failed to bind authorization callback server to port {server_port}: {ex}"
|
|
109
115
|
)
|
|
110
116
|
time.sleep(self.PORT_BIND_TIMEOUT / self.PORT_BIND_MAX_ATTEMPTS)
|
|
111
117
|
try:
|
|
@@ -114,16 +120,47 @@ class AuthHttpServer:
|
|
|
114
120
|
logger.error(f"Failed to start listening for auth callback: {ex}")
|
|
115
121
|
self.close()
|
|
116
122
|
raise
|
|
117
|
-
|
|
123
|
+
|
|
124
|
+
server_port = self._socket.getsockname()[1]
|
|
118
125
|
self._uri = urllib.parse.ParseResult(
|
|
119
126
|
scheme=parsed_uri.scheme,
|
|
120
|
-
netloc=parsed_uri.hostname + ":" + str(
|
|
127
|
+
netloc=parsed_uri.hostname + ":" + str(server_port),
|
|
121
128
|
path=parsed_uri.path,
|
|
122
129
|
params=parsed_uri.params,
|
|
123
130
|
query=parsed_uri.query,
|
|
124
131
|
fragment=parsed_uri.fragment,
|
|
125
132
|
)
|
|
126
133
|
|
|
134
|
+
if parsed_redirect:
|
|
135
|
+
if (
|
|
136
|
+
self._is_local_uri(parsed_redirect)
|
|
137
|
+
and server_port != parsed_redirect.port
|
|
138
|
+
):
|
|
139
|
+
logger.debug(
|
|
140
|
+
f"Updating redirect port {parsed_redirect.port} to match the server port {server_port}."
|
|
141
|
+
)
|
|
142
|
+
self._redirect_uri = urllib.parse.ParseResult(
|
|
143
|
+
scheme=parsed_redirect.scheme,
|
|
144
|
+
netloc=parsed_redirect.hostname + ":" + str(server_port),
|
|
145
|
+
path=parsed_redirect.path,
|
|
146
|
+
params=parsed_redirect.params,
|
|
147
|
+
query=parsed_redirect.query,
|
|
148
|
+
fragment=parsed_redirect.fragment,
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
self._redirect_uri = parsed_redirect
|
|
152
|
+
else:
|
|
153
|
+
# For backwards compatibility
|
|
154
|
+
self._redirect_uri = self._uri
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def _is_local_uri(uri):
|
|
158
|
+
return uri.hostname in ("localhost", "127.0.0.1")
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def redirect_uri(self) -> str | None:
|
|
162
|
+
return self._redirect_uri.geturl()
|
|
163
|
+
|
|
127
164
|
@property
|
|
128
165
|
def url(self) -> str:
|
|
129
166
|
return self._uri.geturl()
|
|
@@ -35,6 +35,14 @@ logger = logging.getLogger(__name__)
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class _OAuthTokensMixin:
|
|
38
|
+
"""Manages OAuth token caching to avoid repeated browser authentication flows.
|
|
39
|
+
|
|
40
|
+
Access tokens: Short-lived (typically 10 minutes), cached to avoid immediate re-auth.
|
|
41
|
+
Refresh tokens: Long-lived (hours/days), used to obtain new access tokens silently.
|
|
42
|
+
|
|
43
|
+
Tokens are cached per (user, IDP host) to support multiple OAuth providers/accounts.
|
|
44
|
+
"""
|
|
45
|
+
|
|
38
46
|
def __init__(
|
|
39
47
|
self,
|
|
40
48
|
token_cache: TokenCache | None,
|
|
@@ -77,12 +85,18 @@ class _OAuthTokensMixin:
|
|
|
77
85
|
return self._token_cache.retrieve(key)
|
|
78
86
|
|
|
79
87
|
def _pop_cached_access_token(self) -> bool:
|
|
80
|
-
"""Retrieves OAuth access token from the token cache if enabled
|
|
88
|
+
"""Retrieves OAuth access token from the token cache if enabled, available and still valid.
|
|
89
|
+
|
|
90
|
+
Returns True if cached token found, allowing authentication to skip OAuth flow.
|
|
91
|
+
"""
|
|
81
92
|
self._access_token = self._pop_cached_token(self._get_access_token_cache_key())
|
|
82
93
|
return self._access_token is not None
|
|
83
94
|
|
|
84
95
|
def _pop_cached_refresh_token(self) -> bool:
|
|
85
|
-
"""Retrieves OAuth refresh token from the token cache if enabled
|
|
96
|
+
"""Retrieves OAuth refresh token from the token cache (if enabled) to silently obtain new access token.
|
|
97
|
+
|
|
98
|
+
Returns True if refresh token found, enabling automatic token renewal without user interaction.
|
|
99
|
+
"""
|
|
86
100
|
if self._refresh_token_enabled:
|
|
87
101
|
self._refresh_token = self._pop_cached_token(
|
|
88
102
|
self._get_refresh_token_cache_key()
|
|
@@ -65,6 +65,7 @@ class AuthByOauthCode(AuthByOAuthBase):
|
|
|
65
65
|
external_browser_timeout: int | None = None,
|
|
66
66
|
enable_single_use_refresh_tokens: bool = False,
|
|
67
67
|
connection: SnowflakeConnection | None = None,
|
|
68
|
+
uri: str | None = None,
|
|
68
69
|
**kwargs,
|
|
69
70
|
) -> None:
|
|
70
71
|
authentication_url, redirect_uri = self._validate_oauth_code_uris(
|
|
@@ -92,6 +93,7 @@ class AuthByOauthCode(AuthByOAuthBase):
|
|
|
92
93
|
self._origin: str | None = None
|
|
93
94
|
self._authentication_url = authentication_url
|
|
94
95
|
self._redirect_uri = redirect_uri
|
|
96
|
+
self._uri = uri
|
|
95
97
|
self._state = secrets.token_urlsafe(43)
|
|
96
98
|
logger.debug("chose oauth state: %s", "".join("*" for _ in self._state))
|
|
97
99
|
self._protocol = "http"
|
|
@@ -117,7 +119,10 @@ class AuthByOauthCode(AuthByOAuthBase):
|
|
|
117
119
|
) -> (str | None, str | None):
|
|
118
120
|
"""Web Browser based Authentication."""
|
|
119
121
|
logger.debug("authenticating with OAuth authorization code flow")
|
|
120
|
-
with AuthHttpServer(
|
|
122
|
+
with AuthHttpServer(
|
|
123
|
+
redirect_uri=self._redirect_uri,
|
|
124
|
+
uri=self._uri or self._redirect_uri, # for backward compatibility
|
|
125
|
+
) as callback_server:
|
|
121
126
|
code = self._do_authorization_request(callback_server, conn)
|
|
122
127
|
return self._do_token_request(code, callback_server, conn)
|
|
123
128
|
|
|
@@ -260,7 +265,7 @@ You can close this window now and go back where you started from.
|
|
|
260
265
|
connection: SnowflakeConnection,
|
|
261
266
|
) -> str | None:
|
|
262
267
|
authorization_request = self._construct_authorization_request(
|
|
263
|
-
callback_server.
|
|
268
|
+
callback_server.redirect_uri
|
|
264
269
|
)
|
|
265
270
|
logger.debug("step 1: going to open authorization URL")
|
|
266
271
|
print(
|
|
@@ -315,7 +320,7 @@ You can close this window now and go back where you started from.
|
|
|
315
320
|
fields = {
|
|
316
321
|
"grant_type": "authorization_code",
|
|
317
322
|
"code": code,
|
|
318
|
-
"redirect_uri": callback_server.
|
|
323
|
+
"redirect_uri": callback_server.redirect_uri,
|
|
319
324
|
}
|
|
320
325
|
if self._enable_single_use_refresh_tokens:
|
|
321
326
|
fields["enable_single_use_refresh_tokens"] = "true"
|
|
@@ -27,6 +27,7 @@ class AuthByOauthCredentials(AuthByOAuthBase):
|
|
|
27
27
|
token_request_url: str,
|
|
28
28
|
scope: str,
|
|
29
29
|
connection: SnowflakeConnection | None = None,
|
|
30
|
+
credentials_in_body: bool = False,
|
|
30
31
|
**kwargs,
|
|
31
32
|
) -> None:
|
|
32
33
|
self._validate_client_credentials_present(client_id, client_secret, connection)
|
|
@@ -40,6 +41,7 @@ class AuthByOauthCredentials(AuthByOAuthBase):
|
|
|
40
41
|
**kwargs,
|
|
41
42
|
)
|
|
42
43
|
self._application = application
|
|
44
|
+
self._credentials_in_body = credentials_in_body
|
|
43
45
|
self._origin: str | None = None
|
|
44
46
|
|
|
45
47
|
def _get_oauth_type_id(self) -> str:
|
|
@@ -60,4 +62,7 @@ class AuthByOauthCredentials(AuthByOAuthBase):
|
|
|
60
62
|
"grant_type": "client_credentials",
|
|
61
63
|
"scope": self._scope,
|
|
62
64
|
}
|
|
65
|
+
if self._credentials_in_body:
|
|
66
|
+
fields["client_id"] = self._client_id
|
|
67
|
+
fields["client_secret"] = self._client_secret
|
|
63
68
|
return self._get_request_token_response(conn, fields)
|
|
@@ -165,15 +165,26 @@ class AuthByWebBrowser(AuthByPlugin):
|
|
|
165
165
|
return
|
|
166
166
|
|
|
167
167
|
print(
|
|
168
|
-
"Initiating login request with your identity provider.
|
|
169
|
-
"browser window should have opened for you to complete the "
|
|
170
|
-
"login. If you can't see it, check existing browser windows, "
|
|
171
|
-
"or your OS settings. Press CTRL+C to abort and try again..."
|
|
168
|
+
"Initiating login request with your identity provider. Press CTRL+C to abort and try again..."
|
|
172
169
|
)
|
|
173
170
|
|
|
174
171
|
logger.debug("step 2: open a browser")
|
|
175
172
|
print(f"Going to open: {sso_url} to authenticate...")
|
|
176
|
-
|
|
173
|
+
browser_opened = self._webbrowser.open_new(sso_url)
|
|
174
|
+
if browser_opened:
|
|
175
|
+
print(
|
|
176
|
+
"A browser window should have opened for you to complete the "
|
|
177
|
+
"login. If you can't see it, check existing browser windows, "
|
|
178
|
+
"or your OS settings."
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
browser_opened
|
|
183
|
+
or os.getenv("SNOWFLAKE_AUTH_FORCE_SERVER", "False").lower() == "true"
|
|
184
|
+
):
|
|
185
|
+
logger.debug("step 3: accept SAML token")
|
|
186
|
+
self._receive_saml_token(conn, socket_connection)
|
|
187
|
+
else:
|
|
177
188
|
print(
|
|
178
189
|
"We were unable to open a browser window for you, "
|
|
179
190
|
"please open the url above manually then paste the "
|
|
@@ -195,9 +206,6 @@ class AuthByWebBrowser(AuthByPlugin):
|
|
|
195
206
|
},
|
|
196
207
|
)
|
|
197
208
|
return
|
|
198
|
-
else:
|
|
199
|
-
logger.debug("step 3: accept SAML token")
|
|
200
|
-
self._receive_saml_token(conn, socket_connection)
|
|
201
209
|
finally:
|
|
202
210
|
socket_connection.close()
|
|
203
211
|
|
|
@@ -460,6 +468,7 @@ You can close this window now and go back where you started from.
|
|
|
460
468
|
conn._internal_application_name,
|
|
461
469
|
conn._internal_application_version,
|
|
462
470
|
conn._ocsp_mode(),
|
|
471
|
+
conn.cert_revocation_check_mode,
|
|
463
472
|
conn.login_timeout,
|
|
464
473
|
conn.network_timeout,
|
|
465
474
|
conn.socket_timeout,
|
|
@@ -55,12 +55,14 @@ class AuthByWorkloadIdentity(AuthByPlugin):
|
|
|
55
55
|
provider: AttestationProvider | None = None,
|
|
56
56
|
token: str | None = None,
|
|
57
57
|
entra_resource: str | None = None,
|
|
58
|
+
impersonation_path: list[str] | None = None,
|
|
58
59
|
**kwargs,
|
|
59
60
|
) -> None:
|
|
60
61
|
super().__init__(**kwargs)
|
|
61
62
|
self.provider = provider
|
|
62
63
|
self.token = token
|
|
63
64
|
self.entra_resource = entra_resource
|
|
65
|
+
self.impersonation_path = impersonation_path
|
|
64
66
|
|
|
65
67
|
self.attestation: WorkloadIdentityAttestation | None = None
|
|
66
68
|
|
|
@@ -76,6 +78,9 @@ class AuthByWorkloadIdentity(AuthByPlugin):
|
|
|
76
78
|
self.attestation
|
|
77
79
|
).value
|
|
78
80
|
body["data"]["TOKEN"] = self.attestation.credential
|
|
81
|
+
body["data"].setdefault("CLIENT_ENVIRONMENT", {})[
|
|
82
|
+
"WORKLOAD_IDENTITY_IMPERSONATION_PATH_LENGTH"
|
|
83
|
+
] = len(self.impersonation_path or [])
|
|
79
84
|
|
|
80
85
|
def prepare(
|
|
81
86
|
self, *, conn: SnowflakeConnection | None, **kwargs: typing.Any
|
|
@@ -85,6 +90,7 @@ class AuthByWorkloadIdentity(AuthByPlugin):
|
|
|
85
90
|
self.provider,
|
|
86
91
|
self.entra_resource,
|
|
87
92
|
self.token,
|
|
93
|
+
self.impersonation_path,
|
|
88
94
|
session_manager=(
|
|
89
95
|
conn._session_manager.clone(max_retries=0) if conn else None
|
|
90
96
|
),
|