API reference¶
Everything on this page is importable from pytest_databricks_lakeflow. The lakeflow fixture and the command-line flags are registered by the plugin's pytest11 entry point.
The lakeflow fixture¶
Session-scoped. It returns Lakeflow() unless you override it in a conftest.py. Tests that request it get the lakeflow marker, so pytest -m "not lakeflow" deselects them.
Lakeflow¶
Lakeflow
dataclass
¶
Lakeflow(
*,
bundle_root: str | Path | None = None,
target: str = "test",
profile: str | None = None,
workspace_client: WorkspaceClient | None = None,
sync: Sync = "deploy",
variables: Mapping[str, str] | None = None,
deploy_flags: Sequence[str] = (),
timeout: timedelta = timedelta(minutes=30),
poll_interval: timedelta | None = None,
max_concurrent_runs: int | None = None,
catalog: str | None = None,
helpers_path: str | None = None,
helpers_compute: str | None = None,
helpers_environment_version: str = "4",
disable_auto_optimization: bool = True,
performance_optimized: bool = False,
side_effects: SideEffects = "neutralise",
environment_version: str | None = None,
budget_policy_id: str | None = None,
existing_cluster_id: str | None = None,
single_node: bool = False,
allow_undeclared_params: bool = False,
test_marker: bool = False,
notebook_export: NotebookExport = "failed",
dbt_artifacts: bool = False,
sweep_hours: float = 24,
keep: bool = False,
keep_failed: bool = True,
strict_artifacts: bool = False,
permissions: Sequence[
Mapping[str, str] | JobAccessControlRequest
]
| None = None,
run_as: RunAs = None,
queue: bool | None = None,
disable: Sequence[str] | None = None,
extra_dependencies: Sequence[str] | None = None,
children: Children = "warn",
setup: LifecycleStep | None = None,
teardown: LifecycleStep | None = None,
environments: Mapping[str, Mapping[str, Any]]
| None = None,
saved_queries: SavedQueries = "deployed",
modify_settings: Callable[[JobSettings, Item], None]
| None = None,
run_finished: Callable[[JobRun, Item], None]
| None = None,
)
Makes throwaway copies of a bundle's jobs for tests.
Tests get one from the lakeflow fixture. Override the fixture to configure it:
@pytest.fixture(scope="session")
def lakeflow() -> Lakeflow:
return Lakeflow(target="test", catalog="dev_sandbox")
Creating one does nothing. The first test that uses it sets up the bundle, which happens once per session for
each bundle target, however many Lakeflow instances use it and however many xdist workers there are.
Attributes:
| Name | Type | Description |
|---|---|---|
bundle_root |
str | Path | None
|
The bundle's directory, relative to the pytest rootdir. Defaults to the nearest directory with a databricks.yml, starting at the rootdir. |
target |
str
|
The bundle target to deploy and read job templates from. |
profile |
str | None
|
The Databricks config profile for the CLI and the SDK. Defaults to their standard resolution, which
reads |
workspace_client |
WorkspaceClient | None
|
A client to use instead of making one from |
sync |
Sync
|
How to prepare the bundle: |
variables |
Mapping[str, str] | None
|
Bundle variables, passed as |
deploy_flags |
Sequence[str]
|
Extra flags for |
timeout |
timedelta
|
The default timeout for one job run. Each job is also created with |
poll_interval |
timedelta | None
|
How long to wait between two polls of a run that has not finished. Defaults to two seconds.
Zero or less raises |
max_concurrent_runs |
int | None
|
How many runs this process may have active at once, for a workspace with a tight
serverless quota. |
catalog |
str | None
|
The catalog in which |
helpers_path |
str | None
|
The workspace folder for the helper notebooks. Defaults to
|
helpers_compute |
str | None
|
A |
helpers_environment_version |
str
|
The serverless environment version for stub, probe, setup and teardown tasks. |
disable_auto_optimization |
bool
|
Stop serverless from retrying failed tasks, so that a failure fails once and fast. |
performance_optimized |
bool
|
Run every ephemeral job as |
side_effects |
SideEffects
|
|
environment_version |
str | None
|
The serverless environment version of every environment copied from the template,
except those whose spec sets |
budget_policy_id |
str | None
|
The budget policy of every ephemeral job and pipeline. |
existing_cluster_id |
str | None
|
A running cluster for every task that the template puts on a job cluster or a new
cluster, stub, probe, setup and teardown tasks and tasks nested in a |
single_node |
bool
|
Make every job cluster and every task's |
allow_undeclared_params |
bool
|
Allow parameters that the job does not declare. |
test_marker |
bool
|
Declare a |
notebook_export |
NotebookExport
|
Which notebook tasks to read with |
dbt_artifacts |
bool
|
Download the artefacts of each dbt task as soon as its run finishes, while the platform's
30 minute link is valid, and parse them into |
sweep_hours |
float
|
The age after which |
keep |
bool
|
Keep every ephemeral job and temporary schema. |
keep_failed |
bool
|
Keep the ephemeral job when its test fails. |
strict_artifacts |
bool
|
Raise |
permissions |
Sequence[Mapping[str, str] | JobAccessControlRequest] | None
|
The |
run_as |
RunAs
|
The default of |
queue |
bool | None
|
The default of |
disable |
Sequence[str] | None
|
The default of |
extra_dependencies |
Sequence[str] | None
|
The default of |
children |
Children
|
The default of |
setup |
LifecycleStep | None
|
The default of |
teardown |
LifecycleStep | None
|
The default of |
environments |
Mapping[str, Mapping[str, Any]] | None
|
The default of |
saved_queries |
SavedQueries
|
The default of A per-call argument that is |
modify_settings |
Callable[[JobSettings, Item], None] | None
|
Called with each ephemeral job's settings and the test, just before the job is created. Change the settings in place. |
run_finished |
Callable[[JobRun, Item], None] | None
|
Called with the outcome of each run and the test, after the run finishes. |
active_runs |
set[int]
|
Ids of the runs started by this |
active_updates |
dict[str, str]
|
The update that |
ws
property
¶
ws: WorkspaceClient
The workspace client: workspace_client, or one made from profile on first use.
run_id
property
¶
run_id: str
The id of this test session, which tags ephemeral jobs and names temporary schemas.
templates
property
¶
templates: dict[str, dict[str, Any]]
The deployed settings of each usable bundle job, by resource key, as dicts.
template_errors
property
¶
template_errors: dict[str, str]
Why each bundle job that cannot be used as a template cannot, by resource key.
access_control_list ¶
access_control_list() -> (
list[jobs.JobAccessControlRequest] | None
)
Get permissions as the access_control_list that jobs.create takes, or None if there are none.
template ¶
template(key: str) -> jobs.JobSettings
Get a fresh copy of the deployed settings of a bundle job.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The bundle resource key of the job. |
required |
Returns:
| Type | Description |
|---|---|
JobSettings
|
The job's settings, safe to change. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the bundle has no job |
LakeflowBundleError
|
If the job cannot be used as a template, for example because it is not deployed. |
check ¶
check(
key: str, *, rules: Collection[str] | None = None
) -> list[str]
Find the wiring mistakes in a bundle job's template, without creating or running anything.
It reports a {{job.parameters.<name>}} the job does not declare, a {{tasks.<key>.values.<name>}} whose
task is not upstream of the task that refers to it, a depends_on task that is not in the job, and retry
settings on a for_each_task, which belong on its nested task. bundle validate passes all of them. The
rules that rules names report more: wheel a python_wheel_task entry point that the newest built wheel
of its package under the bundle's dist does not have, library a library, Python file or environment
dependency path that starts with / and does not exist in the workspace, dash a task reference to a task
key with a dash, trigger a {{job.trigger.*}} reference, which a test's run does not resolve as its
trigger would, and the opt-in equal_to an EQUAL_TO or NOT_EQUAL condition on a number or a task
value, which compares text. It lints the template the session loaded: the deployed job, or the
bundle validate output under sync="sync" or "none". It works outside a test, for example in a
session-scoped fixture, and only reads the workspace.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The bundle resource key of the job. |
required |
rules
|
Collection[str] | None
|
The named rules to apply, from |
None
|
Returns:
| Type | Description |
|---|---|
list[str]
|
One message per problem, in the order of the job's tasks, each starting with |
list[str]
|
missing dependencies of its environments, each starting with |
list[str]
|
references in its job parameters, each starting with |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the bundle has no job |
LakeflowBundleError
|
If the job cannot be used as a template, for example because it is not deployed. |
ValueError
|
If |
job ¶
job(
key: str,
params: Mapping[str, str] | None = None,
*,
capture_task_values: Mapping[str, Sequence[str]]
| None = None,
name: str | None = None,
run_as: RunAs = None,
disable: Sequence[str] | None = None,
task_params: Mapping[
str, Mapping[str, str] | Sequence[str]
]
| None = None,
force_conditions: Mapping[str, bool] | None = None,
children: Children | None = None,
setup: LifecycleStep | None = None,
teardown: LifecycleStep | None = None,
teardown_at: TeardownAt = "run",
extra_dependencies: Sequence[str] | None = None,
environments: Mapping[str, Mapping[str, Any]]
| None = None,
task_overrides: Mapping[str, Mapping[str, object]]
| None = None,
upstream_task_values: Upstream | None = None,
pipelines: Pipelines = "deployed",
schema: str | None = None,
for_each_inputs: Mapping[str, Sequence[object]]
| None = None,
trigger: Mapping[str, str] | None = None,
saved_queries: SavedQueries | None = None,
) -> EphemeralJob
Make a throwaway copy of a bundle job.
setup and teardown run on the job's compute, as notebook tasks of the copy. The setup task runs before
every other task on every run, and the teardown task after every other task, whether they passed or failed,
or with teardown_at="close" alone when the job closes.
Each is one of three forms:
- A plain function taking any of
spark,dbutilsandparams, a dict of the job's parameters with their values for the run, as strings: those it declares, thosemodify_settingsdeclares and those passed underallow_undeclared_params=True. It must be self-contained: it is shipped as source, so imports go inside it and it cannot use variables of an enclosing function. A value it returns becomes the task'soutputas JSON. - A list of SQL statements, each rendered with
string.Templatefrom the same parameters (${name}, and$$for a literal dollar) and run in order throughspark.sql. The output is{"statements": <count>}. The list must not be empty. Each${name}is checked here, whenjob()is called, so it must be a parameter the bundle job declares or a key ofparams; one that onlyrun(params=...)ormodify_settingswould supply is refused. - A
pathlib.Pathto a.pyfile, relative to the pytest rootdir, uploaded as the notebook. It reads the parameters from its widgets and callsdbutils.notebook.exititself for an output.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The bundle resource key of the job, as |
required |
params
|
Mapping[str, str] | None
|
Job parameters for every run of the copy. |
None
|
capture_task_values
|
Mapping[str, Sequence[str]] | None
|
The task value keys to capture, by task key. A for-each task and the task nested in it cannot be named, because the loop's iterations cannot set task values. |
None
|
name
|
str | None
|
Replaces the test node id in the job name. |
None
|
run_as
|
RunAs
|
Who the copy runs as. |
None
|
disable
|
Sequence[str] | None
|
Task keys to disable in the copy. Runs skip them, and the platform disables every task downstream
of them too. Both appear in |
None
|
task_params
|
Mapping[str, Mapping[str, str] | Sequence[str]] | None
|
Parameters for single tasks of the copy, by task key, in the shape the task type takes. A
mapping is merged into a notebook task's |
None
|
force_conditions
|
Mapping[str, bool] | None
|
The outcome each if/else condition task takes in every run of the copy, by task key:
|
None
|
children
|
Children | None
|
What to do about Run Job tasks, which the copy keeps as deployed, so they run the deployed
child job and not a copy. |
None
|
setup
|
LifecycleStep | None
|
A function, a list of SQL statements or a |
None
|
teardown
|
LifecycleStep | None
|
A function, a list of SQL statements or a |
None
|
teardown_at
|
TeardownAt
|
When the teardown task runs. |
'run'
|
extra_dependencies
|
Sequence[str] | None
|
Test-only dependencies for the copy, as PyPI requirements, workspace or Volumes
paths of wheels, or local wheels as paths relative to the bundle root that start with |
None
|
environments
|
Mapping[str, Mapping[str, Any]] | None
|
Fields of the copy's serverless environment specs, by |
None
|
task_overrides
|
Mapping[str, Mapping[str, object]] | None
|
Timeout and retry fields of the copy's tasks, by task key, such as
|
None
|
upstream_task_values
|
Upstream | None
|
Tasks of the copy to replace with stubs, by task key, with the task values each stub
sets, such as |
None
|
pipelines
|
Pipelines
|
What the copy's pipeline tasks update. |
'deployed'
|
schema
|
str | None
|
The full name of the schema the pipeline copies publish to, as |
None
|
for_each_inputs
|
Mapping[str, Sequence[object]] | None
|
The list each for-each task of the copy iterates over, by task key, such as
|
None
|
trigger
|
Mapping[str, str] | None
|
The values the copy's |
None
|
saved_queries
|
SavedQueries | None
|
What the copy's saved query tasks, SQL tasks with |
None
|
Returns:
| Type | Description |
|---|---|
EphemeralJob
|
The job, created when entered with |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the bundle has no job |
ValueError
|
If an argument is wrong on its own: |
LakeflowError
|
If called outside a test, or an argument does not fit the job: |
LakeflowBundleError
|
If |
task ¶
task(
ref: str,
params: Mapping[str, str] | None = None,
*,
upstream_task_values: Upstream | None = None,
capture_task_values: Sequence[str] | None = None,
name: str | None = None,
run_as: RunAs = None,
task_params: Mapping[
str, Mapping[str, str] | Sequence[str]
]
| None = None,
upstream_from: JobRun | None = None,
children: Children | None = None,
setup: LifecycleStep | None = None,
teardown: LifecycleStep | None = None,
teardown_at: TeardownAt = "run",
extra_dependencies: Sequence[str] | None = None,
environments: Mapping[str, Mapping[str, Any]]
| None = None,
task_overrides: Mapping[str, Mapping[str, object]]
| None = None,
pipelines: Pipelines = "deployed",
schema: str | None = None,
for_each_inputs: Sequence[object] | None = None,
input: object | None = None,
trigger: Mapping[str, str] | None = None,
saved_queries: SavedQueries | None = None,
) -> EphemeralJob
Make a throwaway job that holds one task of a bundle job.
Each upstream task named in upstream_task_values is replaced by a stub task with the same key, so the task's
{{tasks.<key>.values.<name>}} references and taskValues.get calls resolve against the stub. A stub is a
notebook task, so it has no SQL, alert or other task output: the task's {{tasks.<key>.output.<path>}}
references are replaced by the literals that a Stub gives in outputs.
upstream_from replays the task with the values a previous run of the job captured: each task that the task
depends on is stubbed with its task_values in that run. The platform returns no task values with a run, so
that run must have captured them, with capture_task_values={"<upstream key>": [...]} on job().
A three-part ref names the task nested in a for-each task, such as "fanout.loop.inner". The job holds that
task in place of the for-each task, so it runs once, as an ordinary task, with input as its iteration input
and the for-each task's upstream tasks as its own:
upstream = {"extract": {"rows": 3}}
with lakeflow.task("fanout.loop.inner", input={"id": 7}, upstream_task_values=upstream) as task:
assert task.run().task("inner").parameters["item_id"] == "7.0"
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ref
|
str
|
The job and task as |
required |
params
|
Mapping[str, str] | None
|
Job parameters for every run. |
None
|
upstream_task_values
|
Upstream | None
|
By upstream task key, a mapping of value keys to values, or a |
None
|
capture_task_values
|
Sequence[str] | None
|
The task value keys to capture from the task. For a three-part |
None
|
name
|
str | None
|
Replaces the test node id in the job name, as for |
None
|
run_as
|
RunAs
|
Who the job runs as, as for |
None
|
task_params
|
Mapping[str, Mapping[str, str] | Sequence[str]] | None
|
Parameters for the task, as for |
None
|
upstream_from
|
JobRun | None
|
A run of the same job whose captured task values stub the task's upstream tasks. |
None
|
children
|
Children | None
|
What to do when the task is a Run Job task, as for |
None
|
setup
|
LifecycleStep | None
|
Runs first, before the stubs, as for |
None
|
teardown
|
LifecycleStep | None
|
Runs last, after the task and its probe, as for |
None
|
teardown_at
|
TeardownAt
|
When the teardown task runs, at the end of every run or when the job closes, as for |
'run'
|
extra_dependencies
|
Sequence[str] | None
|
Test-only dependencies for the job, as for |
None
|
environments
|
Mapping[str, Mapping[str, Any]] | None
|
Fields of the job's serverless environment specs, by |
None
|
task_overrides
|
Mapping[str, Mapping[str, object]] | None
|
Timeout and retry fields of the task, as for |
None
|
pipelines
|
Pipelines
|
|
'deployed'
|
schema
|
str | None
|
The full name of the schema the pipeline copy publishes to, as for |
None
|
for_each_inputs
|
Sequence[object] | None
|
The list the task iterates over when it is a for-each task, such as |
None
|
input
|
object | None
|
The iteration input of the nested task a three-part |
None
|
trigger
|
Mapping[str, str] | None
|
The values the task's |
None
|
saved_queries
|
SavedQueries | None
|
|
None
|
Returns:
| Type | Description |
|---|---|
EphemeralJob
|
The job, created when entered with |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the bundle has no such job. |
ValueError
|
If |
LakeflowError
|
If called outside a test, the job has no such task, a three-part |
LakeflowBundleError
|
If |
attach ¶
attach(run_id: int) -> JobRun
Rebuild the outcome of a finished run of a kept ephemeral job, without running anything.
The run's job must still exist, as keep_failed, keep and --lakeflow-keep leave it, because its settings
say which tasks were stubs and which values the probes captured. Nothing is deployed, created, cancelled or
deleted, so a test that only attaches needs no bundle. The outcome is recorded in the test's report section
as for a run the test started, but run_finished is not called. A child run of a Run Job task is named by
its job id, not its bundle key.
run = lakeflow.attach(5437110661)
assert run.task("transform").task_values == {"row_count": 3}
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_id
|
int
|
The job run id, the number at the end of the |
required |
Returns:
| Type | Description |
|---|---|
JobRun
|
The run's outcome, as |
Raises:
| Type | Description |
|---|---|
LakeflowError
|
If called outside a test, the run does not exist, it is a task run, it has not finished, its job no longer exists, or its job was not created by this plugin. |
pipeline ¶
pipeline(
key: str,
schema: str,
*,
configuration: Mapping[str, str] | None = None,
name: str | None = None,
) -> EphemeralPipeline
Make a throwaway copy of a bundle pipeline that publishes to schema.
The copy is made from the deployed pipeline's spec, so it runs the code that the last bundle deploy uploaded.
It publishes to schema, in the publishing mode the deployed pipeline uses, runs in development mode, and
leaves out the deployment, the continuous and trigger settings, the notifications and the event log. It runs as
you. Only tables that the pipeline's code names without a schema go to schema; a fully qualified name still
writes where it says.
with lakeflow.schema() as schema, lakeflow.pipeline("my_pipeline", schema=schema) as pipeline:
update = pipeline.run(full_refresh=True)
assert update.state == "COMPLETED"
The copy is deleted with its tables before the schema is dropped, unless the keep rules keep it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The bundle resource key of the pipeline. |
required |
schema
|
str
|
The full name of the schema the copy publishes to, |
required |
configuration
|
Mapping[str, str] | None
|
Keys to set in the copy's configuration, over the deployed pipeline's, for code that reads
its catalog or schema from |
None
|
name
|
str | None
|
Replaces the test node id in the copy's name. |
None
|
Returns:
| Type | Description |
|---|---|
EphemeralPipeline
|
The copy, created when entered with |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the bundle has no pipeline |
ValueError
|
If |
LakeflowBundleError
|
If |
LakeflowError
|
If called outside a test, the pipeline publishes to the Hive metastore, or the copy would have more than 25 tags without the attribution tags. |
schema ¶
schema(
catalog: str | None = None,
) -> Generator[str, None, None]
Create a temporary schema, and drop it on leaving the with block.
The schema is named <catalog>.pytest_<run id>_<random>. Pass it to jobs as a job parameter, because
bundle variables cannot change per test. It is dropped even when the block fails, unless keep or
--lakeflow-keep is set. It carries the pytest_expires property of --lakeflow-keep-ttl and the
pytest_git_branch property, when they have a value, which the sweep reads as it reads a job's tags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
catalog
|
str | None
|
The catalog to create it in. Defaults to |
None
|
Yields:
| Type | Description |
|---|---|
str
|
The schema's full name. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If there is no catalog. |
sweep ¶
sweep(
*,
scope: SweepScope = "mine",
schemas_catalog: str | None = None,
notebooks: bool = False,
branch: str | None = None,
dry_run: bool = False,
report: str | Path | None = None,
) -> SweepReport
Delete leftover ephemeral jobs, pipeline copies, schemas and notebooks, as --lakeflow-sweep does.
It needs no pytest session, no bundle and no test, so a nightly job can call it from a script. It uses this
instance's workspace client, sweep_hours and helpers_path, or your default helpers folder, and spares no
run: every job older than sweep_hours goes, unless its pytest_expires time is still ahead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
SweepScope
|
|
'mine'
|
schemas_catalog
|
str | None
|
A catalog whose old |
None
|
notebooks
|
bool
|
Also delete old setup, teardown and debug notebooks and inlined saved query files that no job the sweep keeps uses. |
False
|
branch
|
str | None
|
Delete only what carries this |
None
|
dry_run
|
bool
|
Delete nothing, and report what would be deleted. |
False
|
report
|
str | Path | None
|
A file to write the report to, as JSON. |
None
|
Returns:
| Type | Description |
|---|---|
SweepReport
|
What was deleted, or with |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
EphemeralJob¶
EphemeralJob ¶
EphemeralJob(
lakeflow: Lakeflow,
job_key: str,
settings: JobSettings,
params: Mapping[str, str] | None = None,
capture_task_values: Mapping[str, Sequence[str]]
| None = None,
stubs: Collection[str] = (),
*,
extra_dependencies: Sequence[str] = (),
pipeline_copies: Sequence[EphemeralPipeline] = (),
teardown_at: TeardownAt = "run",
query_files: Mapping[str, str] | None = None,
)
Bases: EphemeralResource
A throwaway copy of a bundle job.
The job is created on entering the with block, or by the first run() or start() when used without with.
It is deleted on leaving the block, or at the end of the test that made it, unless keep is set or the test
failed and keep_failed is on. Runs that are still active then are cancelled first. With
teardown_at="close", the teardown task then runs alone, before the job is deleted or kept.
Attributes:
| Name | Type | Description |
|---|---|---|
lakeflow |
The |
|
job_key |
The bundle resource key of the job it copies. |
|
settings |
The settings the job is created with. |
|
params |
Job parameters for every run. |
|
capture_task_values |
The task value keys captured by probes, by task key. |
|
stubs |
Keys of the stub tasks. |
|
extra_dependencies |
The test-only dependencies passed to |
|
pipeline_copies |
The pipeline copies that |
|
teardown_at |
When the teardown task runs. |
|
job_id |
int | None
|
The job's id, once created. |
runs |
list[JobRun]
|
The outcome of each finished run, in order. The teardown run that closing the job starts is not one. |
query_files |
The SQL text of each saved query that |
|
teardown_run |
JobRun | None
|
The run of the teardown task alone that closing the job started, with |
create ¶
create() -> None
Create the job if it does not exist yet, after the pipeline copies its pipeline tasks point at.
Emits a UserWarning naming the notebook tasks that extra_dependencies does not reach, checked after
modify_settings, before jobs.create. modify_settings sees the deployed pipelines' ids, which are replaced
by the copies' ids after it. With pipelines="copy", the pipelines to copy are chosen after it too.
Raises:
| Type | Description |
|---|---|
LakeflowError
|
If the job has been closed, |
run ¶
run(
params: Mapping[str, str] | None = None,
only: Sequence[str] | None = None,
*,
timeout: timedelta | None = None,
stop_after: timedelta | None = None,
performance_target: PerformanceTarget
| str
| None = None,
queue: bool | None = None,
full_refresh: bool | None = None,
full_refresh_selection: Sequence[str] | None = None,
refresh_selection: Sequence[str] | None = None,
refresh_flow_selection: Sequence[str] | None = None,
reset_checkpoint_selection: Sequence[str] | None = None,
replay: JobRun | None = None,
stream: bool | None = None,
dbt_commands: Sequence[str] | None = None,
) -> JobRun
Run the job and wait for it to finish, creating it first if needed.
Every call sends a fresh idempotency token with the run request, so a request the SDK retries cannot
start a second run. It is start(params, only, timeout=timeout, ...).wait(stop_after=stop_after).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
Mapping[str, str] | None
|
Job parameters for this run only, merged over the job's params. |
None
|
only
|
Sequence[str] | None
|
Task keys to run. |
None
|
timeout
|
timedelta | None
|
How long to wait. Defaults to |
None
|
stop_after
|
timedelta | None
|
How long the run may go on before it is cancelled, for a job that does not end on its own,
such as a streaming job. The run is then polled until it has ended and returned as a |
None
|
performance_target
|
PerformanceTarget | str | None
|
The performance target of this run only, such as |
None
|
queue
|
bool | None
|
Whether this run may queue behind other runs. Defaults to |
None
|
full_refresh
|
bool | None
|
Whether the job's pipeline tasks run a full refresh in this run. Defaults to what each
|
None
|
full_refresh_selection
|
Sequence[str] | None
|
Tables that the job's pipeline tasks fully refresh in this run. Needs databricks-sdk 0.110.0 or later. |
None
|
refresh_selection
|
Sequence[str] | None
|
Tables that the job's pipeline tasks refresh in this run. It applies to every pipeline task in the run. Needs databricks-sdk 0.110.0 or later. |
None
|
refresh_flow_selection
|
Sequence[str] | None
|
Flows that the job's pipeline tasks refresh in this run, by flow name. Needs databricks-sdk 0.110.0 or later. |
None
|
reset_checkpoint_selection
|
Sequence[str] | None
|
Streaming flows whose checkpoints the job's pipeline tasks reset in this run, so that they process their source again from the start. Needs databricks-sdk 0.110.0 or later. |
None
|
replay
|
JobRun | None
|
A run of the same job whose captured task values stub the tasks that |
None
|
stream
|
bool | None
|
Whether to print the start of the run, each task state change and the end of the run to the
terminal while waiting, as |
None
|
dbt_commands
|
Sequence[str] | None
|
The commands of every dbt task in this run, such as |
None
|
Returns:
| Type | Description |
|---|---|
JobRun
|
The run's outcome. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
LakeflowError
|
If the job has been closed, a parameter is not declared, |
LakeflowTimeout
|
If the run did not finish in time. The run is cancelled first. |
start ¶
start(
params: Mapping[str, str] | None = None,
only: Sequence[str] | None = None,
*,
timeout: timedelta | None = None,
performance_target: PerformanceTarget
| str
| None = None,
queue: bool | None = None,
full_refresh: bool | None = None,
full_refresh_selection: Sequence[str] | None = None,
refresh_selection: Sequence[str] | None = None,
refresh_flow_selection: Sequence[str] | None = None,
reset_checkpoint_selection: Sequence[str] | None = None,
dbt_commands: Sequence[str] | None = None,
) -> RunHandle
Start a run of the job without waiting for it, creating the job first if needed.
The run is cancelled when the job closes, unless RunHandle.wait() has returned by then. Its page is
recorded in the test's report straight away, so a run that is never waited for still appears there, and
with --lakeflow-report-dir the cancelled run is listed in report.json. The job allows one run at a time,
so start runs of different jobs to run them side by side.
Under --lakeflow-max-concurrent-runs or Lakeflow's max_concurrent_runs, when the process already has
that many runs active, it waits for one of them to end before starting the run, for at most timeout. While
it waits it polls those runs, so a run that has ended frees its slot even if nobody has waited for it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
Mapping[str, str] | None
|
Job parameters for this run only, as for |
None
|
only
|
Sequence[str] | None
|
Task keys to run, as for |
None
|
timeout
|
timedelta | None
|
How long |
None
|
performance_target
|
PerformanceTarget | str | None
|
The performance target of this run only, as for |
None
|
queue
|
bool | None
|
Whether this run may queue behind other runs, as for |
None
|
full_refresh
|
bool | None
|
Whether the job's pipeline tasks run a full refresh in this run, as for |
None
|
full_refresh_selection
|
Sequence[str] | None
|
Tables that the job's pipeline tasks fully refresh in this run, as for |
None
|
refresh_selection
|
Sequence[str] | None
|
Tables that the job's pipeline tasks refresh in this run, as for |
None
|
refresh_flow_selection
|
Sequence[str] | None
|
Flows that the job's pipeline tasks refresh in this run, as for |
None
|
reset_checkpoint_selection
|
Sequence[str] | None
|
Streaming flows whose checkpoints the job's pipeline tasks reset in this run,
as for |
None
|
dbt_commands
|
Sequence[str] | None
|
The commands of every dbt task in this run, as for |
None
|
Returns:
| Type | Description |
|---|---|
RunHandle
|
A handle to wait for the run or cancel it. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
LakeflowError
|
If the job has been closed, a parameter is not declared, |
debug_notebook ¶
debug_notebook(
task_key: str, run: JobRun | None = None
) -> DebugNotebook
Write a notebook that reproduces a notebook task of a run, to debug it interactively.
The notebook sets the task's resolved parameters as widgets and runs the task's notebook with %run. It is
written to <helpers_path>/debug/<job_key>__<task_key>__<run_id>, replacing any notebook of the same run,
and its URL is recorded in the test's report as lakeflow_debug_notebook. It replays the parameters only:
a notebook that reads upstream task values needs debugValue= in dbutils.jobs.taskValues.get().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_key
|
str
|
The notebook task to reproduce. |
required |
run
|
JobRun | None
|
The run whose parameters to replay. Defaults to the job's last run. |
None
|
Returns:
| Type | Description |
|---|---|
DebugNotebook
|
The notebook written. |
Raises:
| Type | Description |
|---|---|
LakeflowError
|
If the job has no task |
KeyError
|
If the task was not part of the run, as |
close ¶
close(failed: bool = False) -> None
Cancel active runs, then delete the job unless the keep rules say to keep it, then its pipeline copies.
With teardown_at="close", the teardown task runs alone between the two, with the job's params and no
run-level ones, and is waited for for Lakeflow's timeout, unless the job never ran or keep or
--lakeflow-keep keeps it. keep_failed does not skip it: a job kept because its test failed is cleaned
up too, and its teardown run is among the kept runs. A teardown run that fails or times out only logs a
warning with its page, and the job is deleted or kept as usual.
With --lakeflow-report-dir, each cancelled run is polled until it has ended, for at most 60 seconds, and
listed in the report.json of the test that is running, whose report is still to be written: for a job that a
module- or session-scoped fixture closes, the test being torn down. Outside a test the run is not polled.
The job is deleted even when the polling is interrupted. The pipeline copies go after the job, with the same
keep rules, so a kept job never points at a deleted pipeline, and they go even when deleting the job fails.
When the job was never created, no job points at them, so keep_failed does not keep them. The SQL files of
query_files stay with a kept job and are deleted otherwise. Unlike the pipeline copies, they are deleted when
the job was never created even when keep or --lakeflow-keep is on. A failure to delete one only logs a
warning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failed
|
bool
|
Whether the test failed, which keeps the job when |
False
|
EphemeralPipeline¶
EphemeralPipeline ¶
EphemeralPipeline(
lakeflow: Lakeflow,
pipeline_key: str,
source_id: str,
create_kwargs: Mapping[str, Any],
schema: str,
)
Bases: EphemeralResource
A throwaway copy of a deployed pipeline, publishing to a schema that the test chose.
The copy is created on entering the with block, or by the first run() when used without with. It is
deleted with its tables on leaving the block, or at the end of the test that made it, unless keep is set or the
test failed and keep_failed is on. An update that is still running then is stopped first. The copies that
pipelines="copy" makes for a job are created and closed by that job instead.
Attributes:
| Name | Type | Description |
|---|---|---|
lakeflow |
The |
|
pipeline_key |
The bundle resource key of the pipeline it copies, or that pipeline's id when the bundle does not define it. |
|
source_id |
The id of the pipeline it copies. |
|
create_kwargs |
The arguments the copy is created with, as |
|
schema |
The full name of the schema the copy publishes to. |
|
pipeline_id |
str | None
|
The copy's id, once created. |
updates |
list[PipelineUpdate]
|
The outcome of each update that |
create ¶
create() -> None
Create the copy if it does not exist yet.
Raises:
| Type | Description |
|---|---|
LakeflowError
|
If the copy has been closed. Errors from |
run ¶
run(
*,
full_refresh: bool | None = None,
full_refresh_selection: Sequence[str] | None = None,
refresh_selection: Sequence[str] | None = None,
timeout: timedelta | None = None,
) -> PipelineUpdate
Run an update of the copy and wait for it to end, creating the copy first if needed.
A failed update is returned, not raised: check its state, and read what went wrong with
events(level="ERROR"). Each change of the update's state is logged and shown in the lakeflow report
section of the test.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
full_refresh
|
bool | None
|
Whether the update refreshes every table from scratch. |
None
|
full_refresh_selection
|
Sequence[str] | None
|
Tables that the update refreshes from scratch. |
None
|
refresh_selection
|
Sequence[str] | None
|
Tables that the update refreshes. |
None
|
timeout
|
timedelta | None
|
How long to wait. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
PipelineUpdate
|
The update, which is also appended to |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a selection is a string rather than a list of names. |
LakeflowError
|
If the copy has been closed. |
LakeflowTimeout
|
If the update did not end in time. It is stopped first. |
close ¶
close(failed: bool = False) -> None
Stop an update that is still running, then delete the copy with its tables unless the keep rules say not to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failed
|
bool
|
Whether the test failed, which keeps the copy when |
False
|
RunHandle¶
RunHandle ¶
RunHandle(
job: EphemeralJob,
run_id: int,
item: Item,
first: Run,
timeout: timedelta | None = None,
*,
stream: bool | None = None,
performance_target: PerformanceTarget | None = None,
)
A run started by EphemeralJob.start(), to wait for or cancel later.
Attributes:
| Name | Type | Description |
|---|---|---|
job |
The job the run belongs to. |
|
run_id |
The run's id. |
url
property
¶
url: str | None
The run's page in the workspace, or None if the workspace has not reported it yet.
wait ¶
wait(
timeout: timedelta | None = None,
*,
stop_after: timedelta | None = None,
) -> JobRun
Wait for the run to finish.
Waiting again returns the same JobRun, and run_finished is called only the first time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout
|
timedelta | None
|
How long to wait from this call. Defaults to the |
None
|
stop_after
|
timedelta | None
|
How long the run may go on before it is cancelled, counted from |
None
|
Returns:
| Type | Description |
|---|---|
JobRun
|
The run's outcome, which is also appended to the job's |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
LakeflowError
|
If the job closed before the run finished, which cancelled the run, or |
LakeflowTimeout
|
If the run did not finish in time. The run is cancelled first. |
cancel ¶
cancel() -> None
Cancel the run. It ends CANCELED shortly after, which a later wait() returns.
JobRun¶
JobRun
dataclass
¶
JobRun(
job_key: str,
job_id: int,
run_id: int,
run_url: str,
result_state: str | None,
termination_code: str | None,
termination_message: str | None,
duration: timedelta,
tasks: dict[str, TaskRun],
injected_tasks: dict[str, TaskRun],
skipped_tasks: dict[str, TaskRun] = dict(),
disabled_tasks: dict[str, TaskRun] = dict(),
parameters: dict[str, str] = dict(),
timing: Timing = Timing(),
effective_performance_target: str | None = None,
trigger_type: str | None = None,
)
The outcome of one run of an ephemeral job, or of the child run that a run-job task triggered.
Attributes:
| Name | Type | Description |
|---|---|---|
job_key |
str
|
The bundle resource key of the job. For a child run, the child job's key when the job is in the bundle, otherwise its job id as a string. |
job_id |
int
|
The ephemeral job's id. For a child run, the id of the deployed child job. |
run_id |
int
|
The run's id. |
run_url |
str
|
The run's page in the workspace. |
result_state |
str | None
|
The parent run's result state. Not a verdict: a run whose probe ran after a failed task
ends |
termination_code |
str | None
|
The parent run's termination code. |
termination_message |
str | None
|
The parent run's termination message. |
duration |
timedelta
|
The time from start to end of the parent run. |
tasks |
dict[str, TaskRun]
|
The user's tasks that were part of the run, by task key. |
injected_tasks |
dict[str, TaskRun]
|
The stub, probe, setup and teardown tasks added by the plugin, by task key. |
skipped_tasks |
dict[str, TaskRun]
|
Tasks left out by |
disabled_tasks |
dict[str, TaskRun]
|
Tasks disabled in the job, in the bundle or with |
parameters |
dict[str, str]
|
The run's job parameters by name: the value passed for the run, or the default when none was. Parameters the plugin injects are left out. |
timing |
Timing
|
The queue, setup, execution and cleanup durations of the parent run. Zero where the platform reported none; a run with several tasks reports its time on the tasks instead. |
effective_performance_target |
str | None
|
The serverless performance mode the run used, |
trigger_type |
str | None
|
What started the run, as the Jobs API reports it: |
succeeded
property
¶
succeeded: bool
Whether every task in tasks ended SUCCESS.
Injected and skipped tasks do not count, nor do tasks EXCLUDED because their run_if or if/else
condition was not met.
timed_out
property
¶
timed_out: bool
Whether the parent run ended TIMEDOUT or any task in tasks timed out.
cancelled
property
¶
cancelled: bool
Whether the parent run ended CANCELED, as a run stopped by stop_after does. Such a run also failed.
executed_tasks
property
¶
executed_tasks: list[str]
The sorted keys of the tasks in tasks whose ran is true.
setup
property
¶
setup: TaskRun | None
The task that ran the job's setup= function, or None when the job has none.
When it fails, the user's tasks end UPSTREAM_FAILED, so succeeded is false, and repr() names the setup
failure first.
teardown
property
¶
teardown: TaskRun | None
The task that ran the job's teardown= function, or None when the job has none or the run left it out.
A run leaves it out when the job was made with teardown_at="close": the task then ends DISABLED and runs
alone when the job closes, in EphemeralJob.teardown_run. A failed teardown does not change succeeded; the
plugin logs a warning instead. Assert run.teardown.succeeded to fail the test on it.
task ¶
task(key: str) -> TaskRun
Get one of the user's tasks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The task key. |
required |
Returns:
| Type | Description |
|---|---|
TaskRun
|
The task's outcome. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the task was not part of the run. The message lists the available keys and says whether
the task was disabled in the job or skipped by |
branch_taken ¶
branch_taken(key: str) -> bool
Get the outcome of an if/else condition task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The condition task's key. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
The task's |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the task was not part of the run. |
LakeflowError
|
If the task is not a condition task, or the platform reported no outcome for it. |
raise_for_failure ¶
raise_for_failure() -> JobRun
Raise if the run did not succeed.
Returns:
| Type | Description |
|---|---|
JobRun
|
The run itself, so |
Raises:
| Type | Description |
|---|---|
LakeflowRunFailed
|
If |
as_dict ¶
as_dict() -> dict[str, Any]
Get the run as a dict that json.dumps accepts, as --lakeflow-report-dir writes it to report.json.
Every field of the run and of each TaskRun is kept, including attempts and a nested child_run, with these
changes: duration becomes duration_seconds and each timing a dict of queue_seconds, setup_seconds,
execution_seconds and cleanup_seconds; error is a dict of type, message, trace, root_cause and
code, or None; task_values is a plain dict and missing_task_value_reasons holds the reason for each of
missing_task_values; the outputs of SQL, alert, dbt, run-job, dashboard and clean room tasks are the dicts of
the Jobs API, except that a dbt output leaves out artifacts_headers; dbt is a dict of artifacts_dir,
results (each a dict of the DbtResult fields, by unique id), failed_models and all_passed, leaving out
run_results and manifest, or None; pipeline_update is a dict of
pipeline_id, update_id, state, cause and full_refresh, or None; iterations is a list of tasks
serialised the same way, and for_each_stats a dict of its fields, with errors a list of dicts, or None.
The run also gets succeeded.
logs and the exported notebook are left out, because logs can reach 5 MB per task. Instead logs_file and
notebook_file name where --lakeflow-report-dir saves them, relative to the test's report directory:
<run_id>/<task_key>.log and <run_id>/<task_key>.html, with .attempt-<n> before the suffix for an attempt
that was retried and .iteration-<n>, counting from 0, for an iteration of a for-each task. Each is None
when the task has no logs or no exported notebook.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The run as a JSON-serialisable dict. |
TaskRun¶
TaskRun
dataclass
¶
TaskRun(
task_key: str,
run_id: int,
result_state: str | None,
termination_code: str | None,
termination_message: str | None,
run_url: str | None,
duration: timedelta,
output: str | None = None,
output_truncated: bool = False,
logs: str = "",
logs_truncated: bool = False,
error: TaskError | None = None,
task_values: TaskValues = TaskValues(),
missing_task_values: list[str] = list(),
attempt: int = 0,
parameters: dict[str, str] | list[str] | None = None,
attempts: list[TaskRun] = list(),
timing: Timing = Timing(),
effective_performance_target: str | None = None,
condition_outcome: bool | None = None,
sql_output: SqlOutput | None = None,
alert_output: AlertTaskOutput | None = None,
dbt_output: DbtOutput | None = None,
dbt: DbtArtifacts | None = None,
run_job_output: RunJobOutput | None = None,
child_run_id: int | None = None,
child_run: JobRun | None = None,
dashboard_output: DashboardTaskOutput | None = None,
clean_rooms_notebook_output: CleanRoomsNotebookTaskCleanRoomsNotebookTaskOutput
| None = None,
notebook: NotebookView | None = None,
sql_result: SqlResult | None = None,
pipeline_update: PipelineUpdate | None = None,
iterations: list[TaskRun] = list(),
for_each_stats: ForEachStats | None = None,
)
The outcome of one task in a job run.
When the platform retried the task, this describes the last attempt and attempts holds every attempt.
Attributes:
| Name | Type | Description |
|---|---|---|
task_key |
str
|
The task's key. |
run_id |
int
|
The task run's id. |
result_state |
str | None
|
The task's result state, such as |
termination_code |
str | None
|
The termination code, such as |
termination_message |
str | None
|
The termination message. |
run_url |
str | None
|
The task run's page in the workspace. |
duration |
timedelta
|
The time from start to end. |
output |
str | None
|
The value the notebook passed to |
output_truncated |
bool
|
Whether |
logs |
str
|
stdout and stderr of a Python script, wheel or JAR task. Empty for notebook tasks, whose printed text
is in |
logs_truncated |
bool
|
Whether |
error |
TaskError | None
|
The task's error, or |
task_values |
TaskValues
|
Task values captured by a probe. |
missing_task_values |
list[str]
|
Keys that were requested from the probe but not captured. |
attempt |
int
|
The attempt number, 0 for the first attempt. |
parameters |
dict[str, str] | list[str] | None
|
The task's parameters after job parameters and |
attempts |
list[TaskRun]
|
One |
timing |
Timing
|
The queue, setup, execution and cleanup durations of the task run. Zero where the platform reported none. |
effective_performance_target |
str | None
|
The serverless performance mode the task ran with, |
condition_outcome |
bool | None
|
The outcome of an if/else condition task: |
sql_output |
SqlOutput | None
|
The output of a SQL task as the platform reported it: |
alert_output |
AlertTaskOutput | None
|
The output of an alert task, with its |
dbt_output |
DbtOutput | None
|
The output of a dbt task, with |
dbt |
DbtArtifacts | None
|
The artefacts of a dbt task, downloaded from |
run_job_output |
RunJobOutput | None
|
The output of a run-job task, with the triggered run's |
child_run_id |
int | None
|
The id of the job run that a run-job task triggered, from |
child_run |
JobRun | None
|
The run that a run-job task triggered, as a |
dashboard_output |
DashboardTaskOutput | None
|
The output of a dashboard task, with its |
clean_rooms_notebook_output |
CleanRoomsNotebookTaskCleanRoomsNotebookTaskOutput | None
|
The output of a clean room notebook task, with |
notebook |
NotebookView | None
|
The rendered notebook of a notebook task, with each cell's code, output and error, read with
|
sql_result |
SqlResult | None
|
The columns and rows a SQL file task returned, read from |
pipeline_update |
PipelineUpdate | None
|
The pipeline update that a pipeline task started, found once the run finished among the
pipeline's updates by its creation time, which lies between the task's start and end. |
iterations |
list[TaskRun]
|
The iterations of a for-each task, one |
for_each_stats |
ForEachStats | None
|
The iteration counts of a for-each task, as the platform reports them, or |
timed_out
property
¶
timed_out: bool
Whether the task ended TIMEDOUT, stopped by the platform at its timeout_seconds.
ran
property
¶
ran: bool
Whether the task ran. False if it was skipped, excluded, disabled or cancelled, or has no result state.
The platform reports no result state for the tasks of a run it skipped because every task is disabled.
excluded
property
¶
excluded: bool
Whether the task ended EXCLUDED because its run_if or if/else condition was not met.
upstream_failed
property
¶
upstream_failed: bool
Whether the task ended UPSTREAM_FAILED because a task it depends on failed.
disabled
property
¶
disabled: bool
Whether the task ended DISABLED: disabled in the job, downstream of a disabled task, or left out by only.
JobRun.disabled_tasks and JobRun.skipped_tasks tell them apart.
alert_state
property
¶
alert_state: str | None
The state an alert evaluated to: TRIGGERED, OK, ERROR or UNKNOWN.
Read from alert_output for an alert task, else from sql_output.alert_output for a legacy SQL alert task.
None for any other task or when the platform reported no state. An alert task succeeds whether or not the
alert triggered, so assert on this rather than on succeeded. ERROR means the alert could not be
evaluated, for example because its query failed; the task then fails too.
output_json
property
¶
output_json: object
output parsed as JSON.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the notebook did not call |
raised ¶
raised(exc_type: type[BaseException]) -> bool
Check whether the task failed with an exception of the given class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc_type
|
type[BaseException]
|
The exception class. Only its name is compared, because the task ran in another process. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the task's error has the class name of |
DbtArtifacts¶
DbtArtifacts
dataclass
¶
DbtArtifacts(
artifacts_dir: Path,
results: dict[str, DbtResult],
run_results: dict[str, Any],
manifest: dict[str, Any] | None,
)
The artefacts a dbt task wrote, downloaded and extracted once its run finished.
The platform runs each of the task's commands in turn, so run_results.json describes the last command that
wrote one, such as dbt build after dbt deps.
Attributes:
| Name | Type | Description |
|---|---|---|
artifacts_dir |
Path
|
Where the tarball was extracted, in a temporary directory removed at the end of the pytest
session, unless |
results |
dict[str, DbtResult]
|
One |
run_results |
dict[str, Any]
|
|
manifest |
dict[str, Any] | None
|
|
DbtResult¶
DbtResult
dataclass
¶
DbtResult(
unique_id: str,
status: str,
message: str | None = None,
failures: int | None = None,
execution_time: float = 0.0,
)
The outcome of one dbt node, a model, test, seed or snapshot, as run_results.json reports it.
Attributes:
| Name | Type | Description |
|---|---|---|
unique_id |
str
|
The node's unique id, such as |
status |
str
|
What dbt reported: |
message |
str | None
|
dbt's message for the node, such as the database error, or |
failures |
int | None
|
The number of failing rows of a test, or |
execution_time |
float
|
How long the node took, in seconds. |
ForEachStats¶
ForEachStats
dataclass
¶
ForEachStats(
total_iterations: int,
succeeded_iterations: int,
failed_iterations: int,
errors: list[ForEachError] = list(),
)
The iteration counts of a for-each task, as the platform reports them on the task run.
Each iteration counts once, however often it was retried.
Attributes:
| Name | Type | Description |
|---|---|---|
total_iterations |
int
|
How many iterations the task had, one per input. |
succeeded_iterations |
int
|
How many of them succeeded. |
failed_iterations |
int
|
How many of them failed. |
errors |
list[ForEachError]
|
The errors they failed with, each with the number of iterations that failed with it. |
from_stats
classmethod
¶
from_stats(stats: ForEachStats) -> ForEachStats
Read the counts of a RunForEachTask.stats.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stats
|
ForEachStats
|
The stats from |
required |
Returns:
| Type | Description |
|---|---|
ForEachStats
|
The counts, with 0 for each one the platform does not report. |
ForEachError¶
ForEachError
dataclass
¶
ForEachError(
message: str,
count: int,
termination_category: str | None = None,
)
One error that iterations of a for-each task failed with, as the platform counts it.
Attributes:
| Name | Type | Description |
|---|---|---|
message |
str
|
The error message. The platform reports the same generic message, such as |
count |
int
|
How many iterations failed with it. |
termination_category |
str | None
|
The platform's category of the error, such as |
ALL_RULES and DEFAULT_RULES¶
The names of the rules that Lakeflow.check(key, rules=...) applies on top of the four it always applies, as frozensets: ALL_RULES is wheel, library, dash, trigger and equal_to, and DEFAULT_RULES, what check applies when rules is None, is every rule but equal_to. See Check every job's wiring.
Stub¶
Stub
dataclass
¶
Stub(
values: Mapping[str, object] = dict(),
outputs: Mapping[str, object] = dict(),
)
What a stub task stands in for: the task values it sets and the output references it answers.
A plain mapping in upstream_task_values is the same as Stub(values=mapping).
Attributes:
| Name | Type | Description |
|---|---|---|
values |
Mapping[str, object]
|
The task values the stub sets, by key, as a plain mapping gives them. |
outputs |
Mapping[str, object]
|
Literals for the |
TaskValues¶
TaskValues ¶
TaskValues(
values: Mapping[str, object] | None = None,
reasons: Mapping[str, str] | None = None,
)
Bases: dict[str, object]
Task values captured by a probe task.
A dict whose missing keys raise a KeyError that says why the value is missing: the task never set it, the
task did not run, or the probe failed.
Attributes:
| Name | Type | Description |
|---|---|---|
reasons |
The explanation for each missing key. |
TaskError¶
TaskError
dataclass
¶
TaskError(type: str | None, message: str, trace: str)
An error reported by a task run.
Attributes:
| Name | Type | Description |
|---|---|---|
type |
str | None
|
The exception class name as Python printed it, possibly dotted, such as
|
message |
str
|
The exception message. |
trace |
str
|
The error trace with ANSI colour codes removed. |
root_cause
property
¶
root_cause: str | None
The first thing that went wrong, read from trace.
A Python chained traceback, from raise ... from e or an exception raised while handling another, prints
the innermost exception first, so only the part of trace before the first chain marker is read. In that
part, the text after the last Caused by: line wins, as in a Py4J or Spark trace. Otherwise, when the
trace is chained, it is the innermost exception as Name: message, such as
ZeroDivisionError: division by zero, while type and message still describe the outer exception.
None when the trace has neither a Caused by: line nor a chain.
code
property
¶
code: str | None
The bracketed error class, such as TABLE_OR_VIEW_NOT_FOUND, at the start of message or root_cause.
None when neither starts with one. Lowercase tags such as [my_tag] are not error classes.
from_output
classmethod
¶
from_output(
error: str | None, trace: str | None
) -> TaskError | None
Parse the error fields of a task's get_run_output response.
The error field is preferred, because error_trace is ANSI-coloured IPython output. The last
Name: message line of the trace is the fallback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
error
|
str | None
|
The |
required |
trace
|
str | None
|
The |
required |
Returns:
| Type | Description |
|---|---|
TaskError | None
|
The parsed error, or |
Timing¶
Timing
dataclass
¶
Timing(
queue: timedelta = timedelta(0),
setup: timedelta = timedelta(0),
execution: timedelta = timedelta(0),
cleanup: timedelta = timedelta(0),
)
Where the time of a run or task run went, as runs/get reports it.
Attributes:
| Name | Type | Description |
|---|---|---|
queue |
timedelta
|
Time spent waiting in the queue. |
setup |
timedelta
|
Time spent setting up compute and the environment. |
execution |
timedelta
|
Time spent running the code. |
cleanup |
timedelta
|
Time spent cleaning up afterwards. |
total
property
¶
total: timedelta
The sum of queue, setup, execution and cleanup.
It differs from the duration of JobRun and TaskRun, which is wall clock from start to end, for example
when a run waited in the queue.
from_run
classmethod
¶
from_run(run: Run | RunTask) -> Timing
Read the timing of a run or task run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run
|
Run | RunTask
|
The run or task run from |
required |
Returns:
| Type | Description |
|---|---|
Timing
|
The timing, with |
SqlResult¶
SqlResult
dataclass
¶
SqlResult(
task_key: str,
columns: list[str],
types: list[str],
rows: list[dict[str, str | None]],
truncated: bool = False,
warehouse_id: str | None = None,
query_text: str | None = None,
)
The rows a SQL file task returned, as runs/get-output reports them under sql_output.file_output.
The Jobs API reference does not document file_output and databricks-sdk does not model it, so the plugin reads
the raw response. The platform keeps at most 1,000 rows, for 7 days.
Attributes:
| Name | Type | Description |
|---|---|---|
task_key |
str
|
The task's key. |
columns |
list[str]
|
The column names in order, such as |
types |
list[str]
|
The platform's type name of each column, such as |
rows |
list[dict[str, str | None]]
|
One dict per row, by column name. Values are strings as the platform reports them, such as |
truncated |
bool
|
Whether the platform cut the rows, which it does after 1,000. |
warehouse_id |
str | None
|
The SQL warehouse the task ran on. |
query_text |
str | None
|
The SQL file as the task ran it. Named parameter markers such as |
first_row
property
¶
first_row: dict[str, str | None]
from_output
classmethod
¶
from_output(
task_key: str, output: Mapping[str, Any]
) -> SqlResult | None
Read the query result of a SQL file task from its raw runs/get-output response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_key
|
str
|
The task's key. |
required |
output
|
Mapping[str, Any]
|
The response as JSON. |
required |
Returns:
| Type | Description |
|---|---|
SqlResult | None
|
The result, or |
SqlResult | None
|
query, alert or dashboard task. |
PipelineUpdate¶
PipelineUpdate
dataclass
¶
PipelineUpdate(
pipeline_id: str,
update_id: str,
state: str | None,
cause: str | None,
full_refresh: bool,
_ws: WorkspaceClient,
_since: int,
)
An update of a pipeline: the one a pipeline task started, or one that EphemeralPipeline.run() started.
The Jobs API does not say which update a pipeline task started, so the plugin lists the pipeline's updates once
the run finished and takes the one created while the task ran, preferring one whose cause is JOB_TASK. The
pipeline is the one the task points at: the deployed one, or a copy with pipelines="copy".
Attributes:
| Name | Type | Description |
|---|---|---|
pipeline_id |
str
|
The pipeline's id. |
update_id |
str
|
The update's id. |
state |
str | None
|
The update's state, such as |
cause |
str | None
|
What started the update: |
full_refresh |
bool
|
Whether the update was a full refresh of every table. |
from_info
classmethod
¶
from_info(
ws: WorkspaceClient,
info: UpdateInfo,
*,
since: int | None = None,
) -> PipelineUpdate
Build the update from what pipelines.get_update or pipelines.list_updates reports.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ws
|
WorkspaceClient
|
The workspace client, which |
required |
info
|
UpdateInfo
|
The update as the Pipelines API reports it. |
required |
since
|
int | None
|
The time in epoch milliseconds before which the update logged no event, so |
None
|
Returns:
| Type | Description |
|---|---|
PipelineUpdate
|
The update. |
events ¶
events(
level: str | None = None,
) -> list[pipelines.PipelineEvent]
Read the events the update logged, newest first, with pipelines.list_pipeline_events.
The platform lists the events of every update of the pipeline, newest first, so the events of other updates are dropped and the listing stops at the first event logged before the task started.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
str | None
|
Only events of this level, such as |
None
|
Returns:
| Type | Description |
|---|---|
list[PipelineEvent]
|
The events, each a |
list[PipelineEvent]
|
|
NotebookView¶
NotebookView
dataclass
¶
NotebookView(html: str, cells: list[NotebookCell] = list())
A notebook task run as jobs.export_run renders it, with every cell's code and output.
The output comes from the rendered notebook, so it is complete only once the task has terminated.
Attributes:
| Name | Type | Description |
|---|---|---|
html |
str
|
The exported HTML, unchanged. |
cells |
list[NotebookCell]
|
The notebook's cells in order. Empty when the export could not be read. |
stdout
property
¶
stdout: str
What every cell wrote to standard output, in order, which is what print() produced.
failed_cell
property
¶
failed_cell: NotebookCell | None
The first cell that raised an exception, or None.
save ¶
save(path: str | Path) -> Path
Write the exported HTML to a file, which opens in a browser like the run page.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The file to write. Missing parent directories are created. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The path written. |
NotebookCell¶
NotebookCell
dataclass
¶
NotebookCell(
index: int,
code: str,
output: str = "",
output_html: str = "",
error: str | None = None,
stdout: str = "",
)
One cell of a notebook exported from a task run.
Attributes:
| Name | Type | Description |
|---|---|---|
index |
int
|
The cell's position in |
code |
str
|
The cell's source. |
output |
str
|
The cell's text output, such as what it printed, one result per line, with HTML tags and ANSI colour codes removed and HTML entities unescaped. Empty when the cell had no output. |
output_html |
str
|
The cell's results as exported, unchanged: HTML for an HTML result, otherwise the text the notebook wrote. |
error |
str | None
|
The exception the cell raised, as |
stdout |
str
|
What the cell wrote to standard output, such as what it printed, with ANSI colour codes removed.
Unlike |
DebugNotebook¶
DebugNotebook
dataclass
¶
DebugNotebook(
task_key: str, run_id: int, path: str, url: str
)
A notebook in the workspace that reproduces a notebook task of a run, written by EphemeralJob.debug_notebook().
It sets the task's resolved parameters as widgets and runs the task's notebook with %run.
Attributes:
| Name | Type | Description |
|---|---|---|
task_key |
str
|
The task's key. |
run_id |
int
|
The id of the job run whose parameters it replays. |
path |
str
|
The notebook's workspace path. |
url |
str
|
The notebook's page in the workspace. |
SweepReport¶
SweepReport
dataclass
¶
SweepReport(
dry_run: bool,
jobs: tuple[int, ...] = (),
pipelines: tuple[str, ...] = (),
schemas: tuple[str, ...] = (),
notebooks: tuple[str, ...] = (),
errors: tuple[str, ...] = (),
)
What a sweep deleted, or with dry_run would have deleted, as Lakeflow.sweep() returns it.
Attributes:
| Name | Type | Description |
|---|---|---|
dry_run |
bool
|
Whether the sweep only listed what it would delete. |
jobs |
tuple[int, ...]
|
The ids of the jobs. |
pipelines |
tuple[str, ...]
|
The ids of the pipelines. |
schemas |
tuple[str, ...]
|
The full names of the schemas. |
notebooks |
tuple[str, ...]
|
The workspace paths of the notebooks and of the inlined saved query files. |
errors |
tuple[str, ...]
|
What could not be listed or deleted. |
as_dict ¶
as_dict() -> dict[str, Any]
Get the report as --lakeflow-sweep-report writes it, with a version key.
Errors¶
Two kinds of error leave the plugin. A ValueError means an argument is wrong on its own: a choice outside the ones listed, a setup= that is neither a function, a list nor a .py path, a stub value that is not JSON-serialisable, a stop_after longer than its timeout. A LakeflowError, or one of its subclasses, means the bundle, the job or the workspace did not fit: a task key the job does not have, a reference the copy cannot resolve, a run that did not finish, a deploy that failed. Catch LakeflowError for the second kind; the first kind is a mistake in the test to fix.
LakeflowError ¶
Bases: Exception
Base class for errors raised by pytest-databricks-lakeflow.
LakeflowBundleError ¶
Bases: LakeflowError
A Databricks CLI bundle command failed, or the bundle cannot supply a job template.
LakeflowTimeout ¶
Bases: LakeflowError
A job run or pipeline update did not finish within its timeout. The run was cancelled, the update stopped.
LakeflowRunFailed ¶
LakeflowRunFailed(message: str, run: JobRun)
Bases: LakeflowError
A job run did not succeed. Raised by JobRun.raise_for_failure().
Attributes:
| Name | Type | Description |
|---|---|---|
run |
The run that failed. |