databricks-bundle-decorators 0.4.2__tar.gz → 0.4.3__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.
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/PKG-INFO +1 -1
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/pyproject.toml +1 -1
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/decorators.py +47 -3
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/polars_csv.py +2 -2
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/polars_delta.py +3 -4
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/polars_json.py +2 -2
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/polars_parquet.py +2 -2
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/spark_delta.py +2 -2
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/spark_parquet.py +2 -2
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/runtime.py +20 -20
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/task_values.py +13 -4
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/README.md +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/__init__.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/cli.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/codegen.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/context.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/discovery.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_manager.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/__init__.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/io_managers/spark_uc.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/registry.py +0 -0
- {databricks_bundle_decorators-0.4.2 → databricks_bundle_decorators-0.4.3}/src/databricks_bundle_decorators/sdk_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: databricks-bundle-decorators
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Decorator-based framework for defining Databricks jobs and tasks as Python code.
|
|
5
5
|
Author: boccileonardo
|
|
6
6
|
Author-email: boccileonardo <leonardobocci99@hotmail.com>
|
|
@@ -4,7 +4,7 @@ requires = [ "uv-build>=0.10.4,<0.11" ]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "databricks-bundle-decorators"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.3"
|
|
8
8
|
description = "Decorator-based framework for defining Databricks jobs and tasks as Python code."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [ { name = "boccileonardo", email = "leonardobocci99@hotmail.com" } ]
|
|
@@ -31,6 +31,32 @@ from databricks_bundle_decorators.registry import (
|
|
|
31
31
|
from databricks_bundle_decorators.sdk_types import ClusterConfig, JobConfig, TaskConfig
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# Reserved parameter namespace
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
#: Parameter names that are reserved for internal runtime wiring.
|
|
39
|
+
_RESERVED_PARAM_NAMES: frozenset[str] = frozenset(
|
|
40
|
+
{"__job_name__", "__task_key__", "__run_id__"}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
#: Parameter name prefixes that are reserved for internal runtime wiring.
|
|
44
|
+
_RESERVED_PARAM_PREFIXES: tuple[str, ...] = ("__upstream__",)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _validate_user_params(params: dict[str, str], context: str) -> None:
|
|
48
|
+
"""Raise ``ValueError`` if any *params* key collides with reserved names."""
|
|
49
|
+
for name in params:
|
|
50
|
+
if name in _RESERVED_PARAM_NAMES or any(
|
|
51
|
+
name.startswith(p) for p in _RESERVED_PARAM_PREFIXES
|
|
52
|
+
):
|
|
53
|
+
raise ValueError(
|
|
54
|
+
f"{context}: parameter name {name!r} is reserved for internal "
|
|
55
|
+
f"runtime use. Reserved names: {sorted(_RESERVED_PARAM_NAMES)}; "
|
|
56
|
+
f"reserved prefix: {list(_RESERVED_PARAM_PREFIXES)}."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
34
60
|
# ---------------------------------------------------------------------------
|
|
35
61
|
# Job context – tracks which @job body is currently being executed
|
|
36
62
|
# ---------------------------------------------------------------------------
|
|
@@ -95,7 +121,8 @@ def task(
|
|
|
95
121
|
|
|
96
122
|
When used **outside** a ``@job`` body (e.g. at module level), the
|
|
97
123
|
function is registered under its short name for use in tests or
|
|
98
|
-
standalone execution.
|
|
124
|
+
standalone execution. Duplicate names at module level raise
|
|
125
|
+
`DuplicateResourceError`.
|
|
99
126
|
|
|
100
127
|
Parameters
|
|
101
128
|
----------
|
|
@@ -110,7 +137,12 @@ def task(
|
|
|
110
137
|
directly to the ``databricks.bundles.jobs.Task`` constructor at
|
|
111
138
|
deploy time. See `TaskConfig`
|
|
112
139
|
for the full list of supported fields.
|
|
113
|
-
|
|
140
|
+
Notes
|
|
141
|
+
-----
|
|
142
|
+
Dependency edges are detected only for `TaskProxy` objects passed as
|
|
143
|
+
**direct** positional or keyword arguments. Proxies nested inside
|
|
144
|
+
lists, dicts, or other container types are **not** inspected and will
|
|
145
|
+
not register dependency edges."""
|
|
114
146
|
|
|
115
147
|
def decorator(fn: types.FunctionType) -> Callable[..., Any]:
|
|
116
148
|
task_key = fn.__name__
|
|
@@ -128,13 +160,21 @@ def task(
|
|
|
128
160
|
_current_job_tasks[task_key] = meta
|
|
129
161
|
else:
|
|
130
162
|
# Module-level definition (standalone / test usage).
|
|
131
|
-
_TASK_REGISTRY
|
|
163
|
+
_register_unique(_TASK_REGISTRY, task_key, meta, "task")
|
|
132
164
|
|
|
133
165
|
@functools.wraps(fn)
|
|
134
166
|
def wrapper(*args, **kwargs):
|
|
135
167
|
if _current_job_name is not None:
|
|
136
168
|
# We're being *called* inside a @job body – return a
|
|
137
169
|
# TaskProxy and record DAG edges from any proxy args.
|
|
170
|
+
if task_key in _current_job_dag:
|
|
171
|
+
raise DuplicateResourceError(
|
|
172
|
+
f"Task '{task_key}' is called more than once in job "
|
|
173
|
+
f"'{_current_job_name}'. Each @task may only be invoked "
|
|
174
|
+
"once per @job body. Use a unique function name for "
|
|
175
|
+
"each logical step."
|
|
176
|
+
)
|
|
177
|
+
|
|
138
178
|
upstream_deps: list[str] = []
|
|
139
179
|
edge_map: dict[str, str] = {}
|
|
140
180
|
|
|
@@ -314,6 +354,10 @@ def job(
|
|
|
314
354
|
f"Duplicate job '{job_name}'. Each job must have a unique name."
|
|
315
355
|
)
|
|
316
356
|
|
|
357
|
+
# --- validate param names -----------------------------------------
|
|
358
|
+
if params:
|
|
359
|
+
_validate_user_params(params, f"@job('{job_name}')")
|
|
360
|
+
|
|
317
361
|
# --- validate cluster type -----------------------------------------
|
|
318
362
|
if cluster is not None and not isinstance(cluster, ClusterMeta):
|
|
319
363
|
raise TypeError(
|
|
@@ -11,7 +11,7 @@ Requires the ``polars`` optional dependency::
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
13
|
from collections.abc import Callable
|
|
14
|
-
from typing import Any
|
|
14
|
+
from typing import Any, cast
|
|
15
15
|
|
|
16
16
|
from databricks_bundle_decorators.io_manager import (
|
|
17
17
|
InputContext,
|
|
@@ -107,7 +107,7 @@ class PolarsCsvIoManager(IoManager):
|
|
|
107
107
|
def storage_options(self) -> dict[str, str] | None:
|
|
108
108
|
"""Resolve *storage_options*, calling it first if it is a callable."""
|
|
109
109
|
if callable(self._storage_options):
|
|
110
|
-
return self._storage_options()
|
|
110
|
+
return cast(Callable[[], dict[str, str]], self._storage_options)()
|
|
111
111
|
return self._storage_options
|
|
112
112
|
|
|
113
113
|
def _uri(self, key: str) -> str:
|
|
@@ -12,7 +12,7 @@ Requires the ``polars`` and ``deltalake`` optional dependencies::
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
14
|
from collections.abc import Callable
|
|
15
|
-
from typing import Any
|
|
15
|
+
from typing import Any, cast
|
|
16
16
|
|
|
17
17
|
from databricks_bundle_decorators.io_manager import (
|
|
18
18
|
InputContext,
|
|
@@ -81,8 +81,7 @@ class PolarsDeltaIoManager(IoManager):
|
|
|
81
81
|
they are managed by the IoManager.
|
|
82
82
|
mode : str
|
|
83
83
|
Delta write mode. One of ``"overwrite"``, ``"append"``,
|
|
84
|
-
``"error"``, or ``"ignore"``. Defaults to ``"
|
|
85
|
-
for idempotent task outputs.
|
|
84
|
+
``"error"``, or ``"ignore"``. Defaults to ``"error"``.
|
|
86
85
|
|
|
87
86
|
For **merge** operations, ignore this parameter and return a
|
|
88
87
|
fully-configured `deltalake.table.TableMerger` from your task
|
|
@@ -129,7 +128,7 @@ class PolarsDeltaIoManager(IoManager):
|
|
|
129
128
|
def storage_options(self) -> dict[str, str] | None:
|
|
130
129
|
"""Resolve *storage_options*, calling it first if it is a callable."""
|
|
131
130
|
if callable(self._storage_options):
|
|
132
|
-
return self._storage_options()
|
|
131
|
+
return cast(Callable[[], dict[str, str]], self._storage_options)()
|
|
133
132
|
return self._storage_options
|
|
134
133
|
|
|
135
134
|
def _uri(self, key: str) -> str:
|
|
@@ -15,7 +15,7 @@ Requires the ``polars`` optional dependency::
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
from collections.abc import Callable
|
|
18
|
-
from typing import Any
|
|
18
|
+
from typing import Any, cast
|
|
19
19
|
|
|
20
20
|
from databricks_bundle_decorators.io_manager import (
|
|
21
21
|
InputContext,
|
|
@@ -114,7 +114,7 @@ class PolarsJsonIoManager(IoManager):
|
|
|
114
114
|
def storage_options(self) -> dict[str, str] | None:
|
|
115
115
|
"""Resolve *storage_options*, calling it first if it is a callable."""
|
|
116
116
|
if callable(self._storage_options):
|
|
117
|
-
return self._storage_options()
|
|
117
|
+
return cast(Callable[[], dict[str, str]], self._storage_options)()
|
|
118
118
|
return self._storage_options
|
|
119
119
|
|
|
120
120
|
def _uri(self, key: str) -> str:
|
|
@@ -11,7 +11,7 @@ Requires the ``polars`` optional dependency::
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
13
|
from collections.abc import Callable
|
|
14
|
-
from typing import Any
|
|
14
|
+
from typing import Any, cast
|
|
15
15
|
|
|
16
16
|
from databricks_bundle_decorators.io_manager import (
|
|
17
17
|
InputContext,
|
|
@@ -114,7 +114,7 @@ class PolarsParquetIoManager(IoManager):
|
|
|
114
114
|
def storage_options(self) -> dict[str, str] | None:
|
|
115
115
|
"""Resolve *storage_options*, calling it first if it is a callable."""
|
|
116
116
|
if callable(self._storage_options):
|
|
117
|
-
return self._storage_options()
|
|
117
|
+
return cast(Callable[[], dict[str, str]], self._storage_options)()
|
|
118
118
|
return self._storage_options
|
|
119
119
|
|
|
120
120
|
def _uri(self, key: str) -> str:
|
|
@@ -14,7 +14,7 @@ Requires PySpark, which is pre-installed on Databricks clusters.
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
16
|
from collections.abc import Callable
|
|
17
|
-
from typing import Any
|
|
17
|
+
from typing import Any, cast
|
|
18
18
|
|
|
19
19
|
from databricks_bundle_decorators.io_manager import (
|
|
20
20
|
InputContext,
|
|
@@ -194,7 +194,7 @@ class SparkDeltaIoManager(_SparkDeltaBase):
|
|
|
194
194
|
def spark_configs(self) -> dict[str, str] | None:
|
|
195
195
|
"""Resolve *spark_configs*, calling it first if it is a callable."""
|
|
196
196
|
if callable(self._spark_configs):
|
|
197
|
-
return self._spark_configs()
|
|
197
|
+
return cast(Callable[[], dict[str, str]], self._spark_configs)()
|
|
198
198
|
return self._spark_configs
|
|
199
199
|
|
|
200
200
|
def setup(self) -> None:
|
|
@@ -14,7 +14,7 @@ Requires PySpark, which is pre-installed on Databricks clusters.
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
16
|
from collections.abc import Callable
|
|
17
|
-
from typing import Any
|
|
17
|
+
from typing import Any, cast
|
|
18
18
|
|
|
19
19
|
from databricks_bundle_decorators.io_manager import (
|
|
20
20
|
InputContext,
|
|
@@ -153,7 +153,7 @@ class SparkParquetIoManager(_SparkParquetBase):
|
|
|
153
153
|
def spark_configs(self) -> dict[str, str] | None:
|
|
154
154
|
"""Resolve *spark_configs*, calling it first if it is a callable."""
|
|
155
155
|
if callable(self._spark_configs):
|
|
156
|
-
return self._spark_configs()
|
|
156
|
+
return cast(Callable[[], dict[str, str]], self._spark_configs)()
|
|
157
157
|
return self._spark_configs
|
|
158
158
|
|
|
159
159
|
def setup(self) -> None:
|
|
@@ -11,8 +11,8 @@ Databricks invokes the ``dbxdec-run`` console-script, which calls
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import argparse
|
|
14
|
+
import logging
|
|
14
15
|
import os
|
|
15
|
-
import sys
|
|
16
16
|
import typing
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
@@ -20,6 +20,8 @@ from databricks_bundle_decorators.context import _populate_params
|
|
|
20
20
|
from databricks_bundle_decorators.io_manager import InputContext, OutputContext
|
|
21
21
|
from databricks_bundle_decorators.registry import _TASK_REGISTRY
|
|
22
22
|
|
|
23
|
+
_logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
23
25
|
|
|
24
26
|
def _parse_named_args(argv: list[str]) -> dict[str, str]:
|
|
25
27
|
"""Parse ``--key=value`` pairs from an argv list into a dict."""
|
|
@@ -58,14 +60,14 @@ def run_task(task_key: str, cli_params: dict[str, str]) -> None:
|
|
|
58
60
|
_populate_params(cli_params)
|
|
59
61
|
|
|
60
62
|
# ---- look up task metadata -------------------------------------------
|
|
61
|
-
# Try qualified key (job_name.task_key) first, then short key.
|
|
62
63
|
qualified_key = f"{job_name}.{task_key}"
|
|
63
|
-
task_meta = _TASK_REGISTRY.get(qualified_key)
|
|
64
|
+
task_meta = _TASK_REGISTRY.get(qualified_key)
|
|
64
65
|
if task_meta is None:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
available = list(_TASK_REGISTRY.keys())
|
|
67
|
+
raise RuntimeError(
|
|
68
|
+
f"Task '{task_key}' not found by qualified key '{qualified_key}'. "
|
|
69
|
+
f"Available: {available}"
|
|
70
|
+
)
|
|
69
71
|
|
|
70
72
|
# ---- resolve type hints for the current task's parameters ------------
|
|
71
73
|
try:
|
|
@@ -77,9 +79,7 @@ def run_task(task_key: str, cli_params: dict[str, str]) -> None:
|
|
|
77
79
|
kwargs: dict[str, Any] = {}
|
|
78
80
|
for param_name, upstream_task_key in upstream_map.items():
|
|
79
81
|
upstream_qualified = f"{job_name}.{upstream_task_key}"
|
|
80
|
-
upstream_meta = _TASK_REGISTRY.get(upstream_qualified)
|
|
81
|
-
upstream_task_key
|
|
82
|
-
)
|
|
82
|
+
upstream_meta = _TASK_REGISTRY.get(upstream_qualified)
|
|
83
83
|
if upstream_meta and upstream_meta.io_manager:
|
|
84
84
|
upstream_meta.io_manager._ensure_setup()
|
|
85
85
|
context = InputContext(
|
|
@@ -91,10 +91,11 @@ def run_task(task_key: str, cli_params: dict[str, str]) -> None:
|
|
|
91
91
|
)
|
|
92
92
|
kwargs[param_name] = upstream_meta.io_manager.read(context)
|
|
93
93
|
else:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
_logger.warning(
|
|
95
|
+
"Upstream task '%s' has no IoManager – "
|
|
96
|
+
"cannot auto-load data for parameter '%s'.",
|
|
97
|
+
upstream_task_key,
|
|
98
|
+
param_name,
|
|
98
99
|
)
|
|
99
100
|
|
|
100
101
|
# ---- execute the task function ---------------------------------------
|
|
@@ -116,10 +117,10 @@ def run_task(task_key: str, cli_params: dict[str, str]) -> None:
|
|
|
116
117
|
)
|
|
117
118
|
task_meta.io_manager.write(context, result)
|
|
118
119
|
elif result is not None and not task_meta.io_manager:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
_logger.warning(
|
|
121
|
+
"Task '%s' returned a value but has no IoManager – "
|
|
122
|
+
"the return value will be discarded.",
|
|
123
|
+
task_key,
|
|
123
124
|
)
|
|
124
125
|
|
|
125
126
|
|
|
@@ -142,8 +143,7 @@ def main() -> None:
|
|
|
142
143
|
|
|
143
144
|
task_key = cli_params.get("__task_key__")
|
|
144
145
|
if not task_key:
|
|
145
|
-
|
|
146
|
-
sys.exit(1)
|
|
146
|
+
raise RuntimeError("--__task_key__=<name> is required.")
|
|
147
147
|
|
|
148
148
|
# 3. Run the task.
|
|
149
149
|
run_task(task_key, cli_params)
|
|
@@ -6,6 +6,7 @@ small primitive payloads (~48 KB) and must be opted-in explicitly by calling
|
|
|
6
6
|
`set_task_value` inside a ``@task`` function.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
import os
|
|
9
10
|
from typing import Any
|
|
10
11
|
|
|
11
12
|
# Module-level fallback store used during local / test execution.
|
|
@@ -16,6 +17,11 @@ _local_task_values: dict[str, dict[str, Any]] = {}
|
|
|
16
17
|
_current_task_key: str | None = None
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def _is_databricks_runtime() -> bool:
|
|
21
|
+
"""Return ``True`` when running inside a live Databricks job cluster."""
|
|
22
|
+
return bool(os.environ.get("DATABRICKS_RUNTIME_VERSION"))
|
|
23
|
+
|
|
24
|
+
|
|
19
25
|
def set_task_value(key: str, value: str | int | float | bool) -> None:
|
|
20
26
|
"""Write a small value into Databricks task values.
|
|
21
27
|
|
|
@@ -37,14 +43,16 @@ def set_task_value(key: str, value: str | int | float | bool) -> None:
|
|
|
37
43
|
f"got {type(value).__name__}. Use an IoManager for complex data."
|
|
38
44
|
)
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
if _is_databricks_runtime():
|
|
47
|
+
# On Databricks: let any API/permission error propagate so that
|
|
48
|
+
# real runtime failures are visible rather than silently swallowed.
|
|
41
49
|
from pyspark.dbutils import DBUtils # type: ignore[import-untyped]
|
|
42
50
|
from pyspark.sql import SparkSession # type: ignore[import-untyped]
|
|
43
51
|
|
|
44
52
|
spark = SparkSession.builder.getOrCreate()
|
|
45
53
|
dbutils = DBUtils(spark)
|
|
46
54
|
dbutils.jobs.taskValues.set(key=key, value=value)
|
|
47
|
-
|
|
55
|
+
else:
|
|
48
56
|
# Local / testing fallback — use the current task key if set by
|
|
49
57
|
# the runtime runner, otherwise fall back to "__current__".
|
|
50
58
|
store_key = _current_task_key or "__current__"
|
|
@@ -61,12 +69,13 @@ def get_task_value(task_key: str, key: str) -> Any:
|
|
|
61
69
|
key:
|
|
62
70
|
The key passed to `set_task_value`.
|
|
63
71
|
"""
|
|
64
|
-
|
|
72
|
+
if _is_databricks_runtime():
|
|
73
|
+
# On Databricks: let any API/permission error propagate.
|
|
65
74
|
from pyspark.dbutils import DBUtils # type: ignore[import-untyped]
|
|
66
75
|
from pyspark.sql import SparkSession # type: ignore[import-untyped]
|
|
67
76
|
|
|
68
77
|
spark = SparkSession.builder.getOrCreate()
|
|
69
78
|
dbutils = DBUtils(spark)
|
|
70
79
|
return dbutils.jobs.taskValues.get(taskKey=task_key, key=key)
|
|
71
|
-
|
|
80
|
+
else:
|
|
72
81
|
return _local_task_values.get(task_key, {}).get(key)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|