databricks-sdk 0.44.1__py3-none-any.whl → 0.46.0__py3-none-any.whl

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.

Potentially problematic release.


This version of databricks-sdk might be problematic. Click here for more details.

Files changed (63) hide show
  1. databricks/sdk/__init__.py +135 -116
  2. databricks/sdk/_base_client.py +112 -88
  3. databricks/sdk/_property.py +12 -7
  4. databricks/sdk/_widgets/__init__.py +13 -2
  5. databricks/sdk/_widgets/default_widgets_utils.py +21 -15
  6. databricks/sdk/_widgets/ipywidgets_utils.py +47 -24
  7. databricks/sdk/azure.py +8 -6
  8. databricks/sdk/casing.py +5 -5
  9. databricks/sdk/config.py +156 -99
  10. databricks/sdk/core.py +57 -47
  11. databricks/sdk/credentials_provider.py +306 -206
  12. databricks/sdk/data_plane.py +75 -50
  13. databricks/sdk/dbutils.py +123 -87
  14. databricks/sdk/environments.py +52 -35
  15. databricks/sdk/errors/base.py +61 -35
  16. databricks/sdk/errors/customizer.py +3 -3
  17. databricks/sdk/errors/deserializer.py +38 -25
  18. databricks/sdk/errors/details.py +417 -0
  19. databricks/sdk/errors/mapper.py +1 -1
  20. databricks/sdk/errors/overrides.py +27 -24
  21. databricks/sdk/errors/parser.py +26 -14
  22. databricks/sdk/errors/platform.py +10 -10
  23. databricks/sdk/errors/private_link.py +24 -24
  24. databricks/sdk/logger/round_trip_logger.py +28 -20
  25. databricks/sdk/mixins/compute.py +90 -60
  26. databricks/sdk/mixins/files.py +815 -145
  27. databricks/sdk/mixins/jobs.py +191 -16
  28. databricks/sdk/mixins/open_ai_client.py +26 -20
  29. databricks/sdk/mixins/workspace.py +45 -34
  30. databricks/sdk/oauth.py +379 -198
  31. databricks/sdk/retries.py +14 -12
  32. databricks/sdk/runtime/__init__.py +34 -17
  33. databricks/sdk/runtime/dbutils_stub.py +52 -39
  34. databricks/sdk/service/_internal.py +12 -7
  35. databricks/sdk/service/apps.py +618 -418
  36. databricks/sdk/service/billing.py +827 -604
  37. databricks/sdk/service/catalog.py +6552 -4474
  38. databricks/sdk/service/cleanrooms.py +550 -388
  39. databricks/sdk/service/compute.py +5263 -3536
  40. databricks/sdk/service/dashboards.py +1331 -924
  41. databricks/sdk/service/files.py +446 -309
  42. databricks/sdk/service/iam.py +2115 -1483
  43. databricks/sdk/service/jobs.py +4151 -2588
  44. databricks/sdk/service/marketplace.py +2210 -1517
  45. databricks/sdk/service/ml.py +3839 -2256
  46. databricks/sdk/service/oauth2.py +910 -584
  47. databricks/sdk/service/pipelines.py +1865 -1203
  48. databricks/sdk/service/provisioning.py +1435 -1029
  49. databricks/sdk/service/serving.py +2060 -1290
  50. databricks/sdk/service/settings.py +2846 -1929
  51. databricks/sdk/service/sharing.py +2201 -877
  52. databricks/sdk/service/sql.py +4650 -3103
  53. databricks/sdk/service/vectorsearch.py +816 -550
  54. databricks/sdk/service/workspace.py +1330 -906
  55. databricks/sdk/useragent.py +36 -22
  56. databricks/sdk/version.py +1 -1
  57. {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/METADATA +31 -31
  58. databricks_sdk-0.46.0.dist-info/RECORD +70 -0
  59. {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/WHEEL +1 -1
  60. databricks_sdk-0.44.1.dist-info/RECORD +0 -69
  61. {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/LICENSE +0 -0
  62. {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/NOTICE +0 -0
  63. {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/top_level.txt +0 -0
@@ -4,11 +4,12 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
  from dataclasses import dataclass
7
- from typing import BinaryIO, Dict, Iterator, List, Optional
7
+ from typing import Any, BinaryIO, Dict, Iterator, List, Optional
8
8
 
9
9
  from ._internal import _escape_multi_segment_path_parameter, _repeated_dict
10
10
 
11
- _LOG = logging.getLogger('databricks.sdk')
11
+ _LOG = logging.getLogger("databricks.sdk")
12
+
12
13
 
13
14
  # all definitions in this file are in alphabetical order
14
15
 
@@ -24,26 +25,29 @@ class AddBlock:
24
25
  def as_dict(self) -> dict:
25
26
  """Serializes the AddBlock into a dictionary suitable for use as a JSON request body."""
26
27
  body = {}
27
- if self.data is not None: body['data'] = self.data
28
- if self.handle is not None: body['handle'] = self.handle
28
+ if self.data is not None:
29
+ body["data"] = self.data
30
+ if self.handle is not None:
31
+ body["handle"] = self.handle
29
32
  return body
30
33
 
31
34
  def as_shallow_dict(self) -> dict:
32
35
  """Serializes the AddBlock into a shallow dictionary of its immediate attributes."""
33
36
  body = {}
34
- if self.data is not None: body['data'] = self.data
35
- if self.handle is not None: body['handle'] = self.handle
37
+ if self.data is not None:
38
+ body["data"] = self.data
39
+ if self.handle is not None:
40
+ body["handle"] = self.handle
36
41
  return body
37
42
 
38
43
  @classmethod
39
- def from_dict(cls, d: Dict[str, any]) -> AddBlock:
44
+ def from_dict(cls, d: Dict[str, Any]) -> AddBlock:
40
45
  """Deserializes the AddBlock from a dictionary."""
41
- return cls(data=d.get('data', None), handle=d.get('handle', None))
46
+ return cls(data=d.get("data", None), handle=d.get("handle", None))
42
47
 
43
48
 
44
49
  @dataclass
45
50
  class AddBlockResponse:
46
-
47
51
  def as_dict(self) -> dict:
48
52
  """Serializes the AddBlockResponse into a dictionary suitable for use as a JSON request body."""
49
53
  body = {}
@@ -55,7 +59,7 @@ class AddBlockResponse:
55
59
  return body
56
60
 
57
61
  @classmethod
58
- def from_dict(cls, d: Dict[str, any]) -> AddBlockResponse:
62
+ def from_dict(cls, d: Dict[str, Any]) -> AddBlockResponse:
59
63
  """Deserializes the AddBlockResponse from a dictionary."""
60
64
  return cls()
61
65
 
@@ -68,24 +72,25 @@ class Close:
68
72
  def as_dict(self) -> dict:
69
73
  """Serializes the Close into a dictionary suitable for use as a JSON request body."""
70
74
  body = {}
71
- if self.handle is not None: body['handle'] = self.handle
75
+ if self.handle is not None:
76
+ body["handle"] = self.handle
72
77
  return body
73
78
 
74
79
  def as_shallow_dict(self) -> dict:
75
80
  """Serializes the Close into a shallow dictionary of its immediate attributes."""
76
81
  body = {}
77
- if self.handle is not None: body['handle'] = self.handle
82
+ if self.handle is not None:
83
+ body["handle"] = self.handle
78
84
  return body
79
85
 
80
86
  @classmethod
81
- def from_dict(cls, d: Dict[str, any]) -> Close:
87
+ def from_dict(cls, d: Dict[str, Any]) -> Close:
82
88
  """Deserializes the Close from a dictionary."""
83
- return cls(handle=d.get('handle', None))
89
+ return cls(handle=d.get("handle", None))
84
90
 
85
91
 
86
92
  @dataclass
87
93
  class CloseResponse:
88
-
89
94
  def as_dict(self) -> dict:
90
95
  """Serializes the CloseResponse into a dictionary suitable for use as a JSON request body."""
91
96
  body = {}
@@ -97,7 +102,7 @@ class CloseResponse:
97
102
  return body
98
103
 
99
104
  @classmethod
100
- def from_dict(cls, d: Dict[str, any]) -> CloseResponse:
105
+ def from_dict(cls, d: Dict[str, Any]) -> CloseResponse:
101
106
  """Deserializes the CloseResponse from a dictionary."""
102
107
  return cls()
103
108
 
@@ -113,26 +118,29 @@ class Create:
113
118
  def as_dict(self) -> dict:
114
119
  """Serializes the Create into a dictionary suitable for use as a JSON request body."""
115
120
  body = {}
116
- if self.overwrite is not None: body['overwrite'] = self.overwrite
117
- if self.path is not None: body['path'] = self.path
121
+ if self.overwrite is not None:
122
+ body["overwrite"] = self.overwrite
123
+ if self.path is not None:
124
+ body["path"] = self.path
118
125
  return body
119
126
 
120
127
  def as_shallow_dict(self) -> dict:
121
128
  """Serializes the Create into a shallow dictionary of its immediate attributes."""
122
129
  body = {}
123
- if self.overwrite is not None: body['overwrite'] = self.overwrite
124
- if self.path is not None: body['path'] = self.path
130
+ if self.overwrite is not None:
131
+ body["overwrite"] = self.overwrite
132
+ if self.path is not None:
133
+ body["path"] = self.path
125
134
  return body
126
135
 
127
136
  @classmethod
128
- def from_dict(cls, d: Dict[str, any]) -> Create:
137
+ def from_dict(cls, d: Dict[str, Any]) -> Create:
129
138
  """Deserializes the Create from a dictionary."""
130
- return cls(overwrite=d.get('overwrite', None), path=d.get('path', None))
139
+ return cls(overwrite=d.get("overwrite", None), path=d.get("path", None))
131
140
 
132
141
 
133
142
  @dataclass
134
143
  class CreateDirectoryResponse:
135
-
136
144
  def as_dict(self) -> dict:
137
145
  """Serializes the CreateDirectoryResponse into a dictionary suitable for use as a JSON request body."""
138
146
  body = {}
@@ -144,7 +152,7 @@ class CreateDirectoryResponse:
144
152
  return body
145
153
 
146
154
  @classmethod
147
- def from_dict(cls, d: Dict[str, any]) -> CreateDirectoryResponse:
155
+ def from_dict(cls, d: Dict[str, Any]) -> CreateDirectoryResponse:
148
156
  """Deserializes the CreateDirectoryResponse from a dictionary."""
149
157
  return cls()
150
158
 
@@ -158,19 +166,21 @@ class CreateResponse:
158
166
  def as_dict(self) -> dict:
159
167
  """Serializes the CreateResponse into a dictionary suitable for use as a JSON request body."""
160
168
  body = {}
161
- if self.handle is not None: body['handle'] = self.handle
169
+ if self.handle is not None:
170
+ body["handle"] = self.handle
162
171
  return body
163
172
 
164
173
  def as_shallow_dict(self) -> dict:
165
174
  """Serializes the CreateResponse into a shallow dictionary of its immediate attributes."""
166
175
  body = {}
167
- if self.handle is not None: body['handle'] = self.handle
176
+ if self.handle is not None:
177
+ body["handle"] = self.handle
168
178
  return body
169
179
 
170
180
  @classmethod
171
- def from_dict(cls, d: Dict[str, any]) -> CreateResponse:
181
+ def from_dict(cls, d: Dict[str, Any]) -> CreateResponse:
172
182
  """Deserializes the CreateResponse from a dictionary."""
173
- return cls(handle=d.get('handle', None))
183
+ return cls(handle=d.get("handle", None))
174
184
 
175
185
 
176
186
  @dataclass
@@ -185,26 +195,29 @@ class Delete:
185
195
  def as_dict(self) -> dict:
186
196
  """Serializes the Delete into a dictionary suitable for use as a JSON request body."""
187
197
  body = {}
188
- if self.path is not None: body['path'] = self.path
189
- if self.recursive is not None: body['recursive'] = self.recursive
198
+ if self.path is not None:
199
+ body["path"] = self.path
200
+ if self.recursive is not None:
201
+ body["recursive"] = self.recursive
190
202
  return body
191
203
 
192
204
  def as_shallow_dict(self) -> dict:
193
205
  """Serializes the Delete into a shallow dictionary of its immediate attributes."""
194
206
  body = {}
195
- if self.path is not None: body['path'] = self.path
196
- if self.recursive is not None: body['recursive'] = self.recursive
207
+ if self.path is not None:
208
+ body["path"] = self.path
209
+ if self.recursive is not None:
210
+ body["recursive"] = self.recursive
197
211
  return body
198
212
 
199
213
  @classmethod
200
- def from_dict(cls, d: Dict[str, any]) -> Delete:
214
+ def from_dict(cls, d: Dict[str, Any]) -> Delete:
201
215
  """Deserializes the Delete from a dictionary."""
202
- return cls(path=d.get('path', None), recursive=d.get('recursive', None))
216
+ return cls(path=d.get("path", None), recursive=d.get("recursive", None))
203
217
 
204
218
 
205
219
  @dataclass
206
220
  class DeleteDirectoryResponse:
207
-
208
221
  def as_dict(self) -> dict:
209
222
  """Serializes the DeleteDirectoryResponse into a dictionary suitable for use as a JSON request body."""
210
223
  body = {}
@@ -216,14 +229,13 @@ class DeleteDirectoryResponse:
216
229
  return body
217
230
 
218
231
  @classmethod
219
- def from_dict(cls, d: Dict[str, any]) -> DeleteDirectoryResponse:
232
+ def from_dict(cls, d: Dict[str, Any]) -> DeleteDirectoryResponse:
220
233
  """Deserializes the DeleteDirectoryResponse from a dictionary."""
221
234
  return cls()
222
235
 
223
236
 
224
237
  @dataclass
225
238
  class DeleteResponse:
226
-
227
239
  def as_dict(self) -> dict:
228
240
  """Serializes the DeleteResponse into a dictionary suitable for use as a JSON request body."""
229
241
  body = {}
@@ -235,7 +247,7 @@ class DeleteResponse:
235
247
  return body
236
248
 
237
249
  @classmethod
238
- def from_dict(cls, d: Dict[str, any]) -> DeleteResponse:
250
+ def from_dict(cls, d: Dict[str, Any]) -> DeleteResponse:
239
251
  """Deserializes the DeleteResponse from a dictionary."""
240
252
  return cls()
241
253
 
@@ -260,68 +272,92 @@ class DirectoryEntry:
260
272
  def as_dict(self) -> dict:
261
273
  """Serializes the DirectoryEntry into a dictionary suitable for use as a JSON request body."""
262
274
  body = {}
263
- if self.file_size is not None: body['file_size'] = self.file_size
264
- if self.is_directory is not None: body['is_directory'] = self.is_directory
265
- if self.last_modified is not None: body['last_modified'] = self.last_modified
266
- if self.name is not None: body['name'] = self.name
267
- if self.path is not None: body['path'] = self.path
275
+ if self.file_size is not None:
276
+ body["file_size"] = self.file_size
277
+ if self.is_directory is not None:
278
+ body["is_directory"] = self.is_directory
279
+ if self.last_modified is not None:
280
+ body["last_modified"] = self.last_modified
281
+ if self.name is not None:
282
+ body["name"] = self.name
283
+ if self.path is not None:
284
+ body["path"] = self.path
268
285
  return body
269
286
 
270
287
  def as_shallow_dict(self) -> dict:
271
288
  """Serializes the DirectoryEntry into a shallow dictionary of its immediate attributes."""
272
289
  body = {}
273
- if self.file_size is not None: body['file_size'] = self.file_size
274
- if self.is_directory is not None: body['is_directory'] = self.is_directory
275
- if self.last_modified is not None: body['last_modified'] = self.last_modified
276
- if self.name is not None: body['name'] = self.name
277
- if self.path is not None: body['path'] = self.path
290
+ if self.file_size is not None:
291
+ body["file_size"] = self.file_size
292
+ if self.is_directory is not None:
293
+ body["is_directory"] = self.is_directory
294
+ if self.last_modified is not None:
295
+ body["last_modified"] = self.last_modified
296
+ if self.name is not None:
297
+ body["name"] = self.name
298
+ if self.path is not None:
299
+ body["path"] = self.path
278
300
  return body
279
301
 
280
302
  @classmethod
281
- def from_dict(cls, d: Dict[str, any]) -> DirectoryEntry:
303
+ def from_dict(cls, d: Dict[str, Any]) -> DirectoryEntry:
282
304
  """Deserializes the DirectoryEntry from a dictionary."""
283
- return cls(file_size=d.get('file_size', None),
284
- is_directory=d.get('is_directory', None),
285
- last_modified=d.get('last_modified', None),
286
- name=d.get('name', None),
287
- path=d.get('path', None))
305
+ return cls(
306
+ file_size=d.get("file_size", None),
307
+ is_directory=d.get("is_directory", None),
308
+ last_modified=d.get("last_modified", None),
309
+ name=d.get("name", None),
310
+ path=d.get("path", None),
311
+ )
288
312
 
289
313
 
290
314
  @dataclass
291
315
  class DownloadResponse:
292
316
  content_length: Optional[int] = None
317
+ """The length of the HTTP response body in bytes."""
293
318
 
294
319
  content_type: Optional[str] = None
295
320
 
296
321
  contents: Optional[BinaryIO] = None
297
322
 
298
323
  last_modified: Optional[str] = None
324
+ """The last modified time of the file in HTTP-date (RFC 7231) format."""
299
325
 
300
326
  def as_dict(self) -> dict:
301
327
  """Serializes the DownloadResponse into a dictionary suitable for use as a JSON request body."""
302
328
  body = {}
303
- if self.content_length is not None: body['content-length'] = self.content_length
304
- if self.content_type is not None: body['content-type'] = self.content_type
305
- if self.contents: body['contents'] = self.contents
306
- if self.last_modified is not None: body['last-modified'] = self.last_modified
329
+ if self.content_length is not None:
330
+ body["content-length"] = self.content_length
331
+ if self.content_type is not None:
332
+ body["content-type"] = self.content_type
333
+ if self.contents:
334
+ body["contents"] = self.contents
335
+ if self.last_modified is not None:
336
+ body["last-modified"] = self.last_modified
307
337
  return body
308
338
 
309
339
  def as_shallow_dict(self) -> dict:
310
340
  """Serializes the DownloadResponse into a shallow dictionary of its immediate attributes."""
311
341
  body = {}
312
- if self.content_length is not None: body['content-length'] = self.content_length
313
- if self.content_type is not None: body['content-type'] = self.content_type
314
- if self.contents: body['contents'] = self.contents
315
- if self.last_modified is not None: body['last-modified'] = self.last_modified
342
+ if self.content_length is not None:
343
+ body["content-length"] = self.content_length
344
+ if self.content_type is not None:
345
+ body["content-type"] = self.content_type
346
+ if self.contents:
347
+ body["contents"] = self.contents
348
+ if self.last_modified is not None:
349
+ body["last-modified"] = self.last_modified
316
350
  return body
317
351
 
318
352
  @classmethod
319
- def from_dict(cls, d: Dict[str, any]) -> DownloadResponse:
353
+ def from_dict(cls, d: Dict[str, Any]) -> DownloadResponse:
320
354
  """Deserializes the DownloadResponse from a dictionary."""
321
- return cls(content_length=int(d.get('content-length', None)),
322
- content_type=d.get('content-type', None),
323
- contents=d.get('contents', None),
324
- last_modified=d.get('last-modified', None))
355
+ return cls(
356
+ content_length=int(d.get("content-length", None)),
357
+ content_type=d.get("content-type", None),
358
+ contents=d.get("contents", None),
359
+ last_modified=d.get("last-modified", None),
360
+ )
325
361
 
326
362
 
327
363
  @dataclass
@@ -341,33 +377,42 @@ class FileInfo:
341
377
  def as_dict(self) -> dict:
342
378
  """Serializes the FileInfo into a dictionary suitable for use as a JSON request body."""
343
379
  body = {}
344
- if self.file_size is not None: body['file_size'] = self.file_size
345
- if self.is_dir is not None: body['is_dir'] = self.is_dir
346
- if self.modification_time is not None: body['modification_time'] = self.modification_time
347
- if self.path is not None: body['path'] = self.path
380
+ if self.file_size is not None:
381
+ body["file_size"] = self.file_size
382
+ if self.is_dir is not None:
383
+ body["is_dir"] = self.is_dir
384
+ if self.modification_time is not None:
385
+ body["modification_time"] = self.modification_time
386
+ if self.path is not None:
387
+ body["path"] = self.path
348
388
  return body
349
389
 
350
390
  def as_shallow_dict(self) -> dict:
351
391
  """Serializes the FileInfo into a shallow dictionary of its immediate attributes."""
352
392
  body = {}
353
- if self.file_size is not None: body['file_size'] = self.file_size
354
- if self.is_dir is not None: body['is_dir'] = self.is_dir
355
- if self.modification_time is not None: body['modification_time'] = self.modification_time
356
- if self.path is not None: body['path'] = self.path
393
+ if self.file_size is not None:
394
+ body["file_size"] = self.file_size
395
+ if self.is_dir is not None:
396
+ body["is_dir"] = self.is_dir
397
+ if self.modification_time is not None:
398
+ body["modification_time"] = self.modification_time
399
+ if self.path is not None:
400
+ body["path"] = self.path
357
401
  return body
358
402
 
359
403
  @classmethod
360
- def from_dict(cls, d: Dict[str, any]) -> FileInfo:
404
+ def from_dict(cls, d: Dict[str, Any]) -> FileInfo:
361
405
  """Deserializes the FileInfo from a dictionary."""
362
- return cls(file_size=d.get('file_size', None),
363
- is_dir=d.get('is_dir', None),
364
- modification_time=d.get('modification_time', None),
365
- path=d.get('path', None))
406
+ return cls(
407
+ file_size=d.get("file_size", None),
408
+ is_dir=d.get("is_dir", None),
409
+ modification_time=d.get("modification_time", None),
410
+ path=d.get("path", None),
411
+ )
366
412
 
367
413
 
368
414
  @dataclass
369
415
  class GetDirectoryMetadataResponse:
370
-
371
416
  def as_dict(self) -> dict:
372
417
  """Serializes the GetDirectoryMetadataResponse into a dictionary suitable for use as a JSON request body."""
373
418
  body = {}
@@ -379,7 +424,7 @@ class GetDirectoryMetadataResponse:
379
424
  return body
380
425
 
381
426
  @classmethod
382
- def from_dict(cls, d: Dict[str, any]) -> GetDirectoryMetadataResponse:
427
+ def from_dict(cls, d: Dict[str, Any]) -> GetDirectoryMetadataResponse:
383
428
  """Deserializes the GetDirectoryMetadataResponse from a dictionary."""
384
429
  return cls()
385
430
 
@@ -387,33 +432,43 @@ class GetDirectoryMetadataResponse:
387
432
  @dataclass
388
433
  class GetMetadataResponse:
389
434
  content_length: Optional[int] = None
435
+ """The length of the HTTP response body in bytes."""
390
436
 
391
437
  content_type: Optional[str] = None
392
438
 
393
439
  last_modified: Optional[str] = None
440
+ """The last modified time of the file in HTTP-date (RFC 7231) format."""
394
441
 
395
442
  def as_dict(self) -> dict:
396
443
  """Serializes the GetMetadataResponse into a dictionary suitable for use as a JSON request body."""
397
444
  body = {}
398
- if self.content_length is not None: body['content-length'] = self.content_length
399
- if self.content_type is not None: body['content-type'] = self.content_type
400
- if self.last_modified is not None: body['last-modified'] = self.last_modified
445
+ if self.content_length is not None:
446
+ body["content-length"] = self.content_length
447
+ if self.content_type is not None:
448
+ body["content-type"] = self.content_type
449
+ if self.last_modified is not None:
450
+ body["last-modified"] = self.last_modified
401
451
  return body
402
452
 
403
453
  def as_shallow_dict(self) -> dict:
404
454
  """Serializes the GetMetadataResponse into a shallow dictionary of its immediate attributes."""
405
455
  body = {}
406
- if self.content_length is not None: body['content-length'] = self.content_length
407
- if self.content_type is not None: body['content-type'] = self.content_type
408
- if self.last_modified is not None: body['last-modified'] = self.last_modified
456
+ if self.content_length is not None:
457
+ body["content-length"] = self.content_length
458
+ if self.content_type is not None:
459
+ body["content-type"] = self.content_type
460
+ if self.last_modified is not None:
461
+ body["last-modified"] = self.last_modified
409
462
  return body
410
463
 
411
464
  @classmethod
412
- def from_dict(cls, d: Dict[str, any]) -> GetMetadataResponse:
465
+ def from_dict(cls, d: Dict[str, Any]) -> GetMetadataResponse:
413
466
  """Deserializes the GetMetadataResponse from a dictionary."""
414
- return cls(content_length=int(d.get('content-length', None)),
415
- content_type=d.get('content-type', None),
416
- last_modified=d.get('last-modified', None))
467
+ return cls(
468
+ content_length=int(d.get("content-length", None)),
469
+ content_type=d.get("content-type", None),
470
+ last_modified=d.get("last-modified", None),
471
+ )
417
472
 
418
473
 
419
474
  @dataclass
@@ -427,22 +482,27 @@ class ListDirectoryResponse:
427
482
  def as_dict(self) -> dict:
428
483
  """Serializes the ListDirectoryResponse into a dictionary suitable for use as a JSON request body."""
429
484
  body = {}
430
- if self.contents: body['contents'] = [v.as_dict() for v in self.contents]
431
- if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
485
+ if self.contents:
486
+ body["contents"] = [v.as_dict() for v in self.contents]
487
+ if self.next_page_token is not None:
488
+ body["next_page_token"] = self.next_page_token
432
489
  return body
433
490
 
434
491
  def as_shallow_dict(self) -> dict:
435
492
  """Serializes the ListDirectoryResponse into a shallow dictionary of its immediate attributes."""
436
493
  body = {}
437
- if self.contents: body['contents'] = self.contents
438
- if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
494
+ if self.contents:
495
+ body["contents"] = self.contents
496
+ if self.next_page_token is not None:
497
+ body["next_page_token"] = self.next_page_token
439
498
  return body
440
499
 
441
500
  @classmethod
442
- def from_dict(cls, d: Dict[str, any]) -> ListDirectoryResponse:
501
+ def from_dict(cls, d: Dict[str, Any]) -> ListDirectoryResponse:
443
502
  """Deserializes the ListDirectoryResponse from a dictionary."""
444
- return cls(contents=_repeated_dict(d, 'contents', DirectoryEntry),
445
- next_page_token=d.get('next_page_token', None))
503
+ return cls(
504
+ contents=_repeated_dict(d, "contents", DirectoryEntry), next_page_token=d.get("next_page_token", None)
505
+ )
446
506
 
447
507
 
448
508
  @dataclass
@@ -453,19 +513,21 @@ class ListStatusResponse:
453
513
  def as_dict(self) -> dict:
454
514
  """Serializes the ListStatusResponse into a dictionary suitable for use as a JSON request body."""
455
515
  body = {}
456
- if self.files: body['files'] = [v.as_dict() for v in self.files]
516
+ if self.files:
517
+ body["files"] = [v.as_dict() for v in self.files]
457
518
  return body
458
519
 
459
520
  def as_shallow_dict(self) -> dict:
460
521
  """Serializes the ListStatusResponse into a shallow dictionary of its immediate attributes."""
461
522
  body = {}
462
- if self.files: body['files'] = self.files
523
+ if self.files:
524
+ body["files"] = self.files
463
525
  return body
464
526
 
465
527
  @classmethod
466
- def from_dict(cls, d: Dict[str, any]) -> ListStatusResponse:
528
+ def from_dict(cls, d: Dict[str, Any]) -> ListStatusResponse:
467
529
  """Deserializes the ListStatusResponse from a dictionary."""
468
- return cls(files=_repeated_dict(d, 'files', FileInfo))
530
+ return cls(files=_repeated_dict(d, "files", FileInfo))
469
531
 
470
532
 
471
533
  @dataclass
@@ -476,24 +538,25 @@ class MkDirs:
476
538
  def as_dict(self) -> dict:
477
539
  """Serializes the MkDirs into a dictionary suitable for use as a JSON request body."""
478
540
  body = {}
479
- if self.path is not None: body['path'] = self.path
541
+ if self.path is not None:
542
+ body["path"] = self.path
480
543
  return body
481
544
 
482
545
  def as_shallow_dict(self) -> dict:
483
546
  """Serializes the MkDirs into a shallow dictionary of its immediate attributes."""
484
547
  body = {}
485
- if self.path is not None: body['path'] = self.path
548
+ if self.path is not None:
549
+ body["path"] = self.path
486
550
  return body
487
551
 
488
552
  @classmethod
489
- def from_dict(cls, d: Dict[str, any]) -> MkDirs:
553
+ def from_dict(cls, d: Dict[str, Any]) -> MkDirs:
490
554
  """Deserializes the MkDirs from a dictionary."""
491
- return cls(path=d.get('path', None))
555
+ return cls(path=d.get("path", None))
492
556
 
493
557
 
494
558
  @dataclass
495
559
  class MkDirsResponse:
496
-
497
560
  def as_dict(self) -> dict:
498
561
  """Serializes the MkDirsResponse into a dictionary suitable for use as a JSON request body."""
499
562
  body = {}
@@ -505,7 +568,7 @@ class MkDirsResponse:
505
568
  return body
506
569
 
507
570
  @classmethod
508
- def from_dict(cls, d: Dict[str, any]) -> MkDirsResponse:
571
+ def from_dict(cls, d: Dict[str, Any]) -> MkDirsResponse:
509
572
  """Deserializes the MkDirsResponse from a dictionary."""
510
573
  return cls()
511
574
 
@@ -521,26 +584,29 @@ class Move:
521
584
  def as_dict(self) -> dict:
522
585
  """Serializes the Move into a dictionary suitable for use as a JSON request body."""
523
586
  body = {}
524
- if self.destination_path is not None: body['destination_path'] = self.destination_path
525
- if self.source_path is not None: body['source_path'] = self.source_path
587
+ if self.destination_path is not None:
588
+ body["destination_path"] = self.destination_path
589
+ if self.source_path is not None:
590
+ body["source_path"] = self.source_path
526
591
  return body
527
592
 
528
593
  def as_shallow_dict(self) -> dict:
529
594
  """Serializes the Move into a shallow dictionary of its immediate attributes."""
530
595
  body = {}
531
- if self.destination_path is not None: body['destination_path'] = self.destination_path
532
- if self.source_path is not None: body['source_path'] = self.source_path
596
+ if self.destination_path is not None:
597
+ body["destination_path"] = self.destination_path
598
+ if self.source_path is not None:
599
+ body["source_path"] = self.source_path
533
600
  return body
534
601
 
535
602
  @classmethod
536
- def from_dict(cls, d: Dict[str, any]) -> Move:
603
+ def from_dict(cls, d: Dict[str, Any]) -> Move:
537
604
  """Deserializes the Move from a dictionary."""
538
- return cls(destination_path=d.get('destination_path', None), source_path=d.get('source_path', None))
605
+ return cls(destination_path=d.get("destination_path", None), source_path=d.get("source_path", None))
539
606
 
540
607
 
541
608
  @dataclass
542
609
  class MoveResponse:
543
-
544
610
  def as_dict(self) -> dict:
545
611
  """Serializes the MoveResponse into a dictionary suitable for use as a JSON request body."""
546
612
  body = {}
@@ -552,7 +618,7 @@ class MoveResponse:
552
618
  return body
553
619
 
554
620
  @classmethod
555
- def from_dict(cls, d: Dict[str, any]) -> MoveResponse:
621
+ def from_dict(cls, d: Dict[str, Any]) -> MoveResponse:
556
622
  """Deserializes the MoveResponse from a dictionary."""
557
623
  return cls()
558
624
 
@@ -571,30 +637,33 @@ class Put:
571
637
  def as_dict(self) -> dict:
572
638
  """Serializes the Put into a dictionary suitable for use as a JSON request body."""
573
639
  body = {}
574
- if self.contents is not None: body['contents'] = self.contents
575
- if self.overwrite is not None: body['overwrite'] = self.overwrite
576
- if self.path is not None: body['path'] = self.path
640
+ if self.contents is not None:
641
+ body["contents"] = self.contents
642
+ if self.overwrite is not None:
643
+ body["overwrite"] = self.overwrite
644
+ if self.path is not None:
645
+ body["path"] = self.path
577
646
  return body
578
647
 
579
648
  def as_shallow_dict(self) -> dict:
580
649
  """Serializes the Put into a shallow dictionary of its immediate attributes."""
581
650
  body = {}
582
- if self.contents is not None: body['contents'] = self.contents
583
- if self.overwrite is not None: body['overwrite'] = self.overwrite
584
- if self.path is not None: body['path'] = self.path
651
+ if self.contents is not None:
652
+ body["contents"] = self.contents
653
+ if self.overwrite is not None:
654
+ body["overwrite"] = self.overwrite
655
+ if self.path is not None:
656
+ body["path"] = self.path
585
657
  return body
586
658
 
587
659
  @classmethod
588
- def from_dict(cls, d: Dict[str, any]) -> Put:
660
+ def from_dict(cls, d: Dict[str, Any]) -> Put:
589
661
  """Deserializes the Put from a dictionary."""
590
- return cls(contents=d.get('contents', None),
591
- overwrite=d.get('overwrite', None),
592
- path=d.get('path', None))
662
+ return cls(contents=d.get("contents", None), overwrite=d.get("overwrite", None), path=d.get("path", None))
593
663
 
594
664
 
595
665
  @dataclass
596
666
  class PutResponse:
597
-
598
667
  def as_dict(self) -> dict:
599
668
  """Serializes the PutResponse into a dictionary suitable for use as a JSON request body."""
600
669
  body = {}
@@ -606,7 +675,7 @@ class PutResponse:
606
675
  return body
607
676
 
608
677
  @classmethod
609
- def from_dict(cls, d: Dict[str, any]) -> PutResponse:
678
+ def from_dict(cls, d: Dict[str, Any]) -> PutResponse:
610
679
  """Deserializes the PutResponse from a dictionary."""
611
680
  return cls()
612
681
 
@@ -623,26 +692,29 @@ class ReadResponse:
623
692
  def as_dict(self) -> dict:
624
693
  """Serializes the ReadResponse into a dictionary suitable for use as a JSON request body."""
625
694
  body = {}
626
- if self.bytes_read is not None: body['bytes_read'] = self.bytes_read
627
- if self.data is not None: body['data'] = self.data
695
+ if self.bytes_read is not None:
696
+ body["bytes_read"] = self.bytes_read
697
+ if self.data is not None:
698
+ body["data"] = self.data
628
699
  return body
629
700
 
630
701
  def as_shallow_dict(self) -> dict:
631
702
  """Serializes the ReadResponse into a shallow dictionary of its immediate attributes."""
632
703
  body = {}
633
- if self.bytes_read is not None: body['bytes_read'] = self.bytes_read
634
- if self.data is not None: body['data'] = self.data
704
+ if self.bytes_read is not None:
705
+ body["bytes_read"] = self.bytes_read
706
+ if self.data is not None:
707
+ body["data"] = self.data
635
708
  return body
636
709
 
637
710
  @classmethod
638
- def from_dict(cls, d: Dict[str, any]) -> ReadResponse:
711
+ def from_dict(cls, d: Dict[str, Any]) -> ReadResponse:
639
712
  """Deserializes the ReadResponse from a dictionary."""
640
- return cls(bytes_read=d.get('bytes_read', None), data=d.get('data', None))
713
+ return cls(bytes_read=d.get("bytes_read", None), data=d.get("data", None))
641
714
 
642
715
 
643
716
  @dataclass
644
717
  class UploadResponse:
645
-
646
718
  def as_dict(self) -> dict:
647
719
  """Serializes the UploadResponse into a dictionary suitable for use as a JSON request body."""
648
720
  body = {}
@@ -654,7 +726,7 @@ class UploadResponse:
654
726
  return body
655
727
 
656
728
  @classmethod
657
- def from_dict(cls, d: Dict[str, any]) -> UploadResponse:
729
+ def from_dict(cls, d: Dict[str, Any]) -> UploadResponse:
658
730
  """Deserializes the UploadResponse from a dictionary."""
659
731
  return cls()
660
732
 
@@ -668,232 +740,272 @@ class DbfsAPI:
668
740
 
669
741
  def add_block(self, handle: int, data: str):
670
742
  """Append data block.
671
-
743
+
672
744
  Appends a block of data to the stream specified by the input handle. If the handle does not exist,
673
745
  this call will throw an exception with ``RESOURCE_DOES_NOT_EXIST``.
674
-
746
+
675
747
  If the block of data exceeds 1 MB, this call will throw an exception with ``MAX_BLOCK_SIZE_EXCEEDED``.
676
-
748
+
677
749
  :param handle: int
678
750
  The handle on an open stream.
679
751
  :param data: str
680
752
  The base64-encoded data to append to the stream. This has a limit of 1 MB.
681
-
682
-
753
+
754
+
683
755
  """
684
756
  body = {}
685
- if data is not None: body['data'] = data
686
- if handle is not None: body['handle'] = handle
687
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
757
+ if data is not None:
758
+ body["data"] = data
759
+ if handle is not None:
760
+ body["handle"] = handle
761
+ headers = {
762
+ "Accept": "application/json",
763
+ "Content-Type": "application/json",
764
+ }
688
765
 
689
- self._api.do('POST', '/api/2.0/dbfs/add-block', body=body, headers=headers)
766
+ self._api.do("POST", "/api/2.0/dbfs/add-block", body=body, headers=headers)
690
767
 
691
768
  def close(self, handle: int):
692
769
  """Close the stream.
693
-
770
+
694
771
  Closes the stream specified by the input handle. If the handle does not exist, this call throws an
695
772
  exception with ``RESOURCE_DOES_NOT_EXIST``.
696
-
773
+
697
774
  :param handle: int
698
775
  The handle on an open stream.
699
-
700
-
776
+
777
+
701
778
  """
702
779
  body = {}
703
- if handle is not None: body['handle'] = handle
704
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
780
+ if handle is not None:
781
+ body["handle"] = handle
782
+ headers = {
783
+ "Accept": "application/json",
784
+ "Content-Type": "application/json",
785
+ }
705
786
 
706
- self._api.do('POST', '/api/2.0/dbfs/close', body=body, headers=headers)
787
+ self._api.do("POST", "/api/2.0/dbfs/close", body=body, headers=headers)
707
788
 
708
789
  def create(self, path: str, *, overwrite: Optional[bool] = None) -> CreateResponse:
709
790
  """Open a stream.
710
-
791
+
711
792
  Opens a stream to write to a file and returns a handle to this stream. There is a 10 minute idle
712
793
  timeout on this handle. If a file or directory already exists on the given path and __overwrite__ is
713
794
  set to false, this call will throw an exception with ``RESOURCE_ALREADY_EXISTS``.
714
-
795
+
715
796
  A typical workflow for file upload would be:
716
-
797
+
717
798
  1. Issue a ``create`` call and get a handle. 2. Issue one or more ``add-block`` calls with the handle
718
799
  you have. 3. Issue a ``close`` call with the handle you have.
719
-
800
+
720
801
  :param path: str
721
802
  The path of the new file. The path should be the absolute DBFS path.
722
803
  :param overwrite: bool (optional)
723
804
  The flag that specifies whether to overwrite existing file/files.
724
-
805
+
725
806
  :returns: :class:`CreateResponse`
726
807
  """
727
808
  body = {}
728
- if overwrite is not None: body['overwrite'] = overwrite
729
- if path is not None: body['path'] = path
730
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
731
-
732
- res = self._api.do('POST', '/api/2.0/dbfs/create', body=body, headers=headers)
809
+ if overwrite is not None:
810
+ body["overwrite"] = overwrite
811
+ if path is not None:
812
+ body["path"] = path
813
+ headers = {
814
+ "Accept": "application/json",
815
+ "Content-Type": "application/json",
816
+ }
817
+
818
+ res = self._api.do("POST", "/api/2.0/dbfs/create", body=body, headers=headers)
733
819
  return CreateResponse.from_dict(res)
734
820
 
735
821
  def delete(self, path: str, *, recursive: Optional[bool] = None):
736
822
  """Delete a file/directory.
737
-
823
+
738
824
  Delete the file or directory (optionally recursively delete all files in the directory). This call
739
825
  throws an exception with `IO_ERROR` if the path is a non-empty directory and `recursive` is set to
740
826
  `false` or on other similar errors.
741
-
827
+
742
828
  When you delete a large number of files, the delete operation is done in increments. The call returns
743
829
  a response after approximately 45 seconds with an error message (503 Service Unavailable) asking you
744
830
  to re-invoke the delete operation until the directory structure is fully deleted.
745
-
831
+
746
832
  For operations that delete more than 10K files, we discourage using the DBFS REST API, but advise you
747
833
  to perform such operations in the context of a cluster, using the [File system utility
748
834
  (dbutils.fs)](/dev-tools/databricks-utils.html#dbutils-fs). `dbutils.fs` covers the functional scope
749
835
  of the DBFS REST API, but from notebooks. Running such operations using notebooks provides better
750
836
  control and manageability, such as selective deletes, and the possibility to automate periodic delete
751
837
  jobs.
752
-
838
+
753
839
  :param path: str
754
840
  The path of the file or directory to delete. The path should be the absolute DBFS path.
755
841
  :param recursive: bool (optional)
756
842
  Whether or not to recursively delete the directory's contents. Deleting empty directories can be
757
843
  done without providing the recursive flag.
758
-
759
-
844
+
845
+
760
846
  """
761
847
  body = {}
762
- if path is not None: body['path'] = path
763
- if recursive is not None: body['recursive'] = recursive
764
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
848
+ if path is not None:
849
+ body["path"] = path
850
+ if recursive is not None:
851
+ body["recursive"] = recursive
852
+ headers = {
853
+ "Accept": "application/json",
854
+ "Content-Type": "application/json",
855
+ }
765
856
 
766
- self._api.do('POST', '/api/2.0/dbfs/delete', body=body, headers=headers)
857
+ self._api.do("POST", "/api/2.0/dbfs/delete", body=body, headers=headers)
767
858
 
768
859
  def get_status(self, path: str) -> FileInfo:
769
860
  """Get the information of a file or directory.
770
-
861
+
771
862
  Gets the file information for a file or directory. If the file or directory does not exist, this call
772
863
  throws an exception with `RESOURCE_DOES_NOT_EXIST`.
773
-
864
+
774
865
  :param path: str
775
866
  The path of the file or directory. The path should be the absolute DBFS path.
776
-
867
+
777
868
  :returns: :class:`FileInfo`
778
869
  """
779
870
 
780
871
  query = {}
781
- if path is not None: query['path'] = path
782
- headers = {'Accept': 'application/json', }
872
+ if path is not None:
873
+ query["path"] = path
874
+ headers = {
875
+ "Accept": "application/json",
876
+ }
783
877
 
784
- res = self._api.do('GET', '/api/2.0/dbfs/get-status', query=query, headers=headers)
878
+ res = self._api.do("GET", "/api/2.0/dbfs/get-status", query=query, headers=headers)
785
879
  return FileInfo.from_dict(res)
786
880
 
787
881
  def list(self, path: str) -> Iterator[FileInfo]:
788
882
  """List directory contents or file details.
789
-
883
+
790
884
  List the contents of a directory, or details of the file. If the file or directory does not exist,
791
885
  this call throws an exception with `RESOURCE_DOES_NOT_EXIST`.
792
-
886
+
793
887
  When calling list on a large directory, the list operation will time out after approximately 60
794
888
  seconds. We strongly recommend using list only on directories containing less than 10K files and
795
889
  discourage using the DBFS REST API for operations that list more than 10K files. Instead, we recommend
796
890
  that you perform such operations in the context of a cluster, using the [File system utility
797
891
  (dbutils.fs)](/dev-tools/databricks-utils.html#dbutils-fs), which provides the same functionality
798
892
  without timing out.
799
-
893
+
800
894
  :param path: str
801
895
  The path of the file or directory. The path should be the absolute DBFS path.
802
-
896
+
803
897
  :returns: Iterator over :class:`FileInfo`
804
898
  """
805
899
 
806
900
  query = {}
807
- if path is not None: query['path'] = path
808
- headers = {'Accept': 'application/json', }
901
+ if path is not None:
902
+ query["path"] = path
903
+ headers = {
904
+ "Accept": "application/json",
905
+ }
809
906
 
810
- json = self._api.do('GET', '/api/2.0/dbfs/list', query=query, headers=headers)
907
+ json = self._api.do("GET", "/api/2.0/dbfs/list", query=query, headers=headers)
811
908
  parsed = ListStatusResponse.from_dict(json).files
812
909
  return parsed if parsed is not None else []
813
910
 
814
911
  def mkdirs(self, path: str):
815
912
  """Create a directory.
816
-
913
+
817
914
  Creates the given directory and necessary parent directories if they do not exist. If a file (not a
818
915
  directory) exists at any prefix of the input path, this call throws an exception with
819
916
  `RESOURCE_ALREADY_EXISTS`. **Note**: If this operation fails, it might have succeeded in creating some
820
917
  of the necessary parent directories.
821
-
918
+
822
919
  :param path: str
823
920
  The path of the new directory. The path should be the absolute DBFS path.
824
-
825
-
921
+
922
+
826
923
  """
827
924
  body = {}
828
- if path is not None: body['path'] = path
829
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
925
+ if path is not None:
926
+ body["path"] = path
927
+ headers = {
928
+ "Accept": "application/json",
929
+ "Content-Type": "application/json",
930
+ }
830
931
 
831
- self._api.do('POST', '/api/2.0/dbfs/mkdirs', body=body, headers=headers)
932
+ self._api.do("POST", "/api/2.0/dbfs/mkdirs", body=body, headers=headers)
832
933
 
833
934
  def move(self, source_path: str, destination_path: str):
834
935
  """Move a file.
835
-
936
+
836
937
  Moves a file from one location to another location within DBFS. If the source file does not exist,
837
938
  this call throws an exception with `RESOURCE_DOES_NOT_EXIST`. If a file already exists in the
838
939
  destination path, this call throws an exception with `RESOURCE_ALREADY_EXISTS`. If the given source
839
940
  path is a directory, this call always recursively moves all files.
840
-
941
+
841
942
  :param source_path: str
842
943
  The source path of the file or directory. The path should be the absolute DBFS path.
843
944
  :param destination_path: str
844
945
  The destination path of the file or directory. The path should be the absolute DBFS path.
845
-
846
-
946
+
947
+
847
948
  """
848
949
  body = {}
849
- if destination_path is not None: body['destination_path'] = destination_path
850
- if source_path is not None: body['source_path'] = source_path
851
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
950
+ if destination_path is not None:
951
+ body["destination_path"] = destination_path
952
+ if source_path is not None:
953
+ body["source_path"] = source_path
954
+ headers = {
955
+ "Accept": "application/json",
956
+ "Content-Type": "application/json",
957
+ }
852
958
 
853
- self._api.do('POST', '/api/2.0/dbfs/move', body=body, headers=headers)
959
+ self._api.do("POST", "/api/2.0/dbfs/move", body=body, headers=headers)
854
960
 
855
961
  def put(self, path: str, *, contents: Optional[str] = None, overwrite: Optional[bool] = None):
856
962
  """Upload a file.
857
-
963
+
858
964
  Uploads a file through the use of multipart form post. It is mainly used for streaming uploads, but
859
965
  can also be used as a convenient single call for data upload.
860
-
966
+
861
967
  Alternatively you can pass contents as base64 string.
862
-
968
+
863
969
  The amount of data that can be passed (when not streaming) using the __contents__ parameter is limited
864
970
  to 1 MB. `MAX_BLOCK_SIZE_EXCEEDED` will be thrown if this limit is exceeded.
865
-
971
+
866
972
  If you want to upload large files, use the streaming upload. For details, see :method:dbfs/create,
867
973
  :method:dbfs/addBlock, :method:dbfs/close.
868
-
974
+
869
975
  :param path: str
870
976
  The path of the new file. The path should be the absolute DBFS path.
871
977
  :param contents: str (optional)
872
978
  This parameter might be absent, and instead a posted file will be used.
873
979
  :param overwrite: bool (optional)
874
980
  The flag that specifies whether to overwrite existing file/files.
875
-
876
-
981
+
982
+
877
983
  """
878
984
  body = {}
879
- if contents is not None: body['contents'] = contents
880
- if overwrite is not None: body['overwrite'] = overwrite
881
- if path is not None: body['path'] = path
882
- headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
883
-
884
- self._api.do('POST', '/api/2.0/dbfs/put', body=body, headers=headers)
985
+ if contents is not None:
986
+ body["contents"] = contents
987
+ if overwrite is not None:
988
+ body["overwrite"] = overwrite
989
+ if path is not None:
990
+ body["path"] = path
991
+ headers = {
992
+ "Accept": "application/json",
993
+ "Content-Type": "application/json",
994
+ }
995
+
996
+ self._api.do("POST", "/api/2.0/dbfs/put", body=body, headers=headers)
885
997
 
886
998
  def read(self, path: str, *, length: Optional[int] = None, offset: Optional[int] = None) -> ReadResponse:
887
999
  """Get the contents of a file.
888
-
1000
+
889
1001
  Returns the contents of a file. If the file does not exist, this call throws an exception with
890
1002
  `RESOURCE_DOES_NOT_EXIST`. If the path is a directory, the read length is negative, or if the offset
891
1003
  is negative, this call throws an exception with `INVALID_PARAMETER_VALUE`. If the read length exceeds
892
1004
  1 MB, this call throws an exception with `MAX_READ_SIZE_EXCEEDED`.
893
-
1005
+
894
1006
  If `offset + length` exceeds the number of bytes in a file, it reads the contents until the end of
895
1007
  file.
896
-
1008
+
897
1009
  :param path: str
898
1010
  The path of the file to read. The path should be the absolute DBFS path.
899
1011
  :param length: int (optional)
@@ -901,17 +1013,22 @@ class DbfsAPI:
901
1013
  of 0.5 MB.
902
1014
  :param offset: int (optional)
903
1015
  The offset to read from in bytes.
904
-
1016
+
905
1017
  :returns: :class:`ReadResponse`
906
1018
  """
907
1019
 
908
1020
  query = {}
909
- if length is not None: query['length'] = length
910
- if offset is not None: query['offset'] = offset
911
- if path is not None: query['path'] = path
912
- headers = {'Accept': 'application/json', }
913
-
914
- res = self._api.do('GET', '/api/2.0/dbfs/read', query=query, headers=headers)
1021
+ if length is not None:
1022
+ query["length"] = length
1023
+ if offset is not None:
1024
+ query["offset"] = offset
1025
+ if path is not None:
1026
+ query["path"] = path
1027
+ headers = {
1028
+ "Accept": "application/json",
1029
+ }
1030
+
1031
+ res = self._api.do("GET", "/api/2.0/dbfs/read", query=query, headers=headers)
915
1032
  return ReadResponse.from_dict(res)
916
1033
 
917
1034
 
@@ -919,19 +1036,19 @@ class FilesAPI:
919
1036
  """The Files API is a standard HTTP API that allows you to read, write, list, and delete files and
920
1037
  directories by referring to their URI. The API makes working with file content as raw bytes easier and
921
1038
  more efficient.
922
-
1039
+
923
1040
  The API supports [Unity Catalog volumes], where files and directories to operate on are specified using
924
1041
  their volume URI path, which follows the format
925
1042
  /Volumes/<catalog_name>/<schema_name>/<volume_name>/<path_to_file>.
926
-
1043
+
927
1044
  The Files API has two distinct endpoints, one for working with files (`/fs/files`) and another one for
928
1045
  working with directories (`/fs/directories`). Both endpoints use the standard HTTP methods GET, HEAD, PUT,
929
1046
  and DELETE to manage files and directories specified using their URI path. The path is always absolute.
930
-
1047
+
931
1048
  Some Files API client features are currently experimental. To enable them, set
932
1049
  `enable_experimental_files_api_client = True` in your configuration profile or use the environment
933
1050
  variable `DATABRICKS_ENABLE_EXPERIMENTAL_FILES_API_CLIENT=True`.
934
-
1051
+
935
1052
  [Unity Catalog volumes]: https://docs.databricks.com/en/connect/unity-catalog/volumes.html"""
936
1053
 
937
1054
  def __init__(self, api_client):
@@ -939,143 +1056,153 @@ class FilesAPI:
939
1056
 
940
1057
  def create_directory(self, directory_path: str):
941
1058
  """Create a directory.
942
-
1059
+
943
1060
  Creates an empty directory. If necessary, also creates any parent directories of the new, empty
944
1061
  directory (like the shell command `mkdir -p`). If called on an existing directory, returns a success
945
1062
  response; this method is idempotent (it will succeed if the directory already exists).
946
-
1063
+
947
1064
  :param directory_path: str
948
1065
  The absolute path of a directory.
949
-
950
-
1066
+
1067
+
951
1068
  """
952
1069
 
953
1070
  headers = {}
954
1071
 
955
- self._api.do('PUT',
956
- f'/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}',
957
- headers=headers)
1072
+ self._api.do(
1073
+ "PUT", f"/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}", headers=headers
1074
+ )
958
1075
 
959
1076
  def delete(self, file_path: str):
960
1077
  """Delete a file.
961
-
1078
+
962
1079
  Deletes a file. If the request is successful, there is no response body.
963
-
1080
+
964
1081
  :param file_path: str
965
1082
  The absolute path of the file.
966
-
967
-
1083
+
1084
+
968
1085
  """
969
1086
 
970
1087
  headers = {}
971
1088
 
972
- self._api.do('DELETE',
973
- f'/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}',
974
- headers=headers)
1089
+ self._api.do("DELETE", f"/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}", headers=headers)
975
1090
 
976
1091
  def delete_directory(self, directory_path: str):
977
1092
  """Delete a directory.
978
-
1093
+
979
1094
  Deletes an empty directory.
980
-
1095
+
981
1096
  To delete a non-empty directory, first delete all of its contents. This can be done by listing the
982
1097
  directory contents and deleting each file and subdirectory recursively.
983
-
1098
+
984
1099
  :param directory_path: str
985
1100
  The absolute path of a directory.
986
-
987
-
1101
+
1102
+
988
1103
  """
989
1104
 
990
1105
  headers = {}
991
1106
 
992
- self._api.do('DELETE',
993
- f'/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}',
994
- headers=headers)
1107
+ self._api.do(
1108
+ "DELETE", f"/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}", headers=headers
1109
+ )
995
1110
 
996
1111
  def download(self, file_path: str) -> DownloadResponse:
997
1112
  """Download a file.
998
-
1113
+
999
1114
  Downloads a file. The file contents are the response body. This is a standard HTTP file download, not
1000
1115
  a JSON RPC. It supports the Range and If-Unmodified-Since HTTP headers.
1001
-
1116
+
1002
1117
  :param file_path: str
1003
1118
  The absolute path of the file.
1004
-
1119
+
1005
1120
  :returns: :class:`DownloadResponse`
1006
1121
  """
1007
1122
 
1008
- headers = {'Accept': 'application/octet-stream', }
1009
- response_headers = ['content-length', 'content-type', 'last-modified', ]
1010
- res = self._api.do('GET',
1011
- f'/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}',
1012
- headers=headers,
1013
- response_headers=response_headers,
1014
- raw=True)
1123
+ headers = {
1124
+ "Accept": "application/octet-stream",
1125
+ }
1126
+ response_headers = [
1127
+ "content-length",
1128
+ "content-type",
1129
+ "last-modified",
1130
+ ]
1131
+ res = self._api.do(
1132
+ "GET",
1133
+ f"/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}",
1134
+ headers=headers,
1135
+ response_headers=response_headers,
1136
+ raw=True,
1137
+ )
1015
1138
  return DownloadResponse.from_dict(res)
1016
1139
 
1017
1140
  def get_directory_metadata(self, directory_path: str):
1018
1141
  """Get directory metadata.
1019
-
1142
+
1020
1143
  Get the metadata of a directory. The response HTTP headers contain the metadata. There is no response
1021
1144
  body.
1022
-
1145
+
1023
1146
  This method is useful to check if a directory exists and the caller has access to it.
1024
-
1147
+
1025
1148
  If you wish to ensure the directory exists, you can instead use `PUT`, which will create the directory
1026
1149
  if it does not exist, and is idempotent (it will succeed if the directory already exists).
1027
-
1150
+
1028
1151
  :param directory_path: str
1029
1152
  The absolute path of a directory.
1030
-
1031
-
1153
+
1154
+
1032
1155
  """
1033
1156
 
1034
1157
  headers = {}
1035
1158
 
1036
- self._api.do('HEAD',
1037
- f'/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}',
1038
- headers=headers)
1159
+ self._api.do(
1160
+ "HEAD", f"/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}", headers=headers
1161
+ )
1039
1162
 
1040
1163
  def get_metadata(self, file_path: str) -> GetMetadataResponse:
1041
1164
  """Get file metadata.
1042
-
1165
+
1043
1166
  Get the metadata of a file. The response HTTP headers contain the metadata. There is no response body.
1044
-
1167
+
1045
1168
  :param file_path: str
1046
1169
  The absolute path of the file.
1047
-
1170
+
1048
1171
  :returns: :class:`GetMetadataResponse`
1049
1172
  """
1050
1173
 
1051
1174
  headers = {}
1052
- response_headers = ['content-length', 'content-type', 'last-modified', ]
1053
- res = self._api.do('HEAD',
1054
- f'/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}',
1055
- headers=headers,
1056
- response_headers=response_headers)
1175
+ response_headers = [
1176
+ "content-length",
1177
+ "content-type",
1178
+ "last-modified",
1179
+ ]
1180
+ res = self._api.do(
1181
+ "HEAD",
1182
+ f"/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}",
1183
+ headers=headers,
1184
+ response_headers=response_headers,
1185
+ )
1057
1186
  return GetMetadataResponse.from_dict(res)
1058
1187
 
1059
- def list_directory_contents(self,
1060
- directory_path: str,
1061
- *,
1062
- page_size: Optional[int] = None,
1063
- page_token: Optional[str] = None) -> Iterator[DirectoryEntry]:
1188
+ def list_directory_contents(
1189
+ self, directory_path: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None
1190
+ ) -> Iterator[DirectoryEntry]:
1064
1191
  """List directory contents.
1065
-
1192
+
1066
1193
  Returns the contents of a directory. If there is no directory at the specified path, the API returns a
1067
1194
  HTTP 404 error.
1068
-
1195
+
1069
1196
  :param directory_path: str
1070
1197
  The absolute path of a directory.
1071
1198
  :param page_size: int (optional)
1072
1199
  The maximum number of directory entries to return. The response may contain fewer entries. If the
1073
1200
  response contains a `next_page_token`, there may be more entries, even if fewer than `page_size`
1074
1201
  entries are in the response.
1075
-
1202
+
1076
1203
  We recommend not to set this value unless you are intentionally listing less than the complete
1077
1204
  directory contents.
1078
-
1205
+
1079
1206
  If unspecified, at most 1000 directory entries will be returned. The maximum value is 1000. Values
1080
1207
  above 1000 will be coerced to 1000.
1081
1208
  :param page_token: str (optional)
@@ -1085,51 +1212,61 @@ class FilesAPI:
1085
1212
  request. To list all of the entries in a directory, it is necessary to continue requesting pages of
1086
1213
  entries until the response contains no `next_page_token`. Note that the number of entries returned
1087
1214
  must not be used to determine when the listing is complete.
1088
-
1215
+
1089
1216
  :returns: Iterator over :class:`DirectoryEntry`
1090
1217
  """
1091
1218
 
1092
1219
  query = {}
1093
- if page_size is not None: query['page_size'] = page_size
1094
- if page_token is not None: query['page_token'] = page_token
1095
- headers = {'Accept': 'application/json', }
1220
+ if page_size is not None:
1221
+ query["page_size"] = page_size
1222
+ if page_token is not None:
1223
+ query["page_token"] = page_token
1224
+ headers = {
1225
+ "Accept": "application/json",
1226
+ }
1096
1227
 
1097
1228
  while True:
1098
1229
  json = self._api.do(
1099
- 'GET',
1100
- f'/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}',
1230
+ "GET",
1231
+ f"/api/2.0/fs/directories{_escape_multi_segment_path_parameter(directory_path)}",
1101
1232
  query=query,
1102
- headers=headers)
1103
- if 'contents' in json:
1104
- for v in json['contents']:
1233
+ headers=headers,
1234
+ )
1235
+ if "contents" in json:
1236
+ for v in json["contents"]:
1105
1237
  yield DirectoryEntry.from_dict(v)
1106
- if 'next_page_token' not in json or not json['next_page_token']:
1238
+ if "next_page_token" not in json or not json["next_page_token"]:
1107
1239
  return
1108
- query['page_token'] = json['next_page_token']
1240
+ query["page_token"] = json["next_page_token"]
1109
1241
 
1110
1242
  def upload(self, file_path: str, contents: BinaryIO, *, overwrite: Optional[bool] = None):
1111
1243
  """Upload a file.
1112
-
1244
+
1113
1245
  Uploads a file of up to 5 GiB. The file contents should be sent as the request body as raw bytes (an
1114
1246
  octet stream); do not encode or otherwise modify the bytes before sending. The contents of the
1115
1247
  resulting file will be exactly the bytes sent in the request body. If the request is successful, there
1116
1248
  is no response body.
1117
-
1249
+
1118
1250
  :param file_path: str
1119
1251
  The absolute path of the file.
1120
1252
  :param contents: BinaryIO
1121
1253
  :param overwrite: bool (optional)
1122
1254
  If true, an existing file will be overwritten.
1123
-
1124
-
1255
+
1256
+
1125
1257
  """
1126
1258
 
1127
1259
  query = {}
1128
- if overwrite is not None: query['overwrite'] = overwrite
1129
- headers = {'Content-Type': 'application/octet-stream', }
1130
-
1131
- self._api.do('PUT',
1132
- f'/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}',
1133
- query=query,
1134
- headers=headers,
1135
- data=contents)
1260
+ if overwrite is not None:
1261
+ query["overwrite"] = overwrite
1262
+ headers = {
1263
+ "Content-Type": "application/octet-stream",
1264
+ }
1265
+
1266
+ self._api.do(
1267
+ "PUT",
1268
+ f"/api/2.0/fs/files{_escape_multi_segment_path_parameter(file_path)}",
1269
+ query=query,
1270
+ headers=headers,
1271
+ data=contents,
1272
+ )