Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .codegen.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"tagging.py",
"tagging.py.lock"
],
"allow_from_source": [
"allow_from_packages": [
"**/*.{md,py,rst,png,svg,gif,tmpl,ps1}",
"**/py.typed",
".codegen/{_last_sha,_openapi_sha}",
Expand Down
2 changes: 1 addition & 1 deletion .codegen/_last_sha
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8758d3b71cae7ab16f4bfb80629e5c156885ccbb
22daa3292725a414f9527c8d74409750887c1235
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Version changelog

## Release v0.140.0 (2026-09-16)

### API Changes
* Add `group_name` field for `databricks.sdk.service.pipelines.RunAs`.

## Release v0.139.0 (2026-09-13)

### API Changes
Expand Down
3 changes: 1 addition & 2 deletions databricks/sdk/service/aifunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,8 +710,7 @@ def ai_extract(self, content: any, schema: any, *, options: Optional[AiExtractOp
def ai_parse_document(
self, content: str, *, options: Optional[AiParseDocumentOptions] = None
) -> AiParseDocumentResponse:
"""Parse structured content from unstructured documents. For REST API requests, the default rate limit is
120 pages per minute per workspace. Contact your Databricks account team to request a higher limit.
"""Parse structured content from unstructured documents.

:param content: str
The document to parse, given as a Unity Catalog volume path to the source file (the REST API accepts
Expand Down
3 changes: 1 addition & 2 deletions databricks/sdk/service/apps.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion databricks/sdk/service/files.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions databricks/sdk/service/jobs.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions databricks/sdk/service/ml.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion databricks/sdk/service/pipelines.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion databricks/sdk/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.139.0"
__version__ = "0.140.0"
3 changes: 1 addition & 2 deletions docs/workspace/aifunctions/ai_functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@

.. py:method:: ai_parse_document(content: str [, options: Optional[AiParseDocumentOptions]]) -> AiParseDocumentResponse

Parse structured content from unstructured documents. For REST API requests, the default rate limit is
120 pages per minute per workspace. Contact your Databricks account team to request a higher limit.
Parse structured content from unstructured documents.

:param content: str
The document to parse, given as a Unity Catalog volume path to the source file (the REST API accepts
Expand Down
2 changes: 1 addition & 1 deletion docs/workspace/files/files.rst
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
The API supports `Unity Catalog volumes
<https://docs.databricks.com/en/connect/unity-catalog/volumes.html>`__, where files and directories to
operate on are specified using their volume URI path, which follows the format
/Volumes/&lt;catalog_name&gt;/&lt;schema_name&gt;/&lt;volume_name&gt;/&lt;path_to_file&gt;.
/Volumes/<catalog_name>/<schema_name>/<volume_name>/<path_to_file>.

The Files API has two distinct endpoints, one for working with files (``/fs/files``) and another one for
working with directories (``/fs/directories``). Both endpoints use the standard HTTP methods GET, HEAD,
Expand Down
4 changes: 4 additions & 0 deletions docs/workspace/ml/feature_store.rst
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@

Update an Online Feature Store.

This update is not guaranteed to be atomic: when a request changes multiple fields, some may be
applied while others fail. On a failed response, treat the update as partially applied and retry until
it succeeds.

:param name: str
The name of the online store. This is the unique identifier for the online store.
:param online_store: :class:`OnlineStore`
Expand Down
170 changes: 170 additions & 0 deletions tests/test_compute_mixins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pytest

from databricks.sdk import WorkspaceClient
from databricks.sdk.mixins.compute import SemVer
from databricks.sdk.service import compute


@pytest.mark.parametrize(
Expand Down Expand Up @@ -40,3 +42,171 @@ def test_sorting_semver():
SemVer(1, 0, 0),
SemVer(12, 0, 0),
]


def test_select_spark_version_filters_and_selects_latest_lts_from_http(config, requests_mock):
requests_mock.get(
"http://localhost/api/2.1/clusters/spark-versions",
json={
"versions": [
{
"key": "14.3.x-scala2.12",
"name": "14.3 LTS (includes Apache Spark 3.5.0, Scala 2.12)",
},
{
"key": "15.4.x-scala2.12",
"name": "15.4 LTS (includes Apache Spark 3.5.0, Scala 2.12)",
},
{
"key": "16.0.x-scala2.12",
"name": "16.0 Beta (includes Apache Spark 4.0.0, Scala 2.12)",
},
{
"key": "15.4.x-photon-scala2.12",
"name": "15.4 LTS Photon (includes Apache Spark 3.5.0, Scala 2.12)",
},
]
},
)
workspace = WorkspaceClient(config=config)

selected = workspace.clusters.select_spark_version(long_term_support=True)

assert selected == "15.4.x-scala2.12"
assert requests_mock.last_request.method == "GET"


def test_select_node_type_filters_diskless_and_unavailable_nodes_from_http(config, requests_mock):
def node_type(
node_type_id,
*,
memory_mb,
num_cores,
local_disks,
local_disk_size_gb,
node_info=None,
):
node = {
"category": "General Purpose",
"description": node_type_id,
"instance_type_id": node_type_id,
"is_deprecated": False,
"memory_mb": memory_mb,
"node_instance_type": {
"instance_type_id": node_type_id,
"local_disk_size_gb": local_disk_size_gb,
"local_disks": local_disks,
"local_nvme_disk_size_gb": 0,
"local_nvme_disks": 0,
},
"node_type_id": node_type_id,
"num_cores": num_cores,
"num_gpus": 0,
}
if node_info is not None:
node["node_info"] = node_info
return node

requests_mock.get(
"http://localhost/api/2.1/clusters/list-node-types",
json={
"node_types": [
node_type(
"unavailable-local",
memory_mb=4096,
num_cores=2,
local_disks=1,
local_disk_size_gb=100,
node_info={"status": ["NotAvailableInRegion"]},
),
node_type(
"diskless-small",
memory_mb=4096,
num_cores=2,
local_disks=0,
local_disk_size_gb=0,
),
node_type(
"local-medium",
memory_mb=8192,
num_cores=4,
local_disks=1,
local_disk_size_gb=100,
),
node_type(
"local-large",
memory_mb=16384,
num_cores=8,
local_disks=1,
local_disk_size_gb=200,
),
]
},
)
workspace = WorkspaceClient(config=config)

selected = workspace.clusters.select_node_type(local_disk=True)

assert selected == "local-medium"
assert requests_mock.last_request.method == "GET"


def test_ensure_cluster_is_running_waits_for_termination_then_starts(config, monkeypatch, requests_mock):
cluster_url = "http://localhost/api/2.1/clusters/get?cluster_id=cluster-1"
requests_mock.register_uri(
"GET",
cluster_url,
[
{"json": {"cluster_id": "cluster-1", "cluster_name": "fixture", "state": "TERMINATING"}},
{"json": {"cluster_id": "cluster-1", "cluster_name": "fixture", "state": "TERMINATED"}},
{"json": {"cluster_id": "cluster-1", "cluster_name": "fixture", "state": "PENDING"}},
{"json": {"cluster_id": "cluster-1", "cluster_name": "fixture", "state": "RUNNING"}},
],
)
requests_mock.post("http://localhost/api/2.1/clusters/start", json={})
monkeypatch.setattr(compute.time, "sleep", lambda _: None)
workspace = WorkspaceClient(config=config)

workspace.clusters.ensure_cluster_is_running("cluster-1")

assert [request.method for request in requests_mock.request_history] == ["GET", "GET", "POST", "GET", "GET"]
assert requests_mock.request_history[2].json() == {"cluster_id": "cluster-1"}


def test_cluster_events_reposts_next_page_request_at_http_boundary(config, requests_mock):
next_page = {
"cluster_id": "cluster-1",
"event_types": ["STARTING", "TERMINATING"],
"limit": 1,
"offset": 1,
}
requests_mock.register_uri(
"POST",
"http://localhost/api/2.1/clusters/events",
[
{
"json": {
"events": [{"cluster_id": "cluster-1", "timestamp": 1000, "type": "STARTING"}],
"next_page": next_page,
}
},
{"json": {"events": [{"cluster_id": "cluster-1", "timestamp": 2000, "type": "TERMINATING"}]}},
],
)
workspace = WorkspaceClient(config=config)

events = list(
workspace.clusters.events(
"cluster-1",
event_types=[compute.EventType.STARTING, compute.EventType.TERMINATING],
limit=1,
)
)

assert [event.type for event in events] == [compute.EventType.STARTING, compute.EventType.TERMINATING]
assert requests_mock.request_history[0].json() == {
"cluster_id": "cluster-1",
"event_types": ["STARTING", "TERMINATING"],
"limit": 1,
}
assert requests_mock.request_history[1].json() == next_page
Loading
Loading