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,614 @@
1
+ from __future__ import annotations
2
+
3
+ import binascii
4
+ import re
5
+ import xml.etree.ElementTree as ET
6
+ from datetime import datetime, timezone
7
+ from io import IOBase
8
+ from logging import getLogger
9
+ from operator import itemgetter
10
+ from typing import TYPE_CHECKING, Any, NamedTuple
11
+
12
+ from cryptography.hazmat.primitives import hashes, hmac
13
+
14
+ from .compat import quote, urlparse
15
+ from .constants import (
16
+ HTTP_HEADER_CONTENT_TYPE,
17
+ HTTP_HEADER_VALUE_OCTET_STREAM,
18
+ FileHeader,
19
+ ResultStatus,
20
+ )
21
+ from .encryption_util import EncryptionMetadata
22
+ from .storage_client import SnowflakeStorageClient, remove_content_encoding
23
+ from .vendored import requests
24
+
25
+ if TYPE_CHECKING: # pragma: no cover
26
+ from .file_transfer_agent import SnowflakeFileMeta, StorageCredential
27
+
28
+ logger = getLogger(__name__)
29
+
30
+ META_PREFIX = "x-amz-meta-"
31
+ SFC_DIGEST = "sfc-digest"
32
+
33
+ AMZ_MATDESC = "x-amz-matdesc"
34
+ AMZ_KEY = "x-amz-key"
35
+ AMZ_IV = "x-amz-iv"
36
+
37
+ ERRORNO_WSAECONNABORTED = 10053 # network connection was aborted
38
+
39
+ EXPIRED_TOKEN = "ExpiredToken"
40
+ ADDRESSING_STYLE = "virtual" # explicit force to use virtual addressing style
41
+ UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"
42
+
43
+ RE_MULTIPLE_SPACES = re.compile(r" +")
44
+
45
+
46
+ class S3Location(NamedTuple):
47
+ bucket_name: str
48
+ path: str
49
+
50
+
51
+ class SnowflakeS3RestClient(SnowflakeStorageClient):
52
+ def __init__(
53
+ self,
54
+ meta: SnowflakeFileMeta,
55
+ credentials: StorageCredential,
56
+ stage_info: dict[str, Any],
57
+ chunk_size: int,
58
+ use_accelerate_endpoint: bool | None = None,
59
+ use_s3_regional_url: bool = False,
60
+ unsafe_file_write: bool = False,
61
+ ) -> None:
62
+ """Rest client for S3 storage.
63
+
64
+ Args:
65
+ stage_info:
66
+ """
67
+ super().__init__(
68
+ meta,
69
+ stage_info,
70
+ chunk_size,
71
+ credentials=credentials,
72
+ unsafe_file_write=unsafe_file_write,
73
+ )
74
+ # Signature version V4
75
+ # Addressing style Virtual Host
76
+ self.region_name: str = stage_info["region"]
77
+ # Multipart upload only
78
+ self.upload_id: str | None = None
79
+ self.etags: list[str] | None = None
80
+ self.s3location: S3Location = (
81
+ SnowflakeS3RestClient._extract_bucket_name_and_path(
82
+ self.stage_info["location"]
83
+ )
84
+ )
85
+ self.use_s3_regional_url = (
86
+ use_s3_regional_url
87
+ or "useS3RegionalUrl" in stage_info
88
+ and stage_info["useS3RegionalUrl"]
89
+ or "useRegionalUrl" in stage_info
90
+ and stage_info["useRegionalUrl"]
91
+ )
92
+ self.location_type = stage_info.get("locationType")
93
+
94
+ # if GS sends us an endpoint, it's likely for FIPS. Use it.
95
+ self.endpoint: str | None = None
96
+ if stage_info["endPoint"]:
97
+ self.endpoint = (
98
+ f"https://{self.s3location.bucket_name}." + stage_info["endPoint"]
99
+ )
100
+ self.transfer_accelerate_config(use_accelerate_endpoint)
101
+
102
+ def transfer_accelerate_config(
103
+ self, use_accelerate_endpoint: bool | None = None
104
+ ) -> bool:
105
+ # accelerate cannot be used in China and us government
106
+ if self.region_name and self.region_name.startswith("cn-"):
107
+ self.endpoint = (
108
+ f"https://{self.s3location.bucket_name}."
109
+ f"s3.{self.region_name}.amazonaws.com.cn"
110
+ )
111
+ return False
112
+ # if self.endpoint has been set, e.g. by metadata, no more config is needed.
113
+ if self.endpoint is not None:
114
+ return self.endpoint.find("s3-accelerate.amazonaws.com") >= 0
115
+ if self.use_s3_regional_url:
116
+ self.endpoint = (
117
+ f"https://{self.s3location.bucket_name}."
118
+ f"s3.{self.region_name}.amazonaws.com"
119
+ )
120
+ return False
121
+ else:
122
+ if use_accelerate_endpoint is None:
123
+ if str(self.s3location.bucket_name).lower().startswith("sfc-"):
124
+ # SNOW-2324060: no s3:GetAccelerateConfiguration and no intention to add either
125
+ # for internal stage, thus previously the client got HTTP403 on /accelerate call
126
+ logger.debug(
127
+ "Not attempting to get bucket transfer accelerate endpoint for internal stage."
128
+ )
129
+ use_accelerate_endpoint = False
130
+ else:
131
+ use_accelerate_endpoint = self._get_bucket_accelerate_config(
132
+ self.s3location.bucket_name
133
+ )
134
+
135
+ if use_accelerate_endpoint:
136
+ self.endpoint = (
137
+ f"https://{self.s3location.bucket_name}.s3-accelerate.amazonaws.com"
138
+ )
139
+ else:
140
+ self.endpoint = (
141
+ f"https://{self.s3location.bucket_name}.s3.amazonaws.com"
142
+ )
143
+ logger.debug(f"Using {self.endpoint} as storage endpoint.")
144
+ return use_accelerate_endpoint
145
+
146
+ @staticmethod
147
+ def _sign_bytes(secret_key: bytes, _input: str) -> bytes:
148
+ """Applies HMAC-SHA-256 to given string with secret_key."""
149
+ h = hmac.HMAC(secret_key, hashes.SHA256())
150
+ h.update(_input.encode("utf-8"))
151
+ return h.finalize()
152
+
153
+ @staticmethod
154
+ def _sign_bytes_hex(secret_key: bytes, _input: str) -> bytes:
155
+ """Convenience function, same as _sign_bytes, but returns result in hex form."""
156
+ return binascii.hexlify(SnowflakeS3RestClient._sign_bytes(secret_key, _input))
157
+
158
+ @staticmethod
159
+ def _hash_bytes(_input: bytes) -> bytes:
160
+ """Applies SHA-256 hash to given bytes."""
161
+ digest = hashes.Hash(hashes.SHA256())
162
+ digest.update(_input)
163
+ return digest.finalize()
164
+
165
+ @staticmethod
166
+ def _hash_bytes_hex(_input: bytes) -> bytes:
167
+ """Convenience function, same as _hash_bytes, but returns result in hex form."""
168
+ return binascii.hexlify(SnowflakeS3RestClient._hash_bytes(_input))
169
+
170
+ @staticmethod
171
+ def _construct_query_string(
172
+ query_parts: tuple[tuple[str, str], ...],
173
+ ) -> str:
174
+ """Convenience function to build the query part of a URL from key-value pairs.
175
+
176
+ It filters out empty strings from the key, value pairs.
177
+ """
178
+ return "&".join(["=".join(filter(bool, e)) for e in query_parts])
179
+
180
+ @staticmethod
181
+ def _construct_canonicalized_and_signed_headers(
182
+ headers: dict[str, str | list[str]]
183
+ ) -> tuple[str, str]:
184
+ """Construct canonical headers as per AWS specs, returns the signed headers too.
185
+
186
+ Does not support sorting by values in case the keys are the same, don't send
187
+ in duplicate keys, but this is not possible with a dictionary anyways.
188
+ """
189
+ res = []
190
+ low_key_dict = {k.lower(): v for k, v in headers.items()}
191
+ sorted_headers = sorted(low_key_dict.keys())
192
+ _res = [(k, low_key_dict[k]) for k in sorted_headers]
193
+
194
+ for k, v in _res:
195
+ # if value is a list, convert to string delimited by comma
196
+ if isinstance(v, list):
197
+ v = ",".join(v)
198
+ # if multiline header, replace withs space
199
+ k = k.replace("\n", " ")
200
+ res.append(k.strip() + ":" + RE_MULTIPLE_SPACES.sub(" ", v.strip()))
201
+
202
+ ans = "\n".join(res)
203
+ if ans:
204
+ ans += "\n"
205
+
206
+ return ans, ";".join(sorted_headers)
207
+
208
+ @staticmethod
209
+ def _construct_canonical_request_and_signed_headers(
210
+ verb: str,
211
+ canonical_uri_parameter: str,
212
+ query_parts: dict[str, str],
213
+ canonical_headers: dict[str, str | list[str]] | None = None,
214
+ payload_hash: str = "",
215
+ ) -> tuple[str, str]:
216
+ """Build canonical request and also return signed headers.
217
+
218
+ Note: this doesn't support sorting by values in case the same key is given
219
+ more than once, but doing this is also not possible with a dictionary.
220
+ """
221
+ canonical_query_string = "&".join(
222
+ "=".join([k, v]) for k, v in sorted(query_parts.items(), key=itemgetter(0))
223
+ )
224
+ (
225
+ canonical_headers,
226
+ signed_headers,
227
+ ) = SnowflakeS3RestClient._construct_canonicalized_and_signed_headers(
228
+ canonical_headers
229
+ )
230
+
231
+ return (
232
+ "\n".join(
233
+ [
234
+ verb,
235
+ canonical_uri_parameter or "/",
236
+ canonical_query_string,
237
+ canonical_headers,
238
+ signed_headers,
239
+ payload_hash,
240
+ ]
241
+ ),
242
+ signed_headers,
243
+ )
244
+
245
+ @staticmethod
246
+ def _construct_string_to_sign(
247
+ region_name: str,
248
+ service_name: str,
249
+ amzdate: str,
250
+ short_amzdate: str,
251
+ canonical_request_hash: bytes,
252
+ ) -> tuple[str, str]:
253
+ """Given all the necessary information construct a V4 string to sign.
254
+
255
+ As per AWS specs it requires the scope, the hash of the canonical request and
256
+ the current date in the following format: YYYYMMDDTHHMMSSZ where T and Z are
257
+ constant characters.
258
+ This function generates the scope from the amzdate (which is just the date
259
+ portion of amzdate), region name and service we want to use (this is only s3
260
+ in our case).
261
+ """
262
+ scope = f"{short_amzdate}/{region_name}/{service_name}/aws4_request"
263
+ return (
264
+ "\n".join(
265
+ [
266
+ "AWS4-HMAC-SHA256",
267
+ amzdate,
268
+ scope,
269
+ canonical_request_hash.decode("utf-8"),
270
+ ]
271
+ ),
272
+ scope,
273
+ )
274
+
275
+ def _has_expired_token(self, response: requests.Response) -> bool:
276
+ """Extract error code and error message from the S3's error response.
277
+
278
+ Expected format:
279
+ https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#RESTErrorResponses
280
+
281
+ Args:
282
+ response: Rest error response in XML format
283
+
284
+ Returns: True if the error response is caused by token expiration
285
+
286
+ """
287
+ if response.status_code != 400:
288
+ return False
289
+ message = response.text
290
+ if not message or message.isspace():
291
+ return False
292
+ err = ET.fromstring(message)
293
+ return err.find("Code").text == EXPIRED_TOKEN
294
+
295
+ @staticmethod
296
+ def _extract_bucket_name_and_path(stage_location) -> S3Location:
297
+ # split stage location as bucket name and path
298
+ bucket_name, _, path = stage_location.partition("/")
299
+ if path and not path.endswith("/"):
300
+ path += "/"
301
+
302
+ return S3Location(bucket_name=bucket_name, path=path)
303
+
304
+ def _send_request_with_authentication_and_retry(
305
+ self,
306
+ url: str,
307
+ verb: str,
308
+ retry_id: int | str,
309
+ query_parts: dict[str, str] | None = None,
310
+ x_amz_headers: dict[str, str] | None = None,
311
+ headers: dict[str, str] | None = None,
312
+ payload: bytes | bytearray | IOBase | None = None,
313
+ unsigned_payload: bool = False,
314
+ ignore_content_encoding: bool = False,
315
+ ) -> requests.Response:
316
+ if x_amz_headers is None:
317
+ x_amz_headers = {}
318
+ if headers is None:
319
+ headers = {}
320
+ if payload is None:
321
+ payload = b""
322
+ if query_parts is None:
323
+ query_parts = {}
324
+ parsed_url = urlparse(url)
325
+ x_amz_headers["x-amz-security-token"] = self.credentials.creds.get(
326
+ "AWS_TOKEN", ""
327
+ )
328
+ x_amz_headers["host"] = parsed_url.hostname
329
+ if unsigned_payload:
330
+ x_amz_headers["x-amz-content-sha256"] = UNSIGNED_PAYLOAD
331
+ else:
332
+ x_amz_headers["x-amz-content-sha256"] = (
333
+ SnowflakeS3RestClient._hash_bytes_hex(payload).lower().decode()
334
+ )
335
+
336
+ def generate_authenticated_url_and_args_v4() -> tuple[bytes, dict[str, bytes]]:
337
+ t = datetime.now(timezone.utc).replace(tzinfo=None)
338
+ amzdate = t.strftime("%Y%m%dT%H%M%SZ")
339
+ short_amzdate = amzdate[:8]
340
+ x_amz_headers["x-amz-date"] = amzdate
341
+ x_amz_headers["x-amz-security-token"] = self.credentials.creds.get(
342
+ "AWS_TOKEN", ""
343
+ )
344
+
345
+ (
346
+ canonical_request,
347
+ signed_headers,
348
+ ) = self._construct_canonical_request_and_signed_headers(
349
+ verb=verb,
350
+ canonical_uri_parameter=parsed_url.path
351
+ + (f";{parsed_url.params}" if parsed_url.params else ""),
352
+ query_parts=query_parts,
353
+ canonical_headers=x_amz_headers,
354
+ payload_hash=x_amz_headers["x-amz-content-sha256"],
355
+ )
356
+ string_to_sign, scope = self._construct_string_to_sign(
357
+ self.region_name,
358
+ "s3",
359
+ amzdate,
360
+ short_amzdate,
361
+ self._hash_bytes_hex(canonical_request.encode("utf-8")).lower(),
362
+ )
363
+ kDate = self._sign_bytes(
364
+ ("AWS4" + self.credentials.creds["AWS_SECRET_KEY"]).encode("utf-8"),
365
+ short_amzdate,
366
+ )
367
+ kRegion = self._sign_bytes(kDate, self.region_name)
368
+ kService = self._sign_bytes(kRegion, "s3")
369
+ signing_key = self._sign_bytes(kService, "aws4_request")
370
+
371
+ signature = self._sign_bytes_hex(signing_key, string_to_sign).lower()
372
+ authorization_header = (
373
+ "AWS4-HMAC-SHA256 "
374
+ + f"Credential={self.credentials.creds['AWS_KEY_ID']}/{scope}, "
375
+ + f"SignedHeaders={signed_headers}, "
376
+ + f"Signature={signature.decode('utf-8')}"
377
+ )
378
+ headers.update(x_amz_headers)
379
+ headers["Authorization"] = authorization_header
380
+ rest_args = {"headers": headers}
381
+
382
+ if payload:
383
+ rest_args["data"] = payload
384
+
385
+ # add customized hook: to remove content-encoding from response.
386
+ if ignore_content_encoding:
387
+ rest_args["hooks"] = {"response": remove_content_encoding}
388
+
389
+ return url.encode("utf-8"), rest_args
390
+
391
+ return self._send_request_with_retry(
392
+ verb, generate_authenticated_url_and_args_v4, retry_id
393
+ )
394
+
395
+ def get_file_header(self, filename: str) -> FileHeader | None:
396
+ """Gets the metadata of file in specified location.
397
+
398
+ Args:
399
+ filename: Name of remote file.
400
+
401
+ Returns:
402
+ None if HEAD returns 404, otherwise a FileHeader instance populated
403
+ with metadata
404
+ """
405
+ path = quote(self.s3location.path + filename.lstrip("/"))
406
+ url = self.endpoint + f"/{path}"
407
+
408
+ retry_id = "HEAD"
409
+ self.retry_count[retry_id] = 0
410
+ response = self._send_request_with_authentication_and_retry(
411
+ url=url, verb="HEAD", retry_id=retry_id
412
+ )
413
+ if response.status_code == 200:
414
+ self.meta.result_status = ResultStatus.UPLOADED
415
+ metadata = response.headers
416
+ encryption_metadata = (
417
+ EncryptionMetadata(
418
+ key=metadata.get(META_PREFIX + AMZ_KEY),
419
+ iv=metadata.get(META_PREFIX + AMZ_IV),
420
+ matdesc=metadata.get(META_PREFIX + AMZ_MATDESC),
421
+ )
422
+ if metadata.get(META_PREFIX + AMZ_KEY)
423
+ else None
424
+ )
425
+ return FileHeader(
426
+ digest=metadata.get(META_PREFIX + SFC_DIGEST),
427
+ content_length=int(metadata.get("Content-Length")),
428
+ encryption_metadata=encryption_metadata,
429
+ )
430
+ elif response.status_code == 404:
431
+ logger.debug(
432
+ f"not found. bucket: {self.s3location.bucket_name}, path: {path}"
433
+ )
434
+ self.meta.result_status = ResultStatus.NOT_FOUND_FILE
435
+ return None
436
+ else:
437
+ response.raise_for_status()
438
+
439
+ def _prepare_file_metadata(self) -> dict[str, Any]:
440
+ """Construct metadata for a file to be uploaded.
441
+
442
+ Returns: File metadata in a dict.
443
+
444
+ """
445
+ s3_metadata = {
446
+ META_PREFIX + SFC_DIGEST: self.meta.sha256_digest,
447
+ }
448
+ if self.encryption_metadata:
449
+ s3_metadata.update(
450
+ {
451
+ META_PREFIX + AMZ_IV: self.encryption_metadata.iv,
452
+ META_PREFIX + AMZ_KEY: self.encryption_metadata.key,
453
+ META_PREFIX + AMZ_MATDESC: self.encryption_metadata.matdesc,
454
+ }
455
+ )
456
+ return s3_metadata
457
+
458
+ def _initiate_multipart_upload(self) -> None:
459
+ query_parts = (("uploads", ""),)
460
+ path = quote(self.s3location.path + self.meta.dst_file_name.lstrip("/"))
461
+ query_string = self._construct_query_string(query_parts)
462
+ url = self.endpoint + f"/{path}?{query_string}"
463
+ s3_metadata = self._prepare_file_metadata()
464
+ # initiate multipart upload
465
+ retry_id = "Initiate"
466
+ self.retry_count[retry_id] = 0
467
+ response = self._send_request_with_authentication_and_retry(
468
+ url=url,
469
+ verb="POST",
470
+ retry_id=retry_id,
471
+ x_amz_headers=s3_metadata,
472
+ headers={HTTP_HEADER_CONTENT_TYPE: HTTP_HEADER_VALUE_OCTET_STREAM},
473
+ query_parts=dict(query_parts),
474
+ )
475
+ if response.status_code == 200:
476
+ self.upload_id = ET.fromstring(response.content)[2].text
477
+ self.etags = [None] * self.num_of_chunks
478
+ else:
479
+ response.raise_for_status()
480
+
481
+ def _upload_chunk(self, chunk_id: int, chunk: bytes) -> None:
482
+ path = quote(self.s3location.path + self.meta.dst_file_name.lstrip("/"))
483
+ url = self.endpoint + f"/{path}"
484
+
485
+ if self.num_of_chunks == 1: # single request
486
+ s3_metadata = self._prepare_file_metadata()
487
+ response = self._send_request_with_authentication_and_retry(
488
+ url=url,
489
+ verb="PUT",
490
+ retry_id=chunk_id,
491
+ payload=chunk,
492
+ x_amz_headers=s3_metadata,
493
+ headers={HTTP_HEADER_CONTENT_TYPE: HTTP_HEADER_VALUE_OCTET_STREAM},
494
+ unsigned_payload=True,
495
+ )
496
+ response.raise_for_status()
497
+ else:
498
+ # multipart PUT
499
+ query_parts = (
500
+ ("partNumber", str(chunk_id + 1)),
501
+ ("uploadId", self.upload_id),
502
+ )
503
+ query_string = self._construct_query_string(query_parts)
504
+ chunk_url = f"{url}?{query_string}"
505
+ response = self._send_request_with_authentication_and_retry(
506
+ url=chunk_url,
507
+ verb="PUT",
508
+ retry_id=chunk_id,
509
+ payload=chunk,
510
+ unsigned_payload=True,
511
+ query_parts=dict(query_parts),
512
+ )
513
+ if response.status_code == 200:
514
+ self.etags[chunk_id] = response.headers["ETag"]
515
+ response.raise_for_status()
516
+
517
+ def _complete_multipart_upload(self) -> None:
518
+ query_parts = (("uploadId", self.upload_id),)
519
+ path = quote(self.s3location.path + self.meta.dst_file_name.lstrip("/"))
520
+ query_string = self._construct_query_string(query_parts)
521
+ url = self.endpoint + f"/{path}?{query_string}"
522
+ logger.debug("Initiating multipart upload complete")
523
+ # Complete multipart upload
524
+ root = ET.Element("CompleteMultipartUpload")
525
+ for idx, etag_str in enumerate(self.etags):
526
+ part = ET.Element("Part")
527
+ etag = ET.Element("ETag")
528
+ etag.text = etag_str
529
+ part.append(etag)
530
+ part_number = ET.Element("PartNumber")
531
+ part_number.text = str(idx + 1)
532
+ part.append(part_number)
533
+ root.append(part)
534
+ retry_id = "Complete"
535
+ self.retry_count[retry_id] = 0
536
+ response = self._send_request_with_authentication_and_retry(
537
+ url=url,
538
+ verb="POST",
539
+ retry_id=retry_id,
540
+ payload=ET.tostring(root),
541
+ query_parts=dict(query_parts),
542
+ )
543
+ response.raise_for_status()
544
+
545
+ def _abort_multipart_upload(self) -> None:
546
+ if self.upload_id is None:
547
+ return
548
+ query_parts = (("uploadId", self.upload_id),)
549
+ path = quote(self.s3location.path + self.meta.dst_file_name.lstrip("/"))
550
+ query_string = self._construct_query_string(query_parts)
551
+ url = self.endpoint + f"/{path}?{query_string}"
552
+
553
+ retry_id = "Abort"
554
+ self.retry_count[retry_id] = 0
555
+ response = self._send_request_with_authentication_and_retry(
556
+ url=url,
557
+ verb="DELETE",
558
+ retry_id=retry_id,
559
+ query_parts=dict(query_parts),
560
+ )
561
+ response.raise_for_status()
562
+
563
+ def download_chunk(self, chunk_id: int) -> None:
564
+ logger.debug(f"Downloading chunk {chunk_id}")
565
+ path = quote(self.s3location.path + self.meta.src_file_name.lstrip("/"))
566
+ url = self.endpoint + f"/{path}"
567
+ if self.num_of_chunks == 1:
568
+ response = self._send_request_with_authentication_and_retry(
569
+ url=url,
570
+ verb="GET",
571
+ retry_id=chunk_id,
572
+ ignore_content_encoding=True,
573
+ )
574
+ if response.status_code == 200:
575
+ self.write_downloaded_chunk(0, response.content)
576
+ self.meta.result_status = ResultStatus.DOWNLOADED
577
+ response.raise_for_status()
578
+ else:
579
+ chunk_size = self.chunk_size
580
+ if chunk_id < self.num_of_chunks - 1:
581
+ _range = f"{chunk_id * chunk_size}-{(chunk_id+1)*chunk_size-1}"
582
+ else:
583
+ _range = f"{chunk_id * chunk_size}-"
584
+
585
+ response = self._send_request_with_authentication_and_retry(
586
+ url=url,
587
+ verb="GET",
588
+ retry_id=chunk_id,
589
+ headers={"Range": f"bytes={_range}"},
590
+ )
591
+ if response.status_code in (200, 206):
592
+ self.write_downloaded_chunk(chunk_id, response.content)
593
+ response.raise_for_status()
594
+
595
+ def _get_bucket_accelerate_config(self, bucket_name: str) -> bool:
596
+ query_parts = (("accelerate", ""),)
597
+ query_string = self._construct_query_string(query_parts)
598
+ url = f"https://{bucket_name}.s3.amazonaws.com/?{query_string}"
599
+ retry_id = "accelerate"
600
+ self.retry_count[retry_id] = 0
601
+ response = self._send_request_with_authentication_and_retry(
602
+ url=url, verb="GET", retry_id=retry_id, query_parts=dict(query_parts)
603
+ )
604
+ if response.status_code == 200:
605
+ config = ET.fromstring(response.text)
606
+ namespace = config.tag[: config.tag.index("}") + 1]
607
+ statusTag = f"{namespace}Status"
608
+ found = config.find(statusTag)
609
+ use_accelerate_endpoint = (
610
+ False if found is None else (found.text == "Enabled")
611
+ )
612
+ logger.debug(f"use_accelerate_endpoint: {use_accelerate_endpoint}")
613
+ return use_accelerate_endpoint
614
+ return False