polars-runtime-compat 1.34.0b2__cp39-abi3-win_arm64.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.

Potentially problematic release.


This version of polars-runtime-compat might be problematic. Click here for more details.

Files changed (203) hide show
  1. _polars_runtime_compat/.gitkeep +0 -0
  2. _polars_runtime_compat/_polars_runtime_compat.pyd +0 -0
  3. polars/__init__.py +528 -0
  4. polars/_cpu_check.py +265 -0
  5. polars/_dependencies.py +355 -0
  6. polars/_plr.py +99 -0
  7. polars/_plr.pyi +2496 -0
  8. polars/_reexport.py +23 -0
  9. polars/_typing.py +478 -0
  10. polars/_utils/__init__.py +37 -0
  11. polars/_utils/async_.py +102 -0
  12. polars/_utils/cache.py +176 -0
  13. polars/_utils/cloud.py +40 -0
  14. polars/_utils/constants.py +29 -0
  15. polars/_utils/construction/__init__.py +46 -0
  16. polars/_utils/construction/dataframe.py +1397 -0
  17. polars/_utils/construction/other.py +72 -0
  18. polars/_utils/construction/series.py +560 -0
  19. polars/_utils/construction/utils.py +118 -0
  20. polars/_utils/convert.py +224 -0
  21. polars/_utils/deprecation.py +406 -0
  22. polars/_utils/getitem.py +457 -0
  23. polars/_utils/logging.py +11 -0
  24. polars/_utils/nest_asyncio.py +264 -0
  25. polars/_utils/parquet.py +15 -0
  26. polars/_utils/parse/__init__.py +12 -0
  27. polars/_utils/parse/expr.py +242 -0
  28. polars/_utils/polars_version.py +19 -0
  29. polars/_utils/pycapsule.py +53 -0
  30. polars/_utils/scan.py +27 -0
  31. polars/_utils/serde.py +63 -0
  32. polars/_utils/slice.py +215 -0
  33. polars/_utils/udfs.py +1251 -0
  34. polars/_utils/unstable.py +63 -0
  35. polars/_utils/various.py +782 -0
  36. polars/_utils/wrap.py +25 -0
  37. polars/api.py +370 -0
  38. polars/catalog/__init__.py +0 -0
  39. polars/catalog/unity/__init__.py +19 -0
  40. polars/catalog/unity/client.py +733 -0
  41. polars/catalog/unity/models.py +152 -0
  42. polars/config.py +1571 -0
  43. polars/convert/__init__.py +25 -0
  44. polars/convert/general.py +1046 -0
  45. polars/convert/normalize.py +261 -0
  46. polars/dataframe/__init__.py +5 -0
  47. polars/dataframe/_html.py +186 -0
  48. polars/dataframe/frame.py +12582 -0
  49. polars/dataframe/group_by.py +1067 -0
  50. polars/dataframe/plotting.py +257 -0
  51. polars/datatype_expr/__init__.py +5 -0
  52. polars/datatype_expr/array.py +56 -0
  53. polars/datatype_expr/datatype_expr.py +304 -0
  54. polars/datatype_expr/list.py +18 -0
  55. polars/datatype_expr/struct.py +69 -0
  56. polars/datatypes/__init__.py +122 -0
  57. polars/datatypes/_parse.py +195 -0
  58. polars/datatypes/_utils.py +48 -0
  59. polars/datatypes/classes.py +1213 -0
  60. polars/datatypes/constants.py +11 -0
  61. polars/datatypes/constructor.py +172 -0
  62. polars/datatypes/convert.py +366 -0
  63. polars/datatypes/group.py +130 -0
  64. polars/exceptions.py +230 -0
  65. polars/expr/__init__.py +7 -0
  66. polars/expr/array.py +964 -0
  67. polars/expr/binary.py +346 -0
  68. polars/expr/categorical.py +306 -0
  69. polars/expr/datetime.py +2620 -0
  70. polars/expr/expr.py +11272 -0
  71. polars/expr/list.py +1408 -0
  72. polars/expr/meta.py +444 -0
  73. polars/expr/name.py +321 -0
  74. polars/expr/string.py +3045 -0
  75. polars/expr/struct.py +357 -0
  76. polars/expr/whenthen.py +185 -0
  77. polars/functions/__init__.py +193 -0
  78. polars/functions/aggregation/__init__.py +33 -0
  79. polars/functions/aggregation/horizontal.py +298 -0
  80. polars/functions/aggregation/vertical.py +341 -0
  81. polars/functions/as_datatype.py +848 -0
  82. polars/functions/business.py +138 -0
  83. polars/functions/col.py +384 -0
  84. polars/functions/datatype.py +121 -0
  85. polars/functions/eager.py +524 -0
  86. polars/functions/escape_regex.py +29 -0
  87. polars/functions/lazy.py +2751 -0
  88. polars/functions/len.py +68 -0
  89. polars/functions/lit.py +210 -0
  90. polars/functions/random.py +22 -0
  91. polars/functions/range/__init__.py +19 -0
  92. polars/functions/range/_utils.py +15 -0
  93. polars/functions/range/date_range.py +303 -0
  94. polars/functions/range/datetime_range.py +370 -0
  95. polars/functions/range/int_range.py +348 -0
  96. polars/functions/range/linear_space.py +311 -0
  97. polars/functions/range/time_range.py +287 -0
  98. polars/functions/repeat.py +301 -0
  99. polars/functions/whenthen.py +353 -0
  100. polars/interchange/__init__.py +10 -0
  101. polars/interchange/buffer.py +77 -0
  102. polars/interchange/column.py +190 -0
  103. polars/interchange/dataframe.py +230 -0
  104. polars/interchange/from_dataframe.py +328 -0
  105. polars/interchange/protocol.py +303 -0
  106. polars/interchange/utils.py +170 -0
  107. polars/io/__init__.py +64 -0
  108. polars/io/_utils.py +317 -0
  109. polars/io/avro.py +49 -0
  110. polars/io/clipboard.py +36 -0
  111. polars/io/cloud/__init__.py +17 -0
  112. polars/io/cloud/_utils.py +80 -0
  113. polars/io/cloud/credential_provider/__init__.py +17 -0
  114. polars/io/cloud/credential_provider/_builder.py +520 -0
  115. polars/io/cloud/credential_provider/_providers.py +618 -0
  116. polars/io/csv/__init__.py +9 -0
  117. polars/io/csv/_utils.py +38 -0
  118. polars/io/csv/batched_reader.py +142 -0
  119. polars/io/csv/functions.py +1495 -0
  120. polars/io/database/__init__.py +6 -0
  121. polars/io/database/_arrow_registry.py +70 -0
  122. polars/io/database/_cursor_proxies.py +147 -0
  123. polars/io/database/_executor.py +578 -0
  124. polars/io/database/_inference.py +314 -0
  125. polars/io/database/_utils.py +144 -0
  126. polars/io/database/functions.py +516 -0
  127. polars/io/delta.py +499 -0
  128. polars/io/iceberg/__init__.py +3 -0
  129. polars/io/iceberg/_utils.py +697 -0
  130. polars/io/iceberg/dataset.py +556 -0
  131. polars/io/iceberg/functions.py +151 -0
  132. polars/io/ipc/__init__.py +8 -0
  133. polars/io/ipc/functions.py +514 -0
  134. polars/io/json/__init__.py +3 -0
  135. polars/io/json/read.py +101 -0
  136. polars/io/ndjson.py +332 -0
  137. polars/io/parquet/__init__.py +17 -0
  138. polars/io/parquet/field_overwrites.py +140 -0
  139. polars/io/parquet/functions.py +722 -0
  140. polars/io/partition.py +491 -0
  141. polars/io/plugins.py +187 -0
  142. polars/io/pyarrow_dataset/__init__.py +5 -0
  143. polars/io/pyarrow_dataset/anonymous_scan.py +109 -0
  144. polars/io/pyarrow_dataset/functions.py +79 -0
  145. polars/io/scan_options/__init__.py +5 -0
  146. polars/io/scan_options/_options.py +59 -0
  147. polars/io/scan_options/cast_options.py +126 -0
  148. polars/io/spreadsheet/__init__.py +6 -0
  149. polars/io/spreadsheet/_utils.py +52 -0
  150. polars/io/spreadsheet/_write_utils.py +647 -0
  151. polars/io/spreadsheet/functions.py +1323 -0
  152. polars/lazyframe/__init__.py +9 -0
  153. polars/lazyframe/engine_config.py +61 -0
  154. polars/lazyframe/frame.py +8564 -0
  155. polars/lazyframe/group_by.py +669 -0
  156. polars/lazyframe/in_process.py +42 -0
  157. polars/lazyframe/opt_flags.py +333 -0
  158. polars/meta/__init__.py +14 -0
  159. polars/meta/build.py +33 -0
  160. polars/meta/index_type.py +27 -0
  161. polars/meta/thread_pool.py +50 -0
  162. polars/meta/versions.py +120 -0
  163. polars/ml/__init__.py +0 -0
  164. polars/ml/torch.py +213 -0
  165. polars/ml/utilities.py +30 -0
  166. polars/plugins.py +155 -0
  167. polars/py.typed +0 -0
  168. polars/pyproject.toml +96 -0
  169. polars/schema.py +265 -0
  170. polars/selectors.py +3117 -0
  171. polars/series/__init__.py +5 -0
  172. polars/series/array.py +776 -0
  173. polars/series/binary.py +254 -0
  174. polars/series/categorical.py +246 -0
  175. polars/series/datetime.py +2275 -0
  176. polars/series/list.py +1087 -0
  177. polars/series/plotting.py +191 -0
  178. polars/series/series.py +9197 -0
  179. polars/series/string.py +2367 -0
  180. polars/series/struct.py +154 -0
  181. polars/series/utils.py +191 -0
  182. polars/sql/__init__.py +7 -0
  183. polars/sql/context.py +677 -0
  184. polars/sql/functions.py +139 -0
  185. polars/string_cache.py +185 -0
  186. polars/testing/__init__.py +13 -0
  187. polars/testing/asserts/__init__.py +9 -0
  188. polars/testing/asserts/frame.py +231 -0
  189. polars/testing/asserts/series.py +219 -0
  190. polars/testing/asserts/utils.py +12 -0
  191. polars/testing/parametric/__init__.py +33 -0
  192. polars/testing/parametric/profiles.py +107 -0
  193. polars/testing/parametric/strategies/__init__.py +22 -0
  194. polars/testing/parametric/strategies/_utils.py +14 -0
  195. polars/testing/parametric/strategies/core.py +615 -0
  196. polars/testing/parametric/strategies/data.py +452 -0
  197. polars/testing/parametric/strategies/dtype.py +436 -0
  198. polars/testing/parametric/strategies/legacy.py +169 -0
  199. polars/type_aliases.py +24 -0
  200. polars_runtime_compat-1.34.0b2.dist-info/METADATA +31 -0
  201. polars_runtime_compat-1.34.0b2.dist-info/RECORD +203 -0
  202. polars_runtime_compat-1.34.0b2.dist-info/WHEEL +4 -0
  203. polars_runtime_compat-1.34.0b2.dist-info/licenses/LICENSE +1 -0
@@ -0,0 +1,80 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Generic, TypeVar
5
+
6
+ from polars._typing import PartitioningScheme
7
+ from polars._utils.various import is_path_or_str_sequence
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ class NoPickleOption(Generic[T]):
13
+ """
14
+ Wrapper that does not pickle the wrapped value.
15
+
16
+ This wrapper will unpickle to contain a None. Used for cached values.
17
+ """
18
+
19
+ def __init__(self, opt_value: T | None = None) -> None:
20
+ self._opt_value = opt_value
21
+
22
+ def get(self) -> T | None:
23
+ return self._opt_value
24
+
25
+ def set(self, value: T | None) -> None:
26
+ self._opt_value = value
27
+
28
+ def __getstate__(self) -> tuple[()]:
29
+ # Needs to return not-None for `__setstate__()` to be called
30
+ return ()
31
+
32
+ def __setstate__(self, _state: tuple[()]) -> None:
33
+ NoPickleOption.__init__(self)
34
+
35
+
36
+ def _first_scan_path(
37
+ source: Any,
38
+ ) -> str | Path | None:
39
+ if isinstance(source, (str, Path)):
40
+ return source
41
+ elif is_path_or_str_sequence(source) and source:
42
+ return source[0]
43
+ elif isinstance(source, PartitioningScheme):
44
+ return source._base_path
45
+
46
+ return None
47
+
48
+
49
+ def _get_path_scheme(path: str | Path) -> str | None:
50
+ path_str = str(path)
51
+ i = path_str.find("://")
52
+
53
+ return path_str[:i] if i >= 0 else None
54
+
55
+
56
+ def _is_aws_cloud(*, scheme: str, first_scan_path: str) -> bool:
57
+ if any(scheme == x for x in ["s3", "s3a"]):
58
+ return True
59
+
60
+ if scheme == "http" or scheme == "https":
61
+ bucket_end = first_scan_path.find(".s3.")
62
+ region_end = first_scan_path.find(".amazonaws.com/", bucket_end + 4)
63
+
64
+ if (
65
+ first_scan_path.find("/", len(scheme) + 3, region_end) > 0
66
+ or "?" in first_scan_path
67
+ ):
68
+ return False
69
+
70
+ return 0 < bucket_end < region_end
71
+
72
+ return False
73
+
74
+
75
+ def _is_azure_cloud(scheme: str) -> bool:
76
+ return any(scheme == x for x in ["az", "azure", "adl", "abfs", "abfss"])
77
+
78
+
79
+ def _is_gcp_cloud(scheme: str) -> bool:
80
+ return any(scheme == x for x in ["gs", "gcp", "gcs"])
@@ -0,0 +1,17 @@
1
+ from polars.io.cloud.credential_provider._providers import (
2
+ CredentialProvider,
3
+ CredentialProviderAWS,
4
+ CredentialProviderAzure,
5
+ CredentialProviderFunction,
6
+ CredentialProviderFunctionReturn,
7
+ CredentialProviderGCP,
8
+ )
9
+
10
+ __all__ = [
11
+ "CredentialProvider",
12
+ "CredentialProviderAWS",
13
+ "CredentialProviderAzure",
14
+ "CredentialProviderFunction",
15
+ "CredentialProviderFunctionReturn",
16
+ "CredentialProviderGCP",
17
+ ]
@@ -0,0 +1,520 @@
1
+ from __future__ import annotations
2
+
3
+ import abc
4
+ import os
5
+ import threading
6
+ from typing import TYPE_CHECKING, Any, Callable, Literal, Union
7
+
8
+ import polars._utils.logging
9
+ from polars._utils.cache import LRUCache
10
+ from polars._utils.logging import eprint, verbose
11
+ from polars._utils.unstable import issue_unstable_warning
12
+ from polars.io.cloud._utils import NoPickleOption
13
+ from polars.io.cloud.credential_provider._providers import (
14
+ CachedCredentialProvider,
15
+ CachingCredentialProvider,
16
+ CredentialProvider,
17
+ CredentialProviderAWS,
18
+ CredentialProviderAzure,
19
+ CredentialProviderFunction,
20
+ CredentialProviderGCP,
21
+ UserProvidedGCPToken,
22
+ )
23
+
24
+ if TYPE_CHECKING:
25
+ import sys
26
+
27
+ if sys.version_info >= (3, 10):
28
+ from typing import TypeAlias
29
+ else:
30
+ from typing_extensions import TypeAlias
31
+
32
+ # https://docs.rs/object_store/latest/object_store/enum.ClientConfigKey.html
33
+ OBJECT_STORE_CLIENT_OPTIONS: frozenset[str] = frozenset(
34
+ [
35
+ "allow_http",
36
+ "allow_invalid_certificates",
37
+ "connect_timeout",
38
+ "default_content_type",
39
+ "http1_only",
40
+ "http2_only",
41
+ "http2_keep_alive_interval",
42
+ "http2_keep_alive_timeout",
43
+ "http2_keep_alive_while_idle",
44
+ "http2_max_frame_size",
45
+ "pool_idle_timeout",
46
+ "pool_max_idle_per_host",
47
+ "proxy_url",
48
+ "proxy_ca_certificate",
49
+ "proxy_excludes",
50
+ "timeout",
51
+ "user_agent",
52
+ ]
53
+ )
54
+
55
+ CredentialProviderBuilderReturn: TypeAlias = Union[
56
+ CredentialProvider, CredentialProviderFunction, None
57
+ ]
58
+
59
+
60
+ class CredentialProviderBuilder:
61
+ """
62
+ Builds credential providers.
63
+
64
+ This is used to defer credential provider initialization to happen at
65
+ `collect()` rather than immediately during query construction. This makes
66
+ the behavior predictable when queries are sent to another environment for
67
+ execution.
68
+ """
69
+
70
+ def __init__(
71
+ self,
72
+ credential_provider_init: CredentialProviderBuilderImpl,
73
+ ) -> None:
74
+ """
75
+ Initialize configuration for building a credential provider.
76
+
77
+ Parameters
78
+ ----------
79
+ credential_provider_init
80
+ Initializer function that returns a credential provider.
81
+ """
82
+ self.credential_provider_init = credential_provider_init
83
+
84
+ # Note: The rust-side expects this exact function name.
85
+ def build_credential_provider(
86
+ self,
87
+ clear_cached_credentials: bool = False, # noqa: FBT001
88
+ ) -> CredentialProviderBuilderReturn:
89
+ """
90
+ Instantiate a credential provider from configuration.
91
+
92
+ Parameters
93
+ ----------
94
+ clear_cached_credentials
95
+ If the built provider is an instance of `CachingCredentialProvider`,
96
+ clears any cached credentials on that object.
97
+ """
98
+ verbose = polars._utils.logging.verbose()
99
+
100
+ if verbose:
101
+ eprint(
102
+ "[CredentialProviderBuilder]: Begin initialize "
103
+ f"{self.credential_provider_init!r} "
104
+ f"{clear_cached_credentials = }"
105
+ )
106
+
107
+ v = self.credential_provider_init()
108
+
109
+ if verbose:
110
+ if v is not None:
111
+ eprint(
112
+ f"[CredentialProviderBuilder]: Initialized {v!r} "
113
+ f"from {self.credential_provider_init!r}"
114
+ )
115
+ else:
116
+ eprint(
117
+ f"[CredentialProviderBuilder]: No provider initialized "
118
+ f"from {self.credential_provider_init!r}"
119
+ )
120
+
121
+ if clear_cached_credentials and isinstance(v, CachingCredentialProvider):
122
+ v.clear_cached_credentials()
123
+
124
+ if verbose:
125
+ eprint(
126
+ f"[CredentialProviderBuilder]: Clear cached credentials for {v!r}"
127
+ )
128
+
129
+ return v
130
+
131
+ @classmethod
132
+ def from_initialized_provider(
133
+ cls, credential_provider: CredentialProviderFunction
134
+ ) -> CredentialProviderBuilder:
135
+ """Initialize with an already constructed provider."""
136
+ return cls(InitializedCredentialProvider(credential_provider))
137
+
138
+ def __getstate__(self) -> Any:
139
+ state = self.credential_provider_init
140
+
141
+ if verbose():
142
+ eprint(f"[CredentialProviderBuilder]: __getstate__(): {state = !r} ")
143
+
144
+ return state
145
+
146
+ def __setstate__(self, state: Any) -> None:
147
+ self.credential_provider_init = state
148
+
149
+ if verbose():
150
+ eprint(f"[CredentialProviderBuilder]: __setstate__(): {self = !r}")
151
+
152
+ def __repr__(self) -> str:
153
+ return f"CredentialProviderBuilder({self.credential_provider_init!r})"
154
+
155
+
156
+ class CredentialProviderBuilderImpl(abc.ABC):
157
+ @abc.abstractmethod
158
+ def __call__(self) -> CredentialProviderFunction | None:
159
+ pass
160
+
161
+ @property
162
+ @abc.abstractmethod
163
+ def provider_repr(self) -> str:
164
+ """Used for logging."""
165
+
166
+ def __repr__(self) -> str:
167
+ provider_repr = self.provider_repr
168
+ builder_name = type(self).__name__
169
+
170
+ return f"{provider_repr} @ {builder_name}"
171
+
172
+
173
+ # Wraps an already initialized credential provider into the builder interface.
174
+ # Used for e.g. user-provided credential providers.
175
+ class InitializedCredentialProvider(CredentialProviderBuilderImpl):
176
+ """Wraps an already initialized credential provider."""
177
+
178
+ def __init__(self, credential_provider: CredentialProviderFunction) -> None:
179
+ self.credential_provider = credential_provider
180
+
181
+ def __call__(self) -> CredentialProviderBuilderReturn:
182
+ if isinstance(self.credential_provider, CachingCredentialProvider):
183
+ return self.credential_provider
184
+
185
+ # We use the cache by keying the entry as the address of the object
186
+ # provided by the user.
187
+ return _build_with_cache(
188
+ lambda: id(self.credential_provider),
189
+ lambda: CachedCredentialProvider(self.credential_provider),
190
+ )
191
+
192
+ @property
193
+ def provider_repr(self) -> str:
194
+ return repr(self.credential_provider)
195
+
196
+
197
+ # The keys of this can be:
198
+ # * int: Object address of a user-passed credential provider
199
+ # * bytes: Hash of an AutoInit configuration
200
+ BUILT_PROVIDERS_LRU_CACHE: (
201
+ LRUCache[int | bytes, CredentialProviderBuilderReturn] | None
202
+ ) = None
203
+ BUILT_PROVIDERS_LRU_CACHE_LOCK: threading.RLock = threading.RLock()
204
+
205
+
206
+ def _build_with_cache(
207
+ get_cache_key_func: Callable[[], int | bytes],
208
+ build_provider_func: Callable[[], CredentialProviderBuilderReturn],
209
+ ) -> CredentialProviderBuilderReturn:
210
+ global BUILT_PROVIDERS_LRU_CACHE
211
+
212
+ if (
213
+ max_items := int(
214
+ os.getenv(
215
+ "POLARS_CREDENTIAL_PROVIDER_BUILDER_CACHE_SIZE",
216
+ 8,
217
+ )
218
+ )
219
+ ) <= 0:
220
+ if BUILT_PROVIDERS_LRU_CACHE_LOCK.acquire(blocking=False):
221
+ BUILT_PROVIDERS_LRU_CACHE = None
222
+ BUILT_PROVIDERS_LRU_CACHE_LOCK.release()
223
+
224
+ return build_provider_func()
225
+
226
+ verbose = polars._utils.logging.verbose()
227
+
228
+ with BUILT_PROVIDERS_LRU_CACHE_LOCK:
229
+ if BUILT_PROVIDERS_LRU_CACHE is None:
230
+ if verbose:
231
+ eprint(f"Create built credential providers LRU cache ({max_items = })")
232
+
233
+ BUILT_PROVIDERS_LRU_CACHE = LRUCache(max_items)
234
+
235
+ cache_key = get_cache_key_func()
236
+
237
+ try:
238
+ provider = BUILT_PROVIDERS_LRU_CACHE[cache_key]
239
+
240
+ if verbose:
241
+ eprint(
242
+ f"Loaded credential provider from cache: {provider!r} {cache_key = }"
243
+ )
244
+ except KeyError:
245
+ provider = build_provider_func()
246
+ BUILT_PROVIDERS_LRU_CACHE[cache_key] = provider
247
+
248
+ if verbose:
249
+ eprint(
250
+ f"Added new credential provider to cache: {provider!r} {cache_key = }"
251
+ )
252
+
253
+ return provider
254
+
255
+
256
+ # Represents an automatic initialization configuration. This is created for
257
+ # credential_provider="auto".
258
+ class AutoInit(CredentialProviderBuilderImpl):
259
+ def __init__(self, cls: Any, **kw: Any) -> None:
260
+ self.cls = cls
261
+ self.kw = kw
262
+ self._cache_key: NoPickleOption[bytes] = NoPickleOption()
263
+
264
+ def __call__(self) -> CredentialProviderFunction | None:
265
+ # This is used for credential_provider="auto", which allows for
266
+ # ImportErrors.
267
+ try:
268
+ return _build_with_cache(
269
+ self.get_or_init_cache_key,
270
+ lambda: self.cls(**self.kw),
271
+ )
272
+ except ImportError as e:
273
+ if verbose():
274
+ eprint(f"failed to auto-initialize {self.provider_repr}: {e!r}")
275
+
276
+ return None
277
+
278
+ def get_or_init_cache_key(self) -> bytes:
279
+ cache_key = self._cache_key.get()
280
+
281
+ if cache_key is None:
282
+ cache_key = self.get_cache_key_impl()
283
+ self._cache_key.set(cache_key)
284
+
285
+ if verbose():
286
+ eprint(f"{self!r}: AutoInit cache key: {cache_key.hex()}")
287
+
288
+ return cache_key
289
+
290
+ def get_cache_key_impl(self) -> bytes:
291
+ import hashlib
292
+ import pickle
293
+
294
+ hash = hashlib.sha256(pickle.dumps(self))
295
+ return hash.digest()[:16]
296
+
297
+ @property
298
+ def provider_repr(self) -> str:
299
+ return self.cls.__name__
300
+
301
+
302
+ DEFAULT_CREDENTIAL_PROVIDER: CredentialProviderFunction | Literal["auto"] | None = (
303
+ "auto"
304
+ )
305
+
306
+
307
+ def _init_credential_provider_builder(
308
+ credential_provider: CredentialProviderFunction
309
+ | CredentialProviderBuilder
310
+ | Literal["auto"]
311
+ | None,
312
+ source: Any,
313
+ storage_options: dict[str, Any] | None,
314
+ caller_name: str,
315
+ ) -> CredentialProviderBuilder | None:
316
+ def f() -> CredentialProviderBuilder | None:
317
+ # Note: The behavior of this function should depend only on the function
318
+ # parameters. Any environment-specific behavior should take place inside
319
+ # instantiated credential providers.
320
+
321
+ from polars.io.cloud._utils import (
322
+ _first_scan_path,
323
+ _get_path_scheme,
324
+ _is_aws_cloud,
325
+ _is_azure_cloud,
326
+ _is_gcp_cloud,
327
+ )
328
+
329
+ if credential_provider is None:
330
+ return None
331
+
332
+ if isinstance(credential_provider, CredentialProviderBuilder):
333
+ # This happens when the catalog client auto-inits and passes it to
334
+ # scan/write_delta, which calls us again.
335
+ return credential_provider
336
+
337
+ if credential_provider != "auto":
338
+ msg = f"the `credential_provider` parameter of `{caller_name}` is considered unstable."
339
+ issue_unstable_warning(msg)
340
+
341
+ return CredentialProviderBuilder.from_initialized_provider(
342
+ credential_provider
343
+ )
344
+
345
+ if DEFAULT_CREDENTIAL_PROVIDER is None:
346
+ return None
347
+
348
+ if (first_scan_path := _first_scan_path(source)) is None:
349
+ return None
350
+
351
+ if (scheme := _get_path_scheme(first_scan_path)) is None:
352
+ return None
353
+
354
+ def get_default_credential_provider() -> CredentialProviderBuilder | None:
355
+ return (
356
+ CredentialProviderBuilder.from_initialized_provider(
357
+ DEFAULT_CREDENTIAL_PROVIDER
358
+ )
359
+ if DEFAULT_CREDENTIAL_PROVIDER != "auto"
360
+ else None
361
+ )
362
+
363
+ if _is_azure_cloud(scheme):
364
+ tenant_id = None
365
+ storage_account = None
366
+
367
+ if storage_options is not None:
368
+ for k, v in storage_options.items():
369
+ k = k.lower()
370
+
371
+ # https://docs.rs/object_store/latest/object_store/azure/enum.AzureConfigKey.html
372
+ if k in {
373
+ "azure_storage_tenant_id",
374
+ "azure_storage_authority_id",
375
+ "azure_tenant_id",
376
+ "azure_authority_id",
377
+ "tenant_id",
378
+ "authority_id",
379
+ }:
380
+ tenant_id = v
381
+ elif k in {"azure_storage_account_name", "account_name"}:
382
+ storage_account = v
383
+ elif k in {"azure_use_azure_cli", "use_azure_cli"}:
384
+ continue
385
+ elif k in OBJECT_STORE_CLIENT_OPTIONS:
386
+ continue
387
+ else:
388
+ # We assume some sort of access key was given, so we
389
+ # just dispatch to the rust side.
390
+ return None
391
+
392
+ storage_account = (
393
+ # Prefer the one embedded in the path
394
+ CredentialProviderAzure._extract_adls_uri_storage_account(
395
+ str(first_scan_path)
396
+ )
397
+ or storage_account
398
+ )
399
+
400
+ if (default := get_default_credential_provider()) is not None:
401
+ return default
402
+
403
+ return CredentialProviderBuilder(
404
+ AutoInit(
405
+ CredentialProviderAzure,
406
+ tenant_id=tenant_id,
407
+ _storage_account=storage_account,
408
+ )
409
+ )
410
+
411
+ elif _is_aws_cloud(scheme=scheme, first_scan_path=str(first_scan_path)):
412
+ region = None
413
+ profile = None
414
+ default_region = None
415
+ unhandled_key = None
416
+ has_endpoint_url = False
417
+
418
+ if storage_options is not None:
419
+ for k, v in storage_options.items():
420
+ k = k.lower()
421
+
422
+ # https://docs.rs/object_store/latest/object_store/aws/enum.AmazonS3ConfigKey.html
423
+ if k in {"aws_region", "region"}:
424
+ region = v
425
+ elif k in {"aws_default_region", "default_region"}:
426
+ default_region = v
427
+ elif k in {"aws_profile", "profile"}:
428
+ profile = v
429
+ elif k in {
430
+ "aws_endpoint",
431
+ "aws_endpoint_url",
432
+ "endpoint",
433
+ "endpoint_url",
434
+ }:
435
+ has_endpoint_url = True
436
+ elif k in {"aws_request_payer", "request_payer"}:
437
+ continue
438
+ elif k in OBJECT_STORE_CLIENT_OPTIONS:
439
+ continue
440
+ else:
441
+ # We assume this is some sort of access key
442
+ unhandled_key = k
443
+
444
+ if unhandled_key is not None:
445
+ if profile is not None:
446
+ msg = (
447
+ "unsupported: cannot combine aws_profile with "
448
+ f"{unhandled_key} in storage_options"
449
+ )
450
+ raise ValueError(msg)
451
+
452
+ if (
453
+ unhandled_key is None
454
+ and (default := get_default_credential_provider()) is not None
455
+ ):
456
+ return default
457
+
458
+ return CredentialProviderBuilder(
459
+ AutoInit(
460
+ CredentialProviderAWS,
461
+ profile_name=profile,
462
+ region_name=region or default_region,
463
+ _auto_init_unhandled_key=unhandled_key,
464
+ _storage_options_has_endpoint_url=has_endpoint_url,
465
+ )
466
+ )
467
+
468
+ elif _is_gcp_cloud(scheme):
469
+ token = None
470
+ unhandled_key = None
471
+
472
+ if storage_options is not None:
473
+ for k, v in storage_options.items():
474
+ k = k.lower()
475
+
476
+ # https://docs.rs/object_store/latest/object_store/gcp/enum.GoogleConfigKey.html
477
+ if k in {"token", "bearer_token"}:
478
+ token = v
479
+ elif k in {
480
+ "google_bucket",
481
+ "google_bucket_name",
482
+ "bucket",
483
+ "bucket_name",
484
+ }:
485
+ continue
486
+ elif k in OBJECT_STORE_CLIENT_OPTIONS:
487
+ continue
488
+ else:
489
+ # We assume some sort of access key was given, so we
490
+ # just dispatch to the rust side.
491
+ unhandled_key = k
492
+
493
+ if unhandled_key is not None:
494
+ if token is not None:
495
+ msg = (
496
+ "unsupported: cannot combine token with "
497
+ f"{unhandled_key} in storage_options"
498
+ )
499
+ raise ValueError(msg)
500
+
501
+ return None
502
+
503
+ if token is not None:
504
+ return CredentialProviderBuilder(
505
+ InitializedCredentialProvider(UserProvidedGCPToken(token))
506
+ )
507
+
508
+ if (default := get_default_credential_provider()) is not None:
509
+ return default
510
+
511
+ return CredentialProviderBuilder(AutoInit(CredentialProviderGCP))
512
+
513
+ return None
514
+
515
+ credential_provider_init = f()
516
+
517
+ if verbose():
518
+ eprint(f"_init_credential_provider_builder(): {credential_provider_init = !r}")
519
+
520
+ return credential_provider_init