Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions experimental/python/databricks/bundles/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def _apply_mutators(
("resources", "jobs", resource_name), location
)
resources.jobs[resource_name] = new_job
job = new_job
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the comment above, it is not possible to detect in-place mutations, but this doesn't do anything to prevent them. Is that correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I will add tests for it. If the object is mutated but not copied, a mutation will have an effect, but we aren't going to record LOC changes. We can potentially detect mutation by comparing it to deep copy or hashing objects, but it will introduce an additional overhead.

except Exception as exc:
mutator_name = mutator.function.__name__

Expand Down
66 changes: 66 additions & 0 deletions experimental/python/databricks_tests/test_build.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import sys
from dataclasses import replace
from io import StringIO
from pathlib import Path

from databricks.bundles.build import (
_append_resources,
_apply_mutators,
_Args,
_Conf,
_load_object,
Expand All @@ -21,6 +23,7 @@
Location,
Resources,
Severity,
job_mutator,
)
from databricks.bundles.jobs import Job

Expand Down Expand Up @@ -299,6 +302,69 @@ def test_conf_from_dict():
)


def test_mutators():
bundle = Bundle(target="default")
resources = Resources()
resources.add_job("job_0", Job(tags={"tag": "value"}))

@job_mutator
def add_first_tag(bundle: Bundle, job: Job) -> Job:
tags = bundle.resolve_variable(job.tags)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call resolve_variable here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because of types, job.tags can potentially refer to a variable, while it isn't possible in practice.


return replace(job, tags={"first": "tag", **tags})

@job_mutator
def add_second_tag(bundle: Bundle, job: Job) -> Job:
tags = bundle.resolve_variable(job.tags)

return replace(job, tags={"second": "tag", **tags})

new_resources, diagnostics = _apply_mutators(
bundle=bundle,
resources=resources,
mutator_functions=[add_first_tag, add_second_tag],
)

# add_second_tag is the last mutator that has modified a job
expected_location = Location.from_callable(add_second_tag.function)

assert not diagnostics.has_error()
assert new_resources._locations[("resources", "jobs", "job_0")] == expected_location
assert new_resources.jobs["job_0"].tags == {
"first": "tag",
"second": "tag",
"tag": "value",
}


def test_mutators_unmodified():
bundle = Bundle(target="default")

resources = Resources()
resources.add_job("job_0", Job(description="description"))

@job_mutator
def mutator_1(job: Job) -> Job:
return replace(job, description="updated description")

@job_mutator
def mutator_2(job: Job) -> Job:
return job

new_resources, diagnostics = _apply_mutators(
bundle=bundle,
resources=resources,
mutator_functions=[mutator_1, mutator_2],
)

# despite mutator_2 being called last, it doesn't change the job, and we should use location of mutator_1
expected_location = Location.from_callable(mutator_1.function)

assert not diagnostics.has_error()
assert new_resources._locations[("resources", "jobs", "job_0")] == expected_location
assert new_resources.jobs["job_0"].description == "updated description"


def test_load_resources():
bundle = Bundle(target="default")

Expand Down
Loading