snowflake-connector-python 4.0.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.
Files changed (261) hide show
  1. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/DESCRIPTION.md +10 -1
  2. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/PKG-INFO +19 -10
  3. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/setup.cfg +8 -8
  4. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/_auth.py +30 -2
  5. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/_http_server.py +44 -7
  6. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/_oauth_base.py +16 -2
  7. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/oauth_code.py +8 -3
  8. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/webbrowser.py +16 -8
  9. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/azure_storage_client.py +4 -4
  10. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/connection.py +105 -4
  11. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/connection_diagnostic.py +2 -2
  12. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/constants.py +3 -0
  13. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/crl.py +158 -67
  14. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +2 -0
  15. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/network.py +12 -5
  16. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ocsp_snowflake.py +5 -4
  17. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/pandas_tools.py +1 -1
  18. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/platform_detection.py +153 -65
  19. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/result_batch.py +11 -5
  20. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/session_manager.py +119 -48
  21. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ssl_wrap_socket.py +7 -3
  22. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/storage_client.py +5 -3
  23. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/telemetry.py +4 -4
  24. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/telemetry_oob.py +1 -1
  25. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/token_cache.py +37 -0
  26. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/util_text.py +4 -2
  27. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/version.py +1 -1
  28. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/wif_util.py +2 -2
  29. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/PKG-INFO +19 -10
  30. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/requires.txt +8 -8
  31. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/CONTRIBUTING.md +0 -0
  32. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/LICENSE.txt +0 -0
  33. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/MANIFEST.in +0 -0
  34. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/NOTICE +0 -0
  35. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/README.md +0 -0
  36. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/SECURITY.md +0 -0
  37. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/pyproject.toml +0 -0
  38. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/setup.py +0 -0
  39. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/__init__.py +0 -0
  40. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/_query_context_cache.py +0 -0
  41. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/_sql_util.py +0 -0
  42. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/_utils.py +0 -0
  43. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/arrow_context.py +0 -0
  44. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/__init__.py +0 -0
  45. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/by_plugin.py +0 -0
  46. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/default.py +0 -0
  47. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/idtoken.py +0 -0
  48. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/keypair.py +0 -0
  49. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/no_auth.py +0 -0
  50. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/oauth.py +0 -0
  51. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/oauth_credentials.py +0 -0
  52. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/okta.py +0 -0
  53. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/pat.py +0 -0
  54. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/usrpwdmfa.py +0 -0
  55. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/auth/workload_identity.py +0 -0
  56. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/backoff_policies.py +0 -0
  57. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/bind_upload_agent.py +0 -0
  58. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/cache.py +0 -0
  59. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/compat.py +0 -0
  60. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/config_manager.py +0 -0
  61. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter.py +0 -0
  62. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter_issue23517.py +0 -0
  63. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter_null.py +0 -0
  64. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/converter_snowsql.py +0 -0
  65. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/crl_cache.py +0 -0
  66. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/cursor.py +0 -0
  67. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/dbapi.py +0 -0
  68. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/description.py +0 -0
  69. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/direct_file_operation_utils.py +0 -0
  70. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/encryption_util.py +0 -0
  71. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/errorcode.py +0 -0
  72. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/errors.py +0 -0
  73. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/externals_utils/__init__.py +0 -0
  74. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/externals_utils/externals_setup.py +0 -0
  75. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/feature.py +0 -0
  76. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_compression_type.py +0 -0
  77. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_lock.py +0 -0
  78. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_transfer_agent.py +0 -0
  79. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/file_util.py +0 -0
  80. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/gcs_storage_client.py +0 -0
  81. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/gzip_decoder.py +0 -0
  82. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/interval_util.py +0 -0
  83. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/local_storage_client.py +0 -0
  84. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/log_configuration.py +0 -0
  85. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/logging_utils/__init__.py +0 -0
  86. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/logging_utils/filters.py +0 -0
  87. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +0 -0
  88. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +0 -0
  89. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +0 -0
  90. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +0 -0
  91. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +0 -0
  92. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +0 -0
  93. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +0 -0
  94. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +0 -0
  95. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +0 -0
  96. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +0 -0
  97. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +0 -0
  98. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +0 -0
  99. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +0 -0
  100. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +0 -0
  101. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +0 -0
  102. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +0 -0
  103. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +0 -0
  104. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +0 -0
  105. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +0 -0
  106. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +0 -0
  107. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +0 -0
  108. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +0 -0
  109. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +0 -0
  110. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +0 -0
  111. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +0 -0
  112. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +0 -0
  113. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +0 -0
  114. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +0 -0
  115. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +0 -0
  116. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +0 -0
  117. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +0 -0
  118. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +0 -0
  119. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +0 -0
  120. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +0 -0
  121. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +0 -0
  122. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +0 -0
  123. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +0 -0
  124. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +0 -0
  125. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +0 -0
  126. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +0 -0
  127. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +0 -0
  128. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +0 -0
  129. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +0 -0
  130. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +0 -0
  131. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +0 -0
  132. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +0 -0
  133. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +0 -0
  134. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +0 -0
  135. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +0 -0
  136. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +0 -0
  137. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +0 -0
  138. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +0 -0
  139. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +0 -0
  140. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +0 -0
  141. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +0 -0
  142. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +0 -0
  143. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +0 -0
  144. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +0 -0
  145. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +0 -0
  146. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +0 -0
  147. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +0 -0
  148. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +0 -0
  149. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +0 -0
  150. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +0 -0
  151. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +0 -0
  152. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +0 -0
  153. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +0 -0
  154. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +0 -0
  155. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +0 -0
  156. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +0 -0
  157. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +0 -0
  158. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +0 -0
  159. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +0 -0
  160. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +0 -0
  161. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +0 -0
  162. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +0 -0
  163. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +0 -0
  164. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +0 -0
  165. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +0 -0
  166. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +0 -0
  167. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +0 -0
  168. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +0 -0
  169. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +0 -0
  170. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +0 -0
  171. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +0 -0
  172. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +0 -0
  173. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +0 -0
  174. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +0 -0
  175. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +0 -0
  176. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +0 -0
  177. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ocsp_asn1crypto.py +0 -0
  178. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/options.py +0 -0
  179. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/proxy.py +0 -0
  180. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/py.typed +0 -0
  181. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/result_set.py +0 -0
  182. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/s3_storage_client.py +0 -0
  183. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/secret_detector.py +0 -0
  184. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sf_dirs.py +0 -0
  185. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sfbinaryformat.py +0 -0
  186. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sfdatetime.py +0 -0
  187. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/snow_logging.py +0 -0
  188. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/sqlstate.py +0 -0
  189. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/ssd_internal_keys.py +0 -0
  190. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/test_util.py +0 -0
  191. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/time_util.py +0 -0
  192. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/__init__.py +0 -0
  193. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/dump_certs.py +0 -0
  194. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/dump_ocsp_response.py +0 -0
  195. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/dump_ocsp_response_cache.py +0 -0
  196. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/tool/probe_connection.py +0 -0
  197. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/url_util.py +0 -0
  198. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/__init__.py +0 -0
  199. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/LICENSE +0 -0
  200. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/__init__.py +0 -0
  201. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/__version__.py +0 -0
  202. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/_internal_utils.py +0 -0
  203. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/adapters.py +0 -0
  204. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/api.py +0 -0
  205. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/auth.py +0 -0
  206. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/certs.py +0 -0
  207. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/compat.py +0 -0
  208. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/cookies.py +0 -0
  209. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/exceptions.py +0 -0
  210. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/help.py +0 -0
  211. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/hooks.py +0 -0
  212. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/models.py +0 -0
  213. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/packages.py +0 -0
  214. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/sessions.py +0 -0
  215. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/status_codes.py +0 -0
  216. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/structures.py +0 -0
  217. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/requests/utils.py +0 -0
  218. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/LICENSE.txt +0 -0
  219. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/__init__.py +0 -0
  220. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_base_connection.py +0 -0
  221. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_collections.py +0 -0
  222. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_request_methods.py +0 -0
  223. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/_version.py +0 -0
  224. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/connection.py +0 -0
  225. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/connectionpool.py +0 -0
  226. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
  227. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/__init__.py +0 -0
  228. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/connection.py +0 -0
  229. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/emscripten_fetch_worker.js +0 -0
  230. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/fetch.py +0 -0
  231. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/request.py +0 -0
  232. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/emscripten/response.py +0 -0
  233. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +0 -0
  234. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/contrib/socks.py +0 -0
  235. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/exceptions.py +0 -0
  236. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/fields.py +0 -0
  237. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/filepost.py +0 -0
  238. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/http2/__init__.py +0 -0
  239. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/http2/connection.py +0 -0
  240. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/http2/probe.py +0 -0
  241. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/poolmanager.py +0 -0
  242. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/py.typed +0 -0
  243. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/response.py +0 -0
  244. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/__init__.py +0 -0
  245. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/connection.py +0 -0
  246. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/proxy.py +0 -0
  247. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/request.py +0 -0
  248. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/response.py +0 -0
  249. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/retry.py +0 -0
  250. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/ssl_.py +0 -0
  251. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +0 -0
  252. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/ssltransport.py +0 -0
  253. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/timeout.py +0 -0
  254. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/url.py +0 -0
  255. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/util.py +0 -0
  256. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake/connector/vendored/urllib3/util/wait.py +0 -0
  257. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/SOURCES.txt +0 -0
  258. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/dependency_links.txt +0 -0
  259. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/entry_points.txt +0 -0
  260. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/not-zip-safe +0 -0
  261. {snowflake_connector_python-4.0.0 → snowflake_connector_python-4.1.0}/src/snowflake_connector_python.egg-info/top_level.txt +0 -0
@@ -7,7 +7,16 @@ https://docs.snowflake.com/
7
7
  Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
8
8
 
9
9
  # Release Notes
10
- - v4.1.0(TBD)
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.
11
20
 
12
21
  - v4.0.0(October 09,2025)
13
22
  - Added support for checking certificates revocation using revocation lists (CRLs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: snowflake-connector-python
3
- Version: 4.0.0
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,16 +39,16 @@ 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: cryptography>=3.1.0
43
- Requires-Dist: pyOpenSSL<26.0.0,>=22.0.0
44
- 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
45
45
  Requires-Dist: pytz
46
- Requires-Dist: requests<3.0.0
46
+ Requires-Dist: requests<3.0.0,>=2.32.4
47
47
  Requires-Dist: packaging
48
48
  Requires-Dist: charset_normalizer<4,>=2
49
- Requires-Dist: idna<4,>=2.5
50
- Requires-Dist: urllib3<2.0.0,>=1.21.1; python_version < "3.10"
51
- Requires-Dist: certifi>=2017.4.17
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
52
52
  Requires-Dist: typing_extensions<5,>=4.3
53
53
  Requires-Dist: filelock<4,>=3.5
54
54
  Requires-Dist: sortedcontainers>=2.4.0
@@ -75,7 +75,7 @@ Requires-Dist: pytzdata; extra == "development"
75
75
  Requires-Dist: responses; extra == "development"
76
76
  Provides-Extra: pandas
77
77
  Requires-Dist: pandas<3.0.0,>=2.1.2; extra == "pandas"
78
- Requires-Dist: pyarrow; extra == "pandas"
78
+ Requires-Dist: pyarrow>=14.0.1; extra == "pandas"
79
79
  Provides-Extra: secure-local-storage
80
80
  Requires-Dist: keyring<26.0.0,>=23.1.0; extra == "secure-local-storage"
81
81
  Dynamic: license-file
@@ -90,7 +90,16 @@ https://docs.snowflake.com/
90
90
  Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
91
91
 
92
92
  # Release Notes
93
- - v4.1.0(TBD)
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.
94
103
 
95
104
  - v4.0.0(October 09,2025)
96
105
  - Added support for checking certificates revocation using revocation lists (CRLs)
@@ -44,16 +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
- cryptography>=3.1.0
48
- pyOpenSSL>=22.0.0,<26.0.0
49
- 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
50
50
  pytz
51
- requests<3.0.0
51
+ requests>=2.32.4,<3.0.0
52
52
  packaging
53
53
  charset_normalizer>=2,<4
54
- idna>=2.5,<4
55
- urllib3>=1.21.1,<2.0.0; python_version < '3.10'
56
- certifi>=2017.4.17
54
+ idna>=3.7,<4
55
+ urllib3>=1.26.5,<2.0.0; python_version < '3.10'
56
+ certifi>=2024.7.4
57
57
  typing_extensions>=4.3,<5
58
58
  filelock>=3.5,<4
59
59
  sortedcontainers>=2.4.0
@@ -95,7 +95,7 @@ development =
95
95
  responses
96
96
  pandas =
97
97
  pandas>=2.1.2,<3.0.0
98
- pyarrow
98
+ pyarrow>=14.0.1
99
99
  secure-local-storage =
100
100
  keyring>=23.1.0,<26.0.0
101
101
 
@@ -53,7 +53,9 @@ from ..network import (
53
53
  ReauthenticationRequest,
54
54
  )
55
55
  from ..platform_detection import detect_platforms
56
- from ..session_manager import SessionManager
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
@@ -106,8 +108,17 @@ class Auth:
106
108
  network_timeout: int | None = None,
107
109
  socket_timeout: int | None = None,
108
110
  platform_detection_timeout_seconds: float | None = None,
109
- session_manager: SessionManager | None = None,
111
+ session_manager: SyncSessionManager | None = None,
112
+ http_config: BaseHttpConfig | None = None,
110
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
+
111
122
  return {
112
123
  "data": {
113
124
  "CLIENT_APP_ID": internal_application_name,
@@ -503,6 +514,16 @@ class Auth:
503
514
  user: str,
504
515
  session_parameters: dict[str, Any],
505
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
+ """
506
527
  if session_parameters.get(PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL, False):
507
528
  self._rest.id_token = self._read_temporary_credential(
508
529
  host,
@@ -538,6 +559,13 @@ class Auth:
538
559
  session_parameters: dict[str, Any],
539
560
  response: dict[str, Any],
540
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
+ """
541
569
  if (
542
570
  self._rest._connection.auth_class.consent_cache_id_token
543
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
- port = parsed_uri.port or 0
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
- port,
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 {port}: {ex}"
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 {port}: {ex}"
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 {port}: {ex}"
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
- port = self._socket.getsockname()[1]
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(port),
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(self._redirect_uri) as callback_server:
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.url
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.url,
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"
@@ -165,15 +165,26 @@ class AuthByWebBrowser(AuthByPlugin):
165
165
  return
166
166
 
167
167
  print(
168
- "Initiating login request with your identity provider. A "
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
- if not self._webbrowser.open_new(sso_url):
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
 
@@ -14,7 +14,7 @@ from .compat import quote
14
14
  from .constants import FileHeader, ResultStatus
15
15
  from .encryption_util import EncryptionMetadata
16
16
  from .storage_client import SnowflakeStorageClient
17
- from .util_text import get_md5
17
+ from .util_text import get_md5_for_integrity
18
18
  from .vendored import requests
19
19
 
20
20
  if TYPE_CHECKING: # pragma: no cover
@@ -241,9 +241,9 @@ class SnowflakeAzureRestClient(SnowflakeStorageClient):
241
241
  fd.close()
242
242
  headers = {
243
243
  "x-ms-blob-content-encoding": "utf-8",
244
- "x-ms-blob-content-md5": base64.b64encode(get_md5(file_content)).decode(
245
- "utf-8"
246
- ),
244
+ "x-ms-blob-content-md5": base64.b64encode(
245
+ get_md5_for_integrity(file_content)
246
+ ).decode("utf-8"),
247
247
  }
248
248
  azure_metadata = self._prepare_file_metadata()
249
249
  headers.update(azure_metadata)
@@ -88,6 +88,7 @@ from .constants import (
88
88
  )
89
89
  from .converter import SnowflakeConverter
90
90
  from .crl import CRLConfig
91
+ from .crl_cache import CRLCacheFactory
91
92
  from .cursor import LOG_MAX_QUERY_LENGTH, SnowflakeCursor, SnowflakeCursorBase
92
93
  from .description import (
93
94
  CLIENT_NAME,
@@ -129,7 +130,12 @@ from .network import (
129
130
  ReauthenticationRequest,
130
131
  SnowflakeRestful,
131
132
  )
132
- from .session_manager import HttpConfig, ProxySupportAdapterFactory, SessionManager
133
+ from .session_manager import (
134
+ HttpConfig,
135
+ ProxySupportAdapterFactory,
136
+ SessionManager,
137
+ SessionManagerFactory,
138
+ )
133
139
  from .sqlstate import SQLSTATE_CONNECTION_NOT_EXISTS, SQLSTATE_FEATURE_NOT_SUPPORTED
134
140
  from .telemetry import TelemetryClient, TelemetryData, TelemetryField
135
141
  from .time_util import HeartBeatTimer, get_time_millis
@@ -199,6 +205,10 @@ DEFAULT_CONFIGURATION: dict[str, tuple[Any, type | tuple[type, ...]]] = {
199
205
  "proxy_port": (None, (type(None), str)), # snowflake
200
206
  "proxy_user": (None, (type(None), str)), # snowflake
201
207
  "proxy_password": (None, (type(None), str)), # snowflake
208
+ "no_proxy": (
209
+ None,
210
+ (type(None), str, Iterable),
211
+ ), # hosts/ips to bypass proxy (str or iterable)
202
212
  "protocol": ("https", str), # snowflake
203
213
  "warehouse": (None, (type(None), str)), # snowflake
204
214
  "region": (None, (type(None), str)), # snowflake
@@ -271,8 +281,13 @@ DEFAULT_CONFIGURATION: dict[str, tuple[Any, type | tuple[type, ...]]] = {
271
281
  "support_negative_year": (True, bool), # snowflake
272
282
  "log_max_query_length": (LOG_MAX_QUERY_LENGTH, int), # snowflake
273
283
  "disable_request_pooling": (False, bool), # snowflake
274
- # enable temporary credential file for Linux, default false. Mac/Win will overlook this
284
+ # Cache SSO ID tokens to avoid repeated browser popups. Must be enabled on the server-side.
285
+ # Storage: keyring (macOS/Windows), file (Linux). Auto-enabled on macOS/Windows.
286
+ # Sets session PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL as well
275
287
  "client_store_temporary_credential": (False, bool),
288
+ # Cache MFA tokens to skip MFA prompts on reconnect. Must be enabled on the server-side.
289
+ # Storage: keyring (macOS/Windows), file (Linux). Auto-enabled on macOS/Windows.
290
+ # In driver, we extract this from session using PARAMETER_CLIENT_REQUEST_MFA_TOKEN.
276
291
  "client_request_mfa_token": (False, bool),
277
292
  "use_openssl_only": (
278
293
  True,
@@ -375,6 +390,11 @@ DEFAULT_CONFIGURATION: dict[str, tuple[Any, type | tuple[type, ...]]] = {
375
390
  # SNOW-1825621: OAUTH implementation
376
391
  ),
377
392
  "oauth_redirect_uri": ("http://127.0.0.1", str),
393
+ "oauth_socket_uri": (
394
+ "http://127.0.0.1",
395
+ str,
396
+ # SNOW-2194055: Separate server and redirect URIs in AuthHttpServer
397
+ ),
378
398
  "oauth_scope": (
379
399
  "",
380
400
  str,
@@ -808,6 +828,10 @@ class SnowflakeConnection:
808
828
  def proxy_password(self) -> str | None:
809
829
  return self._proxy_password
810
830
 
831
+ @property
832
+ def no_proxy(self) -> str | Iterable | None:
833
+ return self._no_proxy
834
+
811
835
  @property
812
836
  def account(self) -> str:
813
837
  return self._account
@@ -1069,6 +1093,15 @@ class SnowflakeConnection:
1069
1093
 
1070
1094
  self._crl_config: CRLConfig = CRLConfig.from_connection(self)
1071
1095
 
1096
+ no_proxy_csv_str = (
1097
+ ",".join(str(x) for x in self.no_proxy)
1098
+ if (
1099
+ self.no_proxy is not None
1100
+ and isinstance(self.no_proxy, Iterable)
1101
+ and not isinstance(self.no_proxy, (str, bytes))
1102
+ )
1103
+ else self.no_proxy
1104
+ )
1072
1105
  self._http_config = HttpConfig(
1073
1106
  adapter_factory=ProxySupportAdapterFactory(),
1074
1107
  use_pooling=(not self.disable_request_pooling),
@@ -1076,8 +1109,9 @@ class SnowflakeConnection:
1076
1109
  proxy_port=self.proxy_port,
1077
1110
  proxy_user=self.proxy_user,
1078
1111
  proxy_password=self.proxy_password,
1112
+ no_proxy=no_proxy_csv_str,
1079
1113
  )
1080
- self._session_manager = SessionManager(self._http_config)
1114
+ self._session_manager = SessionManagerFactory.get_manager(self._http_config)
1081
1115
 
1082
1116
  if self.enable_connection_diag:
1083
1117
  exceptions_dict = {}
@@ -1119,11 +1153,17 @@ class SnowflakeConnection:
1119
1153
  else:
1120
1154
  self.__open_connection()
1121
1155
 
1156
+ # Register the connection in the pool after successful connection
1157
+ _connections_registry.add_connection(self)
1158
+
1122
1159
  def close(self, retry: bool = True) -> None:
1123
1160
  """Closes the connection."""
1124
1161
  # unregister to dereference connection object as it's already closed after the execution
1125
1162
  atexit.unregister(self._close_at_exit)
1126
1163
  try:
1164
+ # Remove connection from the pool
1165
+ _connections_registry.remove_connection(self)
1166
+
1127
1167
  if not self.rest:
1128
1168
  logger.debug("Rest object has been destroyed, cannot close session")
1129
1169
  return
@@ -1135,7 +1175,8 @@ class SnowflakeConnection:
1135
1175
 
1136
1176
  # close telemetry first, since it needs rest to send remaining data
1137
1177
  logger.debug("closed")
1138
- self._telemetry.close(send_on_close=bool(retry and self.telemetry_enabled))
1178
+ if self.telemetry_enabled:
1179
+ self._telemetry.close(retry=retry)
1139
1180
  if (
1140
1181
  self._all_async_queries_finished()
1141
1182
  and not self._server_session_keep_alive
@@ -1368,9 +1409,11 @@ class SnowflakeConnection:
1368
1409
  backoff_generator=self._backoff_generator,
1369
1410
  )
1370
1411
  elif self._authenticator == EXTERNAL_BROWSER_AUTHENTICATOR:
1412
+ # Enable SSO credential caching
1371
1413
  self._session_parameters[
1372
1414
  PARAMETER_CLIENT_STORE_TEMPORARY_CREDENTIAL
1373
1415
  ] = (self._client_store_temporary_credential if IS_LINUX else True)
1416
+ # Try to load cached ID token to avoid browser popup
1374
1417
  auth.read_temporary_credentials(
1375
1418
  self.host,
1376
1419
  self.user,
@@ -1434,6 +1477,7 @@ class SnowflakeConnection:
1434
1477
  host=self.host, port=self.port
1435
1478
  ),
1436
1479
  redirect_uri=self._oauth_redirect_uri,
1480
+ uri=self._oauth_socket_uri,
1437
1481
  scope=self._oauth_scope,
1438
1482
  pkce_enabled=not self._oauth_disable_pkce,
1439
1483
  token_cache=(
@@ -1461,9 +1505,11 @@ class SnowflakeConnection:
1461
1505
  connection=self,
1462
1506
  )
1463
1507
  elif self._authenticator == USR_PWD_MFA_AUTHENTICATOR:
1508
+ # Enable MFA token caching
1464
1509
  self._session_parameters[PARAMETER_CLIENT_REQUEST_MFA_TOKEN] = (
1465
1510
  self._client_request_mfa_token if IS_LINUX else True
1466
1511
  )
1512
+ # Try to load cached MFA token to skip MFA prompt
1467
1513
  if self._session_parameters[PARAMETER_CLIENT_REQUEST_MFA_TOKEN]:
1468
1514
  auth.read_temporary_credentials(
1469
1515
  self.host,
@@ -1672,6 +1718,8 @@ class SnowflakeConnection:
1672
1718
  WORKLOAD_IDENTITY_AUTHENTICATOR,
1673
1719
  PROGRAMMATIC_ACCESS_TOKEN,
1674
1720
  PAT_WITH_EXTERNAL_SESSION,
1721
+ OAUTH_AUTHORIZATION_CODE,
1722
+ OAUTH_CLIENT_CREDENTIALS,
1675
1723
  }
1676
1724
 
1677
1725
  if not (self._master_token and self._session_token):
@@ -2492,3 +2540,56 @@ class SnowflakeConnection:
2492
2540
  return "jupyter_notebook"
2493
2541
  if "snowbooks" in sys.modules:
2494
2542
  return "snowflake_notebook"
2543
+
2544
+
2545
+ class _ConnectionsRegistry:
2546
+ """Thread-safe registry for tracking opened SnowflakeConnection instances.
2547
+
2548
+ This class maintains a registry of active connections using weak references
2549
+ to avoid preventing garbage collection.
2550
+ """
2551
+
2552
+ def __init__(self):
2553
+ """Initialize the connections registry with an empty registry and a lock."""
2554
+ self._connections: weakref.WeakSet = weakref.WeakSet()
2555
+ self._lock = Lock()
2556
+
2557
+ def add_connection(self, connection: SnowflakeConnection) -> None:
2558
+ """Add a connection to the registry.
2559
+
2560
+ Args:
2561
+ connection: The SnowflakeConnection instance to register.
2562
+ """
2563
+ with self._lock:
2564
+ self._connections.add(connection)
2565
+ logger.debug(
2566
+ f"Connection {id(connection)} added to pool. Total connections: {len(self._connections)}"
2567
+ )
2568
+
2569
+ def remove_connection(self, connection: SnowflakeConnection) -> None:
2570
+ """Remove a connection from the registry.
2571
+
2572
+ Args:
2573
+ connection: The SnowflakeConnection instance to unregister.
2574
+ """
2575
+ with self._lock:
2576
+ self._connections.discard(connection)
2577
+ logger.debug(
2578
+ f"Connection {id(connection)} removed from registry. Total connections: {len(self._connections)}"
2579
+ )
2580
+
2581
+ if len(self._connections) == 0:
2582
+ self._last_connection_handler()
2583
+
2584
+ def _last_connection_handler(self):
2585
+ # If no connections left then stop CRL background task
2586
+ # to avoid script dangling
2587
+ CRLCacheFactory.stop_periodic_cleanup()
2588
+
2589
+ def get_connection_count(self) -> int:
2590
+ with self._lock:
2591
+ return len(self._connections)
2592
+
2593
+
2594
+ # Global instance of the connections pool
2595
+ _connections_registry = _ConnectionsRegistry()
@@ -19,7 +19,7 @@ import OpenSSL
19
19
 
20
20
  from .compat import IS_WINDOWS, urlparse
21
21
  from .cursor import SnowflakeCursor
22
- from .session_manager import SessionManager
22
+ from .session_manager import SessionManager, SessionManagerFactory
23
23
  from .url_util import extract_top_level_domain_from_hostname
24
24
  from .vendored import urllib3
25
25
 
@@ -197,7 +197,7 @@ class ConnectionDiagnostic:
197
197
  self._session_manager = (
198
198
  session_manager.clone(use_pooling=False)
199
199
  if session_manager
200
- else SessionManager(use_pooling=False)
200
+ else SessionManagerFactory.get_manager(use_pooling=False)
201
201
  )
202
202
 
203
203
  def __parse_proxy(self, proxy_url: str) -> tuple[str, str, str, str]:
@@ -441,7 +441,10 @@ DAY_IN_SECONDS = 60 * 60 * 24
441
441
  # TODO: all env variables definitions should be here
442
442
  ENV_VAR_PARTNER = "SF_PARTNER"
443
443
  ENV_VAR_TEST_MODE = "SNOWFLAKE_TEST_MODE"
444
+ ENV_VAR_DISABLE_PLATFORM_DETECTION = "SNOWFLAKE_DISABLE_PLATFORM_DETECTION"
444
445
 
446
+ # Boolean positive values (lowercased) for environment variable checks
447
+ ENV_VAR_BOOL_POSITIVE_VALUES_LOWERCASED = ["true"]
445
448
 
446
449
  _DOMAIN_NAME_MAP = {_DEFAULT_HOSTNAME_TLD: "GLOBAL", _CHINA_HOSTNAME_TLD: "CHINA"}
447
450