databricks-sdk 0.158.0__tar.gz → 0.159.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/CHANGELOG.md +136 -0
  2. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/PKG-INFO +1 -1
  3. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/__init__.py +16 -0
  4. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/config.py +4 -7
  5. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/files.py +4 -278
  6. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/billing.py +3 -2
  7. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/catalog.py +18 -13
  8. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/compute.py +19 -16
  9. databricks_sdk-0.159.0/databricks/sdk/service/computemigrations.py +934 -0
  10. databricks_sdk-0.159.0/databricks/sdk/service/genieagents.py +1524 -0
  11. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/iamv2.py +462 -323
  12. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/jobs.py +977 -9
  13. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/ml.py +21 -16
  14. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/postgres.py +42 -11
  15. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/sandbox.py +203 -1
  16. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/settings.py +45 -0
  17. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/sql.py +12 -8
  18. databricks_sdk-0.159.0/databricks/sdk/version.py +1 -0
  19. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks_sdk.egg-info/PKG-INFO +1 -1
  20. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks_sdk.egg-info/SOURCES.txt +2 -0
  21. databricks_sdk-0.158.0/databricks/sdk/version.py +0 -1
  22. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/CONTRIBUTING.md +0 -0
  23. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/DCO +0 -0
  24. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/LICENSE +0 -0
  25. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/MANIFEST.in +0 -0
  26. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/Makefile +0 -0
  27. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/NOTICE +0 -0
  28. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/README.md +0 -0
  29. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/SECURITY.md +0 -0
  30. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/__init__.py +0 -0
  31. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_base_client.py +0 -0
  32. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_property.py +0 -0
  33. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_sandbox_grpc/__init__.py +0 -0
  34. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_sandbox_grpc/sandbox_service_pb2.py +0 -0
  35. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_sandbox_grpc/sandbox_service_pb2_grpc.py +0 -0
  36. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_widgets/__init__.py +0 -0
  37. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_widgets/default_widgets_utils.py +0 -0
  38. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/_widgets/ipywidgets_utils.py +0 -0
  39. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/azure.py +0 -0
  40. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/casing.py +0 -0
  41. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/client_types.py +0 -0
  42. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/clock.py +0 -0
  43. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/common/lro.py +0 -0
  44. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/common/types/__init__.py +0 -0
  45. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/common/types/fieldmask.py +0 -0
  46. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/core.py +0 -0
  47. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/credentials_provider.py +0 -0
  48. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/data_plane.py +0 -0
  49. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/dbutils.py +0 -0
  50. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/environments.py +0 -0
  51. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/__init__.py +0 -0
  52. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/base.py +0 -0
  53. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/customizer.py +0 -0
  54. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/deserializer.py +0 -0
  55. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/details.py +0 -0
  56. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/mapper.py +0 -0
  57. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/overrides.py +0 -0
  58. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/parser.py +0 -0
  59. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/platform.py +0 -0
  60. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/private_link.py +0 -0
  61. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/errors/sdk.py +0 -0
  62. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/logger/__init__.py +0 -0
  63. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/logger/round_trip_logger.py +0 -0
  64. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/__init__.py +0 -0
  65. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/_grpc_transport.py +0 -0
  66. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/compute.py +0 -0
  67. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/files_utils.py +0 -0
  68. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/jobs.py +0 -0
  69. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/open_ai_client.py +0 -0
  70. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/sandbox.py +0 -0
  71. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/sharing.py +0 -0
  72. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/mixins/workspace.py +0 -0
  73. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/oauth.py +0 -0
  74. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/oidc.py +0 -0
  75. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/oidc_token_supplier.py +0 -0
  76. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/py.typed +0 -0
  77. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/retries.py +0 -0
  78. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/runtime/__init__.py +0 -0
  79. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/runtime/dbutils_stub.py +0 -0
  80. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/__init__.py +0 -0
  81. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/_internal.py +0 -0
  82. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/agentbricks.py +0 -0
  83. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/agentkit.py +0 -0
  84. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/aifunctions.py +0 -0
  85. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/aisearch.py +0 -0
  86. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/apps.py +0 -0
  87. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/bundle.py +0 -0
  88. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/bundledeployments.py +0 -0
  89. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/cleanrooms.py +0 -0
  90. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/dashboards.py +0 -0
  91. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/database.py +0 -0
  92. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/dataclassification.py +0 -0
  93. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/dataquality.py +0 -0
  94. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/disasterrecovery.py +0 -0
  95. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/domains.py +0 -0
  96. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/environments.py +0 -0
  97. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/files.py +0 -0
  98. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/iam.py +0 -0
  99. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/knowledgeassistants.py +0 -0
  100. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/marketplace.py +0 -0
  101. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/networking.py +0 -0
  102. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/oauth2.py +0 -0
  103. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/pipelines.py +0 -0
  104. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/provisioning.py +0 -0
  105. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/qualitymonitorv2.py +0 -0
  106. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/serving.py +0 -0
  107. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/settingsv2.py +0 -0
  108. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/sharing.py +0 -0
  109. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/supervisoragents.py +0 -0
  110. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/tags.py +0 -0
  111. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/vectorsearch.py +0 -0
  112. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/service/workspace.py +0 -0
  113. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks/sdk/useragent.py +0 -0
  114. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks_sdk.egg-info/dependency_links.txt +0 -0
  115. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks_sdk.egg-info/requires.txt +0 -0
  116. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/databricks_sdk.egg-info/top_level.txt +0 -0
  117. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/pyproject.toml +0 -0
  118. {databricks_sdk-0.158.0 → databricks_sdk-0.159.0}/setup.cfg +0 -0
@@ -1,5 +1,141 @@
1
1
  # Version changelog
2
2
 
3
+ ## Release v0.159.0 (2026-11-02)
4
+
5
+ ### API Changes
6
+ * Add `databricks.sdk.service.computemigrations` and `databricks.sdk.service.genieagents` packages.
7
+ * Add [w.compute_migrations](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/computemigrations/compute_migrations.html) workspace-level service.
8
+ * Add [w.genie_agents](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/genieagents/genie_agents.html) workspace-level service.
9
+ * Add `download_file()` and `upload_file()` methods for [w.sandbox](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/sandbox/sandbox.html) workspace-level service.
10
+ * Add `update_network_connectivity_config()` method for [a.network_connectivity](https://databricks-sdk-py.readthedocs.io/en/latest/account/settings/network_connectivity.html) account-level service.
11
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.CreateDirectGroupMemberProxyRequest`.
12
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.CreateDirectGroupMemberRequest`.
13
+ * Add `parent` field for `databricks.sdk.service.iamv2.CreateGroupProxyRequest`.
14
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.CreateGroupRequest`.
15
+ * Add `parent` field for `databricks.sdk.service.iamv2.CreateServicePrincipalProxyRequest`.
16
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.CreateServicePrincipalRequest`.
17
+ * Add `parent` field for `databricks.sdk.service.iamv2.CreateUserProxyRequest`.
18
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.CreateUserRequest`.
19
+ * Add `parent` field for `databricks.sdk.service.iamv2.CreateWorkspaceAssignmentProxyRequest`.
20
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.CreateWorkspaceAssignmentRequest`.
21
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteDirectGroupMemberProxyRequest`.
22
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteDirectGroupMemberRequest`.
23
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteGroupProxyRequest`.
24
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteGroupRequest`.
25
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteServicePrincipalProxyRequest`.
26
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteServicePrincipalRequest`.
27
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteUserProxyRequest`.
28
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteUserRequest`.
29
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteWorkspaceAssignmentProxyRequest`.
30
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.DeleteWorkspaceAssignmentRequest`.
31
+ * Add `name` and `parent` fields for `databricks.sdk.service.iamv2.DirectGroupMember`.
32
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetDirectGroupMemberProxyRequest`.
33
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetDirectGroupMemberRequest`.
34
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetGroupProxyRequest`.
35
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetGroupRequest`.
36
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetServicePrincipalProxyRequest`.
37
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetServicePrincipalRequest`.
38
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetUserProxyRequest`.
39
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetUserRequest`.
40
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetWorkspaceAccessDetailLocalRequest`.
41
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetWorkspaceAccessDetailRequest`.
42
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetWorkspaceAssignmentProxyRequest`.
43
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetWorkspaceAssignmentRequest`.
44
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.GetWorkspaceIdentityDetailRequest`.
45
+ * Add `name` and `parent` fields for `databricks.sdk.service.iamv2.Group`.
46
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListDirectGroupMembersProxyRequest`.
47
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListDirectGroupMembersRequest`.
48
+ * Add `parent` field for `databricks.sdk.service.iamv2.ListGroupsProxyRequest`.
49
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListGroupsRequest`.
50
+ * Add `parent` field for `databricks.sdk.service.iamv2.ListServicePrincipalsProxyRequest`.
51
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListServicePrincipalsRequest`.
52
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListTransitiveParentGroupsProxyRequest`.
53
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListTransitiveParentGroupsRequest`.
54
+ * Add `parent` field for `databricks.sdk.service.iamv2.ListUsersProxyRequest`.
55
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListUsersRequest`.
56
+ * Add `parent` field for `databricks.sdk.service.iamv2.ListWorkspaceAssignmentsProxyRequest`.
57
+ * [Breaking] Add `parent` field for `databricks.sdk.service.iamv2.ListWorkspaceAssignmentsRequest`.
58
+ * Add `name` and `parent` fields for `databricks.sdk.service.iamv2.ServicePrincipal`.
59
+ * Add `name` field for `databricks.sdk.service.iamv2.TransitiveParentGroup`.
60
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateGroupProxyRequest`.
61
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateGroupRequest`.
62
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateServicePrincipalProxyRequest`.
63
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateServicePrincipalRequest`.
64
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateUserProxyRequest`.
65
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateUserRequest`.
66
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateWorkspaceAssignmentProxyRequest`.
67
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateWorkspaceAssignmentRequest`.
68
+ * [Breaking] Add `name` field for `databricks.sdk.service.iamv2.UpdateWorkspaceIdentityDetailRequest`.
69
+ * Add `name` and `parent` fields for `databricks.sdk.service.iamv2.User`.
70
+ * Add `name` field for `databricks.sdk.service.iamv2.WorkspaceAccessDetail`.
71
+ * Add `name` and `parent` fields for `databricks.sdk.service.iamv2.WorkspaceAssignment`.
72
+ * Add `name` field for `databricks.sdk.service.iamv2.WorkspaceIdentityDetail`.
73
+ * Add `serverless_compute` field for `databricks.sdk.service.jobs.JobCluster`.
74
+ * Add `job_completion` field for `databricks.sdk.service.jobs.PerTriggerState`.
75
+ * Add `ai_function_task` field for `databricks.sdk.service.jobs.ResolvedValues`.
76
+ * Add `ai_function_task_output` field for `databricks.sdk.service.jobs.RunOutput`.
77
+ * Add `ai_function_task` field for `databricks.sdk.service.jobs.RunTask`.
78
+ * Add `ai_function_task` field for `databricks.sdk.service.jobs.SubmitTask`.
79
+ * Add `ai_function_task` field for `databricks.sdk.service.jobs.Task`.
80
+ * Add `job_completion` field for `databricks.sdk.service.jobs.TriggerConfiguration`.
81
+ * Add `job_completion` field for `databricks.sdk.service.jobs.TriggerInfo`.
82
+ * Add `job_completion` field for `databricks.sdk.service.jobs.TriggerSettings`.
83
+ * Add `job_completion` field for `databricks.sdk.service.jobs.TriggerStateProto`.
84
+ * Add `billing_workspace_id` field for `databricks.sdk.service.settings.NetworkConnectivityConfiguration`.
85
+ * Add `create_feature` and `read_feature` enum values for `databricks.sdk.service.catalog.Privilege`.
86
+ * Add `feature` enum value for `databricks.sdk.service.catalog.SecurableType`.
87
+ * Add `job_completion` enum value for `databricks.sdk.service.jobs.TriggerType`.
88
+ * [Breaking] Change `create_direct_group_member()`, `create_group()`, `create_service_principal()`, `create_user()`, `create_workspace_assignment()`, `delete_direct_group_member()`, `delete_group()`, `delete_service_principal()`, `delete_user()`, `delete_workspace_assignment()`, `get_direct_group_member()`, `get_group()`, `get_service_principal()`, `get_user()`, `get_workspace_access_detail()`, `get_workspace_assignment()`, `list_direct_group_members()`, `list_groups()`, `list_service_principals()`, `list_transitive_parent_groups()`, `list_users()`, `list_workspace_assignments()`, `update_group()`, `update_service_principal()`, `update_user()` and `update_workspace_assignment()` methods for [a.account_iam_v2](https://databricks-sdk-py.readthedocs.io/en/latest/account/iamv2/account_iam_v2.html) account-level service with new required argument order.
89
+ * [Breaking] Change `create_direct_group_member()`, `create_group()`, `create_service_principal()`, `create_user()`, `create_workspace_assignment()`, `delete_direct_group_member()`, `delete_group()`, `delete_service_principal()`, `delete_user()`, `delete_workspace_assignment()`, `get_direct_group_member()`, `get_group()`, `get_service_principal()`, `get_user()`, `get_workspace_access_detail()`, `get_workspace_assignment()`, `list_direct_group_members()`, `list_groups()`, `list_service_principals()`, `list_transitive_parent_groups()`, `list_users()`, `list_workspace_assignments()`, `update_group()`, `update_service_principal()`, `update_user()` and `update_workspace_assignment()` methods for [a.account_iam_v2](https://databricks-sdk-py.readthedocs.io/en/latest/account/iamv2/account_iam_v2.html) account-level service. Method path has changed.
90
+ * [Breaking] Change `create_direct_group_member_proxy()`, `delete_direct_group_member_proxy()`, `delete_group_proxy()`, `delete_service_principal_proxy()`, `delete_user_proxy()`, `delete_workspace_assignment_proxy()`, `get_direct_group_member_proxy()`, `get_group_proxy()`, `get_service_principal_proxy()`, `get_user_proxy()`, `get_workspace_access_detail_local()`, `get_workspace_assignment_proxy()`, `get_workspace_identity_detail()`, `list_direct_group_members_proxy()`, `list_transitive_parent_groups_proxy()`, `update_group_proxy()`, `update_service_principal_proxy()`, `update_user_proxy()`, `update_workspace_assignment_proxy()` and `update_workspace_identity_detail()` methods for [w.workspace_iam_v2](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/iamv2/workspace_iam_v2.html) workspace-level service. Method path has changed.
91
+ * [Breaking] Change `create_direct_group_member_proxy()`, `delete_direct_group_member_proxy()`, `delete_group_proxy()`, `delete_service_principal_proxy()`, `delete_user_proxy()`, `delete_workspace_assignment_proxy()`, `get_direct_group_member_proxy()`, `get_group_proxy()`, `get_service_principal_proxy()`, `get_user_proxy()`, `get_workspace_access_detail_local()`, `get_workspace_assignment_proxy()`, `get_workspace_identity_detail()`, `list_direct_group_members_proxy()`, `list_transitive_parent_groups_proxy()`, `update_group_proxy()`, `update_service_principal_proxy()`, `update_user_proxy()`, `update_workspace_assignment_proxy()` and `update_workspace_identity_detail()` methods for [w.workspace_iam_v2](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/iamv2/workspace_iam_v2.html) workspace-level service with new required argument order.
92
+ * [Breaking] Remove `group_id` field for `databricks.sdk.service.iamv2.CreateDirectGroupMemberProxyRequest`.
93
+ * [Breaking] Remove `account_id` and `group_id` fields for `databricks.sdk.service.iamv2.CreateDirectGroupMemberRequest`.
94
+ * [Breaking] Remove `account_id` field for `databricks.sdk.service.iamv2.CreateGroupRequest`.
95
+ * [Breaking] Remove `account_id` field for `databricks.sdk.service.iamv2.CreateServicePrincipalRequest`.
96
+ * [Breaking] Remove `account_id` field for `databricks.sdk.service.iamv2.CreateUserRequest`.
97
+ * [Breaking] Remove `account_id` and `workspace_id` fields for `databricks.sdk.service.iamv2.CreateWorkspaceAssignmentRequest`.
98
+ * [Breaking] Remove `group_id` and `principal_id` fields for `databricks.sdk.service.iamv2.DeleteDirectGroupMemberProxyRequest`.
99
+ * [Breaking] Remove `account_id`, `group_id` and `principal_id` fields for `databricks.sdk.service.iamv2.DeleteDirectGroupMemberRequest`.
100
+ * [Breaking] Remove `group_id` field for `databricks.sdk.service.iamv2.DeleteGroupProxyRequest`.
101
+ * [Breaking] Remove `account_id` and `group_id` fields for `databricks.sdk.service.iamv2.DeleteGroupRequest`.
102
+ * [Breaking] Remove `service_principal_id` field for `databricks.sdk.service.iamv2.DeleteServicePrincipalProxyRequest`.
103
+ * [Breaking] Remove `account_id` and `service_principal_id` fields for `databricks.sdk.service.iamv2.DeleteServicePrincipalRequest`.
104
+ * [Breaking] Remove `user_id` field for `databricks.sdk.service.iamv2.DeleteUserProxyRequest`.
105
+ * [Breaking] Remove `account_id` and `user_id` fields for `databricks.sdk.service.iamv2.DeleteUserRequest`.
106
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.DeleteWorkspaceAssignmentProxyRequest`.
107
+ * [Breaking] Remove `account_id`, `workspace_id` and `principal_id` fields for `databricks.sdk.service.iamv2.DeleteWorkspaceAssignmentRequest`.
108
+ * [Breaking] Remove `group_id` and `principal_id` fields for `databricks.sdk.service.iamv2.GetDirectGroupMemberProxyRequest`.
109
+ * [Breaking] Remove `account_id`, `group_id` and `principal_id` fields for `databricks.sdk.service.iamv2.GetDirectGroupMemberRequest`.
110
+ * [Breaking] Remove `group_id` field for `databricks.sdk.service.iamv2.GetGroupProxyRequest`.
111
+ * [Breaking] Remove `account_id` and `group_id` fields for `databricks.sdk.service.iamv2.GetGroupRequest`.
112
+ * [Breaking] Remove `service_principal_id` field for `databricks.sdk.service.iamv2.GetServicePrincipalProxyRequest`.
113
+ * [Breaking] Remove `account_id` and `service_principal_id` fields for `databricks.sdk.service.iamv2.GetServicePrincipalRequest`.
114
+ * [Breaking] Remove `user_id` field for `databricks.sdk.service.iamv2.GetUserProxyRequest`.
115
+ * [Breaking] Remove `account_id` and `user_id` fields for `databricks.sdk.service.iamv2.GetUserRequest`.
116
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.GetWorkspaceAccessDetailLocalRequest`.
117
+ * [Breaking] Remove `account_id`, `workspace_id` and `principal_id` fields for `databricks.sdk.service.iamv2.GetWorkspaceAccessDetailRequest`.
118
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.GetWorkspaceAssignmentProxyRequest`.
119
+ * [Breaking] Remove `account_id`, `workspace_id` and `principal_id` fields for `databricks.sdk.service.iamv2.GetWorkspaceAssignmentRequest`.
120
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.GetWorkspaceIdentityDetailRequest`.
121
+ * [Breaking] Remove `group_id` field for `databricks.sdk.service.iamv2.ListDirectGroupMembersProxyRequest`.
122
+ * [Breaking] Remove `account_id` and `group_id` fields for `databricks.sdk.service.iamv2.ListDirectGroupMembersRequest`.
123
+ * [Breaking] Remove `account_id` field for `databricks.sdk.service.iamv2.ListGroupsRequest`.
124
+ * [Breaking] Remove `account_id` field for `databricks.sdk.service.iamv2.ListServicePrincipalsRequest`.
125
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.ListTransitiveParentGroupsProxyRequest`.
126
+ * [Breaking] Remove `account_id` and `principal_id` fields for `databricks.sdk.service.iamv2.ListTransitiveParentGroupsRequest`.
127
+ * [Breaking] Remove `account_id` field for `databricks.sdk.service.iamv2.ListUsersRequest`.
128
+ * [Breaking] Remove `account_id` and `workspace_id` fields for `databricks.sdk.service.iamv2.ListWorkspaceAssignmentsRequest`.
129
+ * [Breaking] Remove `group_id` field for `databricks.sdk.service.iamv2.UpdateGroupProxyRequest`.
130
+ * [Breaking] Remove `account_id` and `group_id` fields for `databricks.sdk.service.iamv2.UpdateGroupRequest`.
131
+ * [Breaking] Remove `service_principal_id` field for `databricks.sdk.service.iamv2.UpdateServicePrincipalProxyRequest`.
132
+ * [Breaking] Remove `account_id` and `service_principal_id` fields for `databricks.sdk.service.iamv2.UpdateServicePrincipalRequest`.
133
+ * [Breaking] Remove `user_id` field for `databricks.sdk.service.iamv2.UpdateUserProxyRequest`.
134
+ * [Breaking] Remove `account_id` and `user_id` fields for `databricks.sdk.service.iamv2.UpdateUserRequest`.
135
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.UpdateWorkspaceAssignmentProxyRequest`.
136
+ * [Breaking] Remove `account_id`, `workspace_id` and `principal_id` fields for `databricks.sdk.service.iamv2.UpdateWorkspaceAssignmentRequest`.
137
+ * [Breaking] Remove `principal_id` field for `databricks.sdk.service.iamv2.UpdateWorkspaceIdentityDetailRequest`.
138
+
3
139
  ## Release v0.158.0 (2026-10-29)
4
140
 
5
141
  ### API Changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databricks-sdk
3
- Version: 0.158.0
3
+ Version: 0.159.0
4
4
  Summary: Databricks SDK for Python (Beta)
5
5
  Project-URL: Documentation, https://databricks-sdk-py.readthedocs.io
6
6
  Keywords: databricks,sdk
@@ -19,6 +19,7 @@ from databricks.sdk.service import bundledeployments as pkg_bundledeployments
19
19
  from databricks.sdk.service import catalog as pkg_catalog
20
20
  from databricks.sdk.service import cleanrooms as pkg_cleanrooms
21
21
  from databricks.sdk.service import compute as pkg_compute
22
+ from databricks.sdk.service import computemigrations as pkg_computemigrations
22
23
  from databricks.sdk.service import dashboards as pkg_dashboards
23
24
  from databricks.sdk.service import database as pkg_database
24
25
  from databricks.sdk.service import dataclassification as pkg_dataclassification
@@ -27,6 +28,7 @@ from databricks.sdk.service import disasterrecovery as pkg_disasterrecovery
27
28
  from databricks.sdk.service import domains as pkg_domains
28
29
  from databricks.sdk.service import environments as pkg_environments
29
30
  from databricks.sdk.service import files as pkg_files
31
+ from databricks.sdk.service import genieagents as pkg_genieagents
30
32
  from databricks.sdk.service import iam as pkg_iam
31
33
  from databricks.sdk.service import iamv2 as pkg_iamv2
32
34
  from databricks.sdk.service import jobs as pkg_jobs
@@ -88,6 +90,7 @@ from databricks.sdk.service.compute import ClusterPoliciesAPI
88
90
  from databricks.sdk.service.compute import ClustersAPI
89
91
  from databricks.sdk.service.compute import CommandExecutionAPI
90
92
  from databricks.sdk.service.settings import ComplianceSecurityProfileAPI
93
+ from databricks.sdk.service.computemigrations import ComputeMigrationsAPI
91
94
  from databricks.sdk.service.catalog import ConnectionsAPI
92
95
  from databricks.sdk.service.marketplace import ConsumerFulfillmentsAPI
93
96
  from databricks.sdk.service.marketplace import ConsumerInstallationsAPI
@@ -137,6 +140,7 @@ from databricks.sdk.service.files import FilesAPI
137
140
  from databricks.sdk.service.ml import ForecastingAPI
138
141
  from databricks.sdk.service.catalog import FunctionsAPI
139
142
  from databricks.sdk.service.dashboards import GenieAPI
143
+ from databricks.sdk.service.genieagents import GenieAgentsAPI
140
144
  from databricks.sdk.service.workspace import GitCredentialsAPI
141
145
  from databricks.sdk.service.compute import GlobalInitScriptsAPI
142
146
  from databricks.sdk.service.catalog import GrantsAPI
@@ -389,6 +393,7 @@ class WorkspaceClient:
389
393
  self._cluster_policies = pkg_compute.ClusterPoliciesAPI(self._api_client)
390
394
  self._clusters = ClustersExt(self._api_client)
391
395
  self._command_execution = pkg_compute.CommandExecutionAPI(self._api_client)
396
+ self._compute_migrations = pkg_computemigrations.ComputeMigrationsAPI(self._api_client)
392
397
  self._connections = pkg_catalog.ConnectionsAPI(self._api_client)
393
398
  self._consumer_fulfillments = pkg_marketplace.ConsumerFulfillmentsAPI(self._api_client)
394
399
  self._consumer_installations = pkg_marketplace.ConsumerInstallationsAPI(self._api_client)
@@ -419,6 +424,7 @@ class WorkspaceClient:
419
424
  self._forecasting = pkg_ml.ForecastingAPI(self._api_client)
420
425
  self._functions = pkg_catalog.FunctionsAPI(self._api_client)
421
426
  self._genie = pkg_dashboards.GenieAPI(self._api_client)
427
+ self._genie_agents = pkg_genieagents.GenieAgentsAPI(self._api_client)
422
428
  self._git_credentials = pkg_workspace.GitCredentialsAPI(self._api_client)
423
429
  self._global_init_scripts = pkg_compute.GlobalInitScriptsAPI(self._api_client)
424
430
  self._grants = pkg_catalog.GrantsAPI(self._api_client)
@@ -642,6 +648,11 @@ class WorkspaceClient:
642
648
  """This API allows execution of Python, Scala, SQL, or R commands on running Databricks Clusters."""
643
649
  return self._command_execution
644
650
 
651
+ @property
652
+ def compute_migrations(self) -> pkg_computemigrations.ComputeMigrationsAPI:
653
+ """Manage migrations of Classic compute workloads to Serverless."""
654
+ return self._compute_migrations
655
+
645
656
  @property
646
657
  def connections(self) -> pkg_catalog.ConnectionsAPI:
647
658
  """A connection represents an external data source for use within Databricks."""
@@ -787,6 +798,11 @@ class WorkspaceClient:
787
798
  """Genie provides a no-code experience for business users, powered by AI/BI."""
788
799
  return self._genie
789
800
 
801
+ @property
802
+ def genie_agents(self) -> pkg_genieagents.GenieAgentsAPI:
803
+ """Genie provides a no-code experience for business users, powered by AI/BI."""
804
+ return self._genie_agents
805
+
790
806
  @property
791
807
  def git_credentials(self) -> pkg_workspace.GitCredentialsAPI:
792
808
  """Registers personal access token for Databricks to do operations on behalf of the user."""
@@ -179,7 +179,7 @@ class Config:
179
179
  # File multipart upload/download parameters
180
180
  # ----------------------
181
181
 
182
- # Minimal input stream size (bytes) to use multipart / resumable uploads.
182
+ # Minimal input stream size (bytes) to use multipart uploads.
183
183
  # For small files it's more efficient to make one single-shot upload request.
184
184
  # When uploading a file, SDK will initially buffer this many bytes from input stream.
185
185
  # This parameter can be less or bigger than multipart_upload_chunk_size.
@@ -247,12 +247,9 @@ class Config:
247
247
  # but a maximum time between consecutive data reception events (even 1 byte) from the server
248
248
  files_ext_network_transfer_inactivity_timeout_seconds: float = 60
249
249
 
250
- # Cap on the number of custom retries during incremental uploads:
251
- # 1) multipart: upload part URL is expired, so new upload URLs must be requested to continue upload
252
- # 2) resumable: chunk upload produced a retryable response (or exception), so upload status must be
253
- # retrieved to continue the upload.
254
- # In these two cases standard SDK retries (which are capped by the `retry_timeout_seconds` option) are not used.
255
- # Note that retry counter is reset when upload is successfully resumed.
250
+ # Cap on the number of custom retries during multipart uploads, when an upload part URL is expired and new
251
+ # upload URLs must be requested to continue the upload. Standard SDK retries (capped by the
252
+ # `retry_timeout_seconds` option) are not used in this case.
256
253
  files_ext_multipart_upload_max_retries = 3
257
254
 
258
255
  # Cap on the number of custom retries during parallel downloads.
@@ -7,7 +7,6 @@ import math
7
7
  import os
8
8
  import pathlib
9
9
  import platform
10
- import re
11
10
  import shutil
12
11
  import xml.etree.ElementTree as ET
13
12
  from abc import ABC, abstractmethod
@@ -32,7 +31,7 @@ from requests import RequestException
32
31
  from .._base_client import _BaseClient, _RawResponse, _StreamingResponse
33
32
  from .._property import _cached_property
34
33
  from ..config import Config
35
- from ..errors import AlreadyExists, InternalError, NotFound, PermissionDenied
34
+ from ..errors import InternalError, NotFound, PermissionDenied
36
35
  from ..errors.mapper import _error_mapper
37
36
  from ..retries import retried
38
37
  from databricks.sdk.service import files
@@ -779,8 +778,8 @@ class _Endpoint:
779
778
  class _PresignedUrlRequestBuilder:
780
779
  """Builds presigned URL requests for file upload operations.
781
780
 
782
- Encapsulates the coordination API calls (create-upload-part-urls,
783
- create-resumable-upload-url) and response parsing into a single place.
781
+ Encapsulates the coordination API calls (create-upload-part-urls, create-download-url) and response parsing
782
+ into a single place.
784
783
  """
785
784
 
786
785
  def __init__(self, api, hostname: str):
@@ -817,27 +816,6 @@ class _PresignedUrlRequestBuilder:
817
816
  results.append(_PresignedUrl(url=url, headers=headers, part_number=part_number))
818
817
  return results
819
818
 
820
- def build_resumable_upload_url(self, path: str, session_token: str) -> _PresignedUrl:
821
- """Fetches a presigned URL for resumable upload."""
822
- body = {"path": path, "session_token": session_token}
823
- # The _api.do() method handles retries and will raise an exception in case of failure.
824
- response = self._api.do(
825
- "POST",
826
- url=f"{self._hostname}/api/2.0/fs/create-resumable-upload-url",
827
- headers={"Content-Type": "application/json"},
828
- body=body,
829
- )
830
- url_node = response.get("resumable_upload_url")
831
- if not url_node:
832
- raise ValueError(f"Unexpected server response: {response}")
833
- url = url_node.get("url")
834
- if not url:
835
- raise ValueError(f"Unexpected server response: {response}")
836
- headers: dict[str, str] = {}
837
- for h in url_node.get("headers", []):
838
- headers[h["name"]] = h["value"]
839
- return _PresignedUrl(url=url, headers=headers)
840
-
841
819
  def build_download_url(self, path: str, expire_time: str) -> CreateDownloadUrlResponse:
842
820
  """Fetches a presigned URL for downloading a file."""
843
821
  response = self._api.do(
@@ -888,21 +866,6 @@ class _StorageProxyRequestBuilder:
888
866
  )
889
867
  return results
890
868
 
891
- def build_resumable_upload_url(self, path: str, session_token: str) -> _PresignedUrl:
892
- """Builds a URL for resumable upload directly to the storage proxy."""
893
- escaped = _escape_multi_segment_path_parameter(path)
894
- base = f"{self._hostname}/api/2.0/fs/files{escaped}"
895
- query = parse.urlencode(
896
- {
897
- "session_token": session_token,
898
- "upload_type": "resumable",
899
- }
900
- )
901
- return _PresignedUrl(
902
- url=f"{base}?{query}",
903
- headers={"Content-Type": "application/octet-stream"},
904
- )
905
-
906
869
  def build_download_url(self, path: str, expire_time: str) -> CreateDownloadUrlResponse:
907
870
  """Builds a URL for downloading a file directly from the storage proxy."""
908
871
  escaped = _escape_multi_segment_path_parameter(path)
@@ -952,7 +915,6 @@ class FilesExt(files.FilesAPI):
952
915
  def __init__(self, api_client, config: Config):
953
916
  super().__init__(api_client)
954
917
  self._config = config.copy()
955
- self._multipart_upload_read_ahead_bytes = 1
956
918
  self._cached_cloud_provider_session: Optional[requests.Session] = None
957
919
  self._cloud_provider_session_lock = Lock()
958
920
  self._dp_hostname_available: Optional[bool] = None
@@ -1713,16 +1675,6 @@ class FilesExt(files.FilesAPI):
1713
1675
  # Rethrow the original exception
1714
1676
  raise e from None
1715
1677
 
1716
- elif initiate_upload_response.get("resumable_upload"):
1717
- session_token = initiate_upload_response["resumable_upload"]["session_token"]
1718
-
1719
- try:
1720
- self._perform_resumable_upload(ctx, contents, session_token, pre_read_buffer)
1721
- except FallbackToUploadUsingFilesApi as e:
1722
- _LOG.info(f"Falling back to single-shot upload with Files API: {e}")
1723
- # Concatenate the buffered part and the rest of the stream.
1724
- full_stream = _ConcatenatedInputStream(BytesIO(e.buffer), contents)
1725
- return self._single_thread_single_shot_upload(ctx, full_stream)
1726
1678
  else:
1727
1679
  raise ValueError(f"Unexpected server response: {initiate_upload_response}")
1728
1680
 
@@ -1734,10 +1686,7 @@ class FilesExt(files.FilesAPI):
1734
1686
  """
1735
1687
  initiate_upload_response = self._initiate_multipart_upload(ctx)
1736
1688
 
1737
- if initiate_upload_response.get("resumable_upload"):
1738
- _LOG.warning("GCP does not support parallel resumable uploads, falling back to single-threaded upload")
1739
- return self._single_thread_multipart_upload(ctx, contents)
1740
- elif initiate_upload_response.get("multipart_upload"):
1689
+ if initiate_upload_response.get("multipart_upload"):
1741
1690
  session_token = initiate_upload_response["multipart_upload"].get("session_token")
1742
1691
  if not session_token:
1743
1692
  raise ValueError(f"Unexpected server response: {initiate_upload_response}")
@@ -1803,10 +1752,6 @@ class FilesExt(files.FilesAPI):
1803
1752
  # Rethrow the original exception.
1804
1753
  raise e from None
1805
1754
 
1806
- elif initiate_upload_response.get("resumable_upload"):
1807
- _LOG.warning("GCP does not support parallel resumable uploads, falling back to single-threaded upload")
1808
- with open(ctx.source_file_path, "rb") as f:
1809
- return self._upload_single_thread_with_known_size(ctx, f)
1810
1755
  else:
1811
1756
  raise ValueError(f"Unexpected server response: {initiate_upload_response}")
1812
1757
 
@@ -2339,212 +2284,6 @@ class FilesExt(files.FilesAPI):
2339
2284
  return True
2340
2285
  return False
2341
2286
 
2342
- def _perform_resumable_upload(
2343
- self,
2344
- ctx: _UploadContext,
2345
- input_stream: BinaryIO,
2346
- session_token: str,
2347
- pre_read_buffer: bytes,
2348
- ) -> None:
2349
- """
2350
- Performs resumable upload on GCP: https://cloud.google.com/storage/docs/performing-resumable-uploads
2351
- """
2352
- # Session URI we're using expires after a week
2353
-
2354
- # Why are we buffering the current chunk?
2355
- # When using resumable upload API we're uploading data in chunks. During chunk upload
2356
- # server responds with the "received offset" confirming how much data it stored so far,
2357
- # so we should continue uploading from that offset. (Note this is not a failure but an
2358
- # expected behaviour as per the docs.) But, input stream might be consumed beyond that
2359
- # offset, since server might have read more data than it confirmed received, or some data
2360
- # might have been pre-cached by e.g. OS or a proxy. So, to continue upload, we must rewind
2361
- # the input stream back to the byte next to "received offset". This is not possible
2362
- # for non-seekable input stream, so we must buffer the whole last chunk and seek inside
2363
- # the buffer. By always uploading from the buffer we fully support non-seekable streams.
2364
-
2365
- # Why are we doing read-ahead?
2366
- # It's not possible to upload an empty chunk as "Content-Range" header format does not
2367
- # support this. So if current chunk happens to finish exactly at the end of the stream,
2368
- # we need to know that and mark the chunk as last (by passing real file size in the
2369
- # "Content-Range" header) when uploading it. To detect if we're at the end of the stream
2370
- # we're reading "ahead" an extra bytes but not uploading them immediately. If
2371
- # nothing has been read ahead, it means we're at the end of the stream.
2372
- # On the contrary, in multipart upload we can decide to complete upload *after*
2373
- # last chunk has been sent.
2374
-
2375
- builder = self._create_request_builder()
2376
-
2377
- try:
2378
- presigned = builder.build_resumable_upload_url(ctx.target_path, session_token)
2379
- except Exception as e:
2380
- raise FallbackToUploadUsingFilesApi(
2381
- pre_read_buffer, f"Failed to obtain resumable upload URL: {e}, falling back to single shot upload"
2382
- ) from e
2383
-
2384
- resumable_upload_url = presigned.url
2385
- base_headers = presigned.headers
2386
-
2387
- try:
2388
- # We will buffer this many bytes: one chunk + read-ahead block.
2389
- # Note buffer may contain more data initially (from pre_read_buffer).
2390
- min_buffer_size = ctx.part_size + self._multipart_upload_read_ahead_bytes
2391
-
2392
- buffer = pre_read_buffer
2393
-
2394
- # How many bytes in the buffer were confirmed to be received by the server.
2395
- # All the remaining bytes in the buffer must be uploaded.
2396
- uploaded_bytes_count = 0
2397
-
2398
- chunk_offset = 0
2399
-
2400
- retry_count = 0
2401
- while True:
2402
- # If needed, fill the buffer to contain at least min_buffer_size bytes
2403
- # (unless end of stream), discarding already uploaded bytes.
2404
- bytes_to_read = max(0, min_buffer_size - (len(buffer) - uploaded_bytes_count))
2405
- next_buf = input_stream.read(bytes_to_read)
2406
- buffer = buffer[uploaded_bytes_count:] + next_buf
2407
-
2408
- if len(next_buf) < bytes_to_read:
2409
- # This is the last chunk in the stream.
2410
- # Let's upload all the remaining bytes in one go.
2411
- actual_chunk_length = len(buffer)
2412
- file_size = chunk_offset + actual_chunk_length
2413
- else:
2414
- # More chunks expected, let's upload current chunk (excluding read-ahead block).
2415
- actual_chunk_length = ctx.part_size
2416
- file_size = "*"
2417
-
2418
- headers: dict = {"Content-Type": "application/octet-stream", **base_headers}
2419
-
2420
- chunk_last_byte_offset = chunk_offset + actual_chunk_length - 1
2421
- content_range_header = f"bytes {chunk_offset}-{chunk_last_byte_offset}/{file_size}"
2422
- _LOG.debug(f"Uploading chunk: {content_range_header}")
2423
- headers["Content-Range"] = content_range_header
2424
-
2425
- def retrieve_upload_status() -> Optional[requests.Response]:
2426
- def perform():
2427
- return self._cloud_provider_session().request(
2428
- "PUT",
2429
- resumable_upload_url,
2430
- headers={"Content-Range": "bytes */*"},
2431
- data=b"",
2432
- timeout=self._config.files_ext_network_transfer_inactivity_timeout_seconds,
2433
- )
2434
-
2435
- try:
2436
- return self._retry_cloud_idempotent_operation(perform)
2437
- except RequestException:
2438
- _LOG.warning("Failed to retrieve upload status")
2439
- return None
2440
-
2441
- try:
2442
- upload_response = self._cloud_provider_session().request(
2443
- "PUT",
2444
- resumable_upload_url,
2445
- headers=headers,
2446
- data=BytesIO(buffer[:actual_chunk_length]),
2447
- timeout=self._config.files_ext_network_transfer_inactivity_timeout_seconds,
2448
- )
2449
-
2450
- # https://cloud.google.com/storage/docs/performing-resumable-uploads#resume-upload
2451
- # If an upload request is terminated before receiving a response, or if you receive
2452
- # a 503 or 500 response, then you need to resume the interrupted upload from where it left off.
2453
-
2454
- # Let's follow that for all potentially retryable status codes.
2455
- if upload_response.status_code in self._RETRYABLE_STATUS_CODES:
2456
- if retry_count < self._config.files_ext_multipart_upload_max_retries:
2457
- retry_count += 1
2458
- # let original upload_response be handled as an error
2459
- upload_response = retrieve_upload_status() or upload_response
2460
- else:
2461
- # we received non-retryable response, reset retry count
2462
- retry_count = 0
2463
-
2464
- except RequestException as e:
2465
- # Let's do the same for retryable network errors.
2466
- if (
2467
- _BaseClient._is_retryable(e)
2468
- and retry_count < self._config.files_ext_multipart_upload_max_retries
2469
- ):
2470
- retry_count += 1
2471
- upload_response = retrieve_upload_status()
2472
- if not upload_response:
2473
- # rethrow original exception
2474
- raise e from None
2475
- else:
2476
- # rethrow original exception
2477
- raise e from None
2478
-
2479
- if upload_response.status_code in (200, 201):
2480
- if file_size == "*":
2481
- raise ValueError(
2482
- f"Received unexpected status {upload_response.status_code} before reaching end of stream"
2483
- )
2484
-
2485
- # upload complete
2486
- break
2487
-
2488
- elif upload_response.status_code == 308:
2489
- # chunk accepted (or check-status succeeded), let's determine received offset to resume from there
2490
- range_string = upload_response.headers.get("Range")
2491
- confirmed_offset = self._extract_range_offset(range_string)
2492
- _LOG.debug(f"Received confirmed offset: {confirmed_offset}")
2493
-
2494
- if confirmed_offset:
2495
- if confirmed_offset < chunk_offset - 1 or confirmed_offset > chunk_last_byte_offset:
2496
- raise ValueError(
2497
- f"Unexpected received offset: {confirmed_offset} is outside of expected range, chunk offset: {chunk_offset}, chunk last byte offset: {chunk_last_byte_offset}"
2498
- )
2499
- else:
2500
- if chunk_offset > 0:
2501
- raise ValueError(
2502
- f"Unexpected received offset: {confirmed_offset} is outside of expected range, chunk offset: {chunk_offset}, chunk last byte offset: {chunk_last_byte_offset}"
2503
- )
2504
-
2505
- # We have just uploaded a part of chunk starting from offset "chunk_offset" and ending
2506
- # at offset "confirmed_offset" (inclusive), so the next chunk will start at
2507
- # offset "confirmed_offset + 1"
2508
- if confirmed_offset:
2509
- next_chunk_offset = confirmed_offset + 1
2510
- else:
2511
- next_chunk_offset = chunk_offset
2512
- uploaded_bytes_count = next_chunk_offset - chunk_offset
2513
- chunk_offset = next_chunk_offset
2514
-
2515
- elif upload_response.status_code == 412 and not ctx.overwrite:
2516
- # Assuming this is only possible reason
2517
- # Full message in this case: "At least one of the pre-conditions you specified did not hold."
2518
- raise AlreadyExists("The file being created already exists.")
2519
-
2520
- else:
2521
- message = f"Unsuccessful chunk upload. Response status: {upload_response.status_code}, body: {upload_response.content}"
2522
- _LOG.warning(message)
2523
- mapped_error = _error_mapper(upload_response, {})
2524
- raise mapped_error or ValueError(message)
2525
-
2526
- except Exception as e:
2527
- _LOG.info(f"Aborting resumable upload on error: {e}")
2528
- try:
2529
- self._abort_resumable_upload(resumable_upload_url, base_headers)
2530
- except BaseException as ex:
2531
- _LOG.warning(f"Failed to abort upload: {ex}")
2532
- # ignore, abort is a best-effort
2533
- finally:
2534
- # rethrow original exception
2535
- raise e from None
2536
-
2537
- @staticmethod
2538
- def _extract_range_offset(range_string: Optional[str]) -> Optional[int]:
2539
- """Parses the response range header to extract the last byte."""
2540
- if not range_string:
2541
- return None # server did not yet confirm any bytes
2542
-
2543
- if match := re.match("bytes=0-(\\d+)", range_string):
2544
- return int(match.group(1))
2545
- else:
2546
- raise ValueError(f"Cannot parse response header: Range: {range_string}")
2547
-
2548
2287
  def _get_rfc339_timestamp_with_future_offset(self, base_time: datetime.datetime, offset: timedelta) -> str:
2549
2288
  """Generates an offset timestamp in an RFC3339 format suitable for URL generation"""
2550
2289
  offset_timestamp = base_time + offset
@@ -2584,19 +2323,6 @@ class FilesExt(files.FilesAPI):
2584
2323
  if not abort_response.ok:
2585
2324
  raise ValueError(abort_response)
2586
2325
 
2587
- def _abort_resumable_upload(self, resumable_upload_url: str, headers: dict[str, str]) -> None:
2588
- """Aborts ongoing resumable upload session to clean up incomplete file. Best-effort, so sent once."""
2589
- abort_response = self._cloud_provider_session().request(
2590
- "DELETE",
2591
- resumable_upload_url,
2592
- headers=headers,
2593
- data=b"",
2594
- timeout=self._config.files_ext_network_transfer_inactivity_timeout_seconds,
2595
- )
2596
-
2597
- if abort_response.status_code not in (200, 201):
2598
- raise ValueError(abort_response)
2599
-
2600
2326
  def _cloud_provider_session(self) -> requests.Session:
2601
2327
  """Returns a session for cloud storage operations.
2602
2328
 
@@ -195,8 +195,9 @@ class AlertSpendStatus:
195
195
  percent_consumed: Optional[str] = None
196
196
  """Percentage of the threshold consumed, as a decimal string rounded down to one decimal place (for
197
197
  example, "68.4" means 68.4%). May exceed 100 when spend is over the threshold. Returns "0.0" if
198
- there's no spend, and is omitted if the threshold is $0. For shared thresholds, this is the only
199
- value returned; the absolute ``spend`` and ``threshold`` dollar amounts are withheld."""
198
+ there's no spend, except that a $0 threshold always returns "100.0". For shared thresholds, this
199
+ is the only value returned; the absolute ``spend`` and ``threshold`` dollar amounts are
200
+ withheld."""
200
201
 
201
202
  scope_type: Optional[AlertConfigurationScopeType] = None
202
203
  """Whether the threshold is evaluated per individual user