pipeloom-databricks 0.5.0__py3-none-any.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.
- pipeloom_databricks/__init__.py +18 -0
- pipeloom_databricks/api.py +45 -0
- pipeloom_databricks/bundle.py +113 -0
- pipeloom_databricks/cli.py +561 -0
- pipeloom_databricks/client/__init__.py +121 -0
- pipeloom_databricks/client/connect.py +84 -0
- pipeloom_databricks/client/sdk.py +275 -0
- pipeloom_databricks/deploy.py +188 -0
- pipeloom_databricks/finalize_states.py +72 -0
- pipeloom_databricks/grouping.py +158 -0
- pipeloom_databricks/jobs_model.py +116 -0
- pipeloom_databricks/keys.py +45 -0
- pipeloom_databricks/options.py +66 -0
- pipeloom_databricks/py.typed +0 -0
- pipeloom_databricks/render.py +396 -0
- pipeloom_databricks/repair.py +66 -0
- pipeloom_databricks/run.py +357 -0
- pipeloom_databricks/secrets.py +50 -0
- pipeloom_databricks/serialize.py +30 -0
- pipeloom_databricks/spec.py +75 -0
- pipeloom_databricks/task.py +422 -0
- pipeloom_databricks/task_values.py +69 -0
- pipeloom_databricks/testing/__init__.py +1 -0
- pipeloom_databricks/testing/fake.py +293 -0
- pipeloom_databricks/testing/jobsim.py +179 -0
- pipeloom_databricks/unity.py +23 -0
- pipeloom_databricks/upload.py +217 -0
- pipeloom_databricks-0.5.0.dist-info/METADATA +114 -0
- pipeloom_databricks-0.5.0.dist-info/RECORD +33 -0
- pipeloom_databricks-0.5.0.dist-info/WHEEL +4 -0
- pipeloom_databricks-0.5.0.dist-info/entry_points.txt +14 -0
- pipeloom_databricks-0.5.0.dist-info/licenses/LICENSE +202 -0
- pipeloom_databricks-0.5.0.dist-info/licenses/NOTICE +2 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Databricks renderer for pipeloom: a compiled plan as Jobs settings JSON and bundle YAML.
|
|
2
|
+
|
|
3
|
+
Rendering is pure. Nothing here imports `databricks.sdk`; only the modules that talk to a
|
|
4
|
+
workspace will, and they load it lazily.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def pipeloom_databricks_task() -> None:
|
|
11
|
+
"""The entry point of a rendered task, found by `package_name` and `entry_point`.
|
|
12
|
+
|
|
13
|
+
A function of the package covers a Databricks lookup that does not read entry points. The
|
|
14
|
+
task module loads only when a task runs.
|
|
15
|
+
"""
|
|
16
|
+
from pipeloom_databricks.task import main
|
|
17
|
+
|
|
18
|
+
main()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""The stable surface other pipeloom distributions (such as an Airflow renderer) may call.
|
|
2
|
+
|
|
3
|
+
Importing it loads no SDK: `connect` imports `databricks.sdk` only when it runs.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from pipeloom_databricks.client import (
|
|
9
|
+
ApiError,
|
|
10
|
+
ConnectionNotConfigured,
|
|
11
|
+
DatabricksClient,
|
|
12
|
+
JobSummary,
|
|
13
|
+
RunInfo,
|
|
14
|
+
TaskRunInfo,
|
|
15
|
+
connect,
|
|
16
|
+
)
|
|
17
|
+
from pipeloom_databricks.deploy import DeployResult, DuplicateJobs, deploy, find_job
|
|
18
|
+
from pipeloom_databricks.finalize_states import task_states
|
|
19
|
+
from pipeloom_databricks.grouping import task_key_map
|
|
20
|
+
from pipeloom_databricks.render import deploy_options, render_job
|
|
21
|
+
from pipeloom_databricks.repair import repair
|
|
22
|
+
from pipeloom_databricks.run import RunStarted, SelectionError, find_run, run_job
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"ApiError",
|
|
26
|
+
"ConnectionNotConfigured",
|
|
27
|
+
"DatabricksClient",
|
|
28
|
+
"DeployResult",
|
|
29
|
+
"DuplicateJobs",
|
|
30
|
+
"JobSummary",
|
|
31
|
+
"RunInfo",
|
|
32
|
+
"RunStarted",
|
|
33
|
+
"SelectionError",
|
|
34
|
+
"TaskRunInfo",
|
|
35
|
+
"connect",
|
|
36
|
+
"deploy",
|
|
37
|
+
"deploy_options",
|
|
38
|
+
"find_job",
|
|
39
|
+
"find_run",
|
|
40
|
+
"render_job",
|
|
41
|
+
"repair",
|
|
42
|
+
"run_job",
|
|
43
|
+
"task_key_map",
|
|
44
|
+
"task_states",
|
|
45
|
+
]
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""The files of a Declarative Automation Bundle: one job file and one stable manifest per pipeline.
|
|
2
|
+
|
|
3
|
+
Pure: it returns bytes and never writes. `${workspace.file_path}` is the bundle variable that
|
|
4
|
+
resolves to the synced files at deploy time, so the job finds the project and the manifest
|
|
5
|
+
wherever the bundle lands.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from collections.abc import Sequence
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Final
|
|
14
|
+
|
|
15
|
+
from pipeloom.diagnostics import Report
|
|
16
|
+
from pipeloom.plan.manifest import manifest_bytes
|
|
17
|
+
from pipeloom.plan.model import Plan
|
|
18
|
+
from pipeloom_databricks.jobs_model import to_json
|
|
19
|
+
from pipeloom_databricks.render import (
|
|
20
|
+
Locations,
|
|
21
|
+
_own_version,
|
|
22
|
+
deploy_options,
|
|
23
|
+
job_name,
|
|
24
|
+
render_job,
|
|
25
|
+
)
|
|
26
|
+
from pipeloom_databricks.serialize import to_bundle_yaml
|
|
27
|
+
|
|
28
|
+
BUNDLE_FILE: Final = "databricks.yml"
|
|
29
|
+
WORKSPACE_FILES: Final = "${workspace.file_path}"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class BundleFile:
|
|
34
|
+
path: Path
|
|
35
|
+
"""Where the file goes: `<out>/<name>`."""
|
|
36
|
+
content: bytes
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class Runtime:
|
|
41
|
+
"""What the target says that the job needs to know."""
|
|
42
|
+
|
|
43
|
+
artifacts_root: str | None
|
|
44
|
+
state_shared: bool
|
|
45
|
+
cancel_grace: int = 30
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def find_bundle_root(out: Path, explicit: Path | None) -> Path | None:
|
|
49
|
+
"""`explicit`, else the nearest ancestor of `out` (itself included) that holds databricks.yml."""
|
|
50
|
+
if explicit is not None:
|
|
51
|
+
return explicit.resolve()
|
|
52
|
+
here = out.resolve()
|
|
53
|
+
for folder in (here, *here.parents):
|
|
54
|
+
if (folder / BUNDLE_FILE).is_file():
|
|
55
|
+
return folder
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def relative_to_root(path: Path, root: Path) -> str | None:
|
|
60
|
+
"""`path` below `root` as POSIX text (empty for the root itself), or None when outside."""
|
|
61
|
+
try:
|
|
62
|
+
rel = path.resolve().relative_to(root).as_posix()
|
|
63
|
+
except ValueError:
|
|
64
|
+
return None
|
|
65
|
+
return "" if rel == "." else rel
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _workspace(rel: str) -> str:
|
|
69
|
+
return f"{WORKSPACE_FILES}/{rel}" if rel else WORKSPACE_FILES
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def render_bundle(
|
|
73
|
+
plan: Plan,
|
|
74
|
+
runtime: Runtime,
|
|
75
|
+
pipelines: Sequence[str],
|
|
76
|
+
*,
|
|
77
|
+
out: Path,
|
|
78
|
+
project_rel: str,
|
|
79
|
+
out_rel: str,
|
|
80
|
+
report: Report,
|
|
81
|
+
) -> list[BundleFile] | None:
|
|
82
|
+
"""The files of the given pipelines (all of them when empty), or None with the problems in
|
|
83
|
+
`report`. `project_rel` and `out_rel` are the project folder and the output folder relative
|
|
84
|
+
to the bundle root."""
|
|
85
|
+
opts = deploy_options(plan, report)
|
|
86
|
+
if opts is None:
|
|
87
|
+
return None
|
|
88
|
+
manifest = manifest_bytes(plan, stable=True)
|
|
89
|
+
files: list[BundleFile] = []
|
|
90
|
+
before = report.error_count
|
|
91
|
+
for pipeline in pipelines or sorted(opts.pipelines):
|
|
92
|
+
name = job_name(plan, pipeline)
|
|
93
|
+
locs = Locations(
|
|
94
|
+
project_root=_workspace(project_rel),
|
|
95
|
+
manifest_path=_workspace(f"{out_rel}/{name}.manifest.json".lstrip("/")),
|
|
96
|
+
artifacts_root=runtime.artifacts_root,
|
|
97
|
+
state_shared=runtime.state_shared,
|
|
98
|
+
cancel_grace=runtime.cancel_grace,
|
|
99
|
+
)
|
|
100
|
+
job = render_job(plan, pipeline, locs, report)
|
|
101
|
+
if job is None:
|
|
102
|
+
continue
|
|
103
|
+
header = (
|
|
104
|
+
f"Generated by pipeloom-databricks {_own_version(plan)}.\n"
|
|
105
|
+
f"Project: {plan.metadata.project}. Pipeline: {pipeline}. "
|
|
106
|
+
f"Target: {plan.metadata.target}.\n"
|
|
107
|
+
"Do not edit: run `pipeloom databricks bundle` again."
|
|
108
|
+
)
|
|
109
|
+
files.append(
|
|
110
|
+
BundleFile(out / f"{name}.job.yml", to_bundle_yaml(name, to_json(job.settings), header))
|
|
111
|
+
)
|
|
112
|
+
files.append(BundleFile(out / f"{name}.manifest.json", manifest))
|
|
113
|
+
return None if report.error_count > before else files
|