ygg 0.1.31__tar.gz → 0.1.33__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ygg-0.1.31 → ygg-0.1.33}/PKG-INFO +1 -1
- {ygg-0.1.31 → ygg-0.1.33}/pyproject.toml +1 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/ygg.egg-info/PKG-INFO +1 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/ygg.egg-info/SOURCES.txt +1 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/compute/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/compute/cluster.py +244 -3
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/compute/execution_context.py +100 -11
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/compute/remote.py +24 -0
- ygg-0.1.33/src/yggdrasil/databricks/jobs/__init__.py +5 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/jobs/config.py +29 -4
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/sql/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/sql/engine.py +217 -36
- ygg-0.1.33/src/yggdrasil/databricks/sql/exceptions.py +1 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/sql/statement_result.py +147 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/sql/types.py +33 -1
- ygg-0.1.33/src/yggdrasil/databricks/workspaces/__init__.py +5 -0
- ygg-0.1.33/src/yggdrasil/databricks/workspaces/filesytem.py +344 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/workspaces/io.py +387 -9
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/workspaces/path.py +297 -2
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/workspaces/path_kind.py +3 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/databricks/workspaces/workspace.py +202 -5
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/dataclasses/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/dataclasses/dataclass.py +42 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/databrickslib.py +9 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/extensions/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/extensions/polars_extensions.py +72 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/extensions/spark_extensions.py +116 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/pandaslib.py +7 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/polarslib.py +7 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/libs/sparklib.py +41 -0
- ygg-0.1.33/src/yggdrasil/pyutils/__init__.py +8 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/pyutils/callable_serde.py +106 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/pyutils/exceptions.py +16 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/pyutils/modules.py +44 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/pyutils/parallel.py +29 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/pyutils/python_env.py +301 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/pyutils/retry.py +57 -0
- ygg-0.1.33/src/yggdrasil/requests/__init__.py +5 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/requests/msal.py +124 -3
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/requests/session.py +18 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/__init__.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/__init__.py +2 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/arrow_cast.py +123 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/cast_options.py +119 -1
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/pandas_cast.py +29 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/polars_cast.py +47 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/polars_pandas_cast.py +29 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/registry.py +176 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/spark_cast.py +76 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/spark_pandas_cast.py +29 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/cast/spark_polars_cast.py +28 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/libs.py +2 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/python_arrow.py +191 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/yggdrasil/types/python_defaults.py +73 -0
- ygg-0.1.33/src/yggdrasil/version.py +1 -0
- ygg-0.1.31/src/yggdrasil/databricks/jobs/__init__.py +0 -0
- ygg-0.1.31/src/yggdrasil/databricks/sql/exceptions.py +0 -0
- ygg-0.1.31/src/yggdrasil/databricks/workspaces/__init__.py +0 -4
- ygg-0.1.31/src/yggdrasil/databricks/workspaces/filesytem.py +0 -161
- ygg-0.1.31/src/yggdrasil/pyutils/__init__.py +0 -4
- ygg-0.1.31/src/yggdrasil/requests/__init__.py +0 -1
- {ygg-0.1.31 → ygg-0.1.33}/LICENSE +0 -0
- {ygg-0.1.31 → ygg-0.1.33}/README.md +0 -0
- {ygg-0.1.31 → ygg-0.1.33}/setup.cfg +0 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/ygg.egg-info/dependency_links.txt +0 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/ygg.egg-info/entry_points.txt +0 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/ygg.egg-info/requires.txt +0 -0
- {ygg-0.1.31 → ygg-0.1.33}/src/ygg.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ygg"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.33"
|
|
8
8
|
description = "Type-friendly utilities for moving data between Python objects, Arrow, Polars, Pandas, Spark, and Databricks"
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -8,6 +8,7 @@ src/ygg.egg-info/entry_points.txt
|
|
|
8
8
|
src/ygg.egg-info/requires.txt
|
|
9
9
|
src/ygg.egg-info/top_level.txt
|
|
10
10
|
src/yggdrasil/__init__.py
|
|
11
|
+
src/yggdrasil/version.py
|
|
11
12
|
src/yggdrasil/databricks/__init__.py
|
|
12
13
|
src/yggdrasil/databricks/compute/__init__.py
|
|
13
14
|
src/yggdrasil/databricks/compute/cluster.py
|
|
@@ -90,17 +90,21 @@ class Cluster(WorkspaceService):
|
|
|
90
90
|
|
|
91
91
|
@property
|
|
92
92
|
def id(self):
|
|
93
|
+
"""Return the current cluster id."""
|
|
93
94
|
return self.cluster_id
|
|
94
95
|
|
|
95
96
|
@property
|
|
96
97
|
def name(self) -> str:
|
|
98
|
+
"""Return the current cluster name."""
|
|
97
99
|
return self.cluster_name
|
|
98
100
|
|
|
99
101
|
def __post_init__(self):
|
|
102
|
+
"""Initialize cached details after dataclass construction."""
|
|
100
103
|
if self._details is not None:
|
|
101
104
|
self.details = self._details
|
|
102
105
|
|
|
103
106
|
def is_in_databricks_environment(self):
|
|
107
|
+
"""Return True when running on a Databricks runtime."""
|
|
104
108
|
return self.workspace.is_in_databricks_environment()
|
|
105
109
|
|
|
106
110
|
@classmethod
|
|
@@ -114,6 +118,20 @@ class Cluster(WorkspaceService):
|
|
|
114
118
|
libraries: Optional[list[str]] = None,
|
|
115
119
|
**kwargs
|
|
116
120
|
) -> "Cluster":
|
|
121
|
+
"""Create or reuse a cluster that mirrors the current Python environment.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
workspace: Workspace to use for the cluster.
|
|
125
|
+
cluster_id: Optional cluster id to reuse.
|
|
126
|
+
cluster_name: Optional cluster name to reuse.
|
|
127
|
+
single_user_name: Optional user name for single-user clusters.
|
|
128
|
+
runtime_engine: Optional Databricks runtime engine.
|
|
129
|
+
libraries: Optional list of libraries to install.
|
|
130
|
+
**kwargs: Additional cluster specification overrides.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
A Cluster instance configured for the current environment.
|
|
134
|
+
"""
|
|
117
135
|
if workspace is None:
|
|
118
136
|
workspace = Workspace() # your default, whatever it is
|
|
119
137
|
|
|
@@ -146,6 +164,20 @@ class Cluster(WorkspaceService):
|
|
|
146
164
|
libraries: Optional[list[str]] = None,
|
|
147
165
|
**kwargs
|
|
148
166
|
) -> "Cluster":
|
|
167
|
+
"""Create/update a cluster to match the local Python environment.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
source: Optional PythonEnv to mirror (defaults to current).
|
|
171
|
+
cluster_id: Optional cluster id to update.
|
|
172
|
+
cluster_name: Optional cluster name to update.
|
|
173
|
+
single_user_name: Optional single user name for the cluster.
|
|
174
|
+
runtime_engine: Optional runtime engine selection.
|
|
175
|
+
libraries: Optional list of libraries to install.
|
|
176
|
+
**kwargs: Additional cluster specification overrides.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
A Cluster instance configured with the local environment.
|
|
180
|
+
"""
|
|
149
181
|
if source is None:
|
|
150
182
|
source = PythonEnv.get_current()
|
|
151
183
|
|
|
@@ -192,6 +224,15 @@ class Cluster(WorkspaceService):
|
|
|
192
224
|
name: Optional[str] = None,
|
|
193
225
|
target: PythonEnv | str | None = None,
|
|
194
226
|
):
|
|
227
|
+
"""Update or create a local PythonEnv based on remote metadata.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
name: Optional name for the local PythonEnv.
|
|
231
|
+
target: Existing PythonEnv or name to update.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
The updated PythonEnv instance.
|
|
235
|
+
"""
|
|
195
236
|
with self.context() as c:
|
|
196
237
|
m = c.remote_metadata
|
|
197
238
|
version_info = m.version_info
|
|
@@ -220,11 +261,20 @@ class Cluster(WorkspaceService):
|
|
|
220
261
|
|
|
221
262
|
@property
|
|
222
263
|
def details(self):
|
|
264
|
+
"""Return cached cluster details, refreshing when needed."""
|
|
223
265
|
if self._details is None and self.cluster_id is not None:
|
|
224
266
|
self.details = self.clusters_client().get(cluster_id=self.cluster_id)
|
|
225
267
|
return self._details
|
|
226
268
|
|
|
227
269
|
def fresh_details(self, max_delay: float | None = None):
|
|
270
|
+
"""Refresh cluster details if older than ``max_delay`` seconds.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
max_delay: Maximum age in seconds before refresh.
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
The latest ClusterDetails object, if available.
|
|
277
|
+
"""
|
|
228
278
|
max_delay = max_delay or 0
|
|
229
279
|
delay = time.time() - self._details_refresh_time
|
|
230
280
|
|
|
@@ -234,6 +284,7 @@ class Cluster(WorkspaceService):
|
|
|
234
284
|
|
|
235
285
|
@details.setter
|
|
236
286
|
def details(self, value: "ClusterDetails"):
|
|
287
|
+
"""Cache cluster details and update identifiers."""
|
|
237
288
|
self._details_refresh_time = time.time()
|
|
238
289
|
self._details = value
|
|
239
290
|
|
|
@@ -242,6 +293,7 @@ class Cluster(WorkspaceService):
|
|
|
242
293
|
|
|
243
294
|
@property
|
|
244
295
|
def state(self):
|
|
296
|
+
"""Return the current cluster state."""
|
|
245
297
|
details = self.fresh_details(max_delay=10)
|
|
246
298
|
|
|
247
299
|
if details is not None:
|
|
@@ -249,6 +301,14 @@ class Cluster(WorkspaceService):
|
|
|
249
301
|
return State.UNKNOWN
|
|
250
302
|
|
|
251
303
|
def get_state(self, max_delay: float = None):
|
|
304
|
+
"""Return the cluster state with a custom refresh delay.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
max_delay: Maximum age in seconds before refresh.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
The current cluster state.
|
|
311
|
+
"""
|
|
252
312
|
details = self.fresh_details(max_delay=max_delay)
|
|
253
313
|
|
|
254
314
|
if details is not None:
|
|
@@ -257,17 +317,21 @@ class Cluster(WorkspaceService):
|
|
|
257
317
|
|
|
258
318
|
@property
|
|
259
319
|
def is_running(self):
|
|
320
|
+
"""Return True when the cluster is running."""
|
|
260
321
|
return self.state == State.RUNNING
|
|
261
322
|
|
|
262
323
|
@property
|
|
263
324
|
def is_pending(self):
|
|
325
|
+
"""Return True when the cluster is starting, resizing, or terminating."""
|
|
264
326
|
return self.state in (State.PENDING, State.RESIZING, State.RESTARTING, State.TERMINATING)
|
|
265
327
|
|
|
266
328
|
@property
|
|
267
329
|
def is_error(self):
|
|
330
|
+
"""Return True when the cluster is in an error state."""
|
|
268
331
|
return self.state == State.ERROR
|
|
269
332
|
|
|
270
333
|
def raise_for_status(self):
|
|
334
|
+
"""Raise a DatabricksError if the cluster is in an error state."""
|
|
271
335
|
if self.is_error:
|
|
272
336
|
raise DatabricksError("Error in %s" % self)
|
|
273
337
|
|
|
@@ -280,6 +344,17 @@ class Cluster(WorkspaceService):
|
|
|
280
344
|
backoff: int = 2,
|
|
281
345
|
max_sleep_time: float = 15
|
|
282
346
|
):
|
|
347
|
+
"""Wait for the cluster to exit pending states.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
tick: Initial sleep interval in seconds.
|
|
351
|
+
timeout: Max seconds to wait before timing out.
|
|
352
|
+
backoff: Backoff multiplier for the sleep interval.
|
|
353
|
+
max_sleep_time: Maximum sleep interval in seconds.
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
The current Cluster instance.
|
|
357
|
+
"""
|
|
283
358
|
start = time.time()
|
|
284
359
|
sleep_time = tick
|
|
285
360
|
|
|
@@ -297,6 +372,7 @@ class Cluster(WorkspaceService):
|
|
|
297
372
|
|
|
298
373
|
@property
|
|
299
374
|
def spark_version(self) -> str:
|
|
375
|
+
"""Return the cluster Spark version string."""
|
|
300
376
|
d = self.details
|
|
301
377
|
if d is None:
|
|
302
378
|
return None
|
|
@@ -304,6 +380,7 @@ class Cluster(WorkspaceService):
|
|
|
304
380
|
|
|
305
381
|
@property
|
|
306
382
|
def runtime_version(self):
|
|
383
|
+
"""Return the Databricks runtime major/minor version string."""
|
|
307
384
|
# Extract "major.minor" from strings like "17.3.x-scala2.13-ml-gpu"
|
|
308
385
|
v = self.spark_version
|
|
309
386
|
|
|
@@ -331,6 +408,7 @@ class Cluster(WorkspaceService):
|
|
|
331
408
|
# Internal helpers
|
|
332
409
|
# ------------------------------------------------------------------ #
|
|
333
410
|
def clusters_client(self) -> "ClustersAPI":
|
|
411
|
+
"""Return the Databricks clusters API client."""
|
|
334
412
|
return self.workspace.sdk().clusters
|
|
335
413
|
|
|
336
414
|
def spark_versions(
|
|
@@ -338,6 +416,15 @@ class Cluster(WorkspaceService):
|
|
|
338
416
|
photon: Optional[bool] = None,
|
|
339
417
|
python_version: Optional[Union[str, tuple[int, ...]]] = None,
|
|
340
418
|
):
|
|
419
|
+
"""List supported Spark runtimes filtered by photon and python version.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
photon: If set, filter by Photon (True) or non-Photon (False).
|
|
423
|
+
python_version: Optional Python version filter (string or tuple).
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
A list of SparkVersion entries matching the filters.
|
|
427
|
+
"""
|
|
341
428
|
all_versions = self.clusters_client().spark_versions().versions
|
|
342
429
|
|
|
343
430
|
if not all_versions:
|
|
@@ -387,6 +474,15 @@ class Cluster(WorkspaceService):
|
|
|
387
474
|
photon: Optional[bool] = None,
|
|
388
475
|
python_version: Optional[Union[str, tuple[int, ...]]] = None,
|
|
389
476
|
):
|
|
477
|
+
"""Return the latest Spark version that matches requested filters.
|
|
478
|
+
|
|
479
|
+
Args:
|
|
480
|
+
photon: If set, filter by Photon (True) or non-Photon (False).
|
|
481
|
+
python_version: Optional Python version filter (string or tuple).
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
The latest SparkVersion matching the filters.
|
|
485
|
+
"""
|
|
390
486
|
versions = self.spark_versions(photon=photon, python_version=python_version)
|
|
391
487
|
|
|
392
488
|
max_version: SparkVersion = None
|
|
@@ -458,6 +554,17 @@ class Cluster(WorkspaceService):
|
|
|
458
554
|
libraries: Optional[List[Union[str, "Library"]]] = None,
|
|
459
555
|
**cluster_spec: Any
|
|
460
556
|
):
|
|
557
|
+
"""Create a new cluster or update an existing one.
|
|
558
|
+
|
|
559
|
+
Args:
|
|
560
|
+
cluster_id: Optional cluster id to update.
|
|
561
|
+
cluster_name: Optional cluster name to update or create.
|
|
562
|
+
libraries: Optional libraries to install.
|
|
563
|
+
**cluster_spec: Cluster specification overrides.
|
|
564
|
+
|
|
565
|
+
Returns:
|
|
566
|
+
A Cluster instance pointing at the created/updated cluster.
|
|
567
|
+
"""
|
|
461
568
|
found = self.find_cluster(
|
|
462
569
|
cluster_id=cluster_id or self.cluster_id,
|
|
463
570
|
cluster_name=cluster_name or self.cluster_name,
|
|
@@ -482,6 +589,15 @@ class Cluster(WorkspaceService):
|
|
|
482
589
|
libraries: Optional[List[Union[str, "Library"]]] = None,
|
|
483
590
|
**cluster_spec: Any
|
|
484
591
|
) -> str:
|
|
592
|
+
"""Create a new cluster and optionally install libraries.
|
|
593
|
+
|
|
594
|
+
Args:
|
|
595
|
+
libraries: Optional list of libraries to install after creation.
|
|
596
|
+
**cluster_spec: Cluster specification overrides.
|
|
597
|
+
|
|
598
|
+
Returns:
|
|
599
|
+
The current Cluster instance.
|
|
600
|
+
"""
|
|
485
601
|
cluster_spec["autotermination_minutes"] = int(cluster_spec.get("autotermination_minutes", 30))
|
|
486
602
|
update_details = self._check_details(details=ClusterDetails(), **cluster_spec)
|
|
487
603
|
update_details = {
|
|
@@ -512,6 +628,15 @@ class Cluster(WorkspaceService):
|
|
|
512
628
|
libraries: Optional[List[Union[str, "Library"]]] = None,
|
|
513
629
|
**cluster_spec: Any
|
|
514
630
|
) -> "Cluster":
|
|
631
|
+
"""Update cluster configuration and optionally install libraries.
|
|
632
|
+
|
|
633
|
+
Args:
|
|
634
|
+
libraries: Optional libraries to install.
|
|
635
|
+
**cluster_spec: Cluster specification overrides.
|
|
636
|
+
|
|
637
|
+
Returns:
|
|
638
|
+
The updated Cluster instance.
|
|
639
|
+
"""
|
|
515
640
|
self.install_libraries(libraries=libraries, wait_timeout=None, raise_error=False)
|
|
516
641
|
|
|
517
642
|
existing_details = {
|
|
@@ -532,6 +657,7 @@ class Cluster(WorkspaceService):
|
|
|
532
657
|
self, update_details
|
|
533
658
|
)
|
|
534
659
|
|
|
660
|
+
self.wait_for_status()
|
|
535
661
|
self.details = self.clusters_client().edit_and_wait(**update_details)
|
|
536
662
|
|
|
537
663
|
logger.info(
|
|
@@ -542,7 +668,11 @@ class Cluster(WorkspaceService):
|
|
|
542
668
|
return self
|
|
543
669
|
|
|
544
670
|
def list_clusters(self) -> Iterator["Cluster"]:
|
|
545
|
-
"""Iterate clusters, yielding helpers annotated with metadata.
|
|
671
|
+
"""Iterate clusters, yielding helpers annotated with metadata.
|
|
672
|
+
|
|
673
|
+
Returns:
|
|
674
|
+
An iterator of Cluster helpers for each cluster.
|
|
675
|
+
"""
|
|
546
676
|
|
|
547
677
|
for details in self.clusters_client().list():
|
|
548
678
|
details: ClusterDetails = details
|
|
@@ -561,7 +691,16 @@ class Cluster(WorkspaceService):
|
|
|
561
691
|
cluster_name: Optional[str] = None,
|
|
562
692
|
raise_error: Optional[bool] = None
|
|
563
693
|
) -> Optional["Cluster"]:
|
|
564
|
-
"""Find a cluster by name or id and return a populated helper.
|
|
694
|
+
"""Find a cluster by name or id and return a populated helper.
|
|
695
|
+
|
|
696
|
+
Args:
|
|
697
|
+
cluster_id: Optional cluster id to look up.
|
|
698
|
+
cluster_name: Optional cluster name to look up.
|
|
699
|
+
raise_error: Whether to raise if not found.
|
|
700
|
+
|
|
701
|
+
Returns:
|
|
702
|
+
A Cluster instance if found, otherwise None.
|
|
703
|
+
"""
|
|
565
704
|
if not cluster_name and not cluster_id:
|
|
566
705
|
raise ValueError("Either name or cluster_id must be provided")
|
|
567
706
|
|
|
@@ -590,11 +729,21 @@ class Cluster(WorkspaceService):
|
|
|
590
729
|
def ensure_running(
|
|
591
730
|
self,
|
|
592
731
|
) -> "Cluster":
|
|
732
|
+
"""Ensure the cluster is running.
|
|
733
|
+
|
|
734
|
+
Returns:
|
|
735
|
+
The current Cluster instance.
|
|
736
|
+
"""
|
|
593
737
|
return self.start()
|
|
594
738
|
|
|
595
739
|
def start(
|
|
596
740
|
self,
|
|
597
741
|
) -> "Cluster":
|
|
742
|
+
"""Start the cluster if it is not already running.
|
|
743
|
+
|
|
744
|
+
Returns:
|
|
745
|
+
The current Cluster instance.
|
|
746
|
+
"""
|
|
598
747
|
self.wait_for_status()
|
|
599
748
|
|
|
600
749
|
if not self.is_running:
|
|
@@ -608,6 +757,11 @@ class Cluster(WorkspaceService):
|
|
|
608
757
|
def restart(
|
|
609
758
|
self,
|
|
610
759
|
):
|
|
760
|
+
"""Restart the cluster, waiting for libraries to install.
|
|
761
|
+
|
|
762
|
+
Returns:
|
|
763
|
+
The current Cluster instance.
|
|
764
|
+
"""
|
|
611
765
|
self.wait_for_status()
|
|
612
766
|
|
|
613
767
|
if self.is_running:
|
|
@@ -620,6 +774,11 @@ class Cluster(WorkspaceService):
|
|
|
620
774
|
def delete(
|
|
621
775
|
self
|
|
622
776
|
):
|
|
777
|
+
"""Delete the cluster.
|
|
778
|
+
|
|
779
|
+
Returns:
|
|
780
|
+
The SDK delete response.
|
|
781
|
+
"""
|
|
623
782
|
logger.info("Deleting %s", self)
|
|
624
783
|
return self.clusters_client().delete(cluster_id=self.cluster_id)
|
|
625
784
|
|
|
@@ -628,6 +787,15 @@ class Cluster(WorkspaceService):
|
|
|
628
787
|
language: Optional["Language"] = None,
|
|
629
788
|
context_id: Optional[str] = None
|
|
630
789
|
) -> ExecutionContext:
|
|
790
|
+
"""Create a command execution context for this cluster.
|
|
791
|
+
|
|
792
|
+
Args:
|
|
793
|
+
language: Optional language for the execution context.
|
|
794
|
+
context_id: Optional existing context id to reuse.
|
|
795
|
+
|
|
796
|
+
Returns:
|
|
797
|
+
An ExecutionContext instance.
|
|
798
|
+
"""
|
|
631
799
|
return ExecutionContext(
|
|
632
800
|
cluster=self,
|
|
633
801
|
language=language,
|
|
@@ -645,6 +813,20 @@ class Cluster(WorkspaceService):
|
|
|
645
813
|
timeout: Optional[dt.timedelta] = None,
|
|
646
814
|
result_tag: Optional[str] = None,
|
|
647
815
|
):
|
|
816
|
+
"""Execute a command or callable on the cluster.
|
|
817
|
+
|
|
818
|
+
Args:
|
|
819
|
+
obj: Command string or callable to execute.
|
|
820
|
+
language: Optional language for command execution.
|
|
821
|
+
args: Optional positional arguments for the callable.
|
|
822
|
+
kwargs: Optional keyword arguments for the callable.
|
|
823
|
+
env_keys: Optional environment variable names to pass.
|
|
824
|
+
timeout: Optional timeout for execution.
|
|
825
|
+
result_tag: Optional result tag for parsing output.
|
|
826
|
+
|
|
827
|
+
Returns:
|
|
828
|
+
The decoded result from the execution context.
|
|
829
|
+
"""
|
|
648
830
|
return self.context(language=language).execute(
|
|
649
831
|
obj=obj,
|
|
650
832
|
args=args,
|
|
@@ -666,6 +848,7 @@ class Cluster(WorkspaceService):
|
|
|
666
848
|
env_variables: Optional[Dict[str, str]] = None,
|
|
667
849
|
timeout: Optional[dt.timedelta] = None,
|
|
668
850
|
result_tag: Optional[str] = None,
|
|
851
|
+
force_local: bool = False,
|
|
669
852
|
**options
|
|
670
853
|
):
|
|
671
854
|
"""
|
|
@@ -683,9 +866,22 @@ class Cluster(WorkspaceService):
|
|
|
683
866
|
|
|
684
867
|
@ws.remote
|
|
685
868
|
def h(z): ...
|
|
869
|
+
|
|
870
|
+
Args:
|
|
871
|
+
_func: Optional function when used as ``@ws.remote``.
|
|
872
|
+
language: Optional execution language override.
|
|
873
|
+
env_keys: Optional environment variable names to forward.
|
|
874
|
+
env_variables: Optional environment variables to inject.
|
|
875
|
+
timeout: Optional timeout for remote execution.
|
|
876
|
+
result_tag: Optional tag for parsing remote output.
|
|
877
|
+
force_local: force local execution
|
|
878
|
+
**options: Additional execution options passed through.
|
|
879
|
+
|
|
880
|
+
Returns:
|
|
881
|
+
A decorator or wrapped function that executes remotely.
|
|
686
882
|
"""
|
|
687
883
|
def decorator(func: Callable):
|
|
688
|
-
if
|
|
884
|
+
if force_local or self.is_in_databricks_environment():
|
|
689
885
|
return func
|
|
690
886
|
|
|
691
887
|
context = self.context(language=language or Language.PYTHON)
|
|
@@ -723,6 +919,18 @@ class Cluster(WorkspaceService):
|
|
|
723
919
|
raise_error: bool = True,
|
|
724
920
|
restart: bool = True,
|
|
725
921
|
) -> "Cluster":
|
|
922
|
+
"""Install libraries on the cluster and optionally wait for completion.
|
|
923
|
+
|
|
924
|
+
Args:
|
|
925
|
+
libraries: Libraries or package names to install.
|
|
926
|
+
wait_timeout: Optional timeout for installation.
|
|
927
|
+
pip_settings: Optional pip index settings.
|
|
928
|
+
raise_error: Whether to raise on install failure.
|
|
929
|
+
restart: Whether to restart the cluster after installation.
|
|
930
|
+
|
|
931
|
+
Returns:
|
|
932
|
+
The current Cluster instance.
|
|
933
|
+
"""
|
|
726
934
|
if not libraries:
|
|
727
935
|
return self
|
|
728
936
|
|
|
@@ -752,6 +960,11 @@ class Cluster(WorkspaceService):
|
|
|
752
960
|
return self
|
|
753
961
|
|
|
754
962
|
def installed_library_statuses(self):
|
|
963
|
+
"""Return current library install statuses for the cluster.
|
|
964
|
+
|
|
965
|
+
Returns:
|
|
966
|
+
An iterator of library install status objects.
|
|
967
|
+
"""
|
|
755
968
|
return self.workspace.sdk().libraries.cluster_status(cluster_id=self.cluster_id)
|
|
756
969
|
|
|
757
970
|
def uninstall_libraries(
|
|
@@ -760,6 +973,16 @@ class Cluster(WorkspaceService):
|
|
|
760
973
|
libraries: Optional[list["Library"]] = None,
|
|
761
974
|
restart: bool = True
|
|
762
975
|
):
|
|
976
|
+
"""Uninstall libraries from the cluster and optionally restart.
|
|
977
|
+
|
|
978
|
+
Args:
|
|
979
|
+
pypi_packages: Optional list of PyPI package names to uninstall.
|
|
980
|
+
libraries: Optional list of Library objects to uninstall.
|
|
981
|
+
restart: Whether to restart the cluster afterward.
|
|
982
|
+
|
|
983
|
+
Returns:
|
|
984
|
+
The current Cluster instance.
|
|
985
|
+
"""
|
|
763
986
|
if libraries is None:
|
|
764
987
|
to_remove = [
|
|
765
988
|
lib.library
|
|
@@ -805,6 +1028,16 @@ class Cluster(WorkspaceService):
|
|
|
805
1028
|
pip_settings: Optional[PipIndexSettings] = None,
|
|
806
1029
|
raise_error: bool = True,
|
|
807
1030
|
):
|
|
1031
|
+
"""Wait for library installations to finish on the cluster.
|
|
1032
|
+
|
|
1033
|
+
Args:
|
|
1034
|
+
timeout: Maximum time to wait for installs.
|
|
1035
|
+
pip_settings: Optional pip index settings.
|
|
1036
|
+
raise_error: Whether to raise on failures.
|
|
1037
|
+
|
|
1038
|
+
Returns:
|
|
1039
|
+
The current Cluster instance.
|
|
1040
|
+
"""
|
|
808
1041
|
if not self.is_running:
|
|
809
1042
|
return self
|
|
810
1043
|
|
|
@@ -851,6 +1084,14 @@ class Cluster(WorkspaceService):
|
|
|
851
1084
|
self,
|
|
852
1085
|
libraries: str | ModuleType | List[str | ModuleType],
|
|
853
1086
|
):
|
|
1087
|
+
"""Upload local libraries to the cluster's site-packages.
|
|
1088
|
+
|
|
1089
|
+
Args:
|
|
1090
|
+
libraries: Library path, name, module, or iterable of these.
|
|
1091
|
+
|
|
1092
|
+
Returns:
|
|
1093
|
+
The uploaded library argument(s).
|
|
1094
|
+
"""
|
|
854
1095
|
return self.context().install_temporary_libraries(libraries=libraries)
|
|
855
1096
|
|
|
856
1097
|
def _check_library(
|