snowflake-connector-python 4.4.0__tar.gz → 4.5.0__tar.gz

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