snowflake-connector-python 3.7.0__cp312-cp312-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 (219) hide show
  1. snowflake/connector/__init__.py +95 -0
  2. snowflake/connector/_query_context_cache.py +277 -0
  3. snowflake/connector/_sql_util.py +52 -0
  4. snowflake/connector/arrow_context.py +161 -0
  5. snowflake/connector/auth/__init__.py +42 -0
  6. snowflake/connector/auth/_auth.py +786 -0
  7. snowflake/connector/auth/by_plugin.py +219 -0
  8. snowflake/connector/auth/default.py +40 -0
  9. snowflake/connector/auth/idtoken.py +76 -0
  10. snowflake/connector/auth/keypair.py +215 -0
  11. snowflake/connector/auth/oauth.py +53 -0
  12. snowflake/connector/auth/okta.py +337 -0
  13. snowflake/connector/auth/usrpwdmfa.py +73 -0
  14. snowflake/connector/auth/webbrowser.py +439 -0
  15. snowflake/connector/azure_storage_client.py +252 -0
  16. snowflake/connector/backoff_policies.py +145 -0
  17. snowflake/connector/bind_upload_agent.py +76 -0
  18. snowflake/connector/cache.py +681 -0
  19. snowflake/connector/compat.py +131 -0
  20. snowflake/connector/config_manager.py +497 -0
  21. snowflake/connector/connection.py +1892 -0
  22. snowflake/connector/connection_diagnostic.py +729 -0
  23. snowflake/connector/constants.py +383 -0
  24. snowflake/connector/converter.py +781 -0
  25. snowflake/connector/converter_issue23517.py +91 -0
  26. snowflake/connector/converter_null.py +18 -0
  27. snowflake/connector/converter_snowsql.py +209 -0
  28. snowflake/connector/cursor.py +1785 -0
  29. snowflake/connector/dbapi.py +57 -0
  30. snowflake/connector/description.py +23 -0
  31. snowflake/connector/encryption_util.py +220 -0
  32. snowflake/connector/errorcode.py +87 -0
  33. snowflake/connector/errors.py +626 -0
  34. snowflake/connector/feature.py +7 -0
  35. snowflake/connector/file_compression_type.py +122 -0
  36. snowflake/connector/file_transfer_agent.py +1186 -0
  37. snowflake/connector/file_util.py +153 -0
  38. snowflake/connector/gcs_storage_client.py +395 -0
  39. snowflake/connector/gzip_decoder.py +89 -0
  40. snowflake/connector/local_storage_client.py +86 -0
  41. snowflake/connector/nanoarrow_arrow_iterator.cp312-win_amd64.pyd +0 -0
  42. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +23 -0
  43. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +30 -0
  44. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +25 -0
  45. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +27 -0
  46. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +459 -0
  47. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +97 -0
  48. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +129 -0
  49. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +119 -0
  50. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +959 -0
  51. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +141 -0
  52. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +51 -0
  53. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +50 -0
  54. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +91 -0
  55. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +76 -0
  56. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +77 -0
  57. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +32 -0
  58. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +34 -0
  59. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +39 -0
  60. snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +21 -0
  61. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +27 -0
  62. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +49 -0
  63. snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  64. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +12 -0
  65. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +99 -0
  66. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +61 -0
  67. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +40 -0
  68. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
  69. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  70. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +23 -0
  71. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +30 -0
  72. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +40 -0
  73. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +35 -0
  74. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +350 -0
  75. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +149 -0
  76. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +18 -0
  77. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +69 -0
  78. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +72 -0
  79. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
  80. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
  81. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  82. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
  83. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
  84. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
  85. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  86. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
  87. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
  88. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  89. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  90. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  91. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
  92. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
  93. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
  94. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  95. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
  96. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
  97. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
  98. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  99. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  100. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
  101. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
  102. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  103. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  104. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  105. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  106. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  107. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
  108. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
  109. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
  110. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  111. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  112. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
  113. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
  114. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
  115. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
  116. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +253 -0
  117. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
  118. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
  119. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33260 -0
  120. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
  121. snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +104 -0
  122. snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +53 -0
  123. snowflake/connector/network.py +1231 -0
  124. snowflake/connector/ocsp_asn1crypto.py +428 -0
  125. snowflake/connector/ocsp_snowflake.py +1728 -0
  126. snowflake/connector/options.py +131 -0
  127. snowflake/connector/pandas_tools.py +551 -0
  128. snowflake/connector/proxy.py +47 -0
  129. snowflake/connector/py.typed +0 -0
  130. snowflake/connector/result_batch.py +735 -0
  131. snowflake/connector/result_set.py +270 -0
  132. snowflake/connector/s3_storage_client.py +585 -0
  133. snowflake/connector/secret_detector.py +162 -0
  134. snowflake/connector/sf_dirs.py +69 -0
  135. snowflake/connector/sfbinaryformat.py +39 -0
  136. snowflake/connector/sfdatetime.py +349 -0
  137. snowflake/connector/snow_logging.py +148 -0
  138. snowflake/connector/sqlstate.py +13 -0
  139. snowflake/connector/ssd_internal_keys.py +34 -0
  140. snowflake/connector/ssl_wrap_socket.py +139 -0
  141. snowflake/connector/storage_client.py +460 -0
  142. snowflake/connector/telemetry.py +253 -0
  143. snowflake/connector/telemetry_oob.py +547 -0
  144. snowflake/connector/test_util.py +34 -0
  145. snowflake/connector/time_util.py +163 -0
  146. snowflake/connector/tool/__init__.py +3 -0
  147. snowflake/connector/tool/dump_certs.py +61 -0
  148. snowflake/connector/tool/dump_ocsp_response.py +126 -0
  149. snowflake/connector/tool/dump_ocsp_response_cache.py +198 -0
  150. snowflake/connector/tool/probe_connection.py +73 -0
  151. snowflake/connector/url_util.py +43 -0
  152. snowflake/connector/util_text.py +281 -0
  153. snowflake/connector/vendored/__init__.py +3 -0
  154. snowflake/connector/vendored/requests/LICENSE +175 -0
  155. snowflake/connector/vendored/requests/__init__.py +170 -0
  156. snowflake/connector/vendored/requests/__version__.py +14 -0
  157. snowflake/connector/vendored/requests/_internal_utils.py +50 -0
  158. snowflake/connector/vendored/requests/adapters.py +538 -0
  159. snowflake/connector/vendored/requests/api.py +157 -0
  160. snowflake/connector/vendored/requests/auth.py +315 -0
  161. snowflake/connector/vendored/requests/certs.py +17 -0
  162. snowflake/connector/vendored/requests/compat.py +79 -0
  163. snowflake/connector/vendored/requests/cookies.py +561 -0
  164. snowflake/connector/vendored/requests/exceptions.py +141 -0
  165. snowflake/connector/vendored/requests/help.py +134 -0
  166. snowflake/connector/vendored/requests/hooks.py +33 -0
  167. snowflake/connector/vendored/requests/models.py +1034 -0
  168. snowflake/connector/vendored/requests/sessions.py +833 -0
  169. snowflake/connector/vendored/requests/status_codes.py +128 -0
  170. snowflake/connector/vendored/requests/structures.py +99 -0
  171. snowflake/connector/vendored/requests/utils.py +1094 -0
  172. snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
  173. snowflake/connector/vendored/urllib3/__init__.py +85 -0
  174. snowflake/connector/vendored/urllib3/_collections.py +355 -0
  175. snowflake/connector/vendored/urllib3/_version.py +2 -0
  176. snowflake/connector/vendored/urllib3/connection.py +572 -0
  177. snowflake/connector/vendored/urllib3/connectionpool.py +1137 -0
  178. snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
  179. snowflake/connector/vendored/urllib3/contrib/_appengine_environ.py +36 -0
  180. snowflake/connector/vendored/urllib3/contrib/_securetransport/__init__.py +0 -0
  181. snowflake/connector/vendored/urllib3/contrib/_securetransport/bindings.py +519 -0
  182. snowflake/connector/vendored/urllib3/contrib/_securetransport/low_level.py +397 -0
  183. snowflake/connector/vendored/urllib3/contrib/appengine.py +314 -0
  184. snowflake/connector/vendored/urllib3/contrib/ntlmpool.py +130 -0
  185. snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +509 -0
  186. snowflake/connector/vendored/urllib3/contrib/securetransport.py +920 -0
  187. snowflake/connector/vendored/urllib3/contrib/socks.py +216 -0
  188. snowflake/connector/vendored/urllib3/exceptions.py +323 -0
  189. snowflake/connector/vendored/urllib3/fields.py +274 -0
  190. snowflake/connector/vendored/urllib3/filepost.py +98 -0
  191. snowflake/connector/vendored/urllib3/packages/__init__.py +0 -0
  192. snowflake/connector/vendored/urllib3/packages/backports/__init__.py +0 -0
  193. snowflake/connector/vendored/urllib3/packages/backports/makefile.py +51 -0
  194. snowflake/connector/vendored/urllib3/packages/backports/weakref_finalize.py +155 -0
  195. snowflake/connector/vendored/urllib3/packages/six.py +1076 -0
  196. snowflake/connector/vendored/urllib3/poolmanager.py +540 -0
  197. snowflake/connector/vendored/urllib3/request.py +191 -0
  198. snowflake/connector/vendored/urllib3/response.py +885 -0
  199. snowflake/connector/vendored/urllib3/util/__init__.py +49 -0
  200. snowflake/connector/vendored/urllib3/util/connection.py +156 -0
  201. snowflake/connector/vendored/urllib3/util/proxy.py +57 -0
  202. snowflake/connector/vendored/urllib3/util/queue.py +22 -0
  203. snowflake/connector/vendored/urllib3/util/request.py +146 -0
  204. snowflake/connector/vendored/urllib3/util/response.py +107 -0
  205. snowflake/connector/vendored/urllib3/util/retry.py +620 -0
  206. snowflake/connector/vendored/urllib3/util/ssl_.py +495 -0
  207. snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
  208. snowflake/connector/vendored/urllib3/util/ssltransport.py +221 -0
  209. snowflake/connector/vendored/urllib3/util/timeout.py +271 -0
  210. snowflake/connector/vendored/urllib3/util/url.py +435 -0
  211. snowflake/connector/vendored/urllib3/util/wait.py +152 -0
  212. snowflake/connector/version.py +3 -0
  213. snowflake_connector_python-3.7.0.dist-info/LICENSE.txt +202 -0
  214. snowflake_connector_python-3.7.0.dist-info/METADATA +1309 -0
  215. snowflake_connector_python-3.7.0.dist-info/NOTICE +8 -0
  216. snowflake_connector_python-3.7.0.dist-info/RECORD +219 -0
  217. snowflake_connector_python-3.7.0.dist-info/WHEEL +5 -0
  218. snowflake_connector_python-3.7.0.dist-info/entry_points.txt +5 -0
  219. snowflake_connector_python-3.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
4
+ #
5
+
6
+ # Python Db API v2
7
+ #
8
+ from __future__ import annotations
9
+
10
+ from functools import wraps
11
+
12
+ apilevel = "2.0"
13
+ threadsafety = 2
14
+ paramstyle = "pyformat"
15
+
16
+ import logging
17
+ from logging import NullHandler
18
+
19
+ from .connection import SnowflakeConnection
20
+ from .cursor import DictCursor
21
+ from .dbapi import (
22
+ BINARY,
23
+ DATETIME,
24
+ NUMBER,
25
+ ROWID,
26
+ STRING,
27
+ Binary,
28
+ Date,
29
+ DateFromTicks,
30
+ Time,
31
+ TimeFromTicks,
32
+ Timestamp,
33
+ TimestampFromTicks,
34
+ )
35
+ from .errors import (
36
+ DatabaseError,
37
+ DataError,
38
+ Error,
39
+ IntegrityError,
40
+ InterfaceError,
41
+ InternalError,
42
+ NotSupportedError,
43
+ OperationalError,
44
+ ProgrammingError,
45
+ _Warning,
46
+ )
47
+ from .version import VERSION
48
+
49
+ logging.getLogger(__name__).addHandler(NullHandler())
50
+
51
+
52
+ @wraps(SnowflakeConnection.__init__)
53
+ def Connect(**kwargs) -> SnowflakeConnection:
54
+ return SnowflakeConnection(**kwargs)
55
+
56
+
57
+ connect = Connect
58
+
59
+ SNOWFLAKE_CONNECTOR_VERSION = ".".join(str(v) for v in VERSION[0:3])
60
+ __version__ = SNOWFLAKE_CONNECTOR_VERSION
61
+
62
+ __all__ = [
63
+ "SnowflakeConnection",
64
+ # Error handling
65
+ "Error",
66
+ "_Warning",
67
+ "InterfaceError",
68
+ "DatabaseError",
69
+ "NotSupportedError",
70
+ "DataError",
71
+ "IntegrityError",
72
+ "ProgrammingError",
73
+ "OperationalError",
74
+ "InternalError",
75
+ # Extended cursor
76
+ "DictCursor",
77
+ # DBAPI PEP 249 required exports
78
+ "connect",
79
+ "apilevel",
80
+ "threadsafety",
81
+ "paramstyle",
82
+ "Date",
83
+ "Time",
84
+ "Timestamp",
85
+ "Binary",
86
+ "DateFromTicks",
87
+ "TimeFromTicks",
88
+ "TimestampFromTicks",
89
+ "STRING",
90
+ "BINARY",
91
+ "NUMBER",
92
+ "DATETIME",
93
+ "ROWID",
94
+ # Extended data type (experimental)
95
+ ]
@@ -0,0 +1,277 @@
1
+ #
2
+ # Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
3
+ #
4
+ from __future__ import annotations
5
+
6
+ from functools import total_ordering
7
+ from hashlib import md5
8
+ from logging import getLogger
9
+ from threading import Lock
10
+ from typing import Any, Iterable
11
+
12
+ from sortedcontainers import SortedSet
13
+
14
+ logger = getLogger(__name__)
15
+
16
+
17
+ @total_ordering
18
+ class QueryContextElement:
19
+ def __init__(
20
+ self, id: int, read_timestamp: int, priority: int, context: str
21
+ ) -> None:
22
+ # entry with id = 0 is the main entry
23
+ self.id = id
24
+ self.read_timestamp = read_timestamp
25
+ # priority values are 0..N with 0 being the highest priority
26
+ self.priority = priority
27
+ # OpaqueContext field will be base64 encoded in GS, but it is opaque to client side. Client side should not do decoding/encoding and just store the raw data.
28
+ self.context = context
29
+
30
+ def __eq__(self, other: object) -> bool:
31
+ if not isinstance(other, QueryContextElement):
32
+ return False
33
+ return (
34
+ self.id == other.id
35
+ and self.read_timestamp == other.read_timestamp
36
+ and self.priority == other.priority
37
+ and self.context == other.context
38
+ )
39
+
40
+ def __lt__(self, other: Any) -> bool:
41
+ if not isinstance(other, QueryContextElement):
42
+ raise TypeError(
43
+ f"cannot compare QueryContextElement with object of type {type(other)}"
44
+ )
45
+ return self.priority < other.priority
46
+
47
+ def __hash__(self) -> int:
48
+ _hash = 31
49
+
50
+ _hash = _hash * 31 + self.id
51
+ _hash += (_hash * 31) + self.read_timestamp
52
+ _hash += (_hash * 31) + self.priority
53
+ if self.context:
54
+ _hash += (_hash * 31) + int.from_bytes(
55
+ md5(self.context.encode("utf-8")).digest(), "big"
56
+ )
57
+ return _hash
58
+
59
+ def __str__(self) -> str:
60
+ return f"({self.id}, {self.read_timestamp}, {self.priority})"
61
+
62
+
63
+ class QueryContextCache:
64
+ def __init__(self, capacity: int) -> None:
65
+ self.capacity = capacity
66
+ self._id_map: dict[int, QueryContextElement] = {}
67
+ self._priority_map: dict[int, QueryContextElement] = {}
68
+ self._intermediate_priority_map: dict[int, QueryContextElement] = {}
69
+
70
+ # stores elements sorted by priority. Element with
71
+ # least priority value has the highest priority
72
+ self._tree_set: set[QueryContextElement] = SortedSet()
73
+ self._lock = Lock()
74
+ self._data: str = None
75
+
76
+ def _add_qce(self, qce: QueryContextElement) -> None:
77
+ """Adds qce element in tree_set, id_map and intermediate_priority_map.
78
+ We still need to add _sync_priority_map after all the new qce have been merged
79
+ into the cache.
80
+ """
81
+ self._tree_set.add(qce)
82
+ self._id_map[qce.id] = qce
83
+ self._intermediate_priority_map[qce.priority] = qce
84
+
85
+ def _remove_qce(self, qce: QueryContextElement) -> None:
86
+ self._id_map.pop(qce.id)
87
+ self._priority_map.pop(qce.priority)
88
+ self._tree_set.remove(qce)
89
+
90
+ def _replace_qce(
91
+ self, old_qce: QueryContextElement, new_qce: QueryContextElement
92
+ ) -> None:
93
+ """This is just a convenience function to call a remove and add operation back-to-back"""
94
+ self._remove_qce(old_qce)
95
+ self._add_qce(new_qce)
96
+
97
+ def _sync_priority_map(self):
98
+ """
99
+ Sync the _intermediate_priority_map with the _priority_map at the end of the current round of inserts.
100
+ """
101
+ logger.debug(
102
+ f"sync_priority_map called priority_map size = {len(self._priority_map)}, new_priority_map size = {len(self._intermediate_priority_map)}"
103
+ )
104
+
105
+ self._priority_map.update(self._intermediate_priority_map)
106
+ # Clear the _intermediate_priority_map for the next round of QCC insert (a round consists of multiple entries)
107
+ self._intermediate_priority_map.clear()
108
+
109
+ def insert(self, id: int, read_timestamp: int, priority: int, context: str) -> None:
110
+ if id in self._id_map:
111
+ qce = self._id_map[id]
112
+ if (read_timestamp > qce.read_timestamp) or (
113
+ read_timestamp == qce.read_timestamp and priority != qce.priority
114
+ ):
115
+ # when id if found in cache and we are operating on a more recent timestamp. We do not update in-place here.
116
+ new_qce = QueryContextElement(id, read_timestamp, priority, context)
117
+ self._replace_qce(qce, new_qce)
118
+ else:
119
+ new_qce = QueryContextElement(id, read_timestamp, priority, context)
120
+ if priority in self._priority_map:
121
+ old_qce = self._priority_map[priority]
122
+ self._replace_qce(old_qce, new_qce)
123
+ else:
124
+ self._add_qce(new_qce)
125
+
126
+ def trim_cache(self) -> None:
127
+ logger.debug(
128
+ f"trim_cache() called. treeSet size is {len(self._tree_set)} and cache capacity is {self.capacity}"
129
+ )
130
+
131
+ while len(self) > self.capacity:
132
+ # remove the qce with highest priority value => element with least priority
133
+ qce = self._last()
134
+ self._remove_qce(qce)
135
+
136
+ logger.debug(
137
+ f"trim_cache() returns. treeSet size is {len(self._tree_set)} and cache capacity is {self.capacity}"
138
+ )
139
+
140
+ def clear_cache(self) -> None:
141
+ logger.debug("clear_cache() called")
142
+ self._id_map.clear()
143
+ self._priority_map.clear()
144
+ self._tree_set.clear()
145
+ self._intermediate_priority_map.clear()
146
+
147
+ def _get_elements(self) -> Iterable[QueryContextElement]:
148
+ return self._tree_set
149
+
150
+ def _last(self) -> QueryContextElement:
151
+ return self._tree_set[-1]
152
+
153
+ def serialize_to_dict(self) -> dict:
154
+ with self._lock:
155
+ logger.debug("serialize_to_dict() called")
156
+ self.log_cache_entries()
157
+
158
+ if len(self._tree_set) == 0:
159
+ return {} # we should return an empty dict
160
+
161
+ try:
162
+ data = {
163
+ "entries": [
164
+ {
165
+ "id": qce.id,
166
+ "timestamp": qce.read_timestamp,
167
+ "priority": qce.priority,
168
+ "context": {"base64Data": qce.context}
169
+ if qce.context is not None
170
+ else {},
171
+ }
172
+ for qce in self._tree_set
173
+ ]
174
+ }
175
+ # Because on GS side, `context` field is an object with `base64Data` string member variable,
176
+ # we should serialize `context` field to an object instead of string directly to stay consistent with GS side.
177
+
178
+ logger.debug(f"serialize_to_dict(): data to send to server {data}")
179
+
180
+ # query context shoule be an object field of the HTTP request body JSON and on GS side. here we should only return a dict
181
+ # and let the outer HTTP request body to convert the entire big dict to a single JSON.
182
+ return data
183
+ except Exception as e:
184
+ logger.debug(f"serialize_to_dict(): Exception {e}")
185
+ return {}
186
+
187
+ def deserialize_json_dict(self, data: dict) -> None:
188
+ with self._lock:
189
+ logger.debug(f"deserialize_json_dict() called: data from server: {data}")
190
+ self.log_cache_entries()
191
+
192
+ if data is None or len(data) == 0:
193
+ self.clear_cache()
194
+ logger.debug("deserialize_json_dict() returns")
195
+ self.log_cache_entries()
196
+ return
197
+
198
+ try:
199
+ # Deserialize the entries. The first entry with priority 0 is the main entry. On python
200
+ # connector side, we save all entries into one list to simplify the logic. When python
201
+ # connector receives HTTP response, the data["queryContext"] field has been converted
202
+ # from JSON to dict type automatically, so for this function we deserialize from python
203
+ # dict directly. Below is an example QueryContext dict.
204
+ # {
205
+ # "entries": [
206
+ # {
207
+ # "id": 0,
208
+ # "read_timestamp": 123456789,
209
+ # "priority": 0,
210
+ # "context": "base64 encoded context"
211
+ # },
212
+ # {
213
+ # "id": 1,
214
+ # "read_timestamp": 123456789,
215
+ # "priority": 1,
216
+ # "context": "base64 encoded context"
217
+ # },
218
+ # {
219
+ # "id": 2,
220
+ # "read_timestamp": 123456789,
221
+ # "priority": 2,
222
+ # "context": "base64 encoded context"
223
+ # }
224
+ # ]
225
+ # }
226
+
227
+ # Deserialize entries
228
+ entries = data.get("entries", list())
229
+ for entry in entries:
230
+ logger.debug(f"deserialize {entry}")
231
+ if not isinstance(entry.get("id"), int):
232
+ logger.debug("id type error")
233
+ raise TypeError(
234
+ f"Invalid type for 'id' field: Expected int, got {type(entry['id'])}"
235
+ )
236
+ if not isinstance(entry.get("timestamp"), int):
237
+ logger.debug("timestamp type error")
238
+ raise TypeError(
239
+ f"Invalid type for 'timestamp' field: Expected int, got {type(entry['timestamp'])}"
240
+ )
241
+ if not isinstance(entry.get("priority"), int):
242
+ logger.debug("priority type error")
243
+ raise TypeError(
244
+ f"Invalid type for 'priority' field: Expected int, got {type(entry['priority'])}"
245
+ )
246
+
247
+ # OpaqueContext field currently is empty from GS side.
248
+ context = entry.get("context", None)
249
+ if context and not isinstance(entry.get("context"), str):
250
+ logger.debug("context type error")
251
+ raise TypeError(
252
+ f"Invalid type for 'context' field: Expected str, got {type(entry['context'])}"
253
+ )
254
+ self.insert(
255
+ entry.get("id"),
256
+ entry.get("timestamp"),
257
+ entry.get("priority"),
258
+ context,
259
+ )
260
+
261
+ # Sync the priority map at the end of for loop insert.
262
+ self._sync_priority_map()
263
+ except Exception as e:
264
+ logger.debug(f"deserialize_json_dict: Exception = {e}")
265
+ # clear cache due to incomplete insert
266
+ self.clear_cache()
267
+
268
+ self.trim_cache()
269
+ logger.debug("deserialize_json_dict() returns")
270
+ self.log_cache_entries()
271
+
272
+ def log_cache_entries(self) -> None:
273
+ for qce in self._tree_set:
274
+ logger.debug(f"Cache Entry: {str(qce)}")
275
+
276
+ def __len__(self) -> int:
277
+ return len(self._tree_set)
@@ -0,0 +1,52 @@
1
+ #
2
+ # Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
3
+ #
4
+
5
+ from __future__ import annotations
6
+
7
+ import re
8
+
9
+ from .constants import FileTransferType
10
+
11
+ COMMENT_START_SQL_RE = re.compile(
12
+ r"""
13
+ ^\s*(?:
14
+ /\*[\w\W]*?\*/
15
+ )""",
16
+ re.VERBOSE,
17
+ )
18
+
19
+ PUT_SQL_RE = re.compile(r"^\s*put", flags=re.IGNORECASE)
20
+ GET_SQL_RE = re.compile(r"^\s*get", flags=re.IGNORECASE)
21
+
22
+
23
+ def remove_starting_comments(sql: str) -> str:
24
+ """Remove all comments from the start of a SQL statement."""
25
+ commentless_sql = sql
26
+ while True:
27
+ start_comment = COMMENT_START_SQL_RE.match(commentless_sql)
28
+ if start_comment is None:
29
+ break
30
+ commentless_sql = commentless_sql[start_comment.end() :]
31
+ return commentless_sql
32
+
33
+
34
+ def get_file_transfer_type(sql: str) -> FileTransferType | None:
35
+ """Decide whether a SQL is a file transfer and return its type.
36
+
37
+ None is returned if the SQL isn't a file transfer so that this function can be
38
+ used in an if-statement.
39
+ """
40
+ commentless_sql = remove_starting_comments(sql)
41
+ if PUT_SQL_RE.match(commentless_sql):
42
+ return FileTransferType.PUT
43
+ elif GET_SQL_RE.match(commentless_sql):
44
+ return FileTransferType.GET
45
+
46
+
47
+ def is_put_statement(sql: str) -> bool:
48
+ return get_file_transfer_type(sql) == FileTransferType.PUT
49
+
50
+
51
+ def is_get_statement(sql: str) -> bool:
52
+ return get_file_transfer_type(sql) == FileTransferType.GET
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
4
+ #
5
+
6
+ from __future__ import annotations
7
+
8
+ import decimal
9
+ import time
10
+ from datetime import datetime, timedelta, timezone, tzinfo
11
+ from logging import getLogger
12
+ from sys import byteorder
13
+ from typing import TYPE_CHECKING
14
+
15
+ import pytz
16
+ from pytz import UTC
17
+
18
+ from .constants import PARAMETER_TIMEZONE
19
+ from .converter import _generate_tzinfo_from_tzoffset
20
+
21
+ if TYPE_CHECKING:
22
+ from numpy import datetime64, float64, int64
23
+
24
+
25
+ try:
26
+ import numpy
27
+ except ImportError:
28
+ numpy = None
29
+
30
+
31
+ try:
32
+ import tzlocal
33
+ except ImportError:
34
+ tzlocal = None
35
+
36
+ ZERO_EPOCH = datetime.fromtimestamp(0, timezone.utc).replace(tzinfo=None)
37
+
38
+ logger = getLogger(__name__)
39
+
40
+
41
+ class ArrowConverterContext:
42
+ """Python helper functions for arrow conversions.
43
+
44
+ Windows timestamp functions are necessary because Windows cannot handle -ve timestamps.
45
+ Putting the OS check into the non-windows function would probably take up more CPU cycles then
46
+ just deciding this at compile time.
47
+ """
48
+
49
+ def __init__(
50
+ self,
51
+ session_parameters: dict[str, str | int | bool] | None = None,
52
+ ) -> None:
53
+ if session_parameters is None:
54
+ session_parameters = {}
55
+ self._timezone = (
56
+ None
57
+ if PARAMETER_TIMEZONE not in session_parameters
58
+ else session_parameters[PARAMETER_TIMEZONE]
59
+ )
60
+
61
+ @property
62
+ def timezone(self) -> str:
63
+ return self._timezone
64
+
65
+ @timezone.setter
66
+ def timezone(self, tz) -> None:
67
+ self._timezone = tz
68
+
69
+ def _get_session_tz(self) -> tzinfo | UTC:
70
+ """Get the session timezone or use the local computer's timezone."""
71
+ try:
72
+ tz = "UTC" if not self.timezone else self.timezone
73
+ return pytz.timezone(tz)
74
+ except pytz.exceptions.UnknownTimeZoneError:
75
+ logger.warning("converting to tzinfo failed")
76
+ if tzlocal is not None:
77
+ return tzlocal.get_localzone()
78
+ else:
79
+ try:
80
+ return datetime.timezone.utc
81
+ except AttributeError:
82
+ return pytz.timezone("UTC")
83
+
84
+ def TIMESTAMP_TZ_to_python(
85
+ self, epoch: int, microseconds: int, tz: int
86
+ ) -> datetime:
87
+ tzinfo = _generate_tzinfo_from_tzoffset(tz - 1440)
88
+ return datetime.fromtimestamp(epoch, tz=tzinfo) + timedelta(
89
+ microseconds=microseconds
90
+ )
91
+
92
+ def TIMESTAMP_TZ_to_python_windows(
93
+ self, epoch: int, microseconds: int, tz: int
94
+ ) -> datetime:
95
+ tzinfo = _generate_tzinfo_from_tzoffset(tz - 1440)
96
+ t = ZERO_EPOCH + timedelta(seconds=epoch, microseconds=microseconds)
97
+ if pytz.utc != tzinfo:
98
+ t += tzinfo.utcoffset(t)
99
+ return t.replace(tzinfo=tzinfo)
100
+
101
+ def TIMESTAMP_NTZ_to_python(self, epoch: int, microseconds: int) -> datetime:
102
+ return datetime.fromtimestamp(epoch, timezone.utc).replace(
103
+ tzinfo=None
104
+ ) + timedelta(microseconds=microseconds)
105
+
106
+ def TIMESTAMP_NTZ_to_python_windows(
107
+ self, epoch: int, microseconds: int
108
+ ) -> datetime:
109
+ return ZERO_EPOCH + timedelta(seconds=epoch, microseconds=microseconds)
110
+
111
+ def TIMESTAMP_LTZ_to_python(self, epoch: int, microseconds: int) -> datetime:
112
+ tzinfo = self._get_session_tz()
113
+ return datetime.fromtimestamp(epoch, tz=tzinfo) + timedelta(
114
+ microseconds=microseconds
115
+ )
116
+
117
+ def TIMESTAMP_LTZ_to_python_windows(
118
+ self, epoch: int, microseconds: int
119
+ ) -> datetime:
120
+ try:
121
+ tzinfo = self._get_session_tz()
122
+ ts = ZERO_EPOCH + timedelta(seconds=epoch, microseconds=microseconds)
123
+ return pytz.utc.localize(ts, is_dst=False).astimezone(tzinfo)
124
+ except OverflowError:
125
+ logger.debug(
126
+ "OverflowError in converting from epoch time to "
127
+ "timestamp_ltz: %s(ms). Falling back to use struct_time."
128
+ )
129
+ return time.localtime(microseconds)
130
+
131
+ def REAL_to_numpy_float64(self, py_double: float) -> float64:
132
+ return numpy.float64(py_double)
133
+
134
+ def FIXED_to_numpy_int64(self, py_long: int) -> int64:
135
+ return numpy.int64(py_long)
136
+
137
+ def FIXED_to_numpy_float64(self, py_long: int, scale: int) -> float64:
138
+ return numpy.float64(decimal.Decimal(py_long).scaleb(-scale))
139
+
140
+ def DATE_to_numpy_datetime64(self, py_days: int) -> datetime64:
141
+ return numpy.datetime64(py_days, "D")
142
+
143
+ def TIMESTAMP_NTZ_ONE_FIELD_to_numpy_datetime64(
144
+ self, value: int, scale: int
145
+ ) -> datetime64:
146
+ nanoseconds = int(decimal.Decimal(value).scaleb(9 - scale))
147
+ return numpy.datetime64(nanoseconds, "ns")
148
+
149
+ def TIMESTAMP_NTZ_TWO_FIELD_to_numpy_datetime64(
150
+ self, epoch: int, fraction: int
151
+ ) -> datetime64:
152
+ nanoseconds = int(decimal.Decimal(epoch).scaleb(9) + decimal.Decimal(fraction))
153
+ return numpy.datetime64(nanoseconds, "ns")
154
+
155
+ def DECIMAL128_to_decimal(self, int128_bytes: bytes, scale: int) -> decimal.Decimal:
156
+ int128 = int.from_bytes(int128_bytes, byteorder=byteorder, signed=True)
157
+ if scale == 0:
158
+ return int128
159
+ digits = [int(digit) for digit in str(int128) if digit != "-"]
160
+ sign = int128 < 0
161
+ return decimal.Decimal((sign, digits, -scale))
@@ -0,0 +1,42 @@
1
+ #
2
+ # Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
3
+ #
4
+
5
+ from __future__ import annotations
6
+
7
+ from ._auth import Auth, get_public_key_fingerprint, get_token_from_private_key
8
+ from .by_plugin import AuthByPlugin, AuthType
9
+ from .default import AuthByDefault
10
+ from .idtoken import AuthByIdToken
11
+ from .keypair import AuthByKeyPair
12
+ from .oauth import AuthByOAuth
13
+ from .okta import AuthByOkta
14
+ from .usrpwdmfa import AuthByUsrPwdMfa
15
+ from .webbrowser import AuthByWebBrowser
16
+
17
+ FIRST_PARTY_AUTHENTICATORS = frozenset(
18
+ (
19
+ AuthByDefault,
20
+ AuthByKeyPair,
21
+ AuthByOAuth,
22
+ AuthByOkta,
23
+ AuthByUsrPwdMfa,
24
+ AuthByWebBrowser,
25
+ AuthByIdToken,
26
+ )
27
+ )
28
+
29
+ __all__ = [
30
+ "AuthByPlugin",
31
+ "AuthByDefault",
32
+ "AuthByKeyPair",
33
+ "AuthByOAuth",
34
+ "AuthByOkta",
35
+ "AuthByUsrPwdMfa",
36
+ "AuthByWebBrowser",
37
+ "Auth",
38
+ "AuthType",
39
+ "FIRST_PARTY_AUTHENTICATORS",
40
+ "get_public_key_fingerprint",
41
+ "get_token_from_private_key",
42
+ ]