snowflake-connector-python 4.4.0__cp314-cp314-win_amd64.whl

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/__init__.py +118 -0
  2. snowflake/connector/_query_context_cache.py +276 -0
  3. snowflake/connector/_sql_util.py +48 -0
  4. snowflake/connector/_utils.py +353 -0
  5. snowflake/connector/aio/README.md +88 -0
  6. snowflake/connector/aio/__init__.py +163 -0
  7. snowflake/connector/aio/_azure_storage_client.py +227 -0
  8. snowflake/connector/aio/_bind_upload_agent.py +69 -0
  9. snowflake/connector/aio/_connection.py +1216 -0
  10. snowflake/connector/aio/_cursor.py +1402 -0
  11. snowflake/connector/aio/_description.py +5 -0
  12. snowflake/connector/aio/_direct_file_operation_utils.py +88 -0
  13. snowflake/connector/aio/_file_transfer_agent.py +316 -0
  14. snowflake/connector/aio/_gcs_storage_client.py +360 -0
  15. snowflake/connector/aio/_network.py +860 -0
  16. snowflake/connector/aio/_ocsp_asn1crypto.py +51 -0
  17. snowflake/connector/aio/_ocsp_snowflake.py +608 -0
  18. snowflake/connector/aio/_pandas_tools.py +561 -0
  19. snowflake/connector/aio/_result_batch.py +442 -0
  20. snowflake/connector/aio/_result_set.py +309 -0
  21. snowflake/connector/aio/_s3_storage_client.py +460 -0
  22. snowflake/connector/aio/_session_manager.py +588 -0
  23. snowflake/connector/aio/_storage_client.py +331 -0
  24. snowflake/connector/aio/_telemetry.py +97 -0
  25. snowflake/connector/aio/_time_util.py +57 -0
  26. snowflake/connector/aio/_wif_util.py +324 -0
  27. snowflake/connector/aio/auth/__init__.py +52 -0
  28. snowflake/connector/aio/auth/_auth.py +406 -0
  29. snowflake/connector/aio/auth/_by_plugin.py +131 -0
  30. snowflake/connector/aio/auth/_default.py +28 -0
  31. snowflake/connector/aio/auth/_idtoken.py +54 -0
  32. snowflake/connector/aio/auth/_keypair.py +60 -0
  33. snowflake/connector/aio/auth/_no_auth.py +31 -0
  34. snowflake/connector/aio/auth/_oauth.py +27 -0
  35. snowflake/connector/aio/auth/_oauth_code.py +117 -0
  36. snowflake/connector/aio/auth/_oauth_credentials.py +100 -0
  37. snowflake/connector/aio/auth/_okta.py +247 -0
  38. snowflake/connector/aio/auth/_pat.py +27 -0
  39. snowflake/connector/aio/auth/_usrpwdmfa.py +30 -0
  40. snowflake/connector/aio/auth/_webbrowser.py +405 -0
  41. snowflake/connector/aio/auth/_workload_identity.py +60 -0
  42. snowflake/connector/arrow_context.py +211 -0
  43. snowflake/connector/auth/__init__.py +53 -0
  44. snowflake/connector/auth/_auth.py +669 -0
  45. snowflake/connector/auth/_http_server.py +257 -0
  46. snowflake/connector/auth/_oauth_base.py +472 -0
  47. snowflake/connector/auth/by_plugin.py +219 -0
  48. snowflake/connector/auth/default.py +36 -0
  49. snowflake/connector/auth/idtoken.py +72 -0
  50. snowflake/connector/auth/keypair.py +225 -0
  51. snowflake/connector/auth/no_auth.py +39 -0
  52. snowflake/connector/auth/oauth.py +49 -0
  53. snowflake/connector/auth/oauth_code.py +490 -0
  54. snowflake/connector/auth/oauth_credentials.py +71 -0
  55. snowflake/connector/auth/okta.py +339 -0
  56. snowflake/connector/auth/pat.py +40 -0
  57. snowflake/connector/auth/usrpwdmfa.py +69 -0
  58. snowflake/connector/auth/webbrowser.py +514 -0
  59. snowflake/connector/auth/workload_identity.py +110 -0
  60. snowflake/connector/azure_storage_client.py +278 -0
  61. snowflake/connector/backoff_policies.py +141 -0
  62. snowflake/connector/bind_upload_agent.py +89 -0
  63. snowflake/connector/cache.py +696 -0
  64. snowflake/connector/compat.py +127 -0
  65. snowflake/connector/config_manager.py +553 -0
  66. snowflake/connector/connection.py +2671 -0
  67. snowflake/connector/connection_diagnostic.py +793 -0
  68. snowflake/connector/constants.py +460 -0
  69. snowflake/connector/converter.py +809 -0
  70. snowflake/connector/converter_issue23517.py +87 -0
  71. snowflake/connector/converter_null.py +14 -0
  72. snowflake/connector/converter_snowsql.py +205 -0
  73. snowflake/connector/crl.py +919 -0
  74. snowflake/connector/crl_cache.py +734 -0
  75. snowflake/connector/cursor.py +2099 -0
  76. snowflake/connector/dbapi.py +53 -0
  77. snowflake/connector/description.py +21 -0
  78. snowflake/connector/direct_file_operation_utils.py +88 -0
  79. snowflake/connector/encryption_util.py +220 -0
  80. snowflake/connector/errorcode.py +94 -0
  81. snowflake/connector/errors.py +666 -0
  82. snowflake/connector/externals_utils/__init__.py +0 -0
  83. snowflake/connector/externals_utils/externals_setup.py +30 -0
  84. snowflake/connector/feature.py +4 -0
  85. snowflake/connector/file_compression_type.py +118 -0
  86. snowflake/connector/file_lock.py +72 -0
  87. snowflake/connector/file_transfer_agent.py +1244 -0
  88. snowflake/connector/file_util.py +153 -0
  89. snowflake/connector/gcs_storage_client.py +476 -0
  90. snowflake/connector/gzip_decoder.py +85 -0
  91. snowflake/connector/interval_util.py +26 -0
  92. snowflake/connector/local_storage_client.py +90 -0
  93. snowflake/connector/log_configuration.py +62 -0
  94. snowflake/connector/logging_utils/__init__.py +0 -0
  95. snowflake/connector/logging_utils/filters.py +72 -0
  96. snowflake/connector/minicore/__init__.py +0 -0
  97. snowflake/connector/minicore/aix_ppc64/libsf_mini_core.a +0 -0
  98. snowflake/connector/minicore/aix_ppc64/libsf_mini_core_static.a +0 -0
  99. snowflake/connector/minicore/linux_aarch64_glibc/libsf_mini_core.so +0 -0
  100. snowflake/connector/minicore/linux_aarch64_musl/libsf_mini_core.so +0 -0
  101. snowflake/connector/minicore/linux_x86_64_glibc/libsf_mini_core.so +0 -0
  102. snowflake/connector/minicore/linux_x86_64_musl/libsf_mini_core.so +0 -0
  103. snowflake/connector/minicore/macos_aarch64/libsf_mini_core.dylib +0 -0
  104. snowflake/connector/minicore/macos_x86_64/libsf_mini_core.dylib +0 -0
  105. snowflake/connector/minicore/windows_x86_64/sf_mini_core.dll +0 -0
  106. snowflake/connector/minicore/windows_x86_64/sf_mini_core_static.lib +0 -0
  107. snowflake/connector/nanoarrow_arrow_iterator.cp314-win_amd64.pyd +0 -0
  108. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +60 -0
  109. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
  110. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +19 -0
  111. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
  112. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
  113. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
  114. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +570 -0
  115. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +98 -0
  116. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +125 -0
  117. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +115 -0
  118. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +1140 -0
  119. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +138 -0
  120. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +47 -0
  121. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
  122. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +83 -0
  123. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
  124. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +97 -0
  125. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +72 -0
  126. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +73 -0
  127. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
  128. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +30 -0
  129. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
  130. snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
  131. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
  132. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +45 -0
  133. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +75 -0
  134. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +57 -0
  135. snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  136. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +75 -0
  137. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
  138. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +46 -0
  139. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
  140. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
  141. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +95 -0
  142. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +57 -0
  143. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +36 -0
  144. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
  145. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  146. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +19 -0
  147. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
  148. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +36 -0
  149. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
  150. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +346 -0
  151. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +145 -0
  152. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
  153. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +67 -0
  154. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
  155. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
  156. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
  157. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  158. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
  159. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
  160. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
  161. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  162. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
  163. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
  164. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  165. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  166. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  167. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
  168. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
  169. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
  170. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  171. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
  172. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
  173. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
  174. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  175. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  176. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
  177. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
  178. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  179. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  180. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  181. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  182. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  183. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
  184. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
  185. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
  186. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  187. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  188. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
  189. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
  190. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
  191. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
  192. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +262 -0
  193. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
  194. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
  195. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33273 -0
  196. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
  197. snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +100 -0
  198. snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +49 -0
  199. snowflake/connector/network.py +1227 -0
  200. snowflake/connector/ocsp_asn1crypto.py +447 -0
  201. snowflake/connector/ocsp_snowflake.py +1939 -0
  202. snowflake/connector/options.py +179 -0
  203. snowflake/connector/os_details.py +88 -0
  204. snowflake/connector/pandas_tools.py +734 -0
  205. snowflake/connector/platform_detection.py +555 -0
  206. snowflake/connector/proxy.py +28 -0
  207. snowflake/connector/py.typed +0 -0
  208. snowflake/connector/result_batch.py +917 -0
  209. snowflake/connector/result_set.py +340 -0
  210. snowflake/connector/s3_storage_client.py +614 -0
  211. snowflake/connector/secret_detector.py +181 -0
  212. snowflake/connector/session_manager.py +650 -0
  213. snowflake/connector/sf_dirs.py +64 -0
  214. snowflake/connector/sfbinaryformat.py +35 -0
  215. snowflake/connector/sfdatetime.py +345 -0
  216. snowflake/connector/snow_logging.py +144 -0
  217. snowflake/connector/sqlstate.py +9 -0
  218. snowflake/connector/ssd_internal_keys.py +30 -0
  219. snowflake/connector/ssl_wrap_socket.py +281 -0
  220. snowflake/connector/storage_client.py +486 -0
  221. snowflake/connector/telemetry.py +254 -0
  222. snowflake/connector/telemetry_oob.py +544 -0
  223. snowflake/connector/test_util.py +30 -0
  224. snowflake/connector/time_util.py +159 -0
  225. snowflake/connector/token_cache.py +457 -0
  226. snowflake/connector/tool/__init__.py +0 -0
  227. snowflake/connector/tool/dump_certs.py +57 -0
  228. snowflake/connector/tool/dump_ocsp_response.py +139 -0
  229. snowflake/connector/tool/dump_ocsp_response_cache.py +194 -0
  230. snowflake/connector/tool/probe_connection.py +69 -0
  231. snowflake/connector/url_util.py +55 -0
  232. snowflake/connector/util_text.py +320 -0
  233. snowflake/connector/vendored/__init__.py +3 -0
  234. snowflake/connector/vendored/requests/LICENSE +175 -0
  235. snowflake/connector/vendored/requests/__init__.py +184 -0
  236. snowflake/connector/vendored/requests/__version__.py +14 -0
  237. snowflake/connector/vendored/requests/_internal_utils.py +50 -0
  238. snowflake/connector/vendored/requests/adapters.py +696 -0
  239. snowflake/connector/vendored/requests/api.py +157 -0
  240. snowflake/connector/vendored/requests/auth.py +314 -0
  241. snowflake/connector/vendored/requests/certs.py +17 -0
  242. snowflake/connector/vendored/requests/compat.py +106 -0
  243. snowflake/connector/vendored/requests/cookies.py +561 -0
  244. snowflake/connector/vendored/requests/exceptions.py +151 -0
  245. snowflake/connector/vendored/requests/help.py +134 -0
  246. snowflake/connector/vendored/requests/hooks.py +33 -0
  247. snowflake/connector/vendored/requests/models.py +1039 -0
  248. snowflake/connector/vendored/requests/packages.py +23 -0
  249. snowflake/connector/vendored/requests/sessions.py +831 -0
  250. snowflake/connector/vendored/requests/status_codes.py +128 -0
  251. snowflake/connector/vendored/requests/structures.py +99 -0
  252. snowflake/connector/vendored/requests/utils.py +1086 -0
  253. snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
  254. snowflake/connector/vendored/urllib3/__init__.py +211 -0
  255. snowflake/connector/vendored/urllib3/_base_connection.py +165 -0
  256. snowflake/connector/vendored/urllib3/_collections.py +487 -0
  257. snowflake/connector/vendored/urllib3/_request_methods.py +278 -0
  258. snowflake/connector/vendored/urllib3/_version.py +34 -0
  259. snowflake/connector/vendored/urllib3/connection.py +1108 -0
  260. snowflake/connector/vendored/urllib3/connectionpool.py +1178 -0
  261. snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
  262. snowflake/connector/vendored/urllib3/contrib/emscripten/__init__.py +17 -0
  263. snowflake/connector/vendored/urllib3/contrib/emscripten/connection.py +260 -0
  264. snowflake/connector/vendored/urllib3/contrib/emscripten/emscripten_fetch_worker.js +110 -0
  265. snowflake/connector/vendored/urllib3/contrib/emscripten/fetch.py +726 -0
  266. snowflake/connector/vendored/urllib3/contrib/emscripten/request.py +22 -0
  267. snowflake/connector/vendored/urllib3/contrib/emscripten/response.py +277 -0
  268. snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +564 -0
  269. snowflake/connector/vendored/urllib3/contrib/socks.py +228 -0
  270. snowflake/connector/vendored/urllib3/exceptions.py +335 -0
  271. snowflake/connector/vendored/urllib3/fields.py +341 -0
  272. snowflake/connector/vendored/urllib3/filepost.py +89 -0
  273. snowflake/connector/vendored/urllib3/http2/__init__.py +53 -0
  274. snowflake/connector/vendored/urllib3/http2/connection.py +356 -0
  275. snowflake/connector/vendored/urllib3/http2/probe.py +87 -0
  276. snowflake/connector/vendored/urllib3/poolmanager.py +651 -0
  277. snowflake/connector/vendored/urllib3/py.typed +2 -0
  278. snowflake/connector/vendored/urllib3/response.py +1480 -0
  279. snowflake/connector/vendored/urllib3/util/__init__.py +42 -0
  280. snowflake/connector/vendored/urllib3/util/connection.py +137 -0
  281. snowflake/connector/vendored/urllib3/util/proxy.py +43 -0
  282. snowflake/connector/vendored/urllib3/util/request.py +263 -0
  283. snowflake/connector/vendored/urllib3/util/response.py +101 -0
  284. snowflake/connector/vendored/urllib3/util/retry.py +549 -0
  285. snowflake/connector/vendored/urllib3/util/ssl_.py +527 -0
  286. snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
  287. snowflake/connector/vendored/urllib3/util/ssltransport.py +271 -0
  288. snowflake/connector/vendored/urllib3/util/timeout.py +275 -0
  289. snowflake/connector/vendored/urllib3/util/url.py +469 -0
  290. snowflake/connector/vendored/urllib3/util/util.py +42 -0
  291. snowflake/connector/vendored/urllib3/util/wait.py +124 -0
  292. snowflake/connector/version.py +3 -0
  293. snowflake/connector/wif_util.py +434 -0
  294. snowflake_connector_python-4.4.0.dist-info/DELVEWHEEL +2 -0
  295. snowflake_connector_python-4.4.0.dist-info/METADATA +1591 -0
  296. snowflake_connector_python-4.4.0.dist-info/RECORD +302 -0
  297. snowflake_connector_python-4.4.0.dist-info/WHEEL +5 -0
  298. snowflake_connector_python-4.4.0.dist-info/entry_points.txt +4 -0
  299. snowflake_connector_python-4.4.0.dist-info/licenses/LICENSE.txt +202 -0
  300. snowflake_connector_python-4.4.0.dist-info/licenses/NOTICE +8 -0
  301. snowflake_connector_python-4.4.0.dist-info/top_level.txt +1 -0
  302. snowflake_connector_python.libs/msvcp140-0f885b509a685d2bbfa652fed26b5fb3.dll +0 -0
@@ -0,0 +1,860 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import contextlib
5
+ import gzip
6
+ import json
7
+ import logging
8
+ import re
9
+ import uuid
10
+ from typing import TYPE_CHECKING, Any, AsyncGenerator
11
+
12
+ import OpenSSL.SSL
13
+
14
+ from ..compat import FORBIDDEN, OK, UNAUTHORIZED, urlencode, urlparse, urlsplit
15
+ from ..constants import (
16
+ _CONNECTIVITY_ERR_MSG,
17
+ HTTP_HEADER_ACCEPT,
18
+ HTTP_HEADER_CONTENT_TYPE,
19
+ HTTP_HEADER_SERVICE_NAME,
20
+ HTTP_HEADER_USER_AGENT,
21
+ )
22
+ from ..errorcode import (
23
+ ER_CONNECTION_IS_CLOSED,
24
+ ER_CONNECTION_TIMEOUT,
25
+ ER_FAILED_TO_CONNECT_TO_DB,
26
+ ER_FAILED_TO_RENEW_SESSION,
27
+ ER_FAILED_TO_REQUEST,
28
+ ER_HTTP_GENERAL_ERROR,
29
+ ER_RETRYABLE_CODE,
30
+ )
31
+ from ..errors import (
32
+ DatabaseError,
33
+ Error,
34
+ ForbiddenError,
35
+ HttpError,
36
+ OperationalError,
37
+ ProgrammingError,
38
+ RefreshTokenError,
39
+ RevocationCheckError,
40
+ )
41
+ from ..network import (
42
+ ACCEPT_TYPE_APPLICATION_SNOWFLAKE,
43
+ BAD_REQUEST_GS_CODE,
44
+ CONTENT_TYPE_APPLICATION_JSON,
45
+ DEFAULT_SOCKET_CONNECT_TIMEOUT,
46
+ EXTERNAL_BROWSER_AUTHENTICATOR,
47
+ HEADER_AUTHORIZATION_KEY,
48
+ HEADER_SNOWFLAKE_TOKEN,
49
+ ID_TOKEN_EXPIRED_GS_CODE,
50
+ IMPLEMENTATION,
51
+ MASTER_TOKEN_EXPIRED_GS_CODE,
52
+ MASTER_TOKEN_INVALD_GS_CODE,
53
+ MASTER_TOKEN_NOTFOUND_GS_CODE,
54
+ NO_TOKEN,
55
+ PLATFORM,
56
+ PYTHON_VERSION,
57
+ QUERY_IN_PROGRESS_ASYNC_CODE,
58
+ QUERY_IN_PROGRESS_CODE,
59
+ REQUEST_ID,
60
+ REQUEST_TYPE_RENEW,
61
+ SESSION_EXPIRED_GS_CODE,
62
+ SNOWFLAKE_CONNECTOR_VERSION,
63
+ ReauthenticationRequest,
64
+ RetryRequest,
65
+ )
66
+ from ..network import SnowflakeRestful as SnowflakeRestfulSync
67
+ from ..network import (
68
+ SnowflakeRestfulJsonEncoder,
69
+ get_http_retryable_error,
70
+ is_econnreset_exception,
71
+ is_login_request,
72
+ is_retryable_http_code,
73
+ )
74
+ from ..secret_detector import SecretDetector
75
+ from ..sqlstate import (
76
+ SQLSTATE_CONNECTION_NOT_EXISTS,
77
+ SQLSTATE_CONNECTION_REJECTED,
78
+ SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
79
+ )
80
+ from ..time_util import TimeoutBackoffCtx
81
+ from ._description import CLIENT_NAME
82
+ from ._session_manager import (
83
+ SessionManager,
84
+ SessionManagerFactory,
85
+ SnowflakeSSLConnectorFactory,
86
+ )
87
+
88
+ if TYPE_CHECKING:
89
+ from snowflake.connector.aio import SnowflakeConnection
90
+
91
+ logger = logging.getLogger(__name__)
92
+
93
+ PYTHON_CONNECTOR_USER_AGENT = f"{CLIENT_NAME}/{SNOWFLAKE_CONNECTOR_VERSION} ({PLATFORM}) {IMPLEMENTATION}/{PYTHON_VERSION}"
94
+
95
+ try:
96
+ import aiohttp
97
+ except ImportError:
98
+ logger.warning("Please install aiohttp to use asyncio features.")
99
+ raise
100
+
101
+
102
+ def raise_okta_unauthorized_error(
103
+ connection: SnowflakeConnection | None, response: aiohttp.ClientResponse
104
+ ) -> None:
105
+ Error.errorhandler_wrapper(
106
+ connection,
107
+ None,
108
+ DatabaseError,
109
+ {
110
+ "msg": f"Failed to get authentication by OKTA: {response.status}: {response.reason}",
111
+ "errno": ER_FAILED_TO_CONNECT_TO_DB,
112
+ "sqlstate": SQLSTATE_CONNECTION_REJECTED,
113
+ },
114
+ )
115
+
116
+
117
+ def raise_failed_request_error(
118
+ connection: SnowflakeConnection | None,
119
+ url: str,
120
+ method: str,
121
+ response: aiohttp.ClientResponse,
122
+ ) -> None:
123
+ Error.errorhandler_wrapper(
124
+ connection,
125
+ None,
126
+ HttpError,
127
+ {
128
+ "msg": f"{response.status} {response.reason}: {method} {urlsplit(url).netloc}{urlsplit(url).path}",
129
+ "errno": ER_HTTP_GENERAL_ERROR + response.status,
130
+ "sqlstate": SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
131
+ },
132
+ )
133
+
134
+
135
+ class SnowflakeRestful(SnowflakeRestfulSync):
136
+ def __init__(
137
+ self,
138
+ host: str = "127.0.0.1",
139
+ port: int = 8080,
140
+ protocol: str = "http",
141
+ inject_client_pause: int = 0,
142
+ connection: SnowflakeConnection | None = None,
143
+ session_manager: SessionManager | None = None,
144
+ ):
145
+ super().__init__(host, port, protocol, inject_client_pause, connection)
146
+ self._lock_token = asyncio.Lock()
147
+
148
+ if session_manager is None:
149
+ session_manager = (
150
+ connection._session_manager
151
+ if (connection and connection._session_manager)
152
+ else SessionManagerFactory.get_manager(
153
+ connector_factory=SnowflakeSSLConnectorFactory()
154
+ )
155
+ )
156
+ self._session_manager = session_manager
157
+
158
+ async def close(self) -> None:
159
+ if hasattr(self, "_token"):
160
+ del self._token
161
+ if hasattr(self, "_master_token"):
162
+ del self._master_token
163
+ if hasattr(self, "_id_token"):
164
+ del self._id_token
165
+ if hasattr(self, "_mfa_token"):
166
+ del self._mfa_token
167
+
168
+ await self._session_manager.close()
169
+
170
+ async def request(
171
+ self,
172
+ url,
173
+ body=None,
174
+ method: str = "post",
175
+ client: str = "sfsql",
176
+ timeout: int | None = None,
177
+ _no_results: bool = False,
178
+ _include_retry_params: bool = False,
179
+ _no_retry: bool = False,
180
+ ):
181
+ # log to reflect vendored.urllib3.connectionpool:connectionpool.py:474
182
+ logger.debug("%s %s", method.upper(), url)
183
+ if body is None:
184
+ body = {}
185
+ if self.master_token is None and self.token is None:
186
+ Error.errorhandler_wrapper(
187
+ self._connection,
188
+ None,
189
+ DatabaseError,
190
+ {
191
+ "msg": "Connection is closed",
192
+ "errno": ER_CONNECTION_IS_CLOSED,
193
+ "sqlstate": SQLSTATE_CONNECTION_NOT_EXISTS,
194
+ },
195
+ )
196
+
197
+ if client == "sfsql":
198
+ accept_type = ACCEPT_TYPE_APPLICATION_SNOWFLAKE
199
+ else:
200
+ accept_type = CONTENT_TYPE_APPLICATION_JSON
201
+
202
+ headers = {
203
+ HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_APPLICATION_JSON,
204
+ HTTP_HEADER_ACCEPT: accept_type,
205
+ HTTP_HEADER_USER_AGENT: PYTHON_CONNECTOR_USER_AGENT,
206
+ }
207
+ try:
208
+ # SNOW-1763555: inject OpenTelemetry headers if available specifically in WC3 format
209
+ # into our request headers in case tracing is enabled. This should make sure that
210
+ # our requests are accounted for properly if OpenTelemetry is used by users.
211
+ from opentelemetry.trace.propagation.tracecontext import (
212
+ TraceContextTextMapPropagator,
213
+ )
214
+
215
+ TraceContextTextMapPropagator().inject(headers)
216
+ except Exception:
217
+ logger.debug(
218
+ "Opentelemtry otel injection failed",
219
+ exc_info=True,
220
+ )
221
+ if self._connection.service_name:
222
+ headers[HTTP_HEADER_SERVICE_NAME] = self._connection.service_name
223
+ if method == "post":
224
+ return await self._post_request(
225
+ url,
226
+ headers,
227
+ json.dumps(body, cls=SnowflakeRestfulJsonEncoder),
228
+ token=self.token,
229
+ _no_results=_no_results,
230
+ timeout=timeout,
231
+ _include_retry_params=_include_retry_params,
232
+ no_retry=_no_retry,
233
+ )
234
+ else:
235
+ return await self._get_request(
236
+ url,
237
+ headers,
238
+ token=self.token,
239
+ timeout=timeout,
240
+ )
241
+
242
+ async def update_tokens(
243
+ self,
244
+ session_token,
245
+ master_token,
246
+ master_validity_in_seconds=None,
247
+ id_token=None,
248
+ mfa_token=None,
249
+ ) -> None:
250
+ """Updates session and master tokens and optionally temporary credential."""
251
+ async with self._lock_token:
252
+ self._token = session_token
253
+ self._master_token = master_token
254
+ self._id_token = id_token
255
+ self._mfa_token = mfa_token
256
+ self._master_validity_in_seconds = master_validity_in_seconds
257
+
258
+ async def _renew_session(self):
259
+ """Renew a session and master token."""
260
+ return await self._token_request(REQUEST_TYPE_RENEW)
261
+
262
+ async def _token_request(self, request_type):
263
+ logger.debug(
264
+ "updating session. master_token: {}".format(
265
+ "****" if self.master_token else None
266
+ )
267
+ )
268
+ headers = {
269
+ HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_APPLICATION_JSON,
270
+ HTTP_HEADER_ACCEPT: CONTENT_TYPE_APPLICATION_JSON,
271
+ HTTP_HEADER_USER_AGENT: PYTHON_CONNECTOR_USER_AGENT,
272
+ }
273
+ if self._connection.service_name:
274
+ headers[HTTP_HEADER_SERVICE_NAME] = self._connection.service_name
275
+ request_id = str(uuid.uuid4())
276
+ logger.debug("request_id: %s", request_id)
277
+ url = "/session/token-request?" + urlencode({REQUEST_ID: request_id})
278
+
279
+ # NOTE: ensure an empty key if master token is not set.
280
+ # This avoids HTTP 400.
281
+ header_token = self.master_token or ""
282
+ body = {
283
+ "oldSessionToken": self.token,
284
+ "requestType": request_type,
285
+ }
286
+ ret = await self._post_request(
287
+ url,
288
+ headers,
289
+ json.dumps(body, cls=SnowflakeRestfulJsonEncoder),
290
+ token=header_token,
291
+ )
292
+ if ret.get("success") and ret.get("data", {}).get("sessionToken"):
293
+ logger.debug("success: %s", SecretDetector.mask_secrets(str(ret)))
294
+ await self.update_tokens(
295
+ ret["data"]["sessionToken"],
296
+ ret["data"].get("masterToken"),
297
+ master_validity_in_seconds=ret["data"].get("masterValidityInSeconds"),
298
+ )
299
+ logger.debug("updating session completed")
300
+ return ret
301
+ else:
302
+ logger.debug("failed: %s", SecretDetector.mask_secrets(str(ret)))
303
+ err = ret.get("message")
304
+ if err is not None and ret.get("data"):
305
+ err += ret["data"].get("errorMessage", "")
306
+ errno = ret.get("code") or ER_FAILED_TO_RENEW_SESSION
307
+ if errno in (
308
+ ID_TOKEN_EXPIRED_GS_CODE,
309
+ SESSION_EXPIRED_GS_CODE,
310
+ MASTER_TOKEN_NOTFOUND_GS_CODE,
311
+ MASTER_TOKEN_EXPIRED_GS_CODE,
312
+ MASTER_TOKEN_INVALD_GS_CODE,
313
+ BAD_REQUEST_GS_CODE,
314
+ ):
315
+ raise ReauthenticationRequest(
316
+ ProgrammingError(
317
+ msg=err,
318
+ errno=int(errno),
319
+ sqlstate=SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
320
+ )
321
+ )
322
+ Error.errorhandler_wrapper(
323
+ self._connection,
324
+ None,
325
+ ProgrammingError,
326
+ {
327
+ "msg": err,
328
+ "errno": int(errno),
329
+ "sqlstate": SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED,
330
+ },
331
+ )
332
+
333
+ async def _heartbeat(self) -> Any | dict[Any, Any] | None:
334
+ headers = {
335
+ HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_APPLICATION_JSON,
336
+ HTTP_HEADER_ACCEPT: CONTENT_TYPE_APPLICATION_JSON,
337
+ HTTP_HEADER_USER_AGENT: PYTHON_CONNECTOR_USER_AGENT,
338
+ }
339
+ if self._connection.service_name:
340
+ headers[HTTP_HEADER_SERVICE_NAME] = self._connection.service_name
341
+ request_id = str(uuid.uuid4())
342
+ logger.debug("request_id: %s", request_id)
343
+ url = "/session/heartbeat?" + urlencode({REQUEST_ID: request_id})
344
+ ret = await self._post_request(
345
+ url,
346
+ headers,
347
+ None,
348
+ token=self.token,
349
+ )
350
+ if not ret.get("success"):
351
+ logger.error("Failed to heartbeat. code: %s, url: %s", ret.get("code"), url)
352
+ return ret
353
+
354
+ async def delete_session(self, retry: bool = False) -> None:
355
+ """Deletes the session."""
356
+ if self.master_token is None:
357
+ Error.errorhandler_wrapper(
358
+ self._connection,
359
+ None,
360
+ DatabaseError,
361
+ {
362
+ "msg": "Connection is closed",
363
+ "errno": ER_CONNECTION_IS_CLOSED,
364
+ "sqlstate": SQLSTATE_CONNECTION_NOT_EXISTS,
365
+ },
366
+ )
367
+
368
+ url = "/session?" + urlencode({"delete": "true"})
369
+ headers = {
370
+ HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_APPLICATION_JSON,
371
+ HTTP_HEADER_ACCEPT: CONTENT_TYPE_APPLICATION_JSON,
372
+ HTTP_HEADER_USER_AGENT: PYTHON_CONNECTOR_USER_AGENT,
373
+ }
374
+ if self._connection.service_name:
375
+ headers[HTTP_HEADER_SERVICE_NAME] = self._connection.service_name
376
+
377
+ body = {}
378
+ retry_limit = 3 if retry else 1
379
+ num_retries = 0
380
+ should_retry = True
381
+ while should_retry and (num_retries < retry_limit):
382
+ try:
383
+ should_retry = False
384
+ ret = await self._post_request(
385
+ url,
386
+ headers,
387
+ json.dumps(body, cls=SnowflakeRestfulJsonEncoder),
388
+ token=self.token,
389
+ timeout=5,
390
+ no_retry=True,
391
+ )
392
+ if not ret:
393
+ if retry:
394
+ should_retry = True
395
+ else:
396
+ return
397
+ elif ret.get("success"):
398
+ return
399
+ err = ret.get("message")
400
+ if err is not None and ret.get("data"):
401
+ err += ret["data"].get("errorMessage", "")
402
+ # no exception is raised
403
+ logger.debug("error in deleting session. ignoring...: %s", err)
404
+ except Exception as e:
405
+ logger.debug("error in deleting session. ignoring...: %s", e)
406
+ finally:
407
+ num_retries += 1
408
+
409
+ async def _get_request(
410
+ self,
411
+ url: str,
412
+ headers: dict[str, str],
413
+ token: str = None,
414
+ timeout: int | None = None,
415
+ is_fetch_query_status: bool = False,
416
+ ) -> dict[str, Any]:
417
+ if "Content-Encoding" in headers:
418
+ del headers["Content-Encoding"]
419
+ if "Content-Length" in headers:
420
+ del headers["Content-Length"]
421
+
422
+ full_url = f"{self.server_url}{url}"
423
+ ret = await self.fetch(
424
+ "get",
425
+ full_url,
426
+ headers,
427
+ timeout=timeout,
428
+ token=token,
429
+ is_fetch_query_status=is_fetch_query_status,
430
+ )
431
+ if ret.get("code") == SESSION_EXPIRED_GS_CODE:
432
+ try:
433
+ ret = await self._renew_session()
434
+ except ReauthenticationRequest as ex:
435
+ if self._connection._authenticator != EXTERNAL_BROWSER_AUTHENTICATOR:
436
+ raise ex.cause
437
+ ret = await self._connection._reauthenticate()
438
+ logger.debug(
439
+ "ret[code] = {code} after renew_session".format(
440
+ code=(ret.get("code", "N/A"))
441
+ )
442
+ )
443
+ if ret.get("success"):
444
+ return await self._get_request(
445
+ url,
446
+ headers,
447
+ token=self.token,
448
+ is_fetch_query_status=is_fetch_query_status,
449
+ )
450
+
451
+ return ret
452
+
453
+ async def _post_request(
454
+ self,
455
+ url,
456
+ headers,
457
+ body,
458
+ token=None,
459
+ timeout: int | None = None,
460
+ socket_timeout: int | None = None,
461
+ _no_results: bool = False,
462
+ no_retry: bool = False,
463
+ _include_retry_params: bool = False,
464
+ ) -> dict[str, Any]:
465
+ full_url = f"{self.server_url}{url}"
466
+ if self._connection._probe_connection:
467
+ # TODO: SNOW-1572318 for probe connection
468
+ raise NotImplementedError("probe_connection is not supported in asyncio")
469
+
470
+ ret = await self.fetch(
471
+ "post",
472
+ full_url,
473
+ headers,
474
+ data=body,
475
+ timeout=timeout,
476
+ token=token,
477
+ no_retry=no_retry,
478
+ _include_retry_params=_include_retry_params,
479
+ socket_timeout=socket_timeout,
480
+ )
481
+ logger.debug(
482
+ "ret[code] = {code}, after post request".format(
483
+ code=(ret.get("code", "N/A"))
484
+ )
485
+ )
486
+
487
+ if ret.get("code") == MASTER_TOKEN_EXPIRED_GS_CODE:
488
+ self._connection.expired = True
489
+ elif ret.get("code") == SESSION_EXPIRED_GS_CODE:
490
+ try:
491
+ ret = await self._renew_session()
492
+ except ReauthenticationRequest as ex:
493
+ if self._connection._authenticator != EXTERNAL_BROWSER_AUTHENTICATOR:
494
+ raise ex.cause
495
+ ret = await self._connection._reauthenticate()
496
+ logger.debug(
497
+ "ret[code] = {code} after renew_session".format(
498
+ code=(ret.get("code", "N/A"))
499
+ )
500
+ )
501
+ if ret.get("success"):
502
+ return await self._post_request(
503
+ url, headers, body, token=self.token, timeout=timeout
504
+ )
505
+
506
+ if isinstance(ret.get("data"), dict) and ret["data"].get("queryId"):
507
+ logger.debug("Query id: {}".format(ret["data"]["queryId"]))
508
+
509
+ if ret.get("code") == QUERY_IN_PROGRESS_ASYNC_CODE and _no_results:
510
+ return ret
511
+
512
+ while ret.get("code") in (QUERY_IN_PROGRESS_CODE, QUERY_IN_PROGRESS_ASYNC_CODE):
513
+ if self._inject_client_pause > 0:
514
+ logger.debug("waiting for %s...", self._inject_client_pause)
515
+ await asyncio.sleep(self._inject_client_pause)
516
+ # ping pong
517
+ result_url = ret["data"]["getResultUrl"]
518
+ logger.debug("ping pong starting...")
519
+ ret = await self._get_request(
520
+ result_url,
521
+ headers,
522
+ token=self.token,
523
+ timeout=timeout,
524
+ is_fetch_query_status=bool(
525
+ re.match(r"^/queries/.+/result$", result_url)
526
+ ),
527
+ )
528
+ logger.debug("ret[code] = %s", ret.get("code", "N/A"))
529
+ logger.debug("ping pong done")
530
+
531
+ return ret
532
+
533
+ async def fetch(
534
+ self,
535
+ method: str,
536
+ full_url: str,
537
+ headers: dict[str, Any],
538
+ data: dict[str, Any] | None = None,
539
+ timeout: int | None = None,
540
+ **kwargs,
541
+ ) -> dict[Any, Any]:
542
+ """Carry out API request with session management."""
543
+
544
+ class RetryCtx(TimeoutBackoffCtx):
545
+ def __init__(
546
+ self,
547
+ _include_retry_params: bool = False,
548
+ _include_retry_reason: bool = False,
549
+ **kwargs,
550
+ ) -> None:
551
+ super().__init__(**kwargs)
552
+ self.retry_reason = 0
553
+ self._include_retry_params = _include_retry_params
554
+ self._include_retry_reason = _include_retry_reason
555
+
556
+ def add_retry_params(self, full_url: str) -> str:
557
+ if self._include_retry_params and self.current_retry_count > 0:
558
+ retry_params = {
559
+ "clientStartTime": self._start_time_millis,
560
+ "retryCount": self.current_retry_count,
561
+ }
562
+ if self._include_retry_reason:
563
+ retry_params.update({"retryReason": self.retry_reason})
564
+ suffix = urlencode(retry_params)
565
+ sep = "&" if urlparse(full_url).query else "?"
566
+ return full_url + sep + suffix
567
+ else:
568
+ return full_url
569
+
570
+ include_retry_reason = self._connection._enable_retry_reason_in_query_response
571
+ include_retry_params = kwargs.pop("_include_retry_params", False)
572
+
573
+ async with self.use_session(full_url) as session:
574
+ retry_ctx = RetryCtx(
575
+ _include_retry_params=include_retry_params,
576
+ _include_retry_reason=include_retry_reason,
577
+ timeout=(
578
+ timeout if timeout is not None else self._connection.network_timeout
579
+ ),
580
+ backoff_generator=self._connection._backoff_generator,
581
+ )
582
+
583
+ retry_ctx.set_start_time()
584
+ while True:
585
+ ret = await self._request_exec_wrapper(
586
+ session, method, full_url, headers, data, retry_ctx, **kwargs
587
+ )
588
+ if ret is not None:
589
+ return ret
590
+
591
+ async def _request_exec_wrapper(
592
+ self,
593
+ session,
594
+ method,
595
+ full_url,
596
+ headers,
597
+ data,
598
+ retry_ctx,
599
+ no_retry: bool = False,
600
+ token=NO_TOKEN,
601
+ **kwargs,
602
+ ):
603
+ conn = self._connection
604
+ logger.debug(
605
+ "remaining request timeout: %s ms, retry cnt: %s",
606
+ retry_ctx.remaining_time_millis if retry_ctx.timeout is not None else "N/A",
607
+ retry_ctx.current_retry_count + 1,
608
+ )
609
+
610
+ full_url = retry_ctx.add_retry_params(full_url)
611
+ full_url = SnowflakeRestful.add_request_guid(full_url)
612
+ is_fetch_query_status = kwargs.pop("is_fetch_query_status", False)
613
+ try:
614
+ return_object = await self._request_exec(
615
+ session=session,
616
+ method=method,
617
+ full_url=full_url,
618
+ headers=headers,
619
+ data=data,
620
+ token=token,
621
+ **kwargs,
622
+ )
623
+ if return_object is not None:
624
+ return return_object
625
+ if is_fetch_query_status:
626
+ err_msg = (
627
+ "fetch query status failed and http request returned None, this"
628
+ " is usually caused by transient network failures, retrying..."
629
+ )
630
+ logger.info(err_msg)
631
+ raise RetryRequest(err_msg)
632
+ self._handle_unknown_error(method, full_url, headers, data, conn)
633
+ return {}
634
+ except RevocationCheckError as rce:
635
+ rce.exception_telemetry(rce.msg, None, self._connection)
636
+ raise rce
637
+ except RetryRequest as e:
638
+ cause = e.args[0]
639
+ if no_retry:
640
+ self.log_and_handle_http_error_with_cause(
641
+ e,
642
+ full_url,
643
+ method,
644
+ retry_ctx.timeout,
645
+ retry_ctx.current_retry_count,
646
+ conn,
647
+ timed_out=False,
648
+ )
649
+ return {} # required for tests
650
+ if not retry_ctx.should_retry:
651
+ self.log_and_handle_http_error_with_cause(
652
+ e,
653
+ full_url,
654
+ method,
655
+ retry_ctx.timeout,
656
+ retry_ctx.current_retry_count,
657
+ conn,
658
+ )
659
+ return {} # required for tests
660
+
661
+ logger.debug(
662
+ "retrying: errorclass=%s, "
663
+ "error=%s, "
664
+ "counter=%s, "
665
+ "sleeping=%s(s)",
666
+ type(cause),
667
+ cause,
668
+ retry_ctx.current_retry_count + 1,
669
+ retry_ctx.current_sleep_time,
670
+ )
671
+ await asyncio.sleep(float(retry_ctx.current_sleep_time))
672
+ retry_ctx.increment()
673
+
674
+ reason = getattr(cause, "errno", 0)
675
+ if reason is None:
676
+ reason = 0
677
+ else:
678
+ reason = (
679
+ reason - ER_HTTP_GENERAL_ERROR
680
+ if reason >= ER_HTTP_GENERAL_ERROR
681
+ else reason
682
+ )
683
+
684
+ retry_ctx.retry_reason = reason
685
+ # notes: in sync implementation we check ECONNRESET in error message and close low level urllib session
686
+ # we do not have the logic here because aiohttp handles low level connection close-reopen for us
687
+ return None # retry
688
+ except Exception as e:
689
+ if not no_retry:
690
+ raise e
691
+ logger.debug("Ignored error", exc_info=True)
692
+ return {}
693
+
694
+ async def _request_exec(
695
+ self,
696
+ session: aiohttp.ClientSession,
697
+ method,
698
+ full_url,
699
+ headers,
700
+ data,
701
+ token,
702
+ catch_okta_unauthorized_error: bool = False,
703
+ is_raw_text: bool = False,
704
+ is_raw_binary: bool = False,
705
+ binary_data_handler=None,
706
+ socket_timeout: int | None = None,
707
+ is_okta_authentication: bool = False,
708
+ ):
709
+ if socket_timeout is None:
710
+ if self._connection.socket_timeout is not None:
711
+ logger.debug("socket_timeout specified in connection")
712
+ socket_timeout = self._connection.socket_timeout
713
+ else:
714
+ socket_timeout = DEFAULT_SOCKET_CONNECT_TIMEOUT
715
+ logger.debug("socket timeout: %s", socket_timeout)
716
+
717
+ try:
718
+ if not catch_okta_unauthorized_error and data and len(data) > 0:
719
+ headers["Content-Encoding"] = "gzip"
720
+ input_data = gzip.compress(data.encode("utf-8"))
721
+ else:
722
+ input_data = data
723
+
724
+ if HEADER_AUTHORIZATION_KEY in headers:
725
+ del headers[HEADER_AUTHORIZATION_KEY]
726
+ if token != NO_TOKEN:
727
+ headers[HEADER_AUTHORIZATION_KEY] = HEADER_SNOWFLAKE_TOKEN.format(
728
+ token=token
729
+ )
730
+
731
+ # socket timeout is constant. You should be able to receive
732
+ # the response within the time. If not, asyncio.TimeoutError is raised.
733
+
734
+ # delta compared to sync:
735
+ # - in sync, we specify "verify" to True; in aiohttp,
736
+ # the counter parameter is "ssl" and it already defaults to True
737
+ raw_ret = await session.request(
738
+ method=method,
739
+ url=full_url,
740
+ headers=headers,
741
+ data=input_data,
742
+ timeout=aiohttp.ClientTimeout(socket_timeout),
743
+ )
744
+ try:
745
+ if raw_ret.status == OK:
746
+ logger.debug("SUCCESS")
747
+ if is_raw_text:
748
+ ret = await raw_ret.text()
749
+ elif is_raw_binary:
750
+ # TODO: SNOW-1738595 for is_raw_binary support
751
+ raise NotImplementedError(
752
+ "reading raw binary data is not supported in asyncio connector,"
753
+ " please open a feature request issue in"
754
+ " github: https://github.com/snowflakedb/snowflake-connector-python/issues/new/choose"
755
+ )
756
+ else:
757
+ ret = await raw_ret.json()
758
+ return ret
759
+
760
+ if is_login_request(full_url) and raw_ret.status == FORBIDDEN:
761
+ raise ForbiddenError
762
+
763
+ elif is_retryable_http_code(raw_ret.status):
764
+ err = get_http_retryable_error(raw_ret.status)
765
+ # retryable server exceptions
766
+ if is_okta_authentication:
767
+ raise RefreshTokenError(
768
+ msg="OKTA authentication requires token refresh."
769
+ )
770
+ if is_login_request(full_url):
771
+ logger.debug(
772
+ "Received retryable response code while logging in. Will be handled by "
773
+ f"authenticator. Ignore the following. Error stack: {err}",
774
+ exc_info=True,
775
+ )
776
+ raise OperationalError(
777
+ msg="Login request is retryable. Will be handled by authenticator",
778
+ errno=ER_RETRYABLE_CODE,
779
+ )
780
+ else:
781
+ logger.debug(f"{err}. Retrying...")
782
+ raise RetryRequest(err)
783
+
784
+ elif raw_ret.status == UNAUTHORIZED and catch_okta_unauthorized_error:
785
+ # OKTA Unauthorized errors
786
+ raise_okta_unauthorized_error(self._connection, raw_ret)
787
+ return None # required for tests
788
+ else:
789
+ raise_failed_request_error(
790
+ self._connection, full_url, method, raw_ret
791
+ )
792
+ return None # required for tests
793
+ finally:
794
+ raw_ret.close() # ensure response is closed
795
+ except (aiohttp.ClientSSLError, aiohttp.ClientConnectorSSLError) as se:
796
+ if is_econnreset_exception(se):
797
+ raise RetryRequest(se.os_error)
798
+ msg = f"Hit non-retryable SSL error, {str(se)}.\n{_CONNECTIVITY_ERR_MSG}"
799
+ logger.debug(msg)
800
+ # the following code is for backward compatibility with old versions of python connector which calls
801
+ # self._handle_unknown_error to process SSLError
802
+ Error.errorhandler_wrapper(
803
+ self._connection,
804
+ None,
805
+ OperationalError,
806
+ {
807
+ "msg": msg,
808
+ "errno": ER_FAILED_TO_REQUEST,
809
+ },
810
+ )
811
+ except (
812
+ aiohttp.ClientConnectionError,
813
+ aiohttp.ClientConnectorError,
814
+ aiohttp.ConnectionTimeoutError,
815
+ asyncio.TimeoutError,
816
+ OpenSSL.SSL.SysCallError,
817
+ KeyError, # SNOW-39175: asn1crypto.keys.PublicKeyInfo
818
+ ValueError,
819
+ RuntimeError,
820
+ AttributeError, # json decoding error
821
+ ) as err:
822
+ if isinstance(err, RuntimeError) and "Event loop is closed" in str(err):
823
+ logger.info(
824
+ "If you see the logging error message 'RuntimeError: Event loop is closed' during program exit, it probably indicates that the connection was not closed properly before the event loop was shut down. Please use SnowflakeConnection.close() to close connection."
825
+ )
826
+ raise err
827
+ if is_login_request(full_url):
828
+ logger.debug(
829
+ "Hit a timeout error while logging in. Will be handled by "
830
+ f"authenticator. Ignore the following. Error stack: {err}",
831
+ exc_info=True,
832
+ )
833
+ raise OperationalError(
834
+ msg="ConnectionTimeout occurred during login. Will be handled by authenticator",
835
+ errno=ER_CONNECTION_TIMEOUT,
836
+ )
837
+ else:
838
+ logger.debug(
839
+ "Hit retryable client error. Retrying... Ignore the following "
840
+ f"error stack: {err}",
841
+ exc_info=True,
842
+ )
843
+ raise RetryRequest(err)
844
+ except Exception as err:
845
+ if isinstance(err, (Error, RetryRequest, ReauthenticationRequest)):
846
+ raise err
847
+ raise OperationalError(
848
+ msg=f"Unexpected error occurred during request execution: {err}"
849
+ "Please check the stack trace for more information and retry the operation."
850
+ "If you think this is a bug, please collect the error information and open a bug report in github: "
851
+ "https://github.com/snowflakedb/snowflake-connector-python/issues/new/choose.",
852
+ errno=ER_FAILED_TO_REQUEST,
853
+ ) from err
854
+
855
+ @contextlib.asynccontextmanager
856
+ async def use_session(
857
+ self, url: str | None = None
858
+ ) -> AsyncGenerator[aiohttp.ClientSession]:
859
+ async with self._session_manager.use_session(url) as session:
860
+ yield session