From ffdc627d8fe63a58382eaf022e1761183b6862eb Mon Sep 17 00:00:00 2001 From: "databricks-ci-ghec-2[bot]" <184307802+databricks-ci-ghec-2[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 03:11:23 +0000 Subject: [PATCH] Release databricks-sdk-py --- .codegen/_last_sha | 2 +- CHANGELOG.md | 12 + databricks/sdk/service/iamv2.py | 20 +- databricks/sdk/service/jobs.py | 521 ++++++++++++++++++++++++++++++ databricks/sdk/service/serving.py | 9 +- databricks/sdk/version.py | 2 +- docs/dbdataclasses/jobs.rst | 44 +++ docs/workspace/jobs/jobs.rst | 7 +- 8 files changed, 603 insertions(+), 14 deletions(-) diff --git a/.codegen/_last_sha b/.codegen/_last_sha index 45ae29f37..25e77597c 100644 --- a/.codegen/_last_sha +++ b/.codegen/_last_sha @@ -1 +1 @@ -16bf9ed0feeb052d9ec3ee73e4bedcf25fcfe014 \ No newline at end of file +788266450afec17c6d92ce881ba6614c3ee35938 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e5070c04c..c4a828e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Version changelog +## Release v0.127.0 (2026-08-12) + +### API Changes +* Add `mlflow_artifact_location` field for `databricks.sdk.service.jobs.AiRuntimeTask`. +* Add `trigger_details` field for `databricks.sdk.service.jobs.BaseJob`. +* Add `triggers` field for `databricks.sdk.service.jobs.CreateJob`. +* Add `trigger_details` field for `databricks.sdk.service.jobs.Job`. +* Add `triggers` field for `databricks.sdk.service.jobs.JobSettings`. +* Add `api_source_connector_options` field for `databricks.sdk.service.pipelines.ConnectorOptions`. +* Add `api_source_connector_config` field for `databricks.sdk.service.pipelines.SourceConfig`. +* Add `all_vpc_sc_services` and `google_api_endpoints` fields for `databricks.sdk.service.settings.GcpEndpoint`. + ## Release v0.126.0 (2026-08-11) ### API Changes diff --git a/databricks/sdk/service/iamv2.py b/databricks/sdk/service/iamv2.py index 22d30c2c7..deccaae4a 100644 --- a/databricks/sdk/service/iamv2.py +++ b/databricks/sdk/service/iamv2.py @@ -225,8 +225,10 @@ class ExternalGroup: """Internal groupId of the group in Databricks.""" name: Optional[str] = None - """The resource name of the external group. Format: - accounts/{account_id}/external-groups/{external_group_id}""" + """The resource name of the external group. The format depends on the API that returned it: + + - Account-scoped: accounts/{account_id}/external-groups/{external_group_id} + - Workspace-scoped: external-groups/{external_group_id}""" def as_dict(self) -> dict: """Serializes the ExternalGroup into a dictionary suitable for use as a JSON request body.""" @@ -296,8 +298,12 @@ class ExternalServicePrincipal: """Internal servicePrincipalId of the service principal in Databricks.""" name: Optional[str] = None - """The resource name of the external service principal. Format: - accounts/{account_id}/external-service-principals/{external_service_principal_id}""" + """The resource name of the external service principal. The format depends on the API that returned + it: + + - Account-scoped: + accounts/{account_id}/external-service-principals/{external_service_principal_id} + - Workspace-scoped: external-service-principals/{external_service_principal_id}""" def as_dict(self) -> dict: """Serializes the ExternalServicePrincipal into a dictionary suitable for use as a JSON request body.""" @@ -378,8 +384,10 @@ class ExternalUser: """Internal userId of the user in Databricks.""" name: Optional[str] = None - """The resource name of the external user. Format: - accounts/{account_id}/external-users/{external_user_id}""" + """The resource name of the external user. The format depends on the API that returned it: + + - Account-scoped: accounts/{account_id}/external-users/{external_user_id} + - Workspace-scoped: external-users/{external_user_id}""" username: Optional[str] = None """Username/email of the user, from Databricks.""" diff --git a/databricks/sdk/service/jobs.py b/databricks/sdk/service/jobs.py index c2b9b3c76..34200f86e 100644 --- a/databricks/sdk/service/jobs.py +++ b/databricks/sdk/service/jobs.py @@ -796,6 +796,12 @@ class BaseJob: """Settings for this job and all of its runs. These settings can be updated using the ``resetJob`` method.""" + trigger_details: Optional[List[TriggerDetails]] = None + """Per-trigger runtime information for the multi-trigger surface. Same length and order as + ``JobSettings.triggers``; ``trigger_details[i]`` corresponds to ``triggers[i]``. Sub-fields + (``state``, ``history``) are populated independently based on the + ``GetJob.include_trigger_state`` / ``include_trigger_history`` flags.""" + trigger_state: Optional[TriggerStateProto] = None """State of the trigger associated with the job.""" @@ -818,6 +824,8 @@ def as_dict(self) -> dict: body["path"] = self.path if self.settings: body["settings"] = self.settings.as_dict() + if self.trigger_details: + body["trigger_details"] = [v.as_dict() for v in self.trigger_details] if self.trigger_state: body["trigger_state"] = self.trigger_state.as_dict() return body @@ -841,6 +849,8 @@ def as_shallow_dict(self) -> dict: body["path"] = self.path if self.settings: body["settings"] = self.settings + if self.trigger_details: + body["trigger_details"] = self.trigger_details if self.trigger_state: body["trigger_state"] = self.trigger_state return body @@ -857,6 +867,7 @@ def from_dict(cls, d: Dict[str, Any]) -> BaseJob: job_id=d.get("job_id", None), path=d.get("path", None), settings=_from_dict(d, "settings", JobSettings), + trigger_details=_repeated_dict(d, "trigger_details", TriggerDetails), trigger_state=_from_dict(d, "trigger_state", TriggerStateProto), ) @@ -1764,6 +1775,85 @@ def from_dict(cls, d: Dict[str, Any]) -> Continuous: ) +@dataclass +class ContinuousTriggerConfiguration: + """Continuous trigger. Stripped-down counterpart to ``ContinuousSettings``: ``pause_status`` is + owned by the enclosing ``TriggerConfiguration`` and intentionally omitted here.""" + + maintenance_window: Optional[MaintenanceWindow] = None + """Defines when platform-initiated maintenance may run for this trigger. If unspecified, + maintenance may run at any time.""" + + task_retry_mode: Optional[TaskRetryMode] = None + """Whether the continuous job applies task-level retries. Defaults to NEVER.""" + + def as_dict(self) -> dict: + """Serializes the ContinuousTriggerConfiguration into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.maintenance_window: + body["maintenance_window"] = self.maintenance_window.as_dict() + if self.task_retry_mode is not None: + body["task_retry_mode"] = self.task_retry_mode.value + return body + + def as_shallow_dict(self) -> dict: + """Serializes the ContinuousTriggerConfiguration into a shallow dictionary of its immediate attributes.""" + body = {} + if self.maintenance_window: + body["maintenance_window"] = self.maintenance_window + if self.task_retry_mode is not None: + body["task_retry_mode"] = self.task_retry_mode + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> ContinuousTriggerConfiguration: + """Deserializes the ContinuousTriggerConfiguration from a dictionary.""" + return cls( + maintenance_window=_from_dict(d, "maintenance_window", MaintenanceWindow), + task_retry_mode=_enum(d, "task_retry_mode", TaskRetryMode), + ) + + +@dataclass +class ContinuousTriggerState: + consecutive_failures: Optional[int] = None + + is_backing_off: Optional[bool] = None + + next_attempt_ms: Optional[int] = None + + def as_dict(self) -> dict: + """Serializes the ContinuousTriggerState into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.consecutive_failures is not None: + body["consecutive_failures"] = self.consecutive_failures + if self.is_backing_off is not None: + body["is_backing_off"] = self.is_backing_off + if self.next_attempt_ms is not None: + body["next_attempt_ms"] = self.next_attempt_ms + return body + + def as_shallow_dict(self) -> dict: + """Serializes the ContinuousTriggerState into a shallow dictionary of its immediate attributes.""" + body = {} + if self.consecutive_failures is not None: + body["consecutive_failures"] = self.consecutive_failures + if self.is_backing_off is not None: + body["is_backing_off"] = self.is_backing_off + if self.next_attempt_ms is not None: + body["next_attempt_ms"] = self.next_attempt_ms + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> ContinuousTriggerState: + """Deserializes the ContinuousTriggerState from a dictionary.""" + return cls( + consecutive_failures=d.get("consecutive_failures", None), + is_backing_off=d.get("is_backing_off", None), + next_attempt_ms=d.get("next_attempt_ms", None), + ) + + @dataclass class CreateResponse: """Job was created successfully""" @@ -1848,6 +1938,46 @@ def from_dict(cls, d: Dict[str, Any]) -> CronSchedule: ) +@dataclass +class CronTriggerConfiguration: + """Cron schedule trigger. Stripped-down counterpart to ``CronSchedule``: ``pause_status`` and + ``sql_condition`` are owned by the enclosing ``TriggerConfiguration`` and intentionally omitted + here.""" + + quartz_cron_expression: str + """A Cron expression using Quartz syntax that describes the schedule for this trigger. See `Cron + Trigger + `__ for + details.""" + + timezone_id: str + """A Java timezone ID. The schedule is resolved with respect to this timezone. See `Java TimeZone + `__ for details.""" + + def as_dict(self) -> dict: + """Serializes the CronTriggerConfiguration into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.quartz_cron_expression is not None: + body["quartz_cron_expression"] = self.quartz_cron_expression + if self.timezone_id is not None: + body["timezone_id"] = self.timezone_id + return body + + def as_shallow_dict(self) -> dict: + """Serializes the CronTriggerConfiguration into a shallow dictionary of its immediate attributes.""" + body = {} + if self.quartz_cron_expression is not None: + body["quartz_cron_expression"] = self.quartz_cron_expression + if self.timezone_id is not None: + body["timezone_id"] = self.timezone_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> CronTriggerConfiguration: + """Deserializes the CronTriggerConfiguration from a dictionary.""" + return cls(quartz_cron_expression=d.get("quartz_cron_expression", None), timezone_id=d.get("timezone_id", None)) + + @dataclass class DashboardPageSnapshot: page_display_name: Optional[str] = None @@ -3525,6 +3655,12 @@ class Job: """Settings for this job and all of its runs. These settings can be updated using the ``resetJob`` method.""" + trigger_details: Optional[List[TriggerDetails]] = None + """Per-trigger runtime information for the multi-trigger surface. Same length and order as + ``JobSettings.triggers``; ``trigger_details[i]`` corresponds to ``triggers[i]``. Sub-fields + (``state``, ``history``) are populated independently based on the + ``GetJob.include_trigger_state`` / ``include_trigger_history`` flags.""" + trigger_state: Optional[TriggerStateProto] = None """State of the trigger associated with the job.""" @@ -3551,6 +3687,8 @@ def as_dict(self) -> dict: body["run_as_user_name"] = self.run_as_user_name if self.settings: body["settings"] = self.settings.as_dict() + if self.trigger_details: + body["trigger_details"] = [v.as_dict() for v in self.trigger_details] if self.trigger_state: body["trigger_state"] = self.trigger_state.as_dict() return body @@ -3578,6 +3716,8 @@ def as_shallow_dict(self) -> dict: body["run_as_user_name"] = self.run_as_user_name if self.settings: body["settings"] = self.settings + if self.trigger_details: + body["trigger_details"] = self.trigger_details if self.trigger_state: body["trigger_state"] = self.trigger_state return body @@ -3596,6 +3736,7 @@ def from_dict(cls, d: Dict[str, Any]) -> Job: path=d.get("path", None), run_as_user_name=d.get("run_as_user_name", None), settings=_from_dict(d, "settings", JobSettings), + trigger_details=_repeated_dict(d, "trigger_details", TriggerDetails), trigger_state=_from_dict(d, "trigger_state", TriggerStateProto), ) @@ -4502,6 +4643,12 @@ class JobSettings: the job runs only when triggered by clicking “Run Now” in the Jobs UI or sending an API request to ``runNow``.""" + triggers: Optional[List[TriggerConfiguration]] = None + """List of triggers attached to this job. A run starts when any active trigger evaluates to true. + Cannot be set in the same request as the legacy ``schedule``, ``trigger``, or ``continuous`` + fields. The 10-trigger cap is the design's hard limit; rollout steps the effective cap 3 -> 5 -> + 10 via internal validation during the preview.""" + usage_policy_id: Optional[str] = None """The id of the user specified usage policy to use for this job. If not specified, a default usage policy may be applied when creating or modifying the job. See ``effective_usage_policy_id`` for @@ -4563,6 +4710,8 @@ def as_dict(self) -> dict: body["timeout_seconds"] = self.timeout_seconds if self.trigger: body["trigger"] = self.trigger.as_dict() + if self.triggers: + body["triggers"] = [v.as_dict() for v in self.triggers] if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.webhook_notifications: @@ -4622,6 +4771,8 @@ def as_shallow_dict(self) -> dict: body["timeout_seconds"] = self.timeout_seconds if self.trigger: body["trigger"] = self.trigger + if self.triggers: + body["triggers"] = self.triggers if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.webhook_notifications: @@ -4657,6 +4808,7 @@ def from_dict(cls, d: Dict[str, Any]) -> JobSettings: tasks=_repeated_dict(d, "tasks", Task), timeout_seconds=d.get("timeout_seconds", None), trigger=_from_dict(d, "trigger", TriggerSettings), + triggers=_repeated_dict(d, "triggers", TriggerConfiguration), usage_policy_id=d.get("usage_policy_id", None), webhook_notifications=_from_dict(d, "webhook_notifications", WebhookNotifications), ) @@ -5123,6 +5275,27 @@ class ModelTriggerConfigurationCondition(Enum): MODEL_VERSION_READY = "MODEL_VERSION_READY" +@dataclass +class ModelTriggerState: + """Runtime state for a model trigger. Currently empty because model triggers do not expose any + trigger-specific runtime state.""" + + def as_dict(self) -> dict: + """Serializes the ModelTriggerState into a dictionary suitable for use as a JSON request body.""" + body = {} + return body + + def as_shallow_dict(self) -> dict: + """Serializes the ModelTriggerState into a shallow dictionary of its immediate attributes.""" + body = {} + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> ModelTriggerState: + """Deserializes the ModelTriggerState from a dictionary.""" + return cls() + + @dataclass class NotebookOutput: result: Optional[str] = None @@ -5283,6 +5456,88 @@ class PauseStatus(Enum): UNPAUSED = "UNPAUSED" +@dataclass +class PerTriggerState: + """Per-trigger runtime state for the multi-trigger surface. Mirrors ``TriggerConfiguration``'s + trigger-type variants 1:1; each entry sets exactly one variant matching the corresponding + trigger's type. Variants with no runtime state today (``schedule``, ``model``) are emitted as + empty messages.""" + + continuous: Optional[ContinuousTriggerState] = None + + file_arrival: Optional[FileArrivalTriggerState] = None + + model: Optional[ModelTriggerState] = None + + pause_status: Optional[PauseStatus] = None + """Whether this trigger is paused or not. Mirrors the configured pause_status.""" + + periodic: Optional[PeriodicTriggerState] = None + + schedule: Optional[ScheduleTriggerState] = None + + sql_condition: Optional[SqlConditionState] = None + """State for SQL condition evaluation, can coexist with other trigger states.""" + + table_update: Optional[TableTriggerState] = None + + def as_dict(self) -> dict: + """Serializes the PerTriggerState into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.continuous: + body["continuous"] = self.continuous.as_dict() + if self.file_arrival: + body["file_arrival"] = self.file_arrival.as_dict() + if self.model: + body["model"] = self.model.as_dict() + if self.pause_status is not None: + body["pause_status"] = self.pause_status.value + if self.periodic: + body["periodic"] = self.periodic.as_dict() + if self.schedule: + body["schedule"] = self.schedule.as_dict() + if self.sql_condition: + body["sql_condition"] = self.sql_condition.as_dict() + if self.table_update: + body["table_update"] = self.table_update.as_dict() + return body + + def as_shallow_dict(self) -> dict: + """Serializes the PerTriggerState into a shallow dictionary of its immediate attributes.""" + body = {} + if self.continuous: + body["continuous"] = self.continuous + if self.file_arrival: + body["file_arrival"] = self.file_arrival + if self.model: + body["model"] = self.model + if self.pause_status is not None: + body["pause_status"] = self.pause_status + if self.periodic: + body["periodic"] = self.periodic + if self.schedule: + body["schedule"] = self.schedule + if self.sql_condition: + body["sql_condition"] = self.sql_condition + if self.table_update: + body["table_update"] = self.table_update + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> PerTriggerState: + """Deserializes the PerTriggerState from a dictionary.""" + return cls( + continuous=_from_dict(d, "continuous", ContinuousTriggerState), + file_arrival=_from_dict(d, "file_arrival", FileArrivalTriggerState), + model=_from_dict(d, "model", ModelTriggerState), + pause_status=_enum(d, "pause_status", PauseStatus), + periodic=_from_dict(d, "periodic", PeriodicTriggerState), + schedule=_from_dict(d, "schedule", ScheduleTriggerState), + sql_condition=_from_dict(d, "sql_condition", SqlConditionState), + table_update=_from_dict(d, "table_update", TableTriggerState), + ) + + class PerformanceTarget(Enum): """PerformanceTarget defines how performant (lower latency) or cost efficient the execution of run on serverless compute should be. The performance mode on the job or pipeline should map to a @@ -5331,6 +5586,30 @@ class PeriodicTriggerConfigurationTimeUnit(Enum): WEEKS = "WEEKS" +@dataclass +class PeriodicTriggerState: + next_run_time: Optional[int] = None + + def as_dict(self) -> dict: + """Serializes the PeriodicTriggerState into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.next_run_time is not None: + body["next_run_time"] = self.next_run_time + return body + + def as_shallow_dict(self) -> dict: + """Serializes the PeriodicTriggerState into a shallow dictionary of its immediate attributes.""" + body = {} + if self.next_run_time is not None: + body["next_run_time"] = self.next_run_time + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> PeriodicTriggerState: + """Deserializes the PeriodicTriggerState from a dictionary.""" + return cls(next_run_time=d.get("next_run_time", None)) + + @dataclass class PipelineParams: full_refresh: Optional[bool] = None @@ -8279,6 +8558,27 @@ class RunType(Enum): WORKFLOW_RUN = "WORKFLOW_RUN" +@dataclass +class ScheduleTriggerState: + """Runtime state for a schedule trigger. Currently empty because schedule triggers do not expose + any trigger-specific runtime state.""" + + def as_dict(self) -> dict: + """Serializes the ScheduleTriggerState into a dictionary suitable for use as a JSON request body.""" + body = {} + return body + + def as_shallow_dict(self) -> dict: + """Serializes the ScheduleTriggerState into a shallow dictionary of its immediate attributes.""" + body = {} + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> ScheduleTriggerState: + """Deserializes the ScheduleTriggerState from a dictionary.""" + return cls() + + @dataclass class SchemaTool: name: Optional[str] = None @@ -10891,6 +11191,219 @@ def from_dict(cls, d: Dict[str, Any]) -> TraceDestination: ) +@dataclass +class TriggerConfiguration: + """A single trigger attached to a job via ``JobSettings.triggers``. Exactly one of the trigger-type + fields (``periodic``, ``schedule``, ``continuous``, ``file_arrival``, ``table_update``, + ``model``) must be set; mutual exclusivity is enforced in the API handler rather than via + ``oneof`` so that codegen, validation, and JSON serialization across SDKs and Terraform behave + consistently.""" + + continuous: Optional[ContinuousTriggerConfiguration] = None + """Continuous trigger configuration.""" + + file_arrival: Optional[FileArrivalTriggerConfiguration] = None + """File arrival trigger configuration.""" + + model: Optional[ModelTriggerConfiguration] = None + """Model trigger configuration.""" + + pause_status: Optional[PauseStatus] = None + """Whether this trigger is paused. Defaults to UNPAUSED when unset; the server always returns an + explicit value on read.""" + + periodic: Optional[PeriodicTriggerConfiguration] = None + """Trigger type: exactly one must be set; mutual exclusivity is enforced in the API handler + Periodic trigger configuration.""" + + schedule: Optional[CronTriggerConfiguration] = None + """Cron schedule trigger configuration.""" + + sql_condition: Optional[SqlConditionConfiguration] = None + """Optional SQL condition that gates whether this trigger fires.""" + + table_update: Optional[TableUpdateTriggerConfiguration] = None + """Table update trigger configuration.""" + + def as_dict(self) -> dict: + """Serializes the TriggerConfiguration into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.continuous: + body["continuous"] = self.continuous.as_dict() + if self.file_arrival: + body["file_arrival"] = self.file_arrival.as_dict() + if self.model: + body["model"] = self.model.as_dict() + if self.pause_status is not None: + body["pause_status"] = self.pause_status.value + if self.periodic: + body["periodic"] = self.periodic.as_dict() + if self.schedule: + body["schedule"] = self.schedule.as_dict() + if self.sql_condition: + body["sql_condition"] = self.sql_condition.as_dict() + if self.table_update: + body["table_update"] = self.table_update.as_dict() + return body + + def as_shallow_dict(self) -> dict: + """Serializes the TriggerConfiguration into a shallow dictionary of its immediate attributes.""" + body = {} + if self.continuous: + body["continuous"] = self.continuous + if self.file_arrival: + body["file_arrival"] = self.file_arrival + if self.model: + body["model"] = self.model + if self.pause_status is not None: + body["pause_status"] = self.pause_status + if self.periodic: + body["periodic"] = self.periodic + if self.schedule: + body["schedule"] = self.schedule + if self.sql_condition: + body["sql_condition"] = self.sql_condition + if self.table_update: + body["table_update"] = self.table_update + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> TriggerConfiguration: + """Deserializes the TriggerConfiguration from a dictionary.""" + return cls( + continuous=_from_dict(d, "continuous", ContinuousTriggerConfiguration), + file_arrival=_from_dict(d, "file_arrival", FileArrivalTriggerConfiguration), + model=_from_dict(d, "model", ModelTriggerConfiguration), + pause_status=_enum(d, "pause_status", PauseStatus), + periodic=_from_dict(d, "periodic", PeriodicTriggerConfiguration), + schedule=_from_dict(d, "schedule", CronTriggerConfiguration), + sql_condition=_from_dict(d, "sql_condition", SqlConditionConfiguration), + table_update=_from_dict(d, "table_update", TableUpdateTriggerConfiguration), + ) + + +@dataclass +class TriggerDetails: + """Per-trigger runtime details returned by ``GetJob``. Same length and order as + ``JobSettings.triggers``; sub-fields are populated independently based on the corresponding + ``GetJob.include_trigger_state`` / ``include_trigger_history`` flags.""" + + history: Optional[TriggerHistory] = None + """Recent evaluation history. Populated when ``GetJob.include_trigger_history`` is set.""" + + state: Optional[PerTriggerState] = None + """Current runtime state. Populated when ``GetJob.include_trigger_state`` is set.""" + + def as_dict(self) -> dict: + """Serializes the TriggerDetails into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.history: + body["history"] = self.history.as_dict() + if self.state: + body["state"] = self.state.as_dict() + return body + + def as_shallow_dict(self) -> dict: + """Serializes the TriggerDetails into a shallow dictionary of its immediate attributes.""" + body = {} + if self.history: + body["history"] = self.history + if self.state: + body["state"] = self.state + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> TriggerDetails: + """Deserializes the TriggerDetails from a dictionary.""" + return cls(history=_from_dict(d, "history", TriggerHistory), state=_from_dict(d, "state", PerTriggerState)) + + +@dataclass +class TriggerEvaluation: + description: Optional[str] = None + """Human-readable description of the trigger evaluation result. Explains why the trigger evaluation + triggered or did not trigger a run, or failed.""" + + run_id: Optional[int] = None + """The ID of the run that was triggered by the trigger evaluation. Only returned if a run was + triggered.""" + + timestamp: Optional[int] = None + """Timestamp at which the trigger was evaluated.""" + + def as_dict(self) -> dict: + """Serializes the TriggerEvaluation into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.description is not None: + body["description"] = self.description + if self.run_id is not None: + body["run_id"] = self.run_id + if self.timestamp is not None: + body["timestamp"] = self.timestamp + return body + + def as_shallow_dict(self) -> dict: + """Serializes the TriggerEvaluation into a shallow dictionary of its immediate attributes.""" + body = {} + if self.description is not None: + body["description"] = self.description + if self.run_id is not None: + body["run_id"] = self.run_id + if self.timestamp is not None: + body["timestamp"] = self.timestamp + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> TriggerEvaluation: + """Deserializes the TriggerEvaluation from a dictionary.""" + return cls( + description=d.get("description", None), run_id=d.get("run_id", None), timestamp=d.get("timestamp", None) + ) + + +@dataclass +class TriggerHistory: + last_failed: Optional[TriggerEvaluation] = None + """The last time the trigger failed to evaluate.""" + + last_not_triggered: Optional[TriggerEvaluation] = None + """The last time the trigger was evaluated but did not trigger a run.""" + + last_triggered: Optional[TriggerEvaluation] = None + """The last time the run was triggered due to a file arrival.""" + + def as_dict(self) -> dict: + """Serializes the TriggerHistory into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.last_failed: + body["last_failed"] = self.last_failed.as_dict() + if self.last_not_triggered: + body["last_not_triggered"] = self.last_not_triggered.as_dict() + if self.last_triggered: + body["last_triggered"] = self.last_triggered.as_dict() + return body + + def as_shallow_dict(self) -> dict: + """Serializes the TriggerHistory into a shallow dictionary of its immediate attributes.""" + body = {} + if self.last_failed: + body["last_failed"] = self.last_failed + if self.last_not_triggered: + body["last_not_triggered"] = self.last_not_triggered + if self.last_triggered: + body["last_triggered"] = self.last_triggered + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> TriggerHistory: + """Deserializes the TriggerHistory from a dictionary.""" + return cls( + last_failed=_from_dict(d, "last_failed", TriggerEvaluation), + last_not_triggered=_from_dict(d, "last_not_triggered", TriggerEvaluation), + last_triggered=_from_dict(d, "last_triggered", TriggerEvaluation), + ) + + @dataclass class TriggerInfo: """Additional details about what triggered the run""" @@ -11552,6 +12065,7 @@ def create( tasks: Optional[List[Task]] = None, timeout_seconds: Optional[int] = None, trigger: Optional[TriggerSettings] = None, + triggers: Optional[List[TriggerConfiguration]] = None, usage_policy_id: Optional[str] = None, webhook_notifications: Optional[WebhookNotifications] = None, ) -> CreateResponse: @@ -11657,6 +12171,11 @@ def create( A configuration to trigger a run when certain conditions are met. The default behavior is that the job runs only when triggered by clicking “Run Now” in the Jobs UI or sending an API request to ``runNow``. + :param triggers: List[:class:`TriggerConfiguration`] (optional) + List of triggers attached to this job. A run starts when any active trigger evaluates to true. + Cannot be set in the same request as the legacy ``schedule``, ``trigger``, or ``continuous`` fields. + The 10-trigger cap is the design's hard limit; rollout steps the effective cap 3 -> 5 -> 10 via + internal validation during the preview. :param usage_policy_id: str (optional) The id of the user specified usage policy to use for this job. If not specified, a default usage policy may be applied when creating or modifying the job. See ``effective_usage_policy_id`` for the @@ -11720,6 +12239,8 @@ def create( body["timeout_seconds"] = timeout_seconds if trigger is not None: body["trigger"] = trigger.as_dict() + if triggers is not None: + body["triggers"] = [v.as_dict() for v in triggers] if usage_policy_id is not None: body["usage_policy_id"] = usage_policy_id if webhook_notifications is not None: diff --git a/databricks/sdk/service/serving.py b/databricks/sdk/service/serving.py index f13432c9b..548d84548 100644 --- a/databricks/sdk/service/serving.py +++ b/databricks/sdk/service/serving.py @@ -2309,8 +2309,9 @@ def from_dict(cls, d: Dict[str, Any]) -> PtCommitmentAutoRenew: @dataclass class PtCommitmentRelocation: """A request to relocate ("upgrade") an existing Provisioned Throughput commitment onto a - different, same-line endpoint. The commitment row moves intact (same commitment_id) from the - source endpoint to the target in a single transaction.""" + different, same-line endpoint. Each source commitment is deleted and reissued as a fresh + commitment on the target (new id, term restarting at the relocation time, same model units, term + length, and auto-renew) in a single transaction.""" source_endpoint: str """The endpoint that currently owns the commitments (the relocation source).""" @@ -4207,9 +4208,7 @@ class TelemetryConfig: table_names: Optional[UnityCatalogTableNames] = None """The Unity Catalog tables to which endpoint telemetry (logs, traces, and metrics) is exported. - Provide this to create a new telemetry profile for the endpoint from the given tables. This - field selects the tables when writing a telemetry configuration; it is not returned when reading - one. Responses identify the resulting profile with ``telemetry_profile_id`` instead.""" + Provide this to create a new telemetry profile for the endpoint from the given tables.""" telemetry_profile_id: Optional[str] = None """The ID of an existing telemetry profile to apply to this endpoint. Provide this to reuse a diff --git a/databricks/sdk/version.py b/databricks/sdk/version.py index a8b16b76b..6ca6f8c9c 100644 --- a/databricks/sdk/version.py +++ b/databricks/sdk/version.py @@ -1 +1 @@ -__version__ = "0.126.0" +__version__ = "0.127.0" diff --git a/docs/dbdataclasses/jobs.rst b/docs/dbdataclasses/jobs.rst index 7a00be236..dee054e5d 100644 --- a/docs/dbdataclasses/jobs.rst +++ b/docs/dbdataclasses/jobs.rst @@ -244,6 +244,14 @@ These dataclasses are used in the SDK to represent API requests and responses fo :members: :undoc-members: +.. autoclass:: ContinuousTriggerConfiguration + :members: + :undoc-members: + +.. autoclass:: ContinuousTriggerState + :members: + :undoc-members: + .. autoclass:: CreateResponse :members: :undoc-members: @@ -252,6 +260,10 @@ These dataclasses are used in the SDK to represent API requests and responses fo :members: :undoc-members: +.. autoclass:: CronTriggerConfiguration + :members: + :undoc-members: + .. autoclass:: DashboardPageSnapshot :members: :undoc-members: @@ -656,6 +668,10 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: MODEL_VERSION_READY :value: "MODEL_VERSION_READY" +.. autoclass:: ModelTriggerState + :members: + :undoc-members: + .. autoclass:: NotebookOutput :members: :undoc-members: @@ -676,6 +692,10 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: UNPAUSED :value: "UNPAUSED" +.. autoclass:: PerTriggerState + :members: + :undoc-members: + .. py:class:: PerformanceTarget PerformanceTarget defines how performant (lower latency) or cost efficient the execution of run on serverless compute should be. The performance mode on the job or pipeline should map to a performance setting that is passed to Cluster Manager (see cluster-common PerformanceTarget). @@ -704,6 +724,10 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: WEEKS :value: "WEEKS" +.. autoclass:: PeriodicTriggerState + :members: + :undoc-members: + .. autoclass:: PipelineParams :members: :undoc-members: @@ -1059,6 +1083,10 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: WORKFLOW_RUN :value: "WORKFLOW_RUN" +.. autoclass:: ScheduleTriggerState + :members: + :undoc-members: + .. autoclass:: SchemaTool :members: :undoc-members: @@ -1404,6 +1432,22 @@ These dataclasses are used in the SDK to represent API requests and responses fo :members: :undoc-members: +.. autoclass:: TriggerConfiguration + :members: + :undoc-members: + +.. autoclass:: TriggerDetails + :members: + :undoc-members: + +.. autoclass:: TriggerEvaluation + :members: + :undoc-members: + +.. autoclass:: TriggerHistory + :members: + :undoc-members: + .. autoclass:: TriggerInfo :members: :undoc-members: diff --git a/docs/workspace/jobs/jobs.rst b/docs/workspace/jobs/jobs.rst index 7696a7a76..dd7eb6090 100644 --- a/docs/workspace/jobs/jobs.rst +++ b/docs/workspace/jobs/jobs.rst @@ -125,7 +125,7 @@ .. py:method:: cancel_run_and_wait(run_id: int, timeout: datetime.timedelta = 0:20:00) -> Run - .. py:method:: create( [, access_control_list: Optional[List[JobAccessControlRequest]], budget_policy_id: Optional[str], continuous: Optional[Continuous], deployment: Optional[JobDeployment], description: Optional[str], edit_mode: Optional[JobEditMode], email_notifications: Optional[JobEmailNotifications], environment_variables: Optional[List[JobEnvironmentVariables]], environments: Optional[List[JobEnvironment]], format: Optional[Format], git_source: Optional[GitSource], health: Optional[JobsHealthRules], job_clusters: Optional[List[JobCluster]], max_concurrent_runs: Optional[int], name: Optional[str], notification_settings: Optional[JobNotificationSettings], parameters: Optional[List[JobParameterDefinition]], parent_path: Optional[str], performance_target: Optional[PerformanceTarget], queue: Optional[QueueSettings], run_as: Optional[JobRunAs], schedule: Optional[CronSchedule], tags: Optional[Dict[str, str]], tasks: Optional[List[Task]], timeout_seconds: Optional[int], trigger: Optional[TriggerSettings], usage_policy_id: Optional[str], webhook_notifications: Optional[WebhookNotifications]]) -> CreateResponse + .. py:method:: create( [, access_control_list: Optional[List[JobAccessControlRequest]], budget_policy_id: Optional[str], continuous: Optional[Continuous], deployment: Optional[JobDeployment], description: Optional[str], edit_mode: Optional[JobEditMode], email_notifications: Optional[JobEmailNotifications], environment_variables: Optional[List[JobEnvironmentVariables]], environments: Optional[List[JobEnvironment]], format: Optional[Format], git_source: Optional[GitSource], health: Optional[JobsHealthRules], job_clusters: Optional[List[JobCluster]], max_concurrent_runs: Optional[int], name: Optional[str], notification_settings: Optional[JobNotificationSettings], parameters: Optional[List[JobParameterDefinition]], parent_path: Optional[str], performance_target: Optional[PerformanceTarget], queue: Optional[QueueSettings], run_as: Optional[JobRunAs], schedule: Optional[CronSchedule], tags: Optional[Dict[str, str]], tasks: Optional[List[Task]], timeout_seconds: Optional[int], trigger: Optional[TriggerSettings], triggers: Optional[List[TriggerConfiguration]], usage_policy_id: Optional[str], webhook_notifications: Optional[WebhookNotifications]]) -> CreateResponse Usage: @@ -264,6 +264,11 @@ A configuration to trigger a run when certain conditions are met. The default behavior is that the job runs only when triggered by clicking “Run Now” in the Jobs UI or sending an API request to ``runNow``. + :param triggers: List[:class:`TriggerConfiguration`] (optional) + List of triggers attached to this job. A run starts when any active trigger evaluates to true. + Cannot be set in the same request as the legacy ``schedule``, ``trigger``, or ``continuous`` fields. + The 10-trigger cap is the design's hard limit; rollout steps the effective cap 3 -> 5 -> 10 via + internal validation during the preview. :param usage_policy_id: str (optional) The id of the user specified usage policy to use for this job. If not specified, a default usage policy may be applied when creating or modifying the job. See ``effective_usage_policy_id`` for the